SOP TRTC SDK 仪表盘 Android TRTC 发送自定义采集的视频数据 Android TRTC 发送自定义采集音频解决方案 Android TRTC 实现横屏视频通话 iOS端 TRTC 发送自定义采集视频解决方案 iOS端 TRTC 发送自定义采集音频解决方案 APNS推送 脏字过滤 TXLiteAVSDK中使用 AVAudioSession 问题总结 AndroidStudio编译SDK报错 RoomService部署验证 Xcode编译SDK报错 iOS编译库冲突问题 iOS端移动直播自定义采集实现 iOS端TXLiteAVSDK与IMSDK 3.x集成冲突报错问题 Android端TXLiteAVSDK与IMSDK 3.x集成冲突报错问题 Android端LiteIM sdk升级IM4.x版本报错问题 移动直播iOS 12兼容问题 如何实现好的画质 如何计算PCM音量大小 使用播放器播放视频有黑边 直播拉流播放失败 直播拉流端卡顿现象 短视频上传失败 移动直播SDK对接第三方美颜库 移动直播连麦解决方案 Android移动直播推自定义采集的视频数据 Android移动直播推自定义采集的声音数据 Android直播播放如何获取YUV数据 Android直播播放如何自定义渲染 实时音视频画面黑屏 实时音视频订阅流显示 iOS 12默认新编译系统下文件名冲突问题 TXLiteAVSDK指标监控 进阶:小程序实时音视频参数透传 移动直播 Android 9.0 无法拉流问题 移动直播推流事件回调 移动直播拉流事件回调 短视频实现视频缩略图列表转GIF功能 roomService加入群组时报错invalid group id NTP时间戳转换 提示Role not exists 角色不存在 如何播放背景音乐 iOS端短视频添音频相关问题总结 Web同步终端离线推送TIMOfflinePushInfo说明文档 web端自定义消息发送 web端同步终端的已读回执 web端对群组内用户禁言操作 TRTC v2混流接口setMixTranscodingConfig使用指引

如何通过SDK的音频录制回调计算PCM音量大小

发布日期:2018年7月10日 更新日期:2018年7月10日 贡献者:yjiexia yyuanchen

场景

在开发者集成腾讯视频云客户端SDK进行直播业务时,在一些场景中会遇到需要计算麦克风采集音量大小的情况,例如在主播直播时显示音量波形图,或是在直播列表页上显示正在说话的主播等等,针对这些场景,腾讯视频云客户端SDK提供了原始数据采集回调,开发者可以通过此回调接口拿到SDK采集的原始PCM数据,然后再进行处理,这里我们提供一段参考代码,开发者可以根据此段代码来计算PCM数据的音量。

PCM音量大小计算

iOS

#pragma mark - TXAudioCustomProcessDelegate
// 在 iOS 端,这个方法大概每 5ms 回调一次
- (void)onRecordRawPcmData:(NSData *)data timeStamp:(unsigned long long)timeStamp sampleRate:(int)sampleRate channels:(int)channels withBgm:(BOOL)withBgm {
    if (data == nil) {
        return ;
    }

    // AUDIO_FREQUENCY 表示这个方法回调多少次才计算一次音量,iOS 端建议值为 40
    if (_audioCount == AUDIO_FREQUENCY) {
        _averagePower = 0;
        _peakPower = 0;
        _audioCount = 0;
    }

    long long pcmAllLenght = 0;

    short bufferByte[data.length/2];
    memcpy(bufferByte, data.bytes, data.length);

    // 将 buffer 内容取出,进行平方和运算
    for (int i = 0; i < data.length/2; i++) {
        pcmAllLenght += bufferByte[i] * bufferByte[i];
    }
    // 平方和除以数据总长度,得到音量大小。
    double mean = pcmAllLenght / (double)data.length;
    double volume =10 * log10(mean);

    // _averagePower 为音量平均值
    if (volume > 0) {
        _averagePower += volume;
        _audioCount++;
    }

    // _peakPower 为音量峰值
    if (volume > _peakPower) {
        _peakPower = volume;
    }

    if (_audioCount == AUDIO_FREQUENCY) {
        _averagePower /= _audioCount;
        NSLog(@"峰值:%f,平均值:%f", _peakPower, _averagePower);
    }
}

Android

private double mPeakVolume = 0.0;     // 最大音量值
private double mAverageVolume = 0.0;  // 平均音量值
private int count = 1;                  // 统计 Android 回调次数, 每 21ms 回调一次数据

/**
* 计算每个 buffer 的平均音量值
* 位宽按照 16bit 计算
* */
private double doublecalculateVolume(byte[] buffer){
    double sumVolume = 0.0;
    double avgVolume = 0.0;
    double volume = 0.0;
    for(int i = 0; i < buffer.length; i+=2){
        int v1 = buffer[i] & 0xFF;
        int v2 = buffer[i + 1] & 0xFF;
        int temp = v1 + (v2 << 8);  // 小端
        if (temp >= 0x8000) {
            temp = 0xffff - temp;
        }
        sumVolume += Math.abs(temp);
    }
    avgVolume = sumVolume / buffer.length / 2;
    volume = Math.log10(1 + avgVolume) * 10;
    return volume;
}


mLivePusher.setAudioProcessListener(new TXLivePusher.AudioCustomProcessListener() {
    @Override
    public void onRecordRawPcmData(byte[] data, long ts, int sampleRate, int channels, int bits, boolean withBgm) {

    }

    @Override
    public void onRecordPcmData(byte[] data, long ts, int sampleRate, int channels, int bits) {

        if (data == null) {
            return;
        }

        double tempVolume = doublecalculateVolume(data);
        if (tempVolume > 0){
            mAverageVolume += tempVolume;
            count ++;
        }

        if (tempVolume > mPeakVolume) {
            mPeakVolume = tempVolume;
        }

        if (count == 10) {
            mAverageVolume /= count;

            Log.i(TAG, "平均音量 = " + String.valueOf(mAverageVolume) + " | 峰值音量 = " + String.valueOf(mPeakVolume));

            mAverageVolume = 0.0;
            mPeakVolume = 0.0;
            count = 0;
        }

    }
});

计算原理

因为人耳的特性,我们对声音的大小感知呈对数关系,所以我们通常用分贝描述声音大小,分贝(decibel)是量度两个相同单位之数量比例的单位,主要用于度量声音强度,常用dB表示。

声学中,声音的强度定义为声压。计算分贝值时采用20微帕斯卡为参考值(通常被认为是人类的最少听觉响应值,大约是3米以外飞行的蚊子声音)。这一参考值是人类对声音能够感知的阈值下限。声压是场量,因此使用声压计算分贝时使用下述版本的公式:

其中的pref是标准参考声压值20微帕。

声音是一种波,PCM数据是波形的描述,音量值表示波的能量,与波的振幅和各点的相对差值有关。我们要计算音量时,先将PCM数据转换成 -1~1 之间,然后进行快速傅立叶变换(FFT),求出当时的频谱图,就是各个频率的音量大小,求平均就是总音量了。FFT有实部数据和虚部数据,其能量值是 (实部*实部+虚部*虚部) 的开方,而声音的大小是分贝,为 20*lg(能量值),所以频谱图各音量是 10*lg(实部*实部+虚部*虚部),计算时我们用 10*log10(能量)

参考文档:

http://blog.jianchihu.net/pcm-vol-control-advance.html

http://blog.jianchihu.net/pcm-volume-control.html

https://blog.csdn.net/Freeze_Z/article/details/44310245

http://www.myexception.org/multimedia/252889.html

results matching ""

    No results matching ""