base - sound

Base classes for sound objects, depending on the selected audio backend. Use the 'AUDIOSERVER' pref to select, or else use the default_sound_class() function.

Classes:

Sound([fs, duration])

Dummy metaclass for sound base-classes.

Pyo_Sound()

Metaclass for pyo sound objects.

Jack_Sound([jack_client])

Base class for sounds that use the JackClient audio server.

Functions:

get_sound_class([server_type])

Get the default sound class as defined by 'AUDIOSERVER'

class Sound(fs: int = None, duration: float = None, **kwargs)[source]

Bases: autopilot.stim.stim.Stim

Dummy metaclass for sound base-classes. Allows Sounds to be used without a backend to, eg. synthesize waveforms and the like.

Placeholder pending a full refactoring of class structure

Attributes:

PARAMS

type

server_type

Methods:

get_nsamples()

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

PARAMS = []
type = None
server_type = 'dummy'
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)
class Pyo_Sound[source]

Bases: autopilot.stim.stim.Stim

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

play()[source]
table_wrap(audio, duration=None)[source]

Records a PyoAudio generator into a sound table, returns a tableread object which can play the audio with .out()

Parameters
  • audio

  • duration

set_trigger(trig_fn)[source]
Parameters

trig_fn

class Jack_Sound(jack_client: Optional[autopilot.stim.sound.jackclient.JackClient] = None, **kwargs)[source]

Bases: autopilot.stim.stim.Stim

Base class for sounds that use the JackClient audio server.

Variables
  • ~Jack_Sound.PARAMS (list) – List of strings of parameters that need to be defined for this sound

  • ~Jack_Sound.type (str) – Human readable name of sound type

  • ~Jack_Sound.duration (float) – Duration of sound in ms

  • ~Jack_Sound.amplitude (float) – Amplitude of sound as proportion of 1 (eg 0.5 is half amplitude)

  • ~Jack_Sound.table (numpy.ndarray) – A Numpy array of samples

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

  • ~Jack_Sound.trigger (callable) – A function that is called when the sound completes

  • ~Jack_Sound.nsamples (int) – Number of samples in the sound

  • ~Jack_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).

  • ~Jack_Sound.fs (int) – sampling rate of client from jackclient.FS

  • ~Jack_Sound.blocksize (int) – blocksize of client from jackclient.BLOCKSIZE

  • ~Jack_Sound.server (Jack_Client) – Current Jack Client

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

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

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

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

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

  • ~Jack_Sound.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:

init_sound()

Abstract method to initialize sound.

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.

_init_continuous()

Create a duration quantized table for playing continuously

buffer_continuous()

Dump chunks into the continuous sound queue for looping.

play()

Play ourselves.

play_continuous([loop])

Play the sound continuously.

iter_continuous()

Continuously yield frames of audio.

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

abstract init_sound()[source]

Abstract method to initialize sound. Should set the table attribute

Todo

ideally should standardize by returning an array, but pyo objects don’t return arrays necessarily…

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.

_init_continuous()[source]

Create a duration quantized table for playing continuously

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

Continuously yield frames of audio. If this method is not overridden, just wraps table in a itertools.cycle object and returns from it.

Returns

A single frame of audio

Return type

np.ndarray

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

get_sound_class(server_type: Optional[str] = None) Union[Type[autopilot.stim.sound.base.Sound], Type[autopilot.stim.sound.base.Jack_Sound], Type[autopilot.stim.sound.base.Pyo_Sound]][source]

Get the default sound class as defined by 'AUDIOSERVER'

This function is also a convenience class for testing whether a particular audio backend is available

Returns: