Posts RSS Comments RSS 5 Posts and 26 Comments till now

Perancangan Sistem TTS Bahasa Indonesia

Setelah berkenalan dengan sistem TTS (Text-to-Speech), selanjutnya kita akan merancang sebuah sistem TTS bahasa Indonesia. Dalam kasus ini, kita akan membuat sebuah web based TTS.

Pada sistem TTS, seringkali dijumpai kesulitan dalam menentukan jeda pengucapan antar kata dalam sebuah kalimat. Saya mencoba untuk membuat TTS yang menentukan jeda berdasarkan konstituen kalimat. Konstituen kalimat terdiri dari Subjek, Predikat, Objek, Keterangan dan Pelengkap.

Sebagai gambaran, saya akan memberikan contoh

Saya akan pergi ke sekolah akan dibaca saya | akan pergi | ke sekolah

Pada contoh diatas :
saya berperan sebagai subjek,
akan pergi berperan sebagai predikat,
ke sekolah berperan sebagai pelengkap,

Dari pengenalan pada posting sebelumnya, kita sudah tau apa saja yang dibutuhkan. Yaitu pemrosesan bahasa alami untuk bahasa Indonesia dan pemrosesan sinyal digital. Pada kasus ini kita akan menggunakan MBROLA sebagai pemroses sinyal digital. Yang kita harus buat sekarang adalah pemrosesan bahasa alami untuk bahasa Indonesia.

Untuk pemrosesan bahasa alami, kita akan menggunakan  Context Free Grammar (CFG) untuk menentukan grammar atau tata bahasa bahasa indonesia. Sesuai dengan posting mengenai Context Free Grammar kita akan menggunakan Lemon Parser Generator sebagai pembangkit parser.

Sebelum melangkah pada parser, kita juga membutuhkan lexer. Lexer akan melakukan scanning tiap kata dalam kalimat untuk menentukan tipe kata tersebut. Misalnya saja buku akan dideteksi sebagai kata benda, cantik akan dideteksi sebagai kata sifat, dan seterusnya. Hasil keluaran dari lexer, akan menjadi masukan bagi parser.

Parser akan melakukan analisa terhadap tata bahasa dari bahasa indonesia yang selanjutnya akan digunakan untuk mencari Subjek, Predikat, Objek, Keterangan, dan atau Pelengkap dari sebuah kalimat. Hasil parsing dari kalimat akan digunakan sebagai penentu jeda pengucapan kalimat tersebut seperti contoh di awal posting ini.

Setelah mendapatkan hasil analisa dari parser yang menunjukkan masing-masing konstituen kalimat, maka selanjutnya kita membutuhkan pembangkit kode fonetik. Pembangkit ini akan menentukan kode fonetik masing-masing huruf di dalam sebuah kata, dan kemudian memberikan jeda antar konstituen kalimat. (ingat kembali daftar kode fonetik bahasa Indonesia)

Sebagai contoh, kalimat aku akan pergi ke sekolah akan mempunyai kode fonetik sebagai berikut:

_ 100
V 90 25 135 50 113 25 200
k 80 0 133
U 90 25 135 50 113 25 200
_ 200
V 90 25 135 50 113 25 200
k 80 0 133
V 90 25 135 50 113 25 200
n 90 25 135 50 113 25 200
_ 50
p 80 0 133
@ 90 25 135 50 113 25 200
r 80 0 133
g 90 25 135 50 113 25 200
I 80 0 133
_ 200
k 90 25 135 50 113 25 200
@ 90 25 135 50 113 25 200
_ 50
s 80 0 133
@ 90 25 135 50 113 25 200
k 80 0 133
Q 90 25 135 50 113 25 200
l 80 0 133
V 90 25 135 50 113 25 200
h 80 0 133
_ 500

Pada contoh kode fonetik diatas, dapat dilihat jeda antar kata dalam kalimat adalah 50ms dan jeda antar konstituen kalimat adalah 200ms. Deretan angka setelah kode fonetik adalah informasi pitch. Bisa dibaca lebih lanjut di sini.

