Basic Sound Operations with Mathematica

Playing a Function

The Play command plays any mathematical function.

Here is its description from The Mathematica Book, by Steven Wolfram:

	Play takes (the function you give it) to define the waveform for a 	sound: the values of the function give the amplitude of the sound as a 	function of time.

Just as Plot takes a function and realizes it on the screen, so Play takes a function and realizes it in sound.

	Play[f, {t, 0, tmax}]		Play a sound with amplitude f as a 						function of time t in seconds.

The function is evaluated SampleRate times for every second of sound produced.

The function is evaluated at a rate set by SampleRate (see Setting the SampleRate below).  The result of the evaluation is the amplitude of the given waveform at time t.  The range of allowable amplitudes is set by SampleDepth (see Setting the SampleDepth).

The time value you give Play is always measured in seconds.

Here is a 440-Hertz sine tone played for 1 second:

Play[Sin[2 Pi 440 t],{t,0,1}]

Here is  an example of frequency modulation, played for one-half second:

Play[Sin[2 Pi 440 t + 10 * Sin[2 Pi 100 t]],{t,0,0.5}]

Playing Lists of Integers

ListPlay accepts a sequece of integers which are interpreted as samples; on playback they will be played back at the SampleRate.

 ListPlay accepts a sequence of numbers which are interpreted as amplitudes, and then sampled at a given rate (see Setting the SampleRate). 
  
Since ListPlay can be sent any string of integers, it provides a means for the acoustic evaluation of data.

Here is an example by Matt Cook that plays the difference between successive primes:

ListPlay[Table[Prime[n+1]-Prime[n],{n,1,44100}],
		SampleRate->44100]

Playing Sequences of Sounds

CombinedSoundShow, written by Theodore Gray, plays a sequence of sounds in succession with no break between them.

Attributes[CombinedSoundShow] = {HoldFirst};

CombinedSoundShow[list_] := Block[
    {llist},
    Block[
        {$DisplayFunction = Identity,
         $SoundDisplayFunction = Identity},
          llist = list;
      ];
    Show[Sound[Map[First, llist]]]
]

Using CombinedSoundShow is simple.  Here is an example of  a 440-Hz sine tone played for a quarter of a second, followed by the same tone modulated by a 550-Hz sine tone for half a second, followed by a 550-Hz tone played for a quarter of a second:

CombinedSoundShow[{
	Play[Sin[2 Pi 440 t], 
		{t,0,0.25}],
	Play[Sin[2 Pi 440 t + 10 * Sin[2 Pi 550 t]], 
		{t,0,0.5}],
	Play[Sin[2 Pi 550 t], 
		{t,0,0.25}]
	}]

Note:  You cannot combine two-channel and one-channel sounds in the same CombinedSoundShow.  You will not get the results you expect.  To work properly, the function must be sent either all two-channel statements, or all one-channel statements.

Here is an example of using CombinedSoundShow with stereo Play statements.
A 440-Hz sine tone played in the left channel, followed by a 622-Hz sine tone in the right channel, followed by a 880-Hz sine tone played in both channels:

CombinedSoundShow[{
	Play[{Sin[2 Pi 440 t],0},
		{t,0,0.25}],
	Play[{0,Sin[2 Pi 622 t]}, 
		{t,0,0.25}],
	Play[{Sin[2 Pi 880 t],Sin[2 Pi 880 t]}, 
		{t,0,0.25}]
	}]

Note: To get sound in only the right or only the left channel, the corresponding other channel is given the value 0.

Stereo Output

With the proper hardware,  Mathematica is capable of multi-channel sound output on the NeXT and on some Macintosh computers.
 
Here is an example of   A-440 played through channel one, and Eb-622.25 (a tri-tone higher) played through the channel two:

Play[{Sin[2 Pi 440 t], Sin[2 Pi 622.25 t]}, 
	{t,0,0.5}]

Here the two pitches are reversed, A-440 is played through channel two, and  Eb-622.25 through channel one:

Play[{Sin[2 Pi 622.25 t], Sin[2 Pi 440 t]}, 
	{t,0,0.5}]

Note: ``Right'' and ``left'' settings are dependent upon the connections between your computer and your speakers.

