HarmonyOS学习路之开发篇—多媒体开发(音频开发 二)

2023-10-15 08:50:57 浏览数 (1)

一、音频音频采集开发

场景介绍

音频采集的主要工作是通过输入设备将声音采集并转码为音频数据,同时对采集任务进行管理。

接口说明

接口名

描述

AudioCapturer(AudioCapturerInfo audioCapturerInfo) throws IllegalArgumentException

构造函数,设置录音相关音频参数,使用默认录音设备。

AudioCapturer(AudioCapturerInfo audioCapturerInfo, AudioDeviceDescriptor devInfo) throws IllegalArgumentException

构造函数,设置录音相关音频参数并指定录音设备。

getMinBufferSize(int sampleRate, int channelCount, int audioFormat)

获取指定参数条件下所需的最小缓冲区大小。

addSoundEffect(UUID type, String packageName)

增加录音的音频音效。

start()

开始录音。

read(byte[] data, int offset, int size)

读取音频数据。

read​(byte[] data, int offset, int size, boolean isBlocking)

读取音频数据并写入传入的byte数组中。

read​(float[] data, int offsetInFloats, int sizeInFloats)

阻塞式读取音频数据并写入传入的float数组中。

read​(float[] data, int offsetInFloats, int sizeInFloats, boolean isBlocking)

读取音频数据并写入传入的float数组中。

read​(short[] data, int offsetInShorts, int sizeInShorts)

阻塞式读取音频数据并写入传入的short数组中。

read​(short[] data, int offsetInShorts, int sizeInShorts, boolean isBlocking)

读取音频数据并写入传入的short数组中。

read​(java.nio.ByteBuffer buffer, int sizeInBytes)

阻塞式读取音频数据并写入传入的ByteBuffer对象中。

read​(java.nio.ByteBuffer buffer, int sizeInBytes, boolean isBlocking)

读取音频数据并写入传入的ByteBuffer对象中。

stop()

停止录音。

release()

释放录音资源。

getSelectedDevice()

获取输入设备信息。

getCurrentDevice()

获取当前正在录制音频的设备信息。

getCapturerSessionId()

获取录音的session ID。

getSoundEffects()

获取已经激活的音频音效列表。

getState()

获取音频采集状态。

getSampleRate()

获取采样率。

getAudioInputSource()

获取录音的输入设备信息。

getBufferFrameCount​()

获取以帧为单位的缓冲区大小。

getChannelCount​()

获取音频采集通道数。

getEncodingFormat​()

获取音频采集的音频编码格式。

getAudioTime(Timestamp timestamp, Timestamp.Timebase timebase)

获取一个即时的捕获时间戳。

开发步骤

1. 构造音频流参数的数据结构AudioStreamInfo,推荐使用AudioStreamInfo.Builder类来构造,模板如下,模板中设置的均为AudioStreamInfo.Builder类的默认值,根据音频流的具体规格来设置具体参数。

代码语言:javascript复制
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();

2. (可选)通过采集的采样率、声道数和数据格式,调用getMinBufferSize方法获取采集任务所需的最小buffer,参照该buffer值设置步骤3中AudioCapturerInfo的bufferSizeInBytes。

3. 使用步骤1创建的音频流构建音频采集的参数结构AudioCapturerInfo,推荐使用AudioCapturerInfo.Builder类来构造,根据音频采集的具体规格来设置具体参数。以真实的录制pcm流为例:

代码语言:javascript复制
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();

4. (可选)设置采集设备,如麦克风、耳机等。通过AudioManager.getDevices(AudioDeviceDescriptor.DeviceFlag.INPUT_DEVICES_FLAG)获取到设备支持的输入设备,然后依照AudioDeviceDescriptor.DeviceType选择要选用的输入设备类型。

5. 通过构造方法获取AudioCapturer类的实例化对象(构造AudioCapturer类的实例化对象前需先去配置录音权限--ohos.permission.MICROPHONE),其中步骤3的参数为必选参数,通过步骤4获取的指定录音设备为可选参数。

