/* * Copyright (C) 2013 gujicheng * * Licensed under the GPL License Version 2.0; * you may not use this file except in compliance with the License. * * If you have any question, please contact me. * ************************************************************************* ** Author information ** ************************************************************************* ** Email: gujicheng197@126.com ** ** QQ : 29600731 ** ** Weibo: http://weibo.com/gujicheng197 ** ************************************************************************* */ package com.libra.sinvoice; import com.libra.sinvoice.Buffer.BufferData; public class VoiceRecognition { private final static String TAG = "Recognition"; private final static int STATE_START = 1; private final static int STATE_STOP = 2; private final static int STEP1 = 1; private final static int STEP2 = 2; private final static int INDEX[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6, -1, -1, -1, -1, 5, -1, -1, -1, 4, -1, -1, 3, -1, -1, 2, -1, -1, 1, -1, -1, 0 }; private final static int MAX_SAMPLING_POINT_COUNT = 31; private final static int MIN_REG_CIRCLE_COUNT = 10; private int mState; private Listener mListener; private Callback mCallback; private int mSamplingPointCount = 0; private int mSampleRate; private int mChannel; private int mBits; private boolean mIsStartCounting = false; private int mStep; private boolean mIsBeginning = false; private boolean mStartingDet = false; private int mStartingDetCount; private int mRegValue; private int mRegIndex; private int mRegCount; private int mPreRegCircle; private boolean mIsRegStart = false; public static interface Listener { void onStartRecognition(); void onRecognition(int index); void onStopRecognition(); } public static interface Callback { BufferData getRecognitionBuffer(); void freeRecognitionBuffer(BufferData buffer); } public VoiceRecognition(Callback callback, int SampleRate, int channel, int bits) { mState = STATE_STOP; mCallback = callback; mSampleRate = SampleRate; mChannel = channel; mBits = bits; } public void setListener(Listener listener) { mListener = listener; } public void start() { if (STATE_STOP == mState) { if (null != mCallback) { mState = STATE_START; mSamplingPointCount = 0; mIsStartCounting = false; mStep = STEP1; mIsBeginning = false; mStartingDet = false; mStartingDetCount = 0; mPreRegCircle = -1; if (null != mListener) { mListener.onStartRecognition(); } while (STATE_START == mState) { BufferData data = mCallback.getRecognitionBuffer(); if (null != data) { if (null != data.mData) { process(data); mCallback.freeRecognitionBuffer(data); } else { LogHelper.d(TAG, "end input buffer, so stop"); break; } } else { LogHelper.e(TAG, "get null recognition buffer"); break; } } mState = STATE_STOP; if (null != mListener) { mListener.onStopRecognition(); } } } } public void stop() { if (STATE_START == mState) { mState = STATE_STOP; } } private void process(BufferData data) { int size = data.getFilledSize() - 1; short sh = 0; for (int i = 0; i < size; i++) { short sh1 = data.mData[i]; sh1 &= 0xff; short sh2 = data.mData[++i]; sh2 <<= 8; sh = (short) ((sh1) | (sh2)); if (!mIsStartCounting) { if (STEP1 == mStep) { if (sh < 0) { mStep = STEP2; } } else if (STEP2 == mStep) { if (sh > 0) { mIsStartCounting = true; mSamplingPointCount = 0; mStep = STEP1; } } } else { ++mSamplingPointCount; if (STEP1 == mStep) { if (sh < 0) { mStep = STEP2; } } else if (STEP2 == mStep) { if (sh > 0) { // preprocess the circle int samplingPointCount = preReg(mSamplingPointCount); // recognise voice reg(samplingPointCount); mSamplingPointCount = 0; mStep = STEP1; } } } } } private int preReg(int samplingPointCount) { switch (samplingPointCount) { case 8: case 9: case 10: case 11: case 12: samplingPointCount = 10; break; case 13: case 14: case 15: case 16: case 17: samplingPointCount = 15; break; case 18: case 19: case 20: samplingPointCount = 19; break; case 21: case 22: case 23: samplingPointCount = 22; break; case 24: case 25: case 26: samplingPointCount = 25; break; case 27: case 28: case 29: samplingPointCount = 28; break; case 30: case 31: case 32: samplingPointCount = 31; break; default: samplingPointCount = 0; break; } return samplingPointCount; } private void reg(int samplingPointCount) { if (!mIsBeginning) { if (!mStartingDet) { if (MAX_SAMPLING_POINT_COUNT == samplingPointCount) { mStartingDet = true; mStartingDetCount = 0; } } else { if (MAX_SAMPLING_POINT_COUNT == samplingPointCount) { ++mStartingDetCount; if (mStartingDetCount >= MIN_REG_CIRCLE_COUNT) { mIsBeginning = true; mIsRegStart = false; mRegCount = 0; } } else { mStartingDet = false; } } } else { if (!mIsRegStart) { if (samplingPointCount > 0) { mRegValue = samplingPointCount; mRegIndex = INDEX[samplingPointCount]; mIsRegStart = true; mRegCount = 1; } } else { if (samplingPointCount == mRegValue) { ++mRegCount; if (mRegCount >= MIN_REG_CIRCLE_COUNT) { // ok if (mRegValue != mPreRegCircle) { if (null != mListener) { mListener.onRecognition(mRegIndex); } mPreRegCircle = mRegValue; } mIsRegStart = false; } } else { mIsRegStart = false; } } } } }