Minggu, 11 Januari 2015

Menghitung Time Remaining dan Time Elapsed pada MP3 Player


Tidak terasa, rasa semangat ini ternyata telah berhasil menuntun saya dalam menulis tutorial pembuatan MP3 Player yang ketiga. Mana tepuk tangannya? :v

Jika anda benar-benar paham penjelasan pada kedua tutorial sebelumnya, maka harusnya Anda sudah bisa membayangkan bagaimana membuat program MP3 player dengan beberapa kemampuan dasar, yaitu Play, Pause, Seek dan Stop. Sabar... Sabar... Saya memilih menggunakan interface teks karena banyak hal yang harus saya pertimbangkan. Pemrograman GUI membutuhkan banyak kode, takutnya jika saya membuat tutorial dengan GUI, banyak yang semakin bingung. Banyak istilah dan hal baru yang harus dijelaskan secara detail, dengan konsol error mudah untuk ditampilkan. Tapi tenang saja, saya sudah mencoba mengusahakan tutorial perancangan GUI untuk MP3 player. :D


Tutorial ini akan menyempurnakan materi dari tutorial kedua, tentang seeking. Teknik seeking yang kita gunakan dilakukan berdasarkan durasi, jadi, tentu saja ini penting untuk mengetahui sudah berapa lamakah durasi pemutaran MP3 berlangsung. Dengan mengetahui informasi durasi, user yang menggunakan MP3 player kita dapat melakukan navigasi dengan tepat dan mudah.

Secara sederhana durasi terlewat(time elapsed) dan Durasi tersisa(time remaining) dapat dirumuskan sebagai berikut:

Durasi terlewat = Posisi frame sekarang * Durasi per frame

Durasi tersisa = Total durasi - Durasi terlewat


Dari fungsi di atas, ada 2 hal yang sama sekali belum pernah kita bahas, yaitu cara mengetahui Posisi frame sekarang dan Durasi per frame. Total durasi sudah kita bahas pada tutorial kemarin, jadi pada tutorial ini, implementasinya merupakan pengembangan dari kode sebelumnya.

Pertama-tama kita pelajari bagaimana mengetahui maksud dari yang saya tulis “Posisi frame sekarang”.

Kode yang erat kaitannya dengan proses dekode frame adalah sebagai berikut.
 
while(mpg123_read(handle, buffer, ukuran_buffer, &ukuran_samples) == 0)
{
    ao_play(device, buffer, ukuran_samples);
}


Jika seandainya komputer dapat berbicara, maka yang ia katakan adalah, “libmpg123 membaca dan mendekode frame 0 - 15 lalu menyimpan hasilnya pada buffer; libao membaca buffer tersebut dan mengirimkannya ke audio device, sehingga muncul suara. Berikutnya, libmpg123 membaca dan mendekode frame 16 - 31 lalu menyimpan hasilnya pada buffer; libao membaca buffer tersebut dan mengirimkannya ke audio device, sehingga muncul suara........”. Begitu seterusnya hingga libmpg123 sampai pada frame terakhir. Dari sini kita tahu, semua frame punya nomor indeks/urutan. Inilah yang saya sebut posisi frame.

Libmpg123 menyediakan fungsi API untuk mengetahui posisi frame sekarang/current frame. Yang dikatakan current frame adalah posisi frame tepat setelah frame yang baru saja di dekode. Misalnya mpg123_read() mendekode frame 16-31, maka current frame nya adalah frame 32.

off_t mpg123_tellframe(mpg123_handle *mh);

Fungsi di atas mengambil parameter berupa handle. Hasil pemanggilan fungsi berupa posisi frame sekarang. Lalu, untuk mengetahui durasi per frame, libmpg123 juga telah menyediakan fungsinya..

double mpg123_tpf(mpg123_handle *mh);

Parameter yang diperlukan sama seperti fungsi yang dibahas sebelumnya. Hasil fungsi berupa durasi suara yang berlangsung dari setiap frame yang didekode. Umumnya panjang durasi setiap 1 frame tidak lebih dari 0,1 detik, jadi kita menggunakan variabel pecahan untuk mendapatkan nilai yang tepat.


Kode Sepenuhnya
 Berikut ini adalah source codenya. Tidak beda jauh dengan yang sebelumnya.
