У меня есть два необработанных звуковых потока, которые мне нужно сложить. Для целей этого вопроса мы можем предположить, что они имеют одинаковый битрейт и битовую глубину (скажем, 16-битная выборка, частота дискретизации 44,1 кГц).
Очевидно, что если я просто сложу их вместе, я переполню и опустошу свое 16-битное пространство. Если я сложу их вместе и разделю на два, то громкость каждого уменьшится вдвое, что не правильно с точки зрения звука - если два человека говорят в комнате, их голоса не становятся тише наполовину, и микрофон может их уловить. оба вверх, не задев ограничитель.
-Адам
Я был очень разочарован этим. В реальной жизни я всегда слышу оба сигнала независимо от того, в какой фазе они находятся. Но простое добавление отсчетов двух инвертированных по фазе волн приведет к полная тишина. Ни упоминания об этом ...
@jmendeth Отмена фазы реальна. Поместите два динамика рядом друг с другом и поменяйте фазу с одного (поменяйте местами провода). Ваш бас испорчен. Причина, по которой вы не получаете полной отмены, заключается в том, что ваши динамики не являются точечными источниками и у вас два уха.
Я знаю, я знаю ... тем не менее, когда люди слышат «микширование звука», они не ожидают, что два звука нейтрализуют друг друга в зависимости от фазы, что приведет к тишине.
И я не хочу, чтобы у двух инструментов были отменены частоты в зависимости от "удачи", чтобы они были инвертированы по фазе.