Kita akan beralih ke pemrosesan sinyal digital. Berbekal kode fonetik, kita akan membangkitkan suara menggunakan MBROLA. Untuk penggunaannya dapat dibaca dokumentasinya di sini.

Sehingga flowchart sistem secara keseluruhan dapat dilihat pada gambar dibawah ini:

Flowchart Sistem

Pada flowchart di atas, saya menggunakan lame untuk melakukan konversi ke MP3. MBROLA secara default membangkitkan berkas suara format WAV. Format MP3 saya pilih karena lebih mudah untuk dibagi, dan lebih kecil ukuran berkasnya

tulisan ini merupakan posting kedua mengenai Text-to-Speech. akan dilanjutkan dalam posting berikutnya

Pengenalan Text-to-Speech System (Sistem Pensintesis Suara)

Tujuan utama dari sebuah sistem text-to-speech adalah membuat komputer dapat membaca dan bersuara dari sebuah input baik yang dimasukkan oleh operator maupun dari input lain, misalnya Optical Character Recognition (OCR).

Sebuah sistem text-to-speech dapat dibagi menjadi dua bagian. Bagian pertama adalah konversi dari teks ke fonem. Bagian pertama ini merupakan pemrosesan bahasa alami. Bagian kedua adalah konversi fonem ke ucapan. Bagian kedua ini merupakan pemrosesan sinyal digital. Gambar dibawah ini adalah gambaran umum dari sebuah sistem text-to-speech.

Gambaran Sistem TTS

Bagian pertama adalah konversi teks ke fonem (pemrosesan bahasa alami). Pada bagian ini, sebuah input teks diperiksa struktur kata-katanya. Proses ini spesifik hanya untuk bahasa tertentu, karena setiap bahasa mempunyai struktur dan grammar sendiri. Walaupun mungkin ada grammar sebuah bahasa yang mirip dengan bahasa lain.  Proses ini menghasilkan keluaran berupa fonem dan informasi yang berkaitan dengan fonem, misalnya durasi dan pitch.

Konverter teks ke fonem memiliki dua fungsi utama. Pertama adalah mengambil kalimat masukan dalam suatu bahasa  tertentu yang berbentuk barisan teks dan mengubah beberapa hal seperti nomor dan tanda ke dalam tulisan sesuai dengan bunyi yang seharusnya, sering disebut dengan normalisasi teks (text normalization). Sebagai contoh: xerox harus diubah menjadi serok, Quran diubah menjadi kur an, 2 buku diubah menjadi dua buku.

Kemudian menentukan kode fonetik (phonetic transcriptions) untuk tiap kata beserta durasi dan nadanya. Kode fonetik adalah kode yang merepresentasikan unit bunyi yang ingin diucapkan. Pengucapan kata atau kalimat pada prinsipnya adalah urutan bunyi atau secara simbolik adalah urutan kode fonem. Contoh kode fonem untuk bahasa Indonesia berdasarkan database yang dibuat oleh Arry Akhmad Arman dapat dilihat di sini. (lihat bagian SAMPA EQUIVALENT)

Bagian yang kedua adalah konversi fonem ke ucapan (pemrosesan sinyal digital). Proses ini juga dikenal dengan sintesis suara. Konverter fonem ke ucapan yang akan menerima masukan kode-kode fonem serta nada dan durasi yang telah dihasilkan oleh bagian sebelumnya. Berdasarkan kode-kode tersebut bagian ini akan menghasilkan bunyi atau sinyal ucapan yang sesuai dengan kalimat yang ingin diucapkan. Ada beberapa alternatif teknik yang dapat digunakan untuk implementasi bagian ini. Salah satu teknik yang digunakan adalah penyambungan diphone.

Pada sistem yang menggunakan teknik penyambungan diphone, sistem harus didukung oleh suatu basis data diphone yang berisi rekaman segmen-segmen ucapan yang berupa diphone. Ucapan dari suatu bahasa dibentuk dari satu set bunyi mungkin berbeda untuk setiap bahasa, oleh karena itu setiap bahasa harus dilengkapi dengan basis data diphone yang berbeda. Contohnya adalah MBROLA

