[iphone-cocos2d]分享一段Objective-C可调用的游戏中播放音乐
首先需要引入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)
{
// 检查读取到缓存中的包的大小
break;
}
}
repeat = NO;
trackClosed = NO;
trackEnded = NO;
gThereIsAnActiveTrack = YES;
return self;
}
// Created by Jake Peterson (AnotherJake) on 7/6/08.
// Copyright 2008 Jake Peterson. All rights reserved.
防盗加个链接:
作者:Alexliu(alex dotNet Learning)
出处:http://alexliu.cnblogs.com/
稍微底层一点的函数,我们对此进行简单的封装,以至于可以更加方便的使用
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
}

浙公网安备 33010602011771号