了解iPhone游戏开发中声音处理流播放文件

移动开发 iOS 游戏开发
本文主要是了解iPhone游戏开发中声音处理流播放文件,好处是可以快速的开始播放,减少读文件的过程,适合大文件特别是背景音乐的播放。

了解iPhone游戏开发中声音处理流播放文件是本文介绍的内容,流播放文件即用AudioStream 和 AudioQueue 来播放文件。好处是可以快速的开始播放,减少读文件的过程,适合大文件特别是背景音乐的播放。坏处是一次只能播放一个文件,如果要换播放文件,中间需要一定的时间。但是因为iPhone文件读取时间只有10秒,对于资源较大的文件,只能考虑这个方式了。

下面我将分享一下我在这方面的一点经验:1. 单个文件播放2. 在线文件播放

1. 单个文件播放

BOOL isPlaying;    
/*-------------------USED FOR LOCAL FILE--------------------*/    
AudioFileID audioFile;    
AudioStreamBasicDescription dataFormat;    
AudioStreamPacketDescription *packetDescs;    
UInt64 packetIndex;    
UInt32 numPacketsToRead;    
BOOL repeat;    
BOOL trackClosed;    
/*--------------------USED FOR PUBLIC------------------------*/    
BOOL trackEnded;    
    
AudioQueueRef queue;    
AudioQueueBufferRef buffers[NUM_QUEUE_BUFFERS];   
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.

以上是需要定义的为单独文件播放的所需要的元素。可以定义在类里面。

2. 在线文件播放

NSURL *url;    
AudioFileStreamID audioFileStream; // the audio file stream parser    
AudioStreamPacketDescription packetDescsQueue[kAQMaxPacketDescs]; // packet descriptions for enqueuing audio   
CFReadStreamRef stream;    
unsigned int fillBufferIndex; // the index of the audioQueueBuffer that is being filled    
size_t bytesFilled; // how many bytes have been filled    
size_t packetsFilled; // how many packets have been filled    
bool inuse[kNumAQBufs]; // flags to indicate that a buffer is still in use    
bool started; // flag to indicate that the queue has been started    
bool failed; // flag to indicate an error occurred    
bool discontinuous; // flag to trigger bug-avoidance    
pthread_mutex_t mutex; // a mutex to protect the inuse flags    
pthread_cond_t cond; // a condition varable for handling the inuse flags    
pthread_mutex_t mutex2; // a mutex to protect the AudioQueue buffer    
BOOL trackEnded;    
AudioQueueRef queue;    
AudioQueueBufferRef buffers[NUM_QUEUE_BUFFERS];   
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.

利用http1.1协议播放在线文件。以上是在线文件播放所需要的参数。

#define NUM_QUEUE_BUFFERS 3    
#define kNumAQBufs 6 // number of audio queue buffers we allocate    
#define kAQBufSize 32 * 1024 // number of bytes in each audio queue buffer    
#define kAQMaxPacketDescs 512 // number of packet descriptions in our array   
  • 1.
  • 2.
  • 3.
  • 4.

这里是定义的一些参数,NUM_QUEUE_BUFFERS 用于播放本地文件,而 kNumAQBufs 用于播放在线文件。

3. 本地文件初始化

