Reputation: 700
I have a class that uses AudioTrack to generate a sound per specific frequency. Everything works fine, but now I want to customize it so that I can play the sound only on right side of headphones, or only on left side of headphones. (right, or left ear)
So I found that AudioTrack has a such method: setStereoVolume()
, however, when I configure it, for example like this: audioTrack.setStereoVolume(1.0f, 0.0f)
, I'm expecting that only my left side of headphones should sound, and the right side should be mute, but it has not efect. I can hear the sound at the same volume on both right and left side of headphones.
I check the return value of setStreamVolume()
and it's 0, which is equal with SUCCESS, but I still don't hear the difference.
Do you know why it isn't working, or an alternative way how I can specify to play the sound only on left or right side of headphones?
Here's the code that generates the sound:
public class SoundGenerator extends AsyncTask<Float, Void, Void> {
final int SAMPLE_RATE = 11025;
boolean playing=false;
@Override
protected Void doInBackground(Float... params) {
float frequency=params[0];
int minSize = AudioTrack.getMinBufferSize(SAMPLE_RATE,
AudioFormat.CHANNEL_CONFIGURATION_STEREO,
AudioFormat.ENCODING_PCM_16BIT);
AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
SAMPLE_RATE, AudioFormat.CHANNEL_CONFIGURATION_STEREO,
AudioFormat.ENCODING_PCM_16BIT, minSize,
AudioTrack.MODE_STREAM);
short[] buffer = new short[minSize];
float angular_frequency = (float) (2 * Math.PI) * frequency / SAMPLE_RATE;
float angle = 0;
audioTrack.play();
int stereo=audioTrack.setStereoVolume(1.0f, 0.0f);
Log.d("GREC", "Stereo vol: "+stereo);
while (playing) {
for (int i = 0; i < buffer.length; i++) {
buffer[i] = (short) (Short.MAX_VALUE * ((float) Math.sin(angle)));
angle += angular_frequency;
}
audioTrack.write(buffer, 0, buffer.length);
}
Log.d(Globals.TAG, "Stopping the tone generator...");
audioTrack.stop();
audioTrack.release();
return null;
}
public void keepPlaying(boolean flag){
playing=flag;
}
}
Upvotes: 5
Views: 4809
Reputation: 3473
I've noticed same issue. setStereoVolume
was working on Android 4.3 emulator but was not working on Android 4.0.3 device.
I've investigated Android 4.0.3 AudioTrack.java source and found that if i call setStereoVolume
before the write is called for AudioTrack it doesn't work returning ERROR_INVALID_OPERATION
because of invalid mState value.
public int setStereoVolume(float leftVolume, float rightVolume) {
if (mState != STATE_INITIALIZED) {
return ERROR_INVALID_OPERATION;
}
...
}
Then i've changed sequence of calls and added setStereoVolume
after the audioTrack.write
call and it began to work fine. Looks like write method modifies mState value
public int write(byte[] audioData,int offsetInBytes, int sizeInBytes) {
if ((mDataLoadMode == MODE_STATIC)
&& (mState == STATE_NO_STATIC_DATA)
&& (sizeInBytes > 0)) {
mState = STATE_INITIALIZED;
}
...
}
Upvotes: 1