我正在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;
}
你在生成波浪时没有打印出任何东西?
但主要问题是你的合成循环。我猜你听到的点击是因为你在for循环和合成块中跳过了样本(你增加了两次i
。应该是这样以避免点击:
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;
}
}
尝试使用短数据类型而不是核心的双精度。OpenSLEL 无论如何都会将其转换为短,因此可能会添加数据丢失或噪音。同样为了获得良好的质量,请使用更高的采样率。