您的位置:首页 > 移动开发 > Objective-C

分享一段Objective-C可调用的游戏中播放音乐

2010-03-11 09:05 369 查看
首先需要引入AudioTool 这个framework

- (id)initWithPath:(NSString *)path
{
UInt32        size, maxPacketSize;
char        *cookie;
int            i;

if (gThereIsAnActiveTrack)
{
NSLog(@"*** WARNING *** GBMusicTrack only plays one track at a time! You must close the previously running track"
" before you can play another. Requested track was: %@", [path lastPathComponent]);
return nil;
}
//路径不存在的话返回空
if (path == nil) return nil;
// 初始化  
if(!(self = [super init])) return nil;

// 通过指定的路径打开音乐
if (noErr != AudioFileOpenURL((CFURLRef)[NSURL fileURLWithPath:path], 0x01, 0, &audioFile))
{
NSLog(@"*** Error *** GBMusicTrack - initWithPath: could not open audio file. Path given was: %@", path);
return nil;
}

// 得到文件的数据类型
size = sizeof(dataFormat);
AudioFileGetProperty(audioFile, kAudioFilePropertyDataFormat, &size, &dataFormat);

// 创建一个新的队列,使用的是指定的特殊数据类型和回调缓存。

AudioQueueNewOutput(&dataFormat, BufferCallback, self, nil, nil, 0, &queue);

// 如果需要的话读取包的大小并且分配所需要的空间
if (dataFormat.mBytesPerPacket == 0 || dataFormat.mFramesPerPacket == 0)
{
// since we didn't get sizes to work with, then this must be VBR data (Variable BitRate), so
// we'll have to ask Core Audio to give us a conservative estimate of the largest packet we are
// likely to read with kAudioFilePropertyPacketSizeUpperBound
size = sizeof(maxPacketSize);
AudioFileGetProperty(audioFile, kAudioFilePropertyPacketSizeUpperBound, &size, &maxPacketSize);
if (maxPacketSize > gBufferSizeBytes)
{
maxPacketSize = gBufferSizeBytes;
NSLog(@"*** Warning *** GBMusicTrack - initWithPath: had to limit packet size requested for file: %@", [path lastPathComponent]);
}
numPacketsToRead = gBufferSizeBytes / maxPacketSize;

//给包的描述分配空间
packetDescs = malloc(sizeof(AudioStreamPacketDescription) * numPacketsToRead);
}
else
{
// 对于CBR 数据 (Constant BitRate), 使用合适的数据填充到混村中
numPacketsToRead = gBufferSizeBytes / dataFormat.mBytesPerPacket;

// 这种包的描述不需要
packetDescs = nil;
}

// see if file uses a magic cookie (a magic cookie is meta data which some formats use)
AudioFileGetPropertyInfo(audioFile, kAudioFilePropertyMagicCookieData, &size, nil);
if (size > 0)
{
// 把缓存数据从文件中copy出来放到音频队列中
cookie = malloc(sizeof(char) * size);
AudioFileGetProperty(audioFile, kAudioFilePropertyMagicCookieData, &size, cookie);
AudioQueueSetProperty(queue, kAudioQueueProperty_MagicCookie, cookie, size);
free(cookie);
}
AudioQueueAddPropertyListener(queue, kAudioQueueProperty_IsRunning, propertyListenerCallback, self);

// 给特定的缓存分配数据
packetIndex = 0;
for (i = 0; i < NUM_QUEUE_BUFFERS; i++)
{
AudioQueueAllocateBuffer(queue, gBufferSizeBytes, &buffers[i]);
if ([self readPacketsIntoBuffer:buffers[i]] == 0)


稍微底层一点的函数,我们对此进行简单的封装,以至于可以更加方便的使用。

static
GBMusicTrack
*
track;

static
NSMutableDictionary
*
trackFiles;

static
BOOL enabled_
=
TRUE;

static
BOOL musicVolume_
=
1.0f
;

//把音频文件按着名字添加到字典中

+
(
void
) addMusicTrack:(NSString
*
)filename name:(NSString
*
)name {

if
(trackFiles
==
nil) {

trackFiles
=
[[NSMutableDictionary alloc] init];

}

[trackFiles setObject:filename forKey:name];

}

//通过判断字典中是否为空,看有没有音频文件。

+
(BOOL)hasMusicTrack:(NSString
*
)name {

id obj
=
[trackFiles objectForKey:name];

if
(obj
==
nil)
return
FALSE;

else

return
TRUE;

}

//对上文提及的方法进行封装,参数是播放的名字,和是否重复播放

+
(
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]);

}

}

// 这个函数initWithPath就是上文提及的,初始化方法。

//

track
=
[[GBMusicTrack alloc] initWithPath:[[NSBundle mainBundle]

pathForResource:[trackFiles objectForKey:name]

ofType:
@"
mp3
"
]];

[track setRepeat:b];

[track setVolume:musicVolume_];

// 音乐的播放

[track play];

#endif

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: