Class:            SampledSound

Environment:      Siren
Superclass:         Siren.Sound
Category:         Music-Sound
Instance variables:   name rate format channels samplesInMemory firstIndex
Indexed variables:   objects
Class variables:      MagicNumbers MaxIntSample MinIntSample
Imports:            private SoundConstants.*

Instances of SampledSound represent digitally-sampled sound objects. Their "samples" are stored in the "data" instance variable inherited from Function. They can be read/written to/from files (using SoundFile objects), displayed (in SoundViews) and played (via SoundPorts).

The class SampledSound is concrete and assumes 16-bit linear encoding of samples; there are subclasses for floating-point and 8-bit Mu-law sample types. There are useful class methods for creating a number of standard sounds such as silence, impulses, swept sine waves, etc. Note that SampledSound uses the 'range' instance variable inherited from Function as its (integer) size.

Instance variables:
   name the file name or object ID
   rate the sample rate
   format the sample format, e.g., #lin16Bit
   channels the # of channels
   samplesInMemory    The number of samples held in memory (may be smaller than
         size for very large sounds)
   firstIndex    The sample index of the start of the in-memory samples (may be non-zero
         for very large "paged" sounds)

Other properties, such as the sound's (optional) file name, its sample rate, or the number of channels, are stored in the property list dictionary that is inherited by virtue of being an event subclass.

KNOWN BUGS:

Note that not all of this class is finished--there are methods that call non-existent user primitives and have no Smalltalk implementations (like the heavy DSP).

accessing

allocateData
   

channels
   Answer the receiver's 'channels'.

channels: anObject
   Set the receiver's instance variable 'channels' to be anObject.

copy
   Answer a 'clean' copy of the receiver.

copyAllButSamples
   Answer a 'clean' copy of the receiver, but don't write in the samples yet.

copyFrom: start to: stop
   Answer a copy of the receiver for the given sample range.

cueNamed: cName
   Answer a sound derived from the receiver using the samples between the named cue points.

envelope
   Answer the receiver's envelope.

envelope: anEnv
   Set the receiver's envelope property.

file
   Answer the sound file for the receiver (if present).

firstIndex
   Answer the receiver's 'firstIndex'.

firstIndex: anObject
   Set the receiver's instance variable 'firstIndex' to be anObject.

floatsFrom: aStart to: aStop
   Answer a copy of the receiver's data within the given sample range.

format
   Answer the receiver's 'format'.

format: fSymbol
   Set the receiver's instance variable 'format' to be fSymbol.

frameRate
   Answer the receiver's 'rate'.

from: aStart to: aStop
   Answer a copy of the receiver within the given time range.

fromSample: start toSample: finish
   Answer a copy of the receiver within the given sample range.

hasFile
   Answer whether the receiver is stored on a file of the same name.

longFormat
   Answer the receiver's format as a descriptive string.

name
   Answer the receiver's 'name'.

name: anObject
   Set the receiver's instance variable 'name' to be anObject.

rate
   Answer the receiver's 'rate'.

rate: anObject
   Set the receiver's instance variable 'rate' to be anObject.

sampleRate
   Answer the receiver's 'rate'.

samples
   Answer the instance variable 'data'.

samples: theArray
   Accept the argument, 'theArray', (a Byte, Word, or Float array, or an UninterpretedBytes)
   as the new instance variable 'samples'.

samplesInMemory
   Answer the receiver's 'samplesInMemory'.

samplesInMemory: anObject
   Set the receiver's instance variable 'samplesInMemory' to be anObject.

sampleSize
   Answer the size in bytes of the receiver's samples (2).

size
   Return the receiver's size in sample frames.

size: aNumber
   Set the receiver's 'size' in samples.

sizeInBytes
   Answer the size in bytes of the receiver.

sizeInFrames
   Return the receiver's size in sample frames.

sample accessing

at: anIndex
   Answer the value at the given index (between 0 and 1).

at: anIndex put: aValue
   Stuff the given sample at the given index (after lots of checking and testing).

cutFrom: startSample to: stopSample
   Cut the designated section from the receiver; answer a new sound (!).

floatSampleAt: index
   Answer the sample at the given index as a normalized floating-point number.

floatSampleAt: index put: aValue
   Stuff the given floating-point sample at the given index after scaling.

intSampleAt: index
   Answer the sample at the given index as an integer.

intSampleAt: index put: aValue
   Stuff the given integer sample at the given index.

