First, introduce the framework audiotool.
-(ID) initwithpath :( nsstring *) path <br/>{< br/> uint32 size, maxpacketsize; <br/> char * cookie; <br/> int I; </P> <p> If (gthereisanactivetrack) <br/> {<br/> nslog (@ "*** warning *** gbmusictrack only plays one track at a time! You must close the previusly running track "<br/>" before you can play another. requested track was: % @ ", [path lastpathcomponent]); <br/> return nil; <br/>}< br/> // if the path does not exist, null is returned. <br/> If (Path = nil) return nil; <br/> // initialization <br/> If (! (Self = [Super init]) return nil; </P> <p> // open the music in the specified path <br/> If (noerr! = Audiofileopenurl (cfurlref) [nsurl fileurlwithpath: path], 0x01, 0, & audiofile )) <br/> {<br/> nslog (@ "*** error *** gbmusictrack-initwithpath: cocould not open audio file. path given was: % @ ", PATH); <br/> return nil; <br/>}</P> <p> // obtain the data type of the file <br/> size = sizeof (dataformat); <br/> audiofilegetproperty (audiofile, kaudiofilepropertydataformat, & size, & dataformat); </P> <p> // creates a new queue using the specified special data type. And callback cache. </P> <p> audioqueuenewoutput (& dataformat, buffercallback, self, nil, nil, 0, & Queue ); </P> <p> // read the package size and allocate the required space if necessary <br/> If (dataformat. mbytesperpacket = 0 | dataformat. mframesperpacket = 0) <br/>{< br/> // since we didn't get sizes to work with, then this must be VBR data (variable bitrate ), so <br/> // we'll have to ask core audio to give us a conservative estimate of the largest packet we are <br/> // likely to read with kaudiofilepropertypacketsizeupperbound <br /> size = sizeof (maxpacketsize ); <br/> audiofilegetproperty (audiofile, audio, & size, & maxpacketsize); <br/> If (maxpacketsize> gbuffersizebytes) <br/>{< br/> maxpacketsize = gbuffersizebytes; <br/> nslog (@ "*** warning *** gbmusictrack-initwithpath: had to limit packet size requested for file: % @", [path lastpathcomponent]); <br/>}< br/> numpacketstoread = gbuffersizebytes/maxpacketsize; </P> <p> // allocate space to the package description <br/> packetdescs = malloc (sizeof (audiostreampacketdescription) * numpacketstoread ); <br/>}< br/> else <br/> {<br/> // for CBR data (constant bitrate ), use appropriate data to fill in the hybrid village <br/> numpacketstoread = gbuffersizebytes/dataformat. mbytesperpacket; </P> <p> // the description of this package is not required. <br/> packetdescs = nil; <br/>}</P> <p> // see if file uses a Magic cookie (a Magic cookie is meta data which some formats use) <br/> audiofilegetpropertyinfo (audiofile, kaudiofilepropertymagiccookiedata, & size, nil); <br/> If (size> 0) <br/> {<br/> // copy the cached data from the file and put it in the audio queue. <br/> cookie = malloc (sizeof (char) * size ); <br/> audiofilegetproperty (audiofile, kaudiofilepropertymagiccookiedata, & size, cookie); <br/> audioqueuesetproperty (queue, queue, Cookie, size); <br/> free (cookie ); <br/>}< br/> audioqueueaddpropertylistener (queue, kaudioqueueproperty_isrunning, propertylistenercallback, self ); </P> <p> // allocate data to a specific cache <br/> packetindex = 0; <br/> for (I = 0; I <num_queue_buffers; I ++) <br/>{< br/> audioqueueallocatebuffer (queue, gbuffersizebytes, & buffers [I]); <br/> If ([self readpacketsintobuffer: buffers [I] = 0)
A slightly lower-layer function allows us to simply encapsulate it so that it can be used more conveniently.
Static
Gbmusictrack
*
Track;
Static
Nsmutabledictionary
*
Trackfiles;
Static
Bool enabled _
=
True;
Static
Bool musicvolume _
=
1.0f
;
// Add the audio file to the dictionary by name
+
(
Void
) Addmusictrack :( nsstring
*
) Filename name :( nsstring
*
) Name {
If
(Trackfiles
=
Nil ){
Trackfiles
=
[[Nsmutabledictionary alloc] init];
}
[Trackfiles setobject: Filename forkey: Name];
}
// Check whether the dictionary is empty and whether there are audio files.
+
(Bool) hasmusictrack :( nsstring
*
) Name {
Id OBJ
=
[Trackfiles objectforkey: Name];
If
(OBJ
=
Nil)
Return
False;
Else
Return
True;
}
// Encapsulate the method mentioned above. The parameter is the name of the playback and whether to play the video repeatedly.
+
(
Void
) Playmusictrack :( nsstring
*
) Name withrepeat :( bool) B {
# Ifndef debug_no_sound
If
(
!
Enabled _)
Return
;
If
(Trackfiles
=
Nil)
Return
;
If
(Track
! =
Nil ){
@ Try {
[Self stopcurrenttrack];
}
@ Catch (nsexception
*
Ex ){
Nslog ([ex description]);
}
}
// This function initwithpath is mentioned above. Initialization Method.
//
Track
=
[[Gbmusictrack alloc] initwithpath: [nsbundle mainbundle]
Pathforresource: [trackfiles objectforkey: Name]
Oftype:
@"
MP3
"
];
[Track setrepeat: B];
[Track setvolume: musicvolume _];
// Play music
[Track play];
# Endif
}