Генерирующая синусоидальная волна создает шум

#c #audio #trigonometry #synthesizer #sample-rate

#c #Аудио #тригонометрия #синтезатор #частота дискретизации

Вопрос:

У меня есть простая программа на C для генерации прямоугольной волны с определенной частотой, частотой дискретизации и амплитудой, которая отлично работает. Однако, если я закомментирую соответствующую строку и раскомментирую новую синусоидальную строку, она генерирует мою синусоидальную волну, но также создает много шума при обработке выходных данных в Audacity или SoX.

Однако файл журнала, содержащий данные в моем сгенерированном буфере, считывается как ожидалось, со знаковыми значениями в пределах амплитуды, колеблющимися во времени (сэмплы) относительно указанной частоты, без неожиданных значений или шума…

Это может навести меня на мысль, что что-то не так с частотой дискретизации или какой-либо другой настройкой (порядковый номер, моно / стерео, тип данных и т.д.), Но, как я уже говорил ранее, у прямоугольной волны таких проблем нет. Также я позаботился о том, чтобы все вычисления выполнялись с использованием типа с плавающей запятой двойной точности, чтобы я знал, что целочисленное принуждение не является моей проблемой. Я в тупике. Приветствуется любая помощь или понимание.

Вот что у меня есть:

 #define pi 3.1415926

int main()
{
    FILE *fer=fopen("log.txt","w");
    double f=440; //freq
    double a=1000; //amplitude
    double p=44100/f; //period

    int16_t *b=malloc(sizeof(int16_t)*44100);
    if(!b)return 1;

    for(int i=0;i<44100;i  )
    {
        double ll=sin( (2.0L*pi/p)*i ) * a;   //SINE WAVE
        // double ll=fmod(i,p)<p/2?a:-a;   //SQUARE WAVE
        b[i]= ll;
        fprintf(fer,"%in",b[i]);
    }

    fwrite(b,sizeof(int16_t),44100,stdout);

    free(b);
    fclose(fer);
}
  

Комментарии:

1. Как выглядит шум, например, в Audacity?

2. Об этом спрашивали раньше, но я не могу его найти. Проблема заключалась в открытии файла в текстовом режиме (по умолчанию), и данные 0x0D были преобразованы, когда это был один байт, скажем, 0x140D 16-битного значения. Откройте файл в двоичном режиме. Я не понимаю, почему вы отправляете двоичные данные в stdout . Предположительно, вы перенаправляете выходные данные. Взгляните на результирующий размер файла, он больше, чем ожидалось?

3. Кроме того, в данных отсутствует смещение нуля. Audacity возражает против этого? Или он ожидает, что 16-разрядные данные будут сосредоточены вокруг 0x8000 ?

4. @WeatherVane Да, вы были совершенно правы по всем пунктам. Использование stdout было просто сокращением CLI для замены фактического управления файлами. Мне никогда не приходило в голову, что stdout это не был двоичный поток. Теперь я чувствую себя глупо. Я полагаю, вы могли бы создать ответ, если хотите, или я могу удалить вопрос, поскольку это дубликат. Кроме того, я не уверен, понимаю ли я второй вопрос. Возможно, Audacity извлекает значение смещения из кодировки (16-разрядная со знаком, 32-разрядная с плавающей запятой и т.д.) — То же самое для SoX

Ответ №1:

Вы отправили двоичный вывод в stdout , который является текстовым потоком, и, предположительно, перенаправляете его в файл. В некоторых операционных системах преобразуется символ новой строки в текстовом потоке. Таким образом, когда видно значение в байтах 0x0A или, возможно, 0x0D , оно преобразуется в другое значение или, возможно, в два значения. Это может быть, например, частью 16-разрядного значения 0x0D00 , и система не знает, что это 16-разрядные значения. Одна из подсказок заключается в том, что результирующий размер файла больше, чем ожидалось.

Решение состоит в том, чтобы открыть файл в двоичном режиме и записать в него данные.

О другом комментарии: базовое значение. Иногда данные должны иметь свой центр (нулевое значение) в 0x8000 , и данные обрабатываются как неподписанные и корректируются проигрывателем. Я заметил, что ваши данные обрабатываются как подписанные данные без смещения нуля.

Это означает, что для вашей амплитуды 1000 данные находятся либо в диапазоне -1000 до 1000 , либо в диапазоне 31768 до 33768 .

Комментарии:

1. Еще раз спасибо. Итак, что касается этого вопроса, я считаю, что SoX и Audacity ведут себя по-разному, хотя бы просто из-за разницы в пользовательском интерфейсе. SoX более гибкий, поскольку он позволяет вводить необработанные аудиоданные в виде 16-битных неподписанных или подписанных, в то время как Audacity (начиная с версии 2.3.0) допускает только 16-битные необработанные аудиоданные со знаком (он допускает 8-битные без знака). В этом случае SoX будет интерпретировать 0x8000 как базовое значение (без знака), и оба будут использовать 0x0000, если они подписаны. Я на самом деле проверил это с обоими, и SoX как бы инвертирует каждую половину подписанного ввода (в беззнаковом режиме). Надеюсь, это было несколько понятно

2. Хм, да, я полагаю, система кодирования может быть обнаружена по отсутствию данных в крайних областях (если они ненасыщены / не обрезаны).