0

I'm making audio app on Android and I have simple generation of three types of sound waves - Sine, Sawtooth and Square.

Generating of waves is fine. I printed out the result and it's looking good. But the sound is weird. Here is what I recorded. https://soundcloud.com/syntey/synth-sine-wave-test-nothing-to-do-here

It's same for sawtooth and square, but when I play with sawtooth any A, then sound is normal.

Does someone know what is wrong? If I increase size of buffer, then period is longer, but still the same problem

Code for generating sine wave:

play(JNIEnv* env, jclass clazz, jint which, jint count, jdouble freqOfTone)
{
    unsigned i;
    int j = 0;
    double sampleRate = SAMPLERATE/freqOfTone;
    switch (which) {
case SINE:
        for (i = 0; i < TONE_FRAMES; ++i) {
            toneBuffer[i] = sin(2.0*M_PI * i/sampleRate) * 32768;                
        }
        nextBuffer = createResampledBuf(SINE, SL_SAMPLINGRATE_8, &nextSize);
        if(!nextBuffer) {
            nextBuffer = (short*) toneBuffer;
            nextSize  = sizeof(toneBuffer);
        }
        break;
    }
    nextCount = count;
    if (nextSize > 0) {
        SLresult result;
        result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, nextBuffer, nextSize);
        if (SL_RESULT_SUCCESS != result) {
            bqPlayerRecorderBusy = 1;
            return JNI_FALSE;
        }
    }

    return JNI_TRUE;
}
Syntey
  • 147
  • 1
  • 15

2 Answers2

0

You're not printing out anything while generating the wave?

But also the main problem is your synthesis loop. I'm going to guess the clicks you hear is because you're skipping samples (you increment i twice, in your for loop and in your synthesis block. It should be this to avoid the clicks:

for (i = 0; i < SIZE_OF_BUFFER; i++) {
        toneBuffer[i] = sin(2.0*M_PI * i/(44100/freqOfTone)) * 32768;
}

But I would recommend you work with phases, to me it just makes more sense in a signal processing process

float generateSineWave(float freq) {
    // Get phase, then get sample
    phase = 2 * M_PI * freq / 44100 + prev_phase;
    sample = sin(phase);

    // wrap phase
    if (phase > (2 * M_PI)) phase -= (2 * M_PI);

    prev_phase = phase

    return sample;
}

void yourSynthesisLoop() {
    for (int i = 0; i < SIZE_OF_BUFFER; i++) {
        toneBuffer[i] = generateSineWave(freqOfTone) * 32768;
    }
}
yun
  • 1,243
  • 11
  • 30
  • I copied it wrong with that double incrementing, sorry.. I used your code and still it clicks.. but some tones have it quieter. I will post more code in first post – Syntey Feb 24 '16 at 17:13
  • @Syntey hm I have that running in my code and I don't have any clicking, how are you setting up opensl in your code? Does it still sound exactly the same? And again if you're printing anything out (or just any outstanding process) while its generating the waveform you'll get clicks as these functions will slow down your waveform generation block. ALSO - make sure you initialize prev_phase to 0 and as a static variable, you might get clicks if those aren't set up correctly – yun Feb 24 '16 at 17:16
  • I'm using native audio project and recently I edited first post, where I have whole function. Yes I initialized it to 0 – Syntey Feb 24 '16 at 17:21
  • I'm going to have to say something is weird with how you're setting up then. For example, why are you creating a resampled buffer; why is it set to 8 kHz sampling rate even though your sample rate was at 44.1 kHz? I guess I would have to see your whole open sl setup to help debug further, but check this blogpost about how to set up Open SL for audio streaming: https://audioprograming.wordpress.com/2012/03/03/android-audio-streaming-with-opensl-es-and-the-ndk/ – yun Feb 24 '16 at 17:29
0

Try to use short data type instead of double from the core. OpenSLEL converts it to short anyways, hence there may be data loss or noise added. Also for good quality use higher sample rate.