iphone sdk 3.0 - CoreAudio - how to determine the end of the playing aac file -


i playing coreaudio on iphone, , unable find how know when song has finished play.

i put property listener on kaudioqueueproperty_isrunning, working when starting playing not @ end of file. it's work when stop audioqueue...

do have idea ?

thanks lot.

ps : using sample code excellent book iphone cool projects : http://apress.com/book/downloadfile/4453

edit :

there’s bug in code went out book. fix requires small modification -[audioplayer audiorequestdidfinish:] calls [queue endofstream].

this class uli kusterer illustrates functionality clearly.

here's header:

// //  uksound.h //  mobilemoose // //  created uli kusterer on 14.07.08. //  copyright 2008 void software. rights reserved. //  #import <uikit/uikit.h> #import <audiotoolbox/audiotoolbox.h>   #define knumberbuffers          2   @class uksound;   @protocol uksounddelegate  @optional -(void) sound: (uksound*)sender didfinishplaying: (bool)state;  @end    @interface uksound : nsobject {     audiofileid                     maudiofile;     audiostreambasicdescription     mdataformat;     audioqueueref                   mqueue;     audioqueuebufferref             mbuffers[knumberbuffers];     uint64                          mpacketindex;     uint32                          mnumpacketstoread;     audiostreampacketdescription *  mpacketdescs;     bool                            mdone;     id<uksounddelegate>             delegate;     int                             maxbuffersizebytes; }  @property (assign) id<uksounddelegate> delegate;  -(id)   initwithcontentsofurl: (nsurl*)theurl;  -(void) notifydelegateplaybackstatechanged: (id)sender;  -(void) play;   // private: -(void) audioqueue: (audioqueueref)inaq processbuffer: (audioqueuebufferref)incompleteaqbuffer;  @end 

here's implementation:

