The Representation of Sound

"Sound" describes how you can take functions and lists of data and produce sounds from them. This tutorial discusses how sounds are represented in the Wolfram System.

The Wolfram System treats sounds much like graphics. In fact, the Wolfram System allows you to combine graphics with sound to create pictures with "sound tracks".

In analogy with graphics, sounds in the Wolfram System are represented by symbolic sound objects. The sound objects have head (RefLink[Sound, paclet:ref/Sound]), and contain a list of sound primitives, which represent sounds to be played in sequence.

The structure of a sound object.

The functions (RefLink[Play, paclet:ref/Play]) and (RefLink[ListPlay, paclet:ref/ListPlay]) discussed in "Sound" return (RefLink[Sound, paclet:ref/Sound]) objects.

(RefLink[Play, paclet:ref/Play]) returns a (RefLink[Sound, paclet:ref/Sound]) object. On appropriate computer systems, it also produces sound:

play=Play[(2+Cos[20 t]) * Sin[3000 t + 2 Sin[50 t] ],{t,0,2}]

Sound Primitives

Wolfram System sound primitives.

At the lowest level, all sounds in the Wolfram System are represented as a sequence of amplitude samples, or as a sequence of MIDI events. In (RefLink[SampledSoundList, paclet:ref/SampledSoundList]), these amplitude samples are given explicitly in a list. In (RefLink[SampledSoundFunction, paclet:ref/SampledSoundFunction]), however, they are generated when the sound is output, by applying the specified function to a sequence of integer arguments. In both cases, all amplitude values obtained must be between -1 and 1. In (RefLink[SoundNote, paclet:ref/SoundNote]), a note-like sound is represented as a sequence of MIDI events that represent the frequency, duration, amplitude, and styling of the note.

Create a (RefLink[SampledSoundList, paclet:ref/SampledSoundList]) from a numeric list, with a sample rate of 8000:

sampledSoundList=SampledSoundList[RandomReal[{-1,1},10^4],8000]

Sound[sampledSoundList]

Create a (RefLink[SampledSoundFunction, paclet:ref/SampledSoundFunction]) from a function, with a sample rate of 8000:

sampledSoundFunction=SampledSoundFunction[Sin[0.25#]&,8000,8000]

Sound[sampledSoundFunction]

Create a (RefLink[SoundNote, paclet:ref/SoundNote]):

soundNote=SoundNote[5,2,"Piano"]

Sound[soundNote]

(RefLink[ListPlay, paclet:ref/ListPlay]) generates (RefLink[SampledSoundList, paclet:ref/SampledSoundList]) primitives, while (RefLink[Play, paclet:ref/Play]) generates (RefLink[SampledSoundFunction, paclet:ref/SampledSoundFunction]) primitives. With the default option setting (RefLink[Compiled, paclet:ref/Compiled])->(RefLink[True, paclet:ref/True]), (RefLink[Play, paclet:ref/Play]) will produce a (RefLink[SampledSoundFunction, paclet:ref/SampledSoundFunction]) object containing a (RefLink[CompiledFunction, paclet:ref/CompiledFunction]).

Once you have generated a (RefLink[Sound, paclet:ref/Sound]) object containing various sound primitives, you must then output it as a sound. Much as with graphics, the basic scheme is to take the Wolfram System representation of the sound and convert it to a lower-level form that can be handled by an external program, such as a Wolfram System front end.

Play multiple primitives successively:

Sound[{sampledSoundList,sampledSoundFunction,soundNote}]

Play multiple primitives overlapped:

Sound[{Sound[sampledSoundList,{0,1}],Sound[sampledSoundFunction,{0,1}]}]

The low-level representation of sampled sound used by the Wolfram System consists of a sequence of hexadecimal numbers specifying amplitude levels. Within the Wolfram System, amplitude levels are given as approximate real numbers between -1 and 1. In producing the low-level form, the amplitude levels are "quantized". You can use the option (RefLink[SampleDepth, paclet:ref/SampleDepth]) to specify how many bits should be used for each sample. The default is (RefLink[SampleDepth, paclet:ref/SampleDepth])->8, which yields 256 possible amplitude levels, sufficient for most purposes. The low-level representation of note-based sound is as a time-quantized byte stream of MIDI events that specify various parameters about the note objects. The quantization of time is determined automatically at playback.

You can use the option (RefLink[SampleDepth, paclet:ref/SampleDepth]) in (RefLink[Play, paclet:ref/Play]) and (RefLink[ListPlay, paclet:ref/ListPlay]). In sound primitives, you can specify the sample depth by replacing the sample rate argument by the list {rate,depth}.

Import/Export

Importing and exporting functions.

It is possible to import audio data from a file on the local file system or from any accessible remote location.

This imports a sound from the Wolfram Language documentation directory:

snd=Import["ExampleData/Rule30.wav","Sound"]

Use (RefLink[Export, paclet:ref/Export]) to write a sound to disk.

Write the imported (RefLink[Sound, paclet:ref/Sound]) to disk:

Export["soundbite.wav",snd]