鸿蒙实战多媒体运用:【音频组件】

音频组件用于实现音频相关的功能,包括音频播放,录制,音量管理和设备管理。

图 1 音频组件架构图

基本概念

  • 采样

采样是指将连续时域上的模拟信号按照一定的时间间隔采样,获取到离散时域上离散信号的过程。

  • 采样率

采样率为每秒从连续信号中提取并组成离散信号的采样次数,单位用赫兹(Hz)来表示。通常人耳能听到频率范围大约在20Hz~20kHz之间的声音。常用的音频采样频率有:8kHz、11.025kHz、22.05kHz、16kHz、37.8kHz、44.1kHz、48kHz、96kHz、192kHz等。

  • 声道

声道是指声音在录制或播放时在不同空间位置采集或回放的相互独立的音频信号,所以声道数也就是声音录制时的音源数量或回放时相应的扬声器数量。

  • 音频帧

音频数据是流式的,本身没有明确的一帧帧的概念,在实际的应用中,为了音频算法处理/传输的方便,一般约定俗成取2.5ms~60ms为单位的数据量为一帧音频。这个时间被称之为“采样时间”,其长度没有特别的标准,它是根据编解码器和具体应用的需求来决定的。

  • PCM

PCM(Pulse Code Modulation),即脉冲编码调制,是一种将模拟信号数字化的方法,是将时间连续、取值连续的模拟信号转换成时间离散、抽样值离散的数字信号的过程。

目录

仓目录结构如下:

/foundation/multimedia/audio_standard  # 音频组件业务代码
├── frameworks                         # 框架代码
│   ├── native                         # 内部接口实现
│   └── js                             # 外部接口实现
│       └── napi                       # napi 外部接口实现
├── interfaces                         # 接口代码
│   ├── inner_api                      # 内部接口
│   └── kits                           # 外部接口
├── sa_profile                         # 服务配置文件
├── services                           # 服务代码
├── LICENSE                            # 证书文件
└── bundle.json                        # 编译文件

使用说明

音频播放

可以使用此仓库内提供的接口将音频数据转换为音频模拟信号,使用输出设备播放音频信号,以及管理音频播放任务。以下步骤描述了如何使用 AudioRenderer 开发音频播放功能:

  1. 使用 Create 接口和所需流类型来获取 AudioRenderer 实例。

    AudioStreamType streamType = STREAM_MUSIC; // 流类型示例
    std::unique_ptr<AudioRenderer> audioRenderer = AudioRenderer::Create(streamType);
    
  2. (可选)静态接口 GetSupportedFormats(), GetSupportedChannels(), GetSupportedEncodingTypes(), GetSupportedSamplingRates() 可用于获取支持的参数。

  3. 准备设备,调用实例的 SetParams 。

    AudioRendererParams rendererParams;
    rendererParams.sampleFormat = SAMPLE_S16LE;
    rendererParams.sampleRate = SAMPLE_RATE_44100;
    rendererParams.channelCount = STEREO;
    rendererParams.encodingType = ENCODING_PCM;
    
    audioRenderer->SetParams(rendererParams);
    
  4. (可选)使用 audioRenderer->GetParams(rendererParams) 来验证 SetParams。

  5. (可选)使用 SetAudioEffectMode 和 GetAudioEffectMode 接口来设置和获取当前音频流的音效模式。

    AudioEffectMode effectMode = EFFECT_DEFAULT;
    int32_t result = audioRenderer->SetAudioEffectMode(effectMode);
    AudioEffectMode mode = audioRenderer->GetAudioEffectMode();
    
  6. AudioRenderer 实例调用 audioRenderer->Start() 函数来启动播放任务。

  7. 使用 GetBufferSize 接口获取要写入的缓冲区长度。

    audioRenderer->GetBufferSize(bufferLen);
    
  8. 从源(例如音频文件)读取要播放的音频数据并将其传输到字节流中。重复调用Write函数写入渲染数据。

    bytesToWrite = fread(buffer, 1, bufferLen, wavFile);
    while ((bytesWritten < bytesToWrite) && ((bytesToWrite - bytesWritten) > minBytes)) {
        bytesWritten += audioRenderer->Write(buffer + bytesWritten, bytesToWrite - bytesWritten);
        if (bytesWritten < 0)
            break;
    }
    
  9. 调用audioRenderer->Drain()来清空播放流。

  10. 调用audioRenderer->Stop()来停止输出。

  11. 播放任务完成后,调用AudioRenderer实例的audioRenderer->Release()函数来释放资源。

