Code: play.cpp
while (mpg123_read(mh, buffer, buffer_size, &done) == MPG123_OK)
{
ao_play(dev, reinterpret_cast<char*>(buffer), done);
fprintf(stderr, "Frame: %li\n", mpg123_tellframe(mh));
}
//===========reinterpret_cast<char*>(buffer) : digunakan untuk mengkonversikan type buffer unsigned char menjadi char.
cuplikan kode tersebut jika dikompilasi menggunakan mingw gcc akan error, karena gcc tidak mengenal fungsi reinterpret_cast tersebut.
jika diinginkan dapat dicari cara lain untuk melakukan type casting dari unsigned char menjadi char, namun setelah fungsi ao_play() dioprek langsung dari kode sumber libao, maka kita dapat merubah type data char yang digunakan menjadi unsigned char, sehingga tidak perlu melakukan terlalu banyak effort.
berikut ini prosedurnya:
1. extract kode sumber libao (<a href="http://downloads.xiph.org/releases/ao/libao-1.1.0.zip">http://downloads.xiph.org/releases/ao/libao-1.1.0.zip</a>) dan explore kedalam folder src.
2. edit file audio_out.c dengan codeblock dan silahkan cari (ctrl+f) ao_play.
3. didalam fungsi ao_play tersebut lakukan persesuaian type data
int ao_play(ao_device *device, char* output_samples, uint_32 num_bytes)
{
char *playback_buffer;
if (device == NULL)
return 0;
if (device->swap_buffer != NULL) {
int out_bytes = num_bytes*device->output_channels/device->input_channels;
if (_realloc_swap_buffer(device, out_bytes)) {
int i;
int swap = (device->bytewidth>1 &&
device->client_byte_format != device->driver_byte_format);
for(i=0;i<device->output_channels;i++){
int ic = device->inter_permute ? device->inter_permute[i] : i;
if(ic==-1){
_buffer_zero(device->swap_buffer,i,device->bytewidth,device->output_channels,
out_bytes);
}else if(swap){
_buffer_permute_swap(device->swap_buffer,i,device->bytewidth,device->output_channels,
out_bytes, output_samples, ic, device->input_channels);
}else{
_buffer_permute(device->swap_buffer,i,device->bytewidth,device->output_channels,
out_bytes, output_samples, ic, device->input_channels);
}
}
playback_buffer = device->swap_buffer;
num_bytes = out_bytes;
} else
return 0; /* Could not expand swap buffer */
} else
playback_buffer = output_samples;
return device->funcs->play(device, playback_buffer, num_bytes);
}
4. lihat argumen output_samples disana didefinisikan sebagai char* rubahlah menjadi unsigned char* output_samples.
5. lihat deklarasi playback_buffer ia juga didefinisikan sebagai char* rubahlah menjadi unsigned char*.
berikut perubahannya:
int ao_play(ao_device *device, unsigned char* output_samples, uint_32 num_bytes)
{
unsigned char *playback_buffer;
if (device == NULL)
return 0;
if (device->swap_buffer != NULL) {
int out_bytes = num_bytes*device->output_channels/device->input_channels;
if (_realloc_swap_buffer(device, out_bytes)) {
int i;
int swap = (device->bytewidth>1 &&
device->client_byte_format != device->driver_byte_format);
for(i=0;i<device->output_channels;i++){
int ic = device->inter_permute ? device->inter_permute[i] : i;
if(ic==-1){
_buffer_zero(device->swap_buffer,i,device->bytewidth,device->output_channels,
out_bytes);
}else if(swap){
_buffer_permute_swap(device->swap_buffer,i,device->bytewidth,device->output_channels,
out_bytes, output_samples, ic, device->input_channels);
}else{
_buffer_permute(device->swap_buffer,i,device->bytewidth,device->output_channels,
out_bytes, output_samples, ic, device->input_channels);
}
}
playback_buffer = device->swap_buffer;
num_bytes = out_bytes;
} else
return 0; /* Could not expand swap buffer */
} else
playback_buffer = output_samples;
return device->funcs->play(device, playback_buffer, num_bytes);
}
6. Simpan perubahan tersebut, dan silahkan buka folder include, edit file ao/ao.h, lakukan pencarian (ctrl+f) ao_play juga, dan lakukan persesuaian lagi.
int ao_play(ao_device *device, char *output_samples, uint_32 num_bytes);
sesuaikan menjadi:
int ao_play(ao_device *device, unsigned char *output_samples, uint_32 num_bytes);
7. Simpan dan kompilasi ulang library libao tersebut (./configure via msys dan mingw32-make).
8. Jadikan library libao hasil kompilasi menjadi opsi linker yang digunakan oleh codeblok / visual studio.
9. Sedangkan source kode player kita akan menjadi sbb:
#include <mpg123.h>
#include <ao/ao.h>
#include <malloc.h>
#include <stdlib.h>
#include <windows.h>
#define BITS 8
int main(int argc, char *argv[])
{
mpg123_handle *mh;
unsigned char *buffer;
size_t buffer_size;
size_t done;
int err, driver, channels, encoding;
ao_device *dev;
ao_sample_format format;
long rate;
ao_initialize();
driver = ao_default_driver_id();
// ========= inisial library =============
mpg123_init();
mh = mpg123_new(NULL, &err);
buffer_size = mpg123_outblock(mh);
buffer = (unsigned char*)malloc(buffer_size * sizeof(unsigned char));
mpg123_param(mh, MPG123_RESYNC_LIMIT, -1, 0);
char* filename=argv[1];
mpg123_open(mh, filename);
mpg123_getformat(mh, &rate, &channels, &encoding);
// ************************************
format.bits = mpg123_encsize(encoding) * BITS;
format.rate = rate;
format.channels = channels;
format.byte_format = AO_FMT_NATIVE;
format.matrix = 0;
double secs;
dev = ao_open_live(driver, &format, NULL);
while (mpg123_read(mh, buffer, buffer_size, &done) == MPG123_OK)
{
ao_play(dev, buffer, done);
fprintf(stderr, "Frame: %li\n", mpg123_tellframe(mh));
mpg123_position(mh, 0, 0, NULL, NULL, &secs, NULL);
fprintf(stderr,"[%d:%02d] Decoding of %s finished.\n", (int)(secs / 60), ((int)secs) % 60, filename);
}
/* clean up */
free(buffer);
ao_close(dev);
mpg123_close(mh);
mpg123_delete(mh);
mpg123_exit();
ao_shutdown();
return 0;
}
nah kode diatas sudah tidak menggunakan reinterpret_cast<>() lagi, ini dapat dikompilasi oleh mingw gcc.
selamat mencoba...
Tidak ada komentar:
Posting Komentar