The Cracked Bassoon

Sam Mathias

I'm a psychoacoustician. I mainly post code for making interesting sounds.

13. November 2014 1190 words ~7 minutes read Comment

Ripple sounds

portrait-of-ambroise-vollard

Ripples are synthetic sounds that have sinusoidal spectral or spectro-temporal profiles. They are commonly used to measure the response properties of neurons in the auditory system, and are frequently compared with visual gratings (see Shamma, 2001). They have also been used to study auditory short-term memory (e.g., Visscher et al., 2007). To create a ripple, we first need to create a mixture of many sinusoids whose frequencies are spaced evenly along a logarithmic frequency axis. Each sinusoid should also have a random starting phase, and their amplitudes should be modified so that the resulting sound has approximately equal power-spectrum density per octave. We're also going to randomise the amplitude of each sinusoid. The resulting sound can be expressed in terms of the time-varying function, y\left(t\right), defined by the following set of equations:

\begin{eqnarray} &y\left(t\right) &=& \sum_{i=1}^{N}{s_i\left(t\right)}, \\ \textrm{where}& \nonumber \\ &s_i\left(t\right) &=& \gamma_i\cdot\frac{1}{\sqrt{f_i}}\cdot{}\sin{\left(2\pi\cdot{}f_i\cdot{}t+\phi_i\right)}, \\ &f_i &=& f_1\cdot{}\left(\frac{f_N}{f_1}\right)^\frac{i-1}{N-1}, \\ &\gamma_i&\sim&\mathcal{U}\left(0,1\right), \nonumber \\ &\phi{}_i&\sim&\mathcal{U}\left(0,2\pi{}\right), \nonumber \\ &f_1 &=& 250, \nonumber \\ &f_N &=& 8000, \nonumber \\ \textrm{and}& \nonumber \\ &N &=& 1000. \nonumber \end{eqnarray}

Equation 1 sums together N sinusoids. Equation 2 generates each sinusoid, and scales and randomises their amplitudes. Equation 3 determines the frequency of the sinusoids in Hz, and ensures that they are evenly spaced on a musical (log2) scale between 250 Hz and 8 KHz. The random variable \gamma_i is the amplitude randomisation applied to the ith tone; it is not strictly necessary, so could be set to 1. The second random variable \phi_i represents the phase of the ith tone in radians. The python snippet below implements this process:

Click to hear it:

Notice that all we have done so far is create pink noise, albeit via a rather circuitous method. The spectrogram of the stimulus looks like this:
ripple_1_specgram

Notice the lack of any interesting spectral or spectro-temporal features. To add a sinusoidal spectral ripple to the sound, we replace Equation 1 with:

\begin{eqnarray} &y\left(t\right) &=& \sum_{i=1}^{N}{a_i\cdot{}s_i\left(t\right)}, \\ \textrm{where}& \nonumber \\ &a_i &=& 1 + d\cdot\sin\left(2\pi\cdot\Omega\cdot{}x_i + \varphi\right), \\ \textrm{and}& \nonumber \\ &x_i &=& \log_2\left(\frac{f_i}{f_0}\right). \nonumber \end{eqnarray}

Equation 4 multiplies each sinusoid by an amplitude-modulation function (Equation 5) before summing them. There are now three free parameters: d represents the ripple depth — this is set to 1 or 0.9 in most studies; \Omega represents the ripple density in cycles per octave; and \varphi represents the starting phase of the ripple in radians. The output of the function can be visualised easily:
ripple_1_specgram

Here is how to create a spectral ripple in python:


We can see the spectral ripple in the new sound's spectrogram (though due to the linear vertical axis, it is not as clear as in the previous figure):
ripple_1_specgram

Now we have succeeded in creating a stationary ripple. However, single-unit recording studies have shown that neurons respond selectively to sounds with specific ripple densities and phases (Shamma, 2001). Studies of auditory physiology therefore have often used moving ripple sounds, where the instantaneous phase of the ripple changes over time. We can achieve this by replacing the amplitude-modulation function with a time-varying function:

\begin{eqnarray} &y\left(t\right) &=& \sum_{i=1}^{N}{a_i\left(t\right)\cdot{}s_i\left(t\right)}, \\ \textrm{where}& \nonumber \\ &a_i\left(t\right) &=& 1 + d\cdot\sin\left[2\pi\cdot\left(w\cdot{}t+\Omega{}\cdot{}x_i\right) + \varphi\right].\end{eqnarray}

Equations 6 and 7 replace Equations 4 and 5, respectively. This modification adds a 'drift' to the amplitude-modulation function corresponding to w in Hz:
ripple_1_specgram

It also adds a striking new perceptual feature to the sound:


ripple_1_specgram

Finally, we can go one step further and create dynamic moving ripples (Escabí & Schreiner, 2002). To implement these, we need to slightly modify Equation 7:

\begin{eqnarray} &a_i\left(t\right) &=& 1 + d\cdot\sin\left \{2\pi\cdot\left[w^\prime\left(t\right)+\Omega{}\left(t\right)\cdot{}x_i\right] + \varphi\right \}, \\ \textrm{where}& \nonumber \\ &w^\prime\left(t\right) &=& \int_0^\tau w(\tau)\,d\tau. \nonumber \end{eqnarray}

Now \Omega and w are arbitrary vectors of length t, describing the instantaneous ripple density and ripple velocity of the sound, respectively.

The code below puts everything together. Note that any of the sounds you heard earlier can be created by passing the appropriate arguments to the ripple_sound() function in this script. A featureless, noise-like sound like the first example is created by setting both \Omega and w to zero; a stationary ripple like the second example has a non-zero \Omega; and so on.

Here is an example of a dynamic moving sound where \Omega and w go on independent random walks:
ripple_4_env
ripple_4_specgram


References

Banner image is Portrait of Ambroise Vollard by Pablo Picasso.

Leave a Reply

Your email address will not be published. Required fields are marked *