Richard_Papen
Richard_Papen

Reputation: 127

Java - Generating Tones with different amplitudes makes different tones

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):

Sinus

But if I select a higher amplitude, in this case Short.MAX_VALUE, the created tone looks and sounds strange:

Sinus2

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:

noise

Where does this come from and how can I fix it?

Thank you for your help!

Upvotes: 1

Views: 337

Answers (2)

trashgod
trashgod

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

Kwergan Gregory
Kwergan Gregory

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

Related Questions