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
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.