<span style="font-size:32px;">public class SpeechMarker extends BaseDataProcessor
经过本类处理后的数据流中含数的为:SPEECH_START信号, SPEECH_END信号, DoubleData(包含语音和非语音),DataStartSignal信号和DataEndSignal信号。属于语音的DoubleData位于SPEECH_START信号和 SPEECH_END信号之间。
把SPEECH_START和SPEECH_END信号插入从前一个数据处理器得到的数据流中,从中我们可以得到什么时候是utterance的开始,什么时候是utterance的结束。在SPEECH_START和SPEECH_END信号之间的是utterance的开始到utterance的结束时间,这正是我们所要真正识别的部分。
把在SpeechClassifier中得到的被标记为语音和非语音SpeechClassifiedData对象流,规划出其中被认为是语音的区域。这是通过插入SPEECH_START和SPEECH_END信号入流中来实现。
插入两信号的算法如下:
这个算法经常处于两种状态中的一种状态中,两种状态为:’in-speech’和’out-of-speech’.如果处于’out-of-speech’,它将会读取音频数据直到读取的音频数据为语音为止。如果我们读到了多个’startspeech’在连续语音中,我们认为语音已经开始了,插入一个SPEECH_START在语音首次开始前的’speechLeader’时刻。算法的状态转换到’in-speech’。
现在让我们当算法在’in-speech’状态的情况。如果它读到的一个音频(doubledata)是语音,它被调度来输出。如果音频是非语音,一直读取到’endSilence’在连续非语音中。在这一点上我们认为语音已经结束了。一个’SPEECH_END’信号被插入在首次的非语音音频后的’speechTrailer’时刻。算法返回到’out-of-speech’状态。如果在中间有任何语音音频被碰到,重新开始所有的估计(解释)状态。
当被延迟处理的语音音频低于最小的数量。这将有助于分割用可见的延迟低速语音和高速语音,当延迟是最小时。
本类的属性:</span>
<span style="font-size:32px;">@S4Integer(defaultValue = 200)
public static final String PROP_START_SPEECH = "startSpeech";被任为是utterance开始的最小的语言时间总数(即最少多少连续帧语音)。以ms(毫秒)为单位,默认为200ms。即语音时间多少毫秒可以认为是utterance的开始。
private int startSpeechTime;与上相同的意思。
@S4Integer(defaultValue = 500)
public static final String PROP_END_SILENCE = "endSilence";被认为是utterance结束的静音的时间总数(最少多少连续帧非语音)。即静音多少毫秒,可以认为是utterance的结束。以毫秒为单位。
private int endSilenceTime;与一个PROP_END_SILENCE有着相同的意思。
@S4Integer(defaultValue = 50)
public static final String PROP_SPEECH_LEADER = "speechLeader"; startSpeech前的可有的非语音的数量 。默认为50
private int speechLeader;与PROP_SPEECH_LEADER在意思上一样。
@S4Integer(defaultValue = 30)
public static final String PROP_SPEECH_LEADER_FRAMES = "speechLeaderFrames";要想插入speechstartsignal信号,在缓存中最少需有的音频帧数。默认为30.
private int speechLeaderFrames;与PROP_SPEECH_LEADER_FRAMES一样。
@S4Integer(defaultValue = 50)
public static final String PROP_SPEECH_TRAILER = "speechTrailer";语音结束后,可认为最大可能的非语音的总时间。默认为50ms
private int speechTrailer;与PROP_SPEECH_TRAILER一样。
@S4Double(defaultValue = 15.0)
public static final String PROP_END_SILENCE_DECAY = "endSilenceDecay";本属性减少了独到语音后的结束静音,这允许标记器用小的停顿来自适应快的语音。默认为15.0. 用在countSpeechFrame()方法中。来调整endSilence值。
private double endSilenceDecay;与PROP_END_SILENCE_DECAY一样。
private List<Data> outputQueue; // Audio objects are added to the end输出列表。
private boolean inSpeech;是否在语音中
private int frameCount;帧数
private int initialEndSilenceTime;</span>
<span style="font-size:32px;">本类的构造方法:
public SpeechMarker();空的构造方法。仅用于构建对象,不会对任何属性进行初始化。
public SpeechMarker(int startSpeechTime, int endSilenceTime, int speechLeader, int speechLeaderFrames, int speechTrailer, double endSilenceDecay);非空构造方法。初始化了相应的属性。
本类的方法:
public void newProperties(PropertySheet ps);只对属性进行操作,其操作与构造方法一样。用于在后的对象,后改变属性值。
public void initialize();初始化SpeechMarker设置了前处理器,inSpeech = false;
frameCount = 0;this.outputQueue = new ArrayList<Data>();,
private void reset();重置SpeechMarker(语音标记器)到初始状态。inSpeech = false;frameCount = 0;this.outputQueue = new ArrayList<Data>();
private Data readData();从获得前一处理的输出。即获得SpeechClassifiedData数据(分类后的数据)。
private void sendToQueue(Data audio);把获得的SpeechClassifiedData数据添加入outputQueue列表中。
public int getAudioTime(SpeechClassifiedData audio);获得一个SpeechClassifiedData存储的采样数的相应时间,即获得存储的这些采样数所需的时间,也为采样时间。音频时间,以毫秒为单位。
private boolean handleFirstSpeech(SpeechClassifiedData audio);需要考虑的情况如下:以开始读入的SpeechClassifiedData为语音为前提,
1,开始读入的SpeechClassifiedData所包含的音频时间小于可以认为是utterance开始的连续语音的情况:
A,接下来的全部为连续语音的情况。
B,接下来的不都是连续语音的情况:即有非语音的情况。
C,接下来没有足够的音频的情况。即没有startSpeechTime- speechTime时间的音频。
本方法的目的是看输入的语音SpeechClassifiedData,及其后连续的可以认为是语音开始的时间内的SpeechClassifiedData是否都为语音,都为则返回为真,否则返回为false,并把读取的所有SpeechClassifiedData都放入本类的输出列表中。首先输入的SpeechClassifiedData为语音,并获得其语音的时间。和确定的认为是utterance开始的时间比较,如果小于则继续从输入读取SpeechClassifiedData,并检它,为null就返回,否则得话,放入输出列表中,并判断其是否是语音,不是的话返回,是的话语音时间加此SpeechClassifiedData的语音时间。循环以上处理过程,直到连续语音时间等于设定的开始语音时间。将返回为真。
private void addSpeechStart();本方法的目的是添加SPEECH_START信号,需要考虑的情况如下:以检测到了utterance开始为前提:采用回溯的方法。
1, 可以认为是utterance开始的前startSpeechTime后的时间段中包含的情况:
A, 包含DataStartSignal信号的情况,
B, 包含SpeechEndSignal的情况,
C, 包含speechLeader个非语音的情况。
D, 包含语音的情况。
SPEECH_START信号插入在DataStartSignal或SpeechEndSignal或最终回溯到的那个SpeechClassifiedData数据的前面。为了把SPEECH_START加入到outputQueue输出列表中,从当前位置开始回溯。根据设置的speechLeader和startSpeechTime来决定回溯。用在回溯期间的非语音的总时长和speechLeader比较,用。用在回溯期间的语音的总时长和startSpeechTime比较。addSpeechStart()方法是在获得可认为是utterance开始的连续的语音后调用的。speechLeader为可以认为是utterance开始的连续语音段前可的非语音时间段。需要考虑的情况有:</span>
<span style="font-size:32px;">private boolean readEndFrames(SpeechClassifiedData audio);主要用来插入SpeechEndSignal信号。对于一个非语音中我们试图都更多的非语音帧,直到我们可以认为utterance结束为止。输入audio为非语音帧,如果语音真正结束返回为真,否则为false。返回为真的话,会在输出列表相应的地方插入SpeechEndSignal信号。如果读取了endsignaltime的话,还会往下读取最大的可能读取为speechtrailer。需考虑的情况有:
1, 输入的非语音后有连续endsignaltime-1的非语音的情况;
A, 在随后有连续的speechtrailer非语音的情况,
B, 在随后没有连续的speechtrailer非语音的情况
a,其中有语音帧的情况。
B,有dataendsignal信号的情况。
2, 输入的非语音后没有连续endsignaltime-1的非语音的情况;
A, 有dataendsignal信号的情况
B, 其中有语音帧的情况</span>
<span style="font-size:32px;">public boolean inSpeech();返回是否在语音中的布尔值。
public Data getData();返回Data对象,如果在outputQueue输出列表中没有数据则返回为null。本方法分两步处理:
1从前一处理器的读取数据,进行处理(加入SPEECH_END信号和SPEECH_START信号入音频信号流中),并把处理后的数据存入outputQueue输出列表中。
2,从outputQueue输出列表中读取数据输出,(一般是到下一处理器)。
对于第一步,的处理情况为:以outputQueue输出列表的长度小于speechLeaderFrames(缓存列表中所能存储的最大帧数)为前提,
1, 输入不为null的情况(即从前一处理器得到的数据不为null);
A, 不在语音中的情况;即utterance没有开始的情况,
a,得到的data为SpeechClassifiedData的情况
b, 得到的data为DataStartSignal的情况
B, 在语音中的情况,即utterance已经开始的情况,
a,得到的data为SpeechClassifiedData的情况
b, 得到的data为DataStartSignal的情况
c, 得到的data为DataEndSignal的情况
2,输入为null的情况。
对于第二步就是从列表中读取数据,当读到的是SpeechClassifiedData时,取其中doubledata输出。即其doubledata属性。
private void startCountingFrames();把frameCount = 0;
endSilenceTime = initialEndSilenceTime;
private void countSpeechFrame();作用计算语音帧总数,主要是调整了多少个连续非语音中可认为utterance结束的值,private void countSpeechFrame() {
frameCount++;
int minTime = speechLeader + speechTrailer;
endSilenceTime = (int) (initialEndSilenceTime -
((float)initialEndSilenceTime - minTime) / endSilenceDecay *
(frameCount / 100.0));
if (endSilenceTime <= minTime)
endSilenceTime = minTime;
}
</span>