**Miscellaneous****`****Audio****`**

This package provides functions for the generation of standard waveforms and waveforms with user-specified spectra, the synthesis of amplitude and frequency modulated sinusoids, and a function for reading sound files into Mathematica.

The graphic output of Mathematica's sound functions is hardware dependent, so the graphics included in this documentation may differ from those produced by your machine.

**Generating Standard Waveforms**

Creating a standard waveform.

Waveform uses computationally efficient algorithms to create a standard waveform with a theoretically infinite number of overtones.

Standard waveform definitions.

This loads the package.
In[1]:= **<< Miscellaneous`Audio`**

Here Waveform returns a Sound object corresponding to a triangle wave having a fundamental of 440 hertz and lasting 0.2 seconds.
In[2]:= **tri440 = Waveform[Triangle, 440, 0.2]**

Out[2]= -Sound-

The Show function allows you to hear the Sound object returned by Waveform.
In[3]:= **Show[tri440]**

Out[3]= -Sound-

Creating a standard waveform with a specified number of overtones.

The number of overtones that Waveform includes in a sound can be limited by setting the option Overtones.

You can generate a square wave that has only eight overtones, then hear the sound with the Show function.
In[4]:= **Waveform[Square, 880, 0.2,**

Overtones->8] // Show

Out[4]= -Sound-

Here Table is used to create a sequence of sawtooth waveform sounds running from ten overtones down to only two.
In[5]:= **Table[Waveform[Sawtooth, 880, 0.1,**

Overtones->n], {n, 10, 2, -1}] // Show

Out[5]= -Sound-

When you use the option Overtones, the Waveform function uses Fourier summation to create the sound. This process is not as computationally efficient as the default algorithm, but generates a "cleaner" sound with only the specified number of overtones. Mathematica's SetOptions function may be used to make Fourier summation the default.

This ensures that Waveform will use Fourier summation for the creation of sounds.
In[6]:= **SetOptions[Waveform, Overtones->Infinity]**

Out[6]=

This ensures the use of faster algorithms in creating sounds.
In[7]:= **SetOptions[Waveform, Overtones->Automatic]**

Out[7]=

**Specifying the Spectrum for a Waveform**

Creating a waveform with a specified spectrum.

ListWaveform allows you to create a waveform with a specific spectrum. The first argument is a list of pairs, in which the first member of each pair is a frequency relative to the fundamental and the second is the frequency's relative amplitude.

For example, you can define a partial list corresponding to an "instrument" in which the partials' frequencies are nonharmonically related and have complicated amplitude relationships. ListWaveform may then be used to generate these relationships at different fundamental frequencies.

This partial list will define the "instrument".
In[8]:= **partialList =**

{{1,1},{1.1,0.1},{1.2,0.9},{1.3,0.2},

{1.4,0.8},{1.5,0.3},{1.6,0.7},

{1.7,0.4},{1.8,0.6},{1.9,0.5}};

This generates an ascending sequence of six chromatic half-steps, beginning at 440 hertz, all using the same partial list, and each lasting for 0.2 seconds.
In[9]:= **sequence = Table[ListWaveform[partialList,**

440 2^(x/12), 0.2], {x,0,5}]

Out[9]= {-Sound-, -Sound-, -Sound-, -Sound-,

-Sound-, -Sound-}

Now you can hear one partial list at different fundamental frequencies.
In[10]:= **Show[sequence]**

Out[10]= -Sound-

You can create chords with ListWaveform by defining partial lists with amplitude relationships of unity, so that all component frequencies share the same amplitude.

This sequence of relative frequencies defines a major chord. Note that the amplitudes are set at unity, so that the component frequencies are of equal amplitude.
In[11]:= **majorChord = {{1, 1}, {1.26, 1}, {1.5, 1}};**

This creates a major chord based on a fundamental of 493.88 hertz (i.e., the pitch "B4").
In[12]:= **ListWaveform[majorChord, 493.88, 0.2] // Show**

Out[12]= -Sound-

**Amplitude Modulation**

Amplitude modulation is a common analog studio technique in which the created sound contains three frequencies: the carrier frequency, and the sum and difference of the carrier and modulating frequencies.

Amplitude modulation.