录音权限的申请,需要开发者在config.json文件中的“reqPermissions”字段中声明所需要的权限。

代码语言:javascript复制
"module": {
  "reqPermissions": [
    {
      "name": "ohos.permission.MICROPHONE"
    },
    {
    ...
    }
  ]
}

增加Ability接口的访问权限控制:

代码语言:javascript复制
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对象:

代码语言:javascript复制
AudioCapturer audioCapturer = new AudioCapturer(audioCapturerInfo);

6. (可选)设置采集音效,如降噪、回声消除等。使用addSoundEffect(UUID type, String packageName)进行音效设置,其中UUID参考类SoundEffect中提供的静态变量。

7. (可选)构造音频采集回调,首先继承抽象类AudioCapturerCallback,并实现抽象方法onCapturerConfigChanged(List<AudioCapturerConfig> configs),然后调用AudioManager类的registerAudioCapturerCallback(AudioCapturerCallback cb)方法进行音频采集回调注册。代码示例如下:

代码语言:javascript复制
private AudioManager audioManager = new AudioManager();

public void main() {
    AudioCapturerCallback cb = new AudioCapturerCallback() {
        @Override
        public void onCapturerConfigChanged(List<AudioCapturerConfig> configs) {
            configs.forEach(config -> doSomething(config));
        }
    };
    audioManager.registerAudioCapturerCallback(cb);
}

private void doSomething(AudioCapturerConfig config) {
    ...
}

8. 调用 AudioCapturer实例化对象的start()方法启动采集任务。

9. 采集的音频数据读取为byte流,循环调用AudioCapturer的read方法进行数据读取。

10. 调用AudioCapturer实例化对象的stop()方法停止采集。

11. 采集任务结束后,调用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)

指定音量播放系统音。

音频资源的加载与播放

  1. 通过SoundPlayer(int)构造方法获取SoundPlayer类的实例化对象,其中入参taskType的取值范围和含义参考枚举类AudioManager.AudioStreamType的定义。
  2. 调用createSound(String)方法从指定路径加载音频资源,并生成短音ID,后续可使用通过短音ID进行短音资源的播放和删除等操作。
  3. 使用默认播放参数的play(int)方法进行播放,并通过播放成功后返回任务ID进行音量、循环次数、播放速度和优先级等参数的设置,也可以通过任务ID进行短音资源的暂停,恢复等操作。
  4. 短音资源需要暂停的时候可以使用stop(int)来停止短音播放,想要恢复可以使用resume(int)来对短音任务恢复播放。
  5. 短音资源使用完毕需要调用deleteSound(int)对短音任务ID删除,调用release(int)对短音资源的释放。下面的样例展示音频资源的加载与播放:
代码语言:javascript复制
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音的生成与播放

  1. 通过SoundPlayer()构造方法获取SoundPlayer类的实例化对象。
  2. 使用SoundPlayer的实例化对象,通过createSound(ToneDescriptor.ToneType, int)方法,指定tone音类型和tone音播放时长来创建tone音资源。
  3. 使用SoundPlayer的实例化对象,通过play、pause、release方法完成tone音播放、暂停和资源释放。 下面的样例展示tone音的生成与播放:
代码语言:javascript复制
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();
}

系统音的播放

  1. 通过SoundPlayer(String)构造方法获取SoundPlayer类的实例化对象。
  2. 使用SoundPlayer的实例化对象,通过playSound(SoundType)或playSound(SoundType, float)方法指定系统音类型和音量,并进行系统音播放。 下面的样例展示系统音的播放:
代码语言:javascript复制
public void demo() {
    // 步骤1:实例化对象
    SoundPlayer soundPlayer = new SoundPlayer("packageName");
    // 步骤2:播放键盘敲击音,音量为1.0
    soundPlayer.playSound(SoundPlayer.SoundType.KEY_CLICK, 1.0f);
}

0 人点赞