从音频文件输入中检测人声

30

我正在尝试实现自动录音功能,类似于Talking Tom应用程序。 我使用以下代码从音频录制器中读取输入并分析缓冲区:

 float totalAbsValue = 0.0f;
 short sample = 0;

 numberOfReadBytes = audioRecorder.read( audioBuffer, 0, bufferSizeInBytes);

 // Analyze Sound.
 for( int i=0; i<bufferSizeInBytes; i+=2 )
 {
     sample = (short)( (audioBuffer[i]) | audioBuffer[i + 1] << 8 );
     totalAbsValue += Math.abs( sample ) / (numberOfReadBytes/2);
 }

 // Analyze temp buffer.
 tempFloatBuffer[tempIndex%3] = totalAbsValue;
 float temp = 0.0f; 

 for( int i=0; i<3; ++i )
 temp += tempFloatBuffer[i];

现在我能够检测来自音频录制器的语音输入,并分析音频缓冲区。

将缓冲区转换为浮点值,如果它增加了一定数量,则假定背景中有一些声音并开始录制。但问题是,这个应用程序开始记录所有背景噪音,包括风扇/空调管道声。

是否有人可以帮助我分析缓冲区以仅检测人类的语音?或者是否有其他替代方法从音频录制器输入中检测人类的语音?

提前致谢,


1
你知道人声与背景噪音之间的特征吗? - icedwater
@icedwater 没有主意,伙计。。 - Timson
9
时间依赖频率分析 + 一个神经网络应该就能解决问题。毕竟,这就是人类自然而然做的事情。 - John Dvorak
4
你看过这个问题吗?https://dev59.com/Z3A75IYBdhLWcg3w6Nr8 - znarf
@vkulla42尝试了语音识别。但是没有运气:( - Timson
6
“一个典型成年男性的语音基本频率为85到180 Hz,典型成年女性为165到255 Hz。”——如果你使用现有的方法,但首先通过带通滤波器处理(分别为男声和女声进行一次),那会怎么样?只要这些频段中没有太多噪音,那么这可能对您有效。 - Wayne Uroda
10个回答

11

声音检测并不简单。有几种算法,其中一些已经发布,例如GSM VAD。有几个开源的VAD库可用,其中一些讨论在这里


4

对于语音检测,请尝试使用ftt算法。

对于噪声问题,请尝试使用speex库。


4
如果您想要一份干净的录音,您可以:
  1. 使用FFT过滤语音中的噪声,并应用低通、高通和带通滤波器(使用FFT进行滤波)(滤波器)

2.过滤后,噪声会减少,您可以使用语音识别API(API)

过滤越多,噪声越少,识别效果越好,但在过滤时要小心,因为它也可能将语音与噪声一起去除。

还要了解更多关于FFT的知识

(人类声音的快速傅里叶变换)

希望这可以帮到您 :)


语音识别API链接无法使用。"抱歉,您请求的页面无法找到。" - Timson
@Timson 试一下这个:http://android-developers.blogspot.com/2010/03/speech-input-api-for-android.html - Albert Laure
请参考以下链接:http://developer.android.com/reference/android/speech/package-summary.html - Albert Laure
这是上面发布的链接: http://www.javacodegeeks.com/2012/08/android-voice-recognition-tutorial.html - Albert Laure

3
您具体想要什么?您只是想过滤音频中的人类语音,还是您真正想知道这个人说了什么?
几乎每个智能手机都通过在设备背面使用第二个麦克风记录背景噪声并减去两个信号来过滤人类语音。但是,老实说,我没有看到任何Android API可以直接访问这两个信号。
如果您想进行语音转文字转换,请查看Sphinx4和Praat。两者都可以完成此任务,但同样,我没有看到适用于Android的实现。 Sphinx4声称完全由Java编写,因此应该可以将其嵌入Android应用程序中。

1

你是否考虑过使用微软的语音识别API?你可以使用语音关键词来开始录制,就像《星际迷航》中在询问计算机之前说“电脑”一样。使用ISpRecognizer::CreateRecoContext来加载你的识别语法并开始识别。然后使用ISpPhrase实现一个检查,以确定是否应该开始录制。


1
你能解释一下如何在Android设备上安装它吗? - Henry

1
处理输入的方法是使用一个专门的库来去除噪音。例如,http://audacity.sourceforge.net 可以进行噪音去除。只要您已经对主要类型的噪声进行了表征,那么就只剩下语音了。在用户录制之前和录制结束后收集采样数据是值得的,因为这将提供环境中噪声的实时样本。如果每个用户都面临着独特的背景噪声挑战,这将非常有用。

6
Audacity不是一个Android库。 - null pointer
好的,你是说你想要的解决方案仅限于Android库,还是考虑将库作为项目的一部分进行移植? - Faisal Memon

1
在完全一般的情况下,这是一个未解决的问题。在实际意义上...
第一步是尽可能获得无噪音录音。正如其他人所指出的那样,这始于一个聚焦于您想要保留的声音的定向麦克风。
第二步是过滤。如先前所述,电话公司对人类语音理解实际需要哪些频率范围进行了大量研究。过滤掉超出该范围的频率将使声音听起来像... 好吧,就像电话... 但会更多地消除背景噪音。
如果您想走得更远,事情可能会变得非常复杂。有一些算法,如果您可以向它们展示您认为在该特定录音中的噪音样本,它们将分析并尝试去除它而不会太损坏您想要保留的声音。这不是简单的编程;如果我是您,我会认真考虑从已经正确完成它的人那里购买它,而不是尝试重新发明/重新实现它。我不知道它们中是否有任何适用于Android或Typical Android盒子是否具有足够的计算能力以在任何实时环境中执行它们。(我曾在工作室中使用SoundSoap消除空调噪音,效果非常好。)
事实上,我的倾向是简化问题为已解决的问题:使用最具方向性和最接近的麦克风,让Android进行录音...但后来使用现成的工具进行信号处理以清理它。但我承认我有偏见,因为我已经投资于后者。

1

我曾尝试在Windows上解决类似的问题。但我很快发现,仅使用快速傅里叶变换进行简单的频率分析是不够的。许多噪声会影响到人类的频率——从麦克风上的简单敲击声到拍手声。即使进行一定程度的高级过滤也无济于事。我发现最简单的方法是将噪声发送到云API并请求其转录语音。如果云API可以将其转录为合理长度的字符串,则我可以继续录制;否则,停止录制。这需要对一些噪声进行采样并将其发送到云服务提供商。


0

大多数人误解了问题,他们的回复解决的问题与你的不同。

你应该解析缓冲区中的音频,搜索人类声音范围内的频率。一旦检测到它们,就意味着有人开始说话,你可以开始录音(不要忘记包括缓冲区,因为它包含了演讲的第一部分)。

搜索打印音频原始流中频率列表的例程。


0
为了获得最佳效果,您可以使用Silero VAD,在repository中找到更多信息。
val vad = Vad.builder()
        .setContext(applicationContext)
        .setSampleRate(SampleRate.SAMPLE_RATE_8K)
        .setFrameSize(FrameSize.FRAME_SIZE_256)
        .setMode(Mode.NORMAL)
        .setSilenceDurationMs(300)
        .setSpeechDurationMs(50)
        .build()

    val isSpeech = vad.isSpeech(audioData)

    vad.setContinuousSpeechListener(audioData, object : VadListener {
        override fun onSpeechDetected() {
            //Speech detected!
        }

        override fun onNoiseDetected() {
            //Noise detected!
        }
    })

    vad.close()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接