How does a programm outputs sound on a low level? - python

I am trying to understand how a programm outputs sound on a low level. I got this question while thinking about programming a synthesizer.
Rather than an unchaning file (like mp3 sound), a synthesizer creates the sound in real time.
Imagine I got a synthesizer programm with GUI:
A slider can change the pitch of a simple sine wave. There has to be some kind of rate in which the programm sends the pitch values to a system API which somehow transforms the digital data to analog sound to the speakers.
How does this whole process works?
How could I access such API on an Unix system with e.g. python?
Can you recommend any ressources for further reading on sound synthesis or real time data processing?
Thanks for taking your time to read the question!:)

Related

Playing audio in sync with video with frames generated on the fly, real time. Plausible?

I'm a self taught python programmer working on a hobby project, but I'm having some difficulty and would like to address what I see as a potential XY problem.
My app takes an input of an audio file (converts it to wav) and produces visual representations of the audio (90x90, RGB, frames) in the form of numpy arrays. I used to save these frames to a video file using open-cv, then use ffmpeg to scale the video and add the (original, non-wav) audio over the top, but this meant waiting until the app had finished to play the file. I would like to be able to play the audio and display the frames as they are generated, in sync. My generation code takes at maximum 8ms of a 16ms frame (60fps), so I have a reasonable amount of cycles to play with.
From my research, I have found that SDL is the tool that is most appropriate to display frames at high speeds, and have managed to make a simple system to display frames 'in time', by brute-force pixel editing. I have also discovered that SDL can play audio, and it even seems that I could synchronize this with the video as I would like, via the callback function. However, being a decidedly non-c programmer, I am at a loss as to how to best to display frames, as directly assigning pixels cannot be the safest or fastest, and I would like to scale the frames as the are displayed. I am also at a loss as to how best to convert numpy arrays to textures efficiently, as well as how best to control the synchronicity of my generation code, the audio, and video frames.
I'm not specifically looking for an answer to any of those problems, though advice would be appreciated, I'm just making sure that this is a reasonable way forward. Is SDL/pysdl2 coupled with numpy appropriate in this scenario? Or is this asking too much from python overall?

Detecting a noise within an audio stream in Python

My goal is to be able to detect a specific noise that comes through the speakers of a PC using Python. That means the following, in pseudo code:
Sounds is being played out of the speakers, by applications such as games for example
My "audio to detect" sound happens, and I want to detect that, and take an action
The specific sound I want to detect for example can be found here.
If I break that down, i believe I need two things:
A way to sample the audio that is being streamed to an audio device -- perhaps something based on this? or potentially sounddevice - but I can't determine how to make this work by looking at their api?
A way to compare each sample with my "audio to detect" sound file.
The detection does not need to be exact - it just needs to be close. For example there will be lots of other noises happening at the same time, so its more being able to detect the footprint of the "audio to detect" within the audio stream of a variety of sounds.
Having investigated this, I found technologies mentioned in this post on SO and also this interesting article on Chromaprint. The Chromaprint article uses fpcalc to generate fingerprints, but because my "audio to detect" is around 1 - 2 seconds, fpcalc can't generate the fingerprint. I need something which works across smaller timespaces.
My question is - can somebody help me with the two parts to my question:
How do I sample the audio device on my PC using python
How should I attempt this comparison (ideally with a little example)
Many thanks in advance.

Python: translate sensor data into continuous frequency modulated audio

