Copyright ©1995 by NeXT Computer, Inc. All Rights Reserved.
Sound |
Inherits From: | Object | |
Declared In: | soundkit/Sound.h |
Class Description |
Sound objects represent and manage sounds. A Sound object's sound can be recorded from a microphone, read from a soundfile or NXBundle resource, retrieved from the pasteboard or from the sound segment in the application's executable file, or created algorithmically. The Sound class also provides an application-wide name table that lets you identify and locate sounds by name.
Playback and recording are performed by background threads, allowing your application to proceed in parallel. The latency between sending a play: or record: message and the start of the playback or recording, while within the tolerance demanded by most applications, can be further decreased by first reserving the sound facilities that you wish to use. This is done by calling the SNDReserve() C function. You should only use a Sound object to play and record sounds in applications that have a running NXApp object present. You can also edit a Sound object by adding and removing samples. To minimize data movement (and thus save time), an edited Sound may become fragmented; in other words, its sound data might become discontiguous in memory. While playback of a fragmented Sound object is transparent, it does incur some overhead. If you perform a number of edits you may want to return the Sound to a contiguous state by sending it a compactSamples message before you play it. However, a large Sound may take a long time to compact, so a judicious and well-timed use of compactSamples is advised. Fragmented Sounds are automatically compacted before they're copied to a pasteboard (through the writeToPasteboard: method). Also, when you write a Sound to a soundfile, the data in the file will be compact regardless of the state of the object. A Sound object contains a SNDSoundStruct, the structure that describes and contains sound data and that's used as the soundfile format and the pasteboard sound type. Most of the methods defined in the Sound class are implemented so that you needn't be aware of this structure. However, if you wish to directly manipulate the sound data in a Sound object, you need to be familiar with the SNDSoundStruct architecture, as described in the SNDAlloc() function |
Instance Variables |
SNDSoundStruct *soundStruct;
int soundStructSize; int priority; id delegate; int status; char *name; |
soundStruct | The object's sound data structure. | |
soundStructSize | The length of soundStruct in bytes. | |
priority | The object's recording and playback priority. | |
delegate | The target of notification messages. | |
status | What the object is currently doing. | |
name | The object's name. |
Method Types |
Creating and freeing a Sound object |
+ addName:fromBundle: |
+ addName:fromSection: + addName:fromSoundfile: initFromSection: initFromPasteboard: initFromSoundfile: free |
Accessing the Sound name table | + addName:sound: |
+ findSoundFor: + removeSoundForName: |
Accessing the Sound's name | setName: |
name |
Reading and writing sound data | readSoundfile: |
readSoundFromStream: writeSoundfile: writeSoundToStream: writeToPasteboard: |
Modifying sound data | convertToFormat:samplingRate:channelCount: |
convertToFormat: setDataSize:dataFormat:samplingRate: |
channelCount:infoSize: |
setSoundStruct:soundStructSize: setName: name |
Querying the object | soundStruct |
soundStructSize data dataFormat dataSize channelCount samplingRate sampleCount duration info infoSize isEmpty compatibleWith: processingError |
Recording and playing | pause |
pause: isPlayable play play: record record: resume resume: stop stop: samplesProcessed status soundBeingProcessed soundStructBeingProcessed |
Editing sound data | isEditable |
copySamples:at:count: copySound: deleteSamples deleteSamplesAt:count: insertSamples:at: needsCompacting compactSamples |
Archiving the object | finishUnarchiving |
read: write: |
Accessing the delegate | setDelegate: |
delegate tellDelegate: |
Accessing the sound hardware | + getVolume:: |
+ setVolume:: + isMuted + setMute: |
Class Methods |
addName:fromBundle: |
+ addName:(const char *)name fromBundle:(NXBundle *)aBundle |
Creates a Sound object from the sound resource named name in the NXBundle aBundle, assigns the name name to the object, and places the name on the sound name table. If name is already in use, or if the resource isn't found or can't be read, the Sound isn't created and nil is returned. Otherwise, the new Sound is returned. |
addName:fromSection: |
+ addName:(const char *)name fromSection:(const char *)sectionName |
Creates a Sound object from section sectionName in the sound segment of the application's executable file, assigns the name name to the object, and places the name on the sound name table. If name is already in use, or if the section isn't found or its data can't be copied, the Sound isn't created and nil is returned. Otherwise, the new Sound is returned. |
addName:fromSoundfile: |
+ addName:(const char *)name fromSoundfile:(const char *)filename |
Creates a Sound object from the soundfile filename, assigns the name name to the object, and adds it to the named Sound table. If name is already in use, or if filename isn't found or can't be read, the Sound isn't created and nil is returned. Otherwise, the new Sound is returned. |
addName:sound: |
+ addName:(const char *)name sound:aSound |
Assigns the name name to the Sound aSound and adds it to the named Sound table. Returns aSound, or nil if name is already in use. |
findSoundFor: |
+ findSoundFor:(const char *)aName |
Finds and returns the named Sound object. First the named Sound table is searched; if the sound isn't found, then the method looks for "aName.snd" in the sound segment of the application's executable file. Finally, the file is searched for in the following directories (in order): |
~/Library/Sounds | ||
/LocalLibrary/Sounds | ||
/NextLibrary/Sounds |
where ~ represents the user's home directory. If the Sound eludes the search, nil is returned. |
getVolume:: |
+ getVolume:(float *)left :(float *)right |
Returns, by reference, the stereo output levels as floating-point numbers between 0.0 and 1.0. |
isMuted |
+ (BOOL)isMuted |
Returns YES if the sound output level is currently muted. |
removeSoundForName: |
+ removeSoundForName:(const char *)name |
Removes the named Sound from the named Sound table. If the Sound isn't found, returns nil; otherwise returns the Sound. |
setMute: |
+ setMute:(BOOL)aFlag |
Mutes and unmutes the sound output level as aFlag is YES or NO, respectively. If successful, returns self; otherwise returns nil. |
setVolume:: |
+ setVolume:(float)left :(float)right |
Sets the stereo output levels. These affect the volume of the stereo signals sent to the built-in speaker and headphone jacks. left and right must be floating-point numbers between 0.0 (minimum) and 1.0 (maximum). If successful, returns self; otherwise returns nil. |
Instance Methods |
channelCount |
(int)channelCount |
Returns the number of channels in the Sound. |
compactSamples |
(int)compactSamples |
The Sound's sampled data is compacted into a contiguous block, undoing the fragmentation that can occur during editing. If the Sound's data isn't fragmented (its format isn't SND_FORMAT_INDIRECT), then this method does nothing. Compacting a large sound can take a long time; keep in mind that when you copy a Sound to a pasteboard, the object is automatically compacted before it's copied. Also, the soundfile representation of a Sound contains contiguous data so there's no need to compact a Sound before writing it to a soundfile simply to ensure that the file representation will be compact. An error code is returned. |
compatibleWith: |
(BOOL)compatibleWith:aSound |
Returns YES if the format, sampling rate, and channel count of aSound's sound data is the same as that of the Sound receiving this message. If one (or both) of the Sounds doesn't contain a sound (its soundStruct is nil) then the objects are declared compatible and YES is returned. |
convertToFormat: |
(int)convertToFormat:(int)newFormat |
This is the same as convertToFormat:samplingRate:channelCount:, except that only the format is changed. An error code is returned. |
convertToFormat:samplingRate:channelCount: |
(int)convertToFormat:(int)newFormat |
samplingRate:(double)newRate channelCount:(int)newChannelCount |
Convert the Sound's data to the given format, sampling rate, and number of channels. The following conversions are possible: |
Arbitrary sampling rate conversion. | ||
Compression and decompression. | ||
Floating-point formats (including double-precision) to and from linear formats. | ||
Mono to stereo. | ||
CODEC mu-law to and from linear formats. |
An error code is returned. |
copySamples:at:count: |
(int)copySamples:aSound |
at:(int)startSample count:(int)sampleCount |
Replaces the Sound's sampled data with a copy of a portion of aSound's data. The copied portion starts at aSound's startSample'th sample (zero-based) and extends over sampleCount samples. The Sound receiving this message must be editable and the two Sounds must be compatible. If the specified portion of aSound is fragmented, the Sound receiving this message will also be fragmented. An error code is returned. |
copySound: |
(int)copySound:aSound |
Replaces the Sound's data with a copy of aSound's data. The Sound receiving this message needn't be editable, nor must the two Sounds be compatible. An error code is returned. |
data |
(unsigned char *)data |
Returns a pointer to the Sound's sampled data. You can use the pointer to examine, create, and modify the sound data. To intelligently manipulate the data, you need to be aware of its size, format, sampling rate, and the number of channels that it contains (a query method for each of these attributes is provided by the Sound class). The size of the data, in particular, must be respected; it's set when the Sound is created or given a new sound (through readSoundfile:, for example) and can't be changed directly. To resize the data, you should invoke one of the editing methods such as insertSamples:at: or deleteSamplesAt:count:. To start with a new, unfragmented sound with a determinate length, invoke the setDataSize:dataFormat:samplingRate:channelCount:infoSize: method. Keep in mind that the sound data in a fragmented sound is a pointer to a NULL-terminated list of pointers to SNDSoundStructs, one for each fragment. To examine or manipulate the samples in a fragmented sound, you must understand the SNDSoundStruct structure. |
dataFormat |
(int)dataFormat |
Returns the format of the Sound's data. If the data is fragmented, the format of the samples is returned (in other words, SND_FORMAT_INDIRECT is never returned by this method). |
dataSize |
(int)dataSize |
Return the size (in bytes) of the Sound's data. If you modify the data (through the pointer returned by the data method) you must be careful not to exceed its length. If the sound is fragmented, the value returned by this method is the size of the Sound's soundStruct and doesn't include the actual data itself. |
delegate |
delegate |
Returns the Sound's delegate. |
deleteSamples |
(int)deleteSamples |
Deletes all the samples in the Sound's data. The Sound must be editable. An error code is returned. |
deleteSamplesAt:count: |
(int)deleteSamplesAt:(int)startSample count:(int)sampleCount |
Deletes a range of samples from the Sound: sampleCount samples are deleted starting with the startSample'th sample (zero-based). The Sound must be editable and may become fragmented. An error code is returned. |
duration |
(double)duration |
Returns the Sound's length in seconds. |
finishUnarchiving |
finishUnarchiving |
You never invoke this method. It's invoked automatically by the read: method to tie up loose ends after unarchiving the Sound. |
free |
free |
Frees the Sound and deallocates its sound data. The Sound is removed from the named Sound table and its name made eligible for reuse. |
info |
(char *)info |
Returns a pointer to the Sound's info string. |
infoSize |
(int)infoSize |
Returns the size (in bytes) of the Sound's info string. |
initFromPasteboard: |
initFromPasteboard:(Pasteboard *)thePboard |
Initializes the Sound instance, which must be newly allocated, by copying the sound data from the Pasteboard object thePboard. (A Pasteboard can have only one sound entry at a time.) Returns self (an unnamed Sound) if thePboard currently contains a sound entry; otherwise, frees the newly allocated Sound and returns nil.
See also: + alloc (Object), + allocFromZone: (Object) |
initFromSection: |
initFromSection:(const char *)sectionName |
Initializes the Sound instance, which must be newly allocated, by copying the sound data from section sectionName of the sound segment of the application's executable file. If the section isn't found, the object looks for a soundfile named sectionName in the same directory as the application's executable. Returns self (an unnamed Sound) if the sound data was successfully copied; otherwise, frees the newly allocated Sound and returns nil.
See also: + alloc (Object), + allocFromZone: (Object) |
initFromSoundfile: |
initFromSoundfile:(const char *)filename |
Initializes the Sound instance, which must be newly allocated, from the soundfile filename. Returns self (an unnamed Sound) if the file was successfully read; otherwise, frees the newly allocated Sound and returns nil.
See also: + alloc (Object), + allocFromZone: (Object) |
insertSamples:at: |
(int)insertSamples:aSound at:(int)startSample |
Pastes the sound data in aSound into the Sound receiving this message, starting at the receiving Sound's startSample'th sample (zero-based). The receiving Sound doesn't lose any of its original sound data--the samples greater than or equal to startSample are moved to accommodate the inserted sound data. The receiving Sound must be editable and the two Sounds must be compatible (as determined by isCompatible:). If the method is successful, the receiving Sound is fragmented. An error code is returned. |
isEditable |
(BOOL)isEditable |
Returns YES if the Sound's format indicates that it can be edited, otherwise returns NO. |
isEmpty |
(BOOL)isEmpty |
Returns YES if the Sound doesn't contain any sound data, otherwise returns NO. This always returns NO if the Sound isn't editable (as determined by sending it the isEditable message). |
isPlayable |
(BOOL)isPlayable |
Returns YES if the Sound can be played, otherwise returns NO. Some unplayable Sounds just need to be converted to another format, sampling rate, or number of channels; others are inherently unplayable, such as those whose format is SND_FORMAT_DISPLAY. To play a Sound that's just been recorded from the DSP, you must change its format from SND_FORMAT_DSP_DATA_16 to SND_FORMAT_LINEAR_16. |
name |
(const char *)name |
Returns the Sound's name. |
needsCompacting |
(BOOL)needsCompacting |
Returns YES if the Sound's data is fragmented. Otherwise returns NO. |
pause |
(int)pause |
Pauses the Sound during recording or playback. An error code is returned. |
pause: |
pause:sender |
Action method that pauses the Sound. Other than the argument and the return type, this is the same as the pause method. Returns self. |
play |
(int)play |
Initiates playback of the Sound. The method returns immediately while the playback continues asynchronously in the background. The playback ends when the Sound receives the stop message, or when its data is exhausted.
When playback starts, willPlay: is sent to the Sound's delegate; when it stops, didPlay: is sent. An error code is returned. |
Warning: | For this method to work properly, the main event loop must not be blocked. | |
play: |
play:sender |
Action method that plays the Sound. Other than the argument and the return type, this is the same as the play method. Returns self. |
processingError |
(int)processingError |
Returns a constant that represents the last error that was generated. The sound error codes are listed in "Types and Constants." |
read: |
read:(NXTypedStream *)stream |
Reads archived sound data from stream into the Sound. Returns self. |
readSoundfile: |
(int)readSoundfile:(const char *)filename |
Replaces the Sound's contents with those of the soundfile filename. The Sound loses its current name, if any. An error code is returned. |
readSoundFromStream: |
readSoundFromStream:(NXStream *)stream |
Replaces the Sound's contents with those of the sound in the NXStream stream. The Sound is given the name of the sound in the NXStream. If the sound in the NXStream is named, the Sound gets the new name. An error code is returned. |
record |
(int)record |
Initiate recording into the Sound. To record from the CODEC microphone, the Sound's format, sampling rate, and channel count must be SND_FORMAT_MULAW_8, SND_RATE_CODEC, and 1, respectively. If this information isn't set (if the Sound is a newly created object, for example), it defaults to accommodate a CODEC recording. If the Sound's format is SND_FORMAT_DSP_DATA_16, the recording is from the DSP.
The method returns immediately while the recording continues asynchronously in the background. The recording stops when the Sound receives the stop message or when the recording has gone on for the duration of the original sound data. The default CODEC recording lasts precisely ten minutes if not stopped. To record for a longer time, first increase the size of the sound data with setSoundStruct:soundStructSize: or setDataSize:dataFormat:samplingRate:channelCount:infoSize:. When the recording begins, willRecord: is sent to the Sound's delegate; when the recording stops, didRecord: is sent. An error code is returned. |
Warning: | For this method to work properly, the main event loop must not be blocked. | |
record: |
record:sender |
Action method that initiates a recording. Other than the argument and return type, this is the same as the record method. Returns self. |
resume |
(int)resume |
Resumes the paused Sound's activity. An error code is returned. |
resume: |
resume:sender |
Action method that resumes the paused Sound. Returns self. |
sampleCount |
(int)sampleCount |
Returns the number of sample frames, or channel count-independent samples, in the Sound. |
samplesProcessed |
(int)samplesProcessed |
If the Sound is currently playing or recording, this returns the number of sample frames that have been played or recorded so far. Otherwise, the number of sample frames in the Sound is returned. If the sample frame count can't be determined, 1 is returned. |
samplingRate |
(double)samplingRate |
Returns the Sound's sampling rate. |
setDataSize:dataFormat:samplingRate:channelCount:infoSize: |
(int)setDataSize:(int)newDataSize |
dataFormat:(int)newDataFormat samplingRate:(double)newSamplingRate channelCount:(int)newChannelCount infoSize:(int)newInfoSize |
Allocates new, unfragmented sound data for the Sound, as described by the arguments. The Sound's previous data is freed. This method is useful for setting a determinate data length prior to a recording or for creating a scratch pad for algorithmic sound creation. An error code is returned. |
setDelegate: |
setDelegate:anObject |
Sets the Sound's delegate to anObject. The delegate may implement the following methods: |
willPlay: | ||
didPlay: | ||
willRecord: | ||
didRecord: | ||
hadError: |
Returns self. |
setName: |
setName:(const char *)aName |
Sets the Sound's name to aName. If aName is already being used, then the Sound's name isn't set and nil is returned; otherwise returns self. |
setSoundStruct:soundStructSize: |
setSoundStruct:(SNDSoundStruct *)aStruct soundStructSize:(int)size |
Sets the Sound's sound structure to aStruct. The size in bytes of the new structure, including its sound data storage, must be specified by size. This method can be used to set up a large buffer before recording into an existing Sound, by passing the existing soundStruct in the first argument while making size larger than the current size. (The default buffer holds ten minutes of CODEC sound.) The method is also useful in cases where aStruct already has sound data but isn't encapsulated in a Sound object yet. The Sound's status must be NX_SoundInitialized or NX_SoundStopped for this method to do anything. Returns self. |
soundBeingProcessed |
soundBeingProcessed |
Returns the Sound object that's being performed. The default implementation always returns self. |
soundStruct |
(SNDSoundStruct *)soundStruct |
Returns a pointer to the Sound's SNDSoundStruct structure that holds the object's sound data. |
soundStructBeingProcessed |
(SNDSoundStruct *)soundStructBeingProcessed |
Returns a pointer to the SNDSoundStruct structure that's being performed. This may not be the same structure as returned by the soundStruct method--Sound object's contain a private sound structure that may be used for recording playing. If the Sound isn't currently playing or recording, then this will return the public structure. |
soundStructSize |
(int)soundStructSize |
Returns the size, in bytes, of the Sound's sound structure (pointed to by soundStruct). Use of this value requires a knowledge of the SNDSoundStruct architecture. |
status |
(int)status |
Return the Sound's current status, one of the following integer constants: |
NX_SoundStopped | ||
NX_SoundRecording | ||
NX_SoundPlaying | ||
NX_SoundInitialized | ||
NX_SoundRecordingPaused | ||
NX_SoundPlayingPaused | ||
NX_SoundRecordingPending | ||
NX_SoundPlayingPending | ||
NX_SoundFreed |
stop |
(int)stop |
Terminates the Sound's playback or recording. If the Sound was recording, the didRecord: message is sent to the delegate; if playing, didPlay: is sent. An error code is returned. |
stop: |
stop:sender |
Action method that stops the Sound's playback or recording. Other than the argument and the return type, this is the same as the stop method. Returns self. |
tellDelegate: |
tellDelegate:(SEL)theMessage |
Sends theMessage to the Sound's delegate (only sent if the delegate implements theMessage). You never invoke this method directly; it's invoked automatically as the result of activities such as recording and playing. However, you can use it in designing a subclass of Sound. Returns self. |
write: |
write:(NXTypedStream *)stream |
Archives the Sound by writing its data to stream, which must be open for writing. Returns self. |
writeSoundfile: |
(int)writeSoundfile:(const char *)filename |
Writes the Sound's contents (its SNDSoundStruct and sound data) to the soundfile filename. An error code is returned. |
writeSoundToStream: |
writeSoundToStream:(NXStream *)stream |
Writes the Sound's name (if any), priority, SNDSoundStruct, and sound data (if any) to the NXStream stream. Returns self. |
writeToPasteboard: |
(int)writeToPasteboard:(Pasteboard *)thePboard |
Puts a copy of the Sound's contents (its SNDSoundStruct and sound data) on the pasteboard maintained by the Pasteboard object thePboard. If the Sound is fragmented, it's compacted before the copy is created. An error code is returned. |
Methods Implemented by the Delegate |
didPlay: |
didPlay:sender |
Sent to the delegate when the Sound stops playing. |
didRecord: |
didRecord:sender |
Sent to the delegate when the Sound stops recording. |
hadError: |
hadError:sender |
Sent to the delegate if an error occurs during recording or playback. |
willPlay: |
willPlay:sender |
Sent to the delegate when the Sound begins to play. |
willRecord: |
willRecord:sender |
Sent to the delegate when the Sound begins to record. |