上一篇中我们已经了解如何在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>
#defineINBUFSIZE4096
#defineMP3BUFSIZE(int)(1.25*INBUFSIZE)+7200
intencode(char*inPath,char*outPath){
intstatus=0;
lame_global_flags*gfp;
intret_code;
FILE*infp;
FILE*outfp;
short*input_buffer;
intinput_samples;
char*mp3_buffer;
intmp3_bytes;
gfp=lame_init();
if(gfp==NULL){
printf("lame_initfailed/n");
status=-1;
gotoexit;
}
ret_code=lame_init_params(gfp);
if(ret_code<0){
printf("lame_init_paramsreturned%d/n",ret_code);
status=-1;
gotoclose_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;
gotofree_buffers;
}elseif(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:
returnstatus;
}
intmain(intargc,char**argv){
if(argc<3){
printf("usage:lame_testrawinfilemp3outfile/n");
}
encode(argv[1],argv[2]);
return0;
}
#include<stdlib.h>
#include<lame.h>
#defineINBUFSIZE4096
#defineMP3BUFSIZE(int)(1.25*INBUFSIZE)+7200
intencode(char*inPath,char*outPath){
intstatus=0;
lame_global_flags*gfp;
intret_code;
FILE*infp;
FILE*outfp;
short*input_buffer;
intinput_samples;
char*mp3_buffer;
intmp3_bytes;
gfp=lame_init();
if(gfp==NULL){
printf("lame_initfailed/n");
status=-1;
gotoexit;
}
ret_code=lame_init_params(gfp);
if(ret_code<0){
printf("lame_init_paramsreturned%d/n",ret_code);
status=-1;
gotoclose_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;
gotofree_buffers;
}elseif(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:
returnstatus;
}
intmain(intargc,char**argv){
if(argc<3){
printf("usage:lame_testrawinfilemp3outfile/n");
}
encode(argv[1],argv[2]);
return0;
}
编译步骤:
<!--<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>
intencode(char*,char*);
staticPyObject*pylame_encode(PyObject*self,PyObject*args){
intstatus;
char*inPath;
char*outPath;
if(!PyArg_ParseTuple(args,"ss",&inPath,&outPath)){
returnNULL;
}
status=encode(inPath,outPath);
returnPy_BuildValue("i",status);
}
staticPyMethodDefpylame_methods[]={
{"encode",pylame_encode,METH_VARARGS,NULL},
{NULL,NULL,0,NULL}
};
PyMODINIT_FUNCinitpylame(){
Py_InitModule3("pylame",pylame_methods,"ansimplelamemodule.");
}
#include<lame.h>
intencode(char*,char*);
staticPyObject*pylame_encode(PyObject*self,PyObject*args){
intstatus;
char*inPath;
char*outPath;
if(!PyArg_ParseTuple(args,"ss",&inPath,&outPath)){
returnNULL;
}
status=encode(inPath,outPath);
returnPy_BuildValue("i",status);
}
staticPyMethodDefpylame_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/ />-->importpylame
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,打开听听看是否是你想要的歌曲呢,呵呵。。。