上一篇中我们已经了解如何在Python程序和C模块之间进行值的相互传递,现在我们来进入实作阶段,看看如何将一个C语言开发的开源mp3编解码库LAME包装为一个Python下可以使用的扩展模块。
首先去http://lame.sourceforge.net/download.php下载LAME的源代码,然后切换到root用户编译源代码,
./
configure
make
make install
make
make install
安装完成后你可以在/usr/local/include/lame目录下找到lame.h头文件,我们在后面的demo程序中会include它的,下面就是一个非常简单的lame示例程序lame_test.c:
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
#include
<
stdio.h
>
#include < stdlib.h >
#include < lame.h >
#define INBUFSIZE 4096
#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_init failed/n " );
status = - 1 ;
goto exit;
}
ret_code = lame_init_params(gfp);
if (ret_code < 0 ) {
printf( " lame_init_params returned %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_interleaved returned %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 %d mp3 bytes/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_test rawinfile mp3outfile/n " );
}
encode(argv[ 1 ], argv[ 2 ]);
return 0 ;
}
#include < stdlib.h >
#include < lame.h >
#define INBUFSIZE 4096
#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_init failed/n " );
status = - 1 ;
goto exit;
}
ret_code = lame_init_params(gfp);
if (ret_code < 0 ) {
printf( " lame_init_params returned %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_interleaved returned %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 %d mp3 bytes/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_test rawinfile mp3outfile/n " );
}
encode(argv[ 1 ], argv[ 2 ]);
return 0 ;
}
编译步骤:
gcc -I
/
usr
/
local
/
include
/
lame lame_test
.
c -lmp3lame -o lame_test
试验准备:
首先需要一个test.wav文件,先安装sox来将wav文件转为raw格式的数据:
sudo apt-get install sox
sox test . wav -t raw test . raw
sox test . wav -t raw test . raw
然后执行lame_test来对其进行mp3编码:
./
lame_test
./
test
.
raw
./
test
.
mp3
好了,现在我们要在这个c程序的基础上将其包装为一个Python扩展模块。下面的pylame.c就是简单地调用lame_test.c中定义的encode方法,然后通过它对外部的python程序提高mp3编码的服务
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
#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 PyMethodDef pylame_methods[] = {
{ " encode " , pylame_encode, METH_VARARGS, NULL},
{NULL, NULL, 0 , NULL}
};
PyMODINIT_FUNC initpylame() {
Py_InitModule3( " pylame " , pylame_methods, " an simple lame module. " );
}
#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 PyMethodDef pylame_methods[] = {
{ " encode " , pylame_encode, METH_VARARGS, NULL},
{NULL, NULL, 0 , NULL}
};
PyMODINIT_FUNC initpylame() {
Py_InitModule3( " pylame " , pylame_methods, " an simple lame module. " );
}
模块编译步骤:
gcc -shared -I
/
usr
/
include
/
python2
.
6
-I
/
usr
/
local
/
include
/
lame
/
pylame
.
c lame_test
.
c -lmp3lame -o pylame
.
so
ok,现在lame扩展模块已经封装好了,可以到python程序中进行调用了。在pylame.so所在目录下新建一个python文件lame1.py代码如下:
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)
编译执行:
python
./
lame1
.
py
你会发现生成了一个test.mp3,打开听听看是否是你想要的歌曲呢,呵呵。。。