1/* 2 * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import audio from '@ohos.multimedia.audio'; 17import Logger from '../utils/Logger'; 18 19const TAG = 'mAudioCapturer'; 20 21// 与使用AudioCapturer开发音频录制功能过程相似,关键区别在于audioCapturerInfo参数和音频数据流向 22export default class AudioCapturerHelper { 23 private audioCapturer: audio.AudioCapturer | null = null; 24 25 private audioStreamInfo: audio.AudioStreamInfo = { 26 samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_16000, // 采样率 27 channels: audio.AudioChannel.CHANNEL_2, // 通道数 28 sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE, // 采样格式 29 encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW // 编码格式 30 }; 31 private audioCapturerInfo: audio.AudioCapturerInfo = { 32 // 需使用通话场景相应的参数 33 source: audio.SourceType.SOURCE_TYPE_VOICE_COMMUNICATION, // 音源类型:语音通话 34 capturerFlags: 0 // 音频采集器标志:默认为0即可 35 }; 36 private audioCapturerOptions: audio.AudioCapturerOptions = { 37 streamInfo: this.audioStreamInfo, 38 capturerInfo: this.audioCapturerInfo 39 }; 40 41 // 初始化,创建实例 42 async init(): Promise<void> { 43 try { 44 this.audioCapturer = await audio.createAudioCapturer(this.audioCapturerOptions); 45 Logger.info(TAG,`create AudioCapturer success`); 46 } catch (err) { 47 Logger.error(TAG,`Invoke createAudioCapturer failed ${JSON.stringify(err)}`); 48 } 49 50 } 51 52 // 开始一次音频采集 53 async start(callback: (buffer: ArrayBuffer, size: number) => void): Promise<void> { 54 if (!this.audioCapturer) { 55 Logger.info(TAG,`start failed AudioCapturer is null`); 56 return; 57 } 58 59 let stateGroup = [audio.AudioState.STATE_PREPARED, audio.AudioState.STATE_PAUSED, audio.AudioState.STATE_STOPPED]; 60 if (stateGroup.indexOf(this.audioCapturer.state) === -1) { // 当且仅当状态为prepared、paused和stopped之一时才能启动采集 61 Logger.info(TAG,`start failed`); 62 return; 63 } 64 65 try { 66 await this.audioCapturer.start(); // 启动采集 67 Logger.info(TAG,`start AudioCapturer success`); 68 let bufferSize: number = await this.audioCapturer.getBufferSize(); // rk打印出来2972? 先不用 69 Logger.info(TAG,`read bufferSize ${bufferSize}`); 70 while (true) { 71 72 let buffer: ArrayBuffer = await this.audioCapturer.read(bufferSize, true); 73 if (buffer === undefined) { 74 Logger.error(TAG,`read buffer failed`); 75 } else { 76 if (callback) { 77 callback(buffer, bufferSize); 78 } 79 } 80 } 81 } catch (err) { 82 Logger.error(TAG,`start Capturer failed ${JSON.stringify(err)}`); 83 } 84 } 85 86 // 停止采集 87 async stop(): Promise<void> { 88 Logger.info(TAG,`Capturer stop`); 89 try { 90 // 只有采集器状态为STATE_RUNNING或STATE_PAUSED的时候才可以停止 91 if (this.audioCapturer.state !== audio.AudioState.STATE_RUNNING && this.audioCapturer.state !== audio.AudioState.STATE_PAUSED) { 92 Logger.info(TAG,`Capturer is not running or paused`); 93 return; 94 } 95 await this.audioCapturer.stop(); // 停止采集 96 } catch (err) { 97 Logger.error(TAG,`stop Capturer failed ${JSON.stringify(err)}`); 98 } 99 100 } 101 102 // 销毁实例,释放资源 103 async release(): Promise<void> { 104 Logger.info(TAG,`Capturer release`); 105 try { 106 // 采集器状态不是STATE_RELEASED或STATE_NEW状态,才能release 107 if (this.audioCapturer.state === audio.AudioState.STATE_RELEASED || this.audioCapturer.state === audio.AudioState.STATE_NEW) { 108 Logger.info(TAG,`Capturer already released`); 109 return; 110 } 111 await this.audioCapturer.release(); // 释放资源 112 } catch (err) { 113 Logger.error(TAG,`release Capturer failed ${JSON.stringify(err)}`); 114 } 115 } 116} 117