ex

Fork of mbed-os-example-mbed5-blinky by mbed-os-examples

dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/wakeup/WakeUpDecodeThread.java

Committer:
TMBOY
Date:
2017-07-18
Revision:
45:2aa9f933c8d2

File content as of revision 45:2aa9f933c8d2:

/*
 * *
 * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.baidu.duer.dcs.androidsystemimpl.wakeup;

import android.os.Handler;

import com.baidu.duer.dcs.util.LogUtil;

import java.util.concurrent.LinkedBlockingDeque;

/**
 * 唤醒声音处理-唤醒消费者
 * <p>
 * Created by guxiuzhong@baidu.com on 2017/6/22.
 */
public class WakeUpDecodeThread extends Thread {
    private static final String TAG = WakeUpDecodeThread.class.getSimpleName();
    // 唤醒成功
    private static final int WAKEUP_SUCCEED = 1;
    // 唤醒词位置
    private int voiceOffset;
    private boolean isWakeUp;
    private WakeUpNative wakeUpNative;
    private Handler handler;
    private volatile boolean isStart = false;
    private LinkedBlockingDeque<byte[]> linkedBlockingDeque;

    public WakeUpDecodeThread(LinkedBlockingDeque<byte[]> linkedBlockingDeque,
                              WakeUpNative wakeUpNative,
                              Handler handler) {
        this.linkedBlockingDeque = linkedBlockingDeque;
        this.wakeUpNative = wakeUpNative;
        this.handler = handler;
    }

    /**
     * 开始唤醒
     */
    public void startWakeUp() {
        if (isStart) {
            return;
        }
        isStart = true;
        this.start();
    }

    public boolean isStart() {
        return isStart;
    }

    /**
     * 停止唤醒
     */
    public void stopWakeUp() {
        isStart = false;
    }

    @Override
    public void run() {
        super.run();
        LogUtil.i(TAG, "wakeup wakeUpDecode start" );
        while (isStart) {
            try {
                byte[] data = linkedBlockingDeque.take();

                // 暂时不检测vad
                // int volume = calculateVolume(data, 16);
                // LogUtil.i(TAG, "wakeup audioRecord Volume:" + volume);
                // if (volume <= 0) {
                //  continue;
                // }

                if (data.length > 0) {
                    // 是否为最后一帧数据
                    boolean isEnd = false;
                    short[] arr = byteArray2ShortArray(data, data.length / 2);
                    int ret = wakeUpNative.wakeUpDecode(
                            arr,
                            arr.length,
                            "",
                            1,
                            -1,
                            true,
                            voiceOffset++,
                            isEnd
                    );
                    // 唤醒成功
                    if (ret == WAKEUP_SUCCEED) {
                        LogUtil.i(TAG, "wakeup wakeUpDecode ret:" + ret);
                        isWakeUp = true;
                        stopWakeUp();
                        LogUtil.i(TAG, "wakeup wakeUpDecode succeed !!");
                        break;
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        LogUtil.i(TAG, "wakeup after wakeUpDecode over !!");
        LogUtil.i(TAG, "wakeup after linkedBlockingDeque size:" + linkedBlockingDeque.size());

        if (isWakeUp) {
            if (listener != null) {
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        listener.onWakeUpSucceed();
                    }
                });
            }
        }
        // 重置
        voiceOffset = 0;
        isWakeUp = false;
    }

    /**
     * 将byte数组转为short数组
     *
     * @param data  byte数组的音频数据
     * @param items short数组的大小
     * @return 转换后的short数组
     */
    private short[] byteArray2ShortArray(byte[] data, int items) {
        short[] retVal = new short[items];
        for (int i = 0; i < retVal.length; i++) {
            retVal[i] = (short) ((data[i * 2] & 0xff) | (data[i * 2 + 1] & 0xff) << 8);
        }
        return retVal;
    }

    /**
     * 根据输入的音量大小来判断用户是否有语音输入
     *
     * @param var0 原始音频数据
     * @param var1 音频数据格式位PCM,16位每个样本,比如如果音频数据格式设为AudioFormat.ENCODING_PCM_16BIT,则参数传16
     * @return >0 代表有音频输入
     */
    private int calculateVolume(byte[] var0, int var1) {
        int[] var3 = null;
        int var4 = var0.length;
        int var2;
        if (var1 == 8) {
            var3 = new int[var4];
            for (var2 = 0; var2 < var4; ++var2) {
                var3[var2] = var0[var2];
            }
        } else if (var1 == 16) {
            var3 = new int[var4 / 2];
            for (var2 = 0; var2 < var4 / 2; ++var2) {
                byte var5 = var0[var2 * 2];
                byte var6 = var0[var2 * 2 + 1];
                int var13;
                if (var5 < 0) {
                    var13 = var5 + 256;
                } else {
                    var13 = var5;
                }
                short var7 = (short) (var13 + 0);
                if (var6 < 0) {
                    var13 = var6 + 256;
                } else {
                    var13 = var6;
                }
                var3[var2] = (short) (var7 + (var13 << 8));
            }
        }
        int[] var8 = var3;
        if (var3 != null && var3.length != 0) {
            float var10 = 0.0F;
            for (int var11 = 0; var11 < var8.length; ++var11) {
                var10 += (float) (var8[var11] * var8[var11]);
            }
            var10 /= (float) var8.length;
            float var12 = 0.0F;
            for (var4 = 0; var4 < var8.length; ++var4) {
                var12 += (float) var8[var4];
            }
            var12 /= (float) var8.length;
            var4 = (int) (Math.pow(2.0D, (double) (var1 - 1)) - 1.0D);
            double var14 = Math.sqrt((double) (var10 - var12 * var12));
            int var9;
            if ((var9 = (int) (10.0D * Math.log10(var14 * 10.0D * Math.sqrt(2.0D) / (double) var4 + 1.0D))) < 0) {
                var9 = 0;
            }
            if (var9 > 10) {
                var9 = 10;
            }
            return var9;
        } else {
            return 0;
        }
    }

    private IWakeUpListener listener;

    public void setWakeUpListener(IWakeUpListener listener) {
        this.listener = listener;
    }

    /**
     * 唤醒成功回调接口
     */
    public interface IWakeUpListener {
        /**
         * 唤醒成功后回调
         */
        void onWakeUpSucceed();
    }
}