| getAudioInputSource() | 获取录音的输入设备信息。 | | getBufferFrameCount() | 获取以帧为单位的缓冲区大小。 | | getChannelCount() | 获取音频采集通道数。 | | getEncodingFormat() | 获取音频采集的音频编码格式。 | | getAudioTime(Timestamp timestamp, Timestamp.Timebase timebase) | 获取一个即时的捕获时间戳。 |
开发步骤
- 构造音频流参数的数据结构AudioStreamInfo,推荐使用AudioStreamInfo.Builder类来构造,模板如下,模板中设置的均为AudioStreamInfo.Builder类的默认值,根据音频流的具体规格来设置具体参数。
AudioStreamInfo audioStreamInfo = new AudioStreamInfo.Builder() .sampleRate(AudioStreamInfo.SAMPLE_RATE_UNSPECIFIED) .audioStreamFlag(AudioStreamInfo.AudioStreamFlag.AUDIO_STREAM_FLAG_NONE) .encodingFormat(AudioStreamInfo.EncodingFormat.ENCODING_INVALID) .channelMask(AudioStreamInfo.ChannelMask.CHANNEL_INVALID) .streamUsage(AudioStreamInfo.StreamUsage.STREAM_USAGE_UNKNOWN) .build();
复制
-
(可选)通过采集的采样率、声道数和数据格式,调用getMinBufferSize方法获取采集任务所需的最小buffer,参照该buffer值设置步骤3中AudioCapturerInfo的bufferSizeInBytes。
-
使用步骤1创建的音频流构建音频采集的参数结构AudioCapturerInfo,推荐使用AudioCapturerInfo.Builder类来构造,根据音频采集的具体规格来设置具体参数。以真实的录制pcm流为例:
AudioStreamInfo audioStreamInfo = new AudioStreamInfo.Builder() .encodingFormat(AudioStreamInfo.EncodingFormat.ENCODING_PCM_16BIT) // 16-bit PCM .channelMask(AudioStreamInfo.ChannelMask.CHANNEL_IN_STEREO) // 双声道输入 .sampleRate(44100) // 44.1kHz .build(); AudioCapturerInfo audioCapturerInfo = new AudioCapturerInfo.Builder().audioStreamInfo(audioStreamInfo) .build();
复制
-
(可选)设置采集设备,如麦克风、耳机等。通过AudioManager.getDevices(AudioDeviceDescriptor.DeviceFlag.INPUT_DEVICES_FLAG)获取到设备支持的输入设备,然后依照AudioDeviceDescriptor.DeviceType选择要选用的输入设备类型。
-
通过构造方法获取AudioCapturer类的实例化对象(构造AudioCapturer类的实例化对象前需先去配置录音权限--ohos.permission.MICROPHONE),其中步骤3的参数为必选参数,通过步骤4获取的指定录音设备为可选参数。
录音权限的申请,需要开发者在config.json文件中的“reqPermissions”字段中声明所需要的权限。
"module": { "reqPermissions": [ { "name": "ohos.permission.MICROPHONE" }, { ... } ] }
复制
增加Ability接口的访问权限控制:
public class MainAbility extends Ability { @Override public void onStart(Intent intent) { ... requestPermissions(); //在onStart方法中调用申请的权限 } private void requestPermissions() { String[] permissions = { SystemPermission.ohos.permission.MICROPHONE, ...,... }; requestPermissionsFromUser(Arrays.stream(permissions) .filter(permission -> verifySelfPermission(permission) != IBundleManager.PERMISSION_GRANTED).toArray(String[]::new), 0); } }
复制
实例化AudioCapturer对象:
AudioCapturer audioCapturer = new AudioCapturer(audioCapturerInfo);
复制
-
(可选)设置采集音效,如降噪、回声消除等。使用addSoundEffect(UUID type, String packageName)进行音效设置,其中UUID参考类SoundEffect中提供的静态变量。
-
(可选)构造音频采集回调,首先继承抽象类AudioCapturerCallback,并实现抽象方法onCapturerConfigChanged(List configs),然后调用AudioManager类的registerAudioCapturerCallback(AudioCapturerCallback cb)方法进行音频采集回调注册。代码示例如下:
private AudioManager audioManager = new AudioManager();
public void main() { AudioCapturerCallback cb = new AudioCapturerCallback() { @Override public void onCapturerConfigChanged(List configs) { configs.forEach(config -> doSomething(config)); } }; audioManager.registerAudioCapturerCallback(cb); }
private void doSomething(AudioCapturerConfig config) { ... }
复制
-
调用 AudioCapturer实例化对象的start()方法启动采集任务。
-
采集的音频数据读取为byte流,循环调用AudioCapturer的read方法进行数据读取。
-
调用AudioCapturer实例化对象的stop()方法停止采集。
-
采集任务结束后,调用AudioCapturer实例化对象的release()释放资源。
二、音量管理开发
场景介绍
音量管理的主要工作是音量调节,输入/输出设备管理,注册音频中断、音频采集中断的回调等。
接口说明
当前仅系统应用支持设置静音或响铃等模式。
| 接口名 | 描述 |
|---|---|
| AudioManager() | 构造函数。 |
| AudioManager(Context context) | 构造函数,由使用者指定应用上下文Context。 |
| AudioManager(String packageName) | 构造函数,由使用者指定包信息。 |
| activateAudioInterrupt(AudioInterrupt interrupt) | 激活音频中断状态检测。 |
| deactivateAudioInterrupt(AudioInterrupt interrupt) | 去激活音频中断状态检测。 |
| getAudioParameter(String key) | 获取音频硬件中指定参数keys所对应的参数值。 |
| getDevices(DeviceFlag flag) | 获取设备信息。 |
| getMaxVolume(AudioVolumeType volumeType) | 获取指定音频流音量最大档位。 |
| getMinVolume(AudioVolumeType volumeType) | 获取指定音频流音量最小档位。 |
| getRingerMode() | 获取铃声模式。 |
| getVersion() | 获取音频套件版本。 |
| getVolume(AudioVolumeType volumeType) | 获取指定音频流的音量档位。 |
| isDeviceActive(int deviceType) | 判断设备的开关状态。 |
| isMute(AudioVolumeType volumeType) | 特定的流是否处于静音状态。 |
| mute(AudioVolumeType volumeType) | 将特定流设置为静音状态。 |
| setAudioParameter(String key, String value) | 为音频硬件设置可变数量的参数值。 |
| setDeviceActive(int deviceType, boolean state) | 设置设备的开关状态。 |
| setRingerMode(AudioRingMode mode) | 设置铃声模式。 |
| setVolume(AudioVolumeType volumeType, int volume) | 设置特定流的音量档位。 |
| unmute(AudioVolumeType volumeType) | 将特定流设置为非静音状态。 |
| setMasterMute(boolean isMute) | 将主音频输出设备设置为静音或取消静音状态。 |
| setMicrophoneMute(boolean isMute) | 将麦克风设置为静音或取消静音状态。 |
| isMicrophoneMute() | 判断麦克风是否处于静音状态。 |
| getActiveCapturerConfigs() | 获取设备当前激活的音频采集任务的配置信息。 |
| registerAudioCapturerCallback(AudioCapturerCallback cb) | 注册音频采集参数变更回调。 |
| unregisterAudioCapturerCallback(AudioCapturerCallback cb) | 去注册音频采集参数变更回调。 |
| getRingerUri(Context context, RingToneType type) | 获取指定铃声类型的Uri。 |
| setRingerUri(Context context, RingToneType type, Uri uri) | 设置指定铃声类型的Uri。 |
| changeVolumeBy(AudioVolumeType volumeType, int index) | 将当前音量增加或减少一定量。 |
| connectBluetoothSco() | 连接到蓝牙SCO通道。 |
| disconnectBluetoothSco() | 断开与蓝牙SCO通道的连接。 |
| getActiveRendererConfigs() | 获取有关活动音频流信息,包括使用类型、内容类型和标志。 |
| getMasterOutputFrameCount() | 获取主输出设备缓冲区中的帧数。 |
| getMasterOutputSampleRate() | 获取主输出设备的采样率。 |
| isMasterMute() | 检查音频流是否全局静音。 |
| isStreamActive(AudioVolumeType volumeType) | 检查指定类型的音频流是否处于活动状态。 |
| makeSessionId() | 创建一个会话ID,AudioRendererInfo.Builder.sessionID(int)将使用该会话ID来设置音频播放参数,而AudioCapturerInfo.Builder.sessionID(int)将使用该会话ID来设置记录参数。 |
| registerAudioRendererCallback(AudioRendererCallback cb) | 注册音频播放参数变更回调。 |
| unregisterAudioRendererCallback(AudioRendererCallback cb) | 去注册音频播放参数变更回调。 |
开发步骤
音量管理提供的都是独立的功能,一般作为音频播放和音频采集的功能补充来使用。开发者根据具体使用场景选择方法即可。
音频中断状态检测和音频采集中断状态检测的使用样例,请参考音频播放和音频采集的开发步骤。
三、短音播放开发
场景介绍
短音播放主要负责管理音频资源的加载与播放、tone音的生成与播放以及系统音播放。
接口说明
短音播放开放能力分为音频资源、tone音和系统音三部分,均定义在SoundPlayer类
| 接口名 | 描述 |
|---|---|
| SoundPlayer(int taskType) | 构造函数,仅用于音频资源。 |
| createSound(String path) | 从指定的路径加载音频数据生成短音资源。 |
| createSound(Context context, int resourceId) | 根据应用程序上下文合音频资源ID加载音频数据生成短音资源。 |
| createSound(AssetFD assetFD) | 从指定的AssetFD实例加载音频数据生成短音资源。 |
| createSound(java.io.FileDescriptor fd, long offset, long length) | 根据文件描述符从文件加载音频数据生成音频资源。 |
| createSound(java.lang.String path, AudioRendererInfo rendererInfo) | 根据从指定路径和播放信息加载音频数据生成短音资源。 |
| setOnCreateCompleteListener(SoundPlayer.OnCreateCompleteListener listener) | 设置声音创建完成的回调。 |
| setOnCreateCompleteListener(SoundPlayer.OnCreateCompleteListener listener, boolean isDiscarded) | 设置用于声音创建完成的回调,并根据指定的isDiscarded标志位确定是否丢弃队列中的原始回调通知消息。 |
| deleteSound(int soundID) | 删除短音同时释放短音所占资源。 |
| pause(int taskID) | 根据播放任务ID暂停对应的短音播放。 |
| play(int soundID) | 使用默认参数播放短音。 |
| play(int soundID, SoundPlayerParameters parameters) | 使用指定参数播放短音。 |
| resume(int taskID) | 恢复短音播放任务。 |
| setLoop(int taskID, int loopNum) | 设置短音播放任务的循环次数。 |
| setPlaySpeedRate(int taskID, float speedRate) | 设置短音播放任务的播放速度。 |
| setPriority(int taskID, int priority) | 设置短音播放任务的优先级。 |
| setVolume(int taskID, AudioVolumes audioVolumes) | 设置短音播放任务的播放音量。 |
| setVolume(int taskID, float volume) | 设置短音播放任务的所有音频声道的播放音量。 |
| stop(int taskID) | 停止短音播放任务。 |
| pauseAll() | 暂停所有正在播放的任务。 |
| resumeAll() | 恢复虽有已暂停的播放任务。 |
tone音的生成与播放API接口功能介绍
| 接口名 | 描述 |
|---|---|
| SoundPlayer() | 构造函数,仅用于tone音。 |
| createSound(ToneDescriptor.ToneType type, int durationMs) | 创建具有音调频率描述和持续时间(毫秒)的tone音。 |
| createSound(AudioStreamInfo.StreamType streamType, float volume) | 根据音量和音频流类型创建tone音。 |
| play(ToneDescriptor.ToneType toneType, int durationMs) | 播放指定时长和tone音类型的tone音。 |
| pause() | 暂停tone音播放。 |
| play() | 播放创建好的tone音。 |
| release() | 释放tone音资源。 |
系统音的播放API接口功能介绍
| 接口名 | 描述 |
|---|---|
| SoundPlayer(String packageName) | 构造函数,仅用于系统音。 |
| playSound(SoundType type) | 播放系统音。 |
| playSound(SoundType type, float volume) | 指定音量播放系统音。 |
音频资源的加载与播放
- 通过SoundPlayer(int)构造方法获取SoundPlayer类的实例化对象,其中入参taskType的取值范围和含义参考枚举类AudioManager.AudioStreamType的定义。
- 调用createSound(String)方法从指定路径加载音频资源,并生成短音ID,后续可使用通过短音ID进行短音资源的播放和删除等操作。
- 使用默认播放参数的play(int)方法进行播放,并通过播放成功后返回任务ID进行音量、循环次数、播放速度和优先级等参数的设置,也可以通过任务ID进行短音资源的暂停,恢复等操作。
- 短音资源需要暂停的时候可以使用stop(int)来停止短音播放,想要恢复可以使用resume(int)来对短音任务恢复播放。
- 短音资源使用完毕需要调用deleteSound(int)对短音任务ID删除,调用release(int)对短音资源的释放。下面的样例展示音频资源的加载与播放:
public SoundPlayer soundPlayer; public Map<Integer, Boolean> soundMap = new HashMap<>(); public int taskId; public static final int ERRORID = -1; public void initSoundPlayer() { // 步骤1:实例化对象 SoundPlayer soundPlayer = new SoundPlayer(AudioManager.AudioVolumeType.STREAM_MUSIC.getValue()); // 步骤2:加载指定音频资源并创建短音 int soundId1 = soundPlayer.createSound("/xxx/sound1_file_path"); soundMap.put(soundId1, false); int soundId2 = soundPlayer.createSound("/xxx/sound2_file_path"); soundMap.put(soundId2, false); int soundId3 = soundPlayer.createSound("/xxx/sound3_file_path"); soundMap.put(soundId3, false); soundPlayer.setOnCreateCompleteListener((soundPlayer1, cacheId, status) -> { // 对应的短音创建成功 if (status == 0 && soundMap.containsKey(cacheId)) { soundMap.put(cacheId, true); } }); } public int PlaySound(int soundId) { // 步骤3:播放指定的短音 if (soundMap.containsKey(cacheId) && soundMap.get(cacheId)) { taskId = soundPlayer.play(soundId); } else { taskId = ERRORID; HiLog.warn(TAG, "sound id is not ready."); } return taskId; } public void stopSoundPlayer(int taskId) { // 步骤4:停止短音资源 if (taskId > 0){ soundPlayer.stop(taskId); } } public void releaseSoundPlayer() { // 步骤5:释放短音资源 Iterator<Map.Entry<Integer, Boolean>> iterator = soundMap.entrySet().iterator(); while (iterator.hasNext()){ Map.Entry<Integer, Boolean> entry = iterator.next(); int soundId = entry.getKey().intValue(); soundPlayer.deleteSound(soundId); iterator.remove(); } soundPlayer.release(); }
复制
tone音的生成与播放
- 通过SoundPlayer()构造方法获取SoundPlayer类的实例化对象。
- 使用SoundPlayer的实例化对象,通过createSound(ToneDescriptor.ToneType, int)方法,指定tone音类型和tone音播放时长来创建tone音资源。
- 使用SoundPlayer的实例化对象,通过play、pause、release方法完成tone音播放、暂停和资源释放。 下面的样例展示tone音的生成与播放:
public void demo() { // 步骤1:实例化对象 SoundPlayer soundPlayer = new SoundPlayer(); // 步骤2:创建DTMF_0(高频1336Hz,低频941Hz)持续时间1000ms的tone音 soundPlayer.createSound(ToneDescriptor.ToneType.DTMF_0, 1000); // 步骤3:tone音播放、暂停和资源释放 soundPlayer.play(); soundPlayer.pause(); soundPlayer.release(); }
复制
系统音的播放
- 通过SoundPlayer(String)构造方法获取SoundPlayer类的实例化对象。
- 使用SoundPlayer的实例化对象,通过playSound(SoundType)或playSound(SoundType, float)方法指定系统音类型和音量,并进行系统音播放。 下面的样例展示系统音的播放:
public void demo() { // 步骤1:实例化对象 SoundPlayer soundPlayer = new SoundPlayer("packageName"); // 步骤2:播放键盘敲击音,音量为1.0 soundPlayer.playSound(SoundPlayer.SoundType.KEY_CLICK, 1.0f); }
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!