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.agents.pilot.Pilot is initialized: ** autopilot.agents.pilot.Pilot.__init__ checks prefs.AUDIOSERVER,
and calls autopilot.agents.pilot.Pilot.init_audio.
- ** autopilot.agents.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.agents.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:
|
Initialize and check a mono (single-channel) noise. |
|
Initialize and check a multi-channel noise. |
A gap in a continous sound should not be padded (had its last chunk filled with zeros). |
- 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