Mercurial > sdl-ios-xcode
diff src/cdrom/macosx/AudioFilePlayer.cpp @ 768:de1b2c3063b9
Max has been reworking this code so it works on MacOS X 10.1
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sun, 04 Jan 2004 16:20:28 +0000 |
parents | 9c6717a1c66f |
children | 5c5656163ebd |
line wrap: on
line diff
--- a/src/cdrom/macosx/AudioFilePlayer.cpp Sun Jan 04 15:57:16 2004 +0000 +++ b/src/cdrom/macosx/AudioFilePlayer.cpp Sun Jan 04 16:20:28 2004 +0000 @@ -28,31 +28,9 @@ // #include "AudioFilePlayer.h" -extern const char* AudioFilePlayerErrorStr (OSStatus error) -{ - const char *str; - - switch (error) { - case kAudioFileUnspecifiedError: str = "wht?"; break; - case kAudioFileUnsupportedFileTypeError: str = "typ?"; break; - case kAudioFileUnsupportedDataFormatError: str = "fmt?"; break; - case kAudioFileUnsupportedPropertyError: str = "pty?"; break; - case kAudioFileBadPropertySizeError: str = "!siz"; break; - case kAudioFileNotOptimizedError: str = "optm"; break; - case kAudioFilePermissionsError: str = "prm?"; break; - case kAudioFileFormatNameUnavailableError: str = "nme?"; break; - case kAudioFileInvalidChunkError: str = "chk?"; break; - case kAudioFileDoesNotAllow64BitDataSizeError: str = "off?"; break; - default: str = "error unspecified"; - } - - return str; -} - void ThrowResult (OSStatus result, const char* str) { - SDL_SetError ("Error: %s %d (%s)", - str, result, AudioFilePlayerErrorStr(result)); + SDL_SetError ("Error: %s %d", str, result); throw result; } @@ -133,31 +111,25 @@ OpenFile (inFileRef, fileDataSize); // we want about a seconds worth of data for the buffer - int secsBytes = UInt32 (mFileDescription.mSampleRate * mFileDescription.mBytesPerFrame); + int bytesPerSecond = UInt32 (mFileDescription.mSampleRate * mFileDescription.mBytesPerFrame); #if DEBUG printf("File format:\n"); PrintStreamDesc (&mFileDescription); #endif - //round to a 32K boundary - //if ((secsBytes & 0xFFFF8000) > (128 * 1024)) - //secsBytes &= 0xFFFF8000; - //else - //secsBytes = (secsBytes + 0x7FFF) & 0xFFFF8000; - - mAudioFileManager = new AudioFileReaderThread (*this, - mAudioFileID, + mAudioFileManager = new AudioFileManager (*this, + mForkRefNum, fileDataSize, - secsBytes); + bytesPerSecond); } // you can put a rate scalar here to play the file faster or slower // by multiplying the same rate by the desired factor // eg fileSampleRate * 2 -> twice as fast // before you create the AudioConverter -void AudioFilePlayer::SetDestination (AudioUnit &inDestUnit, - int inBusNumber) +void AudioFilePlayer::SetDestination (AudioUnit &inDestUnit, + int inBusNumber) { if (mConnected) throw static_cast<OSStatus>(-1); //can't set dest if already engaged @@ -194,43 +166,15 @@ // we're going to use this to know which convert routine to call // a v1 audio unit will have a type of 'aunt' // a v2 audio unit will have one of several different types. - mIsAUNTUnit = (desc.componentType == kAudioUnitComponentType); - - if (!mIsAUNTUnit) { + if (desc.componentType != kAudioUnitComponentType) { result = badComponentInstance; THROW_RESULT("BAD COMPONENT") } - // HACK - the AIFF files on CDs are in little endian order! - if (mFileDescription.mFormatFlags == 0xE) - mFileDescription.mFormatFlags &= ~kAudioFormatFlagIsBigEndian; - - result = AudioConverterNew (&mFileDescription, &destDesc, &mConverter); THROW_RESULT("AudioConverterNew") - -/* - // if we have a mono source, we're going to copy each channel into - // the destination's channel source... - if (mFileDescription.mChannelsPerFrame == 1) { - - SInt32* channelMap = new SInt32 [destDesc.mChannelsPerFrame]; - for (unsigned int i = 0; i < destDesc.mChannelsPerFrame; ++i) - channelMap[i] = 0; //set first channel to all output channels - - result = AudioConverterSetProperty(mConverter, - kAudioConverterChannelMap, - (sizeof(SInt32) * destDesc.mChannelsPerFrame), - channelMap); - THROW_RESULT("AudioConverterSetProperty") - - delete [] channelMap; - } -*/ - assert (mFileDescription.mChannelsPerFrame == 2); - #if 0 // this uses the better quality SRC UInt32 srcID = kAudioUnitSRCAlgorithm_Polyphase; @@ -272,9 +216,9 @@ mAudioFileManager = 0; } - if (mAudioFileID) { - ::AudioFileClose (mAudioFileID); - mAudioFileID = 0; + if (mForkRefNum) { + FSClose (mForkRefNum); + mForkRefNum = 0; } if (mConverter) { @@ -293,18 +237,16 @@ mAudioFileManager->Connect(mConverter); // set the render callback for the file data to be supplied to the sound converter AU - if (mIsAUNTUnit) { - mInputCallback.inputProc = AudioFileManager::FileInputProc; - mInputCallback.inputProcRefCon = mAudioFileManager; + mInputCallback.inputProc = AudioFileManager::FileInputProc; + mInputCallback.inputProcRefCon = mAudioFileManager; - OSStatus result = AudioUnitSetProperty (mPlayUnit, - kAudioUnitProperty_SetInputCallback, - kAudioUnitScope_Input, - mBusNumber, - &mInputCallback, - sizeof(mInputCallback)); - THROW_RESULT("AudioUnitSetProperty") - } + OSStatus result = AudioUnitSetProperty (mPlayUnit, + kAudioUnitProperty_SetInputCallback, + kAudioUnitScope_Input, + mBusNumber, + &mInputCallback, + sizeof(mInputCallback)); + THROW_RESULT("AudioUnitSetProperty") mConnected = true; } } @@ -317,9 +259,7 @@ if (mNotifier) { (*mNotifier) (mRefCon, inStatus); - } - - else { + } else { SDL_SetError ("Notification posted with no notifier in place"); if (inStatus == kAudioFilePlay_FileIsFinished) @@ -338,40 +278,89 @@ { mConnected = false; - if (mIsAUNTUnit) { - mInputCallback.inputProc = 0; - mInputCallback.inputProcRefCon = 0; - OSStatus result = AudioUnitSetProperty (mPlayUnit, - kAudioUnitProperty_SetInputCallback, - kAudioUnitScope_Input, - mBusNumber, - &mInputCallback, - sizeof(mInputCallback)); - if (result) - SDL_SetError ("AudioUnitSetProperty:RemoveInputCallback:%ld", result); + mInputCallback.inputProc = 0; + mInputCallback.inputProcRefCon = 0; + OSStatus result = AudioUnitSetProperty (mPlayUnit, + kAudioUnitProperty_SetInputCallback, + kAudioUnitScope_Input, + mBusNumber, + &mInputCallback, + sizeof(mInputCallback)); + if (result) + SDL_SetError ("AudioUnitSetProperty:RemoveInputCallback:%ld", result); - } - mAudioFileManager->Disconnect(); } } +struct SSNDData { + UInt32 offset; + UInt32 blockSize; +}; + void AudioFilePlayer::OpenFile (const FSRef *inRef, SInt64& outFileDataSize) -{ - OSStatus result = AudioFileOpen (inRef, fsRdPerm, 0, &mAudioFileID); - THROW_RESULT("AudioFileOpen") - - UInt32 dataSize = sizeof(AudioStreamBasicDescription); - result = AudioFileGetProperty (mAudioFileID, - kAudioFilePropertyDataFormat, - &dataSize, - &mFileDescription); - THROW_RESULT("AudioFileGetProperty") - - dataSize = sizeof (SInt64); - result = AudioFileGetProperty (mAudioFileID, - kAudioFilePropertyAudioDataByteCount, - &dataSize, - &outFileDataSize); - THROW_RESULT("AudioFileGetProperty") -} \ No newline at end of file +{ + ContainerChunk chunkHeader; + ChunkHeader chunk; + SSNDData ssndData; + + OSErr result; + HFSUniStr255 dfName; + ByteCount actual; + SInt64 offset; + + // Open the data fork of the input file + result = FSGetDataForkName(&dfName); + THROW_RESULT("AudioFilePlayer::OpenFile(): FSGetDataForkName") + + result = FSOpenFork(inRef, dfName.length, dfName.unicode, fsRdPerm, &mForkRefNum); + THROW_RESULT("AudioFilePlayer::OpenFile(): FSOpenFork") + + // Read the file header, and check if it's indeed an AIFC file + result = FSReadFork(mForkRefNum, fsAtMark, 0, sizeof(chunkHeader), &chunkHeader, &actual); + THROW_RESULT("AudioFilePlayer::OpenFile(): FSReadFork") + + if (chunkHeader.ckID != 'FORM') { + result = -1; + THROW_RESULT("AudioFilePlayer::OpenFile(): chunk id is not 'FORM'"); + } + + if (chunkHeader.formType != 'AIFC') { + result = -1; + THROW_RESULT("AudioFilePlayer::OpenFile(): file format is not 'AIFC'"); + } + + // Search for the SSND chunk. We ignore all compression etc. information + // in other chunks. Of course that is kind of evil, but for now we are lazy + // and rely on the cdfs to always give us the same fixed format. + // TODO: Parse the COMM chunk we currently skip to fill in mFileDescription. + offset = 0; + do { + result = FSReadFork(mForkRefNum, fsFromMark, offset, sizeof(chunk), &chunk, &actual); + THROW_RESULT("AudioFilePlayer::OpenFile(): FSReadFork") + + // Skip the chunk data + offset = chunk.ckSize; + } while (chunk.ckID != 'SSND'); + + // Read the header of the SSND chunk. After this, we are positioned right + // at the start of the audio data. + result = FSReadFork(mForkRefNum, fsAtMark, 0, sizeof(ssndData), &ssndData, &actual); + THROW_RESULT("AudioFilePlayer::OpenFile(): FSReadFork") + + result = FSSetForkPosition(mForkRefNum, fsFromMark, ssndData.offset); + THROW_RESULT("AudioFilePlayer::OpenFile(): FSSetForkPosition") + + // Data size + outFileDataSize = chunk.ckSize - ssndData.offset; + + // File format + mFileDescription.mSampleRate = 44100; + mFileDescription.mFormatID = kAudioFormatLinearPCM; + mFileDescription.mFormatFlags = kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagIsSignedInteger; + mFileDescription.mBytesPerPacket = 4; + mFileDescription.mFramesPerPacket = 1; + mFileDescription.mBytesPerFrame = 4; + mFileDescription.mChannelsPerFrame = 2; + mFileDescription.mBitsPerChannel = 16; +}