当前位置: 首页 > news >正文

做ppt的模板的网站做好的网站怎么发布

做ppt的模板的网站,做好的网站怎么发布,网页设计与制作的岗位职责,如何建设好一个网站导航app引导中经常遇到破音,这里也将之前经历过的方案收集以下,方便以后选择: 1 对于开始和结尾破音: 可以用升降音来处理 两种方式 一种是 直接对开始和结束的时间段进行音量直接渐进改变。这里配的是200ms的渐变。 VolumeSha…

导航app引导中经常遇到破音,这里也将之前经历过的方案收集以下,方便以后选择:

1 对于开始和结尾破音: 可以用升降音来处理


  两种方式

  一种是 直接对开始和结束的时间段进行音量直接渐进改变。这里配的是200ms的渐变。
  VolumeShaper.Configuration cfg_out= null;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            cfg_out = new VolumeShaper.Configuration.Builder()
                    .setCurve(new float[]{0f,1f},new float[]{1f,0f})
                    .setInterpolatorType(VolumeShaper.Configuration.INTERPOLATOR_TYPE_LINEAR)
                    .setDuration(200)
                    .build();
            VolumeShaper vShaper = mAudioTrack.createVolumeShaper(cfg_out);
            vShaper.apply(VolumeShaper.Operation.PLAY);
        }

  一种是 开始的那帧数据进行音量从零渐进增加到当前音量,结束的那几帧数据进行音量从当前音量降到零
      /**
     * 对音频数据做 fade out
     * @param byteBuffer byteBuffer
     * @param channelCount channelCount
     */
    private ByteBuffer shortFadeOut(ByteBuffer byteBuffer, int channelCount) {
        int shortCount = byteBuffer.limit() / 2;
        if(1 == channelCount) {
            for(int i = 0; i < shortCount; i++) {
                short data = (short) (byteBuffer.getShort(i * 2) * 1.0f * (shortCount - i) / (2*shortCount));
                byteBuffer.putShort(i * 2, data);
            }
        } else {
            for(int i = 0; i < shortCount; i += 2) {
                short data = (short) (byteBuffer.getShort(i * 2) * 1.0f * (shortCount - i) / (2*shortCount));
                byteBuffer.putShort(i * 2, data);
                data = (short)(byteBuffer.getShort((i + 1) * 2) * 1.0f * (shortCount - i) / (2*shortCount));
                byteBuffer.putShort((i + 1) * 2, data);
            }
        }
        byteBuffer.rewind();
        return byteBuffer;
    }

2 适用于自己的tts引擎


  tts放入app进程会受当前app的业务影响,导致tts 不稳定,尤其是导航app,大量的cpu,内存占用是常有的事,可单独放到一个独立进程里,并且启动个前台服务提高优先级。
  怎么两个进程沟通呢,由于是低频的沟通,直接广播即可。

3 不固定位置的破音:直接控制tts解析出来的数据块


   原理:破音由于系统处理的数据不足,或数据塞入间隔时间过长过短,我们这里直接控制每次写入的数据大小及间隔数据:
   详细看下代码(系统不同,代码效果也不一样,要和系统tts端配合,而且要能拿到tts解析数据,我们是自己的tts引擎):

public class AudioTrackManager {
    public static final String TAG = "AudioTrackManager";
    private AudioTrack audioTrack;
    private static AudioTrackManager mInstance;
    private int bufferSize;
    private byte[] simpleBytes = null;
    private int writeRate = 180;
    private int pushRate = 90;
    //系统一次处理的数据块的最小值,小于的话,就会破音
    private static int RateSize = 1900;

    private SyncStack syncStack = new SyncStack();
    private long oldTime = 0;
    private ExecutorService pool = Executors.newSingleThreadExecutor();

    //类似生产者,消费者的一个读写类(每写一次,都给一次取的机会,目的是不耽误取出播报的节奏)
    class SyncStack {

        LinkedBlockingQueue<byte[]> datas = new LinkedBlockingQueue<byte[]>();
        long oldTime = 0;

        public void clearData(){
            datas.clear();
        }

        public synchronized void push(byte[] data) {
            try {
                datas.put(data);
                long time  = System.currentTimeMillis()-oldTime;
                //空出机会给写入线程机会
                if (time > pushRate) {
                    time = 5;
                } else {
                    time = pushRate - time;
                }

                if(time>0) {
                    wait(time);
                }
                oldTime = System.currentTimeMillis();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
//            this.notify();
        }

        public synchronized byte[] pop() throws InterruptedException {
            if (datas == null || datas.size() == 0) {
                //50ms后不再等待数据,自动结束流程
                if (datas == null || datas.size() == 0) {
                    wait(50);
                }
                if(datas==null||datas.size()==0) {
                    return null;
                }
            }
            return datas.take();
        }
    }

    public AudioTrackManager() {
        bufferSize = AudioTrack.getMinBufferSize(8000, AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT);
        audioTrack = new AudioTrack(AudioPolicyManager.STREAM_NAVI, 8000, AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT, bufferSize, AudioTrack.MODE_STREAM);
    }

