Оригиналът е на полския програмист Томек Рекавек, който работи върху проекта 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. Ще се получи инструмент, който:

  1. Чете аудиопотока от стандартния вход, например с помощта на ffmpeg
  2. Анализира го и намира джинглите
  3. Извежда този аудиопоток към стандартния 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

8
ДОБАВИ КОМЕНТАР

avatar
6 Коментари
2 Отговори на коментарите
5 Последователи
 
Коментарът с най-много реакции
Най-горещият коментар
7 Автори на коментарите
ХиХиМангалатаdjagiКаспармъни Автори на последните коментари
  Абонирай се  
нови стари оценка
Извести ме за
НЕ ВИ ЩЪ РЕКЛАМИТЕ
НЕ ВИ ЩЪ РЕКЛАМИТЕ

Смърт за всички реклами

the professor
the professor

чакаме adblocker и за телевизията…

мъни
мъни

Има! Просто сядам да гледам по-късно и си превъртам рекламите. IPTV!

мъни
мъни

Бойкот за продуктите рекламирани по досаден начин!

Каспар
Каспар

И като изключи рекламата от радиото, какво ще се възпроизвежда през това време?

djagi
djagi

хаха, ами реклама от създателя на приложението, което ти блокира останалите реклами… хитро.

Мангалата
Мангалата

Стигнах до Жава и спрях да чета.

ХиХи
ХиХи

Най-обичам докато вечерям да ми пуснат реклама на дамски превръзки или препарати против миризлива слива по ТВ-то.