Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
Docs
提交
6ce4b770
D
Docs
项目概览
OpenHarmony
/
Docs
1 年多 前同步成功
通知
159
Star
292
Fork
28
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
Docs
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
未验证
提交
6ce4b770
编写于
3月 16, 2022
作者:
O
openharmony_ci
提交者:
Gitee
3月 16, 2022
浏览文件
操作
浏览文件
下载
差异文件
!2091 audio-renderer.md、js-apis-audio.md、system-sound-manager.md文档修改
Merge pull request !2091 from li-yifan2/master
上级
b8924e5c
a8aeb4bf
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
419 addition
and
32 deletion
+419
-32
zh-cn/application-dev/media/audio-capturer.md
zh-cn/application-dev/media/audio-capturer.md
+116
-0
zh-cn/application-dev/media/audio-management.md
zh-cn/application-dev/media/audio-management.md
+76
-32
zh-cn/application-dev/media/audio-renderer.md
zh-cn/application-dev/media/audio-renderer.md
+227
-0
未找到文件。
zh-cn/application-dev/media/audio-capturer.md
0 → 100644
浏览文件 @
6ce4b770
# AudioCapturer音频采集开发指南
## 场景介绍
AudioCapturer提供了用于获取原始音频文件的方法。开发者可以通过本指导了解应用如何通过AudioCapturer采集音频。
## 注意事项
在进行应用开发的过程中,建议开发者通过on('stateChange')方法订阅AudioCapturer的状态变更。因为针对AudioCapturer的某些操作,仅在音频采集器在固定状态时才能执行。如果应用在音频采集器处于错误状态时执行操作,系统可能会抛出异常或生成其他未定义的行为。
## 状态检查
应用程序开发人员应该记住,AudioCapturer 是基于状态的。
<br/>
也就是说,AudioCapturer 有一个内部状态,应用程序在调用录制器控制 API 时必须始终检查该状态,因为某些操作仅在录制器处于给定状态时才可接受。
如果应用程序在录制器处于不正确状态时执行操作,系统可能会抛出错误/异常或生成其他未定义的行为。
## 开发步骤
1.
使用createAudioCapturer()创建一个AudioCapturer实例。
<br/>
在audioCapturerOptions中设置音频采集器的相关参数。该实例可用于音频采集、控制和获取采集状态,以及注册通知回调。
```
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.
调用start()方法来启动/恢复采集任务。
启动完成后,采集器状态将变更为STATE_RUNNING,然后应用可以开始读取缓冲区。
```
await audioCapturer.start();
if (audioCapturer.state == audio.AudioState.STATE_RUNNING) {
console.info('AudioRecLog: Capturer started');
} else {
console.info('AudioRecLog: Capturer start failed');
}
```
3.
使用getBufferSize()方法获取要读取的最小缓冲区大小。
```
var bufferSize = await audioCapturer.getBufferSize();
console.info('AudioRecLog: buffer size: ' + bufferSize);
```
4.
读取采集器的音频数据并将其转换为字节流。重复调用read()方法读取数据,直到应用准备停止采集。
参考以下示例,将采集到的数据写入文件。
```
import fileio from '@ohos.fileio';
const path = '/data/data/.pulse_dir/capture_js.wav';
let fd = fileio.openSync(path, 0o102, 0o777);
if (fd !== null) {
console.info('AudioRecLog: file fd created');
}
else{
console.info('AudioRecLog: file fd create : FAILED');
return;
}
fd = fileio.openSync(path, 0o2002, 0o666);
if (fd !== null) {
console.info('AudioRecLog: file fd opened in append mode');
}
var numBuffersToCapture = 150;
while (numBuffersToCapture) {
var buffer = await audioCapturer.read(bufferSize, true);
if (typeof(buffer) == undefined) {
console.info('read buffer failed');
} else {
var number = fileio.writeSync(fd, buffer);
console.info('AudioRecLog: data written: ' + number);
}
numBuffersToCapture--;
}
```
5.
采集完成后,调用stop方法,停止录制。
```
await audioCapturer.stop();
if (audioCapturer.state == audio.AudioState.STATE_STOPPED) {
console.info('AudioRecLog: Capturer stopped');
} else {
console.info('AudioRecLog: Capturer stop failed');
}
```
6.
任务结束,调用release()方法释放相关资源。
```
await audioCapturer.release();
if (audioCapturer.state == audio.AudioState.STATE_RELEASED) {
console.info('AudioRecLog: Capturer released');
} else {
console.info('AudioRecLog: Capturer release failed');
}
```
\ No newline at end of file
zh-cn/application-dev/media/audio-management.md
浏览文件 @
6ce4b770
...
...
@@ -18,62 +18,82 @@
| DeviceFlag | 表示可获取的设备种类的枚举。 |
| DeviceRole | 表示设备角色的枚举。 |
| DeviceType | 表示设备类型的枚举。 |
| AudioScene | 表示音频场景的枚举。 |
**表2**
音频管理相关的interface
**AudioManager**
| 接口名 | 描述 |
| 接口名 | 描述 |
| -------- | -------- |
| setVolume(audioType:
AudioVolumeType,volume:
number,callback:
AsyncCallback
<
void
>
):
void | 改变某个流的音量。 |
| setVolume(audioType:
AudioVolumeType,volume:
number):
Promise
<
void
>
| 改变某个流的音量。 |
| getVolume(audioType:
AudioVolumeType,
callback:
AsyncCallback
<
number
>
):
void | 获得某个流的音量。 |
| getVolume(audioType:
AudioVolumeType):
Promise
<
number
>
| 获得某个流的音量。 |
| getMinVolume(audioType:
AudioVolumeType,
callback:
AsyncCallback
<
number
>
):
void | 获得某个流的最小音量。 |
| getMinVolume(audioType:
AudioVolumeType):
Promise
<
number
>
| 获得某个流的最小音量。 |
| getMaxVolume(audioType:
AudioVolumeType,
callback:
AsyncCallback
<
number
>
):
void | 获得某个流的最大音量。 |
| getMaxVolume(audioType:
AudioVolumeType):
Promise
<
number
>
| 获得某个流的最大音量。 |
| getDevices(deviceFlag:
DeviceFlag,
callback:
AsyncCallback
<
AudioDeviceDescriptors
>
):
void | 获得设备列表。 |
| getDevices(deviceFlag:
DeviceFlag):
Promise
<
AudioDeviceDescriptors
>
| 获得设备列表。 |
| setVolume(audioType:
AudioVolumeType,volume:
number,callback:
AsyncCallback
<
void
>
):
void | 改变某个流的音量。 |
| setVolume(audioType:
AudioVolumeType,volume:
number):
Promise
<
void
>
| 改变某个流的音量。 |
| getVolume(audioType:
AudioVolumeType,
callback:
AsyncCallback
<
number
>
):
void | 获得某个流的音量。 |
| getVolume(audioType:
AudioVolumeType):
Promise
<
number
>
| 获得某个流的音量。 |
| getMinVolume(audioType:
AudioVolumeType,
callback:
AsyncCallback
<
number
>
):
void | 获得某个流的最小音量。 |
| getMinVolume(audioType:
AudioVolumeType):
Promise
<
number
>
| 获得某个流的最小音量。 |
| getMaxVolume(audioType:
AudioVolumeType,
callback:
AsyncCallback
<
number
>
):
void | 获得某个流的最大音量。 |
| getMaxVolume(audioType:
AudioVolumeType):
Promise
<
number
>
| 获得某个流的最大音量。 |
| getDevices(deviceFlag:
DeviceFlag,
callback:
AsyncCallback
<
AudioDeviceDescriptors
>
):
void | 获得设备列表。 |
| getDevices(deviceFlag:
DeviceFlag):
Promise
<
AudioDeviceDescriptors
>
| 获得设备列表。 |
| setDeviceActive(deviceType: ActiveDeviceType, active: boolean, callback: AsyncCallback
<void>
): void | 激活设备,使用callback返回异步结果 |
| setDeviceActive(deviceType: ActiveDeviceType, active: boolean): Promise
<void>
| 激活设备,使用Promise返回异步结果。 |
| isDeviceActive(deviceType: ActiveDeviceType, callback: AsyncCallback
<boolean>
): void | 检查设备是否激活,使用callback返回异步结果。 |
| isDeviceActive(deviceType: ActiveDeviceType): Promise
<boolean>
| 检查设备是否激活,使用Promise返回异步结果。 |
| on(type: 'deviceChange', callback: AsyncCallback
<DeviceChangeAction>
): void | 订阅设备更改事件。 当设备连接或断开时,注册的客户端将收到回调。 |
| setAudioScene(scene: AudioScene, callback: AsyncCallback
<void>
): void | 设置音频场景模式,使用callback返回异步结果。 |
| setAudioScene(scene: AudioScene): Promise
<void>
| 设置音频场景模式,使用Promise返回异步结果。 |
| getAudioScene(callback: AsyncCallback
<AudioScene>
): void | 获取音频场景模式,使用callback返回异步结果。 |
| getAudioScene(): Promise
<AudioScene>
| 获取音频场景模式,使用Promise返回异步结果。 |
**表3**
表示音频设备的interface
**AudioDeviceDescriptor**
| 属性 | 描述 |
| 属性 | 描述 |
| -------- | -------- |
| deviceRole:
DeviceRole | 设备角色。 |
| deviceType:
DeviceType | 设备类型。 |
| deviceRole:
DeviceRole | 设备角色。 |
| deviceType:
DeviceType | 设备类型。 |
**表4**
表示音频流类型的枚举
**AudioVolumeType**
| 枚举值 | 描述 |
| 枚举值 | 描述 |
| -------- | -------- |
| MEDIA
=
1 | 媒体声音。 |
| RINGTONE
=
2 | 铃声。 |
| VOICE_CALL = 0 | 语音通话。 |
| MEDIA
=
1 | 媒体声音。 |
| RINGTONE
=
2 | 铃声。 |
| VOICE_ASSISTANT = 9 | 语音助手。 |
**表5**
表示可获取的设备种类的枚举
**DeviceFlag**
| 枚举值 | 描述 |
| 枚举值 | 描述 |
| -------- | -------- |
| OUTPUT_DEVICES_FLAG
=
1 | 输出设备。 |
| INPUT_DEVICES_FLAG
=
2 | 输入设备。 |
| ALL_DEVICES_FLAG
=
3 | 所有设备。 |
| OUTPUT_DEVICES_FLAG
=
1 | 输出设备。 |
| INPUT_DEVICES_FLAG
=
2 | 输入设备。 |
| ALL_DEVICES_FLAG
=
3 | 所有设备。 |
**表6**
表示设备角色的枚举
**DeviceRole**
| 枚举值 | 描述 |
| 枚举值 | 描述 |
| -------- | -------- |
| INPUT_DEVICE
=
1 | 输入设备。 |
| OUTPUT_DEVICE
=
2 | 输出设备。 |
| INPUT_DEVICE
=
1 | 输入设备。 |
| OUTPUT_DEVICE
=
2 | 输出设备。 |
**表7**
表示设备类型的枚举
**DeviceType**
| 枚举值 | 描述 |
| 枚举值 | 描述 |
| -------- | -------- |
| INVALID
=
0 | 无效。 |
| SPEAKER
=
1 | 扬声器。 |
| WIRED_HEADSET
=
2 | 有线耳机。 |
| BLUETOOTH_SCO
=
3 | 蓝牙设备。 |
| BLUETOOTH_A2DP
=
4 | 支持A2DP的蓝牙设备。 |
| MIC
=
5 | 麦克风。 |
| INVALID
=
0 | 无效。 |
| SPEAKER
=
2 | 扬声器。 |
| WIRED_HEADSET
=
3 | 有线耳机。 |
| BLUETOOTH_SCO
=
7 | 蓝牙设备。 |
| BLUETOOTH_A2DP
=
8 | 支持A2DP的蓝牙设备。 |
| MIC
=
15 | 麦克风。 |
**表8**
表示音频模式的枚举
** **
AudioScene
**
| Name | Description |
| :------------------------- | :----------------------- |
| AUDIO_SCENE_DEFAULT = 0 | 默认的音频。
<br/>
|
| AUDIO_SCENE_RINGING = 1 | 响铃音频场景。
<br/>
|
| AUDIO_SCENE_PHONE_CALL = 2 | 电话音频场景。
<br/>
|
| AUDIO_SCENE_VOICE_CHAT = 3 | 语音聊天音频场景。
<br/>
|
## 开发步骤
...
...
@@ -92,3 +112,27 @@
console.log(`Media getVolume ${value}`);
});
```
## 使用方法
**setAudioScene**
**示例**
1.
获取音频管理器。
```
const audioManager = audio.getAudioManager();
```
2.
获取当前的音频场景。
```
audioManager.getAudioScene((err, value) => {
if (err) {
console.error('Failed to obtain the audio scene mode. ${err.message}');
return;
}
console.log('Audio scene mode ${value)');
})
```
\ No newline at end of file
zh-cn/application-dev/media/audio-renderer.md
0 → 100644
浏览文件 @
6ce4b770
# AudioRenderer音频渲染开发指导
## 场景介绍
AudioRenderer提供了渲染音频文件和控制播放的接口,开发者可以通过本指导,了解如何在输出设备中播放音频文件并管理播放任务。
<br/>
同时,AudioRenderer支持音频中断的功能。
<br/>
**音频中断:**
当优先级较高的音频流需要播放时,AudioRenderer会中断优先级较低的流。例如,当用户在收听音乐时有来电,则优先级较低音乐播放将被暂停,具体可参考
[
开发步骤
](
#开发步骤)。
## 状态检查
您还应该记住,AudioRenderer 是基于状态的。
也就是说,AudioRenderer 有一个内部状态,在调用播放控制 API 时必须始终检查它,因为某些操作仅在音频播放器处于给定状态时才可接受。
如果您在不正确的状态下执行操作,系统可能会抛出错误/异常或生成其他未定义的行为。
## 异步操作
大多数AudioRenderer调用都是异步的。因此,UI线程不会被阻塞。
<br/>
对于每个API,框架都提供callback函数和promise函数。
在本例中,为了简单起见,使用了promise函数。
[
**js api audio.md**
](
../reference/apis/js-apis-audio.md
)
为callback和promise提供参考。
## 开发步骤
1.
使用createAudioRenderer()创建一个AudioRenderer实例。
在audioCapturerOptions中设置相关参数。该实例可用于音频渲染、控制和获取采集状态,以及注册通知回调。
```
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')方法订阅音频中断事件。
<br/>
当优先级更高或相等的Stream-B请求激活并使用输出设备时,Stream-A被中断。
在某些情况下,框架会采取暂停播放、降低音量等强制操作,并通过InterruptEvent通知应用。在其他情况下,应用可以自行对InterruptEvent做出响应。
<br/>
在音频中断的情况下,应用可能会碰到音频数据写入失败的问题。所以建议不感知、不处理中断的应用在写入音频数据前,使用audioRenderer.state检查播放器状态。而订阅音频中断事件,可以获取到更多详细信息,具体可参考
[
InterruptEvent
](
../reference/apis/js-apis-audio.md#interruptevent8
)
。
```
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()方法来启动/恢复播放任务。
启动完成后,渲染器状态将变更为STATE_RUNNING,然后应用可以开始读取缓冲区。
```
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()方法向缓冲区写入数据。
将需要播放的音频数据读入缓冲区,重复调用write()方法写入。
```
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
;
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()方法暂停/停止渲染音频数据。
```
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'
);
}
}
```
6.
任务完成,调用release()方法释放相关资源。
AudioRenderer会使用大量的系统资源,所以请确保完成相关任务后,进行资源释放。
```
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
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录