The expression used by AmplitudeModulation is given by

When the modulating frequency is subaudio (below 20 hertz), the result of amplitude modulation is what musicians call "tremolo".
In[13]:= **AmplitudeModulation[440, 6, 1, 0.5] //Show**

Out[13]= -Sound-

The "depth" or "intensity" of the modulation is controlled by the modulation index . The carrier is said to be overmodulated when . The best way to understand the effect of

is to try it out with different values, usually between 0.1 and 2.0.

Ring modulation.

If you set the option RingModulation->True, the Sound object created by AmplitudeModulation will contain only two frequencies: the sum and the difference of the carrier and modulating frequencies. This is called ring modulation, and is given by the expression

In this example, the output sound contains the frequencies 700 and 300 hertz, the sum and difference of the carrier and modulating frequencies.
In[14]:= **AmplitudeModulation[200, 500, 1, 0.5,**

RingModulation->True] //Show

Out[14]= -Sound-

**Frequency Modulation**

Frequency modulation (FM) is a technique used at major universities on workstations and in suburban homes on synthesizers. The ubiquitousness of this technique stems in part from its mathematical simplicity and its ease of implementation in an electronic circuit. The expression for frequency modulation is given by

Frequency modulation.

When the modulating frequency is subaudio (below 20 hertz), the result is what musicians call "vibrato".
In[15]:= **FrequencyModulation[660, {7,70}, 0.5] //Show**

Out[15]= -Sound-

The modulation index is the ratio of the peak deviation to the modulating frequency. Higher values of the modulation index result in more partials and a "brighter" sound. Very high values will result in aliasing, and will add low-frequency components to the sound.

This is an example of frequency modulation with a modulation index of 5500/550.
In[16]:= **FrequencyModulation[**

440, {550, 5500}, 0.5] //Show

Out[16]= -Sound-

The modulation ratio is the ratio of the modulating frequency to the carrier frequency. If this ratio is an integer greater than zero, the resulting overtones and sidebands will have harmonic relationships to each other, analogous to those of standard orchestral instruments. If the modulation ratio is not integer valued, the resulting overtones and sidebands will have an inharmonic relationship to each other, analogous to percussion instruments and bells. One speaks of a harmonic relationship when the overtones and sidebands have frequencies that coincide with the harmonics of some fundamental, not necessarily the carrier.

Cascade frequency modulation.

Cascade frequency modulation is a type of frequency modulation where the modulating frequency is itself modulated, thus "cascading" the modulation. The expression for cascade frequency modulation with two modulating frequencies is given by

This nesting process can be carried out for a list of modulating frequencies of any size.

In this example of cascade frequency modulation, each modulating frequency is given a distinct peak deviation.
In[17]:= **FrequencyModulation[880, {{340, 100},**

{550, 50}, {730, 25}}, 0.5,

ModulationType->Cascade] // Show

Out[17]= -Sound-

Parallel frequency modulation.

In contrast to cascade frequency modulation, parallel frequency modulation is a technique where the carrier frequency is modulated by two or more modulating frequencies that do not modulate each other. The expression for parallel frequency modulation with two modulating frequencies is given by

This uses the same values as the example for cascade FM, but generates an instance of parallel FM instead. Note the stronger presence of the higher partials in the resulting sound.
In[18]:= **FrequencyModulation[880,**

{{340, 100}, {550, 50}, {730, 25}}, 0.5,

ModulationType->Parallel] // Show

Out[18]= -Sound-

**Reading Sound Files from Disk**

There are numerous sound file formats used for the storage of sampled sounds. In general, they consist of a header containing information that describes the sound, followed by the sampled sound data. The ReadSoundfile function is capable of reading NeXT/Sun, WAVE, and AIFF sound file formats. ReadSoundfile can read the AIFF format used by SGI, Amiga, and some Apple sound files. It will not work with Apple's SoundDesigner II sound files, due to the fact that data (the sound samples) are kept in the data fork, but format information is kept in the resource fork.

Reading a sound file into *Mathematica*.

ReadSoundfile lets you read a sampled sound file directly into Mathematica. The samples are translated into signed 16-bit integers. If the sound is stereo, ReadSoundfile returns a list of lists for the right and left channels. The returned list can be played with ListPlay or plotted with ListPlot.

