Ucapkan angka dari 0 hingga 9 dengan keras

15

Terinspirasi oleh pertanyaan ini dari electronics.SE , inilah tantangan untuk Anda:

Tulis program atau subrutin yang menggunakan urutan angka desimal (0 hingga 9) dan ucapkan dengan keras, tanpa menggunakan alat sintesis bicara yang ada.

Memasukkan:

Anda dapat meminta digit input disediakan dalam format apa pun yang masuk akal, misalnya sebagai string digit ASCII, array bilangan bulat, angka berkode BCD, dll. Jika solusi Anda adalah program yang dapat dieksekusi, Anda dapat mengambil input tersebut sebagai parameter baris perintah, membacanya dari input standar, atau mendapatkannya dengan cara lain yang masuk akal.

Program Anda harus dapat berbicara setidaknya delapan digit per doa. Anda dapat mengasumsikan bahwa digit pertama bukan nol, kecuali itu satu-satunya digit.

Keluaran:

Program Anda dapat berbicara angka-angka secara langsung menggunakan perangkat audio, atau dapat menghasilkan file suara yang dapat diputar. File output, jika ada, mungkin dalam format audio standar apa pun, atau mungkin terdiri dari data sampel mentah. Jika Anda menampilkan data sampel mentah, harap perhatikan parameter yang sesuai untuk pemutaran (laju sampel, bit per sampel, endianness, bertanda / tidak ditandai, # saluran). Format yang didukung oleh aplay lebih disukai.

Anda bebas untuk memutuskan rincian tentang bagaimana angka-angka akan diucapkan, tetapi output Anda harus terdiri dari angka bahasa Inggris yang diucapkan dengan cara yang dapat dimengerti oleh penutur bahasa Inggris yang khas , dan itu harus cukup jelas bagi pendengar untuk dapat secara akurat menyalin nomor acak delapan digit yang diucapkan. Tidak, hanya berbunyi n kali dan tidak masuk hitungan. Jangan lupa untuk memasukkan jeda di antara digit.

Mencetak:

Aturan penilaian standar berlaku: Skor Anda adalah panjang kode Anda dalam byte atau, jika kode Anda ditulis dalam teks Unicode, dalam karakter Unicode. Skor terendah menang. Bahasa apa saja.

Karena pertanyaan awal tentang elektronik. SE adalah tentang pemrograman tertanam, saya merasa akan lebih tepat untuk melemparkan tulang ke penulis menggunakan bahasa tingkat rendah: jika solusi Anda ditulis dalam bahasa yang dikompilasi, Anda dapat memilih untuk menghitung panjang mengkompilasi file yang dapat dieksekusi dalam byte sebagai skor Anda. (Ya, bytecode yang dikompilasi, seperti .classfile Java , juga OK.) Jika Anda memilih untuk menggunakan opsi ini, harap sertakan salinan dari executable yang dikompilasi dalam jawaban Anda (misalnya sebagai dump hex) bersama dengan kode sumber Anda dan versi kompiler dan opsi yang Anda gunakan untuk menghasilkannya.

Sebuah menyebutkan terhormat , bersama dengan karunia 50 rep, akan diberikan kepada jawaban pertama yang juga memenuhi kriteria dari pertanyaan awal , yaitu mampu berjalan pada MCU tertanam dengan 4 kb flash dan 1 kb dari SRAM.

Pembatasan:

Anda tidak boleh menggunakan file atau sumber daya jaringan apa pun yang bukan bagian dari lingkungan runtime standar bahasa yang Anda pilih, kecuali jika Anda menghitung panjang file atau sumber daya yang disebutkan sebagai bagian dari skor Anda. (Ini untuk melarang mis. Memuat sampel audio dari web.)

Anda juga tidak boleh menggunakan alat sintesis pidato atau pustaka atau kompilasi data audio yang sudah ada sebelumnya (kecuali Anda juga menghitung ukurannya sebagai bagian dari skor Anda), bahkan jika mereka termasuk dalam lingkungan runtime standar bahasa yang Anda pilih.

Ilmari Karonen
sumber
Ps. Saya mungkin memposting solusi saya sendiri nanti, jika saya berhasil membuatnya menghasilkan sesuatu yang benar-benar terdengar dimengerti. Namun, jangan malu untuk memposting sendiri; pada titik ini, jawaban apa pun adalah jawaban yang baik.
Ilmari Karonen
1
Apakah kita diperbolehkan mengunduh basis data angka yang diucapkan (dan menghitung ukurannya terhadap skor) atau kita harus merekam suara kita sendiri? Saya ragu saya dapat menghasilkan sampel pidato secara algoritmik.
John Dvorak
umm ... bagian "output" tidak menentukan kita harus menampilkan sampel pidato. Apakah kita boleh berbunyi bip sepuluh kali saja?
John Dvorak
@PeterTaylor: Jika Anda menghitung ukurannya sebagai bagian dari skor Anda, tidak masalah. Saya hanya khawatir bahwa mungkin ada beberapa sistem di luar sana yang memiliki sampel audio angka yang terkubur di suatu tempat di lingkungan runtime standarnya.
Ilmari Karonen
3
Karena tampaknya ada aliran orang yang tidak membaca pertanyaan sampai akhir dan membungkus pembungkus sepele di sekitar perpustakaan kelas berat, mungkin perlu diedit untuk lebih menekankan pada aspek "Lakukan sendiri".
Peter Taylor

Jawaban:

10

ruby - 3710 = 90 karakter kode + 3620 byte data

require'zlib'
$><<$*[0].chars.map{|x|Zlib::Inflate.inflate File.open(x).read}.join(?0*5e3)

input: argumen baris perintah tunggal, nomor yang harus dibaca

output: data suara mentah, PCM 8bit / 8kHz

Ini dapat membaca string input apa saja, selama

  • hanya berisi karakter yang merupakan nama file yang valid. hanya untuk empat karakter, Anda dapat memperbesar set ke semua karakter.
  • Anda memiliki file yang diperlukan.
  • kenapa oh kamu space dee oh en apostrophe tee space em i en dee space tee aitch i es period

5e3mengkodekan jeda antara dua kata. Di sini, 5 contoh ~ = 0,6s. Tweak sesuai keinginan.

Sekarang, bagian yang sulit adalah untuk mendapatkan file sampel dalam 4K dan belum dapat mendekompresnya dengan mudah dan dalam kualitas yang cukup. Inilah cara saya mendapatkannya:

  • Ambil mesin Text-to-speech yang dapat menghasilkan file suara. Wikipedia punya satu .
  • Berikan teks yang berisi semua digit, idealnya saling berdekatan. Saya menggunakan http://en.wikipedia.org/wiki/Base_13
  • Downsample.
  • Gunting setiap bagian dalam editor suara .
  • Simpan sebagai file mentah.
  • Hancurkan setiap sampel (buang bit pesanan rendah).
  • Menurunkan.

Sekarang, kita harus memilih tingkat sampel dan jumlah penipisan. Terlalu banyak, dan suaranya tidak akan bisa dimengerti. Terlalu sedikit, dan Anda tidak cocok. Saya telah membayar 8kHz / 3b. Itu mereka: https://github.com/honnza/drops/raw/master/digits.zip

  • 8KHz * 4b / sampel dan kualitas lebih tinggi - terlalu besar
  • 8KHz * 3b / sampel - kualitas rendah, tetapi cocok menjadi 4K
  • 8KHz * 2b / sampel - kch kchhhhhhhhh [tidak bisa dimengerti]
  • 2KHz * 8b / sampel - terlalu besar
  • 2KHz * 3b / sampel - kch kchhhhhhhhh
  • 1KHz * 8b / sampel - kch kchhhhhhhhh

Berikut skrip penipisan:

require'zlib'
Dir.glob "*.raw" do |fname|
  File.open fname[/\d/], "wb" do |out|
    File.open fname do |input|
      bytes = input.bytes.to_a
      bytes.map! {|x|x&0xE0}
      dfl = Zlib::Deflate.deflate(bytes.pack("C*"),9)
      dfl.each_byte do |byte|
        out.print byte.chr
      end
      puts "done #{fname}: #{dfl.size}"
    end
  end
end

Adapun tantangan aslinya: ada 476 byte ruang untuk kode dan tabel file. Ini mungkin sedikit terlalu tergantung pada seberapa kecil kita bisa dapatkan dengan perpustakaan DEFLATE. Jika perlu, kita dapat memotong beberapa sudut di sana-sini dengan memotong sampel audio sedikit lebih agresif. [fo:r]atau [o:]tidak terlalu penting tetapi menghemat byte. Saya agak baik hati ketika memotong angka. Juga, skema penipisan yang berbeda atau mengorbankan penipisan untuk downsampling mungkin membantu - saya akan mempermainkannya nanti. Juga, menjatuhkan header DEFLATE mungkin menghemat sedikit ruang.

Menggabungkan sampel suara cukup mudah, tetapi 4K sedikit sempit. Jika Anda tidak terikat oleh ruang 4k, saya sarankan mengurangi penipisan. 4 bit per sampel sebenarnya tarifnya cukup baik dan hanya sedikit lebih besar.

John Dvorak
sumber
+1, tidak buruk. Kejelasannya cukup marjinal, meskipun: Saya mencoba menyalin beberapa angka acak dan mendapat tingkat keberhasilan sekitar 70%. (Saya berharap untuk sesuatu yang lebih dekat ke 99%.) Saya juga masih sedikit di pagar tentang hal menyebutkan terhormat: sementara Anda telah membuat argumen yang cukup baik bahwa 4K dapat dicapai dengan cara ini, Anda belum sebenarnya menunjukkannya. Bahkan jika Anda membuang ruby ​​untuk C (yang tampaknya cukup mudah untuk dilakukan; Saya akan bersedia untuk mengambil bagian itu dengan keyakinan), dapatkah Anda benar - benar memasukkan dekoder DEFLATE di ruang flash yang tersisa? Plus, seperti yang saya perhatikan, kualitas suaranya sangat buruk.
Ilmari Karonen
Ps. Beberapa tips tentang kompresi yang lebih baik: Anda dapat mengisi semua sampel hingga panjang yang tetap dengan null byte (yang seharusnya mengompres dengan baik) dan menggabungkannya menjadi satu file terkompresi, kemudian mendekompres dan mengirisnya. Selain itu, trik KZIP dari jawaban ini dapat memberi Anda kompresi DEFLATE yang lebih baik. Terakhir, coba edit file suara gabungan untuk mengganti fonem yang setara dengan salinan yang tepat.
Ilmari Karonen
baik, sampel suara asli tidak bisa dimengerti baik IMO - downsampling tidak banyak merusaknya. Perpustakaan DEFLATE terkecil yang saya tahu - yang pertama dihubungkan oleh wikipeda - beratnya sekitar 500b. Terus terang, apakah Anda ingin saya port inflater ke perangkat tertentu? Saya mungkin sampai ke sana sebenarnya, tapi saya belum pernah kode untuk ARM sebelumnya.
John Dvorak
Saya cukup terkejut dengan tingkat keberhasilan 70% - Saya menemukan angka-angka itu mudah dimengerti. Digit mana yang paling membingungkan Anda?
John Dvorak
Porting ke Cortex M0 mungkin agak terlalu banyak untuk ditanyakan (walaupun jika Anda bisa melakukan itu, itu akan luar biasa!), Tapi saya pikir biner yang berdiri sendiri (+ file data, jika ada) pas di bawah 4k tampaknya demonstrasi yang masuk akal. (Tidak perlu menautkan libc secara statis untuk file I / O, karena Anda tidak memerlukannya di perangkat yang disematkan, tetapi kode DEFLATE harus dihitung.) Pada dasarnya, sesuatu yang dapat Anda poskan sebagai jawaban untuk pertanyaan awal pada electronics.SE dan dengan yakin mengatakan "jika Anda mengkompilasi ini untuk perangkat Anda, saya yakin itu akan cocok".
Ilmari Karonen