tulisan ini merupakan tulisan awal, akan dilanjutkan dengan posting berikutnya

Context Free Grammar

Context Free Grammar (CFG) adalah sebuah notasi untuk merepresentasikan sintaks bahasa. CFG adalah salah satu tipe bahasa yang ditentukan oleh Noam Chomsky pada tahun 1950.
Komponen-komponen dalam CFG adalah sebagai berikut:

  1. Terminal : simbol dasar yang menjadi pembentuk string. Terminal disebut juga dengan token.
  2. Nonterminal : variabel sintaksis yang menunjukkan kumpulan string.
  3. Start Symbol: dalam sebuah grammar, salah satu nonterminal berperan sebagai start symbol. Dan kumpulan string yang ditunjukkannnya sebagai language.
  4. Production : berfungsi untuk menentukan cara-cara teminal dan nonterminal dapat dikombinasikan untuk membentuk string.Tiap production terdiri atas ebuah nonterminal diikuti tanda panah atau ::= lalu diikuti kombinasi terminal maupun nonterminal.

Dalam posting kali ini, saya akan membahas mengenai context free grammar yang digunakan dalam  Lemon Parser Generator.  Kali ini kita akan membuat sebuah context free grammar dari sebuah kalkulator sederhana:

      program(A) ::= expr(B). { return A;}
      expr(A)    ::= expr(B) MINUS  expr(C).   { A = B - C; }
      expr(A)    ::= expr(B) PLUS  expr(C).   { A = B + C; }
      expr(A)    ::= NUMBER(B). { A = B;}

Dalam code diatas,  start symbol adalah program. Simbol terminal dapat dikenali dari kata yang hurufnya UPPERCASE, sedangkan non terminal hurufnya lowercase. Simbol terminal biasanya didapat dari sebuah Lexer. Setiap production, dilengkapi dengan kode program yang akan dieksekusi apabila program menemukan kondisi yang cocok. Misalnya dalam production:

expr(A) ::= expr(B) MINUS  expr(C).   { A = B - C; }

Ketika program mendeteksi kecocokan, misalnya dengan input: 9 – 8 , maka sistem akan mengurangkan kedua angka tersebut.

SWAP Nilai Dua Buah Variabel

Bagaimana menukar isi dua buah variabel? Hmm… mungkin cara lama dan paling mudah digunakan adalah dengan menggunakan variabel sementara.


    void swap(&x, &y)
    {
        temp = x;
        x = y;
        y = temp;
    }

Ada cara yang lebih singkat kodenya, namun belum tentu lebih cepat. Ini adalah metode menggunakan penambahan dan pengurangan. Namun cara ini hanya berlaku untuk variabel bertipe integer.


    void swap2(&x, &y)
    {
        x = (y += x -= y) - x;
    }

Ada cara lain yakni menggunakan logika XOR, dan mampu untuk digunakan dalam penukaran dua buah variabel yang bukan integer, karena metode ini dilakukan dalam bentuk biner.


    void swap3(&x, &y)
    {
        x ^= y ^= x ^= y;
    }

Penjelasan lebih lanjut mengenai XOR Swap Algoritm bisa di lihat di Wikipedia.

Catatan.
Tanda & pada kode diatas bermakna pass by reference di dunia pemrograman.

Selamat Datang di Code Lovin’ (codelov.in)

Code Lovin’, sebuah padanan kata yang menunjukkan kami menyukai code. Code adalah hidup dan nyawa untuk kami. Kami, Ganda Manurung dan Puji Priyono Triwibowo (deptz),  adalah orang yang menyukai programming.

Dalam weblog ini, kami ingin berbagi mengenai programming. Dengan tagline ‘ we love to hack the code‘, kami ingin berbagi tentang ide, tip/trik, diskusi, dan hal-hal lainnya yang berkaitan dengan programming dan tidak terbatas pada bahasa pemrograman tertentu.