This reads the Multimedia sound file chimes.wav, and returns a list of the samples in the file.
In[19]:= **chimes = ReadSoundfile["chimes.wav",**

PrintHeader->True];

Format: Multimedia WAVE

Duration: 0.72 seconds

Channels: 1

Sampling rate: 22050

Bits per sample: 8

Data size: 15876 bytes

Number of samples: 15876

The list chimes may be played with ListPlay, at the SampleRate displayed by setting PrintHeader->True. Note that the PlayRange is adjusted to account for the 16-bit signed samples.
In[20]:= **ListPlay[chimes, SampleRate->22050,**

PlayRange->{-2^15,2^15}]

Out[20]= -Sound-

Plot the sound with ListPlot. Remember to set PlotRange to a range that will accommodate the 16-bit signed amplitudes.
In[21]:= **ListPlot[chimes, PlotRange->{-2^15,2^15}]**

ReadSoundfile is capable of reading in sounds that have been mu-law encoded. Mu-law encoding is a logarithmic encoding scheme in which 12 bits of data are stored in 8 bits, resulting in "telephone-quality" sound. Voice-mail frequently uses some form of mu-law encoding.

Read in the mu-law encoded Sun sound file bubbles.au.
In[22]:= **bubbles = ReadSoundfile["bubbles.au",**

PrintHeader->True];

Format: NeXT/Sun

Duration: 3.90137 seconds

Channels: 1

Sampling rate: 8000

Bits per sample: 8

Data size: 31211 bytes

Number of samples: 31211

Encoding: 8-bit mulaw

Text: bubbling goop

Play the sound with ListPlay.
In[23]:= **ListPlay[bubbles, SampleRate->8000,**

PlayRange->{-2^15, 2^15}]

Out[23]= -Sound-

In the case of stereo files, the data are returned as a list of two lists: left-channel sample data and right-channel sample data.

This reads in a stereo file.
In[24]:= **voice = ReadSoundfile["voice.snd",**

PrintHeader->True] ;

Format: NeXT/Sun

Duration: 0.143492 seconds

Channels: 2

Sampling rate: 22050

Bits per sample: 16

Data size: 25312 bytes

Number of samples: 6328

Text: by Christopher Penrose

This plays the stereo sound.
In[25]:= **ListPlay[voice, SampleRate->22050,**

PlayRange->{-2^15, 2^15}]

Out[25]= -Sound-

When plotting a stereo sound, remember to add the two lists together; otherwise you will get a plot of the left channel followed by the right channel.

The left and right channels are added together before plotting.
In[26]:= **ListPlot[Plus @@ voice,**

PlotRange->{-2^15, 2^15}];

**Setting Options DisplayFunction, SampleRate, SampleDepth, and PlayRange**

All the sound-generating functions in the Miscellaneous`Audio` package use the MathematicaPlay function to do the low-level work of generating sounds. Some options of Play, such as SampleRate, SampleDepth, and PlayRange, can significantly change the quality and constitution of the resulting sound. The option DisplayFunction affects whether the created Sound object will be played immediately after it is returned.

Loading the package will set the options SampleRate, SampleDepth, and PlayRange to their optimum values for your machine. The package also sets DisplayFunction->Identity, which causes Sound objects to be returned without being played. You can reset these options by using Mathematica's SetOptions function, or by specifying them on the command line.

You can create a sound at a specified SampleRate.
In[27]:= **AmplitudeModulation[440, 100, 1, 0.5,**

SampleRate->22050]

Out[27]= -Sound-

By setting the option DisplayFunction->$SoundDisplayFunction, you can hear a sound immediately after it is created by Mathematica, without having to use the Show function each time. This is most useful when you are experimenting with combinations of arguments and wish to hear the effect they have on the resulting sound.

Now all Sound objects returned by FrequencyModulation will be played immediately after being returned.
In[28]:= **SetOptions[FrequencyModulation, DisplayFunction->$SoundDisplayFunction]**

Out[28]=

This assigns a frequency modulated sound to casfm2 and plays the sound.
In[29]:= **casfm2 = FrequencyModulation[660,{{770, 100},**

{660, 50}, {540, 25}}, 0.5, ModulationType->Cascade]

