OpenHarmony 音频管理
前言
音频可以通过超级终端在其他外部设备上播放本地的音频流
例如使用 Openharmony 或者 HarmonyOS 设备与一台华为sound使用超级终端连接并播放一首歌曲
下面是音频管理的介绍和运行实例的代码片段
官方代码仓库 multimedia_audio_framework: Audio management implementation | 音频管理功能实现
介绍
音频组件用于实现音频相关功能,包括播放、音量管理、设备管理等
架构如下图
 
应用接入
音频播放
使用AudioRenderer实现音频播放
    1.使用Create接口和所需要流的类型来获取AudioRenderer实例
| 1 | AudioStreamType streamType = STREAM_MUSIC; // 流类型 | 
 2.[选]静态接口
GetSupportedFormats(),GetSupportedChannels(),GetSupportedEncodingTypes(),GetSupportedSamplingRates() 来获取参数
    3.调用实例的SetParams
| 1 | AudioRendererParams rendererParams; | 
    4.[选]使用audioRenderer->GetParams(rendererParams)验证SetParams
    5.AudioRenderer实例调用audioRenderer->Start() 函数启动播放Task
    6.使用GetBufferSize接口获取需写入缓冲区长度
| 1 | audioRenderer->GetBufferSize(bufferLen); | 
 7.读取源需播放的音频数据并传输到流中,重复调用Write函数写入渲染数据
| 1 | bytesToWrite = fread(buffer, 1, bufferLen, wavFile); | 
    8.调用audioRenderer->Drain()清空播放流
    9.调用audioRenderer->Stop()停止输出流
    10.在播放任务完成后,调用AudioRenderer实例的audioRenderer->Release()释放资源
    11.使用audioRenderer->SetVolume(float)和audioRenderer->GetVolume()设置和获取当前流音量,可选范围为[0.0,1.0]
音频录制
使用仓库内提供的接口让应用程序完成使用输入设备进行声音录制,将语音转换为音频数据,并管理录制的任务
下面的步骤将描述如何使用AudioCapturer开发音频录制功能
- 使用 - Create接口和所需流类型来获取- AudioCapturer实例- 1 
 2- AudioStreamType streamType = STREAM_MUSIC; 
 std::unique_ptr<AudioCapturer> audioCapturer = AudioCapturer::Create(streamType);
- [选]静态接口 - GetSupportedFormats(),- GetSupportedChannels(),- GetSupportedEncodingTypes(),- GetSupportedSamplingRates()可用于获取支持的参数
- 准备设备,调用实例的 - SetParams- 1 
 2
 3
 4
 5
 6
 7- AudioCapturerParams capturerParams; 
 capturerParams.sampleFormat = SAMPLE_S16LE;
 capturerParams.sampleRate = SAMPLE_RATE_44100;
 capturerParams.channelCount = STEREO;
 capturerParams.encodingType = ENCODING_PCM;
 audioCapturer->SetParams(capturerParams);
- [选]使用 - audioCapturer->GetParams(capturerParams)验证- SetParams()
- AudioCapturer实例调用- AudioCapturer->Start()启动录音任务
- 使用 - GetBufferSize接口获取写入的缓冲区长度- 1 - audioCapturer->GetBufferSize(bufferLen); 
- 读取录制的音频数据并将其转换为字节流,重复调用read函数读取数据直到主动停止 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11- // set isBlocking = true/false for blocking/non-blocking read 
 bytesRead = audioCapturer->Read(*buffer, bufferLen, isBlocking);
 while (numBuffersToCapture) {
 bytesRead = audioCapturer->Read(*buffer, bufferLen, isBlockingRead);
 if (bytesRead < 0) {
 break;
 } else if (bytesRead > 0) {
 fwrite(buffer, size, bytesRead, recFile); // example shows writes the recorded data into a file
 numBuffersToCapture--;
 }
 }
- audioCapturer->Flush()清空录音流缓冲区
- AudioCapturer实例调用- audioCapturer->Stop()停止录音
- 在录音任务完成后,调用 - AudioCapturer实例的- audioCapturer->Release()释放资源
音频管理
可以使用audio_system_manager.h的接口来控制音量和设备
- 使用 - GetInstance接口获取- AudioSystemManager实例- 1 - AudioSystemManager *audioSystemMgr = AudioSystemManager::GetInstance(); - 音量控制
- 使用 - GetMaxVolume和- GetMinVolume接口去查询音频流支持的最大和最小音量等级,在此范围内设置音量- 1 
 2
 3- AudioVolumeType streamType = AudioVolumeType::STREAM_MUSIC; 
 int32_t maxVol = audioSystemMgr->GetMaxVolume(streamType);
 int32_t minVol = audioSystemMgr->GetMinVolume(streamType);