以上提供了基本音频播放使用场景。

  1. 使用 audioRenderer->SetVolume(float)  和 audioRenderer->GetVolume()  来设置和获取当前音频流音量, 可选范围为 0.0 到 1.0。

提供上述基本音频播放使用范例。

音频录制

可以使用此仓库内提供的接口,让应用程序可以完成使用输入设备进行声音录制,将语音转换为音频数据,并管理录制的任务。以下步骤描述了如何使用 AudioCapturer 开发音频录制功能:

  1. 使用Create接口和所需流类型来获取 AudioCapturer 实例。

    AudioStreamType streamType = STREAM_MUSIC;
    std::unique_ptr<AudioCapturer> audioCapturer = AudioCapturer::Create(streamType);
    
  2. (可选)静态接口 GetSupportedFormats(), GetSupportedChannels(), GetSupportedEncodingTypes(), GetSupportedSamplingRates() 可用于获取支持的参数。

  3. 准备设备,调用实例的 SetParams 。

    AudioCapturerParams capturerParams;
    capturerParams.sampleFormat = SAMPLE_S16LE;
    capturerParams.sampleRate = SAMPLE_RATE_44100;
    capturerParams.channelCount = STEREO;
    capturerParams.encodingType = ENCODING_PCM;
    
    audioCapturer->SetParams(capturerParams);
    
  4. (可选)使用 audioCapturer->GetParams(capturerParams) 来验证 SetParams()。

  5. AudioCapturer 实例调用 AudioCapturer->Start() 函数来启动录音任务。

  6. 使用 GetBufferSize 接口获取要写入的缓冲区长度。

    audioCapturer->GetBufferSize(bufferLen);
    
  7. 读取录制的音频数据并将其转换为字节流。重复调用read函数读取数据直到主动停止。

    // 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--;
        }
    }
    
  8. (可选)audioCapturer->Flush() 来清空录音流缓冲区。

  9. AudioCapturer 实例调用 audioCapturer->Stop() 函数停止录音。

  10. 录音任务完成后,调用 AudioCapturer 实例的 audioCapturer->Release() 函数释放资源。

音频管理

可以使用 [audio_system_manager.h]内的接口来控制音量和设备。

  1. 使用 GetInstance 接口获取 AudioSystemManager 实例.

    AudioSystemManager *audioSystemMgr = AudioSystemManager::GetInstance();
    
音量控制
  1. 使用 GetMaxVolume 和 GetMinVolume 接口去查询音频流支持的最大和最小音量等级,在此范围内设置音量。

    AudioVolumeType streamType = AudioVolumeType::STREAM_MUSIC;
    int32_t maxVol = audioSystemMgr->GetMaxVolume(streamType);
    int32_t minVol = audioSystemMgr->GetMinVolume(streamType);
    
  2. 使用 SetVolume 和 GetVolume 接口来设置和获取指定音频流的音量等级。

    int32_t result = audioSystemMgr->SetVolume(streamType, 10);
    int32_t vol = audioSystemMgr->GetVolume(streamType);
    
  3. 使用 SetMute 和 IsStreamMute 接口来设置和获取指定音频流的静音状态。

    int32_t result = audioSystemMgr->SetMute(streamType, true);
    bool isMute = audioSystemMgr->IsStreamMute(streamType);
    
  4. 使用 SetRingerMode 和 GetRingerMode 接口来设置和获取铃声模式。参考在 [audio_info.h] 定义的 AudioRingerMode 枚举来获取支持的铃声模式。

    int32_t result = audioSystemMgr->SetRingerMode(RINGER_MODE_SILENT);
    AudioRingerMode ringMode = audioSystemMgr->GetRingerMode();
    
  5. 使用 SetMicrophoneMute 和 IsMicrophoneMute 接口来设置和获取麦克风的静音状态。

    int32_t result = audioSystemMgr->SetMicrophoneMute(true);
    bool isMicMute = audioSystemMgr->IsMicrophoneMute();
    