- (id)initWithPath:(NSString*)path    
{    
UInt32 size, maxPacketSize;    
char *cookie;    
int i;    
    
if (kxxxTrackActive)    
{    
NSLog(@"Other music is playing.");    
return nil;    
}    
    
if (path == nil) return nil;    
if(!(self = [super init])) return nil;    
    
// try to open up the file using the specified path    
if (noErr != AudioFileOpenURL((CFURLRef)[NSURL fileURLWithPath:path], 0x01, 0, &audioFile))    
{    
NSLog(@"File can not be opened!");    
return nil;    
}    
    
// get the data format of the file    
size = sizeof(dataFormat);    
AudioFileGetProperty(audioFile, kAudioFilePropertyDataFormat, &size, &dataFormat);    
    
// create a new playback queue using the specified data format and buffer callback    
AudioQueueNewOutput(&dataFormat, BufferCallback, self, nil, nil, 0, &queue);    
    
// calculate number of packets to read and allocate space for packet descriptions if needed    
if (dataFormat.mBytesPerPacket == 0 || dataFormat.mFramesPerPacket == 0)    
{    
// Ask Core Audio to give us a conservative estimate of the largest packet    
size = sizeof(maxPacketSize);    
AudioFileGetProperty(audioFile, kAudioFilePropertyPacketSizeUpperBound, &size, &maxPacketSize);    
if (maxPacketSize > kxxxBufferSizeBytes)    
{    
/*Limitation for the maximum buffer size*/    
maxPacketSize = kxxxBufferSizeBytes;    
NSLog(@"Size out of bounds!");    
}    
// calculate how many packs to read    
numPacketsToRead = kxxxBufferSizeBytes / maxPacketSize;    
    
// will need a packet description for each packet to allocate space accordingly    
packetDescs = malloc(sizeof(AudioStreamPacketDescription) * numPacketsToRead);    
}    
else    
{    
// constant bitrate    
numPacketsToRead = kxxxBufferSizeBytes / dataFormat.mBytesPerPacket;    
    
// don't need packet descriptions for CBR data    
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 the cookie data from the file into the audio queue    
cookie = malloc(sizeof(char) * size);    
AudioFileGetProperty(audioFile, kAudioFilePropertyMagicCookieData, &size, cookie);    
AudioQueueSetProperty(queue, kAudioQueueProperty_MagicCookie, cookie, size);    
free(cookie);    
}    
    
// we want to know when the playing state changes so we can properly dispose of the audio queue when it's done    
AudioQueueAddPropertyListener(queue, kAudioQueueProperty_IsRunning, propertyListenerCallback, self);    
    
// allocate and prime buffers with some data    
packetIndex = 0;    
for (i = 0; i < NUM_QUEUE_BUFFERS; i++)    
{    
AudioQueueAllocateBuffer(queue, kxxxBufferSizeBytes, &buffers);    
if ([self readPacketsIntoBuffer:buffers] == 0)    
{    
// this might happen if the file was so short that it needed less buffers than we planned on using    
break;    
}    
}    
repeat = NO;    
trackClosed = NO;    
trackEnded = NO;    
kxxxTrackActive = YES;    
return self;    
}   
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.

4. 在线文件初始化

- (id)initWithURL:(NSURL*)newUrl    
{    
self = [super init];    
if (self != nil)    
{    
url = [newUrl retain];    
}    
return self;    
}   
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

算了,废话不多说了,直接上代码,等以后有时间了再逐一解释。

小结了解iPhone游戏开发中声音处理流播放文件的内容介绍完了,希望通过本文的学习能对你有所帮助!

责任编辑:zhaolei 来源: 互联网
相关推荐

2012-12-27 14:29:38

Android开发流媒体

2011-07-22 15:59:15

iPhone 声音 文件

2011-08-04 17:19:49

iPhone开发 Xcode 文档

2011-08-22 15:15:49

iPhone开发NSMutableAr排序

2011-08-10 15:58:58

iPhone视频

2011-07-18 11:07:12

iPhone 游戏 引擎

2011-07-18 10:53:09

2011-07-18 12:29:10

2011-07-18 11:39:58

iPhone 游戏 引擎

2011-07-18 11:23:29

iPhone 游戏 动画

2011-08-02 13:35:41

iOS开发 Get Post

2011-08-12 14:33:06

iPhone缓存文件

2011-07-29 13:27:48

iPhone 开发 Nib

2011-08-08 18:19:09

iPhone音频播放

2011-08-09 14:42:07

iPhonePCM播放器

2020-09-28 06:50:02

DuerOS 智能语音

2011-07-08 20:32:57

iPhone midi

2010-01-07 18:22:40

VB.NET声音播放

2011-08-01 14:34:06

iPhone 声音 音频

2011-08-02 10:36:02

iOS开发 SDK 多媒体
点赞
收藏

51CTO技术栈公众号