前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android使用webrtc实现检测用户是否在说话

Android使用webrtc实现检测用户是否在说话

作者头像
夜雨飘零
发布2020-05-06 11:54:16
2.7K2
发布2020-05-06 11:54:16
举报
文章被收录于专栏:CSDN博客

原文博客:Doi技术团队 链接地址:https://blog.doiduoyi.com/authors/1584446358138 初心:记录优秀的Doi技术团队学习经历 本文链接:https://blog.doiduoyi.com/articles/2020/04/16/1587006578892.html

前言

我们在Android应用做语音识别的时候,一般是用户唤醒之后开始说话。当用户超过一定的时候没有说话,就停止录音,并把录音发送到语音识别服务器,获取语音识别结果。本教程就是解决如何检测用户是否停止说话,我们使用的是WebRTC架构的源代码中的vad代码实现的。 VAD算法全称是Voice Activity Detection,该算法的作用是检测是否是人的语音,使用范围极广,降噪,语音识别等领域都需要有vad检测。webrtc的vad检测原理是根据人声的频谱范围,把输入的频谱分成六个子带:80Hz——250Hz,250Hz——500Hz,500Hz——1K,1K——2K,2K——3K,3K——4K。分别计算这六个子带的能量。然后使用高斯模型的概率密度函数做运算,得出一个对数似然比函数。对数似然比分为全局和局部,全局是六个子带之加权之和,而局部是指每一个子带则是局部,所以语音判决会先判断子带,子带判断没有时会判断全局,只要有一个通过认为是语音。

创建Android项目

现在我们就来使用webrtc的vad源码开发检测是否有语音的Android项目。

首先我们创建一个Android项目,修改local.properties中的配置信息,添加NDK的路径,例如笔者的如下:

代码语言:javascript
复制
ndk.dir=D\:\\Android\\android-ndk-r15c
sdk.dir=D\:\\Android\\sdk

接着在app目录下创建CMakeLists.txt文件,并添加以下代码:

代码语言:javascript
复制
cmake_minimum_required(VERSION 3.4.1)

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -pedantic")

aux_source_directory(src/main/cpp/vad_src/ DIR_LIB_SRCS)

add_definitions(-DWEBRTC_POSIX)
add_definitions(-DWEBRTC_ANDROID)

add_library( native-lib
             SHARED
             src/main/cpp/native-lib.cpp
             ${DIR_LIB_SRCS})

include_directories(src/main/cpp/vad_src/)

find_library( log-lib
              log )

target_link_libraries( native-lib
                       ${log-lib} )

然后修改app目录下的build.gradle文件,修改如下:

代码语言:javascript
复制
# 在defaultConfig添加
externalNativeBuild {
    cmake {
        arguments = ['-DANDROID_STL=c++_static']
        cppFlags ""
    }
}
# 在android下添加
buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
        }
    }

使用webrtc

接下来就开始克隆webrtc源码

代码语言:javascript
复制
git clone https://android.googlesource.com/platform/external/webrtc

我们所需的源码主要存放webrtc/webrtc/common_audio/vad目录中,我们把里面的源码文件都复制到我们的Android项目main/cpp/vad_src目录下,主要: 有很多的依赖代码并不在这个目录中,我们需要更加每个文件的导入库查看依赖库所在的位置,并吧他们都复制到main/cpp/vad_src目录下。在鼻子提供的源码中,已经提取好了,可以下载:

main/cpp目录下创建native-lib.cpp文件,为Java调用vad提供接口,代码如下:

代码语言:javascript
复制
#include <jni.h>
#include <string>
#include <malloc.h>
#include "vad_src/webrtc_vad.h"
#include "vad_src/vad_core.h"



extern "C"
JNIEXPORT jboolean JNICALL
Java_com_yeyupiaoling_testvad_MainActivity_webRtcVad_1Process(JNIEnv *env, jobject instance,
                                                                 jshortArray audioData_,
                                                                 jint offsetInshort,
                                                                 jint readSize) {

    VadInst *handle = WebRtcVad_Create();
    WebRtcVad_Init(handle);
    WebRtcVad_set_mode(handle, 2);
    int index = readSize / 160;
    jshort *pcm_data = env->GetShortArrayElements(audioData_, JNI_FALSE);
    bool b = JNI_FALSE;
    for (int i = 0; i < index; ++i) {
        int vad = WebRtcVad_Process(handle, 16000, pcm_data + offsetInshort + i * 160, 160);
        if (vad == 1) {
            b = JNI_TRUE;
        } else{
            b=JNI_FALSE;
        }
    }
    env->ReleaseShortArrayElements(audioData_, pcm_data, JNI_ABORT);
    WebRtcVad_Free(handle);
    return static_cast<jboolean>(b);
}

其对应的Java方法如下:

代码语言:javascript
复制
public native boolean webRtcVad_Process(short[] audioData, int offsetInshort, int readSize);

最后在我们的Android这样子调用,可以检测到用户是否在说话。

代码语言:javascript
复制
int mMinBufferSize = AudioRecord.getMinBufferSize(16000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
AudioRecord mRecorder = new AudioRecord(MediaRecorder.AudioSource.MIC, 16000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, mMinBufferSize * 2);

mMinBufferSize = 320;
short[] audioData = new short[mMinBufferSize];
if (mRecorder.getState() != AudioRecord.STATE_INITIALIZED) {
    stopRecord();
    return;
}
mRecorder.startRecording();

while (mIsRecording) {
    if (null != mRecorder) {
        readSize = mRecorder.read(audioData, 0, mMinBufferSize);

        if (readSize == AudioRecord.ERROR_INVALID_OPERATION || readSize == AudioRecord.ERROR_BAD_VALUE) {
            continue;
        }
        if (readSize != 0 && readSize != -1) {
            // 语音活动检测
            mSpeaking = webRtcVad_Process(audioData, 0, readSize);
            if (mSpeaking) {
                Log.d(TAG, ">>>>>正在讲话");
            } else {
                Log.d(TAG, "=====当前无声音");
            }
        } else {
            break;
        }
    }
}

最后别忘了添加录音权限RECORD_AUDIO,如果是Android 6.0以上的,还需要动态申请权限。

代码语言:javascript
复制
if (!hasPermission()){
    requestPermission();
}

// check had permission
private boolean hasPermission() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        return checkSelfPermission(Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED;
    } else {
        return true;
    }
}

// request permission
private void requestPermission() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        requestPermissions(new String[]{Manifest.permission.RECORD_AUDIO}, 1);
    }
}
效果图
效果图

本项目下载地址:https://resource.doiduoyi.com/#qoe3sse

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/04/16 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 创建Android项目
  • 使用webrtc
相关产品与服务
语音识别
腾讯云语音识别(Automatic Speech Recognition,ASR)是将语音转化成文字的PaaS产品,为企业提供精准而极具性价比的识别服务。被微信、王者荣耀、腾讯视频等大量业务使用,适用于录音质检、会议实时转写、语音输入法等多个场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档