Оригиналът е на полския програмист Томек Рекавек, който работи върху проекта Jackrabbit Oak в рамките на Apache Software Foundation за Adobe. Статията е публикувана в неговия личен блог на 24 февруари 2016 година. Но е интересна и актуална до днес.Полското „Радио-3“, известно и като „Тройката“ предлага хубава музика и има интелигентни водещи. От друга страна, предаването изобилства от шумни и дразнещи рекламни блокове, предлагащи от електроника до лекарства. Томек обича и слуша това радио почти непрекъснато и като програмист, преди време си е задал въпроса, а дали не мога да махна тази реклама? Изглежда че решение има. Цифрова обработка на сигналитеЦелта е да се създаде приложение, което заглушава рекламата в радиопредаванията. Рекламният блок започва и приключва със специални „джингли“, които програмата трябва да разпознае и да изключи звука между тях.  Известно е, че тази област на математиката и информатиката се нарича цифрова обработка на сигналите, но за мнозина DSP е нещо като магия. Но това е и една отлична възможност да се научи нещо ново и полезно. Най-подходящият механизъм за нашия случай е използването на крос-корелация (cross-correlation). OctaveВсички материали посочват реализацията на различните алгоритми в MATLAB. Но MATLAB е едно голямо, тежко и скъпо приложение, което наистина улеснява изпълняването на сложните математически операции, включително и DSP. За щастие, съществува безплатната алтернатива Octave. В Octave съвсем не е сложно да се стартира взаимната корелация на два аудиофайла. Необходими са само следните пет команди: pkg load signal
jingle = wavread('jingle.wav')(:,1);
audio = wavread ('audio.wav')(:,1);
[R, lag] = xcorr(jingle, audio);
plot(R);Получава се и следната диаграма: 
Добре се вижда пика, показващ мястото на jingle.wav в audio.wav. Всичко става съвсем лесно: цялата работа върши функцията xcorr(). Останалият код служи за четене на файловете и показване на резултата. Сега остава същият алгоритъм да се реализира на Java. Ще се получи инструмент, който: Чете аудиопотока от стандартния вход, например с помощта на ffmpegАнализира го и намира джинглитеИзвежда този аудиопоток към стандартния stdout и/или временно го изключваИзползването на stdin и stdout дава възможност за включването на новия анализатор и към други приложения за възпроизвеждане и обработка на звука. Четене на звуковите файловеПървата работа, която трябва да свърши Java програмата е прочитането на джингъла, представен като .wav файл и поставянето му в масив. Във файла има допълнителна информация, като заглавие, метаданни и други. Но на нас ни трябва само звука. Подходящият за тази цел формат е PCM – това е просто списък с числа. Преобразуването на WAV във PCM може да стане с помощта на ffmpeg: ffmpeg -i input.wav -f s16le -acodec pcm_s16le output.rawТук всеки семпъл се съхранява във вид на 16-битово число с обратна наредба на байтове (little endian). В Java е подходящо да се използва типа short. А за автоматичното преобразуване на входния поток в short значения може да се използва класа ByteBuffer: ByteBuffer buf = ByteBuffer.allocate(4);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.put(bytes);
short leftChannel = buf.readShort(); // stereo stream
short rightChannel = buf.readShort();Дизасемблиране на xcorrЗа да се реализира функцията xcorr() на Java е необходимо да се прегледа сорс кода на Octave. Всичко е доста лесно. Ето как изглежда тази функция на Java: N = length(audio);
M = 2 ^ nextpow2(2 * N - 1);
pre = fft(postpad(prepad(jingle(:), length(jingle) + N - 1), M));
post = fft(postpad(audio(:), M));
cor = ifft(pre .* conj(post));
R = real(cor(1:2 * N));Изглежда малко страшно, но това са предимно тривиални операции с масиви. В основата на крос-корелацията е използването на бързото преобразуване на Фурие. Бързото преобразуване на ФуриеБез никакъв опит в DSP е достатъчно да се гледа на FFT като функция, която на входа си приема масива, описващ звуковия откъс и го преобразува в масив с комплексни числа, показващи честотите. Този минималистичен подход работи много добре. Сравнението на този Java алгоритъм с Octave показва едни и същи резултати. А това е предостатъчно. Използването на xcorr в стрийминг предаваниятаПредставеният по-горе алгоритъм предполага, че audio е някакъв масив, в който търсим jingle. Но това не е подходящо за стрийминговите предавания на радиата. За да се анализира подобен поток е достатъчно използването на цикличен буфер с малко по-голям от джингъла размер. Входният поток запълва буфера и след като бъде запълнен се стартира теста за крос-корелацията. Ако нищо не бъда намерено, най-старата част на буфера се премахва. След това той се запълва отново. Експериментите показват, че най-добри резултати се получават когато размерът на буфера е 1,5 пъти по-голям от размера на джингъла. Обединяваме всичко на едно мястоДа се преобразува радио стрийма в PCM формат също не е сложно. Това отново може да стане с помощта на ffmpeg. Показаната по-долу команда прехвърля аудиопотока към стандартния Java вход и след това извежда Got jingle 0 или Got jingle 1, когато в потока бъде открит съответния образец. ffmpeg -loglevel -8
-i http://stream3.polskieradio.pl:8904/;stream
-f s16le -acodec pcm_s16le -
| java -jar target/analyzer-1.0.0-SNAPSHOT-jar-with-dependencies.jar
2
src/test/resources/commercial-start-44.1k.raw 500
src/test/resources/commercial-end-44.1k.raw 700Автономната версияВече е готова несложна автономна версия на анализатора, която самостоятелно се включва към потока на „Тройката“ (без да се използва външен ffmpeg), като резултатът се извежда с помощта на javax.sound. Всичко е събрано само в един JAR и съдържа съвсем базов интерфейс с бутони Start и Stop. Файлът може да бъде изтеглен оттук. А ако не обичате да стартиране на своите устройства чужди jar файлове (което е съвсем правилно), то можете да вземете сорс кодовете от GitHub. 
Изглежда, че всичко работи както трябва. Следващи целиКрайната цел е да се създаде неголямо хардуерно устройство, което може да изключва рекламата от ефирните предавания, а не само от интернет потоците. Това се обяснява в следващата статия. Програмата на Томек Рекавек за блокиране на рекламата в различните аудио потоци, както и хардуерния блокатор на реклами за произволен аудиосигнал, предизвикаха изключителен интерес сред потребителите, който не стихва и до днес. Простотата на алгоритъма и неговата съвсем лесна реализация повдигнаха интересни въпроси относно създаването на подобни блокатори не само за радио, но и за телевизионните предавания. При това не само за блокиране на звука, но и на изображението по време на рекламния блок. Обсъждане на темата в Hacker News Разглеждане на темата във Wykop Обсъждане на темата в Reddit |