Is there any legroom left for optimization (without switching to C)?
static byte[] generateSound(double frequency, int sampleRate, int samples) {
byte output[] = new byte[2 * samples];
int idx = 0;
double _tone = 2 * Math.PI / (sampleRate / frequency);
for (int i = 0; i < samples; ++i) {
double dVal = Math.sin(_tone * i);
final short val = (short) ((dVal * 32767));
output[idx++] = (byte) (val & 0x00ff);
output[idx++] = (byte) ((val & 0xff00) >>> 8);
}
return output;
}
3 Answers 3
There's probably good room for performance gain regarding the Math.sin call itself. You could easily create a lookup-table - there's no faster way than just taking the values straight from an array. (The link's benchmark measures a factor ~6 speed difference.)
It may be problematic because it may cause audible distortions, but that would depend on how much memory you're willing to invest in the lookup-table. Also, you could invest a few more cycles by obtaining both array entries addressed by (_tone*i) and then adding them up, both multiplied by 0.x and respectively (1-0.x), effectively fading over between values.
I don't know how much it will optimize it but this:
double dVal = Math.sin(_tone * i);
Shouldn't be needed.
Replace:
final short val = (short) ((dVal * 32767));
With:
final short val = (short) ((Math.sin(_tone * i) * 32767));
The compiler may be able to optimize it well enough that this doesn't matter, but it may help.
A few optimisation:
Using bitwise operators
byte output[] = new byte[samples << 1]; double _tone = (Math.PI << 1) / (sampleRate / frequency); final short val = (short) ((dVal<<15) - dVal);
Reducing variables
short val = (short) ((Math.sin(_tone * i) * 32767));
Why final? Not sure if adds to the overhead.
Explore related questions
See similar questions with these tags.