Android:AudioTrack 在开始时发出咔哒声

Bar*_*tho 5 audio android

我正在开发一个 Android 应用程序,我想播放一些短的声音(~ 2 秒)。我尝试过 Soundpool,但它并不适合我,因为它无法检查声音是否已经在播放。所以我决定使用 AudioTrack。

它工作得很好,但大多数时候,当它开始播放声音时,会发出“咔嗒”声。我检查了我的音频文件,它们是干净的。

我在流模式下使用音轨。我发现静态模式更适合短声音,但经过多次搜索后我仍然不明白如何使其工作。我还读到,点击噪音可能是由 wav 文件的标头引起的,因此如果我使用setPlaybackHeadPosition(int positionInFrames)函数跳过此标头(应该仅在静态模式下工作),声音可能会消失

这是我的代码(所以问题是开始时的滴答声)

    int minBufferSize = AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_CONFIGURATION_MONO, 
            AudioFormat.ENCODING_PCM_16BIT);
    audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_CONFIGURATION_MONO, 
         AudioFormat.ENCODING_PCM_16BIT, minBufferSize, AudioTrack.MODE_STREAM); 
audioTrack.play();
            int i = 0;
            int bufferSize = 2048; //don't really know which value to put
            audioTrack.setPlaybackRate(88200);

            byte [] buffer = new byte[bufferSize];
//there we open the wav file >
            InputStream inputStream = getResources().openRawResource(R.raw.abordage);
            try {
                while((i = inputStream.read(buffer)) != -1)
                    audioTrack.write(buffer, 0, i);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            try {
                inputStream.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
Run Code Online (Sandbox Code Playgroud)

有人有办法避免这种噪音吗?我尝试过这个,有时有效,但并非每次都有效。有人可以告诉我如何实现音轨MODE_STATIC吗?谢谢

Bar*_*tho 1

最后,经过大量实验,我让它在没有点击噪音的情况下工作。这是我的代码(不幸的是,我无法读取 inputStream 的大小,因为该getChannel().size()方法仅适用于 FileInputStream 类型)

try{
    long totalAudioLen = 0;  
    InputStream inputStream = getResources().openRawResource(R.raw.abordage); // open the file
    totalAudioLen = inputStream.available();
    byte[] rawBytes = new byte[(int)totalAudioLen];
    AudioTrack track = new AudioTrack(AudioManager.STREAM_MUSIC,
                                      44100,
                                      AudioFormat.CHANNEL_CONFIGURATION_MONO,
                                      AudioFormat.ENCODING_PCM_16BIT,
                                     (int)totalAudioLen,
                                     AudioTrack.MODE_STATIC);
    int offset = 0;
    int numRead = 0;

    track.setPlaybackHeadPosition(100); // IMPORTANT to skip the click
    while (offset < rawBytes.length
               && (numRead=inputStream.read(rawBytes, offset, rawBytes.length-offset)) >= 0) {
            offset += numRead;
    } //don't really know why it works, it reads the file
    track.write(rawBytes, 0, (int)totalAudioLen); //write it in the buffer?
    track.play();  // launch the play
    track.setPlaybackRate(88200);
    inputStream.close();
    }
    catch (FileNotFoundException e) {

        Log.e(TAG, "Error loading audio to bytes", e);
    } catch (IOException e) {
        Log.e(TAG, "Error loading audio to bytes", e);
    } catch (IllegalArgumentException e) {
        Log.e(TAG, "Error loading audio to bytes", e);
    }
Run Code Online (Sandbox Code Playgroud)

因此,跳过点击噪音的解决方案是使用MODE_STATICsetPlaybackHeadPosition函数来跳过音频文件的开头(这可能是标题或我不知道是什么)。我希望这部分代码会对某人有所帮助,我花了太多时间试图找到静态模式代码示例,而没有找到加载原始资源的方法。

编辑:在各种设备上测试此解决方案后,它们似乎仍然有咔哒声。

  • 您正在播放 wav 文件吗?那么跳过前 44 个字节就足够了,因为标头(大部分)就是这个大小。更好的是跳过流中已有的字节: inputStream.skip(44) (2认同)