Генерация звука на Android с помощью OpenSL ES

Я делаю аудио приложение для Android, и у меня есть простое поколение трех типов звуковых волн - Sine, Sawtooth и Square.

Генерация волн в порядке. Я распечатал результат, и он выглядит хорошо. Но звук странный. Вот что я записал. https://soundcloud.com/syntey/synth-sine-wave-test-nothing-to-do-here

То же самое для пилообразного и квадратного, но когда я играю с пилообразным любым A, то звук нормальный.

Кто-то знает, что не так? Если я увеличу размер буфера, то период будет длиннее, но проблема все та же

Код для генерации синусоиды:

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;
}

2 ответа

Попробуйте использовать короткий тип данных вместо двойного из ядра. OpenSLEL в любом случае преобразует его в короткое, поэтому могут быть потеря данных или шум. Также для хорошего качества используйте более высокую частоту дискретизации.

Вы ничего не печатаете во время генерации волны?

Но также главной проблемой является ваш цикл синтеза. Я предполагаю, что вы слышите щелчки, потому что вы пропускаете образцы (вы увеличиваете i дважды, в вашем цикле for и в вашем блоке синтеза. Это должно быть так, чтобы избежать кликов:

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

Но я бы порекомендовал вам работать с фазами, для меня это просто имеет больше смысла в процессе обработки сигналов

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;
    }
}
Другие вопросы по тегам