• 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
Re: Getting Audio Stream/File info
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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

References: 
 >Getting Audio Stream/File info (From: Jarek M <email@hidden>)

  • Prev by Date: NSOpenPanel - turning off QuickLook for audio
  • Next by Date: Re: Offline AUs
  • Previous by thread: Re: Getting Audio Stream/File info
  • Next by thread: How do I set the sample rate of the output in a play-only audio unit iPhone app?
  • Index(es):
    • Date
    • Thread