I have a piece of python script that runs through a continuous loop (~5Hz) to obtain data from a set of sensors connected to my PC, much like a proximity sensor.
I would like to translate this sensor data into audio output, using python and in a continuous manner. That is: whilst my sensor loop is running I want to generate and play a continuous sinusoidal audio sound, of which the frequency is modulated by the sensor output (e.g. higher sensor value = higher frequency). This is sort of the output that I want (without the GUI, of course: http://www.szynalski.com/tone-generator/)
I've looked through a lot of the available packages (pyDub, pyAudio, Winsound)but all seem to solve a piece of the puzzle, either signal generation, saving or playing, but I can't seem to find out how to combine them.
It's possible to perform frequency modulation and link different frequencies together and then save them, how to play them in real-time and without clogging up my sensor
It's possible to play threaded audio using WinSound -> but how to update frequence in real-time?
Or is this not a feasible route to walk on using python and should I write a script that inputs the sensor data into another more audio-friendly language?
Thanks.
I have a piece of python script that runs through a continuous loop (~5Hz)
Does it not work if you just add winsound.Beep(frequency_to_play, 1) in the loop?

Pure tones in Psychopy end with unwanted clicks

Pure tones in Psychopy are ending with clicks. How can I remove these clicks?
Tones generated within psychopy and tones imported as .wav both have the same problem. I tried adding 0.025ms of fade out in the .wav tones that I generated using Audacity. But still while playing them in psychopy, they end with a click sound.
Now I am not sure how to go ahead with this. I need to perform a psychoacoustic experiment and it can not proceed with tone presentation like that.
Crackling sounds or clicks are, to my knowledge, often associated with buffering errors. Many years back, I experienced similar problems on Linux systems when an incorrect bitrate was set. So there could be at least two possible culprits at work here: the bitrate, and the buffer size.
You already applied both an onset and offset ramp to allow the membranes to swing in/out, so this should not be the issue. (By the way, I think you meant 0.025 seconds instead of ms? Otherwise, the ramps would be too short!)
PyGame initializes the sound system with the following settings:
initPygame(rate=22050, bits=16, stereo=True, buffer=1024)
Whereas Pyo initializes it the following way:
initPyo(rate=44100, stereo=True, buffer=128)
The documentation of psychopy.sound states:
For control of bitrate and buffer size you can call psychopy.sound.init before
creating your first Sound object:
from psychopy import sound
sound.init(rate=44100, stereo=True, buffer=128)
s1 = sound.Sound('ding.wav')
So, I would suggest you:
Try out both sound backends, Pyo and PyGame -- you can change which one to use in the PsychoPy preferences under General / audio library. Change the field to ['pyo'] to use Pyo only, or to ['pygame'] to use only PyGame.
Experiment with different settings for bitrate and buffer size with both backends (Pyo, PyGame).
If you want to get started with serious psychoacoustics, however, I would suggest you do not use either of the proposed solutions, and get some piece of professional sound hardware or a data-acquisition board with analog outputs, which will deliver undistorted sound with sub-millisecond precision, such as the devices produced by National Instruments or competitors. The NI boards can be controlled from Python via PyLibNIDAQmx.
Clicks in the beginning and end of sounds often occur because the sound is stopped mid-way so that the wave abruptly goes from some value to zero. This waveform can only be made using high-amplitude high-frequency waves superimposed on the signal, i.e. a click. So the solution is to make the wave stop while on zero.
Are you using an old version of psychopy? If yes, then upgrade. Newer versions add a Hamming window (fade in/out) to self-generated tones which should avoid the click.
For the .wav files, try adding (extra) silence in the end, e.g. 50 ms. It might be that psychopy stops the sound prematurely.

Get Treadmill Speed Using PyAudio

I'm trying to read the speed of a manual treadmill (the York Pacer 2120 - manual: http://www.yorkfitness.com.au/uploaded/pdf_40Pacer%202120%20Treadmill_5500.pdf) by intercepting the wire that comes out of its speed sensor. My understanding that I've garnered by taking apart as much of the treadmill as I can is that the speed sensor is basically a magnet attached to a big disk attached to the belt of the treadmill that generates current every time it passes a coil of wire.
The wire that comes out of the speed sensor ends in a 3.5mm jack. I plugged this into my laptop's microphone port and recorded the "sound" of me walking at both high and low speeds. I've attached images of the waveform recorded in Audacity for low and high speed respectively.
My aim is to measure the speed of the treadmill in real time so that I can pass it as input into my game engine and control the speed of a character in game. I'm not sure what the best method to do this is but at the moment I'm trying to measure the distance between the "beats" in python using PyAudio.
To do this I've copied the beat detection code from the answer to another question (Detect beat and play (wav) file in a syncronised manner) but that gave me an usably high level of false positives.
Does anyone have any ideas as to how else I could go about getting a usable speed out of this signal? If you do, a code example would be very much appreciated. Other than that, how else would people go about trying to measure the speed off a manual treadmill? I've tried everything from using a camera to measure the distance between pieces of tape stuck to the treadmill belt to physically sticking a mouse to the treadmill to measure the speed of the belt.
The sound files are here:
https://www.dropbox.com/s/jbyl8c3ajv9e6xg/Fast_Raw.wav?dl=0
https://www.dropbox.com/s/0fp1mzuixhf5uju/Slow_Raw.wav?dl=0
And the audacity projects here:
https://www.dropbox.com/s/3cjvo3m2ln2ldet/AudacityFiles.zip?dl=0
I might look here Convert multi-channel PyAudio into NumPy array
From looking at the audio, you just need a simple trigger for when the signal is <0, you can likely modify the callback method to detect when the amplitude was positive and has been negative for N samples, then count the occurrences per second to retrieve the speed
I did eventually solve this but I gave up on PyAudio and used a Raspberry Pi instead. I open sourced the code if anyone happens to be interested: https://bitbucket.org/grootteam/gpio-treadmill-speed/

Categories