上一篇中我们已经了解如何在Python程序和C模块之间进行值的相互传递,现在我们来进入实作阶段,看看如何将一个C语言开发的开源mp3编解码库LAME包装为一个Python下可以使用的扩展模块。
首先去http://lame.sourceforge.net/download.php下载LAME的源代码,然后切换到root用户编译源代码,
<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->
./
configure
make
makeinstall
make
makeinstall
安装完成后你可以在/usr/local/include/lame目录下找到lame.h头文件,我们在后面的demo程序中会include它的,下面就是一个非常简单的lame示例程序lame_test.c:


<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->
#include
<
stdio.h
>
#include < stdlib.h >
#include < lame.h >
#define INBUFSIZE4096
#define MP3BUFSIZE(int)(1.25*INBUFSIZE)+7200
int encode( char * inPath, char * outPath){
int status = 0 ;
lame_global_flags * gfp;
int ret_code;
FILE * infp;
FILE * outfp;
short * input_buffer;
int input_samples;
char * mp3_buffer;
int mp3_bytes;
gfp = lame_init();
if (gfp == NULL){
printf( " lame_initfailed/n " );
status = - 1 ;
goto exit;
}
ret_code = lame_init_params(gfp);
if (ret_code < 0 ){
printf( " lame_init_paramsreturned%d/n " ,ret_code);
status = - 1 ;
goto close_lame;
}
infp = fopen(inPath, " rb " );
outfp = fopen(outPath, " wb " );
input_buffer = ( short * )malloc(INBUFSIZE * 2 );
mp3_buffer = ( char * )malloc(MP3BUFSIZE);
do {
input_samples = fread(input_buffer, 2 ,INBUFSIZE,infp);
mp3_bytes = lame_encode_buffer_interleaved(gfp,input_buffer,input_samples / 2 ,mp3_buffer,MP3BUFSIZE);
if (mp3_bytes < 0 ){
printf( " lame_encode_buffer_interleavedreturned%d/n " ,mp3_bytes);
status = - 1 ;
goto free_buffers;
} else if (mp3_bytes > 0 ){
fwrite(mp3_buffer, 1 ,mp3_bytes,outfp);
}
} while (input_samples == INBUFSIZE);
mp3_bytes = lame_encode_flush(gfp,mp3_buffer, sizeof (mp3_buffer));
if (mp3_bytes > 0 ){
printf( " writing%dmp3bytes/n " ,mp3_bytes);
fwrite(mp3_buffer, 1 ,mp3_bytes,outfp);
}
free_buffers:
free(mp3_buffer);
free(input_buffer);
fclose(outfp);
fclose(infp);
close_lame:
lame_close(gfp);
exit:
return status;
}
int main( int argc, char ** argv){
if (argc < 3 ){
printf( " usage:lame_testrawinfilemp3outfile/n " );
}
encode(argv[ 1 ],argv[ 2 ]);
return 0 ;
}
#include < stdlib.h >
#include < lame.h >
#define INBUFSIZE4096
#define MP3BUFSIZE(int)(1.25*INBUFSIZE)+7200
int encode( char * inPath, char * outPath){
int status = 0 ;
lame_global_flags * gfp;
int ret_code;
FILE * infp;
FILE * outfp;
short * input_buffer;
int input_samples;
char * mp3_buffer;
int mp3_bytes;
gfp = lame_init();
if (gfp == NULL){
printf( " lame_initfailed/n " );
status = - 1 ;
goto exit;
}
ret_code = lame_init_params(gfp);
if (ret_code < 0 ){
printf( " lame_init_paramsreturned%d/n " ,ret_code);
status = - 1 ;
goto close_lame;
}
infp = fopen(inPath, " rb " );
outfp = fopen(outPath, " wb " );
input_buffer = ( short * )malloc(INBUFSIZE * 2 );
mp3_buffer = ( char * )malloc(MP3BUFSIZE);
do {
input_samples = fread(input_buffer, 2 ,INBUFSIZE,infp);
mp3_bytes = lame_encode_buffer_interleaved(gfp,input_buffer,input_samples / 2 ,mp3_buffer,MP3BUFSIZE);
if (mp3_bytes < 0 ){
printf( " lame_encode_buffer_interleavedreturned%d/n " ,mp3_bytes);
status = - 1 ;
goto free_buffers;
} else if (mp3_bytes > 0 ){
fwrite(mp3_buffer, 1 ,mp3_bytes,outfp);
}
} while (input_samples == INBUFSIZE);
mp3_bytes = lame_encode_flush(gfp,mp3_buffer, sizeof (mp3_buffer));
if (mp3_bytes > 0 ){
printf( " writing%dmp3bytes/n " ,mp3_bytes);
fwrite(mp3_buffer, 1 ,mp3_bytes,outfp);
}
free_buffers:
free(mp3_buffer);
free(input_buffer);
fclose(outfp);
fclose(infp);
close_lame:
lame_close(gfp);
exit:
return status;
}
int main( int argc, char ** argv){
if (argc < 3 ){
printf( " usage:lame_testrawinfilemp3outfile/n " );
}
encode(argv[ 1 ],argv[ 2 ]);
return 0 ;
}
编译步骤:
<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->
gcc-I
/
usr
/
local
/
include
/
lamelame_test
.
c-lmp3lame-olame_test
试验准备:
首先需要一个test.wav文件,先安装sox来将wav文件转为raw格式的数据:
<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->
sudoapt-getinstallsox
soxtest . wav-trawtest . raw
soxtest . wav-trawtest . raw
然后执行lame_test来对其进行mp3编码:
<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->
./
lame_test
./
test
.
raw
./
test
.
mp3
好了,现在我们要在这个c程序的基础上将其包装为一个Python扩展模块。下面的pylame.c就是简单地调用lame_test.c中定义的encode方法,然后通过它对外部的python程序提高mp3编码的服务


