sounds

This module defines classes to generate different sounds.

These classes are currently implemented: * Tone : a sinuosoidal pure tone * Noise : a burst of white noise * File : read from a file * Speech * Gap

The behavior of this module depends on prefs.get(‘AUDIOSERVER’). * If this is ‘jack’, or True:

Then import jack, define Jack_Sound, and all sounds inherit from that.

  • If this is ‘pyo’:

    Then import pyo, define PyoSound, and all sounds inherit from that.

  • If this is ‘docs’:

    Then import both jack and pyo, define both Jack_Sound and PyoSound, and all sounds inherit from object.

  • Otherwise:

    Then do not import jack or pyo, or define either Jack_Sound or PyoSound, and all sounds inherit from object.

Todo

Implement sound level and filter calibration

Classes:

Jack_Sound()

Base class for sounds that use the JackClient audio server.

BASE_CLASS

alias of autopilot.stim.sound.sounds.Jack_Sound

Tone(frequency, duration[, amplitude])

The Humble Sine Wave

Noise(duration[, amplitude, channel])

Generates a white noise burst with specified parameters

File(path[, amplitude])

A .wav file.

Gap(duration, **kwargs)

A silent sound that does not pad its final chunk -- used for creating precise silent gaps in a continuous noise.

Data:

STRING_PARAMS

These parameters should be given string columns rather than float columns.

Functions:

int_to_float(audio)

Convert 16 or 32 bit integer audio to 32 bit float.

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

  • type (str) – Human readable name of sound type

  • 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 samples

  • chunks (list) – table split up into chunks of BLOCKSIZE

  • trigger (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 Client

  • q (multiprocessing.Queue) – Audio Buffer queue from jackclient.QUEUE

  • q_lock (multiprocessing.Lock) – Audio Buffer lock from jackclient.Q_LOCK

  • play_evt (multiprocessing.Event) – play event from jackclient.PLAY

  • stop_evt (multiprocessing.Event) – stop event from jackclient.STOP

  • buffered (bool) – has this sound been dumped into the q ?

  • buffered_continuous (bool) – Has the sound been dumped into the continuous_q?

Initialize a new Jack_Sound

This sets sound-specific parameters to None, set jack-specific parameters to their equivalents in jackclient, initializes some other flags and a logger.

Attributes:

PARAMS

list of strings of parameters to be defined

type

string human readable name of sound

server_type

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_trigger()

Wait for the stop_evt trigger to be set for at least a second after the sound should have ended.

get_nsamples()

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.

buffer_continuous()

Dump chunks into the continuous sound queue for looping.

play()

Play ourselves.

play_continuous([loop])

Play the sound continuously.

stop_continuous()

Stop playing a continuous sound

end()

Release any resources held by this sound

PARAMS = []

list of strings of parameters to be defined

Type

list

type = None

string human readable name of sound

Type

str

server_type = 'jack'

type of server, always ‘jack’ for Jack_Sound s.

Type

str

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)

  • 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()[source]

Dump chunks into the sound queue.

After the last chunk, a None is put into the queue. This tells the jack server that the sound is over and that it should clear the play flag.

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.

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
stop_continuous()[source]

Stop playing a continuous sound

Should be merged into a general stop method

end()[source]

Release any resources held by this sound

BASE_CLASS

alias of autopilot.stim.sound.sounds.Jack_Sound Attributes:

PARAMS

list of strings of parameters to be defined

server_type

type of server, always 'jack' for Jack_Sound s.

type

string human readable name of sound

Methods:

buffer()

Dump chunks into the sound queue.

buffer_continuous()

Dump chunks into the continuous sound queue for looping.

chunk([pad])

Split our table up into a list of Jack_Sound.blocksize chunks.

end()

Release any resources held by this sound

get_nsamples()

given our fs and duration, how many samples do we need?

play()

Play ourselves.

play_continuous([loop])

Play the sound continuously.

quantize_duration([ceiling])

Extend or shorten a sound so that it is a multiple of jackclient.BLOCKSIZE

set_trigger(trig_fn)

Set a trigger function to be called when the stop_evt is set.

stop_continuous()

Stop playing a continuous sound

wait_trigger()

Wait for the stop_evt trigger to be set for at least a second after the sound should have ended.

class Tone(frequency, duration, amplitude=0.01, **kwargs)[source]

Bases: autopilot.stim.sound.sounds.Jack_Sound

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:

PARAMS

list of strings of parameters to be defined

type

string human readable name of sound

Methods:

init_sound()

Create a sine wave table using pyo or numpy, depending on the server type.

PARAMS = ['frequency', 'duration', 'amplitude']

list of strings of parameters to be defined

Type

list

type = 'Tone'

string human readable name of sound

Type

str

init_sound()[source]

Create a sine wave table using pyo or numpy, depending on the server type.

class Noise(duration, amplitude=0.01, channel=None, **kwargs)[source]

Bases: autopilot.stim.sound.sounds.Jack_Sound

Generates a white noise burst with specified parameters

The type attribute is always “Noise”.

Initialize a new white noise burst with specified parameters.

The sound itself is stored as the attribute self.table. This can be 1-dimensional or 2-dimensional, depending on channel. If it is 2-dimensional, then each channel is a column.

Parameters
  • duration (float) – duration of the noise

  • amplitude (float) – amplitude of the sound as a proportion of 1.

  • channel (int or None) – which channel should be used If 0, play noise from the first channel If 1, play noise from the second channel If None, send the same information to all channels (“mono”)

  • **kwargs – extraneous parameters that might come along with instantiating us

Attributes:

PARAMS

list of strings of parameters to be defined

type

string human readable name of sound

Methods:

init_sound()

Defines self.table, the waveform that is played.

PARAMS = ['duration', 'amplitude', 'channel']

list of strings of parameters to be defined

Type

list

type = 'Noise'

string human readable name of sound

Type

str

init_sound()[source]

Defines self.table, the waveform that is played.

The way this is generated depends on self.server_type, because parameters like the sampling rate cannot be known otherwise.

The sound is generated and then it is “chunked” (zero-padded and divided into chunks). Finally self.initialized is set True.

class File(path, amplitude=0.01, **kwargs)[source]

Bases: autopilot.stim.sound.sounds.Jack_Sound

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:

PARAMS

list of strings of parameters to be defined

type

string human readable name of sound

Methods:

init_sound()

Load the wavfile with scipy.io.wavfile , converting int to float as needed.

PARAMS = ['path', 'amplitude']

list of strings of parameters to be defined

Type

list

type = 'File'

string human readable name of sound

Type

str

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 Gap(duration, **kwargs)[source]

Bases: autopilot.stim.sound.sounds.Jack_Sound

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:

type

string human readable name of sound

PARAMS

list of strings of parameters to be defined

Methods:

init_sound()

Create and chunk an array of zeros according to Gap.duration

chunk([pad])

If gap is not duration == 0, call parent chunk.

buffer()

Dump chunks into the sound queue.

play()

Play ourselves.

type = 'Gap'

string human readable name of sound

Type

str

PARAMS = ['duration']

list of strings of parameters to be defined

Type

list

init_sound()[source]

Create and chunk an array of zeros according to Gap.duration

chunk(pad=False)[source]

If gap is not duration == 0, call parent chunk. :Parameters: pad (bool) – unused, passed to parent chunk

buffer()[source]

Dump chunks into the sound queue.

After the last chunk, a None is put into the queue. This tells the jack server that the sound is over and that it should clear the play flag.

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.

STRING_PARAMS = ['path', 'type']

These parameters should be given string columns rather than float columns.

Bother Jonny to do this better bc it’s really bad.

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

numpy.ndarray