#include <mpg123.h>
#include <ao/ao.h>

#define MP3_FILE "/home/irvan/test.mp3"
int main(int argc, char *argv[])
{
    mpg123_handle       *handle;
    ao_sample_format    sample_format;
    ao_device           *device;
    int                    driver_id;
    char               *buffer;
    unsigned int        ukuran_buffer;
    long                rate; //sample rate
    int                    channels;
    int                    encoding;

      
//inisialisasi MPG123
    printf("Komputoo MP3 player\nMemutar %s...\n", MP3_FILE);
    printf("Menyiapkan libmpg123\n");
    mpg123_init();
    handle = mpg123_new(0, 0);
    if(handle == 0)
    {
        printf("Gagal membuat handle baru!\n");
        exit(EXIT_FAILURE);
    }
   
//inisialisasi AO
    printf("Menyiapkan libao\n");
    ao_initialize();
    driver_id = ao_default_driver_id();
    if(driver_id == -1)
    {
        printf("Driver ID tidak diketahui\n");
        exit(EXIT_FAILURE);
    }

//buka mp3
    if(mpg123_open(handle,MP3_FILE) != 0)
    {
        printf("Gagal membuka file!\n");
        exit(EXIT_FAILURE);
    }

//inisialisasi memori buffer untuk menyimpan hasil decode mp3
    ukuran_buffer = mpg123_outblock(handle);
    buffer = (char*) malloc(ukuran_buffer);

//inisialisasi struktur sample_format dari MP3 yang terbuka
    printf("Mengolah informasi MP3...\n");
    mpg123_getformat(handle, &rate, &channels, &encoding);
    sample_format.bits = mpg123_encsize(encoding) * 8;
    sample_format.rate = rate;
    sample_format.channels = channels;
    sample_format.byte_format = AO_FMT_NATIVE;
    sample_format.matrix = 0;
   
//inisialisasi ao sebelum playing
    device = ao_open_live(driver_id, &sample_format, 0);
    if(device == 0)
    {
        printf("ao_open_live error!\n");
        exit(EXIT_FAILURE);
    }

//dapatkan durasi total mp3
    printf("Mencari durasi total...\n");
    off_t    sample_total;
    double    durasi_total;
    sample_total = mpg123_length(handle);
    durasi_total = (double)sample_total / (double)rate;
    printf("- Total sample: %d\n", (int)sample_total);
    printf("- Sample rate: %d\n", (int)rate);
    printf("- Durasi total: %f detik\n", durasi_total);
   
//coba seeking ke 0:20
    //printf("Meloncat ke 0:20\n");
    //off_t frame_baru;
    //frame_baru = mpg123_timeframe(handle, 20);
    //mpg123_seek_frame(handle, frame_baru, SEEK_SET);

//decode dan play mp3
    printf("Memutar MP3...\n");
    off_t posisi_frame;
    double durasi_per_frame;
    double durasi_terlewat;
    double durasi_tersisa;

   
    size_t ukuran_samples;
    while(mpg123_read(handle, buffer, ukuran_buffer, &ukuran_samples) == 0)
    {
        ao_play(device, buffer, ukuran_samples);
        //Cetak time elapsed dan time remaining
        posisi_frame = mpg123_tellframe(handle);
        durasi_per_frame = mpg123_tpf(handle);
        durasi_terlewat = (double)posisi_frame * durasi_per_frame;
        durasi_tersisa = durasi_total - durasi_terlewat;
        printf("Pos. frame: %6d, Dur. lewat: %10f d, Dur. sisa: %10f d\n", (int)posisi_frame, durasi_terlewat, durasi_tersisa);

    }
       
//akhir
    printf("Selesai.\n");
    free(buffer);
    mpg123_close(handle);
    mpg123_delete(handle);
    mpg123_exit();
    ao_close(device);
    ao_shutdown();
   
}



Hasil



Di atas ini merupakan screenshot MP3 yang sedang di play mulai dari Awal. Setelah saya bandingkan dengan durasi yang ditunjukkan oleh MP3 player lain, ternyata durasinya tepat, dan sama persis. Jadi saya yakin, insyaAllah kode ini bebas dari bug :)
Terus ikuti Update blog ini ya, saya akan usahakan tutorial yang terbaik. Heheheh :v
Load disqus comments

0 comments