home *** CD-ROM | disk | FTP | other *** search
- /*
- File: DoubleBufferFromFile.c
-
- Contains: Routines demonstrating how to play a sound from disk using SndPlayDoubleBuffer.
-
- Written by: Mark Cookson
-
- Copyright: Copyright © 1996-1999 by Apple Computer, Inc., All Rights Reserved.
-
- You may incorporate this Apple sample source code into your program(s) without
- restriction. This Apple sample source code has been provided "AS IS" and the
- responsibility for its operation is yours. You are not permitted to redistribute
- this Apple sample source code as "Apple sample source code" after having made
- changes. If you're going to re-distribute the source, we require that you make
- it clear in the source that the code was descended from Apple sample source
- code, but that you've made changes.
-
- Change History (most recent first):
- 8/31/1999 Karl Groethe Updated for Metrowerks Codewarror Pro 2.1
-
-
- */
-
- #include "MyAIFF.h"
- #include "DoubleBufferFromFile.h"
-
- /* Purpose: This creates a new SoundInfo structure and initializes
- it by calling the private function ASoundInit.
- Side Effects: None.
- */
- /*-----------------------------------------------------------------------*/
- SoundInfoPtr ASoundNew (OSErr *theErr)
- /*-----------------------------------------------------------------------*/
- {
- SoundInfoPtr theSoundInfo = nil;
-
- *theErr = noErr;
- theSoundInfo = (SoundInfoPtr)NewPtrClear (sizeof (SoundInfo));
-
- if (MemError () != noErr || theSoundInfo == nil) {
- *theErr = kInitErr;
- }
- else {
- *theErr = ASoundInit (theSoundInfo);
- }
-
- if (*theErr != noErr) {
- DebugPrint ("\pError in ASoundNew");
- }
-
- return theSoundInfo;
- }
-
- /*
- Purpose: Display a StandardFile dialog to select a file.
- Opens the file selected by the user.
- Side Effects: None.
- */
- /*-----------------------------------------------------------------------*/
- OSErr ASoundGetFileToPlay (SoundInfoPtr theSoundInfo)
- /*-----------------------------------------------------------------------*/
- {
- FileFilterUPP myFilterUPP = nil;
- OSErr theErr = noErr;
- short i = 0;
- Boolean good = false;
-
- if (IsValid (theSoundInfo)) {
- myFilterUPP = NewFileFilterProc (ASoundFileFilter);
- if ((theSoundInfo->globals.ggestaltStandardFileAttr & gestaltStandardFile58) == false) {
- StandardFileReply theSFReply;
- short showTypes;
-
- if ((theSoundInfo->globals.ggestaltTranslationAttr & (1 << gestaltTranslationMgrExists)) == true) {
- showTypes = kUseOpenResourceTypes;
- }
- else {
- showTypes = kNoFirstFiltering;
- }
- StandardGetFile (myFilterUPP, showTypes, nil, &theSFReply);
- theSoundInfo->vRefNum = theSFReply.sfFile.vRefNum;
- if (theSFReply.sfGood == true) {
- switch (theSFReply.sfType) {
- case kSNDResource:
- case kResource:
- theErr = FSpOpenRF (&theSFReply.sfFile, fsCurPerm, &(theSoundInfo->refNum));
- break;
- case kCompressedAIFFFile:
- case kUncompressedAIFFFile:
- case kWAVEFile:
- case kWAVFile:
- case kAUFile:
- theErr = FSpOpenDF (&theSFReply.sfFile, fsCurPerm, &(theSoundInfo->refNum));
- break;
- default:
- DebugPrint ("\pASoundGetFileToPlay should have never executed this line");
- }
- if (theErr != noErr) {
- DebugPrint ("\pCouldn't open file");
- }
- else {
- theSoundInfo->fileType = theSFReply.sfType;
- for (i = 0; i <= theSFReply.sfFile.name[0]+1; i++)
- theSoundInfo->theName[i] = theSFReply.sfFile.name[i];
- }
- }
- else {
- theErr = userCanceledErr;
- }
- }
- else {
- SFReply theSFReply;
- Point where = {kInit, kInit};
- Rect screenRect = GetMainScreenRect();
- long dirID = kInit,
- procID = kInit;
-
- where.h = screenRect.right / kHorizAdjust; /* This will put the SFGetFile dialog in the same place */
- where.v = screenRect.bottom / kVertAdjust; /* as the StandardGetFile dialog (or really close). */
- if ((GetMBarHeight() + kOne) > where.h) {
- where.h = GetMBarHeight() + kOne;
- }
- SFGetFile (where, nil, myFilterUPP, kNoFirstFiltering, nil, nil, &theSFReply);
- good = theSFReply.good;
- if (theSFReply.good == true) {
- theErr = GetWDInfo (theSFReply.vRefNum, &(theSoundInfo->vRefNum), &dirID, &procID);
- if (theErr == noErr) {
- switch (theSFReply.fType) {
- case kSNDResource:
- case kResource:
- theErr = HOpenRF (theSoundInfo->vRefNum, dirID, theSFReply.fName, fsCurPerm, &(theSoundInfo->refNum));
- break;
- case kCompressedAIFFFile:
- case kUncompressedAIFFFile:
- case kWAVEFile:
- case kWAVFile:
- case kAUFile:
- theErr = HOpenDF (theSoundInfo->vRefNum, dirID, theSFReply.fName, fsCurPerm, &(theSoundInfo->refNum));
- break;
- default:
- DebugPrint ("\pASoundGetFileToPlay should have never executed this line");
- }
- if (theErr != noErr) {
- DebugPrint ("\pCouldn't open file");
- }
- else {
- theSoundInfo->fileType = theSFReply.fType;
- for (i = 0; i <= theSFReply.fName[0]+1; i++)
- theSoundInfo->theName[i] = theSFReply.fName[i];
- }
- }
- else {
- theErr = kFileErr;
- DebugPrint ("\pCouldn't translate working directory");
- }
- }
- else {
- theErr = userCanceledErr;
- }
- }
- DisposeRoutineDescriptor (myFilterUPP);
- }
- else {
- theErr = kNilPtrErr;
- }
-
- if (theErr != noErr && theErr != userCanceledErr) {
- DebugPrint ("\pError in ASoundGetFileToPlay");
- }
-
- return theErr;
- }
-
- /*
- Purpose: Checks a file to see if its header can be parsed
- and the file can be played.
-
- This will return an error if the sound will not play,
- returning noErr means that sound will play.
-
- Parsing a header can take some time, this routine
- is a canidate for speed improvements.
- Side Effects: None.
- */
- /*-----------------------------------------------------------------------*/
- OSErr ASoundCanThisPlay (CInfoPBPtr theFileInfo)
- /*-----------------------------------------------------------------------*/
- {
- SoundInfoPtr theSoundInfo = nil;
- long dataStart = kInit,
- sndLength = kInit;
- OSErr theErr = noErr,
- closeErr = noErr;
-
- if (theFileInfo != nil) {
- theSoundInfo = ASoundNew (&theErr);
- if (theErr == noErr) {
- theSoundInfo->vRefNum = theFileInfo->hFileInfo.ioVRefNum;
- theSoundInfo->fileType = theFileInfo->hFileInfo.ioFlFndrInfo.fdType;
- theErr = HOpenDF (theFileInfo->hFileInfo.ioVRefNum, theFileInfo->hFileInfo.ioFlParID, theFileInfo->hFileInfo.ioNamePtr, fsRdPerm, &theSoundInfo->refNum);
- if (theErr == noErr) {
- switch (theSoundInfo->fileType) {
- case kCompressedAIFFFile:
- case kUncompressedAIFFFile:
- theErr = ASoundGetAIFFHeader (theSoundInfo, &dataStart, &sndLength);
- break;
- case kWAVEFile:
- case kWAVFile:
- theErr = ASoundGetWAVEHeader (theSoundInfo, &dataStart, &sndLength);
- break;
- case kAUFile:
- theErr = ASoundGetULAWHeader (theSoundInfo, &dataStart, &sndLength);
- break;
- case kSNDResource:
- case kResource:
- theErr = noErr;
- break;
- default:
- /* The file type is not one that we can even parse. */
- theErr = kUnknownFormat;
- break;
- }
- }
- }
- }
- else {
- theErr = kNilPtrErr;
- }
-
- closeErr = FSClose (theSoundInfo->refNum);
- DisposeRoutineDescriptor (ASoundGetSoundCallBack (theSoundInfo));
- DisposePtr ((Ptr)theSoundInfo);
-
- if (closeErr != noErr) {
- theErr = closeErr;
- }
-
- if (theErr != noErr && theErr != kUnknownFormat) {
- DebugPrint ("\pError in ASoundCanThisPlay");
- }
-
- return theErr;
- }
-
- /*
- Purpose: This function is called to get ready to play a sound.
- Use this if you want to make sure that there is enough
- memory to play the sound.
- Side Effects: This will call routines that will allocate memory needed
- to all of the various structures needed by the Sound Manager
- and memory to be used as the sounds' buffers.
- */
- /*-----------------------------------------------------------------------*/
- OSErr ASoundReadyForPlaying (SoundInfoPtr theSoundInfo,
- unsigned long bufferSize)
- /*-----------------------------------------------------------------------*/
- {
- OSErr theErr = noErr;
-
- if (IsValid (theSoundInfo)) {
- if (theSoundInfo->globals.gSupportsSPDB == false) {
- DebugPrint ("\pThis machine doesn't support SoundPlayDoubleBuffer, can't play!");
- theErr = kNoSPDBErr;
- }
- else {
- /* do we want to start at the begining of the file? */
- if ((ASoundGetBytesCopied (theSoundInfo) <= kMaxAIFFHeaderSize) && theSoundInfo->paused == false) {
- theSoundInfo->soundDone = false;
- theErr = SndNewChannel (&(theSoundInfo->chan), sampledSynth, nil, ASoundGetSoundCallBack (theSoundInfo));
- if (theErr != noErr) {
- DebugPrint ("\pSndNewChannel error!");
- }
- else {
- theErr = SetUpSoundHeader (theSoundInfo, bufferSize);
- if (theErr == noErr) {
- theErr = ASoundPrimeBuffers (theSoundInfo);
- ASoundSetCurBuffer (theSoundInfo, kStart);
- }
- }
- }
- else {
- theErr = ASoundPrimeBuffers (theSoundInfo);
- }
- }
- }
- else {
- theErr = kNilPtrErr;
- }
-
- if (theErr != noErr) {
- DebugPrint ("\pError in ASoundReadyForPlaying!");
- (void)ASoundDonePlaying (theSoundInfo, kCloseFile + kFreeMem);
- }
-
- return theErr;
- }
-
- /*
- Purpose: Call this after you have called ASoundReadyForPlaying to
- start playing the sound you prepaired.
- Side Effects: Starts the sound playing.
- */
- /*-----------------------------------------------------------------------*/
- OSErr ASoundPlay (SoundInfoPtr theSoundInfo)
- /*-----------------------------------------------------------------------*/
- {
- OSErr theErr = noErr;
-
- if (IsValid (theSoundInfo)) {
- if (theSoundInfo->playing == false || theSoundInfo->paused == true) {
- if (theSoundInfo->globals.gSupportsSPDB == false) {
- theErr = kNoSPDBErr;
- DebugPrint ("\pThis machine doesn't support SoundPlayDoubleBuffer, can't play!");
- }
- else {
- if (theSoundInfo->paused == false) {
- theErr = SndPlayDoubleBuffer (theSoundInfo->chan, (SndDoubleBufferHeaderPtr)&(theSoundInfo->doubleHeader));
- if (theErr == noErr) {
- theErr = InstallCallBack (theSoundInfo);
- }
- if (theErr == noErr) {
- theSoundInfo->playing = true;
- }
- }
- }
- }
- }
- else {
- theErr = kNilPtrErr;
- }
-
- if (theErr != noErr) {
- DebugPrint ("\pError in ASoundPlay!");
- (void)ASoundDonePlaying (theSoundInfo, kCloseFile + kFreeMem);
- }
-
- return theErr;
- }
-
- /*
- Purpose: Wrapper function called to start playing a sound.
- Use this if you are pretty sure the sound will play, or
- just don't care specifically what goes wrong.
- Side Effects: This will call routines that will allocate memory needed
- for all of the various structures needed by the Sound Manager
- and memory to be used as the sounds' buffers.
- */
- /*-----------------------------------------------------------------------*/
- OSErr ASoundStartPlaying (SoundInfoPtr theSoundInfo,
- unsigned long bufferSize)
- /*-----------------------------------------------------------------------*/
- {
- OSErr theErr = noErr;
-
- theErr = ASoundReadyForPlaying (theSoundInfo, bufferSize);
- if (theErr == noErr) {
- theErr = ASoundPlay (theSoundInfo);
- }
-
- if (theErr != noErr) {
- DebugPrint ("\pError in ASoundStartPlaying!");
- (void)ASoundDonePlaying (theSoundInfo, kCloseFile + kFreeMem);
- }
-
- return theErr;
- }
-
- /*
- Purpose: Stops the currently playing sound.
- Side Effects: Stopping the currently playing sound will cause the
- sound completion routine to run.
- */
- /*-----------------------------------------------------------------------*/
- OSErr ASoundStop (SoundInfoPtr theSoundInfo)
- /*-----------------------------------------------------------------------*/
- {
- SndCommand theCmd = {quietCmd, kInit, kInit};
- OSErr theErr = noErr;
-
- if (StrictIsValid (theSoundInfo)) {
- /* So that ASoundDoubleBackProc knows that it doesn't have to
- actually read any data */
- theSoundInfo->stopping = true;
- theErr = SndDoImmediate (theSoundInfo->chan, &theCmd);
- if (theErr == noErr) {
- theSoundInfo->playing = false;
- theSoundInfo->paused = false;
- }
- }
- else {
- theErr = kNilPtrErr;
- }
-
- if (theErr != noErr) {
- DebugPrint ("\pError in ASoundStop");
- }
-
- return theErr;
- }
-
- /*
- Purpose: Wrapper so the user doesn't have to keep track of if
- the sound is playing or not.
- Side Effects: If resuming a sound and the user had also called
- ASoundPauseForAdjust this will reinstall the sound
- completion callback.
- */
- /*-----------------------------------------------------------------------*/
- OSErr ASoundPause (SoundInfoPtr theSoundInfo)
- /*-----------------------------------------------------------------------*/
- {
- OSErr theErr = noErr;
-
- if (StrictIsValid (theSoundInfo)) {
- if (theSoundInfo->paused == false) {
- theErr = PauseSound (theSoundInfo);
- }
- else {
- theErr = ResumeSound (theSoundInfo);
- }
- }
- else {
- theErr = kNilPtrErr;
- }
-
- if (theErr != noErr) {
- DebugPrint ("\pError in ASoundPause");
- }
-
- return theErr;
- }
-
- /*
- Purpose: If the sound is paused, resume playing. If the sound is
- playing, pause playing.
- This differs from ASoundPause because it actually stops
- the sound instead of pausing it. When the sound is
- paused for adjusting you can reset where the sound will
- next start playing from without having to play the
- remainder of the current buffer. This routine is used
- for the QuickTime style playing.
- Side Effects: Removes the callback from the sound channel because
- otherwise while adjusting the sound the Sound Manager
- would call our clean up routine.
- When resuming a sound ASoundStartPlaying will install
- our callback routine if necessary (if the sound wasn't
- already paused).
- */
- /*-----------------------------------------------------------------------*/
- OSErr ASoundPauseForAdjust (SoundInfoPtr theSoundInfo)
- /*-----------------------------------------------------------------------*/
- {
- SndCommand theCmd = {kInit, kInit, kInit};
- OSErr theErr = noErr;
- static Fixed oldRate = kInit;
-
- if (StrictIsValid (theSoundInfo)) {
- if (theSoundInfo->adjusting == false) {
- theCmd.cmd = flushCmd; /* so the sound completion callback doesn't get called */
- theErr = SndDoImmediate (theSoundInfo->chan, &theCmd);
- if (theErr == noErr) {
- theSoundInfo->adjusting = true;
- theCmd.cmd = quietCmd;
- theErr = SndDoImmediate (theSoundInfo->chan, &theCmd);
- if (theErr == noErr) {
- theSoundInfo->hasBeenAdjusted = true;
- theSoundInfo->playing = false;
- }
- }
- }
- else {
- theSoundInfo->adjusting = false;
- ASoundStartPlaying (theSoundInfo, nil);
- }
- }
- else {
- theErr = kNilPtrErr;
- }
-
- if (theErr != noErr) {
- DebugPrint ("\pError in ASoundPauseForAdjust");
- }
-
- return theErr;
- }
-
- /*
- Purpose: Sound is done playing, dispose of the memory we no
- longer need.
- Side Effects: None.
- */
- /*-----------------------------------------------------------------------*/
- OSErr ASoundDonePlaying (SoundInfoPtr theSoundInfo,
- unsigned long options)
- /*-----------------------------------------------------------------------*/
- {
- myParamBlockRec *myPB = nil;
- OSErr theErr = noErr;
- short i = kInit,
- savedVRefNum = kInit,
- savedRefNum = kInit;
-
- if (IsValid (theSoundInfo)) {
- theSoundInfo->soundDone = false; /* so we don't get called multiple times */
- theSoundInfo->playing = false;
-
- savedVRefNum = theSoundInfo->vRefNum;
- savedRefNum = theSoundInfo->refNum;
- if ((options == kCloseFile) || (options > kCloseFile + kFreeMem)) {
- DebugPrint ("\pInvalid selector passed to ASoundDonePlaying");
- theErr = kBadValue;
- }
- else {
- theSoundInfo->stopping = false; /* Sound is done stopping, hopefully... */
- if (options > kNoOptions) {
- myPB = (myParamBlockRec*)theSoundInfo->doubleHeader.dbhBufferPtr[kDBBufOne]->dbUserInfo[kPBPtr];
- if (myPB != nil) {
- if (options == kCloseFile + kFreeMem) {
- theErr = FSClose (myPB->pb.ioParam.ioRefNum);
- }
- if (theErr == noErr) {
- for (i = kInit; i <= kOne; i++) {
- DisposeRoutineDescriptor (((myParamBlockRec*)theSoundInfo->doubleHeader.dbhBufferPtr[i]->dbUserInfo[kPBPtr])->pb.ioParam.ioCompletion);
- DisposePtr ((Ptr)theSoundInfo->doubleHeader.dbhBufferPtr[i]->dbUserInfo[kPBPtr]);
- /* Have to unhold memory that was held */
- UnholdMemory ((Ptr)theSoundInfo->doubleHeader.dbhBufferPtr[i], sizeof(SndDoubleBuffer) + ASoundGetBufferSize (theSoundInfo));
- DisposePtr ((Ptr)theSoundInfo->doubleHeader.dbhBufferPtr[i]);
- }
- }
- else {
- DebugPrint ("\pFSClose error!");
- }
- theErr = SndDisposeChannel (theSoundInfo->chan, true);
- DisposeRoutineDescriptor (ASoundGetSoundCallBack (theSoundInfo));
- DisposeRoutineDescriptor (theSoundInfo->doubleHeader.dbhDoubleBack);
- if (theErr != noErr) {
- DebugPrint ("\pSndDisposeChannel error!");
- }
- }
- }
-
- if (options == kNoOptions) {
- ASoundSetBytesCopied (theSoundInfo, theSoundInfo->dataStart);
- ASoundSetCurBuffer (theSoundInfo, kStart);
- theSoundInfo->doubleHeader.dbhBufferPtr[kDBBufOne]->dbFlags = nil;
- theSoundInfo->doubleHeader.dbhBufferPtr[kDBBufTwo]->dbFlags = nil;
- theErr = ASoundPrimeBuffers (theSoundInfo);
- }
- if (options == kFreeMem) {
- ASoundInit (theSoundInfo);
- theSoundInfo->vRefNum = savedVRefNum;
- theSoundInfo->refNum = savedRefNum;
- }
- else {
- if (options == kCloseFile + kFreeMem) {
- ASoundInit (theSoundInfo);
- }
- }
- }
- }
- else {
- theErr = kNilPtrErr;
- }
-
- if (theErr != noErr) {
- DebugPrint ("\pError in ASoundDonePlaying");
- }
-
- return theErr;
- }
-
- /*
- Purpose: Returns the channel for the sound in case you want to
- send it specific commands.
- Side Effects: None.
- */
- /*-----------------------------------------------------------------------*/
- SndChannelPtr ASoundGetChan (SoundInfoPtr theSoundInfo)
- /*-----------------------------------------------------------------------*/
- {
- SndChannelPtr returnValue;
-
- if (StrictIsValid (theSoundInfo)) {
- returnValue = theSoundInfo->chan;
- } else {
- returnValue = nil;
- }
-
- return returnValue;
- }
-
- /*
- Purpose: Returns the name of the file containing the currently
- playing sound.
- Side Effects: None.
- */
- /*-----------------------------------------------------------------------*/
- OSErr ASoundGetSoundName (SoundInfoPtr theSoundInfo,
- Str63 theName)
- /*-----------------------------------------------------------------------*/
- {
- OSErr theErr = noErr;
- short i = 0;
-
- if (StrictIsValid (theSoundInfo) && theName != nil) {
- /* This should probably be a BlockMoveData */
- for (i = 0; i <= theSoundInfo->theName[0]+1; i++)
- theName[i] = theSoundInfo->theName[i];
- }
-
- return theErr;
- }
-
- /*
- Purpose: Gets the number of the current buffer
- (in the range 1 to ASoundGetNumBuffers()) of the
- currently playing sound.
- Side Effects: None.
- */
- /*-----------------------------------------------------------------------*/
- long ASoundGetCurBuffer (SoundInfoPtr theSoundInfo)
- /*-----------------------------------------------------------------------*/
- {
- long returnValue = kInit;
- OSErr theErr = noErr;
-
- if (StrictIsValid (theSoundInfo)) {
- returnValue = theSoundInfo->currentBuffer;
- }
- else {
- theErr = kNilPtrErr;
- returnValue = nil;
- }
-
- if (theErr != noErr) {
- DebugPrint ("\pError in ASoundGetCurBuffer");
- }
-
- return returnValue;
- }
-
- /*
- Purpose: Sets which buffer should be the next buffer to play
- from (in the range 1 to ASoundGetNumBuffers())
- for the currently playing sound.
- Side Effects: None.
- */
- /*-----------------------------------------------------------------------*/
- OSErr ASoundSetCurBuffer (SoundInfoPtr theSoundInfo,
- long newValue)
- /*-----------------------------------------------------------------------*/
- {
- OSErr theErr = noErr;
-
- if (IsValid (theSoundInfo)) {
- if ((newValue >= kStart) && (newValue <= ASoundGetNumBuffers (theSoundInfo))) {
- theSoundInfo->currentBuffer = newValue;
- ASoundSetBytesCopied (theSoundInfo, newValue * ASoundGetBufferSize (theSoundInfo) + theSoundInfo->dataStart);
- }
- else {
- theErr = kBadRange;
- }
- }
- else {
- theErr = kNilPtrErr;
- }
-
- return theErr;
- }
-
- /*
- Purpose: Gets the number of buffers that the currently playing
- sound will need to play in its entirety.
- Side Effects: None.
- */
- /*-----------------------------------------------------------------------*/
- long ASoundGetNumBuffers (SoundInfoPtr theSoundInfo)
- /*-----------------------------------------------------------------------*/
- {
- long returnValue = kInit;
- OSErr theErr = noErr;
-
- if (IsValid (theSoundInfo)) {
- returnValue = theSoundInfo->numBuffers;
- }
- else {
- theErr = kNilPtrErr;
- returnValue = nil;
- }
-
- if (theErr != noErr) {
- DebugPrint ("\pError in ASoundGetNumBuffers");
- }
-
- return returnValue;
- }
-
- /*
- Purpose: Gets the length (in bytes) of the currently playing
- sound. This number does not include any header bytes.
- Side Effects: None.
- */
- /*-----------------------------------------------------------------------*/
- long ASoundGetNumTotalBytes (SoundInfoPtr theSoundInfo)
- /*-----------------------------------------------------------------------*/
- {
- long returnValue = kInit;
- OSErr theErr = noErr;
-
- if (IsValid (theSoundInfo)) {
- returnValue = theSoundInfo->bytesTotal;
- }
- else {
- theErr = kNilPtrErr;
- returnValue = nil;
- }
-
- if (theErr != noErr) {
- DebugPrint ("\pError in ASoundGetNumTotalBytes");
- }
-
- return returnValue;
- }
-
- /*
- Purpose: Gets the number of bytes that will be played by the end
- of the current buffer of the currently playing sound.
- Side Effects: None.
- */
- /*-----------------------------------------------------------------------*/
- long ASoundGetBytesCopied (SoundInfoPtr theSoundInfo)
- /*-----------------------------------------------------------------------*/
- {
- long returnValue = kInit;
- OSErr theErr = noErr;
-
- if (IsValid (theSoundInfo)) {
- returnValue = theSoundInfo->bytesCopied;
- }
- else {
- theErr = kNilPtrErr;
- returnValue = nil;
- }
-
- if (theErr != noErr) {
- DebugPrint ("\pError in ASoundGetBytesCopied");
- }
-
- return returnValue;
- }
-
- /*
- Purpose: Sets the location in the file where the next buffer
- should be filled from for the currently playing sound.
- Side Effects: None.
- */
- /*-----------------------------------------------------------------------*/
- OSErr ASoundSetBytesCopied (SoundInfoPtr theSoundInfo,
- long newValue)
- /*-----------------------------------------------------------------------*/
- {
- OSErr theErr = noErr;
-
- if (IsValid (theSoundInfo)) {
- if (newValue >= theSoundInfo->dataStart || newValue == kInit) {
- theSoundInfo->bytesCopied = newValue;
- }
- else {
- theErr = kBadValue;
- }
- }
- else {
- theErr = kNilPtrErr;
- }
-
- if (theErr != noErr) {
- DebugPrint ("\pError in ASoundSetBytesCopied");
- }
-
- return theErr;
- }
-
- /*
- Purpose: Gets the size of a buffer of the currently playing
- sound. Multiply by two to know how much memory is
- reserved for buffering the currently playing sound.
- Side Effects: None.
- */
- /*-----------------------------------------------------------------------*/
- long ASoundGetBufferSize (SoundInfoPtr theSoundInfo)
- /*-----------------------------------------------------------------------*/
- {
- long returnValue = kInit;
- OSErr theErr = noErr;
-
- if (IsValid (theSoundInfo)) {
- returnValue = theSoundInfo->doubleBufferSize;
- }
- else {
- theErr = kNilPtrErr;
- returnValue = nil;
- }
-
- if (theErr != noErr) {
- DebugPrint ("\pError in ASoundGetBufferSize");
- }
-
- return returnValue;
- }
-
- /*
- Purpose: Gets the UPP for the function that should be called when
- the currently playing sound finishes.
- Side Effects: None.
- */
- /*-----------------------------------------------------------------------*/
- SndCallBackUPP ASoundGetSoundCallBack (SoundInfoPtr theSoundInfo)
- /*-----------------------------------------------------------------------*/
- {
- SndCallBackUPP returnValue = nil;
- OSErr theErr = noErr;
-
- if (IsValid (theSoundInfo)) {
- returnValue = theSoundInfo->theSoundCallBackUPP;
- }
- else {
- theErr = kNilPtrErr;
- returnValue = nil;
- }
-
- if (theErr != noErr) {
- DebugPrint ("\pError in ASoundGetSoundCallBack");
- }
-
- return returnValue;
- }
-
- /*
- Purpose: Sets the function that should be called when the the
- currently playing sound finishes.
- Side Effects: None.
- */
- /*-----------------------------------------------------------------------*/
- OSErr ASoundSetSoundCallBack (SoundInfoPtr theSoundInfo,
- void* newValue)
- /*-----------------------------------------------------------------------*/
- {
- OSErr theErr = noErr;
-
- if (IsValid (theSoundInfo)) {
- if (theSoundInfo->theSoundCallBackUPP != nil) {
- DisposeRoutineDescriptor (theSoundInfo->theSoundCallBackUPP);
- }
- if (newValue != nil) {
- theSoundInfo->theSoundCallBackUPP = NewSndCallBackProc(newValue);
- }
- else {
- theSoundInfo->theSoundCallBackUPP = NewSndCallBackProc(ASoundDoneCallBack);
- DebugPrint ("\pDid you really want the default sound callback?");
- }
- }
- else {
- theErr = kNilPtrErr;
- }
-
- if (theErr != noErr) {
- DebugPrint ("\pError in ASoundSetSoundCallBack");
- }
-
- return theErr;
- }
-
- /*
- Purpose: Says whether to play the currently playing sound backwards
- (it actually reverses the sound in the buffer).
- Side Effects: Takes effect when the next sound buffer gets filled.
- */
- /*-----------------------------------------------------------------------*/
- OSErr ASoundPlayBackwards (SoundInfoPtr theSoundInfo,
- Boolean newValue)
- /*-----------------------------------------------------------------------*/
- {
- OSErr theErr = noErr;
-
- if (StrictIsValid (theSoundInfo)) {
- theSoundInfo->backwards = newValue;
- }
- else {
- theErr = kNilPtrErr;
- }
-
- if (theErr != noErr) {
- DebugPrint ("\pError in ASoundPlayBackwards");
- }
-
- return theErr;
- }
-
- /*
- Purpose: Returns true if the currently playing sound's buffer
- is set to be reversed.
- Side Effects: None.
- */
- /*-----------------------------------------------------------------------*/
- Boolean ASoundIsBackwards (SoundInfoPtr theSoundInfo)
- /*-----------------------------------------------------------------------*/
- {
- OSErr theErr = noErr;
- Boolean returnValue = false;
-
- if (StrictIsValid (theSoundInfo)) {
- returnValue = theSoundInfo->backwards;
- }
- else {
- theErr = kNilPtrErr;
- }
-
- if (theErr != noErr) {
- DebugPrint ("\pError in ASoundIsBackwards");
- }
-
- return returnValue;
- }
-
- /*
- Purpose: Returns true if the sound has finished playing.
- Side Effects: None.
- */
- /*-----------------------------------------------------------------------*/
- Boolean ASoundIsDone (SoundInfoPtr theSoundInfo)
- /*-----------------------------------------------------------------------*/
- {
- OSErr theErr = noErr;
- Boolean returnValue = false;
-
- if (StrictIsValid (theSoundInfo)) {
- returnValue = theSoundInfo->soundDone;
- }
- else {
- theErr = kNilPtrErr;
- }
-
- if (theErr != noErr) {
- DebugPrint ("\pError in ASoundIsDone");
- }
-
- return returnValue;
- }
-
- /*
- Purpose: Changes the volume of the currently playing sound.
- The values you pass in are added to the current values.
- Negitive values will decrease the volume, positive values
- will increase the volume.
- Side Effects: None.
- */
- /*-----------------------------------------------------------------------*/
- OSErr ASoundChangeVolume (SoundInfoPtr theSoundInfo,
- unsigned short leftVol,
- unsigned short rightVol)
- /*-----------------------------------------------------------------------*/
- {
- SndCommand theCmd = {volumeCmd, kInit, kInit};
- OSErr theErr = noErr;
- unsigned short tempLeft = kInit,
- tempRight = kInit;
-
- if (StrictIsValid (theSoundInfo)) {
- theErr = ASoundGetVolume (theSoundInfo, &tempLeft, &tempRight);
- if (theErr == noErr) {
- if ((tempLeft + leftVol) > kMaxVolume) leftVol = kMaxVolume - tempLeft;
- if ((tempRight + rightVol) > kMaxVolume) rightVol = kMaxVolume - tempRight;
- if ((tempLeft + leftVol) < kMinVolume) leftVol = -tempLeft;
- if ((tempRight + rightVol) < kMinVolume) rightVol = -tempRight;
- theErr = ASoundSetVolume (theSoundInfo, tempLeft+leftVol, tempRight+rightVol);
- }
- }
- else {
- theErr = kNilPtrErr;
- }
-
- if (theErr != noErr) {
- DebugPrint ("\pError in ASoundChangeVolume");
- }
-
- return theErr;
- }
-
- /*
- Purpose: Gets the volume of the currently playing sound.
- Side Effects: None.
- */
- /*-----------------------------------------------------------------------*/
- OSErr ASoundGetVolume (SoundInfoPtr theSoundInfo,
- unsigned short *leftVol,
- unsigned short *rightVol)
- /*-----------------------------------------------------------------------*/
- {
- SndCommand theCmd = {getVolumeCmd, kInit, kInit};
- unsigned long theVol = kInit;
- OSErr theErr = noErr;
-
- if (StrictIsValid (theSoundInfo)) {
- theCmd.param2 = (long)&theVol;
- theErr = SndDoImmediate(theSoundInfo->chan, &theCmd);
-
- if (theErr == noErr) {
- *leftVol = theVol & kLeftMask;
- *rightVol = theVol >> kSixteen;
- }
- }
- else {
- theErr = kNilPtrErr;
- }
-
- if (theErr != noErr) {
- DebugPrint ("\pError in ASoundGetVolume");
- }
-
- return theErr;
- }
-
- /*
- Purpose: Sets the volume of the currently playing sound.
- Side Effects: None.
- */
- /*-----------------------------------------------------------------------*/
- OSErr ASoundSetVolume (SoundInfoPtr theSoundInfo,
- unsigned short leftVol,
- unsigned short rightVol)
- /*-----------------------------------------------------------------------*/
- {
- SndCommand theCmd = {volumeCmd, kInit, kInit};
- OSErr theErr = noErr;
-
- if (StrictIsValid (theSoundInfo)) {
- theCmd.param2 = (rightVol << kSixteen) | leftVol;
- theErr = SndDoImmediate(theSoundInfo->chan, &theCmd);
- }
- else {
- theErr = kNilPtrErr;
- }
-
- if (theErr != noErr) {
- DebugPrint ("\pError in ASoundSetVolume");
- }
-
- return theErr;
- }
-
- /*
- Purpose: Gets the rate multiplier of the currently playing sound.
- Side Effects: None.
- */
- /*-----------------------------------------------------------------------*/
- OSErr ASoundGetRateMul (SoundInfoPtr theSoundInfo,
- UnsignedFixed *theRateMul)
- /*-----------------------------------------------------------------------*/
- {
- SndCommand theCmd = {getRateMultiplierCmd, kInit, kInit};
- OSErr theErr = noErr;
-
- if (StrictIsValid (theSoundInfo)) {
- theCmd.param2 = (long)theRateMul;
- theErr = SndDoImmediate(theSoundInfo->chan, &theCmd);
- }
- else {
- theErr = kNilPtrErr;
- }
-
- if (theErr != noErr) {
- DebugPrint ("\pError in ASoundGetRateMul");
- }
-
- return theErr;
- }
-
- /*
- Purpose: Gets the rate multiplier of the currently playing sound.
- Side Effects: None.
- */
- /*-----------------------------------------------------------------------*/
- OSErr ASoundSetRateMul (SoundInfoPtr theSoundInfo,
- UnsignedFixed theRateMul)
- /*-----------------------------------------------------------------------*/
- {
- SndCommand theCmd = {rateMultiplierCmd, kInit, kInit};
- OSErr theErr = noErr;
-
- if (StrictIsValid (theSoundInfo)) {
- theCmd.param2 = (long)theRateMul;
- theErr = SndDoImmediate(theSoundInfo->chan, &theCmd);
- }
- else {
- theErr = kNilPtrErr;
- }
-
- if (theErr != noErr) {
- DebugPrint ("\pError in ASoundSetRateMul");
- }
-
- return theErr;
- }
-