Adblock untuk radio

Penulis artikel ini adalah programmer Polandia Tomek Rekavek, yang mengembangkan proyek Jackrabbit Oak sebagai bagian dari Yayasan Perangkat Lunak Apache untuk Adobe. Artikel ini diterbitkan di blog pribadi penulis pada 24 Februari 2016.

Polish β€œRadio-3” (disebut β€œTroika”) Polandia terkenal dengan musik yang bagus dan presenter yang cerdas. Di sisi lain, ia menderita dari kehadiran unit iklan yang keras dan menjengkelkan dalam siaran, yang biasanya mengiklankan beberapa jenis elektronik atau obat-obatan. Saya hampir selalu mendengarkan Troika di tempat kerja dan di rumah, jadi saya bertanya-tanya: bagaimana cara menghapus iklan? Saya pikir saya berhasil menemukan solusi.

Pemrosesan sinyal digital


Tujuan saya adalah membuat aplikasi yang membisukan iklan. Blok komersial dimulai dan diakhiri dengan jingle, sehingga program harus mengenali suara-suara spesifik ini dan mematikan suara di antara mereka.

Saya tahu bahwa bidang ilmu matematika / komputer ini disebut pemrosesan sinyal digital , tetapi bagi saya DSP selalu terasa ajaib. Nah, peluang bagus untuk belajar sesuatu yang baru. Saya menghabiskan satu atau dua hari untuk mencari tahu mekanisme mana yang digunakan untuk menganalisis aliran audio. Dan pada akhirnya, saya menemukan apa yang saya butuhkan: itu adalah korelasi silang atau korelasi silang (korelasi silang).

Oktaf


Biasanya semua orang mengacu pada implementasi MATLAB. Tapi MATLAB adalah aplikasi mahal yang menyederhanakan pelaksanaan operasi matematika yang kompleks, termasuk DSP. Untungnya, ada alternatif gratis bernama Octave . Tampaknya dalam Octave mudah untuk menjalankan korelasi silang pada dua file audio. Hanya perlu menjalankan perintah berikut:

pkg load signal jingle = wavread('jingle.wav')(:,1); audio = wavread ('audio.wav')(:,1); [R, lag] = xcorr(jingle, audio); plot(R); 

Anda mendapatkan bagan berikut:



Puncak terlihat jelas yang menggambarkan posisi jingle.wav di audio.wav . Yang mengejutkan saya adalah kesederhanaan metode ini: xcorr() melakukan semua pekerjaan, sisa kode hanya untuk membaca file dan menampilkan hasilnya.

Saya ingin mengimplementasikan algoritma yang sama di Java, dan kemudian saya akan memiliki alat yang:

  1. membaca aliran audio dari input standar (misalnya, dari ffmpeg),
  2. menganalisisnya untuk mencari jingle,
  3. mencetak aliran yang sama ke stdout dan / atau menonaktifkannya.

Menggunakan stdin dan stdout akan memungkinkan Anda untuk menghubungkan alat analisis baru ke aplikasi lain yang bertanggung jawab atas penyiaran audio dan pemutaran hasilnya.

Membaca file suara


Hal pertama yang harus dibaca oleh program Java adalah jingle (disimpan sebagai file .wav ) ke dalam sebuah array. Ada beberapa informasi tambahan dalam file seperti header, metadata, dan banyak lagi, tetapi kita hanya perlu suara. Format yang cocok disebut PCM, itu hanya daftar angka yang mewakili suara. Konversi WAV ke PCM dapat ffmpeg:

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

Di sini, setiap sampel disimpan sebagai angka 16-bit dengan urutan byte terbalik (little endian). Di Jawa, angka ini disebut short , dan Anda bisa menggunakan kelas ByteBuffer untuk secara otomatis mengonversi aliran input ke daftar nilai 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 reverse engineering


Untuk mengimplementasikan fungsi xcorr() di Java, saya mempelajari kode sumber Oktaf. Tanpa mengubah hasil akhir, saya bisa mengganti panggilan xcorr () dengan baris berikut - mereka harus ditulis ulang di Jawa:

 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)); 

Ini terlihat menakutkan, tetapi sebagian besar fungsinya adalah operasi sepele dengan array. Korelasi-silang didasarkan pada penerapan transformasi Fourier cepat pada sampel suara.

Transformasi Fourier Cepat


Sebagai orang yang tidak memiliki pengalaman dengan DSP, saya hanya melihat FFT sebagai fungsi yang mengambil array dengan deskripsi sampel suara - dan mengembalikan array dengan bilangan kompleks yang mewakili frekuensi. Pendekatan minimalis ini bekerja dengan baik: Saya meluncurkan implementasi FFT dari paket JTransforms dan mendapatkan hasil yang sama seperti di Octave. Saya pikir ini sebagian kultus kargo , tapi sialnya, itu berhasil!

Menjalankan xcorr di utas


Algoritma di atas mengasumsikan bahwa audio adalah larik tempat kita mencari jingle . Ini tidak sepenuhnya cocok untuk siaran, di mana kami memiliki aliran suara yang berkelanjutan. Untuk menjalankan analisis, saya membuat buffer siklik sedikit lebih lama daripada durasi jingle untuk dikenali. Aliran masuk mengisi buffer, dan segera setelah penuh, uji korelasi silang dijalankan. Jika tidak ada yang ditemukan, maka bagian tertua dari buffer dibuang - dan sekali lagi kami berharap untuk diisi.

Saya bereksperimen sedikit dengan panjang buffer dan mendapatkan hasil terbaik dengan ukuran buffer 1,5 kali ukuran jingle.

Menyatukan semuanya


Mendapatkan aliran dalam format PCM itu mudah. Ini dapat dilakukan dengan menggunakan ffmpeg atas. Perintah di bawah ini mengalihkan aliran ke input java standar, dan kemudian output Got jingle 0 atau Got jingle 1 ketika pola yang sesuai ditemukan dalam stream.

 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 

Versi mandiri


Saya juga menyiapkan versi mandiri sederhana dari penganalisis, yang dengan sendirinya menghubungkan ke aliran Troika (tanpa ffmpeg eksternal) dan mereproduksi hasilnya menggunakan javax.sound . Semuanya cocok menjadi satu file JAR dan berisi antarmuka pengguna dasar dengan tombol Star dan Stop. Itu bisa diunduh di sini . Jika Anda tidak suka menjalankan JAR orang lain di mesin Anda (yang benar-benar benar), maka semua sumber ada di GitHub .



Semuanya sepertinya berfungsi sebagaimana mestinya :)

Pekerjaan selanjutnya


Tujuan utamanya adalah untuk menonaktifkan iklan di tingkat amplifier perangkat keras, menerima sinyal FM "nyata", dan bukan aliran Internet. Ini dijelaskan dalam artikel selanjutnya .

Pembaruan (Juni 2018)


Diskusi di Hacker News
Diskusi tentang Wykop
Diskusi tentang Reddit

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


All Articles