Reputation: 127
I am creating tones in my Java-program. So there is a number of oscillator modules which produce the samples I need so that I can play more than one tone at a time. These samples are added and played. If I select a low amplitude, e.g. 100, everything works fine (normalized it in Audacity):
But if I select a higher amplitude, in this case Short.MAX_VALUE, the created tone looks and sounds strange:
The samples are created here (source: http://www.wolinlabs.com/blog/java.sine.wave.html):
short value;
if (type == TYPE_SINE)
{
cycleIncrease = frequency / parent.getSamplingRate();
value = (short) (amplitude * Math.sin(2 * Math.PI * cyclePosition));
cyclePosition += cycleIncrease;
if (cyclePosition > 1)
cyclePosition -= 1;
return value;
}
With sawtooth waves I have the same problem:
else if (type == TYPE_SAW)
{
cycleIncrease = frequency / parent.getSamplingRate();
double doubleValue = cyclePosition - Math.floor(cyclePosition);
cyclePosition += cycleIncrease;
value = (short) (amplitude * doubleValue);
if (cyclePosition > 1)
cyclePosition -= 1;
return value;
}
amplitude
has the value I mentioned above, so in these two cases 100
and Short.MAX_VALUE
.
The samples are summed up in this way, where sum
is the output sample and value
is the calculated sample (0 if no tone is played):
int n = 0;
int sum = 0;
for (Wire inputWire:inputWires)
{
short value = inputWire.getNextSample();
if (value != 0)
{
n += 1;
}
sum += value;
x++;
}
if (n != 0)
sum = sum / n;
I also made sure that there is just the one sample from one oscillator if just one tone is played, so sum = value
.
But I don't understand why different tones are created for different amplitudes with the same code, so why is this happening?
I also have a second question: If I end playing a sine tone with low amplitude, I can hear a short noise, which looks like this:
Where does this come from and how can I fix it?
Thank you for your help!
Upvotes: 1
Views: 337
Reputation: 205865
Verify that the sampleSizeInBits
of your AudioFormat
comports with your chosen amplitude
. If not, you may be seeing a "wrap-around" effect when multiplying by amplitude
. For reference, this example scales the sample size to eight bits representing a signed byte value in the range -128..127
.
AudioFormat af = new AudioFormat(Note.SAMPLE_RATE, 8, 1, true, true);
…
sin[i] = (byte)(Math.sin(angle) * 127f);
Upvotes: 1
Reputation: 21
Question 1:
It looks as though you may be wrapping the waveform:
if (cyclePosition > 1)
cyclePosition -= 1; // You are reducing the amplitude by half? (goes from 1 to -1)
This is where some clipping should occur:
// For example...
if (cyclePosition > 1)
cyclePosition = 1
if (cyclePosition < -1)
cyclePosition = -1
The Audio may sound bad, but this is what normally happens when the Amplitude is too large.
Maybe try scaling the amplitude to always fit it within bounds:
scale = 1 / highestAmplitude;
foreach (point in wavePoints)
{
point *= scale;
}
// or something similar
Question 2:
Make sure the sine wave ends at 0 Amplitude
Upvotes: 1