Это старо, но я читаю это, так что кто-то другой неизбежно сделает это.
В целом я согласен с nishantmishra относительно использования libsndfile, но этот алгоритм микширования вызовет определенное искажение, если он делает то, что ожидает автор:
outdata[i] = (data[i] + data2[i]) -(data[i])*(data2[i])/65535;
(На самом деле, последний термин добавляет немного шума низкого уровня ... перед прочтением статьи V-Toth я подумал, что это интересная форма смешения),
Предполагая, что это было применено способом, который работает как предполагалось (аудио с плавающей запятой колеблется от -1,0 до 1,0, поэтому деление на 65535 уменьшает произведение на 96 дБ, что делает его неслышимым для 16-битного звука). Если вы действительно хотите реализовать этот метод, то читайте в публикации V Toth о том, как делать это для подписанных данных.
Независимо от того, подписаны вы или нет, вы будете добавлять интермодуляционные искажения (даже если они не очень неприятные, они будут присутствовать). Другими словами, это отлично работает для голоса или звука с низкой скоростью передачи (телефонного), где искажение в канале передачи намного превышает искажение интермодуляции, добавляемое произведением каналов.
Если вы просто обрабатываете два файла, а не делаете это в режиме реального времени (воспроизведение при чтении блоков из файла или потока), вы можете нормализовать оба файла, применить усиление микширования так, чтобы gain1 + gain2 = 1.0 и суммируйте их вместе. Эти проблемы с низким разрешением, как упомянуто V Toth, не представляют большой проблемы с 32-битным плавающим или 64-битным двойным.
Наконец, если вас беспокоит то, что один источник слишком тихий, а другой молчит, вы можете применить компрессор динамического диапазона, сшитый с другим каналом. Другая тактика - применять тот же алгоритм, но к огибающим аудио, а не к отдельным сэмплам:
outEnvelope[i] = (envelope1[i] + envelope2[i]) \
-(envelope1[i])*(envelope2[i]);
outdata[i]=outEnvelope[i]*(data[i] + data2[i]);
Где конверт =
envelope1[i]=sqrt(lowPassFilter(data[i]*data[i]));//moving RMS representation
А частота среза фильтра низких частот составляет порядка 10 Гц, чтобы минимизировать гармонические искажения.
Действительно, я думаю, что все, что вы хотите сделать чаще всего, это отбросить этот последний член и использовать эту строку:
outdata[i] = (data[i] + data2[i]);
Пока сумма channel_gain [] = 1.0, вы получите хороший результат. Код от nishantmishra работает хорошо, потому что последний срок добавления искажений сводится к минимальному уровню шума, поэтому вы также можете сэкономить время ЦП и устранить его.