I want to create "heart rate monitor" effect from a 2D array in numpy and want the tone to reflect the values in the array.
You can use the write function from scipy.io.wavfile to create a wav file which you can then play however you wish. Note that the array must be integers, so if you have floats, you might want to scale them appropriately:
import numpy as np
from scipy.io.wavfile import write
rate = 44100
data = np.random.uniform(-1, 1, rate) # 1 second worth of random samples between -1 and 1
scaled = np.int16(data / np.max(np.abs(data)) * 32767)
write('test.wav', rate, scaled)
If you want Python to actually play audio, then this page provides an overview of some of the packages/modules.
For the people coming here in 2016 scikits.audiolab doesn't really seem to work anymore. I was able to get a solution using sounddevice.
import numpy as np
import sounddevice as sd
fs = 44100
data = np.random.uniform(-1, 1, fs)
sd.play(data, fs)
in Jupyter the best option is:
from IPython.display import Audio
wave_audio = numpy.sin(numpy.linspace(0, 3000, 20000))
Audio(wave_audio, rate=20000)
In addition, you could try scikits.audiolab. It features file IO and the ability to 'play' arrays. Arrays don't have to be integers. To mimick dbaupp's example:
import numpy as np
import scikits.audiolab
data = np.random.uniform(-1,1,44100)
# write array to file:
scikits.audiolab.wavwrite(data, 'test.wav', fs=44100, enc='pcm16')
# play the array:
scikits.audiolab.play(data, fs=44100)
I had some problems using scikit.audiolabs, so I looked for some other options for this task. I came up with sounddevice, which seems a lot more up-to-date. I have not checked if it works with Python 3.
A simple way to perform what you want is this:
import numpy as np
import sounddevice as sd
sd.default.samplerate = 44100
time = 2.0
frequency = 440
# Generate time of samples between 0 and two seconds
samples = np.arange(44100 * time) / 44100.0
# Recall that a sinusoidal wave of frequency f has formula w(t) = A*sin(2*pi*f*t)
wave = 10000 * np.sin(2 * np.pi * frequency * samples)
# Convert it to wav format (16 bits)
wav_wave = np.array(wave, dtype=np.int16)
sd.play(wav_wave, blocking=True)
PyGame has the module pygame.sndarray which can play numpy data as audio. The other answers are probably better, as PyGame can be difficult to get up and running. Then again, scipy and numpy come with their own difficulties, so maybe it isn't a large step to add PyGame into the mix.
http://www.pygame.org/docs/ref/sndarray.html
Another modern and convenient solution is to use pysoundfile, which can read and write a wide range of audio file formats:
import numpy as np
import soundfile as sf
data = np.random.uniform(-1, 1, 44100)
sf.write('new_file.wav', data, 44100)
Not sure of the particulars of how you would produce the audio from the array, but I have found mpg321 to be a great command-line audio player, and could potentially work for you.
I use it as my player of choice for Anki, which is written in python and has libraries that could be a great starting place for interfacing your code/arrays with audio.
Check out:
anki.sound.py
customPlayer.py
Related
I want to create "heart rate monitor" effect from a 2D array in numpy and want the tone to reflect the values in the array.
You can use the write function from scipy.io.wavfile to create a wav file which you can then play however you wish. Note that the array must be integers, so if you have floats, you might want to scale them appropriately:
import numpy as np
from scipy.io.wavfile import write
rate = 44100
data = np.random.uniform(-1, 1, rate) # 1 second worth of random samples between -1 and 1
scaled = np.int16(data / np.max(np.abs(data)) * 32767)
write('test.wav', rate, scaled)
If you want Python to actually play audio, then this page provides an overview of some of the packages/modules.
For the people coming here in 2016 scikits.audiolab doesn't really seem to work anymore. I was able to get a solution using sounddevice.
import numpy as np
import sounddevice as sd
fs = 44100
data = np.random.uniform(-1, 1, fs)
sd.play(data, fs)
in Jupyter the best option is:
from IPython.display import Audio
wave_audio = numpy.sin(numpy.linspace(0, 3000, 20000))
Audio(wave_audio, rate=20000)
In addition, you could try scikits.audiolab. It features file IO and the ability to 'play' arrays. Arrays don't have to be integers. To mimick dbaupp's example:
import numpy as np
import scikits.audiolab
data = np.random.uniform(-1,1,44100)
# write array to file:
scikits.audiolab.wavwrite(data, 'test.wav', fs=44100, enc='pcm16')
# play the array:
scikits.audiolab.play(data, fs=44100)
I had some problems using scikit.audiolabs, so I looked for some other options for this task. I came up with sounddevice, which seems a lot more up-to-date. I have not checked if it works with Python 3.
A simple way to perform what you want is this:
import numpy as np
import sounddevice as sd
sd.default.samplerate = 44100
time = 2.0
frequency = 440
# Generate time of samples between 0 and two seconds
samples = np.arange(44100 * time) / 44100.0
# Recall that a sinusoidal wave of frequency f has formula w(t) = A*sin(2*pi*f*t)
wave = 10000 * np.sin(2 * np.pi * frequency * samples)
# Convert it to wav format (16 bits)
wav_wave = np.array(wave, dtype=np.int16)
sd.play(wav_wave, blocking=True)
PyGame has the module pygame.sndarray which can play numpy data as audio. The other answers are probably better, as PyGame can be difficult to get up and running. Then again, scipy and numpy come with their own difficulties, so maybe it isn't a large step to add PyGame into the mix.
http://www.pygame.org/docs/ref/sndarray.html
Another modern and convenient solution is to use pysoundfile, which can read and write a wide range of audio file formats:
import numpy as np
import soundfile as sf
data = np.random.uniform(-1, 1, 44100)
sf.write('new_file.wav', data, 44100)
Not sure of the particulars of how you would produce the audio from the array, but I have found mpg321 to be a great command-line audio player, and could potentially work for you.
I use it as my player of choice for Anki, which is written in python and has libraries that could be a great starting place for interfacing your code/arrays with audio.
Check out:
anki.sound.py
customPlayer.py
Disclaimer: Forgive me if I missed something as I am new to sounds
I have a wav file which is a pure beep. I want to create a python program that listens through my microphone and every time it hears that same beep, it will act(i.e- print "heard").
I recorded that beep with silence at the start and end to make it more realistic. Next, I did this:
import noisereduce as nr
import librosa
import matplotlib.pyplot as plt
import numpy as np
# OG Loading
ogAudio, sampling_rate = librosa.load('.\\Beep.wav')
recordAudio, sampling_rate = librosa.load('.\\OneBeepRecord.wav')
noisy_part = recordAudio[0:25000]
reducedRecord = nr.reduce_noise(recordAudio, sampling_rate, False, noisy_part)
trimmedRecord, index = librosa.effects.trim(reducedRecord, top_db=35, frame_length=512, hop_length=64)
I picked top_db=35 because the result's shape is the closest to the shape of ogAudio.
I figured that to 'compare' sounds I can use the correlation coefficients but I have different ndarray shapes as:
print(ogAudio.shape, trimmedRecord.shape)
Returns:
(2981,) (2944,)
To visualize(Blue is ogAudio and orange is trimmedRecord):
Plotted Arrays
Is it possible that the record is shorter than the sound it self?
I am working on a sound classification problem and I want that my audio file should be atleast 6 second long. If it is not I want to extend it by running in the loop. and then find its STFT which is in librosa library of python.
This might help a bit
import math
import soundfile as sf
import numpy as np
import librosa
data, samplerate = sf.read('test1.wav')
channels = len(data.shape)
length_s = len(data)/float(samplerate)
if(length_s < 6.0):
n = math.ceil(6*samplerate/len(data))
if(channels == 2):
data = np.tile(data,(n,1))
else:
data = np.tile(data,n)
sf.write('new.wav', data, samplerate)
# now calculate stft for each channel if stereo
I'm trying to play square waves generated using SciPy with PyAudio but I get the error
TypeError: len() of unsized object
which is kind of strange because the square wave object should have a size, right?
RATE = 48000
p = pyaudio.PyAudio()
stream = p.open(format = pyaudio.paInt16,
channels = 2,
rate = RATE,
output = True)
# ... inside a loop
wav = signal.square(2*math.pi*FREQ*t)
wav = wav.astype(np.int16)
stream.write(wav) # crash here
The crash happens on the first iteration of the loop, so I suppose the loop is not a problem.
I get the same error. However, you are omitting some information, so I will assume these are your imports:
import pyaudio
import math
import numpy as np
from scipy import signal
And that
FREQ = 440
It looks like the variable you are iterating is t and it's a scalar. You might have good reasons to do this, but I don't think it is how scipy.signal is meant to work. If you use a vector t instead:
t = np.linspace(0, 2)
Then signal.square(...) and stream.write(wav.astype(np.int16)) work without problems.
I have a csv file of data, recorded on a data acquisition center with frequency of 500Hz, and I am trying to convert it to wav format. I have trie to Python and simply feed the numbers (as 16bit integers to the wave package), and it didn't work. How should I construct a wav file from simply a stream of numbers?
I've tried the following code, which includes normalization, and I set the dtype to be float32 so that it would use 32-bit floating-point format according to the documentation here, it just is not generating any sounds.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import numpy as np
import scipy.io.wavfile
from numpy import *
csv_array = np.loadtxt('trimmed.csv', delimiter=',', dtype=float32)
min = np.amin(csv_array)
max = np.amax(csv_array)
med = (max + min) / 2
def f(x):
return (x - med) * (1 - (-1)) / (max - min)
f = np.vectorize(f)
wav_array = f(csv_array)
scipy.io.wavfile.write('output.wav', 500, csv_array)
The problem is with your sampling rate. Try re-sampling the data to something like 44100 Hz (see code below). I do not know what effects re-sampling will have on your data.
import numpy as np
from scipy.io import wavfile
from scipy.signal import resample
data = np.random.uniform(-1, 1, 500)
data_resampled = resample(data, 44100)
wavfile.write('output.wav', 44100, data_resampled)
Try playing around with the rate argument in sipy.io.wavfile.write. As the rate lowers, the frequency of the sound lowers.