Hi,
Still trying to get AudioQueueOfflineRender() to work.. Included is
a very straightforward and short implementation of how I suppose it
should work. The code, when compiled, ouptuts an mp3 just fine to
the OSX device audio output, but in 'offline mode' (see the variable
offlineDecoding), the buffer is filled with zeroes.. Can anyone have
a look at it? It's just 225 lines including whitelines... :)
Compile with:
gcc -o test_offline -framework CoreFoundation -framework
AudioToolbox test_offline.c
Run with:
./test_offline <path to an mp3, or other kind of compressed audio
file>
----(start file test_offline.c)
#include <CoreFoundation/CoreFoundation.h>
#include <AudioToolbox/AudioToolbox.h>
#define packetDescriptionsNumber 50
/*
** AudioFile & AudioQueue variables, defined globally to simplify
code reading
*/
static AudioFileID fileID;
static AudioStreamBasicDescription inputFormat;
static AudioStreamBasicDescription outputFormat;
static AudioQueueRef decodeQueue;
static AudioQueueBufferRef inputReadBuffer;
static AudioStreamPacketDescription
inputPacketDescriptions[packetDescriptionsNumber];
static AudioChannelLayout layout;
static SInt64 currentFilePos;
static UInt8 offlineDecoding = 0; // 0 = play to device out
// 1 = play to offline buffer
static AudioQueueTimelineRef timeline;
static AudioTimeStamp timestamp;
int perr(char *msg, OSStatus err)
{
printf("%s = %d\n", msg, err);
exit(-1);
}
void printBuffer(SInt16 *buf, UInt32 count)
{
int i;
for(i = 0; i < count; i++)
printf("%hd ", buf[i]);
printf("\n");
}
void decodeCallback(void *inUserData, AudioQueueRef inAudioQueue,
AudioQueueBufferRef bufferRef)
{
OSStatus err;
UInt32 nFrames;
Boolean discontinuity;
printf("callback called!\n");
if(offlineDecoding) {
printf("callback in offline mode\n");
/*
** timestamp.. how should this be filled? It errors with -66678
** which would suggest starting the AudioQueue even in
offlineRender
** mode, but starting a queue after the offlineRender() format has
** been set results in an IO timeout...
*/
/*
err = AudioQueueGetCurrentTime(inAudioQueue, timeline, ×tamp,
&discontinuity);
if(err)
printf("AudioQueueGetCurrentTime() = %d\n", err);
*/
printf("BEFORE = ");
printBuffer((SInt16 *)bufferRef->mAudioData, 400);
nFrames = 400; // arbitrary amount
err = AudioQueueOfflineRender(inAudioQueue, ×tamp,
bufferRef, nFrames);
if(err)
printf("AudioQueueOfflineRender() = %d\n", err);
printf("AFTER = ");
printBuffer((SInt16 *)bufferRef->mAudioData, 400);
}
}
void printFormat(AudioStreamBasicDescription format)
{
printf("sample rate = %f\n", format.mSampleRate);
printf("formatid = %d\n", format.mFormatID);
printf("formatflags = %d\n", format.mFormatFlags);
printf("framesperpacket = %d\n", format.mFramesPerPacket);
printf("channelsperframe = %d\n", format.mChannelsPerFrame);
printf("bytesperframe = %d\n", format.mBytesPerFrame);
printf("bytesperpacket = %d\n", format.mBytesPerPacket);
printf("bitsperchannel = %d\n", format.mBitsPerChannel);
}
int main(int argc, char *argv[])
{
CFURLRef urlRef;
OSStatus err;
UInt32 size;
UInt32 queueBufferSize;
UInt32 readBytes, readPackets;
if(argc != 2) {
printf("Usage: %s <audiofile>\n\n", argv[0]);
exit(0);
}
/*
** first, try opening the file
*/
urlRef = CFURLCreateWithBytes(NULL, (UInt8 *)argv[1],
strlen(argv[1]),
kCFStringEncodingASCII, NULL);
if((err = AudioFileOpenURL(urlRef, 0x01, 0, &fileID)))
perr("AudioFileOpenURL()", err);
/*
** read format of the audiofile into inputFormat
*/
size = sizeof(inputFormat);
bzero(&inputFormat, size);
if((err = AudioFileGetProperty(fileID,
kAudioFilePropertyDataFormat, &size,
&inputFormat)))
perr("AudioFileGetProperty()", err);
printf("INPUT = \n");
printFormat(inputFormat);
/*
** set the format offlineRender() should convert to
*/
bzero(&outputFormat, sizeof(outputFormat));
outputFormat.mSampleRate = 44100.0;
outputFormat.mFormatID = kAudioFormatLinearPCM;
outputFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger |
kAudioFormatFlagIsPacked;
outputFormat.mFramesPerPacket = 1;
outputFormat.mChannelsPerFrame = 1;
outputFormat.mBytesPerFrame = sizeof(SInt16) *
outputFormat.mChannelsPerFrame;
outputFormat.mBytesPerPacket = outputFormat.mBytesPerFrame *
outputFormat.mFramesPerPacket;
outputFormat.mBitsPerChannel = (outputFormat.mBytesPerFrame /
outputFormat.mChannelsPerFrame) * 8;
printf("\nOUTPUT = \n");
printFormat(outputFormat);
printf("\n\n");
queueBufferSize = 44100 * 10; // some arbitrary amount
/*
** setup the output layout
*/
bzero(&layout, sizeof(layout));
layout.mChannelLayoutTag = kAudioChannelLayoutTag_Mono | 1;
layout.mChannelBitmap = 0;
layout.mNumberChannelDescriptions = 0;
/*
** now, we're going to open the decode queue
*/
if((err = AudioQueueNewOutput(&inputFormat, decodeCallback, NULL,
NULL,
0, 0, &decodeQueue)))
perr("AudioQueueNewOutput()", err);
// create timeline for GetCurrentTime().. Is this even nessecary?
if((err = AudioQueueCreateTimeline(decodeQueue, &timeline)))
perr("AudioQueueCreateTimeline()", err);
if((err = AudioQueueAllocateBuffer(decodeQueue, queueBufferSize,
&inputReadBuffer)))
perr("AudioQueueAllocateBuffer()", err);
/*
** first, read some packets from the file
*/
currentFilePos = 0;
readBytes = 0;
readPackets = packetDescriptionsNumber;
if((err = AudioFileReadPackets(fileID, FALSE, &readBytes,
inputPacketDescriptions,
currentFilePos,
&readPackets,
inputReadBuffer->mAudioData)))
perr("AudioFileReadPackets()", err);
if(readPackets) {
inputReadBuffer->mAudioDataByteSize = readBytes;
currentFilePos += readPackets;
printf("readBytes = %d, readPackets = %d\n", readBytes,
readPackets);
/*
** we have packets, so enqueue the buffer
*/
if((err = AudioQueueEnqueueBuffer(decodeQueue, inputReadBuffer,
readPackets,
inputPacketDescriptions)))
perr("AudioQueueEnqueueBuffer()", err);
if(!offlineDecoding) {
printf("starting queue for ONLINE decoding\n");
if((err = AudioQueueStart(decodeQueue, NULL)))
perr("AudioQueueStart()", err);
sleep(3); // sleep so we can listen to audio
} else {
printf("starting queue for OFFLINE decoding\n");
if((err = AudioQueueSetOfflineRenderFormat(decodeQueue,
&outputFormat,
&layout)))
perr("AudioQueueSetOfflineRenderFormat", err);
/*
** shouldn't setOfflineRenderFormat() call this? It was
previously
** enqueued....
*/
decodeCallback(NULL, decodeQueue, inputReadBuffer);
}
} else {
printf("no more packets!\n");
}
printf("after decoding\n");
/*
** end..
*/
printf("end..\n");
return(0);
}
----(end file test_offline.c)
_______________________________________________
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