0

我正在 Android 上制作音频应用程序,我简单地生成了三种类型的声波——正弦波、锯齿波和方波。

产生波浪很好。我打印了结果,看起来不错。但是声音很奇怪。这是我记录的。 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;
}
4

2 回答 2

0

尝试使用短数据类型而不是核心的双精度数据类型。OpenSLEL 无论如何都会将其转换为short,因此可能会丢失数据或添加噪音。此外,为了获得良好的质量,请使用更高的采样率。

于 2016-03-07T05:28:24.380 回答
0

您在生成波浪时没有打印任何内容?

但主要问题也是您的综合循环。我猜你听到的点击是因为你跳过了样本(你增加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;
    }
}
于 2016-02-24T15:49:31.327 回答