Core Audio音频基础概述

1、Core Audio

Core Audio提供了数字音频服务为iOS与OS X, 它提供了一系列框架去处理音频.

Core Audio中包含我们最常用的Audio Toolbox与Audio Unit框架.

  • 使用Audio Queue做录制,播放,暂停,循环与同步音频

  • 使用Audio File, Converter, Codec Services去从磁盘读取与写入以及执行音频转换等功能.

  • 使用Audio Unit与Audio Processing Graph在应用程序中管理音频单元.在OS X中可以自定义audio units.

  • 使用Music Sequencing Services播放基于MIDI控制的音频数据

  • 使用Core Audio Clock Services用于音频和MIDI同步以及时间格式管理

  • 使用System Sound Services播放系统声音与界面的音效.

Core Audio在iOS中针对移动平台的计算资源作出了优化,同时,音频服务必须严格由系统进行管理,特别是HAL与I/O Kit,然而Apple也提供了只在iOS平台中才有的服务,如Audio Session Service将帮助我们管理音频上下文.

1.1 Digital Audio与Linear PCM

PCM是最常用的无损压缩数字音频格式数据,根据采样率以规则间隔测量模拟(真实世界)数字音频信号并将每个采集到的样本转换为数值来创建PCM数据.如标准光盘(CD)音频使用44.1 kHz的采样率,16位整数描述每个样本 - 构成分辨率或位深度。

  • sample:一个采样点是对单声道采集到声音的数值

  • frame:一帧数据是一组时间一致的samples,如双声道声音文件中一帧有两个samples,一个左声道,一个右声道.

  • packet:一个或多个连续帧的集合.在线性PCM中,一个packet总是单帧.在其他压缩格式中,一个packet定义给定音频数据格式的最小有意义的帧组。

iOS中使用integer与fixed-point音频数据,目的是在处理音频数据时增加计算速度,减小电池能耗.iOS也提供了来自Audio Converter Services的Converter audio unit服务.

iOS与OS X中,Core Audio提供了最常用的文件格式用于存储域播放音频数据.

1.2 Audio Unit

Apple针对移动平台对iOS的Audio Unit作出了效率与性能优化,在开发中我们必须将audio unit静态编译进APP,所以无法使用别的APP中的Audio Unit.

1.3 HAL(Hardware Abstraction Layer)

大多情况下,我们无法直接与HAL进行交互,Apple提供了一个特别的audio unit,即OS X中的AUHAL, iOS中的AURemoteIO, 我们可以通过它们让音频与硬件交互.

1.4 Properties, Scopes, and Elements

Core Audio接口中使用property管理对象的行为与状态.

  • 属性通常用易记忆的关键字格式,如kAudioFilePropertyFileFormat or kAudioQueueDeviceProperty_NumberChannels.

  • 属性值适用于特定的数据类型,如void*, Float64, AudioChannelLayout...

  • Core Audio对象有一个内部结构,其中每一部分都有属于自己的属性,如一个audio unit对象都有一个input scope, output scope, global scope. 每个scope由一个或多个elements(类似于音频总线)组成.

1.5 回调函数

Core Audio中常用回调函数以实现音频数据通信,回调函数常有一下功能

  • 提供给应用程序音频数据(如:用麦克风进行录制,将麦克风采集的数据通过回调函数传给使用者)

  • 从应用程序中请求音频数据(如:播放回调)

  • 监听某个对象状态的变化

为了去使用回调函数,我们需要做以下两件事情

  • 注册回调函数(如实现录制,播放回调,需要我们在初始化时提供一个函数)

  • 实现回调函数的功能.(实现初始化时提供的函数)

Note: 在OC中,回调函数是一个C语言形式的函数,我们回调OC本类对象作为对象传入其中, 所以回调函数中不能直接引用self.xxx,需要借助传入的OC对象去实现本类的功能.

1.6 音频数据格式

Core Audio封装了音频数据格式,我们只需要对给定结构体赋正确的参数即可。

struct AudioStreamBasicDescription {
    Float64 mSampleRate;
    UInt32  mFormatID;
    UInt32  mFormatFlags;
    UInt32  mBytesPerPacket;
    UInt32  mFramesPerPacket;
    UInt32  mBytesPerFrame;
    UInt32  mChannelsPerFrame;
    UInt32  mBitsPerChannel;
    UInt32  mReserved;
};
typedef struct AudioStreamBasicDescription  AudioStreamBasicDescription;
​
struct  AudioStreamPacketDescription {
    SInt64  mStartOffset;
    UInt32  mVariableFramesInPacket;
    UInt32  mDataByteSize;
};
typedef struct AudioStreamPacketDescription AudioStreamPacketDescription;