- 使用 - SetVolume和- GetVolume接口来设置和获取指定音频流的音量等级- 1 
 2- int32_t result = audioSystemMgr->SetVolume(streamType, 10); 
 int32_t vol = audioSystemMgr->GetVolume(streamType);
- 使用 - SetMute和- IsStreamMute接口来设置和获取指定音频流的静音状态- 1 
 2- int32_t result = audioSystemMgr->SetMute(streamType, true); 
 bool isMute = audioSystemMgr->IsStreamMute(streamType);
- 使用 - SetRingerMode和- GetRingerMode接口来设置和获取铃声模式,参考在audio_info.h定义的- AudioRingerMode枚举来获取支持的铃声模式- 1 
 2- int32_t result = audioSystemMgr->SetRingerMode(RINGER_MODE_SILENT); 
 AudioRingerMode ringMode = audioSystemMgr->GetRingerMode();
- 使用 - SetMicrophoneMute和- IsMicrophoneMute接口来设置和获取麦克风的静音状态- 1 
 2- int32_t result = audioSystemMgr->SetMicrophoneMute(true); 
 bool isMicMute = audioSystemMgr->IsMicrophoneMute();- 设备控制
- 使用 - GetDevices,- deviceType和- deviceRole接口来获取音频输入输出设备信息,参考audio_info.h内定义的- DeviceFlag,- DeviceType和- DeviceRole枚举- 1 
 2
 3
 4
 5
 6- DeviceFlag deviceFlag = OUTPUT_DEVICES_FLAG; 
 vector<sptr<AudioDeviceDescriptor>> audioDeviceDescriptors
 = audioSystemMgr->GetDevices(deviceFlag);
 sptr<AudioDeviceDescriptor> audioDeviceDescriptor = audioDeviceDescriptors[0];
 cout << audioDeviceDescriptor->deviceType_;
 cout << audioDeviceDescriptor->deviceRole_;
- 使用 - SetDeviceActive和- IsDeviceActive接口去激活/去激活音频设备和获取音频设备激活状态- 1 
 2
 3- ActiveDeviceType deviceType = SPEAKER; 
 int32_t result = audioSystemMgr->SetDeviceActive(deviceType, true);
 bool isDevActive = audioSystemMgr->IsDeviceActive(deviceType);