设备控制
  1. 使用 GetDevicesdeviceType_  和 deviceRole_  接口来获取音频输入输出设备信息。内定义的DeviceFlag, DeviceType 和 DeviceRole 枚举。

    DeviceFlag deviceFlag = OUTPUT_DEVICES_FLAG;
    vector<sptr<AudioDeviceDescriptor>> audioDeviceDescriptors
        = audioSystemMgr->GetDevices(deviceFlag);
    sptr<AudioDeviceDescriptor> audioDeviceDescriptor = audioDeviceDescriptors[0];
    cout << audioDeviceDescriptor->deviceType_;
    cout << audioDeviceDescriptor->deviceRole_;
    
  2. 使用 SetDeviceActive 和 IsDeviceActive 接口去激活/去激活音频设备和获取音频设备激活状态。

    ActiveDeviceType deviceType = SPEAKER;
    int32_t result = audioSystemMgr->SetDeviceActive(deviceType, true);
    bool isDevActive = audioSystemMgr->IsDeviceActive(deviceType);
    
  3. 提供其他用途的接口如 IsStreamActiveSetAudioParameter and GetAudioParameter,

  4. 应用程序可以使用 AudioManagerNapi::On注册系统音量的更改。 在此,如果应用程序监听到系统音量更改的事件,就会用以下参数通知应用程序: volumeType : 更改的系统音量的类型 volume : 当前的音量等级 updateUi : 是否需要显示变化详细信息。(如果音量被增大/减小,将updateUi标志设置为true,在其他情况下,updateUi设置为false)。

    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);
        }
      }
    }
    
音频场景
  1. 使用 SetAudioScene 和 getAudioScene 接口去更改和检查音频策略。

    int32_t result = audioSystemMgr->SetAudioScene(AUDIO_SCENE_PHONE_CALL);
    AudioScene audioScene = audioSystemMgr->GetAudioScene();
    

有关支持的音频场景,请参阅 AudioScene 中的枚举[audio_info.h]。

音频流管理

可以使用[audio_stream_manager.h]提供的接口用于流管理功能。

  1. 使用 GetInstance 接口获得 AudioSystemManager 实例。

    AudioStreamManager *audioStreamMgr = AudioStreamManager::GetInstance();
    
  2. 使用 RegisterAudioRendererEventListener 为渲染器状态更改注册侦听器。渲染器状态更改回调,该回调将在渲染器流状态更改时调用, 通过重写 AudioRendererStateChangeCallback 类中的函数 OnRendererStateChange 。

    const int32_t clientPid;
    
    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(clientPid, callback);
    int32_t result = audioStreamMgr->UnregisterAudioRendererEventListener(clientPid);
    
  3. 使用 RegisterAudioCapturerEventListener 为捕获器状态更改注册侦听器。 捕获器状态更改回调,该回调将在捕获器流状态更改时调用, 通过重写 AudioCapturerStateChangeCallback 类中的函数 OnCapturerStateChange 。

    const int32_t clientPid;
    
    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(clientPid, callback);
    int32_t result = audioStreamMgr->UnregisterAudioCapturerEventListener(clientPid);
    
  4. 使用 GetCurrentRendererChangeInfos 获取所有当前正在运行的流渲染器信息,包括clientuid、sessionid、renderinfo、renderstate和输出设备详细信息。

    std::vector<std::unique_ptr<AudioRendererChangeInfo>> audioRendererChangeInfos;
    int32_t currentRendererChangeInfo = audioStreamMgr->GetCurrentRendererChangeInfos(audioRendererChangeInfos);
    
  5. 使用 GetCurrentCapturerChangeInfos 获取所有当前正在运行的流捕获器信息,包括clientuid、sessionid、capturerInfo、capturerState和输入设备详细信息。

    std::vector<std::unique_ptr<AudioCapturerChangeInfo>> audioCapturerChangeInfos;
    int32_t currentCapturerChangeInfo = audioStreamMgr->GetCurrentCapturerChangeInfos(audioCapturerChangeInfos);
    

    有关结构, audioRendererChangeInfos 和 audioCapturerChangeInfos.

  6. 使用 IsAudioRendererLowLatencySupported 检查低延迟功能是否支持。

    const AudioStreamInfo &audioStreamInfo;
    bool isLatencySupport = audioStreamMgr->IsAudioRendererLowLatencySupported(audioStreamInfo);
    
  7. 使用 GetEffectInfoArray 接口查询指定[StreamUsage]下可以支持的音效模式。

    AudioSceneEffectInfo audioSceneEffectInfo;
    int32_t status = audioStreamMgr->GetEffectInfoArray(audioSceneEffectInfo,streamUsage);
    

    有关支持的音效模式,请参阅[audio_effect.h]中的枚举AudioEffectMode

JavaScript 用法:

JavaScript应用可以使用系统提供的音频管理接口,来控制音量和设备。
请参考 [js-apis-audio.md]来获取音量和设备管理相关JavaScript接口的用法。

