Вы предполагаете, что каждый раз генерируется одна и та же синусоида, но поскольку используется переменная phase
и синусоида не всегда точно помещается в буфере, на каждой итерации генерируется разная синусоида, смещеннаянемного.
Не генерирование синусоидальной волны каждый раз приводит к «разрыву» синусоиды.
Я попробую визуализацию с помощью пилообразной волны вместо синусоидальной.Представьте, что размер буфера равен 16, а значения волн находятся в диапазоне от A до H.
// Old way
phase = 0 phase = 2 phase = 4
ABCDEFGHGFEDCBAB|CDEFGHGFEDCBABCD|EFGHGFEDCBABCDEF....
// New way
phase = 0 phase = 0 phase = 0
ABCDEFGHGFEDCBAB|ABCDEFGHGFEDCBAB|ABCDEFGHGFEDCBAB....
Обратите внимание, что по краям буфера присутствуют только маленькие кусочки, где звук "искажен" (например, вместо AB|AB
AB|CD
).Вот почему он звучит правильно в большинстве случаев с некоторыми тревожными короткими «щелчками» между ними.
В некоторых редких случаях, если длина буфера кратна длине волны или когда phase
имеет то же самоезначение, как в предыдущей итерации, вы действительно можете пропустить генерацию буфера, но вы не можете делать это каждый раз.
РЕДАКТИРОВАТЬ: посмотрите на функцию generate_sine , чтобы увидеть, как phase
изменено:
static void generate_sine(const snd_pcm_channel_area_t *areas,
snd_pcm_uframes_t offset,
int count, double *_phase)
{
static double max_phase = 2. * M_PI;
double phase = *_phase;
double step = max_phase*freq/(double)rate;
[...]
phase += step;
if (phase >= max_phase)
phase -= max_phase;
}
*_phase = phase;
}
РЕДАКТИРОВАТЬ2: Это изображение может быть лучше / четче визуализация: