当前位置:   article > 正文

OpenHarmony音频采集开发_openharmony 读取wav音频文件

openharmony 读取wav音频文件

1、OpenHarmony音频采集开发简介

        AudioCapturer提供了用于获取原始音频文件的方法。开发者可以通过本博文了解应用如何通过AudioCapturer接口的调用实现音频数据的采集。

        状态检查:在进行应用开发的过程中,建议开发者通过on('stateChange')方法订阅AudioCapturer的状态变更。因为针对AudioCapturer的某些操作,仅在音频采集器在固定状态时才能执行。如果应用在音频采集器处于错误状态时执行操作,系统可能会抛出异常或生成其他未定义的行为。

 2、OpenHarmony音频采集运行机制

        该模块提供了音频采集模块的状态变化示意图。

                图1 音频采集状态变化示意图

PREPARED状态: 通过调用create()方法进入到该状态。

RUNNING状态: 正在进行音频数据播放,可以在prepared状态通过调用start()方法进入此状态,也可以在stopped状态通过调用start()方法进入此状态。

STOPPED状态: 在running状态可以通过stop()方法停止音频数据的播放。

RELEASED状态: 在prepared和stop状态,用户均可通过release()方法释放掉所有占用的硬件和软件资源,并且不会再进入到其他的任何一种状态了。

 3、OpenHarmony音频采集的约束与限制

开发者在进行音频数据采集功能开发前,需要先对所开发的应用配置麦克风权限(ohos.permission.MICROPHONE),配置方式请参见访问控制授权申请

4、OpenHarmony音频采集开发指导

 详细API含义可参考:音频管理API文档AudioCapturer

(1).使用createAudioCapturer()创建一个AudioCapturer实例。

        在audioCapturerOptions中设置音频采集器的相关参数。该实例可用于音频采集、控制和获取采集状态,以及注册通知回调。

  1. import audio from '@ohos.multimedia.audio';
  2. let audioStreamInfo = {
  3. samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_44100,
  4. channels: audio.AudioChannel.CHANNEL_1,
  5. sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE,
  6. encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW
  7. }
  8. let audioCapturerInfo = {
  9. source: audio.SourceType.SOURCE_TYPE_MIC,
  10. capturerFlags: 0 // 0是音频采集器的扩展标志位,默认为0
  11. }
  12. let audioCapturerOptions = {
  13. streamInfo: audioStreamInfo,
  14. capturerInfo: audioCapturerInfo
  15. }
  16. let audioCapturer = await audio.createAudioCapturer(audioCapturerOptions);
  17. console.log('AudioRecLog: Create audio capturer success.');

(2).调用start()方法来启动/恢复采集任务。

         启动完成后,采集器状态将变更为STATE_RUNNING,然后应用可以开始读取缓冲区。

  1. import audio from '@ohos.multimedia.audio';
  2. async function startCapturer() {
  3. let state = audioCapturer.state;
  4. // Capturer start时的状态应该是STATE_PREPARED、STATE_PAUSED和STATE_STOPPED之一.
  5. if (state != audio.AudioState.STATE_PREPARED || state != audio.AudioState.STATE_PAUSED ||
  6. state != audio.AudioState.STATE_STOPPED) {
  7. console.info('Capturer is not in a correct state to start');
  8. return;
  9. }
  10. await audioCapturer.start();
  11. state = audioCapturer.state;
  12. if (state == audio.AudioState.STATE_RUNNING) {
  13. console.info('AudioRecLog: Capturer started');
  14. } else {
  15. console.error('AudioRecLog: Capturer start failed');
  16. }
  17. }

(3).读取采集器的音频数据并将其转换为字节流。重复调用read()方法读取数据,直到应用准备停止采集。

        参考以下示例,将采集到的数据写入文件。

  1. import fs from '@ohos.file.fs';
  2. let state = audioCapturer.state;
  3. // 只有状态为STATE_RUNNING的时候才可以read.
  4. if (state != audio.AudioState.STATE_RUNNING) {
  5. console.info('Capturer is not in a correct state to read');
  6. return;
  7. }
  8. const path = '/data/data/.pulse_dir/capture_js.wav'; // 采集到的音频文件存储路径
  9. let file = fs.openSync(filePath, 0o2);
  10. let fd = file.fd;
  11. if (file !== null) {
  12. console.info('AudioRecLog: file created');
  13. } else {
  14. console.info('AudioRecLog: file create : FAILED');
  15. return;
  16. }
  17. if (fd !== null) {
  18. console.info('AudioRecLog: file fd opened in append mode');
  19. }
  20. let numBuffersToCapture = 150; // 循环写入150次
  21. let count = 0;
  22. while (numBuffersToCapture) {
  23. let bufferSize = await audioCapturer.getBufferSize();
  24. let buffer = await audioCapturer.read(bufferSize, true);
  25. let options = {
  26. offset: count * this.bufferSize,
  27. length: this.bufferSize
  28. }
  29. if (typeof(buffer) == undefined) {
  30. console.info('AudioRecLog: read buffer failed');
  31. } else {
  32. let number = fs.writeSync(fd, buffer, options);
  33. console.info(`AudioRecLog: data written: ${number}`);
  34. }
  35. numBuffersToCapture--;
  36. count++;
  37. }

