提交 1b39b9a7 编写于 作者: Z zengyawen

update docs

Signed-off-by: Nzengyawen <zengyawen1@huawei.com>
上级 50c06452
# 音频采集开发指导
## 场景介绍
## 简介
AudioCapturer提供了用于获取原始音频文件的方法。开发者可以通过本指导了解应用如何通过AudioCapturer采集音频
AudioCapturer提供了用于获取原始音频文件的方法。开发者可以通过本指导了解应用如何通过AudioCapturer接口的调用实现音频数据的采集
### 状态检查
- **状态检查**:在进行应用开发的过程中,建议开发者通过on('stateChange')方法订阅AudioCapturer的状态变更。因为针对AudioCapturer的某些操作,仅在音频采集器在固定状态时才能执行。如果应用在音频采集器处于错误状态时执行操作,系统可能会抛出异常或生成其他未定义的行为。
在进行应用开发的过程中,建议开发者通过on('stateChange')方法订阅AudioCapturer的状态变更。因为针对AudioCapturer的某些操作,仅在音频采集器在固定状态时才能执行。如果应用在音频采集器处于错误状态时执行操作,系统可能会抛出异常或生成其他未定义的行为。
## 运作机制
详细API含义可参考:[音频管理API文档AudioCapturer](../reference/apis/js-apis-audio.md#audiocapturer8)
该模块提供了音频采集模块的状态变化示意图
**图1** 音频采集状态变化示意图
![audio-capturer-state](figures/audio-capturer-state.png)
**PREPARED状态:** 通过调用create()方法进入到该状态。<br>
**RUNNING状态:** 正在进行音频数据播放,可以在prepared状态通过调用start()方法进入此状态,也可以在stopped状态通过调用start()方法进入此状态。<br>
**STOPPED状态:** 在running状态可以通过stop()方法停止音频数据的播放。<br>
**RELEASED状态:** 在prepared和stop状态,用户均可通过release()方法释放掉所有占用的硬件和软件资源,并且不会再进入到其他的任何一种状态了。<br>
## 约束与限制
**图1** 音频采集状态机
开发者在进行音频数据采集功能开发前,需要先对所开发的应用配置麦克风权限(ohos.permission.MICROPHONE),权限配置相关内容可参考:[访问控制授权申请指导](../security/accesstoken-guidelines.md)
![](figures/audio-capturer-state.png)
## 开发指导
## 开发步骤
详细API含义可参考:[音频管理API文档AudioCapturer](../reference/apis/js-apis-audio.md#audiocapturer8)
1. 使用createAudioCapturer()创建一个AudioCapturer实例。
在audioCapturerOptions中设置音频采集器的相关参数。该实例可用于音频采集、控制和获取采集状态,以及注册通知回调。
```js
var audioStreamInfo = {
samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_44100,
channels: audio.AudioChannel.CHANNEL_1,
sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE,
encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW
}
var audioCapturerInfo = {
source: audio.SourceType.SOURCE_TYPE_MIC,
capturerFlags: 1
}
var audioCapturerOptions = {
streamInfo: audioStreamInfo,
capturerInfo: audioCapturerInfo
}
let audioCapturer = await audio.createAudioCapturer(audioCapturerOptions);
var state = audioRenderer.state;
var audioStreamInfo = {
samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_44100,
channels: audio.AudioChannel.CHANNEL_1,
sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE,
encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW
}
var audioCapturerInfo = {
source: audio.SourceType.SOURCE_TYPE_MIC,
capturerFlags: 1
}
var audioCapturerOptions = {
streamInfo: audioStreamInfo,
capturerInfo: audioCapturerInfo
}
let audioCapturer = await audio.createAudioCapturer(audioCapturerOptions);
var state = audioRenderer.state;
```
2. (可选)使用on('stateChange')订阅音频采集器状态更改。
如果应用需要在采集器状态更新时进行一些操作,可以订阅该事件。更多事件请参考[API参考文档](../reference/apis/js-apis-audio.md)
```js
audioCapturer.on('stateChange',(state) => {
console.info('AudioCapturerLog: Changed State to : ' + state)
switch (state) {
case audio.AudioState.STATE_PREPARED:
console.info('--------CHANGE IN AUDIO STATE----------PREPARED--------------');
console.info('Audio State is : Prepared');
break;
case audio.AudioState.STATE_RUNNING:
console.info('--------CHANGE IN AUDIO STATE----------RUNNING--------------');
console.info('Audio State is : Running');
break;
case audio.AudioState.STATE_STOPPED:
console.info('--------CHANGE IN AUDIO STATE----------STOPPED--------------');
console.info('Audio State is : stopped');
break;
case audio.AudioState.STATE_RELEASED:
console.info('--------CHANGE IN AUDIO STATE----------RELEASED--------------');
console.info('Audio State is : released');
break;
default:
console.info('--------CHANGE IN AUDIO STATE----------INVALID--------------');
console.info('Audio State is : invalid');
break;
}
});
```
如果应用需要在采集器状态更新时进行一些操作,可以订阅该事件。更多事件请参考[API参考文档](../reference/apis/js-apis-audio.md)
```js
audioCapturer.on('stateChange',(state) => {
console.info('AudioCapturerLog: Changed State to : ' + state)
switch (state) {
case audio.AudioState.STATE_PREPARED:
console.info('--------CHANGE IN AUDIO STATE----------PREPARED--------------');
console.info('Audio State is : Prepared');
break;
case audio.AudioState.STATE_RUNNING:
console.info('--------CHANGE IN AUDIO STATE----------RUNNING--------------');
console.info('Audio State is : Running');
break;
case audio.AudioState.STATE_STOPPED:
console.info('--------CHANGE IN AUDIO STATE----------STOPPED--------------');
console.info('Audio State is : stopped');
break;
case audio.AudioState.STATE_RELEASED:
console.info('--------CHANGE IN AUDIO STATE----------RELEASED--------------');
console.info('Audio State is : released');
break;
default:
console.info('--------CHANGE IN AUDIO STATE----------INVALID--------------');
console.info('Audio State is : invalid');
break;
}
});
```
3. 调用start()方法来启动/恢复采集任务。
......@@ -131,7 +142,7 @@ AudioCapturer提供了用于获取原始音频文件的方法。开发者可以
6. 采集完成后,调用stop方法,停止录制。
```
```js
await audioCapturer.stop();
if (audioCapturer.state == audio.AudioState.STATE_STOPPED) {
console.info('AudioRecLog: Capturer stopped');
......
# 音频焦点模式开发指导
## 场景介绍
## 简介
音频焦点模式指的是应用内,允许对多个声音的播放进行控制。<br>
音频应用可以在AudioRenderer下设置独立焦点模式、共享焦点模式。<br>
当设置在共享的模式下,多个音频共用一个会话ID;独立焦点模式下,每一个音频拥有单独会话ID。
### 异步操作
- **异步操作**:为保证UI线程不被阻塞,大部分AudioRenderer调用都是异步的。对于每个API均提供了callback函数和Promise函数,以下示例均采用Promise函数。
为保证UI线程不被阻塞,大部分AudioRenderer调用都是异步的。对于每个API均提供了callback函数和Promise函数,以下示例均采用Promise函数。
## 开发步骤
## 开发指导
详细API含义可参考:[音频管理API文档AudioRenderer](../reference/apis/js-apis-audio.md#audiorenderer8)
1. 使用createAudioRenderer()创建一个AudioRenderer实例。<br>
在audioRendererOptions中设置相关参数。<br>
该实例可用于音频渲染、控制和获取采集状态,以及注册通知回调。<br>
......@@ -21,25 +18,25 @@
```js
import audio from '@ohos.multimedia.audio';
var audioStreamInfo = {
samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_44100,
channels: audio.AudioChannel.CHANNEL_1,
sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE,
encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW
}
var audioRendererInfo = {
content: audio.ContentType.CONTENT_TYPE_SPEECH,
usage: audio.StreamUsage.STREAM_USAGE_VOICE_COMMUNICATION,
rendererFlags: 1
}
var audioRendererOptions = {
streamInfo: audioStreamInfo,
rendererInfo: audioRendererInfo
}
let audioRenderer = await audio.createAudioRenderer(audioRendererOptions);
var audioStreamInfo = {
samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_44100,
channels: audio.AudioChannel.CHANNEL_1,
sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE,
encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW
}
var audioRendererInfo = {
content: audio.ContentType.CONTENT_TYPE_SPEECH,
usage: audio.StreamUsage.STREAM_USAGE_VOICE_COMMUNICATION,
rendererFlags: 1
}
var audioRendererOptions = {
streamInfo: audioStreamInfo,
rendererInfo: audioRendererInfo
}
let audioRenderer = await audio.createAudioRenderer(audioRendererOptions);
```
2. 设置焦点模式。
......
# 音频渲染开发指导
## 场景介绍
## 简介
AudioRenderer提供了渲染音频文件和控制播放的接口,开发者可以通过本指导,了解如何在输出设备中播放音频文件并管理播放任务。
AudioRenderer提供了渲染音频文件和控制播放的接口,开发者可以通过本指导,了解如何在输出设备中播放音频文件并管理播放任务。同时,AudioRenderer支持音频中断的功能。
开发者在调用AudioRenderer提供的各个接口时,需要理解以下名词:
同时,AudioRenderer支持音频中断的功能。
- **音频中断**:当优先级较高的音频流需要播放时,AudioRenderer会中断优先级较低的流。例如,当用户在收听音乐时有来电,则优先级较低音乐播放将被暂停。
- **状态检查**:在进行应用开发的过程中,建议开发者通过on('stateChange')方法订阅AudioRenderer的状态变更。因为针对AudioRenderer的某些操作,仅在音频播放器在固定状态时才能执行。如果应用在音频播放器处于错误状态时执行操作,系统可能会抛出异常或生成其他未定义的行为。
- **异步操作**:为保证UI线程不被阻塞,大部分AudioRenderer调用都是异步的。对于每个API均提供了callback函数和Promise函数,以下示例均采用Promise函数,更多方式可参考[音频管理API文档AudioRenderer](../reference/apis/js-apis-audio.md#audiorenderer8)
### 音频中断
## 运作机制
当优先级较高的音频流需要播放时,AudioRenderer会中断优先级较低的流。例如,当用户在收听音乐时有来电,则优先级较低音乐播放将被暂停,具体可参考[开发步骤](#开发步骤)
该模块提供了音频渲染模块的状态变化示意
### 状态检查
**图1** 音频渲染状态示意图
在进行应用开发的过程中,建议开发者通过on('stateChange')方法订阅AudioRenderer的状态变更。因为针对AudioRenderer的某些操作,仅在音频播放器在固定状态时才能执行。如果应用在音频播放器处于错误状态时执行操作,系统可能会抛出异常或生成其他未定义的行为。
![audio-renderer-state](figures/audio-renderer-state.png)
**图1** 音频渲染状态机
**PREPARED状态:** 通过调用create()方法进入到该状态。<br>
**RUNNING状态:** 正在进行音频数据播放,可以在prepared状态通过调用start()方法进入此状态,也可以在pause状态和stopped状态通过调用start()方法进入此状态。<br>
**PAUSED状态:** 在running状态可以通过pause()方法暂停音频数据的播放,暂停播放之后可以通过调用start()方法继续音频数据播放。<br>
**STOPPED状态:** 在paused状态可以通过调用stop()方法停止音频数据的播放,在running状态可以通过stop()方法停止音频数据的播放。<br>
**RELEASED状态:** 在prepared、paused、stop等状态,用户均可通过release()方法释放掉所有占用的硬件和软件资源,并且不会再进入到其他的任何一种状态了。<br>
![](figures/audio-renderer-state.png)
### 异步操作
为保证UI线程不被阻塞,大部分AudioRenderer调用都是异步的。对于每个API均提供了callback函数和Promise函数,以下示例均采用Promise函数,更多方式可参考[音频管理API文档AudioRenderer](../reference/apis/js-apis-audio.md#audiorenderer8)
## 开发步骤
## 开发指导
1. 使用createAudioRenderer()创建一个AudioRenderer实例。
在audioCapturerOptions中设置相关参数。该实例可用于音频渲染、控制和获取采集状态,以及注册通知回调。
```js
var audioStreamInfo = {
samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_44100,
channels: audio.AudioChannel.CHANNEL_1,
sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE,
encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW
}
var audioRendererInfo = {
content: audio.ContentType.CONTENT_TYPE_SPEECH,
usage: audio.StreamUsage.STREAM_USAGE_VOICE_COMMUNICATION,
rendererFlags: 1
}
var audioRendererOptions = {
streamInfo: audioStreamInfo,
rendererInfo: audioRendererInfo
}
let audioRenderer = await audio.createAudioRenderer(audioRendererOptions);
var audioStreamInfo = {
samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_44100,
channels: audio.AudioChannel.CHANNEL_1,
sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE,
encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW
}
var audioRendererInfo = {
content: audio.ContentType.CONTENT_TYPE_SPEECH,
usage: audio.StreamUsage.STREAM_USAGE_VOICE_COMMUNICATION,
rendererFlags: 1
}
var audioRendererOptions = {
streamInfo: audioStreamInfo,
rendererInfo: audioRendererInfo
}
let audioRenderer = await audio.createAudioRenderer(audioRendererOptions);
```
2. 使用on('interrupt')方法订阅音频中断事件。
......@@ -58,49 +59,49 @@ AudioRenderer提供了渲染音频文件和控制播放的接口,开发者可
在音频中断的情况下,应用可能会碰到音频数据写入失败的问题。所以建议不感知、不处理中断的应用在写入音频数据前,使用audioRenderer.state检查播放器状态。而订阅音频中断事件,可以获取到更多详细信息,具体可参考[InterruptEvent](../reference/apis/js-apis-audio.md#interruptevent9)
```js
audioRenderer.on('interrupt', (interruptEvent) => {
console.info('InterruptEvent Received');
console.info('InterruptType: ' + interruptEvent.eventType);
console.info('InterruptForceType: ' + interruptEvent.forceType);
console.info('AInterruptHint: ' + interruptEvent.hintType);
if (interruptEvent.forceType == audio.InterruptForceType.INTERRUPT_FORCE) {
switch (interruptEvent.hintType) {
// Force Pause: Action was taken by framework.
// Halt the write calls to avoid data loss.
case audio.InterruptHint.INTERRUPT_HINT_PAUSE:
isPlay = false;
break;
// Force Stop: Action was taken by framework.
// Halt the write calls to avoid data loss.
case audio.InterruptHint.INTERRUPT_HINT_STOP:
isPlay = false;
break;
// Force Duck: Action was taken by framework,
// just notifying the app that volume has been reduced.
case audio.InterruptHint.INTERRUPT_HINT_DUCK:
break;
// Force Unduck: Action was taken by framework,
// just notifying the app that volume has been restored.
case audio.InterruptHint.INTERRUPT_HINT_UNDUCK:
break;
}
} else if (interruptEvent.forceType == audio.InterruptForceType.INTERRUPT_SHARE) {
switch (interruptEvent.hintType) {
// Share Resume: Action is to be taken by App.
// Resume the force paused stream if required.
case audio.InterruptHint.INTERRUPT_HINT_RESUME:
startRenderer();
break;
// Share Pause: Stream has been interrupted,
// It can choose to pause or play concurrently.
case audio.InterruptHint.INTERRUPT_HINT_PAUSE:
isPlay = false;
pauseRenderer();
break;
}
}
});
audioRenderer.on('interrupt', (interruptEvent) => {
console.info('InterruptEvent Received');
console.info('InterruptType: ' + interruptEvent.eventType);
console.info('InterruptForceType: ' + interruptEvent.forceType);
console.info('AInterruptHint: ' + interruptEvent.hintType);
if (interruptEvent.forceType == audio.InterruptForceType.INTERRUPT_FORCE) {
switch (interruptEvent.hintType) {
// Force Pause: Action was taken by framework.
// Halt the write calls to avoid data loss.
case audio.InterruptHint.INTERRUPT_HINT_PAUSE:
isPlay = false;
break;
// Force Stop: Action was taken by framework.
// Halt the write calls to avoid data loss.
case audio.InterruptHint.INTERRUPT_HINT_STOP:
isPlay = false;
break;
// Force Duck: Action was taken by framework,
// just notifying the app that volume has been reduced.
case audio.InterruptHint.INTERRUPT_HINT_DUCK:
break;
// Force Unduck: Action was taken by framework,
// just notifying the app that volume has been restored.
case audio.InterruptHint.INTERRUPT_HINT_UNDUCK:
break;
}
} else if (interruptEvent.forceType == audio.InterruptForceType.INTERRUPT_SHARE) {
switch (interruptEvent.hintType) {
// Share Resume: Action is to be taken by App.
// Resume the force paused stream if required.
case audio.InterruptHint.INTERRUPT_HINT_RESUME:
startRenderer();
break;
// Share Pause: Stream has been interrupted,
// It can choose to pause or play concurrently.
case audio.InterruptHint.INTERRUPT_HINT_PAUSE:
isPlay = false;
pauseRenderer();
break;
}
}
});
```
3. 调用start()方法来启动/恢复播放任务。
......@@ -108,24 +109,24 @@ AudioRenderer提供了渲染音频文件和控制播放的接口,开发者可
启动完成后,渲染器状态将变更为STATE_RUNNING,然后应用可以开始读取缓冲区。
```js
async function startRenderer() {
var state = audioRenderer.state;
// state should be prepared, paused or stopped.
if (state != audio.AudioState.STATE_PREPARED || state != audio.AudioState.STATE_PAUSED ||
state != audio.AudioState.STATE_STOPPED) {
console.info('Renderer is not in a correct state to start');
return;
}
await audioRenderer.start();
state = audioRenderer.state;
if (state == audio.AudioState.STATE_RUNNING) {
console.info('Renderer started');
} else {
console.error('Renderer start failed');
}
}
async function startRenderer() {
var state = audioRenderer.state;
// state should be prepared, paused or stopped.
if (state != audio.AudioState.STATE_PREPARED || state != audio.AudioState.STATE_PAUSED ||
state != audio.AudioState.STATE_STOPPED) {
console.info('Renderer is not in a correct state to start');
return;
}
await audioRenderer.start();
state = audioRenderer.state;
if (state == audio.AudioState.STATE_RUNNING) {
console.info('Renderer started');
} else {
console.error('Renderer start failed');
}
}
```
4. 调用write()方法向缓冲区写入数据。
......@@ -133,83 +134,83 @@ AudioRenderer提供了渲染音频文件和控制播放的接口,开发者可
将需要播放的音频数据读入缓冲区,重复调用write()方法写入。
```js
async function writeBuffer(buf) {
var state = audioRenderer.state;
if (state != audio.AudioState.STATE_RUNNING) {
console.error('Renderer is not running, do not write');
isPlay = false;
return;
}
let writtenbytes = await audioRenderer.write(buf);
console.info('Actual written bytes: ' + writtenbytes);
if (writtenbytes < 0) {
console.error('Write buffer failed. check the state of renderer');
}
}
// Reasonable minimum buffer size for renderer. However, the renderer can accept other read sizes as well.
const bufferSize = await audioRenderer.getBufferSize();
const path = '/data/file_example_WAV_2MG.wav';
let ss = fileio.createStreamSync(path, 'r');
const totalSize = 2146166; // file_example_WAV_2MG.wav
let rlen = 0;
let discardHeader = new ArrayBuffer(44);
ss.readSync(discardHeader);
rlen += 44;
async function writeBuffer(buf) {
var state = audioRenderer.state;
if (state != audio.AudioState.STATE_RUNNING) {
console.error('Renderer is not running, do not write');
isPlay = false;
return;
}
let writtenbytes = await audioRenderer.write(buf);
console.info('Actual written bytes: ' + writtenbytes);
if (writtenbytes < 0) {
console.error('Write buffer failed. check the state of renderer');
}
}
var id = setInterval(() => {
if (isPlay || isRelease) {
if (rlen >= totalSize || isRelease) {
ss.closeSync();
stopRenderer();
clearInterval(id);
}
let buf = new ArrayBuffer(bufferSize);
rlen += ss.readSync(buf);
console.info('Total bytes read from file: ' + rlen);
writeBuffer(buf);
} else {
console.info('check after next interval');
}
} , 30); // interval to be set based on audio file format
// Reasonable minimum buffer size for renderer. However, the renderer can accept other read sizes as well.
const bufferSize = await audioRenderer.getBufferSize();
const path = '/data/file_example_WAV_2MG.wav';
let ss = fileio.createStreamSync(path, 'r');
const totalSize = 2146166; // file_example_WAV_2MG.wav
let rlen = 0;
let discardHeader = new ArrayBuffer(44);
ss.readSync(discardHeader);
rlen += 44;
var id = setInterval(() => {
if (isPlay || isRelease) {
if (rlen >= totalSize || isRelease) {
ss.closeSync();
stopRenderer();
clearInterval(id);
}
let buf = new ArrayBuffer(bufferSize);
rlen += ss.readSync(buf);
console.info('Total bytes read from file: ' + rlen);
writeBuffer(buf);
} else {
console.info('check after next interval');
}
} , 30); // interval to be set based on audio file format
```
5. (可选)调用pause()方法或stop()方法暂停/停止渲染音频数据。
```js
async function pauseRenderer() {
var state = audioRenderer.state;
if (state != audio.AudioState.STATE_RUNNING) {
console.info('Renderer is not running');
return;
}
await audioRenderer.pause();
state = audioRenderer.state;
if (state == audio.AudioState.STATE_PAUSED) {
console.info('Renderer paused');
} else {
console.error('Renderer pause failed');
}
}
async function stopRenderer() {
var state = audioRenderer.state;
if (state != audio.AudioState.STATE_RUNNING || state != audio.AudioState.STATE_PAUSED) {
console.info('Renderer is not running or paused');
return;
}
await audioRenderer.stop();
state = audioRenderer.state;
if (state == audio.AudioState.STATE_STOPPED) {
console.info('Renderer stopped');
} else {
console.error('Renderer stop failed');
}
async function pauseRenderer() {
var state = audioRenderer.state;
if (state != audio.AudioState.STATE_RUNNING) {
console.info('Renderer is not running');
return;
}
await audioRenderer.pause();
state = audioRenderer.state;
if (state == audio.AudioState.STATE_PAUSED) {
console.info('Renderer paused');
} else {
console.error('Renderer pause failed');
}
}
async function stopRenderer() {
var state = audioRenderer.state;
if (state != audio.AudioState.STATE_RUNNING || state != audio.AudioState.STATE_PAUSED) {
console.info('Renderer is not running or paused');
return;
}
await audioRenderer.stop();
state = audioRenderer.state;
if (state == audio.AudioState.STATE_STOPPED) {
console.info('Renderer stopped');
} else {
console.error('Renderer stop failed');
}
}
```
......@@ -218,20 +219,20 @@ AudioRenderer提供了渲染音频文件和控制播放的接口,开发者可
AudioRenderer会使用大量的系统资源,所以请确保完成相关任务后,进行资源释放。
```js
async function releaseRenderer() {
if (state_ == RELEASED || state_ == NEW) {
console.info('Resourced already released');
return;
}
await audioRenderer.release();
state = audioRenderer.state;
if (state == STATE_RELEASED) {
console.info('Renderer released');
} else {
console.info('Renderer release failed');
}
}
async function releaseRenderer() {
if (state_ == RELEASED || state_ == NEW) {
console.info('Resourced already released');
return;
}
await audioRenderer.release();
state = audioRenderer.state;
if (state == STATE_RELEASED) {
console.info('Renderer released');
} else {
console.info('Renderer release failed');
}
}
```
\ No newline at end of file
# 音频流管理开发指导
## 场景介绍
## 简介
AudioStreamManager提供了音频流管理的方法。开发者可以通过本指导了解应用如何通过AudioStreamManager管理音频流。
### 工作流程
## 运作机制
在进行应用开发的过程中,开发者需要使用getStreamManager()创建一个AudioStreamManager实例,进而通过该实例管理音频流。开发者可通过调用on('audioRendererChange')、on('audioCapturerChange')监听音频播放应用和音频录制应用,在应用状态变化、设备变化、音频属性变化时获得通知。同时可通过off('audioRendererChange')、off('audioCapturerChange')取消相关事件的监听。与此同时,开发者可以通过调用(可选)使用getCurrentAudioRendererInfoArray()获取当前音频播放应用的音频流唯一ID、音频播放客户端的UID、音频状态等信息,同理可调用getCurrentAudioCapturerInfoArray()获取音频录制应用的信息。其具体调用关系可参考音频流管理调用关系图。
详细API含义可参考:[音频管理API文档AudioStreamManager](../reference/apis/js-apis-audio.md#audiostreammanager9)
该模块提供了音频流管理调用关系图
**图1** 音频流管理调用关系图
![](figures/zh-ch_image_audio_stream_manager.png)
![zh-ch_image_audio_stream_manager](figures/zh-ch_image_audio_stream_manager.png)
**说明**:在进行应用开发的过程中,开发者需要使用getStreamManager()创建一个AudioStreamManager实例,进而通过该实例管理音频流。开发者可通过调用on('audioRendererChange')、on('audioCapturerChange')监听音频播放应用和音频录制应用,在应用状态变化、设备变化、音频属性变化时获得通知。同时可通过off('audioRendererChange')、off('audioCapturerChange')取消相关事件的监听。与此同时,开发者可以通过调用(可选)使用getCurrentAudioRendererInfoArray()获取当前音频播放应用的音频流唯一ID、音频播放客户端的UID、音频状态等信息,同理可调用getCurrentAudioCapturerInfoArray()获取音频录制应用的信息。
## 开发步骤
## 开发指导
详细API含义可参考:[音频管理API文档AudioStreamManager](../reference/apis/js-apis-audio.md#audiostreammanager9)
1. 创建AudioStreamManager实例。
在使用AudioStreamManager的API前,需要使用getStreamManager()创建一个AudioStreamManager实例。
```js
var audioStreamManager = audio.getStreamManager();
var audioManager = audio.getAudioManager();
var audioStreamManager = audioManager.getStreamManager();
```
2. (可选)使用on('audioRendererChange')监听音频渲染器更改事件。
......
# OpenSL ES音频录制开发指导
## 场景介绍
## 简介
开发者可以通过本文了解到在**OpenHarmony**如何使用 **OpenSL ES** 进行录音相关操作;当前仅实现了部分[**OpenSL ES**接口](https://gitee.com/openharmony/third_party_opensles/blob/master/api/1.0.1/OpenSLES.h),未实现接口调用后会返回**SL_RESULT_FEATURE_UNSUPPORTED**
开发者可以通过本文档了解在**OpenHarmony**中如何使用**OpenSL ES**进行录音相关操作;当前仅实现了部分[**OpenSL ES**接口](https://gitee.com/openharmony/third_party_opensles/blob/master/api/1.0.1/OpenSLES.h),因此调用未实现接口后会返回**SL_RESULT_FEATURE_UNSUPPORTED**
## 开发步骤
## 开发指导
以下步骤描述了在**OpenHarmony**如何使用 **OpenSL ES** 开发音频录音功能:
......
# OpenSL ES音频播放开发指导
## 场景介绍
## 简介
开发者可以通过本文了解到在**OpenHarmony**如何使用**OpenSL ES**进行音频播放相关操作;当前仅实现了部分[**OpenSL ES**接口](https://gitee.com/openharmony/third_party_opensles/blob/master/api/1.0.1/OpenSLES.h),未实现接口调用后会返回**SL_RESULT_FEATURE_UNSUPPORTED**
开发者可以通过本文档了解在**OpenHarmony**中如何使用**OpenSL ES**进行音频播放相关操作;当前仅实现了部分[**OpenSL ES**接口](https://gitee.com/openharmony/third_party_opensles/blob/master/api/1.0.1/OpenSLES.h),因此调用未实现接口后会返回**SL_RESULT_FEATURE_UNSUPPORTED**
## 开发步骤
## 开发指导
以下步骤描述了在**OpenHarmony**如何使用**OpenSL ES**开发音频播放功能:
......@@ -58,7 +58,7 @@
5. 获取接口 **SL_IID_OH_BUFFERQUEUE****bufferQueueItf** 实例
```
```c++
SLOHBufferQueueItf bufferQueueItf;
(*pcmPlayerObject)->GetInterface(pcmPlayerObject, SL_IID_OH_BUFFERQUEUE, &bufferQueueItf);
```
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册