Skip to content

Instantly share code, notes, and snippets.

@pseeth
Created January 20, 2016 04:24
Show Gist options
  • Save pseeth/0236519fe611587ea89f to your computer and use it in GitHub Desktop.
Save pseeth/0236519fe611587ea89f to your computer and use it in GitHub Desktop.
"""Helper functions for working with audio files in NumPy."""
import numpy as np
import contextlib
def pcm2float(sig, dtype='float64'):
"""Convert PCM signal to floating point with a range from -1 to 1.
Use dtype='float32' for single precision.
Parameters
----------
sig : array_like
Input array, must have (signed) integral type.
dtype : data type, optional
Desired (floating point) data type.
Returns
-------
ndarray
normalized floating point data.
See Also
--------
float2pcm, dtype
"""
# TODO: allow unsigned (e.g. 8-bit) data
sig = np.asarray(sig)
if sig.dtype.kind != 'i':
raise TypeError("'sig' must be an array of signed integers")
dtype = np.dtype(dtype)
if dtype.kind != 'f':
raise TypeError("'dtype' must be floating point type")
# Note that 'min' has a greater (by 1) absolute value than 'max'!
# Therefore, we use '-min' here to avoid clipping.
return sig.astype(dtype) / dtype.type(-np.iinfo(sig.dtype).min)
def float2pcm(sig, dtype='int16'):
"""Convert floating point signal with a range from -1 to 1 to PCM.
Parameters
----------
sig : array_like
Input array, must have floating point type.
dtype : data type, optional
Desired (integer) data type.
Returns
-------
ndarray
integer data.
See Also
--------
pcm2float, dtype
"""
# TODO: allow unsigned (e.g. 8-bit) data
sig = np.asarray(sig)
if sig.dtype.kind != 'f':
raise TypeError("'sig' must be a float array")
dtype = np.dtype(dtype)
if dtype.kind != 'i':
raise TypeError("'dtype' must be signed integer type")
return (sig * np.iinfo(dtype).max).astype(dtype)
@contextlib.contextmanager
def printoptions(*args, **kwargs):
"""Context manager for temporarily setting NumPy print options.
See http://stackoverflow.com/a/2891805/500098
"""
original = np.get_printoptions()
try:
np.set_printoptions(*args, **kwargs)
yield
finally:
np.set_printoptions(**original)
import os
from scipy.io import wavfile
from scipy.signal import fftconvolve
from IPython.display import HTML
from base64 import b64encode
def convolve_and_play(sid, tid, interface, goal, pre):
impulse_dir = '../../reverberator/impulses/'
srate, sound = wavfile.read('../audio/guitar.wav')
dirs = os.listdir(impulse_dir)
d = [d for d in dirs if str(sid) == d.split('-')[0]][0]
dirs = os.listdir(impulse_dir + d)
order = {surv[sid]['exit']['order'][0]: 'a',
surv[sid]['exit']['order'][1]: 'b'}
audio = impulse_dir + d + '/' + 'task' + str(tid+1)+ order[interface]
if goal:
audio += '-goal'
audio += '.wav'
rate, impulse = wavfile.read(audio)
impulse = pcm2float(impulse)
sound = pcm2float(sound)
result = fftconvolve(sound, impulse, mode='full')
wavfile.write('result.wav', rate, float2pcm(result))
sound = open('result.wav', "rb").read()
return play(sound, pre)
def play(sound, pre):
audio_type = "wav"
sound_encoded = b64encode(sound)
sound_tag = pre + """
<audio id="beep" controls src="data:audio/{1};base64,{0}">
</audio>""".format(sound_encoded, audio_type)
play_beep = """
<script type="text/javascript">
var audio = document.getElementById("beep");
audio.play();
</script>
"""
return (HTML(sound_tag), HTML(play_beep))[0]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment