Detailed Documentation

STRAUSS (Sonification Tools and Resources for Analysis Using Sound Synthesis)

This module provides a toolkit for sonification, i.e. the representation of data using sound.

User-Facing Modules

These are the user-facing modules of the strauss code, that are used to define a Sonification.

Sources

The sources submodule: representing data as sound sources.

This submodule deals with the mapping of input datasets to the parameters controlling sound in the eventual sonification.

strauss.sources.mappable

List of strings indicating possible sonification parameters to which data can be mapped.

Type:

list(str)

strauss.sources.evolvable

List of strings indicating the subset of mappable parameters that can be evolved continuosly for an individual Source.

Type:

list(str)

strauss.sources.param_limits

List of tuples indicating the default numerical ranges bounding corresponding mappable parameter (e.g. 0-1 for volume).

Type:

list(tuple)

strauss.sources.param_lim_dict

Dictionary combining mappable (keys) and param_limits (items).

Type:

dict

Todo

  • Store mappable, evolvable and parameter ranges in YAML files (cleaner).

  • Specialised Event and Object child classes (eg. spectralisation).

class strauss.sources.Events(mapped_quantities)[source]

Bases: Source

Represent data as time-discrete events.

Child class of Source, for Event-type sources. Each Event is discrete in time with single data values mapped to each sonification parameter.

fromdict(datadict)[source]

Take input data from dictionary

Parameters:

datadict (dict) – keys are self.mapped_values, with entries corresponding to the input data. Multiple sources are provided as lists, with data for each source corresponding to the values. Single sources can be represented as single values.

fromfile(datafile, coldict)[source]

Take input data from ASCII file

Parameters:
  • datafile (str) – path to input data file

  • coldict (dict) – keys are self.mapped_values, with entries integer indexes for their corresponding column.

class strauss.sources.Objects(mapped_quantities)[source]

Bases: Source

Represent data as time-continuous objects.

Child class of Source. In addition to supporting single values for each parameter (see Events class), objects also support time evolution for evolvable parameters, given a time-evo mapping.

Todo

  • implement fromfile method

fromdict(datadict)[source]

Take input data from dictionary

Parameters:

datadict (dict) – keys are self.mapped_values, with entries corresponding to the input data. Multiple sources are provided as either lists or 2D numpy.array objects, with each source corresponding to the entries or columns respectively. Single sources can be represented as single values or 1D numpy.array (for evolving parameters).

class strauss.sources.Source(mapped_quantities)[source]

Bases: object

Generic source class defining common methods/attributes

Source and its child classes represent the input data, and its mapping to sonification parameters.

Note

Source isn’t used directly, instead use child classes Events or Objects.

mapped_quantities

The subset of parameters to which data will be mapped.

Type:

list(str)

raw_mapping

Housing the input mapped parameters and data, with keys corresponding to mapped_quantities.

Type:

dict

mapping

processed mapping dict rescaled to parameter ranges, or interpolation funtions for evolving parameters.

Type:

dict

Raises:

UnrecognisedProperty – if mapped_quantities entry not in mappable.

apply_mapping_functions(map_funcs={}, map_lims={}, param_lims={})[source]

Taking input data and mapping to parameters.

This function does the bulk of the work for Source classes, taking each input data variable and applying the mapping function (x’ = x by default), descaling by the x’ upper and lower limits and rescaling to the sonification parameter limits. These values are stored for non-evolving parameters, while for evolving properties they are converted to interpolation functions.

Parameters:
  • map_funcs (dict, optional) – dict with keys that must be a subset self.mapped_quantities. Entries are then function-like objects for converting input data (e.g. taking log of a data set). If not provided, each conversion function is assumed to be f(x) = x.

  • map_lims (dict, optional) – dict with keys that must be a subset self.mapped_quantities. Entries are tuples indicating the lower (index 0) and upper (index 1) limits on the converted input data values. numerical values indicate absolute limits, while strings are used to indicate percentiles [e.g. (‘10%’,’95%’)]. converted data values are clipped to these limits. If not provided, (0,1) is assumed.

  • param_lims (dict, optional) – dict with keys that must be a subset self.mapped_quantities. Entries are tuples indicating the lower (index 0) and upper (index 1) limits of the mapped sonification parameters. The map_lims ranges are resaled to these ranges to give the parameter values. If not provided, the default param_lim_dict values are taken.

Note

There is special behaviour for the polar and azimuth parameters, to ensure shortest angular distance when interpolating across the 0-2pi and 0-pi boundaries.

exception strauss.sources.UnrecognisedProperty[source]

Bases: Exception

Error raised when trying to map unrecognised parameters

Score

The score submodule: musical constraints on what Sources can play

This submodule is intended to control any musical aspects of the sonification, by providing constraints on harmonic and rhythmic aspects.

Todo

  • Incorporate more rhythmic options, such as quantisation

  • Have the Score class handle pitch and rhythm assignment from Sources directly, instead of the Sonification class.

  • Support chord change intervals as a mapped parameter

  • Provide template chord charts for users

