【问题标题】:How to Recognise when user START & STOP speaking in android? (Voice Recognition in Android)如何识别用户何时开始和停止在 android 中说话? (Android中的语音识别)
【发布时间】:2012-04-05 00:44:05
【问题描述】:

我已经进行了大量的研发并使用了很多资源来解决我的问题,但我未能找到任何合适的解决方案。

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

所需的功能是

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

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

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

我不想使用 Android 中默认提供的 Google 语音识别器,因为它需要 Internet,但我的应用程序离线运行。另外,我知道了 CMU-Sphinx。但这对我的要求没有帮助。

已编辑:- 另外,我想补充一点,我已经使用开始和停止按钮实现了这一点,但我不想使用这些按钮。

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

【问题讨论】:

  • 你找到解决方案了吗?
  • 检查这个link解决方案
  • 你找到解决办法了吗?

标签: android voice voice-recognition voice-recording


【解决方案1】:

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

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();


}

校验值函数:

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();
    }


}

我知道这个问题很老而且以前回答过,但是这个小代码 sn-p 可能对其他人有帮助。

【讨论】:

    【解决方案2】:

    最简单最常用的方法是在音频中count the number of zero crossings(即当符号由正变为负时)。

    如果该值太高,则声音不太可能是语音。如果它太低,那么再次,它不太可能是语音。

    将其与简单的能量级别(音频的响度)相结合,您就有了一个非常强大的解决方案。

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

    我强烈建议沿着零交叉线走,因为它易于实现并且在 99% 的时间里都能正常工作:)

    【讨论】:

    • 我很高兴能从像你这样的专业人士那里得到正确的答案....但我对这种声音识别了解不多..and much of the information i gave in my answer is from here..
    • @Raju:很公平...... TBH 进行特征建模非常复杂。我目前正在使用它来识别说话者(即识别给定的人说话)。它不是真的可以简单地进入的东西,唉:(我上面描述的过零方法确实非常简单并且效果很好。虽然我知道对一般语音进行建模并尝试将可能性与之匹配是一个更好的解决方案,但我会通常只需实现过零来识别说话者......它很容易实现并且效果很好,不值得担心太多:D
    • 嗯,我意识到我说的是“识别说话者”......我的意思是“识别某人正在说话”......
    • 是的...我明白那部分... :)
    • @Raju:必须澄清一下;)
    【解决方案3】:

    下面是我用于一个 iPhone 应用程序的代码,它完全做同样的事情。代码在 Objective-C++ 中,但我有很多 cmets。此代码在录制队列的回调函数中执行。我确信 Android 平台也存在类似的方法。

    这种方法在我使用过的几乎所有声学环境中都非常有效,并且在我们的应用程序中也使用了它。需要的话可以download it进行测试。

    尝试在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];});
                }
            }
        }
    

    最好的!

    【讨论】:

    • 我是否遗漏了什么,或者这本质上只是一个非常复杂的幅度检测器? (有更简单的方法可以在 iPhone 上获取电流幅度!)
    • @Goz 我很想告诉我更多关于它、代码、示例、文档的信息
    • AudioQueueGetProperty(mAqr, kAudioQueueProperty_CurrentLevelMeterDB, &aqlms, &size);
    【解决方案4】:

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

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

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


    但我想知道你所描述的关于你的应用程序行为的内容看起来你会像说话汤姆一样重新发明吧??? :-P

    【讨论】:

    • 感谢您的回复。但是对于语音识别,有没有可用的Listner?我想要像会说话的汤姆这样的语音功能......
    • 假设您有一个名为“StartRec()”的方法。您必须从 actionlister 声明中调用此方法,例如 'mainScreen.addListener(new ClickListner(){ startRec();});'我不确定您可以在 android 开发站点中找到的列表器详细信息。
    • 当用户开始说话时,不会说话,然后该动作就会触发它的耳朵。所以我的问题是,你怎么知道用户开始说话或停止说话?
    • @Prem 我感觉他们一直在记录和监控音量。当音量达到某个点时,它们会执行操作。据我所知,这并不是你想要完成的。据我所知,始终在后台收听用户语音命令将是一项非常昂贵的(电池、处理器)冒险。这可能就是为什么谷歌和苹果都还没有实现这种能力的原因。他们都使用按钮开始收听语音命令。
    • @MikeIsrael,感谢您的回复。但是,像会说话的汤姆这样的应用程序是如何制作的?它在Apple和Android中都可用吗?应该有一些我想念的东西......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-02
    • 1970-01-01
    • 1970-01-01
    • 2017-05-16
    • 1970-01-01
    • 2016-08-18
    • 1970-01-01
    相关资源
    最近更新 更多