<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->
#include
<
Python.h
>
#include < lame.h >
int encode( char * , char * );
static PyObject * pylame_encode(PyObject * self,PyObject * args){
int status;
char * inPath;
char * outPath;
if ( ! PyArg_ParseTuple(args, " ss " , & inPath, & outPath)){
return NULL;
}
status = encode(inPath,outPath);
return Py_BuildValue( " i " ,status);
}
static PyMethodDefpylame_methods[] = {
{ " encode " ,pylame_encode,METH_VARARGS,NULL},
{NULL,NULL, 0 ,NULL}
};
PyMODINIT_FUNCinitpylame(){
Py_InitModule3( " pylame " ,pylame_methods, " ansimplelamemodule. " );
}
#include < lame.h >
int encode( char * , char * );
static PyObject * pylame_encode(PyObject * self,PyObject * args){
int status;
char * inPath;
char * outPath;
if ( ! PyArg_ParseTuple(args, " ss " , & inPath, & outPath)){
return NULL;
}
status = encode(inPath,outPath);
return Py_BuildValue( " i " ,status);
}
static PyMethodDefpylame_methods[] = {
{ " encode " ,pylame_encode,METH_VARARGS,NULL},
{NULL,NULL, 0 ,NULL}
};
PyMODINIT_FUNCinitpylame(){
Py_InitModule3( " pylame " ,pylame_methods, " ansimplelamemodule. " );
}
模块编译步骤:
<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->
gcc-shared-I
/
usr
/
include
/
python2
.
6
-I
/
usr
/
local
/
include
/
lame
/
pylame
.
clame_test
.
c-lmp3lame-opylame
.
so
ok,现在lame扩展模块已经封装好了,可以到python程序中进行调用了。在pylame.so所在目录下新建一个python文件lame1.py代码如下:
<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->
import
pylame
if __name__ == ' __main__ ' :
inPath = ' ./test.raw '
outPath = ' ./test.mp3 '
pylame.encode(inPath,outPath)
if __name__ == ' __main__ ' :
inPath = ' ./test.raw '
outPath = ' ./test.mp3 '
pylame.encode(inPath,outPath)
编译执行:
<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->
python
./
lame1
.
py
你会发现生成了一个test.mp3,打开听听看是否是你想要的歌曲呢,呵呵。。。