sounds¶
Classes to play sounds.
Each sound inherits a base type depending on prefs.get(‘AUDIOSERVER’)
prefs.get(‘AUDIOSERVER’) == ‘jack’ :
Jack_Sound
prefs.get(‘AUDIOSERVER’) == ‘pyo’ :
Pyo_Sound
To avoid unnecessary dependencies, Jack_Sound is not defined if AUDIOSERVER is ‘pyo’ and vice versa.
Todo
Implement sound level and filter calibration
Classes:
Metaclass for pyo sound objects. |
|
Base class for sounds that use the |
|
|
The Humble Sine Wave |
|
White Noise |
|
A .wav file. |
|
Speech subclass of File sound. |
|
A silent sound that does not pad its final chunk – used for creating precise silent gaps in a continuous noise. |
Data:
Sounds must be added to this SOUND_LIST so they can be indexed by the string keys used elsewhere. |
|
These parameters should be given string columns rather than float columns. |
Functions:
|
Convert 16 or 32 bit integer audio to 32 bit float. |
-
class
Pyo_Sound
[source]¶ Bases:
object
Metaclass for pyo sound objects.
Note
Use of pyo is generally discouraged due to dropout issues and the general opacity of the module. As such this object is intentionally left undocumented.
Methods:
play
()table_wrap
(audio[, duration])Records a PyoAudio generator into a sound table, returns a tableread object which can play the audio with .out()
set_trigger
(trig_fn)- Parameters
trig_fn
-
class
Jack_Sound
[source]¶ Bases:
object
Base class for sounds that use the
JackClient
audio server.- Variables
PARAMS (list) – List of strings of parameters that need to be defined for this sound
duration (float) – Duration of sound in ms
amplitude (float) – Amplitude of sound as proportion of 1 (eg 0.5 is half amplitude)
table (
numpy.ndarray
) – A Numpy array of samplestrigger (callable) – A function that is called when the sound completes
nsamples (int) – Number of samples in the sound
padded (bool) – Whether the sound had to be padded with zeros when split into chunks (ie. sound duration was not a multiple of BLOCKSIZE).
fs (int) – sampling rate of client from
jackclient.FS
blocksize (int) – blocksize of client from
jackclient.BLOCKSIZE
server (
Jack_Client
) – Current Jack Clientq (
multiprocessing.Queue
) – Audio Buffer queue fromjackclient.QUEUE
q_lock (
multiprocessing.Lock
) – Audio Buffer lock fromjackclient.Q_LOCK
play_evt (
multiprocessing.Event
) – play event fromjackclient.PLAY
stop_evt (
multiprocessing.Event
) – stop event fromjackclient.STOP
buffered (bool) – has this sound been dumped into the
q
?buffered_continuous (bool) – Has the sound been dumped into the
continuous_q
?
Attributes:
list of strings of parameters to be defined
string human readable name of sound
type of server, always ‘jack’ for Jack_Sound s.
Methods:
chunk
([pad])Split our table up into a list of
Jack_Sound.blocksize
chunks.set_trigger
(trig_fn)Set a trigger function to be called when the
stop_evt
is set.Wait for the stop_evt trigger to be set for at least a second after the sound should have ended.
given our fs and duration, how many samples do we need?
quantize_duration
([ceiling])Extend or shorten a sound so that it is a multiple of
jackclient.BLOCKSIZE
buffer
()Dump chunks into the sound queue.
Dump chunks into the continuous sound queue for looping.
play
()Play ourselves.
play_continuous
([loop])Play the sound continuously.
Stop playing a continuous sound
end
()Release any resources held by this sound
-
chunk
(pad=True)[source]¶ Split our table up into a list of
Jack_Sound.blocksize
chunks.- Parameters
pad (bool) – If the sound is not evenly divisible into chunks, pad with zeros (True, default), otherwise jackclient will pad with its continuous sound
-
set_trigger
(trig_fn)[source]¶ Set a trigger function to be called when the
stop_evt
is set.- Parameters
trig_fn (callable) – Some callable
-
wait_trigger
()[source]¶ Wait for the stop_evt trigger to be set for at least a second after the sound should have ended.
Call the trigger when the event is set.
-
get_nsamples
()[source]¶ given our fs and duration, how many samples do we need?
literally:
np.ceil((self.duration/1000.)*self.fs).astype(np.int)
-
quantize_duration
(ceiling=True)[source]¶ Extend or shorten a sound so that it is a multiple of
jackclient.BLOCKSIZE
- Parameters
ceiling (bool) – If true, extend duration, otherwise decrease duration.
-
buffer_continuous
()[source]¶ Dump chunks into the continuous sound queue for looping.
Continuous shoulds should always have full frames - ie. the number of samples in a sound should be a multiple of
jackclient.BLOCKSIZE
.This method will call
quantize_duration()
to force duration such that the sound has full frames.An exception will be raised if the sound has been padded.
Returns:
-
play
()[source]¶ Play ourselves.
If we’re not buffered, be buffered.
Otherwise, set the play event and clear the stop event.
If we have a trigger, set a Thread to wait on it.
-
play_continuous
(loop=True)[source]¶ Play the sound continuously.
Sound will be paused if another sound has its ‘play’ method called.
Currently - only looping is implemented: the full sound is loaded by the jack client and repeated indefinitely.
In the future, sound generation methods will be refactored as python generators so sounds can be continuously generated and played.
- Parameters
loop (bool) – whether the sound will be stored by the jack client and looped (True), or whether the sound will be continuously streamed (False, not implemented)
Returns:
todo:
merge into single play method that changes behavior if continuous or not
-
class
Tone
(frequency, duration, amplitude=0.01, **kwargs)[source]¶ Bases:
object
The Humble Sine Wave
- Parameters
frequency (float) – frequency of sin in Hz
duration (float) – duration of the sin in ms
amplitude (float) – amplitude of the sound as a proportion of 1.
**kwargs – extraneous parameters that might come along with instantiating us
Attributes:
Methods:
Create a sine wave table using pyo or numpy, depending on the server type.
-
PARAMS
= ['frequency', 'duration', 'amplitude']¶
-
type
= 'Tone'¶
-
class
Noise
(duration, amplitude=0.01, **kwargs)[source]¶ Bases:
object
White Noise
- Parameters
duration (float) – duration of the noise
amplitude (float) – amplitude of the sound as a proportion of 1.
**kwargs – extraneous parameters that might come along with instantiating us
Attributes:
Methods:
Create a table of Noise using pyo or numpy, depending on the server_type
-
PARAMS
= ['duration', 'amplitude']¶
-
type
= 'Noise'¶
-
class
File
(path, amplitude=0.01, **kwargs)[source]¶ Bases:
object
A .wav file.
Todo
Generalize this to other audio types if needed.
- Parameters
path (str) – Path to a .wav file relative to the prefs.get(‘SOUNDDIR’)
amplitude (float) – amplitude of the sound as a proportion of 1.
**kwargs – extraneous parameters that might come along with instantiating us
Attributes:
Methods:
Load the wavfile with
scipy.io.wavfile
, converting int to float as needed.-
PARAMS
= ['path', 'amplitude']¶
-
type
= 'File'¶
-
init_sound
()[source]¶ Load the wavfile with
scipy.io.wavfile
, converting int to float as needed.Create a sound table, resampling sound if needed.
-
class
Speech
(path, speaker, consonant, vowel, token, amplitude=0.05, **kwargs)[source]¶ Bases:
autopilot.stim.sound.sounds.File
Speech subclass of File sound.
Example of custom sound class - PARAMS are changed, but nothing else.
- Parameters
speaker (str) – Which Speaker recorded this speech token?
consonant (str) – Which consonant is in this speech token?
vowel (str) – Which vowel is in this speech token?
token (int) – Which token is this for a given combination of speaker, consonant, and vowel
Attributes:
-
type
= 'Speech'¶
-
PARAMS
= ['path', 'amplitude', 'speaker', 'consonant', 'vowel', 'token']¶
-
class
Gap
(duration, **kwargs)[source]¶ Bases:
object
A silent sound that does not pad its final chunk – used for creating precise silent gaps in a continuous noise.
- Parameters
duration (float) – duration of gap in ms
- Variables
gap_zero (bool) – True if duration is zero, effectively do nothing on play.
Attributes:
Methods:
Create and chunk an array of zeros according to
Gap.duration
chunk
([pad])If gap is not duration == 0, call parent
chunk
.buffer
()play
()-
type
= 'Gap'¶
-
PARAMS
= ['duration']¶
-
SOUND_LIST
= { 'File': <class 'autopilot.stim.sound.sounds.File'>, 'Gap': <class 'autopilot.stim.sound.sounds.Gap'>, 'Noise': <class 'autopilot.stim.sound.sounds.Noise'>, 'Speech': <class 'autopilot.stim.sound.sounds.Speech'>, 'Tone': <class 'autopilot.stim.sound.sounds.Tone'>, 'speech': <class 'autopilot.stim.sound.sounds.Speech'>}¶ Sounds must be added to this SOUND_LIST so they can be indexed by the string keys used elsewhere.
-
STRING_PARAMS
= ['path', 'speaker', 'consonant', 'vowel', 'type']¶ These parameters should be given string columns rather than float columns.
Bother Jonny to do this better.
v0.3 will be all about doing parameters better.
-
int_to_float
(audio)[source]¶ Convert 16 or 32 bit integer audio to 32 bit float.
- Parameters
audio (
numpy.ndarray
) – a numpy array of audio- Returns
Audio that has been rescaled and converted to a 32 bit float.
- Return type