Sounds

Tests for generating sound stimuli.

This script runs tests that generate different sound stimuli and verifies that they are initialized correctly.

Currently these only work if AUDIOSERVER is ‘jack’. ‘pyo’ is not tested. ‘docs’ doesn’t actually generate waveforms.

This doesn’t require (or test) a running jackd or even a JackClient. Instead, these tests short-circuit those dependencies by manually setting FS and BLOCKSIZE in autopilot.stim.sound.jackclient.

A TODO is to test the JackClient itself.

Currently only the sound Noise is tested.

These tests cover multiple durations and amplitudes of mono and multi-channel Noise, including some edges cases like very short durations or zero amplitude.

The rest of this docstring addresses the workaround used to short-circuit jackd and JackClient.

Here is the sequence of events that leads to FS and BLOCKSIZE. * If an autopilot.core.pilot.Pilot is initialized: ** autopilot.core.pilot.Pilot.__init__ checks prefs.AUDIOSERVER,

and calls autopilot.core.pilot.Pilot.init_audio.

** autopilot.core.pilot.Pilot.init_audio calls

autopilot.external.__init__.start_jackd.

** autopilot.external.__init__.start_jackd takes the JACKDSTRING pref

and replaces the token ‘-rfs’ in it with the FS pref. The jackd process is launched and stored in autopilot.external.JACKD_PROCESS. That process may fail or not, we continue anyway.

** Next, autopilot.core.pilot.Pilot.init_audio instantiates an

autopilot.stim.sound.jackclient.JackClient()

** autopilot.stim.sound.jackclient.JackClient.__init__

initalizes a jack.Client

** autopilot.stim.sound.jackclient.JackClient.fs

is set to jack.Client.samplerate. Note that this is either the requested sample rate, or some default value from jack (not Autopilot) if the client did not actually succeed in booting.

** autopilot.stim.sound.jackclient.FS (a global variable) is set to

autopilot.stim.sound.jackclient.JackClient.fs

  • Later, a sound (e.g., Noise) is initialized.

** autopilot.stim.sound.sounds.Noise.__init__ calls super().__init__, ** which is autopilot.stim.sound.sounds.Jack_Sound.__init__ ** autopilot.stim.sound.sounds.Jack_Sound.__init__

sets self.fs to jackclient.FS

** autopilot.stim.sound.sounds.Noise.__init__ calls

autopilot.stim.sound.sounds.Noise.init_sound

** autopilot.stim.sound.sounds.Noise.init_sound calls

autopilot.stim.sound.sounds.Jack_Sound.get_nsamples

** autopilot.stim.sound.sounds.Jack_Sound.get_nsamples

inspects self.fs

To remove the dependence on jackd2 and JackClient, the entire first block of code can be circumvented by setting these: autopilot.stim.sound.jackclient.FS autopilot.stim.sound.jackclient.BLOCKSIZE

Functions:

test_init_noise(duration_ms, amplitude, ...)

Initialize and check a mono (single-channel) noise.

test_init_multichannel_noise(duration_ms, ...)

Initialize and check a multi-channel noise.

test_init_noise(duration_ms, amplitude, check_duration_samples, check_n_chunks_expected)[source]

Initialize and check a mono (single-channel) noise.

A mono Noise is initialized with specified duration and amplitude. The following things are checked: * The attributes should be correctly set * The table should be the right dtype and the right duration,

given the sampling rate

  • The chunks should be correct, given the block size. The last chunk should be zero-padded.

  • The waveform should not exceed amplitude anywhere

  • As long as the waveform is sufficiently long, it should exceed 90% of the amplitude somewhere

  • Concatenating the chunks should generate a result equal to the table, albeit zero-padded to a multiple of the block size.

  • Specifying channel as None should give identical results to leaving it unspecified.

duration_ms : passed as duration amplitude : passed as amplitude check_duration_samples : int or None

If not None, the length of the sounds table should be this

check_n_chunks_expectedint or None

If not None, the length of the sounds chunks should be this

test_init_multichannel_noise(duration_ms, amplitude, channel, check_duration_samples, check_n_chunks_expected)[source]

Initialize and check a multi-channel noise.

A multi-channel Noise is initialized with specified duration, amplitude, and channel. The following things are checked: * The attributes should be correctly set * The table should be the right dtype and the right duration,

given the sampling rate

  • The chunks should be correct, given the block size. The last chunk should be zero-padded.

  • The column channel should contain non-zero data and all other columns should contain zero data.

  • The waveform should not exceed amplitude anywhere

  • As long as the waveform is sufficiently long, it should exceed 90% of the amplitude somewhere

  • Concatenating the chunks should generate a result equal to the

duration_ms : passed to Noise as duration amplitude : passed to Noise as amplitude channel : passed to Noise as channel check_duration_samples : int or None

If not None, the length of the sounds table should be this

check_n_chunks_expectedint or None

If not None, the length of the sounds chunks should be this