Skip to content

Instantly share code, notes, and snippets.

@slightfoot
Last active December 12, 2022 22:31
Show Gist options
  • Save slightfoot/6330866 to your computer and use it in GitHub Desktop.
Save slightfoot/6330866 to your computer and use it in GitHub Desktop.
Android Tone Generator
// Usage:
// AudioTrack tone = generateTone(440, 250);
// tone.play();
//
private AudioTrack generateTone(double freqHz, int durationMs)
{
int count = (int)(44100.0 * 2.0 * (durationMs / 1000.0)) & ~1;
short[] samples = new short[count];
for(int i = 0; i < count; i += 2){
short sample = (short)(Math.sin(2 * Math.PI * i / (44100.0 / freqHz)) * 0x7FFF);
samples[i + 0] = sample;
samples[i + 1] = sample;
}
AudioTrack track = new AudioTrack(AudioManager.STREAM_MUSIC, 44100,
AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT,
count * (Short.SIZE / 8), AudioTrack.MODE_STATIC);
track.write(samples, 0, count);
return track;
}
@fresheed
Copy link

fresheed commented Apr 4, 2015

Thanks, it works.
Can you explain some moments:

  1. Why we do binary AND with ~1 (which is 11....11 so it does not make sense)
  2. Why we need to multiply count by 2 and write sample in two array elements?
    Thanks again.

@ganioc
Copy link

ganioc commented Dec 3, 2015

I think

  1. Make sure the count is an even number;
  2. After some tests, it seems for stereo purpose, one for left, the other for right ear.

@fnovoac
Copy link

fnovoac commented Apr 1, 2017

Works, thanks!

@FurqanKaleem
Copy link

Sir, how i can change sound volume in db ?

@liammccon
Copy link

Sir, how i can change sound volume in db ?

It's been a while but I had this issue too. For anyone who needs it, I added a volume parameter; takes a double (should be between 0 and 1) and multiplies it by the overall sine wave

private AudioTrack generateTone(double freqHz, int durationMs, double volume)
{
    if (volume > 1 || volume < 0){
        volume = 1; //will make sure it isn't too loud
    }
    int count = (int)(44100.0 * 2.0 * (durationMs / 1000.0)) & ~1;
    short[] samples = new short[count];
    for(int i = 0; i < count; i += 2){
        short sample = (short)(volume * Math.sin(2 * Math.PI * i / (44100.0 / freqHz)) * 0x7FFF);
        samples[i + 0] = sample;
        samples[i + 1] = sample;
    }
    AudioTrack track = new AudioTrack(AudioManager.STREAM_MUSIC, 44100,
            AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT,
            count * (Short.SIZE / 8), AudioTrack.MODE_STATIC);
    track.write(samples, 0, count);
    return track;
}

@aksvox
Copy link

aksvox commented Apr 27, 2021

How can I infinitely loop the sound?

@liammccon
Copy link

liammccon commented Apr 27, 2021

How can I infinitely loop the sound?

set durationMs really high, then add the following after the above code:
track.setLoopPoints(0, track.getBufferSizeInFrames(), -1);
or
track.setLoopPoints(0, samples.length / 2, -1);
for older versions of android i think
-1 makes it loop indefinetly, or can set it to a high number if you want

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment