Re: Getting Audio Stream/File info
Re: Getting Audio Stream/File info
- Subject: Re: Getting Audio Stream/File info
- From: Hamish Allan <email@hidden>
- Date: Fri, 13 Feb 2009 23:08:55 +0000
Hi,
If you're trying to play a file before it's finished downloading and
therefore can't use (Ext)AudioFile, here's some code I wrote to
estimate duration. Feel free to use it under a BSD license (when I get
time, I'm planning to clean up and open-source the code for the whole
player, which is modeled mostly after AVAudioPlayer, but which can
handle remote URLs).
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
myNumBytesIn += [data length];
[myAudioFileStream parseData:data];
[myWritingHandle writeData:data];
myActualContentLength = [myWritingHandle offsetInFile];
CGFloat proportionOfTotalBytesReceived = (CGFloat)myNumBytesIn /
(CGFloat)myExpectedContentLength;
CGFloat audioProportionOfBytesReceived = (CGFloat)myNumBytesOut /
(CGFloat)myNumBytesIn;
CGFloat audioProportionOfTotalBytes =
proportionOfTotalBytesReceived * audioProportionOfBytesReceived;
CGFloat estimatedDuration = (CGFloat)myExpectedContentLength /
(CGFloat)[myAudioFileStream bitrate] * 8.0;
CGFloat correctedEstimatedDuration = estimatedDuration *
audioProportionOfBytesReceived;
myEstimatedDuration = ((estimatedDuration * (1.0 -
proportionOfTotalBytesReceived)) + (correctedEstimatedDuration *
proportionOfTotalBytesReceived));
myAvailableDuration = myNumPackets * mySecondsPerPacket;
NSInteger oldEstimatedTotalPackets = myEstimatedTotalPackets;
myEstimatedTotalPackets = myNumPackets / audioProportionOfTotalBytes - 1;
if (myEstimatedTotalPackets == oldEstimatedTotalPackets ||
myNumBytesIn == myExpectedContentLength)
{
if (!myDurationStable)
{
[myDelegate fixedLengthHandlerDidDetermineDuration:self];
myDurationStable = YES;
}
}
else
myDurationStable = NO;
if (!myReadyNotificationSent && myNumBytesOut >
[AQAudioQueueBuffer bufferLength] * 3)
{
NSTimeInterval currentDownloadTime = [[NSDate date]
timeIntervalSinceDate:myStartTime];
NSTimeInterval estimatedDownloadTime = currentDownloadTime *
myEstimatedDuration / myAvailableDuration;
if ((estimatedDownloadTime - currentDownloadTime) < myEstimatedDuration)
{
[myDelegate fixedLengthHandlerDidFinishPreloading:self];
myReadyNotificationSent = YES;
}
}
}
myNumBytesOut and myNumPackets come from our parser callback
(AQAudioFileStream is a fairly thin wrapper over an AudioFileStream):
- (void)fileStream:(AQAudioFileStream *)fileStream
didFindPacketData:(NSData *)data numFrames:(UInt32)numFrames
{
++myNumPackets;
myNumBytesOut += [data length];
}
Other stuff comes from the AudioStreamBasicDescription:
- (void)fileStream:(AQAudioFileStream *)fileStream
didFindAudioStreamBasicDescription:(AudioStreamBasicDescription)asbd
{
myAudioStreamBasicDescription = asbd;
mySampleRate = (CGFloat)asbd.mSampleRate;
mySecondsPerPacket = (CGFloat)asbd.mFramesPerPacket /
(CGFloat)asbd.mSampleRate;
myBytesPerSecond = (CGFloat)asbd.mBytesPerPacket / mySecondsPerPacket;
}
Bitrate is an AQAudioFileStream property
(kAudioFileStreamProperty_BitRate) which gets a stable value pretty
quickly, even for VBR.
Feel free to ask if anything else is unclear about my code!
Hope this helps,
Hamish
On Fri, Feb 13, 2009 at 3:33 PM, Jarek M <email@hidden> wrote:
> Howdy. We're working on a project that involves playing audio streams (local files or buffered streams)
> using AudioQueue. Such audio stream can contain an mp3, aac or a pcm. Stream can be CBR or a VBR.
>
> I'm using Carbon/AudioQueue interface to get the audio played.
>
> What I'm wondering about is how to obtain
>
> 1) time in seconds since audio playing began
> 3) Duration of the stream being played (if exists, it may be a continuous stream)
> 2) sampling rate of the stream being played
> 3) bitrate of the stream being played ( this may vary in VBR, I understand)
>
> I think I know how to obtain time; however it is a sampling time that has to be calculated
> based on "Hardware" sampling rate. Is there a simpler way to obtain such info?
>
> Best Regards and Thanks
> Jarek
> _______________________________________________
> 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
>
_______________________________________________
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