程序名:oalTouch (OpenAL的一个应用)
功能:
通过AVAudioPlayer播放背景音乐,通过OpenAL播放自定音乐,其中自定音乐可播放、暂停,当两个音乐同时播放时可实现混音效果。(我去掉了重力检测和AudioSession两个非主要功能)
实现步骤:
直接调用AVAudioPlayer播放音乐较为简单:
- 通过AVAudioPlay的init方法设定音乐文件的路径
- 通过其play方法播放背景音乐
使用openAL播放音乐实现步骤较为烦琐,此处由于用OpenAL播放的只有一个音乐,去掉了创建Session的内容。
- 得到设备device
- 创建一块设备的音频存储空间context
- 把音频数据data添加到缓存buffer中
- 把缓存buffer附加到数据源source中
- 播放数据源source
关键代码:
一、AVAudioPlayer播放音乐
1 NSURL *bgURL = [[NSURL alloc] initFileURLWithPath: [[NSBundle mainBundle] pathForResource:@"background" ofType:@"m4a"]];
2 bgPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:bgURL error:nil];
3 bgPlayer.numberOfLoops = -1; // infinite loop
4 if (bgPlayer) {
5 [bgPlayer play];
6 }
二、OpenAL
1. 初始化设备device和音频存储空间context
1 -(void)initOpenAL
2 {
3 // Initialization
4 mDevice = alcOpenDevice(NULL); // select the "preferred device"
5 if (mDevice) {
6 // use the device to make a context
7 mContext = alcCreateContext(mDevice,NULL);
8 // set my context to the currently active one
9 alcMakeContextCurrent(mContext);
10 }
11 }
2. 得到音乐文件长度
1 -(AudioFileID)openAudioFile:(NSString*)filePath // 给出文件路径调用此方法得到fileID
2 {
3 AudioFileID outAFID;
4 // use the NSURl instead of a cfurlref cuz it is easier
5 NSURL * afUrl = [NSURL fileURLWithPath:filePath];
6
7 // do some platform specific stuff..
8 OSStatus result = AudioFileOpenURL((CFURLRef)afUrl, kAudioFileReadPermission, 0, &outAFID);
9 if (result != 0) NSLog(@"cannot openf file: %@",filePath);
10 return outAFID;
11 }
12 -(UInt32)audioFileSize:(AudioFileID)fileDescriptor // 给出fileID调用此方法,得到fileSize
13 {
14 UInt64 outDataSize = 0;
15 UInt32 thePropSize = sizeof(UInt64);
16 OSStatus result = AudioFileGetProperty(fileDescriptor, kAudioFilePropertyAudioDataByteCount, &thePropSize, &outDataSize);
17 if(result != 0) NSLog(@"cannot find file size");
18 return (UInt32)outDataSize;
19 }
3. 得到音乐数据
1 unsigned char * outData = malloc(fileSize);
2 // this where we actually get the bytes from the file and put them
3 // into the data buffer
4 OSStatus result = noErr;
5 result = AudioFileReadBytes(fileID, false, 0, &fileSize, outData);
6 AudioFileClose(fileID); //close the file
4. 得到缓存buffer
1 alGenBuffers(1, &bufferID);
2 // jam the audio data into the new buffer
3 // 16位立体声格式,8k采样频率
4 alBufferData(bufferID, AL_FORMAT_STEREO16, outData, fileSize, 8000);
5. 得到数据源source
1 alGenSources(1, &sourceID);
2 // attach the buffer to the source
3 alSourcei(sourceID, AL_BUFFER, bufferID);
4 // loop the sound
5 alSourcei(sourceID, AL_LOOPING, AL_TRUE);
程序效果:
背景音乐播放的是一个进行曲
按Play/Pause可播放或暂停自己的音乐文件(一个bubble声)
附件:
附件中的项目OpenALTest实现了oalTouch中的主要功能,大家可以下载源码看看