(try stereo on a Sun4 again)

Note: If you attempt stereo output on a machine not designed for it, your results will depend on the PostScript interpreter on your machine.  For example, on a Sun-4, the two waveforms sent to Play are added together, which may or may not result in an overload on output.

Changing the SampleRate

The SampleRate is the rate at which the amplitude of a function is calculated. It can be set in two ways:

	Globally:	SetOptions[Play, SampleRate-> rate]
	Individually:	Play[Sin[2 Pi 440 t], {t,0,1}, SampleRate-> rate]

According to the sampling theory of Shannon and Nyquist, S samples per second are needed to accurately represent a waveform with a frequency of S/2 Hz.  In other words, the sampling rate must sample at a frequency of twice the highest audio frequency desired to achieve a lossless sampling.

In general, people register frequencies between 20 Hz. and 20,000 Hz as sounds, with some variation depending upon the age and sex of the listener.  Thus, a sampling rate of 40,000 samples per second (2 * 20,000) is theoretically sufficient for accurate digital encoding of the audible sound spectrum.

With Mathematica, you can set the SampleRate to any positive number.  However, you should know that the sound that will be created depends upon the digital-to-analog sampling rate of your hardware.  If you choose a sampling rate that is not congruent with the allowable sampling rates of your hardware, you may well get distortions upon output.

For example, here is A-440, sampled at 22050 samples per second:

Play[Sin[2 Pi 440 t], {t,0,0.5}, SampleRate->22050]

Here is the same pitch, sampled at a rate of 1200 samples per second.  Note the addition of high frequency components (noise) to the sound:

Play[Sin[2 Pi 440 t], {t,0,0.5}, SampleRate->1200]

In general, the higher your sampling rate, the more accurate will be the realization of the sound.  

Note: Be forwarned, increasing the SampleRate increase the number of calculations necessary to create the sound, hence the amount of time necessary to create the sound.

Changing the SampleDepth (Quantization)

Just as sampling is the rate at which a measurement is taken, so quantization is the amount of  the measurement taken.

quantization is the resolution at which measurement is taken.

The SampleDepth sets the level of quantization, which is the range of amplitudes that can be generated.  

Setting SampleDepth->8 gives you a total variety of 2^8 = 256 different amplitude values.

Here is a 440-Hz sine tone, with a quantization of 4 bits.  Note the change in the quality of sound:

Play[Sin[2 Pi 440 t], {t,0,0.25}, SampleDepth->4]

The maximum quantization on the  NeXT computers is 16 bits (2^16 = 65536). On the Apple and Sun-4 machines, the maximum quantizaton is 8 bits (2^8=256).  Exceeding the maximum quantization allowed by your machine will  probably result in silence (see Standard Defaults).

Sun4 uses MuLaw quantization (12-bits are stored in 8-bits)

Setting the PlayRange

PlayRange controls the scaling of amplitudes created by the function evaluated by Play.

When PlayRange->Automatic, (which is the default), an internal procedure is used to scale the amplitudes to fit in the allowable range.

When PlayRange->All, the amplitudes are scaled so that all of them fit in the allowable range.

When PlayRange->{min,max}, only amplitudes between min and max will be used, all others will be clipped.

Apparent Loudness

Mathematics teaches that the formula for a sine wave is:

	e = A * Sin[ 2 Pi f t]
where
	e = amplitude at time t
	A = maximum amplitude
	f = frequency in Herz (cycles per second)
	t = time
	
Thus, one would expect that 

	e = 1/2 * A * Sin[ 2 Pi f t]
	
is half as loud as the first formula, and that

	e = 2 * A * Sin[ 2 Pi f t]
	
is twice as loud as the first formula.  But, if you try this out in Mathematica, the volumes you expect will not be heard.  

For example, below are two sine waves, the first multiplied by 1, the second by 0.25.  As you can hear by clicking on the speaker on the right, the two appear to be of equal amplitude, despite the multiplication.

Play[1 * Sin[2 Pi 440 t],{t, 0,0.25}]

Play[ 0.25 * Sin[2 Pi 440 t],{t,0,0.25}]

