this repo has no description
at fixPythonPipStalling 678 lines 22 kB view raw
1/* Copyright: � Copyright 2005 Apple Computer, Inc. All rights reserved. 2 3 Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. 4 ("Apple") in consideration of your agreement to the following terms, and your 5 use, installation, modification or redistribution of this Apple software 6 constitutes acceptance of these terms. If you do not agree with these terms, 7 please do not use, install, modify or redistribute this Apple software. 8 9 In consideration of your agreement to abide by the following terms, and subject 10 to these terms, Apple grants you a personal, non-exclusive license, under Apple�s 11 copyrights in this original Apple software (the "Apple Software"), to use, 12 reproduce, modify and redistribute the Apple Software, with or without 13 modifications, in source and/or binary forms; provided that if you redistribute 14 the Apple Software in its entirety and without modifications, you must retain 15 this notice and the following text and disclaimers in all such redistributions of 16 the Apple Software. Neither the name, trademarks, service marks or logos of 17 Apple Computer, Inc. may be used to endorse or promote products derived from the 18 Apple Software without specific prior written permission from Apple. Except as 19 expressly stated in this notice, no other rights or licenses, express or implied, 20 are granted by Apple herein, including but not limited to any patent rights that 21 may be infringed by your derivative works or by other works in which the Apple 22 Software may be incorporated. 23 24 The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO 25 WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED 26 WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 27 PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN 28 COMBINATION WITH YOUR PRODUCTS. 29 30 IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR 31 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 32 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION 34 OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT 35 (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN 36 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37*/ 38/*============================================================================= 39 main.cpp 40 41=============================================================================*/ 42 43/* 44 auprocess 45 - takes a source audio file, an AU and generates a processed file 46*/ 47 48#include "CAAUProcessor.h" 49#include "CAAudioFile.h" 50#include "CAXException.h" 51#include "CAHostTimeBase.h" 52#include "CAFilePathUtils.h" 53#include "CAAudioFileFormats.h" 54 55#if TARGET_OS_MAC 56 #include <pthread.h> 57 #include <mach/mach.h> 58#endif 59 60#define require_noerr ca_require_noerr 61 62#define CA_AU_PROFILE_TIME 1 63 64#if CA_AU_PROFILE_TIME 65 UInt64 sReadTime = 0; 66 UInt64 sRenderTime = 0; 67#endif 68 69#pragma mark __print helpers 70 71void PRINT_MARKS () 72{ 73 printf ("| "); 74 for (int i = 0; i < 48; ++i) 75 printf (" "); 76 printf ("|\n"); 77} 78 79void PerfResult(const char *toolname, int group, const char *testname, double value, const char *units, const char *fmt="%.3f") 80{ 81 printf("<result tool='%s' group='%d' test='%s' value='", toolname, group, testname); 82 printf(fmt, value); 83 printf("' units='%s' />\n", units); 84} 85 86static int lastProgressPrintDone = -1; 87void PRINT_PROGRESS (Float32 inPercent) 88{ 89 int current = int(inPercent / 4.0); 90 for (int i = lastProgressPrintDone; i < current; ++i) 91 printf ("* "); 92 lastProgressPrintDone = current; 93} 94 95#pragma mark __Inpput Callback Definitions 96 97static AURenderCallbackStruct sInputCallback; // we set one of these two callbacks based on AU type 98 99static OSStatus InputCallback (void *inRefCon, 100 AudioUnitRenderActionFlags *ioActionFlags, 101 const AudioTimeStamp *inTimeStamp, 102 UInt32 inBusNumber, 103 UInt32 inNumberFrames, 104 AudioBufferList *ioData) 105{ 106 #if CA_AU_PROFILE_TIME 107 UInt64 now = CAHostTimeBase::GetTheCurrentTime(); 108 #endif 109 110 CAAudioFile &readFile = *(static_cast<CAAudioFile*>(inRefCon)); 111 112#if !CAAF_USE_EXTAUDIOFILE 113 if (SInt64(inTimeStamp->mSampleTime) > readFile.GetNumberPackets()) { 114#else 115 if (SInt64(inTimeStamp->mSampleTime) > readFile.GetNumberFrames()) { 116#endif 117#if DEBUG 118 printf ("reading past end of input\n"); 119#endif 120 return -1; 121 } 122 123 readFile.Seek (SInt64(inTimeStamp->mSampleTime)); 124 readFile.Read (inNumberFrames, ioData); 125 126 #if CA_AU_PROFILE_TIME 127 sReadTime += (CAHostTimeBase::GetTheCurrentTime() - now); 128 #endif 129 130 return noErr; 131} 132 133static OSStatus FConvInputCallback (void *inRefCon, 134 AudioUnitRenderActionFlags *ioActionFlags, 135 const AudioTimeStamp *inTimeStamp, 136 UInt32 inBusNumber, 137 UInt32 inNumberFrames, 138 AudioBufferList *ioData) 139{ 140 #if CA_AU_PROFILE_TIME 141 UInt64 now = CAHostTimeBase::GetTheCurrentTime(); 142 #endif 143 144 CAAudioFile &readFile = *(static_cast<CAAudioFile*>(inRefCon)); 145 146 // this test is ONLY needed in case of processing with a Format Converter type of AU 147 // in all other cases, the CAAUProcessor class will NEVER call you for input 148 // beyond the end of the file.... 149 150#if !CAAF_USE_EXTAUDIOFILE 151 if (SInt64(inTimeStamp->mSampleTime) >= readFile.GetNumberPackets()) { 152#else 153 if (SInt64(inTimeStamp->mSampleTime) >= readFile.GetNumberFrames()) { 154#endif 155 return -1; 156 } 157 158 readFile.Seek (SInt64(inTimeStamp->mSampleTime)); 159 UInt32 readPackets = inNumberFrames; 160 161 // also, have to do this for a format converter AU - otherwise we'd just read what we're told 162#if !CAAF_USE_EXTAUDIOFILE 163 if (SInt64(inTimeStamp->mSampleTime + inNumberFrames) > readFile.GetNumberPackets()) { 164#else 165 if (SInt64(inTimeStamp->mSampleTime + inNumberFrames) > readFile.GetNumberFrames()) { 166#endif 167 // first set this to zero as we're only going to read a partial number of frames 168 AudioBuffer *buf = ioData->mBuffers; 169 for (UInt32 i = ioData->mNumberBuffers; i--; ++buf) 170 memset((Byte *)buf->mData, 0, buf->mDataByteSize); 171#if !CAAF_USE_EXTAUDIOFILE 172 readPackets = UInt32 (readFile.GetNumberPackets() - SInt64(inTimeStamp->mSampleTime)); 173#else 174 readPackets = UInt32 (readFile.GetNumberFrames() - SInt64(inTimeStamp->mSampleTime)); 175#endif 176 } 177 178 readFile.Read (readPackets, ioData); 179 180 #if CA_AU_PROFILE_TIME 181 sReadTime += (CAHostTimeBase::GetTheCurrentTime() - now); 182 #endif 183 184 return noErr; 185} 186 187struct ReadBuffer { 188 AUOutputBL *readData; 189 UInt32 readFrames; 190}; 191 192static OSStatus MemoryInputCallback (void *inRefCon, 193 AudioUnitRenderActionFlags *ioActionFlags, 194 const AudioTimeStamp *inTimeStamp, 195 UInt32 inBusNumber, 196 UInt32 inNumberFrames, 197 AudioBufferList *ioData) 198{ 199 #if CA_AU_PROFILE_TIME 200 UInt64 now = CAHostTimeBase::GetTheCurrentTime(); 201 #endif 202 203 ReadBuffer *readBuffer = (ReadBuffer*)inRefCon; 204 205 if (((readBuffer->readFrames + inNumberFrames) * sizeof(Float32)) > (readBuffer->readData->ABL()->mBuffers[0].mDataByteSize)) 206 { 207 // going past read size 208 AudioBuffer *buf = ioData->mBuffers; 209 for (UInt32 i = ioData->mNumberBuffers; i--; ++buf) 210 memset((Byte *)buf->mData, 0, buf->mDataByteSize); 211 } 212 else 213 { 214 AudioBuffer *buf = ioData->mBuffers; 215 AudioBuffer *rBuf = readBuffer->readData->ABL()->mBuffers; 216 for (UInt32 i = ioData->mNumberBuffers; i--; ++buf, ++rBuf) { 217 AudioBuffer readB = *rBuf; 218 readB.mData = static_cast<Float32*>(rBuf->mData) + readBuffer->readFrames; 219 memcpy (buf->mData, readB.mData, buf->mDataByteSize); 220 } 221 readBuffer->readFrames += inNumberFrames; 222 } 223 224 #if CA_AU_PROFILE_TIME 225 sReadTime += (CAHostTimeBase::GetTheCurrentTime() - now); 226 #endif 227 228 return noErr; 229} 230 231#pragma mark __Utility Helpers 232 233CFPropertyListRef ReadPresetFromPresetFile (char* filePath) 234{ 235 if (!filePath) 236 return NULL; 237 238 FSRef ref; 239 if (FSPathMakeRef((UInt8 *)filePath, &ref, NULL)) 240 return NULL; 241 242 CFDataRef resourceData = NULL; 243 CFPropertyListRef theData = NULL; 244 CFStringRef errString = NULL; 245 CFURLRef fileURL = CFURLCreateFromFSRef (kCFAllocatorDefault, &ref); 246 if (fileURL == NULL) { 247 goto home; 248 } 249 250 SInt32 result; 251 252 // Read the XML file. 253 Boolean status; status = CFURLCreateDataAndPropertiesFromResource (kCFAllocatorDefault, fileURL, 254 &resourceData, // place to put file data 255 NULL, NULL, &result); 256 if (status == false || result) { 257 goto home; 258 } 259 260 theData = CFPropertyListCreateFromXMLData (kCFAllocatorDefault, resourceData, 261 kCFPropertyListImmutable, &errString); 262 if (theData == NULL || errString) { 263 if (theData) 264 CFRelease (theData); 265 theData = NULL; 266 goto home; 267 } 268 269home: 270 if (fileURL) 271 CFRelease (fileURL); 272 if (resourceData) 273 CFRelease (resourceData); 274 if (errString) 275 CFRelease (errString); 276 277 return theData; 278} 279 280#pragma mark __the setup code 281 282#define OFFLINE_AU_CMD "[-au TYPE SUBTYPE MANU] The Audio Unit component description\n\t" 283#define INPUT_FILE "[-i /Path/To/File] The file that is to be processed.\n\t" 284#define OUTPUT_FILE "[-o /Path/To/File/To/Create] This will be in the same format as the input file\n\t" 285#define AU_PRESET_CMD "[-p /Path/To/AUPreset/File] Specify an AU Preset File to establish the state of the AU\n\t" 286#define SHORT_MEM_CMD "[-m] Just reads and processes the first half second of the input file\n\t" 287#define USE_MAX_FRAMES "[-f max_frames] default is 32768 (512 for aufc units)" 288 289static char* usageStr = "Usage: auprocess\n\t" 290 OFFLINE_AU_CMD 291 INPUT_FILE 292 OUTPUT_FILE 293 AU_PRESET_CMD 294 SHORT_MEM_CMD 295 USE_MAX_FRAMES; 296 297int main(int argc, const char * argv[]) 298{ 299 setbuf (stdout, NULL); 300 301 302#if TARGET_OS_MAC 303 { 304 thread_extended_policy_data_t theFixedPolicy; 305 theFixedPolicy.timeshare = false; // set to true for a non-fixed thread 306 thread_policy_set(pthread_mach_thread_np(pthread_self()), 307 THREAD_EXTENDED_POLICY, 308 (thread_policy_t)&theFixedPolicy, 309 THREAD_EXTENDED_POLICY_COUNT); 310 311 // We keep a reference to the spawning thread's priority around (initialized in the constructor), 312 // and set the importance of the child thread relative to the spawning thread's priority. 313 thread_precedence_policy_data_t thePrecedencePolicy; 314 315 thePrecedencePolicy.importance = 63 - 36; 316 thread_policy_set(pthread_mach_thread_np(pthread_self()), 317 THREAD_PRECEDENCE_POLICY, 318 (thread_policy_t)&thePrecedencePolicy, 319 THREAD_PRECEDENCE_POLICY_COUNT); 320 } 321#endif 322 323 324// These are the variables that are set up from the input parsing 325 char* srcFilePath = NULL; 326 char* destFilePath = NULL; 327 char* auPresetFile = NULL; 328 bool shortMemoryProfile = false; 329 OSType manu, subType, type = 0; 330 int userSetFrames = -1; 331 332 for (int i = 1; i < argc; ++i) 333 { 334 if (strcmp (argv[i], "-au") == 0) { 335 if ( (i + 3) < argc ) { 336 StrToOSType (argv[i + 1], type); 337 StrToOSType (argv[i + 2], subType); 338 StrToOSType (argv[i + 3], manu); 339 i += 3; 340 } else { 341 printf ("Which Audio Unit:\n%s", usageStr); 342 exit(1); 343 } 344 } 345 else if (strcmp (argv[i], "-i") == 0) { 346 srcFilePath = const_cast<char*>(argv[++i]); 347 } 348 else if (strcmp (argv[i], "-o") == 0) { 349 destFilePath = const_cast<char*>(argv[++i]); 350 } 351 else if (strcmp (argv[i], "-p") == 0) { 352 auPresetFile = const_cast<char*>(argv[++i]); 353 } 354 else if (strcmp (argv[i], "-m") == 0) { 355 shortMemoryProfile = true; 356 } 357 else if (strcmp (argv[i], "-f") == 0) { 358 sscanf(argv[++i], "%d", &userSetFrames); 359 } 360 else { 361 printf ("%s\n", usageStr); 362 exit(1); 363 } 364 } 365 366 if (!type || !srcFilePath) { 367 printf ("%s\n", usageStr); 368 exit(1); 369 } 370 if (!destFilePath) { 371 if (!shortMemoryProfile) { 372 printf ("%s\n", usageStr); 373 exit(1); 374 } 375 } 376 // delete pre-existing output file 377 if (!shortMemoryProfile) { 378 FSRef destFSRef; 379 if (FSPathMakeRef((UInt8 *)destFilePath, &destFSRef, NULL) == noErr) { 380 // output file exists - delete it 381 if (FSDeleteObject(&destFSRef)) { 382 printf ("Cannot Delete Output File\n"); 383 exit(1); 384 } 385 } 386 } 387 388 CAComponentDescription desc(type, subType, manu); 389 390 CFPropertyListRef presetDict = ReadPresetFromPresetFile(auPresetFile); 391 392 // the num of frames to use when processing the file with the Render call 393 UInt32 maxFramesToUse = shortMemoryProfile ? 512 : 32768; 394 395 // not set from command line 396 if (userSetFrames > 0) { 397 maxFramesToUse = userSetFrames; 398 } 399 400 // in some settings (for instance a delay with 100% feedback) tail time is essentially infinite 401 // so you should safeguard the final OL render stage (post process) which is aimed at pulling the tail through 402 // if you want to bypass this completely, just set this to zero. 403 Float64 maxTailTimeSecs = 10.; 404 405#pragma mark - 406#pragma mark __ The driving code 407#pragma mark - 408 409 try 410 { 411 CAComponent comp(desc); 412 413 // CAAUProcessor's constructor throws... so make sure the component is valid 414 if (comp.IsValid() == false) { 415 printf ("Can't Find Component\n"); 416 desc.Print(); 417 exit(1); 418 } 419 420 CAAUProcessor processor(comp); 421 processor.AU().Print(); 422 423 CAAudioFile srcFile; 424 CAAudioFile destFile; 425 426 srcFile.Open(srcFilePath); 427 428 CAStreamBasicDescription procFormat (srcFile.GetFileDataFormat()); 429 procFormat.SetCanonical (srcFile.GetFileDataFormat().NumberChannels(), false); 430 431 printf ("Processing Format:\n\t"); 432 procFormat.Print(); 433 434 435 if (!shortMemoryProfile) { 436 FSRef parentDir; 437 CFStringRef filename; 438 PosixPathToParentFSRefAndName(destFilePath, parentDir, filename); 439 destFile.CreateNew (parentDir, filename, 'AIFF', srcFile.GetFileDataFormat()); 440 destFile.SetClientFormat (procFormat); 441 } 442 443 srcFile.SetClientFormat (procFormat); 444 445 AUOutputBL outputList(procFormat); 446 447 ReadBuffer* readBuf = NULL; 448 449#if !CAAF_USE_EXTAUDIOFILE 450 UInt64 numInputSamples = srcFile.GetNumberPackets(); 451#else 452 UInt64 numInputSamples = srcFile.GetNumberFrames(); 453#endif 454 455 if (shortMemoryProfile) { 456 readBuf = new ReadBuffer; 457 readBuf->readData = new AUOutputBL(procFormat); 458 readBuf->readFrames = 0; 459 UInt32 numFrames = UInt32(procFormat.mSampleRate / 2); 460 readBuf->readData->Allocate (numFrames); // half a second of audio data 461 readBuf->readData->Prepare(); // half a second of audio data 462 463 // read 1/2 second of audio into this read buffer 464 srcFile.Read (numFrames, readBuf->readData->ABL()); 465 466 sInputCallback.inputProc = MemoryInputCallback; 467 sInputCallback.inputProcRefCon = readBuf; 468 numInputSamples = numFrames; 469 } 470 else { 471 if (desc.IsFConv()) { 472 maxFramesToUse = userSetFrames == -1 ? 512 : maxFramesToUse; 473 // some format converter's can call you several times in small granularities 474 // so you can't use a large buffer to render or you won't return all of the input data 475 // this also lessens the final difference between what you should get and what you do 476 // converter units *really* should have a version that are offline AU's to 477 // handle this for you. 478 sInputCallback.inputProc = FConvInputCallback; 479 } else 480 sInputCallback.inputProc = InputCallback; 481 482 sInputCallback.inputProcRefCon = &srcFile; 483 } 484 485 OSStatus result; 486 require_noerr (result = processor.EstablishInputCallback (sInputCallback), home); 487 require_noerr (result = processor.SetMaxFramesPerRender (maxFramesToUse), home); 488 processor.SetMaxTailTime (maxTailTimeSecs); 489 require_noerr (result = processor.Initialize (procFormat, numInputSamples), home); 490 if (presetDict) { 491 require_noerr (result = processor.SetAUPreset (presetDict), home); 492 CFRelease (presetDict); 493 } 494 // this does ALL of the preflighting.. could be specialise for an OfflineAU type 495 // to do this piecemeal and do a progress bar by using the OfflineAUPreflight method 496 require_noerr (result = processor.Preflight (), home); 497 498 bool isDone; isDone = false; 499 bool needsPostProcessing; 500 bool isSilence; 501 UInt32 numFrames; numFrames = processor.MaxFramesPerRender(); 502 503#if CA_AU_PROFILE_TIME 504 sReadTime = 0; 505 sRenderTime = 0; 506#endif 507 508PRINT_MARKS(); 509 // this is the render loop 510 while (!isDone) 511 { 512 #if CA_AU_PROFILE_TIME 513 UInt64 now = CAHostTimeBase::GetTheCurrentTime(); 514 #endif 515 outputList.Prepare(); // have to do this every time... 516 require_noerr (result = processor.Render (outputList.ABL(), numFrames, isSilence, &isDone, 517 &needsPostProcessing), home); 518 #if CA_AU_PROFILE_TIME 519 sRenderTime += (CAHostTimeBase::GetTheCurrentTime() - now); 520 #endif 521 522if (!shortMemoryProfile) 523 PRINT_PROGRESS(processor.GetOLPercentComplete()); 524else 525 PRINT_PROGRESS(((processor.SampleTime() / numInputSamples) * 100.)); 526 527 if (numFrames && !shortMemoryProfile) 528 destFile.Write (numFrames, outputList.ABL()); 529 } 530 531 // this is the postprocessing if needed 532 if (!shortMemoryProfile && needsPostProcessing) 533 { 534 isDone = false; 535 numFrames = processor.MaxFramesPerRender(); 536 while (!isDone) { 537 outputList.Prepare(); // have to do this every time... 538 #if CA_AU_PROFILE_TIME 539 UInt64 now = CAHostTimeBase::GetTheCurrentTime(); 540 #endif 541 require_noerr (result = processor.PostProcess (outputList.ABL(), numFrames, 542 isSilence, isDone), home); 543 #if CA_AU_PROFILE_TIME 544 sRenderTime += (CAHostTimeBase::GetTheCurrentTime() - now); 545 #endif 546 547PRINT_PROGRESS(processor.GetOLPercentComplete()); 548 549 if (numFrames && !shortMemoryProfile) 550 destFile.Write (numFrames, outputList.ABL()); 551 } 552 } 553 554printf ("\n"); 555 556home: 557 if (result) { 558 printf ("Exit with bad result:%ld\n", result); 559 exit(result); 560 } 561 562 if (readBuf) { 563 delete readBuf->readData; 564 delete readBuf; 565 } 566 567#if CA_AU_PROFILE_TIME 568 if (!shortMemoryProfile) { 569 // this flushes any remaing data to be written to the disk. 570 // the source file is closed in its destructor of course 571 destFile.Close(); 572 // open the file again, to get stats about it for profiling 573 destFile.Open(destFilePath); 574 } 575 576 SInt64 numWritten; 577 if (shortMemoryProfile) 578 numWritten = 0; 579 else { 580#if !CAAF_USE_EXTAUDIOFILE 581 numWritten = destFile.GetNumberPackets(); 582#else 583 numWritten = destFile.GetNumberFrames(); 584#endif 585 } 586 587 printf ("Read File Time:%.2f secs for %lld packets (%.1f secs), wrote %lld packets\n", 588 (CAHostTimeBase::ConvertToNanos (sReadTime) / 1.0e9), 589 numInputSamples, 590 (numInputSamples / procFormat.mSampleRate), 591 numWritten); 592 593 if (!shortMemoryProfile) 594 { 595#if !CAAF_USE_EXTAUDIOFILE 596 UInt64 numOutputSamples = destFile.GetNumberPackets(); 597#else 598 UInt64 numOutputSamples = destFile.GetNumberFrames(); 599#endif 600 601 if (numOutputSamples == numInputSamples) { 602 printf ("\tWrote the same number of packets as read\n"); 603 } else { 604 bool expectationMet = !desc.IsOffline(); // we don't have any expectations for offline AU's 605 if (processor.LatencySampleCount() || processor.TailSampleCount()) { 606 if (numOutputSamples - numInputSamples == processor.TailSampleCount()) 607 expectationMet = true; 608 if (expectationMet) 609 printf ("Correctly wrote \'Read Size + Tail\'. "); 610 printf ("AU reports (samples): %ld latency, %ld tail\n", 611 processor.LatencySampleCount(), processor.TailSampleCount()); 612 } 613 if (expectationMet == false) 614 { 615 if (numOutputSamples > numInputSamples) { 616 printf ("\tWrote %lld packets (%.2f secs) more than read\n", 617 (numOutputSamples - numInputSamples), 618 ((numOutputSamples - numInputSamples) / procFormat.mSampleRate)); 619 } else { 620 printf ("\tRead %lld packets (%.2f secs) more than wrote\n", 621 (numInputSamples - numOutputSamples), 622 ((numInputSamples - numOutputSamples) / procFormat.mSampleRate)); 623 } 624 } 625 } 626 } 627 628 Float64 renderTimeSecs = CAHostTimeBase::ConvertToNanos (sRenderTime - sReadTime) / 1.0e9; 629 printf ("Total Render Time:%.2f secs, using render slice size of %ld frames\n", 630 renderTimeSecs, maxFramesToUse); 631 632 Float64 cpuUsage; 633 if (shortMemoryProfile) 634 cpuUsage = (renderTimeSecs / 0.5) * 100.; 635 else 636 cpuUsage = (renderTimeSecs / (numInputSamples / procFormat.mSampleRate)) * 100.; 637 printf ("CPU Usage for Render Time:%.2f%%\n", cpuUsage); 638 639 CFStringRef str = comp.GetCompName(); 640 UInt32 compNameLen = CFStringGetLength (str); 641 642 CFStringRef presetName = NULL; 643 if (auPresetFile) { 644 CFPropertyListRef dict; 645 if (processor.AU().GetAUPreset (dict) == noErr) { 646 presetName = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)dict, CFSTR("name")); 647 CFRelease (dict); 648 } 649 } 650 651 UInt32 presetLen = presetName ? CFStringGetLength(presetName) : 0; 652 653 char* cstr = (char*)malloc (compNameLen + presetLen + 2 + 1); 654 CFStringGetCString (str, cstr, (CFStringGetLength (str) + 1), kCFStringEncodingASCII); 655 if (presetName) { 656 cstr[compNameLen] = ':'; 657 cstr[compNameLen+1] = ':'; 658 CFStringGetCString (presetName, cstr + compNameLen + 2, (CFStringGetLength (presetName) + 1), kCFStringEncodingASCII); 659 } 660 PerfResult("AudioUnitProcess", EndianU32_NtoB(comp.Desc().componentSubType), cstr, cpuUsage, "%realtime"); 661 free (cstr); 662#endif 663 664 665 } 666 catch (CAXException &e) { 667 char buf[256]; 668 printf("Error: %s (%s)\n", e.mOperation, e.FormatError(buf, sizeof(buf))); 669 exit(1); 670 } 671 catch (...) { 672 printf("An unknown error occurred\n"); 673 exit(1); 674 } 675 676 return 0; 677} 678