- 提供其他用途的接口如 - IsStreamActive,- SetAudioParameter和- GetAudioParameter,详细请参考 audio_system_manager.h
- 应用程序可以使用 - AudioManagerNapi::On注册系统音量的更改,在此,如果应用程序监听到系统音量更改的事件,就会用以下参数通知应用程序- volumeType: 更改的系统音量的类型- volume: 当前的音量等级- updateUi: 是否需要显示变化详细信息(如果音量被增大/减小,将- updateUi标志设置为true,在其他情况下,- updateUi设置为false)- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11- const audioManager = audio.getAudioManager(); 
 export default {
 onCreate() {
 audioManager.on('volumeChange', (volumeChange) ==> {
 console.info('volumeType = '+volumeChange.volumeType);
 console.info('volume = '+volumeChange.volume);
 console.info('updateUi = '+volumeChange.updateUi);
 }
 }
 }
音频场景
- 使用 - SetAudioscene和- getAudioScene接口去更改和检查音频策略- 1 
 2- int32_t result = audioSystemMgr->SetAudioScene(AUDIO_SCENE_PHONE_CALL); 
 AudioScene audioScene = audioSystemMgr->GetAudioScene();- 有关支持的音频场景,请参阅 - AudioScene中的枚举audio_info.h- 音频流管理- 可以使用audio_stream_manager.h提供的接口用于流管理功能 
- 使用 - GetInstance接口获得- AudioSystemManager实例- 1 - AudioStreamManager *audioStreamMgr = AudioStreamManager::GetInstance(); 
- 使用 - RegisterAudioRendererEventListener为渲染器状态更改注册侦听器.渲染器状态更改回调,该回调将在渲染器流状态更改时调用,通过重写- AudioRendererStateChangeCallback类中的函数- OnRendererStateChange- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16- const int32_t clientUID; 
 class RendererStateChangeCallback : public AudioRendererStateChangeCallback {
 public:
 RendererStateChangeCallback = default;
 ~RendererStateChangeCallback = default;
 void OnRendererStateChange(
 const std::vector<std::unique_ptr<AudioRendererChangeInfo>> &audioRendererChangeInfos) override
 {
 cout<<"OnRendererStateChange entered"<<endl;
 }
 };
 std::shared_ptr<AudioRendererStateChangeCallback> callback = std::make_shared<RendererStateChangeCallback>();
 int32_t state = audioStreamMgr->RegisterAudioRendererEventListener(clientUID, callback);
 int32_t result = audioStreamMgr->UnregisterAudioRendererEventListener(clientUID);
- 使用 - RegisterAudioCapturerEventListener为捕获器状态更改注册侦听器,捕获器状态更改回调,该回调将在捕获器流状态更改时调用,通过重写- AudioCapturerStateChangeCallback类中的函数- OnCapturerStateChange- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16- const int32_t clientUID; 
 class CapturerStateChangeCallback : public AudioCapturerStateChangeCallback {
 public:
 CapturerStateChangeCallback = default;
 ~CapturerStateChangeCallback = default;
 void OnCapturerStateChange(
 const std::vector<std::unique_ptr<AudioCapturerChangeInfo>> &audioCapturerChangeInfos) override
 {
 cout<<"OnCapturerStateChange entered"<<endl;
 }
 };
 std::shared_ptr<AudioCapturerStateChangeCallback> callback = std::make_shared<CapturerStateChangeCallback>();
 int32_t state = audioStreamMgr->RegisterAudioCapturerEventListener(clientUID, callback);
 int32_t result = audioStreamMgr->UnregisterAudioCapturerEventListener(clientUID);
- 使用 - GetCurrentRendererChangeInfos获取所有当前正在运行的流渲染器信息包括- clientuid、- sessionid、- renderinfo、- renderstate和输出设备详细信息- 1 
 2- std::vector<std::unique_ptr<AudioRendererChangeInfo>> audioRendererChangeInfos; 
 int32_t currentRendererChangeInfo = audioStreamMgr->GetCurrentRendererChangeInfos(audioRendererChangeInfos);
- 使用 - GetCurrentCapturerChangeInfos获取所有当前正在运行的流捕获器信息,包括- clientuid、- sessionid、- capturerInfo、- capturerState和输入设备详细信息- 1 
 2- std::vector<std::unique_ptr<AudioCapturerChangeInfo>> audioCapturerChangeInfos; 
 int32_t currentCapturerChangeInfo = audioStreamMgr->GetCurrentCapturerChangeInfos(audioCapturerChangeInfos);- 有关结构,请参阅audio_info.h - audioRendererChangeInfos和- audioCapturerChangeInfos
- 使用 - IsAudioRendererLowLatencySupported检查低延迟功能是否支持- 1 
 2- const AudioStreamInfo &audioStreamInfo; 
 bool isLatencySupport = audioStreamMgr->IsAudioRendererLowLatencySupported(audioStreamInfo);- JavaScript用法- JavaScript应用可以使用系统提供的音频管理接口,来控制音量和设备 
请参考js-apis-audio.md来获取音量和设备管理相关JavaScript接口的用法
铃声管理
可以使用提供的接口iringtone_sound_manager.h和iringtone_player.h实现铃声播放功能
- 使用 - CreateRingtoneManager接口创建- IRingtoneSoundManager实例- 1 - std::shared_ptr<IRingtoneSoundManager> ringtoneManagerClient = RingtoneFactory::CreateRingtoneManager(); 
- 使用 - SetSystemRingtoneUri接口设置系统铃声Uri- 1 
 2
 3- std::string uri = "/data/media/test.wav"; 
 RingtoneType ringtoneType = RINGTONE_TYPE_DEFAULT;
 ringtoneManagerClient->SetSystemRingtoneUri(context, uri, ringtoneType);
- 使用 - GetRingtonePlayer接口获取- IRingtonePlayer实例- 1 - std::unique_ptr<IRingtonePlayer> ringtonePlayer = ringtoneManagerClient->GetRingtonePlayer(context, ringtoneType); 
- 使用 - Configure接口配置铃声播放器- 1 
 2
 3- float volume = 1; 
 bool loop = true;
 ringtonePlayer.Configure(volume, loop);
- 使用 - Start,- Stop和- Release接口在铃声播放器实例上控制播放状态- 1 
 2
 3- ringtonePlayer.Start(); 
 ringtonePlayer.Stop();
 ringtonePlayer.Release();
- 使用 - GetTitle接口获取当前系统铃声的标题
- 使用 - GetRingtoneState接口获取铃声播放状态- RingtoneState
- 使用 - GetAudioRendererInfo获取- AudioRendererInfo检查内容类型和流使用情况- 蓝牙SCO呼叫- 可以使用提供的接口audio_bluetooth_manager.h实现同步连接导向链路(SCO)的蓝牙呼叫 
- 为监听SCO状态更改,您可以使用 - OnScoStateChanged- 1 
 2
 3- const BluetoothRemoteDevice &device; 
 int state;
 void OnScoStateChanged(const BluetoothRemoteDevice &device, int state);
- [选]静态接口 - RegisterBluetoothScoAgListener(),- UnregisterBluetoothScoAgListener(),可用于注册蓝牙SCO的侦听器