蓝牙SCO呼叫

可以使用提供的接口 [audio_bluetooth_manager.h]实现同步连接导向链路(SCO)的蓝牙呼叫。

  1. 为监听SCO状态更改,您可以使用 OnScoStateChanged.
const BluetoothRemoteDevice &device;
int state;
void OnScoStateChanged(const BluetoothRemoteDevice &device, int state);
  1. (可选) 静态接口 RegisterBluetoothScoAgListener(), UnregisterBluetoothScoAgListener(), 可用于注册蓝牙SCO的侦听器。

鸿蒙OpenHarmony知识已更新←前往

HarmonyOS与OpenHarmony技术路线曲线图2.png

支持设备

以下是音频子系统支持的设备类型列表。

  1. USB Type-C Headset
    数字耳机,包括自己的DAC(数模转换器)和作为耳机一部分的放大器。
  2. WIRED Headset
    模拟耳机内部不包含任何DAC。它可以有3.5mm插孔或不带DAC的C型插孔。
  3. Bluetooth Headset
    蓝牙A2DP(高级音频分配模式)耳机,用于无线传输音频。
  4. Internal Speaker and MIC
    支持内置扬声器和麦克风,并将分别用作播放和录制的默认设备。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/441563.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

macos m1 arm芯片 使用jpype报错 FileNotFoundError: [Errno 2] JVM DLL not found

