Ini adalah versi audio dari tantangan penyandian gambar Twitter .
Rancang format kompresi audio yang dapat mewakili setidaknya satu menit musik dalam 140 byte atau kurang dari teks berkode UTF-8 yang dapat dicetak.
Menerapkannya dengan menulis program baris perintah yang mengambil 3 argumen berikut (setelah nama program itu sendiri):
- String
encode
ataudecode
. - Nama file input.
- Nama file keluaran.
(Jika bahasa pemrograman pilihan Anda tidak memiliki kemampuan untuk menggunakan argumen baris perintah, Anda dapat menggunakan pendekatan alternatif, tetapi harus menjelaskannya dalam jawaban Anda.)
The encode
operasi akan mengkonversi dari format audio Anda memilih untuk dikompresi “Tweet” format Anda, dan decode
operasi akan mengkonversi dari “Tweet” format ke format audio asli. (Tentu saja, Anda diharapkan untuk menerapkan kompresi lossy, sehingga file output tidak harus identik dengan input, hanya dalam format yang sama.)
Sertakan dalam jawaban Anda:
- Kode sumber program Anda, secara penuh. (Jika terlalu lama untuk halaman ini, Anda dapat meng-host-nya di tempat lain dan memposting tautan ke sana.)
- Penjelasan tentang cara kerjanya.
- Setidaknya satu contoh, dengan tautan ke file audio asli, teks "tweet" yang dimampatkan, dan file audio diperoleh dengan mendekode tweet. (Penjawab bertanggung jawab atas pernyataan “penggunaan wajar” hak cipta.)
Aturan
- Saya berhak untuk menutup celah dalam peraturan kontes kapan saja.
- [Diedit 24 April] Untuk input
encode
fungsi Anda (dan outputdecode
fungsi Anda ), Anda dapat menggunakan format audio umum yang masuk akal, apakah itu:- Gelombang terkompresi, seperti WAV.
- Gelombang terkompresi, seperti MP3.
- Gaya "Lembaran musik", seperti MIDI.
- Format "tweet" terkompresi Anda harus benar-benar menyandikan suara dalam file input. Jadi, tipe-tipe output berikut ini tidak masuk hitungan:
- URI atau jalur file yang memberikan lokasi penyimpanan output aktual.
- Kunci ke tabel database di mana output aktual disimpan sebagai gumpalan.
- Ada yang mirip.
- Program Anda harus dirancang untuk mengompres file musik umum , jadi jangan lakukan hal-hal yang terlalu jelas terkait dengan lagu contoh spesifik Anda. Misalnya, jika Anda mendemonstrasikan "Twinkle, Twinkle, Little Star", rutinitas kompresi Anda seharusnya tidak membuat hard-code simbol khusus untuk urutan do-do-so-la-la-so.
- Output program Anda seharusnya benar-benar dapat melalui Twitter dan keluar tanpa cedera. Saya tidak memiliki daftar karakter persis yang didukung, tetapi cobalah untuk tetap berpegang pada huruf, angka, simbol, dan tanda baca; dan menghindari karakter kontrol, menggabungkan karakter, penanda BIDI, atau hal-hal aneh lainnya seperti itu.
- Anda dapat mengirimkan lebih dari satu entri.
Kriteria penilaian
Ini adalah kontes popularitas (yaitu, sebagian besar upvote bersih menang), tetapi pemilih didorong untuk mempertimbangkan hal berikut:
Ketepatan
- Masih bisakah Anda mengenali lagu itu setelah dikompres?
- Apakah itu terdengar bagus?
- Masih bisakah Anda mengenali instrumen yang sedang dimainkan?
- Masih bisakah Anda mengenali liriknya? (Ini mungkin tidak mungkin, tetapi akan mengesankan jika ada yang menyelesaikannya.)
Kompleksitas
Pilihan contoh lagu penting di sini.
- [Ditambahkan 24 April] Tantangan ini akan paling mudah dengan MIDI atau format serupa. Namun, jika Anda melakukan upaya ekstra untuk membuatnya berfungsi dengan format tipe gelombang, itu layak mendapatkan kredit ekstra.
- Apa strukturnya? Tentu, Anda dapat memenuhi persyaratan satu menit dengan hanya mengulangi 4 langkah yang sama beberapa kali secara acak. Tetapi struktur lagu yang lebih kompleks layak mendapat poin lebih banyak.
- Bisakah format menangani banyak catatan yang dimainkan sekaligus?
Kode
- Buatlah sesingkat dan sesederhana mungkin. Namun, ini bukan kode golf, jadi keterbacaan lebih penting daripada jumlah karakter.
- Algoritma yang cerdas dan rumit juga OK, asalkan dibenarkan oleh peningkatan kualitas hasil.
Jawaban:
Scala
Tentu, akan lebih mudah untuk menyandikan file MIDI, tetapi siapa yang punya banyak file MIDI? Ini bukan tahun 1997!
Hal pertama yang pertama: Saya telah memutuskan untuk menafsirkan "byte Unicode" sebagai "Unicode char" dan menggunakan karakter CJK, karena:
Ada beberapa trik yang saya gunakan untuk memeras setiap tetes terakhir entropi dari sumber:
Pertama, musik dibuat dengan catatan. Selain itu, kami umumnya menganggap nada yang sama dalam oktaf berbeda sebagai nada yang sama (itulah sebabnya gitar 12-string terdengar benar), jadi kami hanya memiliki 12 kemungkinan untuk menyandikan. (ketika saya output B, misalnya, saya benar-benar output chord, yang hanya terdiri dari B di semua oktaf, sedikit seperti gitar 12-string).
Selanjutnya, saya ingat dari kelas musik sekolah menengah bahwa kebanyakan transisi nada adalah kecil (naik atau turun satu nada). Lompatan kurang umum. Ini memberitahu kita bahwa mungkin ada lebih sedikit entropi dalam ukuran lompatan daripada di catatan itu sendiri.
Jadi, pendekatan kami adalah memecah sumber kami menjadi sejumlah blok - Saya menemukan 14 blok per detik bekerja dengan baik (catatan, saya selalu bertanya-tanya mengapa audio dikodekan pada 44100 Hz. Ternyata 44100 memiliki banyak faktor, jadi saya bisa memilih 1, 2, 3, 4, 5, 6, 7, 9, 10, 12, 14, 15, 18, 20, 21, 25, 28 atau 30 blok per detik, dan itu akan dibagi dengan bersih ). Kami kemudian FFT blok ini (baik, secara teknis tidak cepat, karena perpustakaan yang saya gunakan tidak cepat untuk non-power-of-2 blok. Dan secara teknis saya menggunakan transformasi Hartley , bukan Fourier).
Kami kemudian menemukan catatan yang terdengar paling keras (saya menggunakan A-weighting , dengan cut-off tinggi dan rendah, sebagian besar karena paling mudah untuk diterapkan), dan menyandikan catatan ini, atau menyandikan diam (pendeteksian diam didasarkan pada SNR - SNR rendah diam).
Kami kemudian menerjemahkan catatan kami yang dikodekan ke dalam lompatan, dan memberi mereka ke kode aritmatika adaptif. Proses penerjemahan ke teks mirip dengan pertanyaan kompresi gambar (tetapi melibatkan beberapa penggunaan BigInteger yang kasar).
Sejauh ini, sangat bagus, tetapi bagaimana jika sampel memiliki terlalu banyak entropi? Kami menggunakan model psikoakustik kasar untuk menghapus beberapa. Lompatan entropi terendah adalah "tidak ada perubahan", jadi kami melihat data FFT kami untuk mencoba menemukan blok di mana pendengar mungkin tidak akan melihat jika kami terus memutar catatan sebelumnya, dengan mencari blok di mana catatan dari blok sebelumnya adalah hampir sekeras not paling keras (di mana "hampir" dikendalikan oleh parameter kualitas).
Jadi, kami punya target 140 karakter. Kami mulai dengan penyandian pada kualitas 1.0 (kualitas maks), dan melihat berapa banyak karakter yang ada. Jika terlalu banyak, kita turun menjadi 0,95 dan mengulang, sampai kita mencapai 140 karakter (atau kita menyerah setelah kualitas 0,05). Ini membuat encoder menjadi n-pass encoder, untuk n <= 20 (meskipun secara besar-besaran juga tidak efisien, jadi m'eh).
Encoder / decoder mengharapkan audio dalam format mono s16be. Ini dapat dicapai dengan menggunakan avconv sebagai:
Untuk menjalankan encoder:
Kode lengkap di https://github.com/jamespic/twelvestring .
Pitfall yang perlu diperhatikan: Anda perlu pustaka Aritmatika Pengkodean nayuki, yang saat ini tidak memiliki artefak Maven. Alih-alih, Anda harus membuat dan menginstal fork forster secara lokal .
Dan ini beberapa contoh. Kedengarannya mengerikan, tetapi hanya bisa dikenali:
Memperbarui
Saya mengubah ambang keheningan dalam kode, dan menyandikan ulang. Pengkodean telah diperbarui sesuai. Juga, saya menambahkan lagu lain (secara teknis bukan open source, tapi saya ragu pemegang hak cipta asli akan merasa IP mereka di bawah ancaman), hanya untuk bersenang-senang:
Lebih Banyak Pembaruan
Saya telah sedikit mengubah encoder, dan ini berdampak mengejutkan pada kualitas (saya lupa bahwa di DHT, sinyal out-of-phase efektif negatif, jadi saya mengabaikan sinyal out-of-phase).
Versi sebelumnya dari kode hanya mengambil yang lebih besar dari sinyal-sinyal di luar fase ini, tetapi kami sekarang mengambil RMS. Juga, saya menambahkan fungsi jendela yang cukup konservatif ke encoder (Tukey, alpha 0,3), untuk mencoba memerangi artefak.
Semuanya diperbarui sesuai.
sumber
BitOutputStream::close
metode yang saya lupa menelepon. Saya akan memperbaiki kode dan memperbarui hasilnya.Python
Saya tidak melakukan mangling khusus sehubungan dengan UTF-8, jadi kiriman saya melewati persyaratan 140 byte. Saya tidak membuat klaim tentang kegunaan, keakuratan, atau efisiensi solusi saya.
Saya menggunakan sample rate 44100 Hz untuk input dan output. SAMPLES_PER_BYTE mengontrol kualitas konversi. Semakin rendah angkanya, semakin baik kualitas suaranya. Nilai yang saya gunakan diberikan di bagian hasil.
Pemakaian
Menyandi
File input harus berupa wav. Ini hanya mengkodekan saluran pertama.
Membaca sandi
Memutar Musik yang Didekodekan
Kode
Input
Kiriman resmi saya adalah Impromptu untuk Pianoforte dan Beatbox oleh Kevin MacLeod . Untuk file ini saya menggunakan SAMPLES_PER_BYTE dari 25450.
Saya juga mengambil kebebasan menyandikan Twinkle, Twinkle, Little Star dengan SAMPLES_PER_BYTE dari 10200. Kedengarannya jauh lebih baik.
Hasil
Dadakan untuk Pianoforte dan Beatbox
Link
Twinkle, Twinkle Little Star
Link
sumber