The equal volume is the result of the automatic scaling done by Mathematica when given a Play command and an unspecified PlayRange: all sounds are scaled to their maximum allowable values, so all sounds have approximately the same loudness. 

To preserve intended volume relationships between sounds, give them an identical PlayRange. 

This can be done on a global level with the command

SetOptions[Play, PlayRange->{x,y}]

where x and y are values great enough to include the maximum and minimum values you expect the amplitudes to have.  

Note: These values should not be set indiscriminately.  For example, if you give x and y very large values, all your sounds will be soft, and if you give x and y very small values, your waveforms will likely be clipped.

Below are three examples of sounds, where the intended volumes are realized by setting the  PlayRange to {-2, 2}.  The first sound is multiplied by 1, and the second by 0.25, and the last by 2.

Play[1 * Sin[2 Pi 440 t], {t,0,0.25}, 
	PlayRange->{-2, 2}]

Play[0.25 * Sin[2 Pi 440 t], {t,0,0.25}, 
	PlayRange->{-2, 2}]

Play[2 * Sin[2 Pi 440 t], {t,0,0.25}, 
	PlayRange->{-2, 2}]

The PlayRange of {-2, 2} was chosen, since 2 was the largest value by which the sound was multiplied.

Clipping (Distortion)

If the value you give to A is greater than that allowd by the setting of  PlayRange, you will get a sound distorted by clipping.

In the example below, what is expected is a sine wave, but due to the clipping that occurs as a result of the value of A exceeding the values allowed by PlayRange, what you hear is something approaching a square wave.

Play[2 * Sin[2 Pi 440 t],{t,0,0.25},PlayRange->{-1,1}]

Clipping can damage speakers by sending a DC current where an AC current is expected.

Efficient Computation with Mathematica

Nesting

For efficiency, Play compiles the function you give it, but only that part of the function that explicitly appears inside the Play statement itself.  For example, 

	 Play[Sin[2 Pi 440  t],{t,0,1}] 
	
will compute almost twice as fast as 

	f := Sin[2 Pi 440 t] 
	Play[f,{t,0,1}]
	
 For longer computations, the difference is even more striking.

Using the Evaluate Command

Another way of reducing the computation time is by using the Evaluate command:

sinewave[frequency_, duration_] := 
	Play[Evaluate[Sin[2 Pi frequency t]],
		{t,0,duration}]

The syntax above ensures that the formula will be evaluated only once, and not each time that a sample is calculated.

The newly defined function is used like this:

sinewave[440, 1]

Output Distortion

In general, the quality of the internal speakers on computers is not high, and they may easily be overdriven by the strength of the signal created by Mathematica.  This will result in a distortion of the sound, a distortion caused by exceeding the limits of the speaker, and not due to the equations being played.

The best way to avoid distortion on output is to use a high-quality, external, amplification system.  If that is not an option, you can mechanically turn down the volume of the internal speaker on your system.  This will lessen the chance of exceeding the internal speaker's limits, and give you a more accurate realization of the sound.

Standard Defaults

NeXT Computers

NeXT computers use the Motorola 56001 DSP chip for creating sounds.  The chip is optimized for the following sampling rates:

	8012.8210513
	22050.0
	44100.0

The following quantization depths are supported:

	8-bit
	16-bit
	24-bit
	32-bit

Mathematica on the NeXT allows up to 16-bit quantization.

A maximum of two-channels of sound is supported.

Apple Sound Chip

Computers that have the Apple Sound Chip include:

	machine		channels
	Mac II si		stereo
	Mac II fx		stereo
	Mac II ci		stereo
	Mac Classic		mono
	Original Classic	mono
	Mac II cx		mono
	SE 30			stereo
	
The following sampling rates are the optimal ones for use with this chip.  

	5563.6363
	7418.1818
	11127.2727
	22254.5454
	
The Apple Sound Chip has a quantization depth of 8 bits.

Sun 4 and SparcStations

Sun uses the AM79C30A Digital Subscriber Controller chip.  Data is sampled at 8000 samples per second, with 12-bit precision, although the data is then compressed using mu-law encoding to 8-bits of precision.

Only mono sound is available.