Adblock للراديو

مؤلف المقالة هو المبرمج البولندي توميك ريكافيك ، الذي يقوم بتطوير مشروع Jackrabbit Oak كجزء من مؤسسة Apache Software Foundation لـ Adobe. نُشر المقال على المدونة الشخصية للمؤلف في 24 فبراير 2016.

تشتهر "Radio-3" البولندية (ما يسمى "Troika") بالموسيقى الجيدة والعروض الذكية. من ناحية أخرى ، يعاني من وجود وحدات إعلانية صاخبة ومزعجة في البث ، والتي عادة ما تعلن عن نوع من الإلكترونيات أو الأدوية. أستمع إلى Troika بشكل دائم تقريبًا في العمل والمنزل ، لذلك تساءلت: كيف يمكنني إزالة الإعلانات؟ أعتقد أنني تمكنت من إيجاد حل.

معالجة الإشارات الرقمية


هدفي هو إنشاء تطبيق يكتم الإعلانات. تبدأ الكتلة التجارية وتنتهي بالأناشيد ، لذلك يجب على البرنامج التعرف على هذه الأصوات المحددة وإيقاف الصوت بينهما.

أعلم أن هذا المجال من الرياضيات / علوم الكمبيوتر يسمى معالجة الإشارات الرقمية ، لكن DSP بدا لي دائمًا السحر. حسنًا ، فرصة رائعة لتعلم شيء جديد. أمضيت يومًا أو يومين أحاول معرفة الآلية التي أستخدمها لتحليل الدفق الصوتي. وفي النهاية ، وجدت ما أحتاج إليه: إنه الارتباط المتبادل أو الارتباط المتبادل (الارتباط المتبادل).

ثماني


عادة ما يشير الجميع إلى تنفيذ 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() بكل العمل ، أما باقي الكود فهو فقط لقراءة الملفات وعرض النتيجة.

كنت أرغب في تنفيذ نفس الخوارزمية في جافا ، وبعد ذلك سيكون لدي أداة:

  1. يقرأ دفق الصوت من الإدخال القياسي (على سبيل المثال ، من ffmpeg) ،
  2. يحللها بحثًا عن الأناشيد ،
  3. يطبع نفس الدفق لتثبيته و / أو تعطيله.

سيسمح لك استخدام stdin و stdout بتوصيل المحلل الجديد بالتطبيقات الأخرى المسؤولة عن البث الصوتي وتشغيل النتيجة.

قراءة الملفات الصوتية


أول شيء يجب أن يقرأه برنامج Java هو جلجل (يتم حفظه كملف .wav ) في صفيف. هناك بعض المعلومات الإضافية في الملف مثل الرؤوس والبيانات الوصفية والمزيد ، ولكننا بحاجة إلى الصوت فقط. يسمى التنسيق المناسب PCM ، وهي مجرد قائمة بأرقام تمثل الأصوات. يمكن تحويل WAV إلى PCM ffmpeg:

 ffmpeg -i input.wav -f s16le -acodec pcm_s16le output.raw 

هنا ، يتم حفظ كل عينة كرقم 16 بت بترتيب بايت عكسي (نهاية صغيرة). في Java ، يُطلق على هذا الرقم اسم short ، ويمكنك استخدام فئة ByteBuffer لتحويل دفق الإدخال تلقائيًا إلى قائمة من القيم short :

 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. بدون تغيير النتيجة النهائية ، تمكنت من استبدال استدعاء xcorr () بالخطوط التالية - يجب إعادة كتابتها في 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 كدالة تأخذ مصفوفة مع وصف لعينة صوتية - وترجع مصفوفة بأرقام معقدة تمثل الترددات. نجح هذا النهج البسيط بشكل جيد: لقد أطلقت تنفيذ FFT من حزمة JTransforms وحصلت على نفس النتائج كما في 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 

نسخة قائمة بذاتها


قمت أيضًا بإعداد نسخة مستقلة بسيطة من المحلل ، والتي تتصل نفسها بدفق Troika (بدون ffmpeg خارجي) javax.sound إنتاج النتيجة باستخدام javax.sound . كل شيء يلائم ملف JAR واحد ويحتوي على واجهة مستخدم أساسية بأزرار Star و Stop. يمكن تنزيله هنا . إذا كنت لا تحب تشغيل JARs لأشخاص آخرين على جهازك (وهذا صحيح تمامًا) ، فإن جميع المصادر موجودة على GitHub .



يبدو أن كل شيء يعمل كما يجب :)

مزيد من العمل


الهدف النهائي هو تعطيل الإعلانات على مستوى مضخم الأجهزة ، وتلقي إشارة FM "حقيقية" ، وليس بعض تدفق الإنترنت. هذا موضح في المقالة التالية .

تحديث (يونيو 2018)


مناقشة في أخبار هاكر
مناقشة على Wykop
مناقشة حول Reddit

Source: https://habr.com/ru/post/ar415469/


All Articles