Android:AudioTrack在开始时发出咔嗒声(Android: AudioTrack makes a click sound at beginning)

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

它工作得很好但是大部分时间,当它开始播放声音时会发出“咔嗒”声。 我检查了我的audiofiles,他们很干净。

我在流模式下使用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(); }

有没有人有解决方案来避免这种噪音? 我尝试了这个 ,有时候工作但不是每次都有效。 有人能告诉我如何在MODE_STATIC中实现MODE_STATIC吗? 谢谢

I'm working on an Android app and I would like to play some short sounds(~ 2s). I tried Soundpool but it doesn't really suit for me since it can't check if a sounds is already playing. So I decided to use AudioTrack.

It works quite good BUT most of the time, when it begins to play a sound there is a "click" sound. I checked my audiofiles and they are clean.

I use audiotrack on stream mode. I saw that static mode is better for short sounds but after many searchs I still don't understand how to make it work. I also read that the clicking noise can be caused by the header of the wav file, so maybe the sound would disappear if I skip this header with setPlaybackHeadPosition(int positionInFrames) function (that is supposed to work only in static mode)

Here is my code (so the problem is the ticking noise at the beginning)

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(); }

Does anyone has a solution to avoid that noise? I tried this, that works sometimes but not everytime. Could someone show me how to implement audiotrack in MODE_STATIC ? Thank you

最满意答案

音频“弹出”的常见原因是由于渲染过程没有在零交叉点处开始/停止声音(假设最小/最大-1到+1交叉将为0)。 扬声器或耳塞等传感器处于静止状态(无声输入),映射到此零交叉。 如果音频渲染过程无法启动/停止此零点,则要求传感器执行不可能的操作,即瞬间从其静止状态转到其最小/最大移动范围内的某个非零位置(或签证)反之亦然,如果你最后得到一个“流行音乐”)。

Finally, after a lot of experimentation, I made it work without the click noise. Here is my code (unfortunaly, I can't read the size of the inputStream since the getChannel().size() method only works with FileInputStream type)

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); }

So the solution to skip the clicking noise is to use MODE_STATIC and setPlaybackHeadPosition function to skip the beginning of the audio file (that is probably the header or I don't know what). I hope that this part of code will help someone, I spent too many time trying to find a static mode code sample without finding a way to load a raw ressource.

Edit: After testing this solution on various devices, it appears that they have the clicking noise anyway.

更多推荐