void CAAudioFileConverter::ConvertFile(const ConversionParameters &_params) { FSRef destFSRef; UInt32 propertySize; CAStreamBasicDescription destFormat; CAAudioChannelLayout origSrcFileLayout, srcFileLayout, destFileLayout; bool openedSourceFile = false, createdOutputFile = false; mParams = _params; mReadBuffer = NULL; mReadPtrs = NULL; CABufferList *writeBuffer = NULL; CABufferList *writePtrs = NULL; PrepareConversion(); try { if (TaggedDecodingFromCAF()) ReadCAFInfo(); OpenInputFile(); openedSourceFile = true; // get input file's format const CAStreamBasicDescription &srcFormat = mSrcFile.GetFileDataFormat(); if (mParams.flags & kOpt_Verbose) { printf("Input file: %s, %qd frames\n", mParams.input.filePath ? basename(mParams.input.filePath) : "?", mSrcFile.GetNumberFrames()); } mSrcFormat = srcFormat; bool encoding = !destFormat.IsPCM(); bool decoding = !srcFormat.IsPCM(); // prepare output file's format destFormat = mParams.output.dataFormat; if (!encoding && destFormat.mSampleRate == 0.) // on encode, it's OK to have a 0 sample rate; ExtAudioFile will get the SR from the converter and set it on the file. // on decode or PCM->PCM, a sample rate of 0 is interpreted as using the source sample rate destFormat.mSampleRate = srcFormat.mSampleRate; // source channel layout srcFileLayout = mSrcFile.GetFileChannelLayout(); origSrcFileLayout = srcFileLayout; if (mParams.input.channelLayoutTag != 0) { XThrowIf(AudioChannelLayoutTag_GetNumberOfChannels(mParams.input.channelLayoutTag) != srcFormat.mChannelsPerFrame, -1, "input channel layout has wrong number of channels for file"); srcFileLayout = CAAudioChannelLayout(mParams.input.channelLayoutTag); mSrcFile.SetFileChannelLayout(srcFileLayout); } // destination channel layout int outChannels = mParams.output.channels; if (mParams.output.channelLayoutTag != 0) { // use the one specified by caller, if any destFileLayout = CAAudioChannelLayout(mParams.output.channelLayoutTag); } else if (srcFileLayout.IsValid()) { // otherwise, assume the same as the source, if any destFileLayout = srcFileLayout; } if (destFileLayout.IsValid()) { // the output channel layout specifies the number of output channels if (outChannels != -1) XThrowIf((unsigned)outChannels != destFileLayout.NumberChannels(), -1, "output channel layout has wrong number of channels"); else outChannels = destFileLayout.NumberChannels(); } if (!(mParams.flags & kOpt_NoSanitizeOutputFormat)) { // adjust the output format's channels; output.channels overrides the channels if (outChannels == -1) outChannels = srcFormat.mChannelsPerFrame; if (outChannels > 0) { destFormat.mChannelsPerFrame = outChannels; destFormat.mBytesPerPacket *= outChannels; destFormat.mBytesPerFrame *= outChannels; } // use AudioFormat API to clean up the output format propertySize = sizeof(AudioStreamBasicDescription); XThrowIfError(AudioFormatGetProperty(kAudioFormatProperty_FormatInfo, 0, NULL, &propertySize, &destFormat), "get destination format info"); } OpenOutputFile(srcFormat, destFormat, destFSRef, destFileLayout); createdOutputFile = true; mDestFormat = destFormat; // set up client formats CAStreamBasicDescription srcClientFormat, destClientFormat; { CAAudioChannelLayout srcClientLayout, destClientLayout; if (encoding) { if (decoding) { // transcoding // XThrowIf(encoding && decoding, -1, "transcoding not currently supported"); if (srcFormat.mChannelsPerFrame > 2 || destFormat.mChannelsPerFrame > 2) CAXException::Warning("Transcoding multichannel audio may not handle channel layouts correctly", 0); srcClientFormat.SetCanonical(std::min(srcFormat.mChannelsPerFrame, destFormat.mChannelsPerFrame), true); srcClientFormat.mSampleRate = std::max(srcFormat.mSampleRate, destFormat.mSampleRate); mSrcFile.SetClientFormat(srcClientFormat, NULL); destClientFormat = srcClientFormat; } else { // encoding srcClientFormat = srcFormat; destClientFormat = srcFormat; } // by here, destClientFormat will have a valid sample rate destClientLayout = srcFileLayout.IsValid() ? srcFileLayout : destFileLayout; mDestFile.SetClientFormat(destClientFormat, &destClientLayout); } else { // decoding or PCM->PCM if (destFormat.mSampleRate == 0.) destFormat.mSampleRate = srcFormat.mSampleRate; destClientFormat = destFormat; srcClientFormat = destFormat; srcClientLayout = destFileLayout; mSrcFile.SetClientFormat(srcClientFormat, &srcClientLayout); } } XThrowIf(srcClientFormat.mBytesPerPacket == 0, -1, "source client format not PCM"); XThrowIf(destClientFormat.mBytesPerPacket == 0, -1, "dest client format not PCM"); if (encoding) { // set the bitrate if (mParams.output.bitRate != -1) { if (mParams.flags & kOpt_Verbose) printf("bitrate = %ld\n", mParams.output.bitRate); mDestFile.SetConverterProperty(kAudioConverterEncodeBitRate, sizeof(UInt32), &mParams.output.bitRate); } // set the codec quality if (mParams.output.codecQuality != -1) { if (mParams.flags & kOpt_Verbose) printf("codec quality = %ld\n", mParams.output.codecQuality); mDestFile.SetConverterProperty(kAudioConverterCodecQuality, sizeof(UInt32), &mParams.output.codecQuality); } // set the bitrate strategy -- called bitrate format in the codecs since it had already shipped if (mParams.output.strategy != -1) { if (mParams.flags & kOpt_Verbose) printf("strategy = %ld\n", mParams.output.strategy); mDestFile.SetConverterProperty(kAudioCodecBitRateFormat, sizeof(UInt32), &mParams.output.strategy); } } // set the SRC quality if (mParams.output.srcQuality != -1) { if (srcFormat.mSampleRate != 0. && destFormat.mSampleRate != 0. && srcFormat.mSampleRate != destFormat.mSampleRate) { if (mParams.flags & kOpt_Verbose) printf("SRC quality = %ld\n", mParams.output.srcQuality); if (encoding) mDestFile.SetConverterProperty(kAudioConverterSampleRateConverterQuality, sizeof(UInt32), &mParams.output.srcQuality); else mSrcFile.SetConverterProperty(kAudioConverterSampleRateConverterQuality, sizeof(UInt32), &mParams.output.srcQuality); } } if (decoding) { if (mParams.output.primeMethod != -1) mSrcFile.SetConverterProperty(kAudioConverterPrimeMethod, sizeof(UInt32), &mParams.output.primeMethod); } PrintFormats(&origSrcFileLayout); // prepare I/O buffers UInt32 bytesToRead = 0x10000; UInt32 framesToRead = bytesToRead; // OK, ReadPackets will limit as appropriate ComputeReadSize(srcFormat, destFormat, bytesToRead, framesToRead); // const SInt64 totalFrames = mSrcFile.GetNumberFrames(); //#warning "GetNumberFrames() can be prohibitively slow for some formats" mReadBuffer = CABufferList::New("readbuf", srcClientFormat); mReadBuffer->AllocateBuffers(bytesToRead); mReadPtrs = CABufferList::New("readptrs", srcClientFormat); BeginConversion(); while (true) { //XThrowIf(Progress(mSrcFile.Tell(), totalFrames), userCanceledErr, "user stopped"); // this was commented out for awhile -- performance? make it optional? UInt32 nFrames = framesToRead; mReadPtrs->SetFrom(mReadBuffer); AudioBufferList *readbuf = &mReadPtrs->GetModifiableBufferList(); mSrcFile.Read(nFrames, readbuf); //printf("read %ld of %ld frames\n", nFrames, framesToRead); if (nFrames == 0) break; mDestFile.Write(nFrames, readbuf); if (ShouldTerminateConversion()) break; } if (decoding) { // fix up the destination file's length if necessary and possible SInt64 nframes = mSrcFile.GetNumberFrames(); if (nframes != 0) { // only shorten, don't try to lengthen nframes = SInt64(ceil(nframes * destFormat.mSampleRate / srcFormat.mSampleRate)); if (nframes < mDestFile.GetNumberFrames()) { mDestFile.SetNumberFrames(nframes); } } } EndConversion(); } catch (...) { delete mReadBuffer; delete mReadPtrs; delete writeBuffer; delete writePtrs; if (!createdOutputFile) PrintFormats(&origSrcFileLayout); try { mSrcFile.Close(); } catch (...) { } try { mDestFile.Close(); } catch (...) { } if (createdOutputFile) unlink(mOutName); throw; } delete mReadBuffer; delete mReadPtrs; delete writeBuffer; delete writePtrs; mSrcFile.Close(); mDestFile.Close(); if (TaggedEncodingToCAF()) WriteCAFInfo(); if (mParams.flags & kOpt_Verbose) { // must close to flush encoder; GetNumberFrames() not necessarily valid until afterwards but then // the file is closed CAAudioFile temp; FSRef destFSRef; if (FSPathMakeRef((UInt8 *)mOutName, &destFSRef, NULL) == noErr) { temp.Open(destFSRef); printf("Output file: %s, %qd frames\n", basename(mOutName), temp.GetNumberFrames()); } } }
int main(int argc, const char * argv[]) { setbuf (stdout, NULL); #if TARGET_OS_MAC { thread_extended_policy_data_t theFixedPolicy; theFixedPolicy.timeshare = false; // set to true for a non-fixed thread thread_policy_set(pthread_mach_thread_np(pthread_self()), THREAD_EXTENDED_POLICY, (thread_policy_t)&theFixedPolicy, THREAD_EXTENDED_POLICY_COUNT); // We keep a reference to the spawning thread's priority around (initialized in the constructor), // and set the importance of the child thread relative to the spawning thread's priority. thread_precedence_policy_data_t thePrecedencePolicy; thePrecedencePolicy.importance = 63 - 36; thread_policy_set(pthread_mach_thread_np(pthread_self()), THREAD_PRECEDENCE_POLICY, (thread_policy_t)&thePrecedencePolicy, THREAD_PRECEDENCE_POLICY_COUNT); } #endif // These are the variables that are set up from the input parsing char* srcFilePath = NULL; char* destFilePath = NULL; char* auPresetFile = NULL; bool shortMemoryProfile = false; OSType manu, subType, type = 0; int userSetFrames = -1; for (int i = 1; i < argc; ++i) { if (strcmp (argv[i], "-au") == 0) { if ( (i + 3) < argc ) { StrToOSType (argv[i + 1], type); StrToOSType (argv[i + 2], subType); StrToOSType (argv[i + 3], manu); i += 3; } else { printf ("Which Audio Unit:\n%s", usageStr); exit(1); } } else if (strcmp (argv[i], "-i") == 0) { srcFilePath = const_cast<char*>(argv[++i]); } else if (strcmp (argv[i], "-o") == 0) { destFilePath = const_cast<char*>(argv[++i]); } else if (strcmp (argv[i], "-p") == 0) { auPresetFile = const_cast<char*>(argv[++i]); } else if (strcmp (argv[i], "-m") == 0) { shortMemoryProfile = true; } else if (strcmp (argv[i], "-f") == 0) { sscanf(argv[++i], "%d", &userSetFrames); } else { printf ("%s\n", usageStr); exit(1); } } if (!type || !srcFilePath) { printf ("%s\n", usageStr); exit(1); } if (!destFilePath) { if (!shortMemoryProfile) { printf ("%s\n", usageStr); exit(1); } } // delete pre-existing output file if (!shortMemoryProfile) { FSRef destFSRef; if (FSPathMakeRef((UInt8 *)destFilePath, &destFSRef, NULL) == noErr) { // output file exists - delete it if (FSDeleteObject(&destFSRef)) { printf ("Cannot Delete Output File\n"); exit(1); } } } CAComponentDescription desc(type, subType, manu); CFPropertyListRef presetDict = ReadPresetFromPresetFile(auPresetFile); // the num of frames to use when processing the file with the Render call UInt32 maxFramesToUse = shortMemoryProfile ? 512 : 32768; // not set from command line if (userSetFrames > 0) { maxFramesToUse = userSetFrames; } // in some settings (for instance a delay with 100% feedback) tail time is essentially infinite // so you should safeguard the final OL render stage (post process) which is aimed at pulling the tail through // if you want to bypass this completely, just set this to zero. Float64 maxTailTimeSecs = 10.; #pragma mark - #pragma mark __ The driving code #pragma mark - try { CAComponent comp(desc); // CAAUProcessor's constructor throws... so make sure the component is valid if (comp.IsValid() == false) { printf ("Can't Find Component\n"); desc.Print(); exit(1); } CAAUProcessor processor(comp); processor.AU().Print(); CAAudioFile srcFile; CAAudioFile destFile; srcFile.Open(srcFilePath); CAStreamBasicDescription procFormat (srcFile.GetFileDataFormat()); procFormat.SetCanonical (srcFile.GetFileDataFormat().NumberChannels(), false); printf ("Processing Format:\n\t"); procFormat.Print(); if (!shortMemoryProfile) { FSRef parentDir; CFStringRef filename; PosixPathToParentFSRefAndName(destFilePath, parentDir, filename); destFile.CreateNew (parentDir, filename, 'AIFF', srcFile.GetFileDataFormat()); destFile.SetClientFormat (procFormat); } srcFile.SetClientFormat (procFormat); AUOutputBL outputList(procFormat); ReadBuffer* readBuf = NULL; #if !CAAF_USE_EXTAUDIOFILE UInt64 numInputSamples = srcFile.GetNumberPackets(); #else UInt64 numInputSamples = srcFile.GetNumberFrames(); #endif if (shortMemoryProfile) { readBuf = new ReadBuffer; readBuf->readData = new AUOutputBL(procFormat); readBuf->readFrames = 0; UInt32 numFrames = UInt32(procFormat.mSampleRate / 2); readBuf->readData->Allocate (numFrames); // half a second of audio data readBuf->readData->Prepare(); // half a second of audio data // read 1/2 second of audio into this read buffer srcFile.Read (numFrames, readBuf->readData->ABL()); sInputCallback.inputProc = MemoryInputCallback; sInputCallback.inputProcRefCon = readBuf; numInputSamples = numFrames; } else { if (desc.IsFConv()) { maxFramesToUse = userSetFrames == -1 ? 512 : maxFramesToUse; // some format converter's can call you several times in small granularities // so you can't use a large buffer to render or you won't return all of the input data // this also lessens the final difference between what you should get and what you do // converter units *really* should have a version that are offline AU's to // handle this for you. sInputCallback.inputProc = FConvInputCallback; } else sInputCallback.inputProc = InputCallback; sInputCallback.inputProcRefCon = &srcFile; } OSStatus result; require_noerr (result = processor.EstablishInputCallback (sInputCallback), home); require_noerr (result = processor.SetMaxFramesPerRender (maxFramesToUse), home); processor.SetMaxTailTime (maxTailTimeSecs); require_noerr (result = processor.Initialize (procFormat, numInputSamples), home); if (presetDict) { require_noerr (result = processor.SetAUPreset (presetDict), home); CFRelease (presetDict); } // this does ALL of the preflighting.. could be specialise for an OfflineAU type // to do this piecemeal and do a progress bar by using the OfflineAUPreflight method require_noerr (result = processor.Preflight (), home); bool isDone; isDone = false; bool needsPostProcessing; bool isSilence; UInt32 numFrames; numFrames = processor.MaxFramesPerRender(); #if CA_AU_PROFILE_TIME sReadTime = 0; sRenderTime = 0; #endif PRINT_MARKS(); // this is the render loop while (!isDone) { #if CA_AU_PROFILE_TIME UInt64 now = CAHostTimeBase::GetTheCurrentTime(); #endif outputList.Prepare(); // have to do this every time... require_noerr (result = processor.Render (outputList.ABL(), numFrames, isSilence, &isDone, &needsPostProcessing), home); #if CA_AU_PROFILE_TIME sRenderTime += (CAHostTimeBase::GetTheCurrentTime() - now); #endif if (!shortMemoryProfile) PRINT_PROGRESS(processor.GetOLPercentComplete()); else PRINT_PROGRESS(((processor.SampleTime() / numInputSamples) * 100.)); if (numFrames && !shortMemoryProfile) destFile.Write (numFrames, outputList.ABL()); } // this is the postprocessing if needed if (!shortMemoryProfile && needsPostProcessing) { isDone = false; numFrames = processor.MaxFramesPerRender(); while (!isDone) { outputList.Prepare(); // have to do this every time... #if CA_AU_PROFILE_TIME UInt64 now = CAHostTimeBase::GetTheCurrentTime(); #endif require_noerr (result = processor.PostProcess (outputList.ABL(), numFrames, isSilence, isDone), home); #if CA_AU_PROFILE_TIME sRenderTime += (CAHostTimeBase::GetTheCurrentTime() - now); #endif PRINT_PROGRESS(processor.GetOLPercentComplete()); if (numFrames && !shortMemoryProfile) destFile.Write (numFrames, outputList.ABL()); } } printf ("\n"); home: if (result) { printf ("Exit with bad result:%ld\n", result); exit(result); } if (readBuf) { delete readBuf->readData; delete readBuf; } #if CA_AU_PROFILE_TIME if (!shortMemoryProfile) { // this flushes any remaing data to be written to the disk. // the source file is closed in its destructor of course destFile.Close(); // open the file again, to get stats about it for profiling destFile.Open(destFilePath); } SInt64 numWritten; if (shortMemoryProfile) numWritten = 0; else { #if !CAAF_USE_EXTAUDIOFILE numWritten = destFile.GetNumberPackets(); #else numWritten = destFile.GetNumberFrames(); #endif } printf ("Read File Time:%.2f secs for %lld packets (%.1f secs), wrote %lld packets\n", (CAHostTimeBase::ConvertToNanos (sReadTime) / 1.0e9), numInputSamples, (numInputSamples / procFormat.mSampleRate), numWritten); if (!shortMemoryProfile) { #if !CAAF_USE_EXTAUDIOFILE UInt64 numOutputSamples = destFile.GetNumberPackets(); #else UInt64 numOutputSamples = destFile.GetNumberFrames(); #endif if (numOutputSamples == numInputSamples) { printf ("\tWrote the same number of packets as read\n"); } else { bool expectationMet = !desc.IsOffline(); // we don't have any expectations for offline AU's if (processor.LatencySampleCount() || processor.TailSampleCount()) { if (numOutputSamples - numInputSamples == processor.TailSampleCount()) expectationMet = true; if (expectationMet) printf ("Correctly wrote \'Read Size + Tail\'. "); printf ("AU reports (samples): %ld latency, %ld tail\n", processor.LatencySampleCount(), processor.TailSampleCount()); } if (expectationMet == false) { if (numOutputSamples > numInputSamples) { printf ("\tWrote %lld packets (%.2f secs) more than read\n", (numOutputSamples - numInputSamples), ((numOutputSamples - numInputSamples) / procFormat.mSampleRate)); } else { printf ("\tRead %lld packets (%.2f secs) more than wrote\n", (numInputSamples - numOutputSamples), ((numInputSamples - numOutputSamples) / procFormat.mSampleRate)); } } } } Float64 renderTimeSecs = CAHostTimeBase::ConvertToNanos (sRenderTime - sReadTime) / 1.0e9; printf ("Total Render Time:%.2f secs, using render slice size of %ld frames\n", renderTimeSecs, maxFramesToUse); Float64 cpuUsage; if (shortMemoryProfile) cpuUsage = (renderTimeSecs / 0.5) * 100.; else cpuUsage = (renderTimeSecs / (numInputSamples / procFormat.mSampleRate)) * 100.; printf ("CPU Usage for Render Time:%.2f%%\n", cpuUsage); CFStringRef str = comp.GetCompName(); UInt32 compNameLen = CFStringGetLength (str); CFStringRef presetName = NULL; if (auPresetFile) { CFPropertyListRef dict; if (processor.AU().GetAUPreset (dict) == noErr) { presetName = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)dict, CFSTR("name")); CFRelease (dict); } } UInt32 presetLen = presetName ? CFStringGetLength(presetName) : 0; char* cstr = (char*)malloc (compNameLen + presetLen + 2 + 1); CFStringGetCString (str, cstr, (CFStringGetLength (str) + 1), kCFStringEncodingASCII); if (presetName) { cstr[compNameLen] = ':'; cstr[compNameLen+1] = ':'; CFStringGetCString (presetName, cstr + compNameLen + 2, (CFStringGetLength (presetName) + 1), kCFStringEncodingASCII); } PerfResult("AudioUnitProcess", EndianU32_NtoB(comp.Desc().componentSubType), cstr, cpuUsage, "%realtime"); free (cstr); #endif } catch (CAXException &e) { char buf[256]; printf("Error: %s (%s)\n", e.mOperation, e.FormatError(buf)); exit(1); } catch (...) { printf("An unknown error occurred\n"); exit(1); } return 0; }
int main(int argc, const char * argv[]) { #if TARGET_OS_MAC { thread_extended_policy_data_t theFixedPolicy; theFixedPolicy.timeshare = false; // set to true for a non-fixed thread thread_policy_set(pthread_mach_thread_np(pthread_self()), THREAD_EXTENDED_POLICY, (thread_policy_t)&theFixedPolicy, THREAD_EXTENDED_POLICY_COUNT); // We keep a reference to the spawning thread's priority around (initialized in the constructor), // and set the importance of the child thread relative to the spawning thread's priority. thread_precedence_policy_data_t thePrecedencePolicy; thePrecedencePolicy.importance = 63 - 36; thread_policy_set(pthread_mach_thread_np(pthread_self()), THREAD_PRECEDENCE_POLICY, (thread_policy_t)&thePrecedencePolicy, THREAD_PRECEDENCE_POLICY_COUNT); } #endif // These are the variables that are set up from the input parsing char* srcFilePath = NULL; char* auPresetFile = NULL; OSType manu, subType, type = 0; UInt32 numFrames = 4096; for (int i = 1; i < argc; ++i) { if (strcmp (argv[i], "-au") == 0) { if ( (i + 3) < argc ) { StrToOSType (argv[i + 1], type); StrToOSType (argv[i + 2], subType); StrToOSType (argv[i + 3], manu); i += 3; } else { printf ("Which Audio Unit:\n%s", usageStr); exit(1); } } else if (strcmp (argv[i], "-i") == 0) { srcFilePath = const_cast<char*>(argv[++i]); } else if (strcmp (argv[i], "-p") == 0) { auPresetFile = const_cast<char*>(argv[++i]); } else if (strcmp (argv[i], "-f") == 0) { sscanf(argv[++i], "%ld", &numFrames); } else { printf ("%s\n", usageStr); exit(1); } } if (!type || !srcFilePath) { printf ("%s\n", usageStr); exit(1); } CAComponentDescription desc(type, subType, manu); CFPropertyListRef presetDict = ReadPresetFromPresetFile(auPresetFile); #pragma mark - #pragma mark __ The driving code #pragma mark - try { CAComponent comp(desc); // CAAUProcessor's constructor throws... so make sure the component is valid if (comp.IsValid() == false) { printf ("Can't Find Component\n"); desc.Print(); exit(1); } CAAUProcessor processor(comp); processor.AU().Comp().Print(); CAAudioFile srcFile; srcFile.Open(srcFilePath); UInt64 numInputSamples = srcFile.GetNumberFrames(); Float64 inputSecs = (numInputSamples / srcFile.GetFileDataFormat().mSampleRate); CAStreamBasicDescription procFormat (srcFile.GetFileDataFormat()); procFormat.SetCanonical (srcFile.GetFileDataFormat().NumberChannels(), false); printf ("Processing file: %s, %.1f secs [proc: %ld frames]\n", srcFilePath, inputSecs, numFrames); #if VERBOSE printf("\t"); procFormat.Print(); #endif srcFile.SetClientFormat (procFormat); AUOutputBL outputList(procFormat); // read the entire file into memory ReadBuffer* readBuf = new ReadBuffer; readBuf->readData = new AUOutputBL(procFormat); readBuf->totalInputFrames = numInputSamples; readBuf->readData->Allocate (numInputSamples); readBuf->readData->Prepare(); UInt32 readSamps = (UInt32)numInputSamples; srcFile.Read (readSamps, readBuf->readData->ABL()); AURenderCallbackStruct inputCallback; inputCallback.inputProc = MemoryInputCallback; inputCallback.inputProcRefCon = readBuf; OSStatus result; require_noerr (result = processor.EstablishInputCallback (inputCallback), home); require_noerr (result = processor.SetMaxFramesPerRender (numFrames), home); require_noerr (result = processor.Initialize (procFormat, numInputSamples), home); if (presetDict) { require_noerr (result = processor.SetAUPreset (presetDict), home); CFRelease (presetDict); } // this does ALL of the preflighting.. could be specialise for an OfflineAU type // to do this piecemeal and do a progress bar by using the OfflineAUPreflight method readBuf->lastInputFrames = 0; require_noerr (result = processor.Preflight (), home); float mean; // now do the processing.... { const int kThrasherSize = 4000000; char* thrasher = new char[kThrasherSize]; bool isDone = false; UInt32 numMeasures = 0; Float64 totalMSqrd = 0; Float64 totalM = 0; int i = 0; int discardResults = 3; // this is the render loop while (!isDone) { bool isSilence, postProcess; outputList.Prepare(); // have to do this every time... readBuf->lastInputFrames = 0; sLastReadTime = 0; memset (thrasher, numMeasures, kThrasherSize); UInt64 now = CAHostTimeBase::GetTheCurrentTime(); require_noerr (result = processor.Render (outputList.ABL(), numFrames, isSilence, &isDone, &postProcess), home); UInt64 renderTime = (CAHostTimeBase::GetTheCurrentTime() - now); if (i++ < discardResults) continue; if (!readBuf->lastInputFrames) break; Float64 renderTimeSecs = CAHostTimeBase::ConvertToNanos (renderTime - sLastReadTime) / 1.0e9; Float64 cpuTime = (renderTimeSecs / (readBuf->lastInputFrames / procFormat.mSampleRate)) * 100.; numMeasures++; totalMSqrd += (cpuTime * cpuTime); totalM += cpuTime; if (cpuTime > sMaxTime) sMaxTime = cpuTime; if (cpuTime < sMinTime) sMinTime = cpuTime; #if VERBOSE // printf ("current measure: %.2f\n", cpuTime); if (numMeasures % 5 == 0) { Float64 mean = totalM / numMeasures; // stdDev = (sum of Xsquared -((sum of X)*(sum of X)/N)) / (N-1)) Float64 stdDev = sqrt ((totalMSqrd - ((totalM * totalM) / numMeasures)) / (numMeasures-1.0)); printf ("ave: %.2f, min: %.2f, max: %.2f, stdev: %.2f, numMeasures: %ld, current: %f\n", mean, sMinTime, sMaxTime, stdDev, numMeasures, cpuTime); } #endif } delete [] thrasher; mean = totalM / numMeasures; // stdDev = (sum of Xsquared -((sum of X)*(sum of X)/N)) / (N-1)) Float64 stdDev = sqrt ((totalMSqrd - ((totalM * totalM) / numMeasures)) / (numMeasures-1.0)); printf ("ave: %.2f, min: %.2f, max: %.2f, sd: %.2f, sd / mean: %.2f%%\n", mean, sMinTime, sMaxTime, stdDev, (stdDev / mean * 100.)); } // we don't care about post-processing home: if (result) { printf ("Exit with bad result:%ld\n", result); exit(result); } if (readBuf) { delete readBuf->readData; delete readBuf; } CFStringRef str = comp.GetCompName(); UInt32 compNameLen = CFStringGetLength (str); CFStringRef presetName = NULL; if (auPresetFile) { CFPropertyListRef dict; if (processor.AU().GetAUPreset (dict) == noErr) { presetName = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)dict, CFSTR("name")); CFRelease (dict); } } UInt32 presetLen = presetName ? CFStringGetLength(presetName) : 0; UInt32 groupID = comp.Desc().componentSubType; char* cstr = (char*)malloc (compNameLen + presetLen + 2 + 1); CFStringGetCString (str, cstr, (CFStringGetLength (str) + 1), kCFStringEncodingASCII); if (presetName) { cstr[compNameLen] = ':'; cstr[compNameLen+1] = ':'; CFStringGetCString (presetName, cstr + compNameLen + 2, (CFStringGetLength (presetName) + 1), kCFStringEncodingASCII); int len = strlen(cstr); for (int i = 0; i < len; ++i) groupID += cstr[i]; } PerfResult("AU Profile", EndianU32_NtoB(groupID), cstr, mean, "%realtime"); free (cstr); } catch (CAXException &e) { char buf[256]; printf("Error: %s (%s)\n", e.mOperation, e.FormatError(buf)); exit(1); } catch (...) { printf("An unknown error occurred\n"); exit(1); } return 0; }
int qtaacdecode(const char *infileName, const char *outfileName) { QTAACFile infile; CAAudioFile outfile; CABufferList *readBuffer = NULL, *readPtrs = NULL; bool createdOutputFile = false; try { EnterMovies(); infile.Open(infileName); // for now we'll always convert to 16-bit stereo 44100 AIFF CAStreamBasicDescription dataFormat; dataFormat.mSampleRate = 44100.; dataFormat.mFormatID = kAudioFormatLinearPCM; dataFormat.mFormatFlags = kAudioFormatFlagIsBigEndian | kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; dataFormat.mFramesPerPacket = 1; dataFormat.mChannelsPerFrame = 2; dataFormat.mBitsPerChannel = 16; dataFormat.mBytesPerPacket = dataFormat.mBytesPerFrame = 4; infile.SetClientFormat(dataFormat); outfile.PrepareNew(dataFormat); // create the output file outfile.Create(outfileName, kAudioFileAIFFType); createdOutputFile = true; // prepare I/O buffers const UInt32 bytesToRead = 0x8000; const UInt32 packetsToRead = bytesToRead; // OK, ReadPackets will limit as appropriate readBuffer = CABufferList::New("readbuf", dataFormat); readBuffer->AllocateBuffers(bytesToRead); readPtrs = CABufferList::New("readptrs", dataFormat); while (true) { UInt32 nPackets = packetsToRead; readPtrs->SetFrom(readBuffer); AudioBufferList *readbuf = &readPtrs->GetModifiableBufferList(); infile.ReadPackets(nPackets, readbuf); if (nPackets == 0) break; outfile.WritePackets(nPackets, readbuf); } } catch (CAXException &e) { char buf[256]; fprintf(stderr, "Error: %s (%s)\n", e.mOperation, CAXException::FormatError(buf, e.mError)); delete readBuffer; delete readPtrs; infile.Close(); if (createdOutputFile) outfile.Delete(); return 1; } catch (...) { fprintf(stderr, "An unknown error occurred\n"); delete readBuffer; delete readPtrs; infile.Close(); if (createdOutputFile) outfile.Delete(); return 1; } infile.Close(); outfile.Close(); return 0; }