это работает. Но я хочу создать приложение VOIP и иметь более одного массива. Поэтому, если я разделю свой массив на 2 части, кодирование> декодирование> слияние, это не будет звучать так же, как раньше.
Как я могу получить одинаковый результат в обоих направлениях? Это специальный режим в speex.js для разделения аудиоданных?
На кнопке Исходный вы воспроизводите с verg, а не с decV, оба имеют одинаковое искажение после кодирования-декодирования, хотя в середине объединенного звука есть заметный разрыв. Вы также не зацикливаете все свои массивы должным образом, но я не верю, что исправление этого остановит прерывание звука посередине. Paul S. 05.03.2015
Speex - это кодек с потерями, поэтому выходные данные являются лишь приближением исходной синусоиды.
Ваша синусоидальная частота составляет около 7 кГц, что близко к верхней полосе пропускания кодека 8 кГц и, как таковая, еще более вероятно, что она будет изменена.
То, что выводит кодек, выглядит как гребенка импульсов дираха, которые будут звучать как исходная синусоида, слышимая через телефон, что, безусловно, отличается от оригинала.
См. эту скрипку, где вы можете послушать, что кодек делает из ваших исходных синусоидальных волн, будь то разделенные на половина или нет.
//Generate a continus sinus in 2 arrays
var len = 16384;
var buffer1 = [];
var buffer2 = [];
var buffer = [];
for(var i=0;i<len;i++){
buffer.push(Math.sin(i/10));
if(i < len/2)
buffer1.push(Math.sin(i/10));
else
buffer2.push(Math.sin(i/10));
}
//Encode and decode both arrays seperatly
var en = Codec.encode(buffer1);
var dec1 = Codec.decode(en);
var en = Codec.encode(buffer2);
var dec2 = Codec.decode(en);
//Merge the arrays to 1 output array
var merge = [];
for(var i in dec1)
merge.push(dec1[i]);
for(var i in dec2)
merge.push(dec2[i]);
//encode and decode the whole array
var en = Codec.encode(buffer);
var dec = Codec.decode(en);
//-----------------
//Down under is only for playing the 2 different arrays
//-------------------
var audioCtx = new window.AudioContext || new window.webkitAudioContext;
function play (sound)
{
var audioBuffer = audioCtx.createBuffer(1, sound.length, 44100);
var bufferData = audioBuffer.getChannelData(0);
bufferData.set(sound);
var source = audioCtx.createBufferSource();
source.buffer = audioBuffer;
source.connect(audioCtx.destination);
source.start();
}
$("#o").click(function() { play(dec); });
$("#c1").click(function() { play(dec1); });
$("#c2").click(function() { play(dec2); });
$("#m").click(function() { play(merge); });
Если вы объедините два выхода декодера половинного сигнала, вы услышите дополнительный щелчок из-за резкого перехода от одного сигнала к другому, звучащий в основном как релейная коммутация. Чтобы избежать этого, вам придется сгладить значения вокруг точка слияния двух ваших буферов.
Ответ 2 · рейтинг 4 · Kirill Slatin
Обратите внимание, что Speex - это кодек с потерями. Таким образом, по определению он не может дать такой же результат, как закодированный буфер. Кроме того, он разработан как кодек для голоса. Таким образом, диапазон 1-2 кГц будет наиболее эффективным, так как он рассчитан на определенную форму сигнала. В чем-то ее можно сравнить с технологией JPEG для растровых изображений.
Я немного изменил ваш пример jsfiddle, чтобы вы могли поиграть с разными параметрами и сравнить результаты. Просто предоставить простую синусоиду с неизвестной частотой - неправильный способ проверки кодека. Однако в примере видно разное влияние на исходный сигнал на разных частотах.
Я думаю, вам следует построить пример с записанным голосом и сравнить результаты в этом случае. Это было бы правильнее.
В общем, чтобы понять идею в деталях, вам нужно изучить цифровую обработку сигналов. Я даже не могу дать правильную ссылку, так как это целая наука, и она математически интенсивна. (единственная известная мне подходящая книга для чтения находится на русском). Если кто-нибудь здесь с сильным математическим образованием может поделиться подходящей литературой для этого случая, я был бы признателен.
РЕДАКТИРОВАТЬ: как упоминал Курои Неко, есть проблема с границами буфера. И кажется, что невозможно сохранить состояние декодера, как указано в этом post, потому что библиотека в использование не поддерживает его. Если вы посмотрите на исходный код, вы увидите, что они используют сторонний кодек speex и не предоставляют полный доступ к его функциям. Я думаю, что лучшим подходом было бы найти достойную библиотеку для speex, поддерживающую восстановление состояния, аналогичную этой а>