Re: Offline rendering difficulty
Re: Offline rendering difficulty
- Subject: Re: Offline rendering difficulty
- From: Doug Wyatt <email@hidden>
- Date: Tue, 16 Jun 2009 23:36:38 -0700
This algorithm is flawed in that it expects to be able, given a single
MP3 packet, to use AudioQueueOfflineRender to immedately produce
exactly the PCM frames corresponding to that packet.
Neither MP3 decoders nor AudioQueueOfflineRender work that way. Both,
for pretty different reasons, require that you "push" the encoded
input at a significantly in advance of where you try to "pull" decoded
output.
You might study the example for AudioQueueOfflineRender carefully and
get a feel for how the example decouples its pushes and pulls. You
might also experiment with using a software MP3 decoder via
AudioConverter, for the same purpose. You might notice that with
AudioConverter you can never pull quite as much as you've pushed. The
horrible difference with AudioQueueOfflineRender is that it's
emulating the realtime playback path too well -- it dutifully
generates as many samples as you ask for, even if not that many have
been decoded yet.
Doug
On Jun 10, 2009, at 13:28 , dct wrote:
(This was sent earlier but I received no receipt reply.)
I am having difficuty with offline rendering to linear pcm.
With an mp3 music input, the rendering operation produces a properly
sized output
but one that is very "spikey" and (more or less) repeating--
certainly not music.
A histogram of the SInt16 output (channel 1 ) shows:
- ~60% zeros,
- ~ one very distinctive spike at about +5652 (~6%) and about 10
lesser ones.
Autocorrelation of channel 1 output shows a very distictive
structure with sharp
spikes at multiples of ~0.02612 sec ( = 1152 / 44100 = output packet
time span).
The 2nd channel shows similar, non-music characteristics.
The input is definitely music--it plays very nicely through iTunes.
My processing goes as follows:
1. In a controlling Obj-C object:
a. Open an audio file parser,
err = AudioFileStreamOpen(self, propertyCallback,
packetCallback, 0, &aFileParserID);
b. Run the parser:
err = AudioFileStreamParseBytes(aFileParserID, inBufSize,
inBuffer, kAudioFileStreamParseFlag_Discontinuity);
2. In the propertyCallback function --
if(inPropertyID==kAudioFileStreamProperty_ReadyToProducePackets):
a. Get properties:
err = AudioFileStreamGetProperty( inAudioFileStream,
kAudioFileStreamProperty_DataFormat, &asbdSize, &asbdX);
b. Set out-format for linear pcm (AudioStreamBasicDescription asbdY):
asbdY.mSampleRate = asbdX.mSampleRate;
asbdY.mFormatID = kAudioFormatLinearPCM;
asbdY.mFormatFlags = kAudioFormatFlagIsSignedInteger |
kAudioFormatFlagsNativeEndian |
kAudioFormatFlagIsPacked;
asbdY.mFramesPerPacket = 1;
asbdY.mChannelsPerFrame = asbdX.mChannelsPerFrame;
asbdY.mBitsPerChannel = 16;
asbdY.mBytesPerFrame = sizeof(SInt16)*asbdY.mChannelsPerFrame;
asbdY.mBytesPerPacket = asbdY.mBytesPerFrame;
c. Create an audio queue:
err = AudioQueueNewOutput(&asbdX, audioQueueCallback,
inBuffer, NULL, NULL, 0,
&queue);
d. Establish a queue buffer (sized to handle one packet at a time):
err = AudioQueueAllocateBuffer( queue, outPcktSize, &ioBuffer );
e. Set queue for offline rendering:
chLayout.mChannelLayoutTag = (asbdX.mChannelsPerFrame==1) ?
kAudioChannelLayoutTag_Mono :
kAudioChannelLayoutTag_Stereo;
chLayout.mChannelBitmap = 0;
chLayout.mNumberChannelDescriptions = 1;
err = AudioQueueSetOfflineRenderFormat( queue, &asbdY,
&chLayout );
3. In the packetCallback function --
once each loop: for(ii=0;ii<inNPackets;ii++)
a. Copy input block to queue buffer
memcpy((char *)ioBuffer, (const char *)inInputData+pcktOffset,
inPcktSz);
b. Generate time stamp, ts
ts.mSampleTime = 0;
ts.mHostTime = (UInt64)startT; (startT derived from Microseconds
() )
ts.mRateScalar = 0;
ts.mWordClockTime = 0;
memset (&ts.mSMPTETime, 0, sizeof(SMPTETime));
ts.mFlags = kAudioTimeStampSampleTimeValid |
kAudioTimeStampHostTimeValid;
c. Render to pcm
nn = asbdX.mFramesPerPacket;
err = AudioQueueOfflineRender( queue, &ts, ioBuffer, nn );
d. Copy queue buffer to output
memcpy((char *)outBuffer+fillOffset, (const char *)ioBuffer,
outPcktSz);
e. Update the fillOffset value
_______________________________________________
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