// //  uksound.m //  mobilemoose // //  created uli kusterer on 14.07.08. //  copyright 2008 void software. rights reserved. //  #import "uksound.h"   static void uksoundaqbuffercallback(void *                  inuserdata,                                     audioqueueref           inaq,                                     audioqueuebufferref     incompleteaqbuffer) {     uksound*    myself = (uksound*)inuserdata;      [myself audioqueue: inaq processbuffer: incompleteaqbuffer]; }   static void uksoundaqpropertylistenercallback( void *                  inuserdata,                                                 audioqueueref           inaq,                                                 audioqueuepropertyid    inid) {     [(uksound*)inuserdata performselectoronmainthread: @selector(notifydelegateplaybackstatechanged:) withobject: nil waituntildone: no]; }   @implementation uksound  @synthesize delegate;  -(id)   initwithcontentsofurl: (nsurl*)theurl {     self = [super init];     if( self )     {         maxbuffersizebytes = 0x10000;         osstatus    err = audiofileopenurl( (cfurlref)theurl, kaudiofilereadpermission, 0, &maudiofile );         if( err != noerr )             nslog(@"couldn't open audiofile.");         uint32 size = sizeof(mdataformat);         err = audiofilegetproperty( maudiofile, kaudiofilepropertydataformat, &size, &mdataformat );         if( err != noerr )             nslog(@"couldn't determine audio file format.");         err = audioqueuenewoutput( &mdataformat, uksoundaqbuffercallback, self, null, null, 0, &mqueue );         if( err != noerr )             nslog(@"couldn't create new output queue.");          // have couple of things take care of         // (1) setting conditions around vbr or cbr format - affects how read file         // if format vbr need use packet table.         if( mdataformat.mbytesperpacket == 0 || mdataformat.mframesperpacket == 0 )         {             // first check see max size of packet - if bigger             // our allocation default size, needs become larger             uint32 maxpacketsize;             size = sizeof(maxpacketsize);             err = audiofilegetproperty( maudiofile, kaudiofilepropertypacketsizeupperbound, &size, &maxpacketsize);             if( err != noerr )                 nslog(@"couldn't max packet size of audio file.");             if( maxpacketsize > maxbuffersizebytes )                  maxbuffersizebytes = maxpacketsize;              // need packet descpriptions file reading             mnumpacketstoread = maxbuffersizebytes / maxpacketsize;             mpacketdescs = malloc( sizeof(audiostreampacketdescription) * mnumpacketstoread );         }         else         {             mnumpacketstoread = maxbuffersizebytes / mdataformat.mbytesperpacket;             mpacketdescs = null;         }          // (2) if file has cookie, should , set on aq         size = sizeof(uint32);         err = audiofilegetpropertyinfo( maudiofile, kaudiofilepropertymagiccookiedata, &size, null );         if( !err && size )         {             char* cookie = malloc( size );             err = audiofilegetproperty( maudiofile, kaudiofilepropertymagiccookiedata, &size, cookie );             if( err != noerr )                 nslog(@"couldn't magic cookie of audio file.");             err = audioqueuesetproperty( mqueue, kaudioqueueproperty_magiccookie, cookie, size );             if( err != noerr )                 nslog(@"couldn't transfer magic cookie of audio file qudio queue.");             free( cookie );         }          err = audioqueueaddpropertylistener( mqueue, kaudioqueueproperty_isrunning,                                     uksoundaqpropertylistenercallback,                                     self );         if( err != noerr )             nslog(@"couldn't register playback state changes.");              // prime queue data before starting         mdone = false;         mpacketindex = 0;         for( int = 0; < knumberbuffers; ++i )         {             err = audioqueueallocatebuffer( mqueue, maxbuffersizebytes, &mbuffers[i] );             if( err != noerr )                 nslog(@"couldn't allocate buffer %d.", i);              uksoundaqbuffercallback( self, mqueue, mbuffers[i] );              if( mdone ) break;         }     }      return self; }   -(void) dealloc {     osstatus err = audioqueuedispose( mqueue, true );     err = audiofileclose( maudiofile );     if( mpacketdescs )         free( mpacketdescs );      [super dealloc]; }   -(void) play {     osstatus err = audioqueuestart( mqueue, null );     if( err != noerr )         nslog(@"couldn't start audio queue.");     else         [self retain]; }   -(bool) isplaying {     uint32      state = no,                 size = sizeof(uint32);     osstatus    err = audioqueuegetproperty( mqueue, kaudioqueueproperty_isrunning, &state, &size );     if( err != noerr )         nslog(@"couldn't play state of queue.");      return state; }   -(void) notifydelegateplaybackstatechanged: (id)sender; {     if( ![self isplaying] )     {             nslog(@"insert functionality here.");         [delegate sound: self didfinishplaying: yes];         audioqueuestop( mqueue, false );         [self release];     } }   -(void) audioqueue: (audioqueueref)inaq processbuffer: (audioqueuebufferref)incompleteaqbuffer {     if( mdone )         return;      uint32 numbytes;     uint32 npackets = mnumpacketstoread;      // read npackets worth of data buffer     osstatus err = audiofilereadpackets( maudiofile, false, &numbytes, mpacketdescs, mpacketindex, &npackets,                                          incompleteaqbuffer->maudiodata);     if( err != noerr )         nslog(@"couldn't read buffer.");      if (npackets > 0)     {         incompleteaqbuffer->maudiodatabytesize = numbytes;                // queues buffer audio input/output.         err = audioqueueenqueuebuffer( inaq, incompleteaqbuffer, (mpacketdescs ? npackets : 0), mpacketdescs );         if( err != noerr )             nslog(@"couldn't enqueue buffer.");          mpacketindex += npackets;     }     else     {         uint32      state = no,                     size = sizeof(uint32);         osstatus    err = audioqueuegetproperty( mqueue, kaudioqueueproperty_isrunning, &state, &size );          // should calling following, makes app hang.         if( state )         {             err = audioqueuestop( mqueue, false );             if( err != noerr )                 nslog(@"couldn't stop queue.");                 // reading npackets == 0 our eof condition         }         mdone = true;     } }  @end 

when call initwithcontentsofurl: (nsurl*)theurl method, uksoundaqpropertylistenercallback added audio queue. set respond kaudioqueueproperty_isrunning audio queue property. after play method called , file finishes playing, uksoundaqpropertylistenercallback called in turn calls notifydelegateplaybackstatechanged method. have added nslog message method illustrate when file stops playing.

i'd happy share xcode project demonstrates functionality.


Comments

Popular posts from this blog

android - Spacing between the stars of a rating bar? -

aspxgridview - Devexpress grid - header filter does not work if column is initially hidden -

c# - How to execute a particular part of code asynchronously in a class -