paste: aSound from: startSample to: stopSample at: index
   Paste the given sound into the receiver; answer a new sound (!).

sampleAt: index
   Answer the sample at the given index, mapping and paging as necessary.

sampleAt: anIndex put: aValue
   Stuff the given sample at the given index (after lots of checking and testing).

interpolating

autoCorrelationBetween: index1 and: index2 length: length
   Answer the cummulative error between the portions of my waveform starting at the given two indices and extending for the given length. The larger this error, the greater the difference between the two waveforms.

errorBetween: sampleArray1 and: sampleArray2
   Answer the cummulative error between the two sample arrays, which are assumed to be the same size.

fadeInOver: fTime
   Apply a fade-in ramp to the receiver with the given time.

fadeOutOver: fTime
   Apply a fade-in ramp to the receiver with the given time.

interpolatedWindowAt: anIndex width: nSamples
   Return an array of N samples starting at the given index in my data.

sampledFrom: aStart to: aStop into: anArray
   Place a down-sampled version of the receiver in the argument array.

sampledTo: anArray
   Place a down-sampled version of the receiver in the argument array.

sampleMaxFrom: aStart to: aStop into: anArray
   Place a version of the root-mean-square energy of the receiver in the argument array.

merging

extractChannel: cNumber into: aSound
   Extract the given channel from the receiver into the argument sound.

mergeChannel: cNumber from: aSound
   Merge the argument sound into the given channel of the receiver.

envelopes

average
   Answer the average sample value of the receiver (normally the DC offset).

computeEnvelope: type
   Compute a sample envelope for the receiver with 128 points per second.

computePeakEnvelope
   Compute a windowed peak sample envelope for the receiver with 1024 points per 4 seconds.

computeRMSEnvelope
   Compute a windowed root-mean-square sample envelope for the receiver.

edit
   Edit the receiver.

max
   Answer the maximum value of the samples.

offsetBy: aFactor
   Answer a copy of the receiver offset by the given factor.

offsetFrom: aStart to: aStop by: anOffset
   Answer a copy of the receiver offset by the given factor.

peakEnvelope
   Answer the receiver's peak-detected envelope, or compute a new one.

peaksFrom: aStart to: aStop into: anArray
   Place a version of the root-mean-square energy of the receiver in the argument array.

readEnvelope: type
   Try to read the sample envelope for the receiver from a file named XXX.env.

rmsEnvelope
   Answer the receiver's envelope, or compute a new one.

rmsFrom: aStart to: aStop into: anArray
   Place a version of the root-mean-square energy of the receiver in the argument array.

rmsTo: anArray
   Place a version of the root-mean-square energy of the receiver in the argument array.

scaleBy: aScaleFactor
   Scale the receiver's samples by the given factor.

scaledBy: aScaleFactor
   Answer a copy of the receiver scaled by the given factor.

scaledByEnvelopeArray: anArray
   Answer a copy of the receiver scaled by the given envelope array.

scaledByFunction: aFunction
   Answer a copy of the receiver scaled by the given breakpoint envelope expressed as points.

scaledFrom: aStart to: aStop by: aScaleFactor
   Answer a copy of the receiver scaled by the given factor.

scaledFrom: aStart to: aStop byEnvelopeArray: anArray
   Answer a copy of the receiver scaled by the given envelope array.

scaledFrom: aStart to: aStop byFunction: aFunction
   Answer a copy of the receiver scaled by the given breakpoint envelope expressed as points.

scaleFrom: aStart to: aStop by: aScaleFactor
   Scale the receiver's damples by the given factor.

writeEnvelope: type
   Write the sample envelope for the receiver to a file named XXX.env or XXX.pk.

enumerating

do: aBlock
   Evaluate aBlock with each of the receiver's elements as the argument.

printing

printOn: aStream
   pretty-print the receiver.

printSamples
   pretty-print a few samples.

printSamplesOn: aStream
   Pretty-print a few samples--32 by default, 1024 if shift-down, *all* of ctrl and shift down.

storeOnFileNamed: aName
   Save the receiver on the sound file named by the argument.

private

getData
   Read samples in from the file if none in memory.

mapSampleIndex: index
   Map the given sample index according to the 'page' (firstIndex) of the receiver.

privateSampleAt: anIndex
   Answer the sample at the given index as an integer.

privateSampleAt: anIndex in: cPtr bigEndian: isBE
   Answer the sample at the given index as an integer,
      assuming the output is a cPointer; handle endianness.

