如何识别用户何时开始和停止在Android中说话?(安卓中的语音识别)



我做了很多R&D花了很多资源来解决我的问题,但我没能找到任何合适的解决方案。

我已经开发了一个应用程序,现在我想向它添加基于语音的功能

所需的功能是

1) 当用户开始讲话时,它应该记录音频/视频

2) 当用户停止讲话时,它应该播放录制的音频/视频

注意:这里的视频指的是用户在此期间在应用程序中执行的任何操作。例如,点击按钮或某种动画等。

我不想使用谷歌的语音识别器,因为它需要互联网,但我的应用程序离线运行。此外,我还了解了CMU狮身人面像。但根据我的要求,这是没有帮助的。

编辑:-此外,我想补充一点,我已经使用Start&停止按钮,但我不想用这些按钮。

如果有人有任何想法或建议,请告诉我。

最简单、最常见的方法是计算音频中的过零次数(即符号从正变为负时)。

如果这个值太高,那么声音就不太可能是语音。如果它太低,那么,再次强调,它不太可能是言语。

再加上一个简单的能量水平(音频的音量),你就有了一个非常强大的解决方案。

如果你需要一个更精确的系统,那么它就会变得更加复杂。一种方法是从"训练数据"中提取音频特征(例如MFCC),用类似GMM的东西对它们进行建模,然后对照GMM测试从实时音频中提取的特征。通过这种方式,您可以对给定音频帧是语音而非非语音的可能性进行建模。然而,这不是一个简单的过程。

我强烈建议走零交叉线,因为它实现简单,99%的时间都很好:)

您可以尝试将侦听器添加到应用程序事件中,如导航、单击动画等。。。在监听器实现中,您可以触发启动/停止功能。。。

http://tseng-blog.nge-web.net/blog/2009/02/14/implementing-listeners-in-your-android-java-application/

看看这些例子。。。这可能对你有帮助。。。。


但我想知道,你对你的应用程序行为的描述看起来像是你要像会说话的tom??:-P

下面是我用于iPhone应用程序的代码,该应用程序执行完全相同的操作。这段代码在Objective-C++中,但我在其中有很多注释。这段代码是在录制队列的回调函数中执行的。我确信Android平台也存在类似的方法。

这种方法在我使用过的几乎每一个声学环境中都非常有效,它也在我们的应用程序中使用。如果你愿意,你可以下载它进行测试。

尝试在android平台上实现它,你就完成了!

// If there are some audio samples in the audio buffer of the recording queue
if (inNumPackets > 0) {
        // The following 4 lines of code are vector functions that compute 
        // the average power of the current audio samples. 
        // Go [here][2] to view documentation about them. 
        vDSP_vflt16((SInt16*)inBuffer->mAudioData, 1, aqr->currentFrameSamplesArray, 1, inNumPackets);
        vDSP_vabs(aqr->currentFrameSamplesArray, 1, aqr->currentFrameSamplesArray, 1, inNumPackets);
        vDSP_vsmul(aqr->currentFrameSamplesArray, 1, &aqr->divider, aqr->currentFrameSamplesArray, 1, inNumPackets);
        vDSP_sve(aqr->currentFrameSamplesArray, 1, &aqr->instantPower, inNumPackets);
        // InstantPower holds the energy for the current audio samples
        aqr->instantPower /= (CGFloat)inNumPackets;
        // S.O.S. Avoid +-infs, NaNs add a small number to InstantPower
        aqr->instantPower = log10f(aqr->instantPower + 0.001f);
        // InstantAvgPower holds the energy for a bigger window 
        // of time than InstantPower
        aqr->instantAvgPower = aqr->instantAvgPower * 0.95f + 0.05f * aqr->instantPower;
        // AvgPower holds the energy for an even bigger window 
        // of time than InstantAvgPower
        aqr->avgPower = aqr->avgPower * 0.97f + 0.03f * aqr->instantAvgPower;
        // This is the ratio that tells us when to record
        CGFloat ratio = aqr->avgPower / aqr->instantPower;
        // If we are not already writing to an audio file and 
        // the ratio is bigger than a specific hardcoded value 
        // (this value has to do with the quality of the microphone 
        // of the device. I have set it to 1.5 for an iPhone) then start writing!
        if (!aqr->writeToFile && ratio > aqr->recordingThreshold) {
            aqr->writeToFile = YES;
        } 
        if (aqr->writeToFile) {
            // write packets to file
            XThrowIfError(AudioFileWritePackets(aqr->mRecordFile, FALSE, inBuffer->mAudioDataByteSize,
                                                inPacketDesc, aqr->mRecordPacket, &inNumPackets, inBuffer->mAudioData),
                          "AudioFileWritePackets failed");
            aqr->mRecordPacket += inNumPackets;
            // Now if we are recording but the instantAvgPower is lower 
            // than avgPower then we increase the countToStopRecording counter
            if (aqr->instantAvgPower < aqr->avgPower) {
                aqr->countToStopRecording++;
            } 
            // or else set him to 0.
            else {
                aqr->countToStopRecording = 0;
            }
            // If we have detected that there is not enough power in 30 consecutive
            // audio sample buffers OR we have recorded TOO much audio 
            // (the user speaks for more than a threshold of time) stop recording 
            if (aqr->countToStopRecording > 30 || aqr->mRecordPacket > kMaxAudioPacketsDuration) {
                aqr->countToStopRecording = 0;
                aqr->writeToFile = NO;
                // Notify the audio player that we finished recording 
                // and start playing the audio!!!
                dispatch_async(dispatch_get_main_queue(), ^{[[NSNotificationCenter defaultCenter] postNotificationName:@"RecordingEndedPlayNow" object:nil];});
            }
        }
    }

最好!

以下是检测用户停止说话的简单代码。我正在检查低于值的

recorder.getMaxAmplitude();

示例代码:

public void startRecording() throws IOException {
    Thread thread = new Thread() {
        @Override
        public void run() {
            int i = 0;
            while (i == 0) {
                try {
                    sleep(100);
                    if (recorder != null) {
                        checkValue(recorder.getMaxAmplitude());
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    };
    thread.start();

}

checkValue函数:

public void checkValue(int amplitude) {

    try{
        if (amplitude > 1000) {
            Log.d("I", "Amplitude : " + amplitude);
            amplitude = recorder.getMaxAmplitude();
            Thread.sleep(2000);
            isListened=true;
        }else if(isListened) {
            Log.d("I","Stop me");
            recordingDialog.dismiss();
        }
    }catch (Exception e){
        e.printStackTrace();
    }

}

我知道这个问题很老,以前也回答过,但这个小代码片段可能会帮助其他人。

最新更新