I am making a class that takes an array of frequencies values (i.e. 440Hz, 880Hz, 1760Hz) and plays how they would sound combined into a single AudioTrack. I am not a sound prog
Ok, so the answer did turn out to be a simple summation loop. Here it is, just replace this for loop with the original one:
// fill out the array
for (int i = 0; i < numOfSamples; ++i) {
double valueSum = 0;
for (int j = 0; j < soundData.length; j++) {
valueSum += Math.sin(2 * Math.PI * i / (SAMPLE_RATE / soundData[j][0]));
}
sample[i] = valueSum / soundData.length;
}
Now, what this does is simply take all possible frequencies, add them together into the variable, valueSum
, and then divide that by the length of the frequency array, soundData
, which is a simple average. This produces a nice sine wave mixture of an arbitrarily long array of frequencies.
I haven't tested performance, but I do have this running in a thread, otherwise it could crash the UI. So, hope this helps - I am marking this as the answer.
If you intend to mix multiple waveforms into one, you might prevent clipping in several ways.
Assuming sample[i] is a float representing the sum of all sounds.
HARD CLIPPING:
if (sample[i]> 1.0f)
{
sample[i]= 1.0f;
}
if (sample[i]< -1.0f)
{
sample[i]= -1.0f;
}
HEADROOM (y= 1.1x - 0.2x^3 for the curve, min and max cap slighty under 1.0f)
if (sample[i] <= -1.25f)
{
sample[i] = -0.987654f;
}
else if (sample[i] >= 1.25f)
{
sample[i] = 0.987654f;
}
else
{
sample[i] = 1.1f * sample[i] - 0.2f * sample[i] * sample[i] * sample[i];
}
For a 3rd polynomial waveshapper (less smooth), replace the last line above with:
sample[i]= 1.1f * sample[i]- 0.2f * sample[i] * sample[i] * sample[i];