Я написал программу на с ++ для генерации WAV-файла для синусоидальной волны 800 Гц (1-канальная, 8-битная, 16000 Гц, 32000 выборок, длительностью 2 секунды), но когда я воспроизводил его или изучал спектрограмму в Audacity, обертоны.
Я думаю, что проблема в алгоритме преобразования синусоиды в PCM; Я не уверен, где поставить «нулевое» смещение, на 127, или 127,5, или 128 и т. Д.
char data[32000];
for (int j = 0; j < 32000; ++j)
{
data[j] = (char) (round(127 + 60 * (sin(2.0 * 3.14159265358979323846264338327950 * j / 20.0))));
}
и файл получился такой: output.wav
Если необходимо, вот файл cpp: wavwriter.cpp
Спасибо!
РЕДАКТИРОВАТЬ 2: я изменил char на uint8_t
uint8_t data[32000];
for (int j = 0; j < 32000; ++j)
{
data[j] = round(127 + 60 * (sin(2.0 * 3.14159265358979323846264338327950 * j / 20.0)));}
outfile.write((char *)&data[0], sizeof data);outfile.close();
return true;
чтобы избежать неопределенного поведения.
Та же проблема все еще применяется.
Вы добавили шум округления и детерминированный шум квантования. Ваша синусоида повторяется с точным целым числом образцов; таким образом, ошибка округления (или разность между значением с плавающей точкой и значением UInt_8 вашей синусоиды) повторяется ровно периодически, что создает слышимые гармоники.
Вы можете уменьшить этот шум, используя округление сглаживания и фильтрование шума при преобразовании синусоиды с плавающей запятой в значения UInt_8.
Сглаживание (или добавление дробных случайных значений к каждой выборке перед округлением) удаляет детерминированный шум. Результирующий шум будет белее, а не из обертонов.
Шумовая фильтрация не просто отбрасывает дробную часть из округления, но объединяет этот дробный остаток с БИХ-фильтром, чтобы переместить шум квантования туда, где он может быть менее слышимым и с меньшей вероятностью создать смещение постоянного тока.
Других решений пока нет …