Out[29]= -Sound-

You can hear the same function with slightly different values of the modulating frequencies.
In[30]:= **FrequencyModulation[660,{{660, 100},**

{540, 50}, {660, 25}}, 0.5, ModulationType->Cascade]

Out[30]= -Sound-

Now FrequencyModulation will no longer play every Sound object it creates.
In[31]:= **SetOptions[FrequencyModulation, DisplayFunction->Identity]**

Out[31]=

You will be better able to use the sound-generating functions if you are aware of the effect of the various options to Play.

SampleRate is an option for sound primitives that specifies the number of samples per second to generate for sounds. According to Nyquist's sampling theorem, samples per second are required to accurately represent a waveform having a maximum frequency content of

hertz. In other words, your sampling rate must be at least twice the highest frequency you would like to hear. Sampling at a lower rate will result in aliasing, in which frequency components above half the sampling rate are rendered as lower frequency components. Since people register frequencies in the range of 20-20,000 hertz as audio signals, a sampling rate of 40,000 samples per second is the minimum required for the accurate encoding of the entire audio range.

Mathematica allows you to set the SampleRate

to any positive number. However, the sound that will be created depends upon the sampling rate of your digital-to-analog converter. If the converter's sampling rate is not a multiple of the chosen sampling rate, a software conversion to the converter's sampling rate will automatically take place, and there may be distortions in the resulting sound.

This is a frequency modulated sound at the default SampleRate.
In[32]:= **FrequencyModulation[660, {100,100},**

0.5] // Show

Out[32]= -Sound-

This plays the same sound with SampleRate->1234. The additional noise is due to the fact that the digital-to-analog converter's sampling rate is not a multiple of 1234 hertz.
In[33]:= **FrequencyModulation[660, {100,100}, 0.5,**

SampleRate->1234] // Show

Out[33]= -Sound-

SampleDepth (frequently called "quantization") is an option for sound primitives which specifies how many bits should be used to encode sound amplitude levels. Setting SampleDepth->8 gives you different amplitude values, and SampleDepth->16 gives you . You should choose a value for SampleDepth

that is the best for your hardware.

Here is the pitch "A5" using the default setting of SampleDepth.
In[34]:= **Waveform[Sawtooth, 880, 0.5] // Show**

Out[34]= -Sound-

On some computers, this SampleDepth produces no sound at all. You might get a sound which is simply "noisier".
In[35]:= **Waveform[Sawtooth, 880, 0.5,**

SampleDepth->3] // Show

Out[35]= -Sound-

PlayRange is an option for Play and related functions which specifies what range of sound amplitude levels should be included. The functions Waveform and FrequencyModulation set this value to All, and the AmplitudeModulation function sets it to {-1,1}. PlayRange in Play behaves like PlotRange in Plot.

Here is a simple plot of a sine waveform.
In[36]:= **Plot[Sin[x], {x, 0, 2Pi}]**

This gives the same plot with a restricted PlotRange.
In[37]:= **Plot[Sin[x], {x, 0, 2Pi},**

PlotRange->{-0.5, 0.5}]

Notice that in the second plot, when the value of the function exceeds the limits specified by PlotRange, the value is cut off or "clipped". Similarly, if the amplitude of your sound exceeds the setting of PlayRange, what you hear will not be a complete representation of your function. This phenomenon is termed "waveshaping" by composers and "distortion" by engineers. PlayRange should be set sufficiently high so that all generated samples may be represented without distortion.

**Playing Sound Objects in Arbitrary Sequences**

Since all the sound-generating functions defined in Miscellaneous`Audio` return a Sound object, the returned values can be played in sequence with the Show function.

First create three sounds.
In[38]:= **{s1, s2, s3} =**

{Waveform[Sawtooth, 880, 0.2],

AmplitudeModulation[440, 530, 1, 0.5],

FrequencyModulation[660,

{{300,400},{600,200}},

0.3, ModulationType->Cascade]}

Out[38]= {-Sound-, -Sound-, -Sound-}

This plays the three Sound objects in reverse sequence.
In[39]:= **Show[s3, s2, s1]**

Out[39]= -Sound-