static void ASBD_NtoB(const AudioStreamBasicDescription *infmt, AudioStreamBasicDescription *outfmt) { *(UInt64 *)&outfmt->mSampleRate = EndianU64_NtoB(*(UInt64 *)&infmt->mSampleRate); outfmt->mFormatID = EndianU32_NtoB(infmt->mFormatID); outfmt->mFormatFlags = EndianU32_NtoB(infmt->mFormatFlags); outfmt->mBytesPerPacket = EndianU32_NtoB(infmt->mBytesPerPacket); outfmt->mFramesPerPacket = EndianU32_NtoB(infmt->mFramesPerPacket); outfmt->mBytesPerFrame = EndianU32_NtoB(infmt->mBytesPerFrame); outfmt->mChannelsPerFrame = EndianU32_NtoB(infmt->mChannelsPerFrame); outfmt->mBitsPerChannel = EndianU32_NtoB(infmt->mBitsPerChannel); }
//FLAC__StreamMetadata_StreamInfo void ACFLACCodec::GetMagicCookie(void* outMagicCookieData, UInt32& ioMagicCookieDataByteSize) const { Byte * buffer; Byte * currPtr; AudioFormatAtom * frmaAtom; FullAtomHeader * flacAtom; AudioTerminatorAtom * termAtom; SInt32 atomSize; UInt32 flacSize; UInt32 chanSize; UInt32 frmaSize; UInt32 termSize; FLAC__StreamMetadata_StreamInfo * config; OSStatus status; UInt32 tempMaxFrameBytes; //RequireAction( sampleDesc != nil, return paramErr; ); config = nil; frmaSize = sizeof(AudioFormatAtom); flacSize = sizeof(FullAtomHeader) + sizeof(FLAC__StreamMetadata_StreamInfo); chanSize = 0; termSize = sizeof(AudioTerminatorAtom); // if we're encoding more than two channels, add an AudioChannelLayout atom to describe the layout if ( mOutputFormat.mChannelsPerFrame > 2 ) { chanSize = sizeof(FullAtomHeader) + offsetof(AudioChannelLayout, mChannelDescriptions); } // create buffer of the required size atomSize = frmaSize + flacSize + chanSize + termSize; // Someone might have a stereo/mono cookie while we're trying to do surround. if ((UInt32)atomSize > ioMagicCookieDataByteSize) { CODEC_THROW(kAudioCodecBadPropertySizeError); } tempMaxFrameBytes = kInputBufferPackets * mOutputFormat.mChannelsPerFrame * ((10 + kMaxSampleSize) / 8) + 1; buffer = (Byte *)calloc( atomSize, 1 ); currPtr = buffer; // fill in the atom stuff frmaAtom = (AudioFormatAtom *) currPtr; frmaAtom->size = EndianU32_NtoB( frmaSize ); frmaAtom->atomType = EndianU32_NtoB( kAudioFormatAtomType ); frmaAtom->format = EndianU32_NtoB( 'flac' ); currPtr += frmaSize; // fill in the FLAC config flacAtom = (FullAtomHeader *) currPtr; flacAtom->size = EndianU32_NtoB( flacSize ); flacAtom->type = EndianU32_NtoB( 'flac' ); flacAtom->versionFlags = 0; currPtr += sizeof(FullAtomHeader); /* unsigned min_blocksize, max_blocksize; unsigned min_framesize, max_framesize; unsigned sample_rate; unsigned channels; unsigned bits_per_sample; FLAC__uint64 total_samples; FLAC__byte md5sum[16]; */ config = (FLAC__StreamMetadata_StreamInfo *) currPtr; if (mCookieDefined) { config->min_blocksize = EndianU32_NtoB( mStreamInfo.min_blocksize ); config->max_blocksize = EndianU32_NtoB( mStreamInfo.max_blocksize ); config->min_framesize = EndianU32_NtoB( mStreamInfo.min_framesize ); config->max_framesize = EndianU32_NtoB( mStreamInfo.max_framesize ); config->sample_rate = EndianU32_NtoB( mStreamInfo.sample_rate ); config->channels = EndianU32_NtoB( mStreamInfo.channels ); config->bits_per_sample = EndianU32_NtoB( mStreamInfo.bits_per_sample ); config->total_samples = EndianU64_NtoB( mStreamInfo.total_samples ); config->md5sum[0] = mStreamInfo.md5sum[0]; config->md5sum[1] = mStreamInfo.md5sum[1]; config->md5sum[2] = mStreamInfo.md5sum[2]; config->md5sum[3] = mStreamInfo.md5sum[3]; config->md5sum[4] = mStreamInfo.md5sum[4]; config->md5sum[5] = mStreamInfo.md5sum[5]; config->md5sum[6] = mStreamInfo.md5sum[6]; config->md5sum[7] = mStreamInfo.md5sum[7]; config->md5sum[8] = mStreamInfo.md5sum[8]; config->md5sum[9] = mStreamInfo.md5sum[9]; config->md5sum[10] = mStreamInfo.md5sum[10]; config->md5sum[11] = mStreamInfo.md5sum[11]; config->md5sum[12] = mStreamInfo.md5sum[12]; config->md5sum[13] = mStreamInfo.md5sum[13]; config->md5sum[14] = mStreamInfo.md5sum[14]; config->md5sum[15] = mStreamInfo.md5sum[15]; } else { config->min_blocksize = EndianU32_NtoB( kFLACDefaultFrameSize ); config->max_blocksize = EndianU32_NtoB( kFLACDefaultFrameSize ); config->min_framesize = EndianU32_NtoB( 0 ); config->max_framesize = EndianU32_NtoB( 0 ); config->sample_rate = EndianU32_NtoB( (UInt32)(mOutputFormat.mSampleRate) ); config->channels = EndianU32_NtoB(mOutputFormat.mChannelsPerFrame); config->bits_per_sample = EndianU32_NtoB(mBitDepth); config->total_samples = 0; config->md5sum[0] = 0; config->md5sum[1] = 0; config->md5sum[2] = 0; config->md5sum[3] = 0; config->md5sum[4] = 0; config->md5sum[5] = 0; config->md5sum[6] = 0; config->md5sum[7] = 0; config->md5sum[8] = 0; config->md5sum[9] = 0; config->md5sum[10] = 0; config->md5sum[11] = 0; config->md5sum[12] = 0; config->md5sum[13] = 0; config->md5sum[14] = 0; config->md5sum[15] = 0; } currPtr += sizeof(FLAC__StreamMetadata_StreamInfo); // if we're encoding more than two channels, add an AudioChannelLayout atom to describe the layout // Unfortunately there is no way to avoid dealing with an atom here if ( mOutputFormat.mChannelsPerFrame > 2 ) { AudioChannelLayoutTag tag; FullAtomHeader * chan; AudioChannelLayout * layout; chan = (FullAtomHeader *) currPtr; chan->size = EndianU32_NtoB( chanSize ); chan->type = EndianU32_NtoB( AudioChannelLayoutAID ); // version flags == 0 currPtr += sizeof(FullAtomHeader); // we use a predefined set of layout tags so we don't need to write any channel descriptions layout = (AudioChannelLayout *) currPtr; tag = sChannelLayoutTags[mOutputFormat.mChannelsPerFrame - 1]; layout->mChannelLayoutTag = EndianU32_NtoB( tag ); layout->mChannelBitmap = 0; layout->mNumberChannelDescriptions = 0; currPtr += offsetof(AudioChannelLayout, mChannelDescriptions); } // fill in Terminator atom header termAtom = (AudioTerminatorAtom *) currPtr; termAtom->size = EndianU32_NtoB( termSize ); termAtom->atomType = EndianU32_NtoB( kAudioTerminatorAtomType ); // all good, return the new description memcpy (outMagicCookieData, (const void *)(buffer), atomSize); ioMagicCookieDataByteSize = atomSize; status = noErr; // delete any memory we allocated if ( buffer != NULL ) { delete buffer; buffer = NULL; } }