• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
AudioUnit problem: CFRunLoopRunInMode() spins after first thread exits, and second thread begins?
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

AudioUnit problem: CFRunLoopRunInMode() spins after first thread exits, and second thread begins?


  • Subject: AudioUnit problem: CFRunLoopRunInMode() spins after first thread exits, and second thread begins?
  • From: Jeremy Friesner <email@hidden>
  • Date: Wed, 15 Oct 2008 13:00:59 -0700

Hi all,

I have a curious problem with my audio playback code. What my program does is spawn a thread that uses AudioUnit to play back a generated stream of audio. In general, this works fine. The problem occurs when (for reasons I won't go into here) my program needs to shut down the thread, and then later spawn another one that is identical to it. The second time, the thread doesn't work correctly... in particular, CFRunLoopRunInMode() immediately returns 1 (aka kCFRunLoopRunFinished) instead of waiting the expected one second and then returning kCFRunLoopTimedOut. This causes one of my Mac's CPU cores to become pegged at 100%, which I want to avoid.

Can anyone hazard a guess as to why this is happening? I do a "gentle" shutdown of the first thread (my main thread sets the _keepGoing flag to false, and then waits for the audio thread to clean up after itself and exit), so I'd expect it to work okay...

Code sample is below.

Thanks,
Jeremy Friesner

--------------

static OSStatus RenderAudioFunc(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData)
{
return ((CoreAudioDataIO *)inRefCon)->RenderAudio(ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData);
}


OSStatus
CoreAudioDataIO :: RenderAudio(AudioUnitRenderActionFlags * / *ioActionFlags*/,
const AudioTimeStamp * /*inTimeStamp*/,
UInt32 /*inBusNumber*/,
UInt32 inNumberFrames,
AudioBufferList *ioData)
{
[... code to write audio samples to ioData->mBuffers[0].mData omitted ...]
return _keepGoing ? noErr : -1;
}



// Audio thread is started here void CoreAudioDataIO :: MyAudioThreadEntryFunc() { // Open the default output unit ComponentDescription desc; memset(&desc, 0, sizeof(desc)); desc.componentType = kAudioUnitType_Output; desc.componentSubType = kAudioUnitSubType_DefaultOutput; desc.componentManufacturer = kAudioUnitManufacturer_Apple; desc.componentFlags = 0; desc.componentFlagsMask = 0;

Component comp = FindNextComponent(NULL, &desc);
if (comp == NULL) {printf ("FindNextComponent failed!\n"); exit(10);}


   AudioUnit outputUnit;

OSStatus err = OpenAComponent(comp, &outputUnit);
if (comp == NULL) {printf ("OpenAComponent=%ld failed!\n", err); exit(10);}


   // Set up a callback function to generate output to the output unit
   AURenderCallbackStruct input; memset(&input, 0, sizeof(input));
   input.inputProc = RenderAudioFunc;
   input.inputProcRefCon = this;

err = AudioUnitSetProperty (outputUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &input, sizeof(input));
if (err) {printf ("AudioUnitSetProperty-CB=%ld\n", err); exit(10);}


// We tell the Output Unit what format we're going to supply data to it
// this is necessary if you're providing data through an input callback
// AND you want the DefaultOutputUnit to do any format conversions
// necessary from your format to the device's format.
AudioStreamBasicDescription streamFormat; memset(&streamFormat, 0, sizeof(streamFormat));
streamFormat.mSampleRate = SAMPLES_PER_SECOND; // the sample rate of the audio stream
streamFormat.mFormatID = kAudioFormatLinearPCM; // the specific encoding type of audio stream
streamFormat.mFormatFlags = kLinearPCMFormatFlagIsFloat | kLinearPCMFormatFlagIsPacked | kAudioFormatFlagIsNonInterleaved;
#if (BYTE_ORDER == BIG_ENDIAN)
streamFormat.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian;
#endif


   streamFormat.mBytesPerPacket = 4;
   streamFormat.mFramesPerPacket = 1;
   streamFormat.mBytesPerFrame = 4;
   streamFormat.mChannelsPerFrame = 1;
   streamFormat.mBitsPerChannel = 32;

err = AudioUnitSetProperty (outputUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamFormat, sizeof(AudioStreamBasicDescription));
if (err) {printf ("AudioUnitSetProperty-SF=%4.4s, %ld\n", (char*)&err, err); exit(10);}


   // Initialize unit
   err = AudioUnitInitialize(outputUnit);
   if (err) {printf ("AudioUnitInitialize=%ld\n", err); exit(10);}

Float64 outSampleRate;
UInt32 size = sizeof(Float64);
err = AudioUnitGetProperty(outputUnit, kAudioUnitProperty_SampleRate, kAudioUnitScope_Output, 0, &outSampleRate, &size);
if (err) {printf ("AudioUnitSetProperty-GF=%4.4s, %ld\n", (char*)&err, err); exit(10);}


// Start the rendering
// The DefaultOutputUnit will do any format conversions to the format of the default device
err = AudioOutputUnitStart (outputUnit);
if (err) {printf ("AudioOutputUnitStart=%ld\n", err); exit(10);}


// we call the CFRunLoopRunInMode to service any notifications that the audio
// system has to deal with
while(_keepGoing) CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1.0, false); // in fault mode, this loop spins at 100% CPU --jaf


// REALLY after you're finished playing STOP THE AUDIO OUTPUT UNIT!!!!!!
verify_noerr (AudioOutputUnitStop(outputUnit));


   err = AudioUnitUninitialize (outputUnit);
   if (err) {printf ("AudioUnitUninitialize=%ld\n", err); exit(10);}

   CloseComponent(outputUnit);
}

_______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden


  • Follow-Ups:
    • Re: AudioUnit problem: CFRunLoopRunInMode() spins after first thread exits, and second thread begins?
      • From: Jeff Moore <email@hidden>
  • Prev by Date: Re: Splitting stereo to 2 audiobuffers with AudioConverter
  • Next by Date: Re: AudioUnit problem: CFRunLoopRunInMode() spins after first thread exits, and second thread begins?
  • Previous by thread: Re: Splitting stereo to 2 audiobuffers with AudioConverter
  • Next by thread: Re: AudioUnit problem: CFRunLoopRunInMode() spins after first thread exits, and second thread begins?
  • Index(es):
    • Date
    • Thread