Если вам нужно сделать это правильно, я бы посоветовал взглянуть на реализации программного микшера с открытым исходным кодом, по крайней мере, для теории.
Некоторые ссылки:
На самом деле вам, вероятно, следует использовать библиотеку.
Audacity просто добавит сэмплы, в результате получится клип (если сэмплы будут высокими). Вы должны вручную отрегулировать усиление каждой дорожки, чтобы предотвратить клиппирование.
Я бы сказал, просто сложите их вместе. Если вы переполняете свое 16-битное пространство PCM, то звуки, которые вы используете, уже для начала невероятно громкие, и вам следует их приглушить. Если это приведет к тому, что они сами по себе станут слишком мягкими, поищите другой способ увеличения общей выходной громкости, например настройку ОС или поворот ручки на динамиках.
Я думаю, что до тех пор, пока потоки не коррелированы, вам не о чем беспокоиться, вы сможете обойтись отсечением. Если вас действительно беспокоят искажения в точках отсечения, мягкий лимитер, вероятно, подойдет.
Вы должны сложить их вместе, но обрезать результат до допустимого диапазона, чтобы предотвратить переполнение / потерю значимости.
В случае клиппирования вы будут вносите искажение в звук, но это неизбежно. Вы можете использовать свой код отсечения, чтобы «обнаружить» это условие и сообщить об этом пользователю / оператору (эквивалент красного индикатора «клипа» на микшере ...)
Вы могли бы реализовать более «правильный» компрессор / ограничитель, но, не зная точного приложения, трудно сказать, стоит ли оно того.
Если вы выполняете много обработки звука, вы можете представить свои уровни звука в виде значений с плавающей запятой и вернуться к 16-битному пространству только в конце процесса. Так часто работают высококачественные цифровые аудиосистемы.
Это правильный ответ, но я приукрасил его некоторыми примечаниями о том, как реализовать автоматическое управление уровнем ниже (написано до того, как у меня были права на комментарии).
@Kyberias Это не имеет смысла; первое предложение буквально объясняет, что делать.
OP уже, что предлагает этот ответ и каков недостаток для этого, из вопроса «Очевидно, что если я просто сложу их вместе, я переполну и опустошу мое 16-битное пространство». @ user1881400
Вы правы, складывая их вместе. Вы всегда можете сканировать сумму двух файлов на предмет пиковых точек и масштабировать весь файл вниз, если они достигают какого-то порогового значения (или если среднее значение этого файла и окружающих его пятен достигает порогового значения)
Я согласен с вами, но это не практично для звукового потока, потому что вы не можете посмотреть звук, может быть, подойдет оконная регулировка динамического усиления?
"Вдвое тише" не совсем правильно. Из-за логарифмического отклика уха разделение выборок пополам сделает его тише на 6 дБ - конечно, заметно, но не катастрофично.
Вы можете пойти на компромисс, умножив на 0,75. Это сделает его тише на 3 дБ, но уменьшит вероятность переполнения, а также уменьшит искажения, когда это произойдет.
На 3 дБ тише вдвое уменьшается мощность, поэтому значения выборки делятся на sqrt (2). Это умножение на 0,707 (1 / sqrt (2)), а не на 0,75. Я согласен с тем, что умножение на 0,75 легче добиться с помощью битового сдвига.
@Gauthier, я был приблизительно.
0,707 происходит от 10 ^ (- 3/20) и не имеет ничего общего с 1 / sqrt (2), кроме того, что десятичное расширение разделяет некоторые ведущие цифры (если вы хотите быть точными :)
@JorisWeimar, он абсолютно прав в том, что уменьшение мощности вдвое потребует деления на квадратный корень из 2. Это принято называть -3 дБ, хотя технически это -3,0103 дБ. Опять приближения.
@MarkRansom да, я спорил в вашу пользу. это приближение. но это не имеет ничего общего с sqrt (2).
Но @JorisWeimar имеет отношение все к sqrt (2)! Это значение -3 дБ, которое является приближением к sqrt (2), а не наоборот - я думал, что ясно дал это понять. Мощность пропорциональна квадрату напряжения, поэтому для уменьшения мощности вдвое необходимо уменьшить напряжение (сигнал) на sqrt (2). Это полное совпадение, что это примерно -3 дБ по той же причине, что 2 ^ 10 (1024) очень близко к 10 ^ 3 (1000).
мы говорим об уменьшении амплитуды с помощью коэффициента умножения. Я думал, что можно преобразовать между амплитудой и dbfs по формуле dbfs = 20 * log (амплитуда). или я ошибаюсь?
@JorisWeimar db - это измерение соотношение, в случае dbfs это отношение полная амплитуда к рассматриваемому сигналу. Ваша формула будет абсолютно правильной, если вы примете это во внимание, с коэффициентом умножения. Вот как я получил цифру, которую цитировал выше: 20 * log(1/sqrt(2)) = -3.0103.
Большинство приложений для микширования звука используют числа с плавающей запятой (32 бита достаточно для микширования небольшого количества потоков). Преобразуйте 16-битные отсчеты в числа с плавающей запятой в диапазоне от -1,0 до 1,0, представляющем полную шкалу в 16-битном мире. Затем сложите образцы вместе - теперь у вас есть много места. Наконец, если вы получите какие-либо сэмплы, значение которых выходит за пределы полной шкалы, вы можете либо ослабить весь сигнал, либо использовать жесткое ограничение (ограничение значения до 1.0).
Это даст намного лучший результат звучания, чем сложение 16-битных семплов вместе и их переполнение. Вот очень простой пример кода, показывающий, как можно суммировать два 16-битных отсчета вместе:
short sample1 = ...;
short sample2 = ...;
float samplef1 = sample1 / 32768.0f;
float samplef2 = sample2 / 32768.0f;
float mixed = samplef1 + sample2f;
// reduce the volume a bit:
mixed *= 0.8;
// hard clipping
if (mixed > 1.0f) mixed = 1.0f;
if (mixed < -1.0f) mixed = -1.0f;
short outputSample = (short)(mixed * 32768.0f)
конечно, но это увеличит вероятность обрезки, поэтому отрегулируйте громкость соответствующим образом
Это принесло вам белый шум @MarkHeath?
Умножая микшированный на 0,8 ... разве вы просто не приближаете уровень шума к «среднему»? Если вы умножите отрицательное значение для смешанного (скажем -0,5) на 0,8, оно приблизится к 0, другими словами, оно станет ВЫШЕ ... так что либо вам нужно преобразовать в диапазон 0+ перед умножением, либо комментарии «немного уменьшить громкость» - это не совсем точно.
Есть статья о смешивании здесь. Мне было бы интересно узнать, что другие думают по этому поводу.
Это интересно. Обычно он выполняет сложение, а затем применяет очень простое «сжатие» сигнала, чтобы избежать клиппирования. Проблема в том, что это значительно изменит значения выборки, даже если нет необходимости обрезать. Для некоторых приложений (например, для телефонии, игр) такой подход, вероятно, подойдет. Но для высококачественной обработки звука это можно рассматривать как ухудшающее качество сигнала ...
Эта статья вводит в заблуждение (см. Мой ответ ниже). Если вы введете примерные значения в его окончательные формулы, вы получите плохие результаты (его алгебра плохая). Например. вход тишины дает вам -1 выход. В любом случае он не масштабируется более чем на два входа, и это алгоритм вуду, не имеющий реальной основы.
Неразумно изменять объем для каждого образца. И алгоритм не правильный, потому что, если у вас есть два канала с одним и тем же сигналом, микширование этих двух каналов должно совпадать с каждым из них. Но этот алгоритм дает сигнал потери.
Эта статья совершенно неверна, как многие предполагали. Пожалуйста, перестаньте голосовать, вы только вводите людей в заблуждение.
преобразовать образцы в значения с плавающей запятой в диапазоне от -1,0 до +1,0, затем:
out = (s1 + s2) - (s1 * s2);
Думаю, мне придется разобраться с этим. Кажется, что это может быть подходящим, но если входы 1 и -1, результат будет 1. Не уверен, хочу ли я вырвать лаплас для этого, но если у вас есть ссылки с дополнительной информацией о том, почему и как это работает , Буду признателен за фору,
Также обратите внимание, что в статье указаны входные значения от 0 до 1.
Вы также можете купить себе запас места с помощью такого алгоритма, как y = 1,1x - 0,2x ^ 3 для кривой и с ограничением сверху и снизу. Я использовал это в Гексафон, когда игрок играет несколько нот вместе (до 6).
float waveshape_distort( float in ) {
if (in <= -1.25f) {
return -0.984375;
} else if (in >= 1.25f) {
return 0.984375;
} else {
return 1.1f * in - 0.2f * in * in * in;
}
}
Он не пуленепробиваемый, но позволит вам подняться до уровня 1,25 и сглаживает клип до приятного изгиба. Создает гармоническое искажение, которое звучит лучше, чем клиппинг, и может быть желательным при некоторых обстоятельствах.
Пробовал это, и это сработало. Хорошее быстрое решение для обрезки.
Кроме того, в этом ответе подразумевается, что вы должны преобразовать в float перед смешиванием.
Выглядит интригующе. Откуда у тебя эти волшебные константы? (в частности, 1,25 и 0,984375?)
1,25 - это потолок, который я был готов принять (уровень 125%). 0,984375 - значение y для x = 1,25 в указанной формуле I.
Для справки: это сжатие (и небольшое расширение).
Я бы предпочел прокомментировать один из двух высоко оцененных ответов, но из-за моей скудной репутации (полагаю) я не могу.
Отмеченный ответ: сложите вместе, и клип будет правильным, но не в том случае, если вы хотите избежать отсечения.
Ответ со ссылкой начинается с работающего алгоритма вуду для двух положительных сигналов в [0,1], но затем применяется некоторая очень ошибочная алгебра, чтобы получить совершенно неверный алгоритм для значений со знаком и 8-битных значений. Алгоритм также не масштабируется до трех или более входов (произведение сигналов будет уменьшаться, а сумма увеличивается).
Итак - преобразуйте входные сигналы в плавающие, масштабируйте их до [0,1] (например, 16-битное значение со знаком станет
float v = ( s + 32767.0 ) / 65536.0 (close enough...))
, а затем просуммируйте их.
Чтобы масштабировать входные сигналы, вам, вероятно, следует проделать некоторую реальную работу, а не умножать или вычитать значение вуду. Я бы посоветовал сохранить текущую среднюю громкость, а затем, если она начнет дрейфовать до высокого (скажем, выше 0,25) или низкого (скажем, ниже 0,01), начните применять значение масштабирования в зависимости от громкости. По сути, это становится реализацией автоматического уровня и масштабируется с любым количеством входов. Лучше всего то, что в большинстве случаев он вообще не испортит ваш сигнал.
Спасибо за заметки! Я думаю, это заслуживает ответа, но теперь у вас есть 50 представителей, так что вы можете комментировать сайт прямо сейчас.
Поскольку в вашем профиле указано, что вы работаете во встроенных системах, я предполагаю, что операции с плавающей запятой не всегда возможны.
> So what's the correct method to add these sounds together in my software mixer?
Как вы уже догадались, добавление и отсечение - правильный путь, если вы не хотите терять громкость источников. Для сэмплов int16_t необходимо, чтобы сумма была int32_t, а затем ограничить и преобразовать обратно в int16_t.
> Am I wrong and the correct method is to lower the volume of each by half?
Да. Уменьшение громкости вдвое - это несколько субъективно, но то, что вы можете видеть здесь и там, - это уменьшение громкости (громкости) вдвое - это уменьшение примерно на 10 дБ (деление мощности на 10 или значений выборки на 3,16). Но вы, очевидно, имеете в виду снизить примерные значения вдвое. Это уменьшение на 6 дБ, заметное уменьшение, но не такое большое, как уменьшение громкости вдвое (очень полезна таблица громкости там).
С помощью этого снижения на 6 дБ вы избежите любого клиппирования. Но что происходит, когда вам нужно больше входных каналов? Для четырех каналов вам нужно будет разделить входные значения на 4, что снизится на 12 дБ и, таким образом, станет меньше половины громкости для каждого канала.
> Do I need to add a compressor/limiter or some other processing stage to
get the volume and mixing effect I'm trying for?
Вы хотите микшировать, а не обрезать, и не терять громкость входных сигналов. Это невозможно без каких-то искажений.
Как было предложено Марком Рэнсомом, решение, позволяющее избежать отсечения, не теряя при этом до 6 дБ на канал, состоит в том, чтобы попасть где-то посередине между «добавлением и отсечением» и «усреднением».
Это для двух источников: сложение, деление где-то между 1 и 2 (уменьшите диапазон от [-65536, 65534] до меньшего), затем ограничение.
Если вы часто используете этот раствор, и он звучит слишком резко, то вы можете смягчить предельное колено с помощью компрессора. Это немного сложнее, так как вам нужно сделать коэффициент деления зависимым от входной мощности. Сначала попробуйте использовать только ограничитель, а компрессор следует рассматривать только в том случае, если результат вас не устраивает.
Я не могу поверить, что никто не знает правильного ответа. Все достаточно близки, но все же чистая философия. Ближайшим, т.е. лучшим было: (s1 + s2) - (s1 * s2). Это отличный подход, особенно для микроконтроллеров.
Итак, алгоритм таков:
factor = average(s1)
Вы предполагаете, что оба сигнала уже в порядке, не переполняется 32767.0s1 = (s1/max(s1))*factors2 = (s2/max(s2))*factoroutput = ((s1+s2)/max(s1+s2))*factorОбратите внимание, что после шага 1. вам действительно не нужно возвращаться к целым числам, вы можете работать с числами с плавающей запятой в интервале от -1,0 до 1,0 и применять возврат к целым числам в конце с ранее выбранным коэффициентом мощности. Надеюсь, я не ошибся сейчас, потому что я очень тороплюсь.
Это не верно. Например. считайте, что s1 и s2 равны 0,5, s1 + s2 => 1, max (s1, s2) равно 0,5, поэтому на выходе будет 2. Вы прошли путь отсечения, и наивное добавление не имело бы. Кроме того, 0,25 и 0,25 дают тот же результат.
Однажды я сделал это так: я использовал числа с плавающей запятой (выборки от -1 до 1) и инициализировал переменную autoGain значением 1. Затем я складывал все образцы вместе (также могло быть больше 2). Тогда я бы умножил исходящий сигнал на autoGain. Если абсолютное значение суммы сигналов до умножения будет больше 1, я бы назначил 1 / это значение суммы. Это фактически сделало бы автоматическое усиление меньше 1, скажем 0,7, и было бы эквивалентно тому, что какой-нибудь оператор быстро уменьшит основную громкость, как только увидит, что общий звук становится слишком громким. Затем в течение регулируемого периода времени я бы добавил к автоусилению, пока оно, наконец, не вернулось к «1» (наш оператор оправился от удара и медленно увеличивает громкость :-)).
// #include <algorithm>
// short ileft, nleft; ...
// short iright, nright; ...
// Mix
float hiL = ileft + nleft;
float hiR = iright + nright;
// Clipping
short left = std::max(-32768.0f, std::min(hiL, 32767.0f));
short right = std::max(-32768.0f, std::min(hiR, 32767.0f));
Спасибо всем за то, что поделились своими идеями, в последнее время я также занимаюсь микшированием звука. Я тоже поэкспериментировал с этим вопросом, ребята, может это вам поможет :).
Обратите внимание, что я использую частоту дискретизации 8 кГц и образец звука 16 бит (SInt16) в ios RemoteIO AudioUnit.
Во время моих экспериментов лучший результат, который я нашел, отличался от всего этого ответа, но основной тот же (как предлагает Родди)
«Вы должны сложить их вместе, но обрезать результат до допустимого диапазона, чтобы предотвратить переполнение / потерю значимости.».
Но каким должен быть лучший способ добавления без переполнения / потери значимости?
Ключевая идея :: У вас есть две звуковые волны, например A и B, и результирующая волна C будет суперпозиция из двух волн A и B. Сэмпл в ограниченном битовом диапазоне может вызвать его переполнение. Итак, теперь мы можем вычислить пересечение максимального лимита на верхней стороне и пересечение минимального лимита на нижней стороне формы волны суперпозиции. Теперь мы вычтем пересечение максимального верхнего предела из верхней части формы волны суперпозиции и добавим пересечение минимального нижнего лимита к нижней части формы волны суперпозиции. ВОЙЛА ... все готово.
Шаги:
следующий код покажет реализацию.
static unsigned long upSideDownValue = 0;
static unsigned long downSideUpValue = 0;
#define SINT16_MIN -32768
#define SINT16_MAX 32767
SInt16* mixTwoVoice (SInt16* RecordedVoiceData, SInt16* RealTimeData, SInt16 *OutputData, unsigned int dataLength){
unsigned long tempDownUpSideValue = 0;
unsigned long tempUpSideDownValue = 0;
//calibrate maker loop
for(unsigned int i=0;i<dataLength ; i++)
{
SInt32 summedValue = RecordedVoiceData[i] + RealTimeData[i];
if (SINT16_MIN < summedValue && summedValue < SINT16_MAX)
{
//the value is within range -- good boy
}
else
{
//nasty calibration needed
unsigned long tempCalibrateValue;
tempCalibrateValue = ABS(summedValue) - SINT16_MIN; // here an optimization comes ;)
if (summedValue < 0)
{
//check the downside -- to calibrate
if (tempDownUpSideValue < tempCalibrateValue)
tempDownUpSideValue = tempCalibrateValue;
}
else
{
//check the upside ---- to calibrate
if (tempUpSideDownValue < tempCalibrateValue)
tempUpSideDownValue = tempCalibrateValue;
}
}
}
//here we need some function which will gradually set the value
downSideUpValue = tempUpSideDownValue;
upSideDownValue = tempUpSideDownValue;
//real mixer loop
for(unsigned int i=0;i<dataLength;i++)
{
SInt32 summedValue = RecordedVoiceData[i] + RealTimeData[i];
if (summedValue < 0)
{
OutputData[i] = summedValue + downSideUpValue;
}
else if (summedValue > 0)
{
OutputData[i] = summedValue - upSideDownValue;
}
else
{
OutputData[i] = summedValue;
}
}
return OutputData;
}
у меня он работает нормально, позже я намерен постепенно изменить значение upSideDownValue & downSideUpValue, чтобы получить более плавный вывод.
насколько я пытался использовать значения 4 pcm из отдельных источников, для меня это было нормально. Больше не пробовал.
convert the samples to floating point values ranging from -1.0 to +1.0, then:
out = (s1 + s2) - (s1 * s2);
Будет вносить сильные искажения, когда | s1 + s2 | подход 1.0 (по крайней мере, когда я пробовал при смешивании простых синусоид). Я прочитал эту рекомендацию в нескольких местах, но, по моему скромному мнению, это бесполезный подход.
Что происходит физически, когда волны «смешиваются», так это то, что их усилители складываются, как уже было предложено на многих плакатах. Либо
Я сделал следующее:
MAX_VAL = Full 8 or 16 or whatever value
dst_val = your base audio sample
src_val = sample to add to base
Res = (((MAX_VAL - dst_val) * src_val) / MAX_VAL) + dst_val
Умножьте левый запас src на нормализованное целевое значение MAX_VAL и добавьте его. Он никогда не будет клипировать, никогда не будет менее громким и абсолютно естественным.
Пример:
250.5882 = (((255 - 180) * 240) / 255) + 180
И это неплохо звучит :)
Можете ли вы дать объяснение, используя, возможно, четыре примера, в которых каждый из dst и src имеет высокое значение и низкое значение, поэтому легко понять, что делает этот алгоритм и почему?
Я нашел новый способ добавлять образцы таким образом, чтобы они никогда не превышали заданный диапазон. Основная идея состоит в том, чтобы преобразовать значения в диапазоне от -1 до 1 в диапазон примерно от -Infinity до + Infinity, сложить все вместе и отменить первоначальное преобразование. Я придумал для этого следующие формулы:
Я попробовал это, и он действительно работает, но для нескольких громких звуков результирующий звук звучит хуже, чем просто сложение сэмплов и обрезка каждого слишком большого значения. Я использовал следующий код, чтобы проверить это:
#include <math.h>
#include <stdio.h>
#include <float.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include <sndfile.h>
// fabs wasn't accurate enough
long double ldabs(long double x){
return x < 0 ? -x : x;
}
// -Inf<input<+Inf, -1<=output<=+1
long double infiniteToFinite( long double sample ){
// if the input value was too big, we'll just map it to -1 or 1
if ( isinf(sample) )
return sample < 0 ? -1. : 1.;
long double ret = sample / ( ldabs(sample) + 1 );
// Just in case of calculation errors
if ( isnan(ret) )
ret = sample < 0 ? -1. : 1.;
if ( ret < -1. )
ret = -1.;
if ( ret > 1. )
ret = 1.;
return ret;
}
// -1<=input<=+1, -Inf<output<+Inf
long double finiteToInfinite( long double sample ){
// if out of range, clamp to 1 or -1
if ( sample > 1. )
sample = 1.;
if ( sample < -1. )
sample = -1.;
long double res = -( sample / ( ldabs(sample) - 1. ) );
// sample was too close to 1 or -1, return largest long double
if ( isinf(res) )
return sample < 0 ? -LDBL_MAX : LDBL_MAX;
return res;
}
// -1<input<1, -1<=output<=1 | Try to avoid input values too close to 1 or -1
long double addSamples( size_t count, long double sample[] ){
long double sum = 0;
while( count-- ){
sum += finiteToInfinite( sample[count] );
if ( isinf(sum) )
sum = sum < 0 ? -LDBL_MAX : LDBL_MAX;
}
return infiniteToFinite( sum );
}
#define BUFFER_LEN 256
int main( int argc, char* argv[] ){
if ( argc < 3 ){
fprintf(stderr,"Usage: %s output.wav input1.wav [input2.wav...]\n",*argv);
return 1;
}
{
SNDFILE *outfile, *infiles[argc-2];
SF_INFO sfinfo;
SF_INFO sfinfo_tmp;
memset( &sfinfo, 0, sizeof(sfinfo) );
for( int i=0; i<argc-2; i++ ){
memset( &sfinfo_tmp, 0, sizeof(sfinfo_tmp) );
if (!( infiles[i] = sf_open( argv[i+2], SFM_READ, &sfinfo_tmp ) )){
fprintf(stderr,"Could not open file: %s\n",argv[i+2]);
puts(sf_strerror(0));
goto cleanup;
}
printf("Sample rate %d, channel count %d\n",sfinfo_tmp.samplerate,sfinfo_tmp.channels);
if ( i ){
if ( sfinfo_tmp.samplerate != sfinfo.samplerate
|| sfinfo_tmp.channels != sfinfo.channels
){
fprintf(stderr,"Mismatching sample rate or channel count\n");
goto cleanup;
}
}else{
sfinfo = sfinfo_tmp;
}
continue;
cleanup: {
while(i--)
sf_close(infiles[i]);
return 2;
}
}
if (!( outfile = sf_open(argv[1], SFM_WRITE, &sfinfo) )){
fprintf(stderr,"Could not open file: %s\n",argv[1]);
puts(sf_strerror(0));
for( int i=0; i<argc-2; i++ )
sf_close(infiles[i]);
return 3;
}
double inbuffer[argc-2][BUFFER_LEN];
double outbuffer[BUFFER_LEN];
size_t max_read;
do {
max_read = 0;
memset(outbuffer,0,BUFFER_LEN*sizeof(double));
for( int i=0; i<argc-2; i++ ){
memset( inbuffer[i], 0, BUFFER_LEN*sizeof(double) );
size_t read_count = sf_read_double( infiles[i], inbuffer[i], BUFFER_LEN );
if ( read_count > max_read )
max_read = read_count;
}
long double insamples[argc-2];
for( size_t j=0; j<max_read; j++ ){
for( int i=0; i<argc-2; i++ )
insamples[i] = inbuffer[i][j];
outbuffer[j] = addSamples( argc-2, insamples );
}
sf_write_double( outfile, outbuffer, max_read );
} while( max_read );
sf_close(outfile);
for( int i=0; i<argc-2; i++ )
sf_close(infiles[i]);
}
return 0;
}
Если я правильно визуализирую это в голове, все, что вы здесь делаете, в любом случае снижает точность при обрезке, что объясняет, почему это звучит плохо. Ограничение ожидаемого диапазона - это именно то, что есть обрезание.
Этот вопрос старый, но вот действительный метод IMO.
Вы можете выполнить первые 2 шага вместе, но вам понадобится максимум и минимум для нормализации на втором проходе для шагов 3 и 4.
Надеюсь, это кому-то поможет.
Тот же вопрос, но более точные ответы: dsp.stackexchange.com/questions/3581/…