如何识别用户何时启动&;停止用android说话?(Android中的语音识别)
我做了大量的研发工作,花了大量的资源来解决我的问题,但我没有得到任何合适的解决方案 我已经开发了一个应用程序,现在我想添加基于语音的功能 所需功能包括 1) 当用户开始讲话时,应录制音频/视频并 2) 用户停止讲话时,应播放录制的音频/视频 注意:这里的视频指的是用户在此期间在应用程序内执行的任何操作。例如,单击按钮或某种动画等 我不想使用Android系统默认提供的谷歌语音识别器,因为它需要互联网,但我的应用程序是离线运行的。另外,我知道了。但按照我的要求,这是没有帮助的 编辑:- 另外,我想补充一点,我已经使用开始和停止按钮实现了这一点,但我不想使用这些按钮如何识别用户何时启动&;停止用android说话?(Android中的语音识别),android,voice,voice-recognition,voice-recording,Android,Voice,Voice Recognition,Voice Recording,我做了大量的研发工作,花了大量的资源来解决我的问题,但我没有得到任何合适的解决方案 我已经开发了一个应用程序,现在我想添加基于语音的功能 所需功能包括 1) 当用户开始讲话时,应录制音频/视频并 2) 用户停止讲话时,应播放录制的音频/视频 注意:这里的视频指的是用户在此期间在应用程序内执行的任何操作。例如,单击按钮或某种动画等 我不想使用Android系统默认提供的谷歌语音识别器,因为它需要互联网,但我的应用程序是离线运行的。另外,我知道了。但按照我的要求,这是没有帮助的 编辑:- 另外,我想
如果有人有任何想法或建议,请告诉我。您可以尝试向应用程序事件添加侦听器,如导航、单击动画等。。。 在侦听器实现中,您可以触发启动/停止功能 看看这些例子。。。这可能对你有帮助
但我想知道你对你的应用程序行为的描述看起来像是你要重新创造一个像谈论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];});
}
}
}
//如果录制队列的音频缓冲区中有一些音频样本
如果(inNumPackets>0){
//以下4行代码是计算
//当前音频采样的平均功率。
//转到[此处][2]查看有关它们的文档。
vDSP_vflt16((SInt16*)在缓冲区->mAudioData,1,aqr->当前帧采样阵列,1,在多个数据包中);
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保存当前音频样本的能量
aqr->instantPower/=(CGFloat)inumpackets;
//S.O.S.避免+-infs,NAN向InstantPower添加一个小数字
aqr->instantPower=log10f(aqr->instantPower+0.001f);
//InstantAvgPower为更大的窗口提供能量
//时间比瞬间的力量更重要
aqr->instantAvgPower=aqr->instantAvgPower*0.95f+0.05f*aqr->instantAvgPower;
//AvgPower拥有更大窗口的能量
//时间比瞬时功率大
aqr->avgPower=aqr->avgPower*0.97f+0.03f*aqr->instantAvgPower;
//这是告诉我们何时记录的比率
CGFloat ratio=aqr->avgPower/aqr->instantPower;
//如果我们尚未写入音频文件
//比率大于特定的硬编码值
//(该值与麦克风的质量有关
//我已经将iPhone设置为1.5),然后开始写!
如果(!aqr->writeToFile&&ratio>aqr->recordingThreshold){
aqr->writeToFile=是;
}
if(aqr->writeToFile){
//将数据包写入文件
XThrowIfError(音频文件写入包(aqr->mRecordFile,FALSE,inBuffer->mAudioDataByteSize,
输入packetdesc,aqr->mRecordPacket,以及输入umpackets,inBuffer->mAudioData),
“AudioFileWritePackages失败”);
aqr->mRecordPacket+=inNumPackets;
//现在,如果我们正在录制,但瞬时VG功率较低
//然后我们增加countToStopRecording计数器
如果(aqr->instantAvgPoweravgPower){
aqr->countToStopRecording++;
}
//或者将其设置为0。
否则{
aqr->countToStopRecording=0;
}
//如果我们检测到连续30分钟内没有足够的功率
//音频采样缓冲区或我们录制了太多音频
//(用户讲话时间超过阈值)停止录制
如果(aqr->countToStopRecording>30 | | aqr->mRecordPacket>kMaxAudioPacketsDuration){
aqr->countToStopRecording=0;
aqr->writeToFile=否;
//通知音频播放器我们已完成录制
//开始播放音频!!!
dispatch_async(dispatch_get_main_queue(),^{[[NSNotificationCenter defaultCenter]postNotificationName:@“RecordingedPlayNow”对象:nil];});
}
}
}
最好的 最简单和最常用的方法是在音频中输入信号(即符号从正变为负) 如果该值太高,则声音不太可能是语音。如果它太低,那么,同样,它不太可能是言语 再加上一个简单的能量级别(音频有多大),你就有了一个非常健壮的解决方案 如果你需要一个更精确的系统,那么它会变得更复杂。一种方法是提取音频特征(例如
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();
}
}