<commit_before>---
layout: post
title: Playing pure tones with PyQt5
date: 2019-06-11
has_code: true
has_comments: true
---

In an [earlier post](getting-started-with-python-for-sound), I recommended using a third-party package called [sounddevice](https://python-sounddevice.readthedocs.io/en/latest/) for playing sounds with Python. I also mentioned that there were some alternatives with similar functions. Overall, I still recommend sounddevice because I find it to be the most straitforward to use and the easiest to install on macOS, Windows, and Linux. However, [PyQt5](https://www.riverbankcomputing.com/software/pyqt/download5) is an alternative certainly worth looking at. PyQt5 provides bindings for [Qt](https://www.qt.io/), software for building complete applications with graphical user interfaces (GUIs). So if you are interested in building a Python app with an audio component, PyQt5 seems like a smart choice.

Unfortunately, I’ve really struggled to use PyQt5’s built-in audio features effectively. Latency issues, clicking, and clipping can be difficult to avoid. This is much to my own chagrin: I use PyQt5 _all the time_ for building psychological experiments, so relying on an extra pacakge for sound playback when this is included within PyQt5 is infuriating. I think a major problem is that there aren’t enough working examples online. I guess people don't use PyQt5 for audio as often as other tasks. In this post, I decided to try to rectify the balance in a small way, by taking an [already existing script](https://wiki.python.org/moin/PyQt/Playing%20a%20sound%20with%20QtMultimedia) and fixing some of its problems. By the end, we will have a Python script that creates a GUI from which the user can play pure tones of different frequencies and levels.

## Setup

This example is included in my [`klangfarbe` GitHub repo](https://github.com/sammosummo/klangfarbe/tree/master). If you decide to clone it, I recommend setting up a conda Python environment of the same name, as per my [getting-started post](getting-started-with-python-for-sound). You will need to install PyQt5 within this environment. Please note that, at the time of writing, the conda version of PyQt5 does not include all the necessary sub-components to play sounds. Therefore, you should install it via `pip install PyQt5` instead.

## Original code

Its very likely that the original webpage will outlive _The Cracked Bassoon_, but nevertheless, here is the example script:

```python
from math import pi, sin
import struct, sys

from PyQt4.QtCore import QBuffer, QByteArray, QIODevice, Qt
from PyQt4.QtGui import QApplication, QFormLayout, QLineEdit, QHBoxLayout, QPushButton, QSlider, QVBoxLayout, QWidget
from PyQt4.QtMultimedia import QAudio, QAudioDeviceInfo, QAudioFormat, QAudioOutput

class Window(QWidget):

    def __init__(self, parent = None):
    
        QWidget.__init__(self, parent)
        
        format = QAudioFormat()
        format.setChannels(1)
        format.setFrequency(22050)
        format.setSampleSize(16)
        format.setCodec("audio/pcm")
        format.setByteOrder(QAudioFormat.LittleEndian)
        format.setSampleType(QAudioFormat.SignedInt)<commit_msg>adding new post<commit_after>---
layout: post
title: Playing pure tones with PyQt5
date: 2019-06-11
has_code: true
has_comments: true
revisions:
 - date: 2019-06-13
   reason: Fixed some typos
---

In an [earlier post](getting-started-with-python-for-sound), I recommended using a third-party package called [sounddevice](https://python-sounddevice.readthedocs.io/en/latest/) for playing sounds with Python. I also mentioned that there were some alternatives with similar functions. Overall, I still recommend sounddevice because I find it to be the most straightforward to use and the easiest to install on macOS, Windows, and Linux. However, [PyQt5](https://www.riverbankcomputing.com/software/pyqt/download5) is an alternative package that may be worth looking at. PyQt5 provides bindings for [Qt](https://www.qt.io/), software for building complete applications with graphical user interfaces (GUIs). If you are interested in building a GUI-based Python app with an audio component, PyQt5 seems like a smart choice.

Unfortunately, I’ve really struggled to use PyQt5’s built-in audio features effectively. Latency issues, clicking, and clipping can be difficult to avoid. This is much to my chagrin: I use PyQt5 _all the time_ for building psychological experiments, so relying on an extra package for sound playback when this is included within PyQt5 is infuriating. I think a major problem is that there aren’t enough working examples online. I guess people don't use PyQt5 for audio as often as other tasks. In this post, I decided to try to rectify the balance in a small way, by taking an [already existing script](https://wiki.python.org/moin/PyQt/Playing%20a%20sound%20with%20QtMultimedia) and fixing some of its problems. By the end, we will have a Python script that creates a GUI from which the user can play pure tones of different frequencies and levels.

## Setup

This example is included in my [`klangfarbe` GitHub repo](https://github.com/sammosummo/klangfarbe/tree/master). If you decide to clone it, I recommend setting up a conda Python environment of the same name, as per my [getting-started post](getting-started-with-python-for-sound). You will need to install PyQt5 within this environment. Please note that, at the time of writing, the conda version of PyQt5 does not include all the necessary sub-components to play sounds. Therefore, you should install it via `pip install PyQt5` instead.

## Original code

Its very likely that the original webpage will outlive _The Cracked Bassoon_, but nevertheless, here is the example script:

```python
from math import pi, sin
import struct, sys

from PyQt4.QtCore import QBuffer, QByteArray, QIODevice, Qt
from PyQt4.QtGui import QApplication, QFormLayout, QLineEdit, QHBoxLayout, QPushButton, QSlider, QVBoxLayout, QWidget
from PyQt4.QtMultimedia import QAudio, QAudioDeviceInfo, QAudioFormat, QAudioOutput

class Window(QWidget):

    def __init__(self, parent = None):
    
        QWidget.__init__(self, parent)
        
        format = QAudioFormat()
        format.setChannels(1)
        format.setFrequency(22050)
        format.setSampleSize(16)
        format.setCodec("audio/pcm")
        format.setByteOrder(QAudioFormat.LittleEndian)
        format.setSampleType(QAudioFormat.SignedInt)
{'fraction_non_alphanumeric': 0.06756338899196042, 'fraction_numerical': 0.013296227581941867, 'mean_word_length': 4.514919011082694, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 10, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '248629', 'n_tokens_mistral': 1811, 'n_tokens_neox': 1716, 'n_words': 796}