• 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
Can't make AudioQueue play my buffer...
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Can't make AudioQueue play my buffer...


  • Subject: Can't make AudioQueue play my buffer...
  • From: Carlos Eduardo Mello <email@hidden>
  • Date: Sun, 12 Apr 2009 13:04:55 -0300

Hi People,

I haven't done any core audio programming in a long time.
Reading the latest docs, I found that AudioQueue would be the best choice for this little project:


I have a small cocoa app (Obj-C++), which produces buffers, ready to be output. I mix them in one central buffer (mMixBuffer) and send it out with this player object (code bellow). I started out with the audio file playing example from "Audio Queue Services Programming Guide" (Oct 2007). Since I am doing linear PCM only and playing samples which are already in memory, I removed all the parts which dealt with fIle reading and decompression, which I assumed wouldn't be needed. I followed the code bellow with the debugger. Everything seems to work OK until it enters the run loop, at which point it never returns. I checked the buffers and they are full, but I never hear anything.

Could someone please help me figure out what is wrong with this code?
Is the audio format correct? ( I want 44.1kHz, mono, and the samples in my buffer are 'floats')
Is there any way to use AudioQueue without having to deal with run loops?


*P.S.: I lef my own comments in the code to see if I am thinking straight. If not, please let me know.

Sorry for the message length. Any suggstions will be much appreciated.



Carlos.

static const int kNumberBuffers = 3;
const float kBufferTime = 1.0; // seconds

Player::Player( void )
{
	mPlaybackQueue = NULL;
	mMixBuffer = NULL;
	mBufferByteSize = 0;
        mIsRunning = false;
	mVolume = 1.0;
	mDataFormat.mSampleRate = 44100.0;
    	mDataFormat.mFormatID = kAudioFormatLinearPCM;
    	mDataFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked;
    	mDataFormat.mBytesPerPacket = sizeof (Float32);
    	mDataFormat.mFramesPerPacket = 1;
   	 mDataFormat.mBytesPerFrame = 4;
    	mDataFormat.mChannelsPerFrame = 1;
    	mDataFormat.mBitsPerChannel = sizeof (Float32) * 8;
}

void Player::Play( void )
{
OSStatus err = noErr;
Float32 gain = Volume();

// Allocate Audio Queue
err = AudioQueueNewOutput( &mDataFormat, HandleOutputBuffer, this, NULL, kCFRunLoopCommonModes, 0, &mPlaybackQueue );
if( err == noErr )
{
// calculate buffer sizes...
mBufferByteSize = static_cast<long> ( kBufferTime * SAMPLING_RATE * sizeof(float) );
// reset playback marker...
mMixBuffer->ResetMarker();


// This is needed in order for the callback to do its thing when priming the queue buffers.
// When there is no more data to fill the buffers, the callback will set this to false, so...
// before starting the audio queue and running the loop, we need to turn this on again
// (see below...)
mIsRunning = true;


// Allocate and fill buffers...
for (int i = 0; i < kNumberBuffers; ++i)
{
err = AudioQueueAllocateBuffer( mPlaybackQueue, mBufferByteSize, &mBuffers[i] );
if( err == noErr )
{
HandleOutputBuffer( this, mPlaybackQueue, mBuffers[i] );
}
}

err = AudioQueueSetParameter( mPlaybackQueue, kAudioQueueParam_Volume, gain );
if( err == noErr )
{
// ... we need to set this again because after priming the buffers,
// the callback turned it off.
mIsRunning = true;

err = AudioQueueStart( mPlaybackQueue, NULL );
if( err == noErr )
{
do
{
CFRunLoopRunInMode ( kCFRunLoopDefaultMode, 0.25,false );
} while ( mIsRunning );
CFRunLoopRunInMode ( kCFRunLoopDefaultMode, 1, false );
}
}
}
}


void Player::Stop( void )
{
	OSStatus err = noErr;

	AudioQueueStop( mPlaybackQueue, true );
	mIsRunning = false;

	// release queue asynch (waiting for buffer completion...)
	err =  AudioQueueDispose( mPlaybackQueue, false );
}

void Player::HandleOutputBuffer( void *aqData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer )
{
OSStatus err = noErr;
UInt32 numBytesRead;
Player * thePlayer = (Player *)aqData;

if(thePlayer->mIsRunning == false) return;

numBytesRead = thePlayer->GetDataFromMixer( inBuffer->mAudioData, inBuffer->mAudioDataBytesCapacity );
if (numBytesRead > 0)
{
inBuffer->mAudioDataByteSize = numBytesRead;
err = AudioQueueEnqueueBuffer( thePlayer->mPlaybackQueue, inBuffer, 0, NULL );
}
else
{
err = AudioQueueStop( thePlayer->mPlaybackQueue, true );
thePlayer->mIsRunning = false;
}
}


// this method reads as many samples from the mix buffer, as will fit in
// the queue buffer. If there are more samples than max bytes, then it sets the
// marker for next read operation and returns. Otherwise it sets the marker to -1
// ( NO_MORE_DATA_IN_BUFFER ) indicating that there is no more data to read
long Player::GetDataFromMixer( void * queueBuffer, long max )
{
long startSample = mMixBuffer->Marker(); // where to start copying data from mix buffer
long numSamples = mMixBuffer->Size(); // can't go further than that in mix buffer
int sampleSize = sizeof(float);
float * qBuffer = (float*)queueBuffer;

if( startSample == NO_MORE_DATA_IN_BUFFER )
return 0;

long i; // keeps track of which element is being writen in queueBuffer
long j; // keeps track of which element is being read from mMixBuffer

// copy data to buffer starting where we last time around (startSample)
for( i = 0, j = startSample; i < ( max / sampleSize ) && j < numSamples; i++, j++ )
{
qBuffer[i] = mMixBuffer->Value( j );
}
// when we are done copying we check to see if we reached the end of the source data...
if( j == numSamples )
{
mMixBuffer->SetMarker( NO_MORE_DATA_IN_BUFFER );
}
else
{
mMixBuffer->SetMarker( j );
}
// inform number of bytes placed in queue buffer...
return ( i * sampleSize );
}


_______________________________________________
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


  • Prev by Date: Re: Capturing AU output to file
  • Next by Date: Re: AULab - AudioDeviceAddPropertyListener errors
  • Previous by thread: Re: AULab - AudioDeviceAddPropertyListener errors
  • Next by thread: parameter persistence and view?
  • Index(es):
    • Date
    • Thread