class strauss.score.Score(chord_sequence, length, pitch_binning='adaptive')[source]

Bases: object

Class defining the musical score for the sonification

The Score class controls the musical aspects of the sonification. Currently supports a chordal score, defining a set of notes that can be played for each section of the simulation. The score also controls the length of the sonification.

Note

Currently, no rhythmic constraints are incorporated in the score. Chords are divided evenly over the length of the sonification. For example for a one minute sonification (length = '1m 0s') the chord_sequence = "Am7_3 | D9_3 | Gmaj7_2" plays each chord for 20s each. Chaining the same chord can be used to change the length of these intervals, (e.g. chord_sequence = "F_3 | F_3 | C_4" plays F for 40s and C for 20s, [[“C2”,”G3”,”E4”]*37+[“G2”,”D3”,”B4”]*23] would play the C voicing for 37s and G voicing for 23s).

strauss.score.parse_chord_sequence(chord_sequence)[source]

parse a chord sequence from a string

Parameters:

chord_sequence (str) – chord sequence to parse, with chord names appended with ‘_N’ where N is the root octave of the chord, and each chord is separated by a pipe character, ‘|’.

Returns:

the chord sequence represented as a list of lists, where each sub-list is a chord comprised of strings representing each note in scientific pitch notation (e.g. ‘A4’)

Return type:

note_list (list(list))

Generator

The generator submodule: creating sounds for the sonification.

This submodule handles the actual generation of sound for the sonification, after parameterisation by the Sources and musical choices dictated by the Score.

Todo

  • Consolidate more common code into the Generator parent class.

  • Support more Envelope and LFO types in the play methods (want pitch, volume and filter options for each)

  • Check buffer length consistency for spectralizer - do we hit grid points?

  • Throw appropriate errors when rendering with unreasonable length and freq combinations

class strauss.generator.Generator(params={}, samprate=48000)[source]

Bases: object

Generic generator Class, defining common code for child classes

Generators have common initialisation and methods that are defined by this parent class.

samprate

Samples per second of audio stream (Hz)

Type:

int

audbuff

Samples per audio buffer

Type:

int

preset

Dictionary of parameters defining the generator.

Type:

dict

env_segment_curve(t, t1, y0, k)[source]

Formula for segments of the envelope function

Function to evaluate the segments of the envelope, allowing for curvature, i.e. concave & convex envelope segments.

Parameters:
  • t (float) – time of each sample along segment

  • t1 (float) – time of segment endpoint

  • y0 (float) – starting value of segment

  • k (float) – curvature value of segment, from (-1,1), with positive values indicating concave and negative convex curvature.

envelope(samp, params, etype='volume')[source]

Envelope function for modulating a single note

The envelope function takes the pre-defined envelope parameters for the specified envelope type and returns the envelope value at each sample. envelopes are defined by attack, decay, sustain and release ('A','D','S' & 'R) values, as well as segment curvatures ('Ac','Dc', & 'Rc) and a normalisation 'level'. See this article for a more detailed explanation of ADSR envelopes.

