bool PlayBuffer::open() { close(); # ifdef NNT_MACH OSStatus sta = AudioFileOpenWithCallbacks(this, private_type::HandlerRead, private_type::HandlerWrite, private_type::HandlerGetSize, private_type::HandlerSetSize, type, &stm); if (sta != 0) { trace_fmt("failed to open buffer, %.4s", (char*)&sta); return false; } sta = ExtAudioFileWrapAudioFileID(stm, false, &d_ptr->extstm); if (sta != 0) { trace_fmt("failed to wrap buffer, %.4s", (char*)&sta); return false; } return d_ptr->refresh(); # endif return false; }
CoreAudioReader (InputStream* const inp) : AudioFormatReader (inp, TRANS (coreAudioFormatName)), ok (false), lastReadPosition (0) { usesFloatingPointData = true; bitsPerSample = 32; OSStatus status = AudioFileOpenWithCallbacks (this, &readCallback, nullptr, // write needs to be null to avoid permisisions errors &getSizeCallback, nullptr, // setSize needs to be null to avoid permisisions errors 0, // AudioFileTypeID inFileTypeHint &audioFileID); if (status == noErr) { status = ExtAudioFileWrapAudioFileID (audioFileID, false, &audioFileRef); if (status == noErr) { AudioStreamBasicDescription sourceAudioFormat; UInt32 audioStreamBasicDescriptionSize = sizeof (AudioStreamBasicDescription); ExtAudioFileGetProperty (audioFileRef, kExtAudioFileProperty_FileDataFormat, &audioStreamBasicDescriptionSize, &sourceAudioFormat); numChannels = sourceAudioFormat.mChannelsPerFrame; sampleRate = sourceAudioFormat.mSampleRate; UInt32 sizeOfLengthProperty = sizeof (int64); ExtAudioFileGetProperty (audioFileRef, kExtAudioFileProperty_FileLengthFrames, &sizeOfLengthProperty, &lengthInSamples); destinationAudioFormat.mSampleRate = sampleRate; destinationAudioFormat.mFormatID = kAudioFormatLinearPCM; destinationAudioFormat.mFormatFlags = kLinearPCMFormatFlagIsFloat | kLinearPCMFormatFlagIsNonInterleaved | kAudioFormatFlagsNativeEndian; destinationAudioFormat.mBitsPerChannel = sizeof (float) * 8; destinationAudioFormat.mChannelsPerFrame = numChannels; destinationAudioFormat.mBytesPerFrame = sizeof (float); destinationAudioFormat.mFramesPerPacket = 1; destinationAudioFormat.mBytesPerPacket = destinationAudioFormat.mFramesPerPacket * destinationAudioFormat.mBytesPerFrame; status = ExtAudioFileSetProperty (audioFileRef, kExtAudioFileProperty_ClientDataFormat, sizeof (AudioStreamBasicDescription), &destinationAudioFormat); if (status == noErr) { bufferList.malloc (1, sizeof (AudioBufferList) + numChannels * sizeof (AudioBuffer)); bufferList->mNumberBuffers = numChannels; ok = true; } } } }
AudioFileReader::AudioFileReader(const void* data, size_t dataSize) : m_data(data) , m_dataSize(dataSize) , m_audioFileID(0) , m_extAudioFileRef(0) { OSStatus result = AudioFileOpenWithCallbacks(this, readProc, 0, getSizeProc, 0, 0, &m_audioFileID); if (result != noErr) return; result = ExtAudioFileWrapAudioFileID(m_audioFileID, false, &m_extAudioFileRef); if (result != noErr) m_extAudioFileRef = 0; }
bool nuiAudioDecoderPrivate::Init() { AudioFileTypeID typeID = 0; // we only want to read (not write) so give NULL for write callbacks (seems to work...) OSStatus err = AudioFileOpenWithCallbacks(&mrStream, &MyAudioFile_ReadProc, NULL, &MyAudioFile_GetSizeProc, NULL, typeID, &mAudioFileID); if (err != noErr) return false; err = ExtAudioFileWrapAudioFileID(mAudioFileID, false /*not for writing*/, &mExtAudioFileRef); return (err == noErr); }
ExtAFSource::ExtAFSource(const std::shared_ptr<FILE> &fp) : m_fp(fp) { AudioFileID afid; void *ctx = reinterpret_cast<void*>(fileno(fp.get())); CHECKCA(AudioFileOpenWithCallbacks(ctx, audiofile::read, 0, audiofile::size, 0, 0, &afid)); m_af.attach(afid, true); ExtAudioFileRef eaf; CHECKCA(ExtAudioFileWrapAudioFileID(m_af, false, &eaf)); m_eaf.attach(eaf, true); std::vector<AudioFormatListItem> aflist; m_af.getFormatList(&aflist); m_iasbd = aflist[0].mASBD; if (m_iasbd.mFormatID != 'lpcm' && m_iasbd.mFormatID != 'alac' && m_iasbd.mFormatID != '.mp3') throw std::runtime_error("Not supported input format"); uint32_t fcc = m_af.getFileFormat(); if (m_iasbd.mFormatID == 'lpcm') { bool isfloat = m_iasbd.mFormatFlags & kAudioFormatFlagIsFloat; uint32_t bits = m_iasbd.mBytesPerFrame / m_iasbd.mChannelsPerFrame * 8; m_asbd = cautil::buildASBDForPCM2(m_iasbd.mSampleRate, m_iasbd.mChannelsPerFrame, m_iasbd.mBitsPerChannel, isfloat ? bits : 32, isfloat ? kAudioFormatFlagIsFloat : kAudioFormatFlagIsSignedInteger); } else if (m_iasbd.mFormatID == 'alac') { unsigned bits_per_channel; { unsigned tab[] = { 16, 20, 24, 32 }; unsigned index = (m_iasbd.mFormatFlags - 1) & 0x3; bits_per_channel = tab[index]; } m_asbd = cautil::buildASBDForPCM2(m_iasbd.mSampleRate, m_iasbd.mChannelsPerFrame, bits_per_channel, 32, kAudioFormatFlagIsSignedInteger); } else { m_asbd = cautil::buildASBDForPCM2(m_iasbd.mSampleRate, m_iasbd.mChannelsPerFrame, 32, 32, kAudioFormatFlagIsFloat); } m_eaf.setClientDataFormat(m_asbd); std::shared_ptr<AudioChannelLayout> acl; try { m_af.getChannelLayout(&acl); chanmap::getChannels(acl.get(), &m_chanmap); } catch (...) {} /* Let AudioFile scan the file and generate index in case of MP3. * Take up about 1s for 35min MP3 in my environment, but this is * mandatory to obtain sample accurate information. */ m_af.getMaximumPacketSize(); int64_t length = m_af.getAudioDataPacketCount() * m_iasbd.mFramesPerPacket; if (fcc == kAudioFileAIFFType || fcc == kAudioFileAIFCType) ID3::fetchAiffID3Tags(fileno(m_fp.get()), &m_tags); else if (fcc == kAudioFileMP3Type) ID3::fetchMPEGID3Tags(fileno(m_fp.get()), &m_tags); else { try { audiofile::fetchTags(m_af, m_fp.get(), &m_tags); } catch (...) {} } try { AudioFilePacketTableInfo ptinfo = { 0 }; m_af.getPacketTableInfo(&ptinfo); int64_t total = ptinfo.mNumberValidFrames + ptinfo.mPrimingFrames + ptinfo.mRemainderFrames; length = (total == length / 2) ? ptinfo.mNumberValidFrames * 2 : ptinfo.mNumberValidFrames; } catch (CoreAudioException &e) { if (!e.isNotSupportedError()) throw; } m_length = length; }
static int CoreAudio_open(Sound_Sample *sample, const char *ext) { CoreAudioFileContainer* core_audio_file_container; AudioFileID* audio_file_id; OSStatus error_result; Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; AudioStreamBasicDescription actual_format; AudioStreamBasicDescription output_format; Float64 estimated_duration; UInt32 format_size; core_audio_file_container = (CoreAudioFileContainer*)malloc(sizeof(CoreAudioFileContainer)); BAIL_IF_MACRO(core_audio_file_container == NULL, ERR_OUT_OF_MEMORY, 0); audio_file_id = (AudioFileID*)malloc(sizeof(AudioFileID)); BAIL_IF_MACRO(audio_file_id == NULL, ERR_OUT_OF_MEMORY, 0); error_result = AudioFileOpenWithCallbacks( internal->rw, CoreAudio_ReadCallback, NULL, CoreAudio_SizeCallback, NULL, CoreAudio_GetAudioTypeForExtension(ext), audio_file_id ); if (error_result != noErr) { AudioFileClose(*audio_file_id); free(audio_file_id); free(core_audio_file_container); SNDDBG(("Core Audio: can't grok data. reason: [%s].\n", CoreAudio_FourCCToString(error_result))); BAIL_MACRO("Core Audio: Not valid audio data.", 0); } /* if */ format_size = sizeof(actual_format); error_result = AudioFileGetProperty( *audio_file_id, kAudioFilePropertyDataFormat, &format_size, &actual_format ); if (error_result != noErr) { AudioFileClose(*audio_file_id); free(audio_file_id); free(core_audio_file_container); SNDDBG(("Core Audio: AudioFileGetProperty failed. reason: [%s]", CoreAudio_FourCCToString(error_result))); BAIL_MACRO("Core Audio: Not valid audio data.", 0); } /* if */ format_size = sizeof(estimated_duration); error_result = AudioFileGetProperty( *audio_file_id, kAudioFilePropertyEstimatedDuration, &format_size, &estimated_duration ); if (error_result != noErr) { AudioFileClose(*audio_file_id); free(audio_file_id); free(core_audio_file_container); SNDDBG(("Core Audio: AudioFileGetProperty failed. reason: [%s].\n", CoreAudio_FourCCToString(error_result))); BAIL_MACRO("Core Audio: Not valid audio data.", 0); } /* if */ core_audio_file_container->audioFileID = audio_file_id; internal->decoder_private = core_audio_file_container; sample->flags = SOUND_SAMPLEFLAG_CANSEEK; sample->actual.rate = (UInt32) actual_format.mSampleRate; sample->actual.channels = (UInt8)actual_format.mChannelsPerFrame; internal->total_time = (SInt32)(estimated_duration * 1000.0 + 0.5); #if 0 /* FIXME: Both Core Audio and SDL 1.3 support float and 32-bit formats */ if(actual_format.mFormatFlags & kAudioFormatFlagIsBigEndian) { if(16 == actual_format.mBitsPerChannel) { if(kAudioFormatFlagIsSignedInteger & actual_format.mFormatFlags) { sample->actual.format = AUDIO_S16MSB; } else { sample->actual.format = AUDIO_U16MSB; } } else if(8 == actual_format.mBitsPerChannel) { if(kAudioFormatFlagIsSignedInteger & actual_format.mFormatFlags) { sample->actual.format = AUDIO_S8; } else { sample->actual.format = AUDIO_U8; } } else // might be 0 for undefined? { // This case seems to come up a lot for me. Maybe for file types like .m4a? sample->actual.format = AUDIO_S16SYS; SNDDBG(("Core Audio: Unsupported actual_format.mBitsPerChannel: [%d].\n", actual_format.mBitsPerChannel)); } } else // little endian { if(16 == actual_format.mBitsPerChannel) { if(kAudioFormatFlagIsSignedInteger & actual_format.mFormatFlags) { sample->actual.format = AUDIO_S16LSB; } else { sample->actual.format = AUDIO_U16LSB; } } else if(8 == actual_format.mBitsPerChannel) { if(kAudioFormatFlagIsSignedInteger & actual_format.mFormatFlags) { sample->actual.format = AUDIO_S8; } else { sample->actual.format = AUDIO_U8; } } else // might be 0 for undefined? { sample->actual.format = AUDIO_S16SYS; SNDDBG(("Core Audio: Unsupported actual_format.mBitsPerChannel: [%d].\n", actual_format.mBitsPerChannel)); } } #else /* * I want to use Core Audio to do conversion and decoding for performance reasons. * This is particularly important on mobile devices like iOS. * Taking from the Ogg Vorbis decode, I pretend the "actual" format is the same * as the desired format. */ sample->actual.format = (sample->desired.format == 0) ? AUDIO_S16SYS : sample->desired.format; #endif SNDDBG(("CoreAudio: channels == (%d).\n", sample->actual.channels)); SNDDBG(("CoreAudio: sampling rate == (%d).\n",sample->actual.rate)); SNDDBG(("CoreAudio: total seconds of sample == (%d).\n", internal->total_time)); SNDDBG(("CoreAudio: sample->actual.format == (%d).\n", sample->actual.format)); error_result = ExtAudioFileWrapAudioFileID(*audio_file_id, false, // set to false for read-only &core_audio_file_container->extAudioFileRef ); if(error_result != noErr) { AudioFileClose(*audio_file_id); free(audio_file_id); free(core_audio_file_container); SNDDBG(("Core Audio: can't wrap data. reason: [%s].\n", CoreAudio_FourCCToString(error_result))); BAIL_MACRO("Core Audio: Failed to wrap data.", 0); } /* if */ /* The output format must be linear PCM because that's the only type OpenAL knows how to deal with. * Set the client format to 16 bit signed integer (native-endian) data because that is the most * optimal format on iPhone/iPod Touch hardware. * Maintain the channel count and sample rate of the original source format. */ output_format.mSampleRate = actual_format.mSampleRate; // preserve the original sample rate output_format.mChannelsPerFrame = actual_format.mChannelsPerFrame; // preserve the number of channels output_format.mFormatID = kAudioFormatLinearPCM; // We want linear PCM data output_format.mFramesPerPacket = 1; // We know for linear PCM, the definition is 1 frame per packet if(sample->desired.format == 0) { // do AUDIO_S16SYS output_format.mFormatFlags = kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; // I seem to read failures problems without kAudioFormatFlagIsPacked. From a mailing list post, this seems to be a Core Audio bug. output_format.mBitsPerChannel = 16; // We know we want 16-bit } else { output_format.mFormatFlags = 0; // clear flags output_format.mFormatFlags |= kAudioFormatFlagIsPacked; // I seem to read failures problems without kAudioFormatFlagIsPacked. From a mailing list post, this seems to be a Core Audio bug. // Mask against bitsize if(0xFF & sample->desired.format) { output_format.mBitsPerChannel = 16; /* 16-bit */ } else { output_format.mBitsPerChannel = 8; /* 8-bit */ } // Mask for signed/unsigned if((1<<15) & sample->desired.format) { output_format.mFormatFlags = output_format.mFormatFlags | kAudioFormatFlagIsSignedInteger; } else { // no flag set for unsigned } // Mask for big/little endian if((1<<12) & sample->desired.format) { output_format.mFormatFlags = output_format.mFormatFlags | kAudioFormatFlagIsBigEndian; } else { // no flag set for little endian } } output_format.mBytesPerPacket = output_format.mBitsPerChannel/8 * output_format.mChannelsPerFrame; // e.g. 16-bits/8 * channels => so 2-bytes per channel per frame output_format.mBytesPerFrame = output_format.mBitsPerChannel/8 * output_format.mChannelsPerFrame; // For PCM, since 1 frame is 1 packet, it is the same as mBytesPerPacket /* output_format.mSampleRate = actual_format.mSampleRate; // preserve the original sample rate output_format.mChannelsPerFrame = actual_format.mChannelsPerFrame; // preserve the number of channels output_format.mFormatID = kAudioFormatLinearPCM; // We want linear PCM data // output_format.mFormatFlags = kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked | kAudioFormatFlagIsSignedInteger; output_format.mFormatFlags = kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsSignedInteger; output_format.mFramesPerPacket = 1; // We know for linear PCM, the definition is 1 frame per packet output_format.mBitsPerChannel = 16; // We know we want 16-bit output_format.mBytesPerPacket = 2 * output_format.mChannelsPerFrame; // We know we are using 16-bit, so 2-bytes per channel per frame output_format.mBytesPerFrame = 2 * output_format.mChannelsPerFrame; // For PCM, since 1 frame is 1 packet, it is the same as mBytesPerPacket */ SNDDBG(("output_format: mSampleRate: %lf\n", output_format.mSampleRate)); SNDDBG(("output_format: mChannelsPerFrame: %d\n", output_format.mChannelsPerFrame)); SNDDBG(("output_format: mFormatID: %d\n", output_format.mFormatID)); SNDDBG(("output_format: mFormatFlags: %d\n", output_format.mFormatFlags)); SNDDBG(("output_format: mFramesPerPacket: %d\n", output_format.mFramesPerPacket)); SNDDBG(("output_format: mBitsPerChannel: %d\n", output_format.mBitsPerChannel)); SNDDBG(("output_format: mBytesPerPacket: %d\n", output_format.mBytesPerPacket)); SNDDBG(("output_format: mBytesPerFrame: %d\n", output_format.mBytesPerFrame)); /* Set the desired client (output) data format */ error_result = ExtAudioFileSetProperty(core_audio_file_container->extAudioFileRef, kExtAudioFileProperty_ClientDataFormat, sizeof(output_format), &output_format); if(noErr != error_result) { ExtAudioFileDispose(core_audio_file_container->extAudioFileRef); AudioFileClose(*audio_file_id); free(audio_file_id); free(core_audio_file_container); SNDDBG(("Core Audio: ExtAudioFileSetProperty(kExtAudioFileProperty_ClientDataFormat) failed, reason: [%s].\n", CoreAudio_FourCCToString(error_result))); BAIL_MACRO("Core Audio: Not valid audio data.", 0); } core_audio_file_container->outputFormat = (AudioStreamBasicDescription*)malloc(sizeof(AudioStreamBasicDescription)); BAIL_IF_MACRO(core_audio_file_container->outputFormat == NULL, ERR_OUT_OF_MEMORY, 0); /* Copy the output format to the audio_description that was passed in so the * info will be returned to the user. */ memcpy(core_audio_file_container->outputFormat, &output_format, sizeof(AudioStreamBasicDescription)); return(1); } /* CoreAudio_open */
bool SFB::Audio::CoreAudioDecoder::_Open(CFErrorRef *error) { // Open the input file OSStatus result = AudioFileOpenWithCallbacks(this, myAudioFile_ReadProc, nullptr, myAudioFile_GetSizeProc, nullptr, 0, &mAudioFile); if(noErr != result) { LOGGER_CRIT("org.sbooth.AudioEngine.Decoder.CoreAudio", "AudioFileOpenWithCallbacks failed: " << result); if(error) { SFB::CFString description = CFCopyLocalizedString(CFSTR("The format of the file “%@” was not recognized."), ""); SFB::CFString failureReason = CFCopyLocalizedString(CFSTR("File Format Not Recognized"), ""); SFB::CFString recoverySuggestion = CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""); *error = CreateErrorForURL(Decoder::ErrorDomain, Decoder::InputOutputError, description, mInputSource->GetURL(), failureReason, recoverySuggestion); } return false; } result = ExtAudioFileWrapAudioFileID(mAudioFile, false, &mExtAudioFile); if(noErr != result) { LOGGER_CRIT("org.sbooth.AudioEngine.Decoder.CoreAudio", "ExtAudioFileWrapAudioFileID failed: " << result); if(error) { SFB::CFString description = CFCopyLocalizedString(CFSTR("The format of the file “%@” was not recognized."), ""); SFB::CFString failureReason = CFCopyLocalizedString(CFSTR("File Format Not Recognized"), ""); SFB::CFString recoverySuggestion = CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""); *error = CreateErrorForURL(Decoder::ErrorDomain, Decoder::InputOutputError, description, mInputSource->GetURL(), failureReason, recoverySuggestion); } result = AudioFileClose(mAudioFile); if(noErr != result) LOGGER_NOTICE("org.sbooth.AudioEngine.Decoder.CoreAudio", "AudioFileClose failed: " << result); mAudioFile = nullptr; return false; } // Query file format UInt32 dataSize = sizeof(mSourceFormat); result = ExtAudioFileGetProperty(mExtAudioFile, kExtAudioFileProperty_FileDataFormat, &dataSize, &mSourceFormat); if(noErr != result) { LOGGER_CRIT("org.sbooth.AudioEngine.Decoder.CoreAudio", "ExtAudioFileGetProperty (kExtAudioFileProperty_FileDataFormat) failed: " << result); result = ExtAudioFileDispose(mExtAudioFile); if(noErr != result) LOGGER_NOTICE("org.sbooth.AudioEngine.Decoder.CoreAudio", "ExtAudioFileDispose failed: " << result); result = AudioFileClose(mAudioFile); if(noErr != result) LOGGER_NOTICE("org.sbooth.AudioEngine.Decoder.CoreAudio", "AudioFileClose failed: " << result); mAudioFile = nullptr; mExtAudioFile = nullptr; return false; } // Tell the ExtAudioFile the format in which we'd like our data // For Linear PCM formats, leave the data untouched if(kAudioFormatLinearPCM == mSourceFormat.mFormatID) mFormat = mSourceFormat; // For Apple Lossless, convert to high-aligned signed ints in 32 bits else if(kAudioFormatAppleLossless == mSourceFormat.mFormatID) { mFormat.mFormatID = kAudioFormatLinearPCM; mFormat.mFormatFlags = kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsAlignedHigh; mFormat.mSampleRate = mSourceFormat.mSampleRate; mFormat.mChannelsPerFrame = mSourceFormat.mChannelsPerFrame; if(kAppleLosslessFormatFlag_16BitSourceData == mSourceFormat.mFormatFlags) mFormat.mBitsPerChannel = 16; else if(kAppleLosslessFormatFlag_20BitSourceData == mSourceFormat.mFormatFlags) mFormat.mBitsPerChannel = 20; else if(kAppleLosslessFormatFlag_24BitSourceData == mSourceFormat.mFormatFlags) mFormat.mBitsPerChannel = 24; else if(kAppleLosslessFormatFlag_32BitSourceData == mSourceFormat.mFormatFlags) mFormat.mBitsPerChannel = 32; mFormat.mBytesPerPacket = 4 * mFormat.mChannelsPerFrame; mFormat.mFramesPerPacket = 1; mFormat.mBytesPerFrame = mFormat.mBytesPerPacket * mFormat.mFramesPerPacket; mFormat.mReserved = 0; } // For all other formats convert to the canonical Core Audio format else { mFormat.mFormatID = kAudioFormatLinearPCM; mFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kAudioFormatFlagIsNonInterleaved; mFormat.mSampleRate = mSourceFormat.mSampleRate; mFormat.mChannelsPerFrame = mSourceFormat.mChannelsPerFrame; mFormat.mBitsPerChannel = 32; mFormat.mBytesPerPacket = (mFormat.mBitsPerChannel / 8); mFormat.mFramesPerPacket = 1; mFormat.mBytesPerFrame = mFormat.mBytesPerPacket * mFormat.mFramesPerPacket; mFormat.mReserved = 0; } result = ExtAudioFileSetProperty(mExtAudioFile, kExtAudioFileProperty_ClientDataFormat, sizeof(mFormat), &mFormat); if(noErr != result) { LOGGER_CRIT("org.sbooth.AudioEngine.Decoder.CoreAudio", "ExtAudioFileSetProperty (kExtAudioFileProperty_ClientDataFormat) failed: " << result); result = ExtAudioFileDispose(mExtAudioFile); if(noErr != result) LOGGER_NOTICE("org.sbooth.AudioEngine.Decoder.CoreAudio", "ExtAudioFileDispose failed: " << result); result = AudioFileClose(mAudioFile); if(noErr != result) LOGGER_NOTICE("org.sbooth.AudioEngine.Decoder.CoreAudio", "AudioFileClose failed: " << result); mAudioFile = nullptr; mExtAudioFile = nullptr; return false; } // Setup the channel layout // There is a bug in EAF where if the underlying AF doesn't return a channel layout it returns an empty struct // result = ExtAudioFileGetPropertyInfo(mExtAudioFile, kExtAudioFileProperty_FileChannelLayout, &dataSize, nullptr); result = AudioFileGetPropertyInfo(mAudioFile, kAudioFilePropertyChannelLayout, &dataSize, nullptr); if(noErr == result) { auto channelLayout = (AudioChannelLayout *)malloc(dataSize); // result = ExtAudioFileGetProperty(mExtAudioFile, kExtAudioFileProperty_FileChannelLayout, &dataSize, mChannelLayout); result = AudioFileGetProperty(mAudioFile, kAudioFilePropertyChannelLayout, &dataSize, channelLayout); if(noErr != result) { // LOGGER_ERR("org.sbooth.AudioEngine.Decoder.CoreAudio", "ExtAudioFileGetProperty (kExtAudioFileProperty_FileChannelLayout) failed: " << result); LOGGER_ERR("org.sbooth.AudioEngine.Decoder.CoreAudio", "AudioFileGetProperty (kAudioFilePropertyChannelLayout) failed: " << result); free(channelLayout); result = ExtAudioFileDispose(mExtAudioFile); if(noErr != result) LOGGER_NOTICE("org.sbooth.AudioEngine.Decoder.CoreAudio", "ExtAudioFileDispose failed: " << result); result = AudioFileClose(mAudioFile); if(noErr != result) LOGGER_NOTICE("org.sbooth.AudioEngine.Decoder.CoreAudio", "AudioFileClose failed: " << result); mAudioFile = nullptr; mExtAudioFile = nullptr; return false; } mChannelLayout = channelLayout; free(channelLayout); } else // LOGGER_ERR("org.sbooth.AudioEngine.Decoder.CoreAudio", "ExtAudioFileGetPropertyInfo (kExtAudioFileProperty_FileChannelLayout) failed: " << result); LOGGER_ERR("org.sbooth.AudioEngine.Decoder.CoreAudio", "AudioFileGetPropertyInfo (kAudioFilePropertyChannelLayout) failed: " << result); // Work around bugs in ExtAudioFile: http://lists.apple.com/archives/coreaudio-api/2009/Nov/msg00119.html // Synopsis: ExtAudioFileTell() and ExtAudioFileSeek() are broken for m4a files AudioFileID audioFile; dataSize = sizeof(audioFile); result = ExtAudioFileGetProperty(mExtAudioFile, kExtAudioFileProperty_AudioFile, &dataSize, &audioFile); if(noErr != result) { LOGGER_ERR("org.sbooth.AudioEngine.Decoder.CoreAudio", "ExtAudioFileGetProperty (kExtAudioFileProperty_AudioFile) failed: " << result); result = ExtAudioFileDispose(mExtAudioFile); if(noErr != result) LOGGER_NOTICE("org.sbooth.AudioEngine.Decoder.CoreAudio", "ExtAudioFileDispose failed: " << result); result = AudioFileClose(mAudioFile); if(noErr != result) LOGGER_NOTICE("org.sbooth.AudioEngine.Decoder.CoreAudio", "AudioFileClose failed: " << result); mAudioFile = nullptr; mExtAudioFile = nullptr; return false; } AudioFileTypeID fileFormat; dataSize = sizeof(fileFormat); result = AudioFileGetProperty(audioFile, kAudioFilePropertyFileFormat, &dataSize, &fileFormat); if(noErr != result) { LOGGER_ERR("org.sbooth.AudioEngine.Decoder.CoreAudio", "AudioFileGetProperty (kAudioFilePropertyFileFormat) failed: " << result); result = ExtAudioFileDispose(mExtAudioFile); if(noErr != result) LOGGER_NOTICE("org.sbooth.AudioEngine.Decoder.CoreAudio", "ExtAudioFileDispose failed: " << result); result = AudioFileClose(mAudioFile); if(noErr != result) LOGGER_NOTICE("org.sbooth.AudioEngine.Decoder.CoreAudio", "AudioFileClose failed: " << result); mAudioFile = nullptr; mExtAudioFile = nullptr; return false; } if(kAudioFileM4AType == fileFormat || kAudioFileMPEG4Type == fileFormat || kAudioFileAAC_ADTSType == fileFormat) mUseM4AWorkarounds = true; #if 0 // This was supposed to determine if ExtAudioFile had been fixed, but even though // it passes on 10.6.2 things are not behaving properly SInt64 currentFrame = -1; result = ExtAudioFileTell(mExtAudioFile, ¤tFrame); if(noErr != result) { LOGGER_ERR("org.sbooth.AudioEngine.Decoder.CoreAudio", "ExtAudioFileTell failed: " << result); result = ExtAudioFileDispose(mExtAudioFile); if(noErr != result) LOGGER_NOTICE("org.sbooth.AudioEngine.Decoder.CoreAudio", "ExtAudioFileDispose failed: " << result); result = AudioFileClose(mAudioFile); if(noErr != result) LOGGER_NOTICE("org.sbooth.AudioEngine.Decoder.CoreAudio", "AudioFileClose failed: " << result); mAudioFile = nullptr; mExtAudioFile = nullptr; return false; } if(0 > currentFrame) mUseM4AWorkarounds = true; #endif return true; }