`

在iPhone中使用AudioQueue实现音频播放

    博客分类:
  • ios
 
阅读更多

(转)http://blog.chinaunix.net/uid-25788167-id-366155.html

AudioQueueMac OS XiPhone中提供录音、播放功能的高级框架,比AudioUnit等框架更方便,而且不要求掌握更多专门的知识。

AudioQueue的名称就可以看出,AudioQueue框架以队列的形式处理音频数据。因此使用时需要给队列分配缓存空间,由回调(Callback)函数完成向队列缓存读写音频数据的功能。另外,AudioQueueAudioToolbox框架的一部分,使用前需要将AudioToolbox框架导入进来。

使用AudioQueue来实现音频播放功能时最主要的步骤,可以更简练的归纳如下。

1. 打开播放音频文件

2. 取得播放音频文件的数据格式

3. 准备播放用的队列

4. 将缓冲中的数据移动到队列中

5. 开始播放

6. 在回调函数中进行队列处理

以下是贯彻上述六个主要步骤的代码实例,只需要向[play:]中传入音频文件的路径就可以开始音频播放。稍加修改可以直接应用到自己的程序中。

Source Audioplay.h

#import <Foundation/Foundation.h>

#import <AudioToolbox/AudioToolbox.h>

#import <AudioToolbox/AudioFile.h>

 

#define NUM_BUFFERS 3

 

@interface AudioPlayer : NSObject {

        //播放音频文件ID

    AudioFileID audioFile;

        //音频流描述对象

    AudioStreamBasicDescription dataFormat;

        //音频队列

    AudioQueueRef queue;

    SInt64 packetIndex;

    UInt32 numPacketsToRead;

    UInt32 bufferByteSize;

    AudioStreamPacketDescription *packetDescs;

    AudioQueueBufferRef buffers[NUM_BUFFERS];

}

//定义队列为实例属性

@property AudioQueueRef queue;

//播放方法定义

- (void) play:(CFURLRef) path;

//定义缓存数据读取方法

- (void) audioQueueOutputWithQueue:(AudioQueueRef)audioQueue

                       queueBuffer:(AudioQueueBufferRef)audioQueueBuffer;

//定义回调(Callback)函数

static void BufferCallback(void *inUserData, AudioQueueRef inAQ,

                                            AudioQueueBufferRef buffer);

//定义包数据的读取方法

- (UInt32)readPacketsIntoBuffer:(AudioQueueBufferRef)buffer;

 

@end

 

Source Audioplay.m

static UInt32 gBufferSizeBytes = 0x10000;

 

@implementation AudioPlayer

 

@synthesize queue;

 

// 回调(Callback)函数的实现

static void BufferCallback(void *inUserData, AudioQueueRef inAQ,

  AudioQueueBufferRef buffer) {

    AudioPlayer* player = (AudioPlayer*)inUserData;

    [player  audioQueueOutputWithQueue:inAQ queueBuffer:buffer];

}

//初始化方法(为NSObject中定义的初始化方法)

- (id) init {

    for(int i=0; i<NUM_BUFFERS; i++) {

        AudioQueueEnqueueBuffer(queue,buffers[i],0,nil);

    }

    return self;

}

//缓存数据读取方法的实现

- (void) audioQueueOutputWithQueue:(AudioQueueRef)audioQueue

                       queueBuffer:(AudioQueueBufferRef)audioQueueBuffer {

    OSStatus status;

 

    // 读取包数据

    UInt32  numBytes;

    UInt32  numPackets = numPacketsToRead;

    status = AudioFileReadPackets(

                audioFile, NO, &numBytes, packetDescs,

                packetIndex, &numPackets, audioQueueBuffer->mAudioData);

 

    // 成功读取时

    if (numPackets > 0) {

        //将缓冲的容量设置为与读取的音频数据一样大小(确保内存空间)

        audioQueueBuffer->mAudioDataByteSize = numBytes;

 

        // 完成给队列配置缓存的处理

        status = AudioQueueEnqueueBuffer(

                audioQueue, audioQueueBuffer, numPackets, packetDescs);

 

        // 移动包的位置

        packetIndex += numPackets;

    }

 

}

//音频播放方法的实现

-(void) play:(CFURLRef) path {

    UInt32      size, maxPacketSize;

    char        *cookie;

    int         i;

    OSStatus status;

 

    // 打开音频文件

    status = AudioFileOpenURL(path, kAudioFileReadPermission, 0, &audioFile);

    if (status != noErr) {

        // 错误处理

        return;

    }

 

    // 取得音频数据格式

    size = sizeof(dataFormat);

    AudioFileGetProperty(audioFile, kAudioFilePropertyDataFormat,

                                                   &size, &dataFormat);

 

    // 创建播放用的音频队列

    AudioQueueNewOutput(&dataFormat, BufferCallback,

                               self, nil, nil, 0, &queue);

 

    //计算单位时间包含的包数

    if (dataFormat.mBytesPerPacket==0 || dataFormat.mFramesPerPacket==0) {

        size = sizeof(maxPacketSize);

        AudioFileGetProperty(audioFile,

          kAudioFilePropertyPacketSizeUpperBound, &size, &maxPacketSize);

        if (maxPacketSize > gBufferSizeBytes) {

            maxPacketSize = gBufferSizeBytes;

        }

        // 算出单位时间内含有的包数

        numPacketsToRead = gBufferSizeBytes / maxPacketSize;

        packetDescs = malloc(

          sizeof(AudioStreamPacketDescription) * numPacketsToRead);

    } else {

        numPacketsToRead = gBufferSizeBytes / dataFormat.mBytesPerPacket;

        packetDescs = nil;

    }

    //设置Magic Cookie,参见第二十七章的相关介绍

    AudioFileGetPropertyInfo(audioFile,

           kAudioFilePropertyMagicCookieData, &size, nil);

    if (size > 0) {

        cookie = malloc(sizeof(char) * size);

        AudioFileGetProperty(audioFile,

                  kAudioFilePropertyMagicCookieData, &size, cookie);

        AudioQueueSetProperty(queue,

                  kAudioQueueProperty_MagicCookie, cookie, size);

        free(cookie);

    }

 

    // 创建并分配缓存空间

    packetIndex = 0;

    for (i = 0; i < NUM_BUFFERS; i++) {

        AudioQueueAllocateBuffer(queue, gBufferSizeBytes, &buffers[i]);

        //读取包数据

        if ([self readPacketsIntoBuffer:buffers[i]] == 0) {

            break;

        }

    }

 

    Float32 gain = 1.0;

    //设置音量

    AudioQueueSetParameter (

                            queue,

                            kAudioQueueParam_Volume,

                            gain

                            );

    //队列处理开始,此后系统会自动调用回调(Callback)函数

    AudioQueueStart(queue, nil);

}

 

- (UInt32)readPacketsIntoBuffer:(AudioQueueBufferRef)buffer {

    UInt32      numBytes, numPackets;

 

    // 从文件中接受包数据并保存到缓存(buffer)

    numPackets = numPacketsToRead;

    AudioFileReadPackets(audioFile, NO, &numBytes, packetDescs,

                       packetIndex, &numPackets, buffer->mAudioData);

    if (numPackets > 0) {

        buffer->mAudioDataByteSize = numBytes;

        AudioQueueEnqueueBuffer(queue, buffer,

              (packetDescs ? numPackets : 0), packetDescs);

        packetIndex += numPackets;

    }

    return numPackets;

}

 

@end

分享到:
评论

相关推荐

    iPhone简易音频播放程序

    AVAudioPlayer类是AVFoundation中的核心,用于播放音频文件。你需要了解如何初始化AVAudioPlayer,设置音频源(如本地音乐文件),并控制播放、暂停、停止、跳转等功能。此外,AVAudioSession用于管理应用程序的音频...

    iphone AVAudioPlayer类 音频播放

    在iOS开发中,AVFoundation框架中的AVAudioPlayer类是一个非常重要的组件,用于播放音频文件。这个类提供了简单易用的接口,使得开发者可以方便地控制音频的播放、暂停、停止等操作。本篇文章将深入探讨如何使用...

    小程序ios音频播放没声音问题的解决

    在实现录音功能时,开发者需要创建一个`recorderManager`实例。通过`recorderManager.start(options)`方法,可以开始录音,并通过`recorderManager.onStop`回调函数获取录音结束后的本地临时文件路径。随后,通过...

    iOS声音采集与播放Object C

    4. 音频数据回调:在AudioQueue中注册回调函数,这个函数会在录音时被调用,将新捕获的音频数据放入缓冲区。在播放时,这个回调会被用来获取缓冲区中的数据并发送给硬件播放。 5. 启动和停止:启动AudioQueue开始...

    iphone上面实现播放视频文件,自己开发的播放器

    本项目标题为“iPhone上面实现播放视频文件,自己开发的播放器”,表明我们需要关注的核心是构建一个能够播放多种视频和音频格式的应用程序。以下是关于这一主题的详细知识点: 1. **多媒体框架**:iOS中的多媒体...

    cocoa iPhone 音频流媒体 demo

    AVAudioPlayer类是AVFoundation中用于播放音频的主要组件,它可以处理本地文件和流媒体资源。 4. **URLSession**:在AudioStreamer中,URLSession用于从服务器获取音频流数据。URLSession是iOS中的网络请求API,...

    iphone的safari浏览器中实现全屏浏览的方法

    在iPhone的Safari浏览器中实现全屏浏览可以让用户在查看网页内容时获得更沉浸式的体验。通常,Safari浏览器在浏览网页时会显示顶部的工具栏和底部的标签页栏,这占据了屏幕的一部分空间。全屏浏览则可以隐藏这些元素...

    在线视频、音频播放

    在线视频和音频播放是移动应用开发中的重要组成部分,特别是在iOS平台上。这个项目源码提供了iPhone上的完整实现,对于想要深入理解这一领域的开发者来说是一个宝贵的资源。以下是对该项目源码涉及的关键知识点的...

    SoundManager, 在Mac和iPhone上,播放音频的简单声音和音乐播放器类.zip

    SoundManager, 在Mac和iPhone上,播放音频的简单声音和音乐播放器类 命令行目SoundManager是在iOS或者Mac应用程序中播放声音和音乐的简单类。支持的操作系统&版本支持 build/Mac 8.0操作系统 10.8 ( Xcode 6.0,苹果...

    iPhone支持多路mp3声音播放的完整演示工程

    `AVAudioPlayer`是用于播放音频文件的主要类,它支持多种格式,包括mp3。通过创建`AVAudioPlayer`实例,我们可以加载mp3文件并控制播放、暂停、停止、调整音量等操作。在多路播放中,我们需要为每个mp3文件创建一个...

    iphone 本地视频播放源码

    2. **AVPlayer:** 这是AVFoundation中的主要播放器对象,负责播放音频和视频内容。通过创建AVPlayer实例,指定播放的AVPlayerItem,我们可以实现视频的播放功能。 3. **AVPlayerItem:** 它代表一个播放队列中的...

    uniapp实现录音、播放功能.rar

    在本文中,我们将深入探讨如何使用uniapp框架来实现类似微信的录音和播放功能。uniapp是一个基于Vue.js开发的多端合一的应用框架,能够帮助开发者编写一次代码,发布到iOS、Android、Web(H5)、以及各种小程序等多...

    ios剪刀布小游戏(音频和音效的播放)

    在iOS开发中,实现一款剪刀石头布小游戏不仅涉及到用户界面设计,还需要处理音频和音效的播放。本文将深入探讨如何在iOS平台上构建这样的应用,重点讲解音频管理及音效播放的关键技术。 首先,iOS提供了多种音频...

    android、iphone音频文件amr和wav的转换

    AMR文件通常较小,适合在网络传输中使用。 相反,WAV是未经压缩的音频格式,保留了原始音频的所有细节,提供最高质量的音频,但文件体积相对较大。在需要高质量音频或编辑音频时,WAV格式更为合适。 在iPhone开发...

    cocos2d iphone 中文开发资料大全

    6. **音频管理**:学习如何使用Cocos2d-iPhone的音频引擎播放背景音乐和音效,包括音乐的循环、淡入淡出效果等。 7. **脚本语言支持**:Cocos2d-iPhone支持Lua和JavaScript,允许开发者用这些脚本语言编写游戏逻辑...

    IPhone SpeakHere例子源代码

    综上所述,SpeakHere源代码不仅展示了Core Audio在录音和播放中的应用,还涵盖了AudioSession管理、AudioQueue服务的使用、硬件音量控制以及错误处理和用户界面设计等多个方面。对于希望深入理解iOS音频编程的开发者...

    iPhone播放声音例子

    在这个框架中,AVAudioPlayer类是用于播放音频的核心组件。我们可以使用这个类来加载音频文件并控制播放、暂停、停止等操作。 1. **引入AVFoundation框架** 在你的项目中,你需要先导入AVFoundation框架。在...

    iphone音乐播放器代码

    在实现过程中,开发者可能使用AVPlayer类来加载和播放音频文件,AVPlayerItem来管理播放内容,而AVPlayerLayer可以用来在屏幕上显示播放进度。此外,可能还会用到MPMediaPickerController,它允许用户从设备的音乐库...

Global site tag (gtag.js) - Google Analytics