欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  科技

使用AudioTrack播放wav文件

程序员文章站 2022-03-03 19:46:07
近期使用AudioTrack播放wav文件的时候出现开头爆音的现象,分析后得知wav文件有个44或46字节的头数据,在使用AudioTrack播放写入数据时要把这个头数据去掉即可。源码实例如下: private static final int STREAM_TYPE = AudioManager.STREAM_MUSIC;//音频流类型 private static final int SAMPLERATE_HZ = 16000;//采样率 private static final......

    近期使用AudioTrack播放wav文件的时候出现开头爆音的现象,分析后得知wav文件有个44或46字节的头数据,在使用AudioTrack播放写入数据时要把这个头数据去掉即可。源码实例如下:

  private static final int STREAM_TYPE = AudioManager.STREAM_MUSIC;//音频流类型
  private static final int SAMPLERATE_HZ = 16000;//采样率
  private static final int CHANNEL_CONFIG = AudioFormat.CHANNEL_CONFIGURATION_MONO;//捕获音频的声道数目
  private static final int AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT;//音频量化位,脉冲编码调制
    /**
     * 启动播放
     * @param voicename
     */
  public void startPlay(String voicename) {
        try {
            String path = LOCALTTS_VOICE_MAP.get(voicename);
            setPath(path);
            byte[] tempBuffer = new byte[mMinBufferSize];
            int readCount = 0;
			int count = 0;
            while (mInputStream.available() > 0) {
                if (mInputStream == null) {
                    return;
                }
                readCount = mInputStream.read(tempBuffer);
                if (readCount == AudioTrack.ERROR_INVALID_OPERATION || readCount == AudioTrack.ERROR_BAD_VALUE) {
                    continue;
                }
                if (readCount != 0 && readCount != -1) {
				    //判断AudioTrack未初始化,停止播放的时候释放了,状态就为STATE_UNINITIALIZED
                    if (mAudioTrack.getState() == AudioTrack.STATE_UNINITIALIZED) {
					    //根据采样率,采样精度,单双声道来得到frame的大小。
                        //按照数字音频的知识,这个算出来的是一秒钟buffer的大小。
                        mMinBufferSize = AudioTrack.getMinBufferSize(SAMPLERATE_HZ, CHANNEL_CONFIG, AUDIO_FORMAT);
                        mAudioTrack = new AudioTrack(STREAM_TYPE, SAMPLERATE_HZ, CHANNEL_CONFIG, AUDIO_FORMAT,
                            mMinBufferSize, mMode);
                    }
                    mAudioTrack.play();
//由于这是播放pcm文件和wav文件的通用接口,在这里检测若是wav文件且为第一轮读取字节数据时,将前44个字节的头数据忽略
                    if (voicename.contains(".wav") && count == 0) {
                        mAudioTrack.write(tempBuffer, 44, readCount);
                    } else {
                        mAudioTrack.write(tempBuffer, 0, readCount);
                    }
		    count++;
                }
            }
            stopPlay();
        } catch (Exception e) {
            Log.i(TAG, "startPlayException:" + e.toString());
        }
    }

    /**
     * 添加播放文件
     * @param path
     */
    private void setPath(String path) {
        File file = new File(path);
        try {
            if (mInputStream == null) {
                mInputStream = new DataInputStream(new FileInputStream(file));
            }
        } catch (Exception e) {
            Log.i(TAG, "setPathException:" + e.toString());
        }
    }

    /**
     * 停止播放
     */
    public void stopPlay() {
        CoreStub.getInstance().onSpeechState(Constant.STATE_SPEAK_END);
        if (mAudioTrack != null) {
            if (mAudioTrack.getState() == AudioRecord.STATE_INITIALIZED) {
                mAudioTrack.stop();
            }
            if (mAudioTrack != null) {
                mAudioTrack.release();
            }
        }
        if (mInputStream != null) {
            try {
                mInputStream.close();
                mInputStream = null;
            } catch (IOException e) {
                Log.i(TAG, "stopPlayException:" + e.toString());
            }
        }
    }

 

本文地址:https://blog.csdn.net/Arise_Yang/article/details/107919468