privateSampleAt: anIndex in: cPtr put: value bigEndian: isBE
   Answer the sample at the given index as an integer,
      assuming the output is a cPointer; handle endianness.

privateSampleAt: anIndex put: aValue
   Stuff the given sample at the given index (safely).

readSamplesFrom: index
   Read in samples from disk starting a bit before the given index.

realSound
   Answer the real sound for the receiver (overridden in virtual subclasses).

scaleSampleIndex: index
   Scale the given sample index according to the sample size of the receiver.

play/record

nextBufferInto: outBuffer frames: bufferSize channels: outChannels format: sformat startingAt: startFrame
   Copy data from the receiver into the given output buffer; answer the current sample index.

play
   Play the receiver out over the default sound port.

testing

hasGaps
   Answer whether the receiver has any gaps.

isComposite
   Answer whether the receiver is a composite sound.

isEmpty
   Answer whether the receiver is empty.

isVirtual
   Answer whether the receiver is a virtual sound.

initialize-release

initialize
   Set up a default sound.

MetaClass:         SampledSound class

instance creation

default
   Answer the default empty sound.

duration: aDur named: nameString rate: aRate channels: aChannels format: aFormat
   Answer a new 16-bit linear sound with the given properties.

duration: aDur rate: aRate channels: aChannels
   Answer a new sound with the given properties.

duration: aDur rate: aRate channels: aChannels format: aFormat
   Answer a new sound with the given properties.

fromData: anArray named: nameString rate: aRate channels: aChannels format: aFormat
   Answer a new sound from the given data.

fromData: anArray rate: aRate channels: aChannels format: aFormat
   Answer a new 16-bit linear sound from the given data.

fromDblData: anArray rate: aRate channels: aChannels size: siz
   Answer a new sound from the given data.

headerFromFile: nameString
   Open the given file (EBICSF, NeXT, or SPARC soundfile format)

named: aName size: aSize format: formatSymbol
   Answer a new Sound with the given name and storage size.

named: nameString size: size rate: rate channels: chans format: formatSymbol
   Answer a new Sound with the given storage size (in sample frames), etc.

named: nameString size: size rate: rate channels: chans format: formatSymbol data: data
   Answer a new Sound with the given storage size (in sample frames), etc.

size: size format: formatSymbol channels: chans
   Answer a new Sound with the given storage size, etc.

size: size rate: aRate channels: chans
   Answer a new Sound with the given storage size, etc.

size: size rate: rate channels: chans format: formatSymbol
   Answer a new Sound with the given storage size, etc.

size: size rate: rate format: formatSymbol channels: chans
   Answer a new Sound with the given storage size, etc.

examples

immediateInspect
   Answer a sampled sound from immediate data; inspect it.

rmsViewExample
   Read a sampled sound from the file, take the rms into 64 values, and edit that.

sweepExample
   Open a sound view on a swept sine wave.

sweepView
   Open a sound view on a swept sine wave.

standard wave forms

constantOfDur: dur value: value rate: rate chans: chans
   Answer a sound with a constant value.

expSweepDur: dur rate: rate from: start to: stop chans: chans
   Answer a SampledSound with a swept sine wave.

impulseOfDur: dur width: width rate: rate chans: chans
   Create a sound with an impulse of the given characteristics.

linearSweepDur: dur rate: rate from: start to: stop chans: chans
   Answer a StoredSound with a swept sine wave.

pulseTrainDur: dur rate: rate freq: freq width: width chans: chans
   Answer a StoredSound with a pulse train.

pulseTrainDur: dur rate: rate freq: freq width: width chans: chans zero: zero
   Answer a StoredSound with a pulse train.

rampDur: dur rate: rate chans: chans
   Answer a StoredSound with a single ramp of samples.

sawtooth
   Answer a StoredSound with raw sawtooth samples.

sawtoothDur: dur rate: rate freq: freq chans: chans
   Answer a StoredSound with raw sawtooth samples.

sineDur: dur rate: rate freq: freq chans: chans
   Answer a StoredSound with a pulse train.

squareDur: dur rate: rate freq: freq chans: chans
   Answer a StoredSound with a square wave.

sweepDur: dur rate: rate from: start to: stop chans: chans
   Answer a StoredSound with a swept sine wave.

class constants

formatSymbol
   Answer the symbolic code used for the format of the receiver's instances.

maxSample
   Answer the maximum value of the receiver class.

minSample
   Answer the minimum value of the receiver class.