startJVM(jpype.getDefaultJVMPath()) 报错 Traceback (most recent call last):File "/Users/thomas990p/PycharmProjects/tuya/volcano-biz-scripts/WenKongFa/FinalCode/java2python/CallJavaAPI.py", line 12, in <module>startJVM(jpype.getDefaultJVMPa…

寻找两个正序数组的中位数[困难]

优质博文IT-BLOG-CN 一、题目 给定两个大小分别为m和n的正序&#xff08;从小到大&#xff09;数组nums1和nums2。请你找出并返回这两个正序数组的 中位数 。 算法的时间复杂度应该为O(log (mn)) 。 示例 1&#xff1a; 输入&#xff1a;nums1 [1,3], nums2 [2] 输出&…

【漏洞复现】帮管客 CRM jiliyu SQL注入漏洞

免责声明&#xff1a;文章来源互联网收集整理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该…

用 Axios 提升前端异步请求的效率

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

代码随想录 -- 栈和队列

文章目录 栈实现队列描述题解 用队列实现栈描述题解 有效的括号描述题解 删除字符串中的所有相邻重复项描述题解 逆波兰表达式求值描述题解 滑动窗口最大值描述题解&#xff1a;暴力题解&#xff1a;单调队列 前 K 个高频元素描述题解 栈实现队列 题目链接 描述 使用两个栈实…

WPF开源的一款免费、开箱即用的翻译、OCR工具

前言 今天大姚给大家分享一款由WPF开源的、免费的&#xff08;MIT License&#xff09;、即开即用、即用即走的翻译、OCR工具&#xff1a;STranslate。 WPF介绍 WPF 是一个强大的桌面应用程序框架&#xff0c;用于构建具有丰富用户界面的 Windows 应用。它提供了灵活的布局、…

TCP包头、TCP为什么安全可靠、UDP和TCP的区别、http协议

我要成为嵌入式高手之3月8日Linux高编第十八天&#xff01;&#xff01; __________________________________________________ 学习笔记 TPC包头 1、序号 发送端发送数据包的编号 2、确认号 已经确认接收到的数据的编号&#xff0c;只有当ACK为1时&#xff0c;该位才有用 …

sentinel prometheus指标收集及资源规则正则表达式实现

sentinel 支持 prometheus 收集指标 实现原理 在 sentinel-extension 模块下&#xff0c;新增 sentinel-prometheus-metric-exporter 模块。依赖Prometheus 提供的 simpleclient 和 simpleclient_httpserver 来实现 exporter。 依赖 simpleclient 主要是为了实现自定义Collect…

关于手机是否支持h264的问题的解决方案

目录 现象 原理 修改内容 现象 开始以为是手机不支持h264的编码 。机器人chatgpt一通乱扯。 后来检查了下手机&#xff0c;明显是有h264嘛。 终于搞定&#xff0c;不枉凌晨三点起来思考 原理 WebRTC 默认使用的视频编码器是VP8和VP9&#xff0c;WebRTC内置了这两种编码器…

flink重温笔记(十二): flink 高级特性和新特性(1)——End-to-End Exactly-Once(端到端精确一致性语义)

Flink学习笔记 前言&#xff1a;今天是学习 flink 的第 12 天啦&#xff01;学习了 flink 高级特性和新特性之 End-to-End Exactly-Once&#xff08;端到端精确一致性语义&#xff09;&#xff0c;主要是解决大数据领域数据从数据源到数据落点的一致性&#xff0c;不会容易造成…

计算机组成原理之机器:存储器之辅助存储器

计算机组成原理之机器&#xff1a;存储器之辅助存储器 笔记来源&#xff1a;哈尔滨工业大学计算机组成原理&#xff08;哈工大刘宏伟&#xff09; Chapter3&#xff1a;存储器之辅助存储器 3.1 概述 3.2 磁记录原理 通不同方向电流时磁化方向不同&#xff0c;由此区分写入…

逆向分析 FSViewer 并写出注册机

逆向分析 FSViewer 并写出注册机 FSViewer是一款老牌的图片管理查看编辑软件, 个人使用免费, 商用收费 本文将逆向分析FSViewer 7.5版本的注册算法并编写注册机 0. 前言 最近在整理之前的资料, 发现了一篇几年前刚学逆向那会儿写的文章, 是跟着看雪一位大牛的文章做的, 但逆向…

基于yolov5的番茄检测系统,可进行图像目标检测,也可进行视屏和摄像检测(pytorch框架)【python源码+UI界面+功能源码详解】

功能演示&#xff1a; 基于yolov5的小番茄检测系统&#xff0c;系统既能够实现图像检测&#xff0c;也可以进行视屏和摄像实时检测_哔哩哔哩_bilibili &#xff08;一&#xff09;简介 基于yolov5的番茄检测系统是在pytorch框架下实现的&#xff0c;这是一个完整的项目&…

Vue 项目性能优化指南:提升应用速度与效率

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

【前端】-初始前端以及html的学习

&#x1f496;作者&#xff1a;小树苗渴望变成参天大树&#x1f388; &#x1f389;作者宣言&#xff1a;认真写好每一篇博客&#x1f4a4; &#x1f38a;作者gitee:gitee✨ &#x1f49e;作者专栏&#xff1a;C语言,数据结构初阶,Linux,C 动态规划算法&#x1f384; 如 果 你 …

(未解决)macOS matplotlib 中文是方框

reference&#xff1a; Mac OS系统下实现python matplotlib包绘图显示中文(亲测有效)_mac plt 中文值-CSDN博客 module ‘matplotlib.font_manager‘ has no attribute ‘_rebuild‘解决方法_font_manager未解析-CSDN博客 # 问题描述&#xff08;笑死 显而易见 # solve 找到…

CleanMyMac X4.15.0专为macOS设计的清理和优化工具

CleanMyMac X 是一款专为 macOS 设计的清理和优化工具。其基本功能和特点主要包括&#xff1a; 系统清理&#xff1a;CleanMyMac X 可以扫描并清除 macOS 系统中的垃圾文件&#xff0c;如缓存、日志、无用的语言文件等&#xff0c;从而释放硬盘空间并提高系统性能。应用程序管…

贪心算法(greedy algorithm,又称贪婪算法)详解(附例题)

目录 基本思想一&#xff09;概念二&#xff09;找出全局最优解的要求三&#xff09;求解时应考虑的问题四&#xff09;基本步骤五&#xff09;贪心策略选择六&#xff09;实际应用 1.零钱找回问题2.背包问题3.哈夫曼编码4.单源路径中的Djikstra算法5.最小生成树Prim算法 基本…

备考银行科技岗刷题笔记(持续更新版)

银行考试计算机部分复习 IEEE 802.11的帧格式 1.1 IEEE 802.11是什么&#xff1f; 802.11是国际电工电子工程学会&#xff08;IEEE&#xff09;为无线局域网络制定的标准。目前在802.11的基础上开发出了802.11a、802.11b、802.11g、802.11n、802.11ac。并且为了保证802.11更…

【电工学笔记】上册第一、二章

电工学 上次考试败在了单位&#xff0c;这次单位 一定要记熟。 第一章 电源或信号源的电压或电流称为激励,它推动电路工作; 由激励所产生的电压和电流称为响应。 复杂电路中,一般无法事先判断某个支路电流的 实际方向或者某个电路元件电压的实际方向 140V/4算不出总电阻的 …