Parameters:
  • samp (array-like) – Audio sample index

  • params (dict) – Keys and values of generator parameters

  • etype (optional , str) – type of envelope, indicating which params group to read (i.e. if etype='volume', read from :obj:`volume_envelope)

lfo(samp, sampfrac, params, ltype='pitch')[source]

Low-Frequency oscillator (LFO)

This function takes the pre-defined LFO parameters (if switched on) for the specified LFO type and returns the LFO value at each sample. LFOs are defined by the same values as strauss.generator.envelope(), with an additional use switch, a waveform (wave, e.g. sine), an amplitude (amount), a frequncy in Hz (freq) a frequency shift in octaves (freq_shift) and a phase, either numerical in cycles or 'random' to indicate randomised.

Note

To modulate the frequency of an oscillator, use the freq_shift parameter, rather than freq

Parameters:
  • samp (array-like) – Audio sample index

  • sampfrac (array-like) – Audio sample as fraction of total number of samples

  • params (dict) – Keys and values of generator parameters

  • ltype (optional , str) – type of LFO, indicating which params group to read (i.e. if ltype='volume', read `from :obj:`pitch_envelope)

Returns:

amplitude of LFO at each input sample

Return type:

v (array-like)

load_preset(preset='default')[source]

Load parameters from a preset YAML file.

Wrapper method for the presets.synth.load_preset or presets.sampler.load_preset functions. Always load the default preset first to ensure all parameters are defined, and then if necessary reload parameters defined by preset

Parameters:

preset (str) – name of the preset. Built-in presets can be named directly and looks to import the preset from the <MODULE_PATH>/presets/<GENERATOR>/ directory as <preset>.yml, where <GENERATOR> is either synth or sampler, <MODULE_PATH> is the path to the strauss module (i.e. strauss.__file__). Custom presets can also be loaded from <preset>.yml if preset represents a path containing file separators.

modify_preset(parameters, cleargroup=[])[source]

Modify parameters within current preset

method allows user to tweak generator parameters directly, using a dictionary of parameters and their values. subgroups within the preset are represented as nested dictionaries.

Parameters:
  • parameters (dict) – keys and items are the preset parameter names and new values. Nested dictionaries are used to redefine grouped parameters, e.g. {'volume_envelope':{'A':0.5}}

  • cleargroup (optional list(str)) – if required, list of the group names to be completely reset (e.g. if defining new oscillators set for synth).

noise(s, f, p)[source]

White noise oscillator

Note

f and p have no efffect for this oscillator, generating a random value for each sample.

Parameters:
  • s (array-like) – sample index

  • f (float) – unused

  • p (float or str) – unused

Returns:

values for each sample

Return type:

v (array-like)

preset_details(term='*')[source]

Print the names and descriptions of presets

Wrapper for preset_details function. lists the name and description of built-in presets with names matching the search term.

Parameters:
  • term (optional, str) – name or glob term for built-in

  • preset (s)

saw(s, f, p)[source]

Sawtooth-wave oscillator

Parameters:
  • s (array-like) – sample index

  • f (float) – samples per cycle

  • p (float or str) – if numerical, phase in units of cycles, 'random' indicates randomised.

Returns:

values for each sample

Return type:

v (array-like)

sine(s, f, p)[source]

Sine-wave oscillator

Parameters:
  • s (array-like) – sample index

  • f (float) – samples per cycle

  • p (float or str) – if numerical, phase in units of cycles, 'random' indicates randomised.

Returns:

values for each sample

Return type:

v (array-like)

square(s, f, p)[source]

Square-wave oscillator

Parameters:
  • s (array-like) – sample index

  • f (float) – samples per cycle

  • p (float or str) – if numerical, phase in units of cycles, 'random' indicates randomised.

Returns:

values for each sample

Return type:

v (array-like)

tri(s, f, p)[source]

Triangle-wave oscillator

Parameters:
  • s (array-like) – sample index

  • f (float) – samples per cycle

  • p (float or str) – if numerical, phase in units of cycles 'random' indicates randomised.

Returns:

values for each sample

Return type:

v (array-like)

class strauss.generator.Sampler(sampfiles, params=None, samprate=48000, sf_preset=None)[source]

Bases: Generator

Sampler generator class

This generator class generates sound using pre-loaded audio samples, representing different notes. Presets define parameters controlling these defines attribute self.gtype = 'sampler'.

gtype

Generator type

Type:

str

Todo

  • Add zone mapping for samples (e.g. allow a sample to define a range of notes played at different speeds).

  • Support non-scientifically named notes? (e.g 'cymbal', 'snare').

  • Have sample loading defined via the preset rather than the sampfiles variable?

forward_back_loopsamp(s, start, end)[source]

Looping samples forward-backward alternately using indexing

From a list of samples and start and end loop-points, return a new list of samples that index the audio file samples to create a back and forth looping effect.

Parameters:
  • s (array-like) – Sample indexes for the duration of a source’s note

  • start (int) – Sample index at which to start the loop

  • end (int) – Sample index at which to end the loop

Returns:

new sample indices to create a back and forth looping effect

Return type:

s_new (array-like)

forward_loopsamp(s, start, end)[source]

Looping samples forward using indexing

From a list of samples and start and end loop-points, return a new list of samples that index the audio file samples to create a forward-looping effect.

Parameters:
  • s (array-like) – Sample indexes for the duration of a source’s note

  • start (int) – Sample index at which to start the loop

  • end (int) – Sample index at which to end the loop

Returns:

new sample indices to create a forward-looping effect

Return type:

s_new (array-like)

get_sfpreset_samples(sfpreset)[source]

Reading samples from a soundfont file along with metadata.

Read in the audio samples from a .sf2 file to populate available notes, mapping the MIDI key values to musical notes, scaling and tuning samples as appropriate.

Parameters:

sf_preset (optional, int) – preset to use. All .sf2 files should contain at least one preset. When given default None value, will print available presets and select the first preset. Note presets are 1-indexed.

Returns:

dictionary of data required to load soundfont samples in to the Sampler, including raw samples, sample_rate, original_pitch of the samples, the min_note and max_note in midi values to use the sample, and the sample_map, assigning each sample to a note.

Return type:

sfpre_dict (dict)

load_samples()[source]

Load audio samples into the sampler.

Read audio samples in from a specified directory or via a dictionary of filepaths, generate interpolation functions for each, and assign them to a named note in scientific pitch notation (e.g. 'A4').

Note

Notes are assigned based on a tag in the filename (see Sampler), not by analysing the audio itself. If a tuned sample is tagged as the wrong note, this will carry over to the sonification. However, this allows non-pitched samples to be assigned notes and triggered.

play(mapping)[source]

Play the sound for a given source.

Play a given source and return the sample values for combination into the overall sonification.

Note

mapping is a linear dictionary (not nested, as for strauss.generator.modify_preset()) where group members are indicated using '/' notation (e.g. {'volume_envelope/A': 0.5, ...).

Parameters:

mapping (dict) – keys and items are generator parameter names and their values. This combines all the preset mapped parameters, overwritten by any Source-mapped parameters (represented as values or interpolation functions for static and evolving parameters, respectively). This is a linear dictionary (not nested, see strauss.generator.modify_preset()) where group members are indicated using '/' notation (e.g. {'volume_envelope/A': 0.5, ...).

reconstruct_samples(sfpre_dict)[source]

Interpolate, combine and resample soundfont samples for each note, and load into the Sampler.

Parameters:

sfpre_dict (dict) – dictionary of data required to load soundfont samples in to the Sampler, including raw samples, sample_rate, original_pitch of the samples, the min_note and max_note in midi values to use the sample, and the sample_map, assigning each sample to a note.

Returns:

output dictionary of mapped notes, with values of arrays of sample values at the samplerate of the Generator.

Return type:

sampdict (dict)

class strauss.generator.Spectralizer(params=None, samprate=48000)[source]

Bases: Generator

Spectralizer generator class

This generator class synthesises sound from a spectrum input using an inverse Fast Fourier Transform (iFFT) algorithm. Defining a minimum and maximum frequency in Hz, input spectrum is interpolated between these points such that the output audio signal has the requested length. Phases are randomised to avoid phase correlations.

gtype

Generator type

Type:

str

Todo

  • Add other synthesiser types, aside from additive (e.g. FM, vector, wavetable)?

play(mapping)[source]

Play the sound for a given source.

Play a given source and return the sample values for combination into the overall sonification.

Note

mapping is a linear dictionary (not nested, as for strauss.generator.modify_preset()) where group members are indicated using '/' notation (e.g. {'volume_envelope/A': 0.5, ...).

Parameters:

mapping (dict) – keys and items are generator parameter names and their values. This combines all the preset mapped parameters, overwritten by any Source-mapped parameters (represented as values or interpolation functions for static and evolving parameters, respectively). This is a linear dictionary (not nested, see strauss.generator.modify_preset()) where group members are indicated using '/' notation (e.g. {'volume_envelope/A': 0.5, ...).

spectrum_to_signal(spectrum, phases, new_nlen, mindx, maxdx, interp_type)[source]

Convert the input spectrum into sound signal

Performs the inverse fast fourier transform to produce spectral sonification.

Parameters:
  • spectrum (ndarray) – Values of the spectrum, ordered from high to low frequency

  • phases (ndarray) – Array of values of [0,2*numpy.pi] representing the complex number argument

  • new_nlen (int) – Number of samples needed to enclose the output signal.

  • mindx (int) – Index in total Fourier transform represnting the minimum audio frequency

  • maxdx (int) – Index in total Fourier transform represnting the maximum audio frequency

  • interp_type (str) – Interpolation approach, either “sample” interpolating between samples, or “preserve_power” where cumulative power is interpolated and then differentiated to avoid missing power.

class strauss.generator.Synthesizer(params=None, samprate=48000)[source]

Bases: Generator

Synthesizer generator class

This generator class synthesises sound using mathmatically generated waveforms or ‘oscillators’, from a combination of oscillator methods defined in the parent class. The relative frequency, phase and amplitude of these oscillators are defined in the preset, and linearly combined to produce the sound. defines attribute self.gtype = 'synth'.

gtype

Generator type

Type:

str

Todo

  • Add other synthesiser types, aside from additive (e.g. FM, vector, wavetable)?

combine_oscs(s, f)[source]

Evaluate and linearly combine oscillators.

Parameters:
  • s (array-like) – Sample index

  • f (float or str) – If numerical, frequency in cycles per second, if string, note name in scientific pitch notation (e.g. 'A4')

Returns:

values for each sample

Return type:

tot (array-like)

modify_preset(parameters, clear_oscs=True)[source]

Synthesizer-specific wrapper for the modify_preset method.

This gives control over whether or not to clear the arbitrary number of oscillators for synthesizer.

Parameters:
  • parameters (dict) – keys and items are the preset parameter names and new values. Nested dictionaries are used to redefine grouped parameters, e.g. {'volume_envelope':{'A':0.5}}

  • clear_oscs (optional, bool) – if True, clear all oscillators from the existing preset. Turn off if just wishing to tweak non-oscillator parameters.

play(mapping)[source]

Play the sound for a given source.

Play a given source and return the sample values for combination into the overall sonification.

Note

mapping is a linear dictionary (not nested, as for strauss.generator.modify_preset()) where group members are indicated using '/' notation (e.g. {'volume_envelope/A': 0.5, ...).

Parameters:

mapping (dict) – keys and items are generator parameter names and their values. This combines all the preset mapped parameters, overwritten by any Source-mapped parameters (represented as values or interpolation functions for static and evolving parameters, respectively). This is a linear dictionary (not nested, see strauss.generator.modify_preset()) where group members are indicated using '/' notation (e.g. {'volume_envelope/A': 0.5, ...).

setup_oscillators()[source]

Setup and consolidate oscs into a two-variable function.

Reads the parameterisation of each oscillator from the preset, specifying their waveform (wave), relative amplitude (level), detuning in cents (det) and phase, either a number in units of cycles, or a string specifying randomisation ('random'). Sets the self.generate method, using the self.combine_oscs.

Note

This is deprecated and will likely be removed from future versions

strauss.generator.detuned_saw(samples, freqsamp, oscdets=[1, 1.005, 0.995])[source]

DEPRECATED CODE: Three oscillator sawtooth wave generator with slight detuning for texture

strauss.generator.forward_back_loopsamp(s, start, end)[source]

Produce array of sample indices for looping a sample forward-back.

Sample indices between values start and end that will loop the sample such that it loops “forward-back”, i.e. start, start+1, …, end-1, end, end-1, …, start+1, start, start+1, … etc. … etc.

Parameters:
  • s (ndarray) – array of input sample indices

  • start (int) – Index of sample after which looping should commence

  • end (int) – Index of sample after which audio loops

Returns:

array of output sample indices

Return type:

out (ndarray)

strauss.generator.forward_loopsamp(s, start, end)[source]

Produce array of sample indices for looping a sample forward.

Sample indices between values start and end that will loop the sample such that it loops “forward”, i.e. start, start+1, …, end-1, end, start, … etc.

Parameters:
  • s (ndarray) – array of input sample indices

  • start (int) – Index of sample after which looping should commence

  • end (int) – Index of sample after which audio loops

Returns:

array of output sample indices

Return type:

out (ndarray)

strauss.generator.gen_chord(stream, chordname, rootoctv=3)[source]

DEPRECATED CODE: generate chord over entire stream given chord name and optional octave of root note

strauss.generator.legacy_env(t, dur, a, d, s, r)[source]

DEPRECATED CODE: older function for generating envelopes

Channels

channels submodule representing the output audio channels.

This submodule defines objects relevant to the output audio channels, including the audio_channels which defines arrays of microphone objects that are channeled to different speakers in the sonification output.

class strauss.channels.audio_channels(setup='stereo', custom_setup={})[source]

Bases: object

Representing output audio channels.

Data object representing the output channels of the sonification for preset common audio setups, or a custom setup. Stores an array of mic objects for each output channel.

Parameters:
  • setup (str) – Type of audio setup. Supported options are "mono", "stereo", "5.1" and "7.1", or "custom".

  • custom_setup (dict) – Dictionary defining a customised audio setup, containing keys for "azimuths", "types" and "labels", containing lists parameterising the first three arguments of the mic object, respectively in the order of their channel index. Also optionally an forder list to unscramble any channel order scrambling done by ffmpeg processing in the sonification sae routines (this may need to be found empirically, awaiting better multichannel save routine).

Raises:

Exception – If custom requested but no parameters provided, or custom parameters provided without requesting a custom setup.

plot_antenna()[source]

Plot antennae patterns for chosen audio setup

Make a matplotlib figure object, representing a radial plot demonstrating the antennae patterns of each channel

Returns:

figure object that can be shown or saved using the standard matplotlib routines.

Return type:

fig (matplotlib.pyplot.figure)

setup_channels(azimuths, types, labels, orders=None, degrees=None)[source]

initialise audio channel setup for lists of properties

Subroutine for setting up the audio_channels as arrays of mic objects, setting the self.mics list attribute to the audio_channels

Parameters:
  • azimuths (list(float)) – list of azimuth values for mic object

  • types (list(float)) – list of mic_types values for mic object.

  • labels (list(float)) – list of label values for mic object

class strauss.channels.mic(azimuth, mic_type='directional', label='C', channel=1, order=None, degree=None)[source]

Bases: object

Microphone / sound detector object

This class represents a microphone, or sound-detector, corresponding to a particular output channel for audio spatialisation in the sonicfication.

Parameters:
  • azimuth (float) – Angular position of the microphone on the horizontal plane, from 0 to 2pi with 0.5 pi being to the left and 1.5 pi being to the right. In the special case of ambisonic, this is instead an index corresponding to the Ambisonic Channel Number (ACN)

  • mic_type (str) – Type of microphone, choose from "directional" (collects using a cardioid antenna pattern), "omni" (collects sound from all directions equally) and "mute" (collects no sound, useful for e.g. muting auxillary channels)

  • label (str) – A label for the mic

  • channel (int) – channel ordering in the output (starting from 0 e.g. stereo L=0, R=1)

Raises:

Exception – if mic_type not in allowed options

Sonification

sonification: generate sonification, combining submodules.

This Submodule handles the combining of all the constituent subroutines into a single sonification object that can then render and output/save the resultant sonification. This handles feeding of information between strauss modules, including taking the sources mapping, applying any musical constraints from score running the generators to make sound and combining them into the output channels for the overall spatialised sonificiation.

Todo

  • Delegate more musical process to the score module

class strauss.sonification.Sonification(score, sources, generator, audio_setup='stereo', caption=None, samprate=48000, ttsmodel=None)[source]

Bases: object

Representing the overall sonification

This class combines the data sources, musical score constraints and generator together to generate and render the ultimate sonification for saving or playing in the jupyter-notebook environment

Todo

  • Support custom audio setups here too.

hear()[source]

Play audio directly to the sound device, for command-line playback.

If available, use the sounddevice module to stream the sonification to the sound device directly (speakers, headphones, etc.) via the underlying PortAudio C-library. if unavaialable, raise error.

Todo

  • Add more options to control the streamed audio

notebook_display(show_waveform=True)[source]

plot the waveforms and embed player in the notebook

Show waveforms and embed an audio player in the python notebook for direct playback. the notebook player only supports up to stereo, so if more than two channels, only the first two are used as left and right.

render(downsamp=1)[source]

Render the sonification.

Generates the sonification by running the Synthesizer play() or Sampler play() functions, and combining these into the output channel streams using any spatialisation for the specified audio_channels.

Parameters:

downsamp (optional, int) – Optionally downsample sources for multi-source sonifications for a quicker test render by some integer factor.

save(fname, master_volume=1.0, embed_caption=True)[source]

Save render as a combined multi-channel wav file

Can use this function to save sonification of any audio_setup to a 32-bit depth WAV using scipy.io.wavfile

Parameters:
  • fname (str)

  • master_volume (float) – peak, from 0-1

  • embed_caption (bool) – at the start of the output audio

Todo

  • Raise scipy issue if common 24-bit WAV can be supported

save_combined(fname, ffmpeg_output=False, master_volume=1.0)[source]

Save render as a combined multi-channel wav file

Can use this function to save sonification of any audio_setup, using ffmpeg processing, and unscrampling to the correct channel order.

Parameters:
  • fname (str)

  • ffmpeg_output (bool) – output to screen

  • master_volume (float) – peak, from 0-1

save_stereo(fname, master_volume=1.0)[source]

Save stereo or mono sonifications

Can use this function to save "stereo" or "mono" sonifications while avoiding ffmpeg processing.

Parameters:
  • fname (str)

  • master_volume (float) – peak, from 0-1

Todo

  • Support master_volume in decibels

Ancillary Modules

These are modules intended for internal use by the strauss module

Utilities

The utilities submodule: useful functions for strauss

This submodule is for useful utility functions used by other strauss modules. Generally these are not intended for direct use by the user.

class strauss.utilities.Capturing(iterable=(), /)[source]

Bases: list

Context manager for handling stdout (see https://stackoverflow.com/a/16571630)

class strauss.utilities.NoSoundDevice(err)[source]

Bases: object

Drop-in replacement for sounddevice module if not working, so we can still use other functionality.

err

Error message from trying to import sounddevice

Type:

Exception

play(*args, **kwargs)[source]

Dummy function replacing sounddevice.play when unavailable.

Parameters:
  • *args – arguments (ignored)

  • **kwargs – keyword-only arguments (ignored)

strauss.utilities.const_or_evo(x, t)[source]

If x is callable, return x(t), else return x

Parameters:
  • x – input value, either a numerical value or a

  • function

  • t (numerical) – values to evaluate x function

strauss.utilities.const_or_evo_func(x)[source]

If x is callable, return x, else provide a function that just returns x

Parameters:
  • x – input value, either a numerical value or a

  • function

strauss.utilities.get_supported_coqui_voices()[source]

Show supported Coqui-AI TTS voices

strauss.utilities.linear_to_nested_dict_reassign(fromdict, todict)[source]

Iterate through a linear dictionary to reassign nested values using keypaths (d1[‘a/b/c’] -> d2[‘a’][‘b’][‘c’], d1[‘a’]->d2[‘a’])

Parameters:
  • fromdict (dict) – Dictionary containing values to assign

  • todict (dict) – Dictionary containing values to be reassigned

strauss.utilities.nested_dict_fill(fromdict, todict)[source]

Recurse through dictionaries and sub-dictionaries in fromdict and assign to any entries missing from todict

Parameters:

fromdict (dict) – Dictionary containing values to assign

todict (dict): Dictionary containing values to

be reassigned

strauss.utilities.nested_dict_idx_reassign(fromdict, todict, idx)[source]

Recurse through dictionaries and sub-dictionaries of iterables in fromdict and index value idx to assign or replact value in todict

Parameters:
  • fromdict (dict) – Dictionary containing values to assign

  • todict (dict) – Dictionary containing values to be reassigned

  • idx (dict) – Index value for retrieving value from iterables

strauss.utilities.nested_dict_reassign(fromdict, todict)[source]

Recurse through dictionaries and sub-dictionaries in fromdict and reassign equivalent values in todict

Args
fromdict (dict): Dictionary containing values

to assign

todict (dict): Dictionary containing values

to be reassigned

strauss.utilities.reassign_nested_item_from_keypath(dictionary, keypath, value)[source]

Reassign item in a nested dictionary to value using keypath syntax, to traverse multiple dictionaries

Parameters:
  • dictionary (dict) – dict object to reassign values within

  • keypath (str) – Using filepath syntax on given OS to traverse dictionary, i.e ‘a/b/c’ (‘abc’) corresponds to dict[‘a’][‘b’][‘c’] on Unix (Windows).

  • value – value to reassign dictionary value with

strauss.utilities.resample(rate_in, samprate, wavobj)[source]

Resample audio from original samplerate to required samplerate

Parameters:
  • rate_in (int)

  • samprate (int)

  • wavobj (tuple)

  • function (by scipy.io.wavfile)

Returns:

new_wavobj (tuple) as wavobj, with new sample rate and resampled sample values

strauss.utilities.rescale_values(x, oldlims, newlims)[source]

Rescale x values defined by limits oldlims to new limits newlims

Parameters:
  • x (of) – Array of input values

  • oldlims (tuple) – tuple representing the original limits

  • x

  • newlims (tuple) – tuple representing the new limits

Returns:

Rescaled array

Return type:

x_rs (array-like)

strauss.utilities.suppress_stdout_stderr()[source]

A context manager that redirects stdout and stderr to devnull

Stream

The stream submodule: representing the sound signal

Containing the Stream class to house the Sonificiation audio signal for each channel in the Channels object. This can be split into uniform segments or buffers via the Buffers object, for processing.

Todo

  • implement filter Q-parameter mapping

class strauss.stream.Buffers(stream, bufflength=0.1)[source]

Bases: object

Audio buffers split into uniform discrete chunks or ‘buffers’.

Audio ~:class:stream.Stream as a discrete sequence of individual ‘buffers’ of fixed duration (number of samples). This allows time varying operations in frequency space, such as signal filtering. Buffers are tiled in a ‘brickwork’ fashion so they always overlap with another buffer.

fade

Window function for recombining overlapping buffers

Type:

ndarray

nsamp_padstream

Number of samples needed to split the stream into discrete buffers of chosen length

Type:

int

nsamp_pad

Number of additional samples needed to add to the original Stream size in this case

Type:

int

buffs_tile

2d array of buffers completely enclosing the stream (number of buffers x samples per buffer)

Type:

ndarray

buffs_olap

allowing for cross fading

Type:

ndarray

to_stream()[source]

Reconstruct stream by cross-fading buffers

Takes the self.buffs_tile and self.buffs_olap arrays and using the self.fade window function, add overlapping sample values together to yield a 1d array of samples.

Returns:

1d array of sample values representing the

new audio signal for the parent Stream.

Return type:

out (ndarray)

class strauss.stream.Stream(length, samprate=44100, ltype='seconds')[source]

Bases: object

Stream object representing audio samples.

Houses audio samples and associates metadata representing the actual audio signal produced by the Generator class and output via the audio_channels class.

samprate

Samples per second of audio stream (Hz)

Type:

int

length

Duration of the stream in seconds

Type:

float

values

Values of individual samples

Type:

ndarray

samples

Indices of each sample

Type:

ndarray

samptype

Time in seconds each sample occurs

Type:

ndarray

buffers

Buffered stream if generated

Type:

Buffers

bufferize(bufflength=0.1)[source]

Wrapper to initialise Buffers subclass

Parameters:

bufflength (optional, float) – duration in seconds of each buffer to be generated

consolidate_buffers()[source]

Wrapper to reassign stream values to consolidated buffers

See to_stream()

filt_sweep(ffunc, fmap, qmap=<function Stream.<lambda>>, flo=20, fhi=22050.0, qlo=0.5, qhi=10)[source]

Apply time varying filter to buffered stream

Parameters:
  • ffunc (function) – function that applies filter

  • fmap (function) – mapping function representing filter cutoff sweep

  • qmap (optional, function) – mapping function for a filters Q parameter

  • flo (optional, float) – lowest frequency of sweep in Hz, default 20

  • fhi (optional, float) – lowest frequency of sweep in Hz, default 22.05 kHz

  • qlo (optional, float) – lowest ‘Q’ value of sweep, default 0.5

  • qhi (optional, float) – lowest frequency of sweep, default 10

get_sampfracs()[source]

Get fractional position of the sample in total stream duration

reset()[source]

Zero audio stream and buffers if present.

save_wav(filename)[source]

Save audio stream to wav file, specified by filename

Parameters:

filename (str) – name of output WAV file

Notes

The notes submodule: translating musical note representations

This submodule contains functions for translating between different representations of musical notes or musical chords, and representative sound frequencies and MIDI notes.

strauss.notes.tuneC0

The frequency in Hz of the C0 musical note

Type:

float

strauss.notes.notecount

Semitone offset above C in an octave

Type:

int

strauss.notes.notesharps

Names of musical notes using sharp notation

Type:

list

strauss.notes.noteflats

Names of musical notes using flat notation.

Type:

list

strauss.notes.semitone_dict

Dictionary of note names to semitone offsets above C.

Type:

dict

strauss.notes.chord_notes(chordname, rootoct=3)[source]

Takes name of a chord and root octave to generate a valid chord voicing as a list of note names, using the pychord library

Parameters:
  • chordname (str) – Standard chord name, e.g. ‘A7’ or ‘Dm7add9’ etc.

  • rootoct (int) – Octave number

Returns:

list of note names constituting chord

Return type:

out (list)

strauss.notes.mkey_to_note(val)[source]

Take MIDI key value and return the note name in scientific notation

Parameters:

val (int) – MIDI key value

Returns:

scientific pitch name, in format

<note><octave>, e.g. ‘E3’ or ‘F#2’

Return type:

out (str)

strauss.notes.parse_chord(chordname, rootoct=3)[source]

Takes name of a chord and root octave to generate a valid chord voicing as an array of frequencies in Hz, using the pychord library

Parameters:
  • chordname (str) – Standard chord name, e.g. ‘A7’ or ‘Dm7add9’ etc.

  • rootoct (int) – Octave number

Returns:

out (ndarray) array of frequencies constituting

chord

strauss.notes.parse_note(notename)[source]

Takes scientific pitch name and returns frequency in Hz. Flat and sharp values supported. Assumes equal temperament and A4 = 440 Hz tuning (ISO 16)

Parameters:

notename (str) – scientific pitch name, in format <note><octave>, e.g. ‘Ab4’, ‘E3’ or ‘F#2’

Returns:

Frequency of note in Hertz

Return type:

out (numerical)

Filters

The filters submodule: containing audio filter functions

These are audio filters that can be applied to the audio signal in frequency space to attenuate (filter out) frequencies. These can be applied to individual Buffers as an evolvable parameter.

Todo

  • Support More Filter Types

  • Implement resonance or ‘Q’ variation

strauss.filters.HPF1(data, cutoff, q, order=5)[source]

High-pass filter data array given cutoff, q and HPF order

Parameters:
  • data (array-like) – Array containing signal for filtering

  • cutoff (float) – Cutoff frequency

  • q (float) – Filter quality-factor or ‘Q’ value

  • order (int) – polynomial order of filter function

Return

y (array-like): Filtered array for output

strauss.filters.LPF1(data, cutoff, q, order=5)[source]

Low-pass filter data array given cutoff, q and LPF order

Parameters:
  • data (array-like) – Array containing signal for filtering

  • cutoff (float) – Cutoff frequency

  • q (float) – Filter quality-factor or ‘Q’ value

  • order (int) – polynomial order of filter function

Return

y (array-like): Filtered array for output

Text-to-Speech

The tts_caption submodule: tool for generating spoken captions

This uses text-to-speech via the the TTS module to allow captions represented as strings to be converted to spoken audio to precede the sonification.

exception strauss.tts_caption.NoTTSAPI[source]

Bases: Exception

exception strauss.tts_caption.TTSIsNotSupported[source]

Bases: Exception

strauss.tts_caption.getVoices(info=False)[source]

Get available voices for text-to-speech.

When info=True, this prints out information for each voice option.

Args:

info (bool): Print out voice information when True, by default False voices (list): List of pyttsx3.voice.Voice objects or dict objects.

strauss.tts_caption.render_caption(caption, samprate, model, caption_path)[source]

The render_caption function generates an audio caption from text input and writes it as a wav file. If the sample rate of the model is not equal to that passed from sonification.py, it resamples to the correct rate and re-writes the file.

If Coqui-AI is installed, text from user input is converted with text-to- speech software from Coqui-AI - https://pypi.org/project/TTS/ . You can view publicly available voice models with ‘TTS.list_models()’

If Coqui-AI is not installed but pyttsx3 (https://pypi.org/project/pyttsx3/) is installed, text from user input is converted offline using pyttsx3.

Note: STRAUSS checks if Coqui-AI is available. If it is, ttsMode is set to coqui-ai. If it is unavailable, STRAUSS checks whether pyttsx3 is available. If it is, ttsMode is set to pyttsx3.

Parameters:
  • caption (str) – script to be spoken by the TTS voice

  • samprate (int) – samples per second

  • model (str for Coqui-AI; dict for pyttsx3) – for Coqui-AI: valid name of TTS voice from the underlying TTS module; for pyttsx3: dictionary with keys of ‘rate’ (percent of speed, signed int16), ‘volume’ (float from 0 to 1), and/or ‘voice’ (the voice ‘id’ that can be chosen from the list given by the TTS.list_models() function).

  • caption_path (str) – filepath for spoken caption output