#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. Хм, да, я полагаю, система кодирования может быть обнаружена по отсутствию данных в крайних областях (если они ненасыщены / не обрезаны).