    private void initTrack() {
        if (audioTrack == null) {
            bufferSize = AudioTrack.getMinBufferSize(8000, AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT);
            audioTrack = new AudioTrack(AudioPolicyManager.STREAM_NAVI, 8000, AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT, bufferSize, AudioTrack.MODE_STREAM);
        }
    }

    public static AudioTrackManager getInstance() {
        if (mInstance == null) {
            synchronized (AudioTrackManager.class) {
                if (mInstance == null) {
                    mInstance = new AudioTrackManager();
                }
            }
        }
        return mInstance;
    }

    public void startReady() {
        initTrack();
        if(syncStack!=null) {
            syncStack.clearData();
        }else{
            syncStack = new SyncStack();
        }
    }

    //System.arraycopy()方法
    public static byte[] byteMerger(byte[] bt1, byte[] bt2) {
        byte[] bt3 = new byte[bt1.length + bt2.length];
        System.arraycopy(bt1, 0, bt3, 0, bt1.length);
        System.arraycopy(bt2, 0, bt3, bt1.length, bt2.length);
        return bt3;
    }
    /**
     * 停止播放
     */
    public void stopPlay() {
        try {
            //destroyThread();
            Log.v(TAG, "yangtest--stopTTS");
            if(syncStack!=null){
                syncStack.clearData();
            }
            if (audioTrack != null) {
                if (audioTrack.getState() == AudioRecord.STATE_INITIALIZED) {
                    audioTrack.stop();
                }
                if (audioTrack != null) {
                    audioTrack.release();
                }
                audioTrack = null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //tts 服务会不停的传过来解析出来的据
    public void startPush(byte[] data) {
        syncStack.push(data);
    }
    //启动播报线程
    public void startPop() {
        Log.e("yangtest","startpop-bufferSize-"+bufferSize);
        pool.execute(
               new Runnable(){

                    public void run() {

                       android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_AUDIO);
                        try {
                            //等待先写入数据一定的数据,防止进来就破音
                            Thread.sleep(getStartTime());
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }

                        audioTrack.play();
                        try {
                            while ((simpleBytes = syncStack.pop()) != null) {

                                while (simpleBytes.length < RateSize) {
                                    try {
                                        //一次取的不够,先等待最小间隔时间再操作
                                        Thread.sleep(writeRate);
                                    } catch (InterruptedException e) {
                                        e.printStackTrace();
                                    }
                                    byte[] temp = syncStack.pop();
                                    if (temp != null) {
                                        simpleBytes = byteMerger(simpleBytes, temp);
                                    } else {
                                        Log.e("yangtest", "no-data");
                                        break;
                                    }
                                }
                                startWrite();
                            }
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }

                        if (endPlay != null) {
                            endPlay.onEnd();
                        }
                    }

                });
    }
    /**
     * 启动播放线程
     */
    private void startWrite() {
        //需先等待最小的间隔时间,保持播报节奏
        long timelen = System.currentTimeMillis() - oldTime;
        if (timelen < writeRate) {
            try {
                Thread.sleep(writeRate - timelen);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        oldTime = System.currentTimeMillis();
        audioTrack.write(simpleBytes, 0, simpleBytes.length);
        simpleBytes = null;
    }

    public long getStartTime(){
        int txtLen = BdTTSPlayer.speechs.length();
        int len = 60 + txtLen * 10;
        return len;
    }

    public void setEndPlay(EndPlay endPlay) {
        this.endPlay = endPlay;
    }

    EndPlay endPlay;

    interface EndPlay {
        public void onEnd();
    }
}
该方案需要自己调时间间隔值,没有一个固定的答案。

http://www.yayakq.cn/news/707885/

相关文章:

  • 创立网站广州网站开发公司有哪些
  • 兴义市建设局网站首页卡纸做荷花网站
  • 网站布局 下载工商注册深圳
  • 招聘求职网站html模板wordpress 标签 超链接
  • 网络营销的发展前景六年级下册数学优化设计答案
  • 做网站电脑配置网站开发 验收
  • 搭建网站要哪些知识王烨老师
  • 360建站的应用场景wordpress弱点
  • 常州市经开区建设局网站wordpress vr主题
  • 信息网站模板WordPress百度快照图片
  • 网站费用明细自己做视频网站
  • 菏砖网站建设wordpress弱密码
  • 第三方网站建设平台潍坊市建设局官方网站
  • 汕头网站制作电话海南网站优化公司
  • 网站关键词公司闲聊app是哪个公司开发
  • 海口网站建设专家评价小程序开发免费平台
  • 网站如何维护网站设计与制作是什么专业
  • 保健品网站源代码欧米茄表价格官网报价
  • 深圳商城网站公司dede采集规则下载网站
  • 网站备案通过后怎么办曲阜官方建设局网站
  • 网站首页一般做多大代做网站转账截图
  • 网站后台文字编辑器手机商城网站设计
  • 做网站跟做app哪个累合肥网络公司
  • 长春网站推广南昌网站建设风格
  • 网站建设目标的文字看想看的做想做的电影网站好
  • 天津河北做网站的公司排名福州seo服务
  • 企业网站建设市场前景wordpress菜单的功能
  • 广西容县建设网站wordpress阿帕奇伪静态
  • 网站备案与icp备案国外素材设计欣赏网站
  • 网站排名怎么做 知乎龙华网站建设app