(4).采集完成后,调用stop方法,停止录制。

  1. async function StopCapturer() {
  2. let state = audioCapturer.state;
  3. // 只有采集器状态为STATE_RUNNING或STATE_PAUSED的时候才可以停止
  4. if (state != audio.AudioState.STATE_RUNNING && state != audio.AudioState.STATE_PAUSED) {
  5. console.info('AudioRecLog: Capturer is not running or paused');
  6. return;
  7. }
  8. await audioCapturer.stop();
  9. state = audioCapturer.state;
  10. if (state == audio.AudioState.STATE_STOPPED) {
  11. console.info('AudioRecLog: Capturer stopped');
  12. } else {
  13. console.error('AudioRecLog: Capturer stop failed');
  14. }
  15. }

(5).任务结束,调用release()方法释放相关资源。

  1. async function releaseCapturer() {
  2. let state = audioCapturer.state;
  3. // 采集器状态不是STATE_RELEASED或STATE_NEW状态,才能release
  4. if (state == audio.AudioState.STATE_RELEASED || state == audio.AudioState.STATE_NEW) {
  5. console.info('AudioRecLog: Capturer already released');
  6. return;
  7. }
  8. await audioCapturer.release();
  9. state = audioCapturer.state;
  10. if (state == audio.AudioState.STATE_RELEASED) {
  11. console.info('AudioRecLog: Capturer released');
  12. } else {
  13. console.info('AudioRecLog: Capturer release failed');
  14. }
  15. }

(6).获取采集器相关信息

        通过以下代码,可以获取采集器的相关信息。

  1. // 获取当前采集器状态
  2. let state = audioCapturer.state;
  3. // 获取采集器信息
  4. let audioCapturerInfo : audio.AuduioCapturerInfo = await audioCapturer.getCapturerInfo();
  5. // 获取音频流信息
  6. let audioStreamInfo : audio.AudioStreamInfo = await audioCapturer.getStreamInfo();
  7. // 获取音频流ID
  8. let audioStreamId : number = await audioCapturer.getAudioStreamId();
  9. // 获取纳秒形式的Unix时间戳
  10. let audioTime : number = await audioCapturer.getAudioTime();
  11. // 获取合理的最小缓冲区大小
  12. let bufferSize : number = await audioCapturer.getBufferSize();

(7).使用on('markReach')方法订阅采集器标记到达事件,使用off('markReach')取消订阅事件。

        注册markReach监听后,当采集器采集的帧数到达设定值时,会触发回调并返回设定的值。

  1. audioCapturer.on('markReach', (reachNumber) => {
  2. console.info('Mark reach event Received');
  3. console.info(`The Capturer reached frame: ${reachNumber}`);
  4. });
  5. audioCapturer.off('markReach'); // 取消markReach事件的订阅,后续将无法监听到“标记到达”事件

(8).使用on('periodReach')方法订阅采集器区间标记到达事件,使用off('periodReach')取消订阅事件。

        注册periodReach监听后,每当采集器采集的帧数到达设定值时,会触发回调并返回设定的值。

  1. audioCapturer.on('periodReach', (reachNumber) => {
  2. console.info('Period reach event Received');
  3. console.info(`In this period, the Capturer reached frame: ${reachNumber}`);
  4. });
  5. audioCapturer.off('periodReach'); // 取消periodReach事件的订阅,后续将无法监听到“区间标记到达”事件

(9).如果应用需要在采集器状态更新时进行一些操作,可以订阅该事件,当采集器状态更新时,会受到一个包含有事件类型的回调。

  1. audioCapturer.on('stateChange', (state) => {
  2. console.info(`AudioCapturerLog: Changed State to : ${state}`)
  3. switch (state) {
  4. case audio.AudioState.STATE_PREPARED:
  5. console.info('--------CHANGE IN AUDIO STATE----------PREPARED--------------');
  6. console.info('Audio State is : Prepared');
  7. break;
  8. case audio.AudioState.STATE_RUNNING:
  9. console.info('--------CHANGE IN AUDIO STATE----------RUNNING--------------');
  10. console.info('Audio State is : Running');
  11. break;
  12. case audio.AudioState.STATE_STOPPED:
  13. console.info('--------CHANGE IN AUDIO STATE----------STOPPED--------------');
  14. console.info('Audio State is : stopped');
  15. break;
  16. case audio.AudioState.STATE_RELEASED:
  17. console.info('--------CHANGE IN AUDIO STATE----------RELEASED--------------');
  18. console.info('Audio State is : released');
  19. break;
  20. default:
  21. console.info('--------CHANGE IN AUDIO STATE----------INVALID--------------');
  22. console.info('Audio State is : invalid');
  23. break;
  24. }
  25. });

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/329277?site
推荐阅读
相关标签
  

闽ICP备14008679号