注意,上面结构体中mReserved是Apple的保留参数,必须为0. 其他一些参数在特定情况下也需为0,如:压缩音频格式每个sample使用不同数量的bits。对于这些格式,mBitsPerChannel成员的值为0。

  • 为AudioStreamBasicDescription赋值

你可以手动为ASBD的成员赋值,如果有些值是你不知道的,可以赋0,Core Audio将自动选择适当的值。

  • 标准的音频数据格式

iOS: 线性PCM 16bit integer, Noninterleaved linear PCM 8.24bit 定点samples

struct AudioStreamBasicDescription {
    mSampleRate       = 44100.0;
    mFormatID         = kAudioFormatLinearPCM;
    mFormatFlags      = kAudioFormatFlagsAudioUnitCanonical;
    mBitsPerChannel   = 8 * sizeof (AudioUnitSampleType);                    // 32 bits
    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
嗨!对于 Windows 平台上的音频播放,可以使用 Core Audio API。以下是一个简单的示例代码,展示如何使用 Core Audio API 播放音频: ```c++ #include <Windows.h> #include <Mmdeviceapi.h> #include <Audioclient.h> #include <iostream> int main() { HRESULT hr; // 初始化 COM 组件 hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); if (FAILED(hr)) { std::cout << "COM 初始化失败" << std::endl; return 1; } // 创建设备枚举器 IMMDeviceEnumerator* pEnumerator = NULL; hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&pEnumerator); if (FAILED(hr)) { std::cout << "设备枚举器创建失败" << std::endl; CoUninitialize(); return 1; } // 获取默认音频渲染设备 IMMDevice* pDevice = NULL; hr = pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pDevice); if (FAILED(hr)) { std::cout << "获取默认音频设备失败" << std::endl; pEnumerator->Release(); CoUninitialize(); return 1; } // 激活设备接口 IAudioClient* pAudioClient = NULL; hr = pDevice->Activate(__uuidof(IAudioClient), CLSCTX_ALL, NULL, (void**)&pAudioClient); if (FAILED(hr)) { std::cout << "音频客户端激活失败" << std::endl; pDevice->Release(); pEnumerator->Release(); CoUninitialize(); return 1; } // 设置音频格式 WAVEFORMATEX* pWaveFormat; hr = pAudioClient->GetMixFormat(&pWaveFormat); if (FAILED(hr)) { std::cout << "获取音频格式失败" << std::endl; pAudioClient->Release(); pDevice->Release(); pEnumerator->Release(); CoUninitialize(); return 1; } // 初始化音频流 hr = pAudioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, 0, 10000000, 0, pWaveFormat, NULL); if (FAILED(hr)) { std::cout << "音频流初始化失败" << std::endl; CoTaskMemFree(pWaveFormat); pAudioClient->Release(); pDevice->Release(); pEnumerator->Release(); CoUninitialize(); return 1; } // 获取音频缓冲区 IAudioRenderClient* pRenderClient = NULL; hr = pAudioClient->GetService(__uuidof(IAudioRenderClient), (void**)&pRenderClient); if (FAILED(hr)) { std::cout << "获取音频渲染客户端失败" << std::endl; CoTaskMemFree(pWaveFormat); pAudioClient->Release(); pDevice->Release(); pEnumerator->Release(); CoUninitialize(); return 1; } // 启动音频流 hr = pAudioClient->Start(); if (FAILED(hr)) { std::cout << "音频流启动失败" << std::endl; CoTaskMemFree(pWaveFormat); pRenderClient->Release(); pAudioClient->Release(); pDevice->Release(); pEnumerator->Release(); CoUninitialize(); return 1; } // 从音频缓冲区写入数据 UINT32 bufferSize = 0; BYTE* pData; hr = pRenderClient->GetBuffer(bufferSize, &pData); if (FAILED(hr)) { std::cout << "获取音频缓冲区失败" << std::endl; CoTaskMemFree(pWaveFormat); pRenderClient->Release(); pAudioClient->Release(); pDevice->Release(); pEnumerator->Release(); CoUninitialize(); return 1; } // 在这里填充音频数据到 pData 缓冲区 // 释放音频缓冲区 hr = pRenderClient->ReleaseBuffer(bufferSize, 0); if (FAILED(hr)) { std::cout << "释放音频缓冲区失败" << std::endl; } // 停止音频流 hr = pAudioClient->Stop(); if (FAILED(hr)) { std::cout << "停止音频流失败" << std::endl; } // 清理资源 CoTaskMemFree(pWaveFormat); pRenderClient->Release(); pAudioClient->Release(); pDevice->Release(); pEnumerator->Release(); CoUninitialize(); return 0; } ``` 这是一个基本示例,你可以根据自己的需求进行修改和扩展。记得在使用完毕后,释放所有的资源以避免内存泄漏。希望对你有帮助!如果你还有其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值