0

I need to generate 2 sine wave tones with different frequency and play them separately into right and left channel in stereo mode on Android.

This is my code:

int sample;
double sampleRate;
double duration;    
double time;
double f1;
double f2;
double amplitude1;
double amplitude2;
double sineWave1;
double sineWave2;
float[] buffer1;
float[] buffer2;
byte[] byteBuffer1;
byte[] byteBuffer2;
byte[] byteBufferFinal;
int bufferIndex;    
short x; 
short y;    
AudioTrack audioTrack;

@Override
public void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    sampleRate = 44100.0;
    duration = 20.0;
    f1 = 440.0;
    amplitude1= 1;
    f2 = 444.0;
    amplitude2 = 0;

    buffer1 = new float[(int)(duration*sampleRate)];
    buffer2 = new float[(int)(duration*sampleRate)];

    for(sample = 0; sample < buffer1.length; sample ++){
        time = sample / sampleRate;
        buffer1[sample] = (float)(amplitude1*Math.sin(2*Math.PI*f1*time));
        buffer2[sample] = (float)(amplitude2*Math.sin(2*Math.PI*f2*time));  
    }

    byteBuffer1 = new byte[buffer1.length*2]; //two bytes per audio frame, 16 bits

    for(int i = 0, bufferIndex=0; i < byteBuffer1.length; i++){
        x = (short) (buffer1[bufferIndex++]*32767.0); // [2^16 - 1]/2 = 32767.0
        byteBuffer1[i] = (byte) x; // low byte
        byteBuffer1[++i] = (byte) (x >>> 8);  // high byte          
    }


    byteBuffer2 = new byte[buffer2.length*2];

    for(int j = 0, bufferIndex=0; j < byteBuffer2.length; j++){
        y = (short) (buffer2[bufferIndex++]*32767.0);
        byteBuffer2[j] = (byte) y;         // low byte
        byteBuffer2[++j] = (byte) (y >>> 8);  // high byte

    }

    byteBufferFinal = new byte[byteBuffer1.length*2]; 
    //LL RR LL RR LL RR 
    for(int k = 0, index = 0; index < byteBufferFinal.length - 4; k=k+2){
        byteBufferFinal[index] = byteBuffer1[k]; // LEFT {0,1/4,5/8,9/12,13;...}
        byteBufferFinal[index+1] = byteBuffer1[k+1];
        index = index + 2;
        byteBufferFinal[index] = byteBuffer2[k]; // RIGHT {2,3/6,7/10,11;...}
        byteBufferFinal[index+1] = byteBuffer2[k+1];
        index = index + 2;
    }

    audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
            (int) sampleRate,AudioFormat.CHANNEL_OUT_STEREO,
            AudioFormat.ENCODING_PCM_16BIT,byteBufferFinal.length,
            AudioTrack.MODE_STATIC);

   audioTrack.write(byteBufferFinal, 0, byteBufferFinal.length);
   audioTrack.play();
   }

The output buffer(byteBufferFinal) has the 16-bit format: LL RR LL RR LL RR LL (where each character is 1 byte)

My code doesn't do well the distribution of the sound in the left and right channel. I prove it leaving one amplitude in "1" and the other in "0", so that 1 of the 2 channels left without sound, BUT both emit sound

What's wrong in my code?

  • What is the audio being routed to (loudspeaker, headphones, USB, ...)? If it's the loudspeaker; does the device you're testing on actually have stereo speakers? – Michael Dec 09 '13 at 06:58
  • I use stereo headphones! – user3081080 Dec 09 '13 at 23:14
  • @Michael hey, I chanced upon this and would be useful for my implementation but before I implement I would like to understand some basic concepts 1. What is the buffer used for (eg: buffer1, buffer2, byteBuffer) 2. Why is the size of the buffer 44.1k (what's the relationship between buffer and sample rate) 3. Where else is the buffer used Thanks! Have a pleasant day! – user1730935 Mar 18 '16 at 17:06

1 Answers1

0

I tried it with API 18, Eclipse Kepler, running on my Samsung S4 and it worked fine. The right channel was silent and the left channel played a 440Hz sine wave.

The only bug I noticed while reading the code is that the played duration is 1/2 of what it should be: the line "byteBufferFinal = new byte[buffer1.length*2];" should instead be "byteBufferFinal = new byte[byteBuffer1.length*2];"

Sadly, the problem might just be your audio cable or speakers: the audio plug might not be plugged all the way into the phone jack, making one channel play in both speakers.

  • I tried it with API 16, on my Samsung Galaxy Ace and doesn't work(the left and right channel emit sound). Then, because of your answer I tried it with API 18, on my NEXUS 7(with headphones) and doesn't work. You have to run my code, with the maximum volume on your phone and you will realize that both channels sound(one lower sound than the other). If you don't do, you will think that one channel sounds and the other not. So, the problem are not the audio cable or speakers :(. I still don't know what is the problem! – user3081080 Dec 09 '13 at 23:10
  • PD: I change the line "byteBufferFinal = new byte[buffer1.length*2];" to "byteBufferFinal = new byte[byteBuffer1.length*2];" I was wrong, when I transferred the code. thanks!! – user3081080 Dec 09 '13 at 23:11
  • "You have to run my code, with the maximum volume on your phone and you will realize that both channels sound(**one lower sound than the other**). If you don't do, you will think that one channel sounds and the other not." indicates that what you are facing is **probably not a software problem**, but rather limited channel isolation in the audio output **circuitry**. Consider generating a test file with audio in only one channel using *audacity* and playing it both on a desktop and on your phone using various player apps. – Chris Stratton Dec 09 '13 at 23:47