Lame虽然没有ffmpeg强大,但是也可以做一些事情。转码的步骤:

1.(optional) Get the version number of the encoder, if you are interested.

void get_lame_version(char *strbuf, size_tbuflen, const char *prefix);

2.Error messages.  By default, LAME willwrite error messages to stderrusing vfprintf().  For GUI applications,this is often a problem and you need to set your own error message handlers:

lame_set_errorf(gfp,error_handler_function);

lame_set_debugf(gfp,error_handler_function);

lame_set_msgf(gfp,error_handler_function);

3.Initialize the encoder.  sets default forall encoder parameters.初始化编码器,设置默认参数

#include "lame.h"

lame_global_flags *gfp;//在lame.h中typedeflame_global_flags *lame_t;

gfp = lame_init();

默认是 44.1khz、128kbps,音质是5,需要的时候设置自己的参数覆盖默认

lame_set_num_channels(gfp,2);/* 默认也是2 */

lame_set_in_samplerate(gfp,44100); /* 采样率 */

lame_set_brate(gfp,128); /* 比特率 */

lame_set_mode(gfp,1); /* mode = 0,1,2,3 = stereo,jstereo,dualchannel(not supported),mono default */

lame_set_quality(gfp,2); /* 2=high 5 = medium 7=low */

4. 检查配置确保返回值ret_code>= 0

ret_code = lame_init_params(gfp);

5  编码: 缓冲区mp3buffer_size大小可以通过 num_samples,samplerate和 encoding rate计算, 最坏的估计是

mp3buffer_size(in bytes) = 1.25*num_samples + 7200.其中num_samples = the number of PCMsamples in each channel.

返回的数字code = 输出到mp3buffer缓冲的大小(number of bytesoutput in mp3buffer),可以为0,但是小于0就出错了

int lame_encode_buffer(lame_global_flags*gfp,

short intleftpcm[],

short int rightpcm[],

int num_samples,

char *mp3buffer,

int mp3buffer_size);

5  调用lame_encode_flush刷新缓冲区,可能返回最后的mp3帧数(return a finalfew mp3 frames).  mp3buffer缓冲区至少是7200 bytes.

返回值code = number of bytes output to mp3buffer.  This can be 0.

int lame_encode_flush(lame_global_flags*,char *mp3buffer, int mp3buffer_size);

6  往mp3文件写入Xing VBR/INFO标签

void lame_mp3_tags_fid(lame_global_flags*,FILE* fid);

7  释放资源的结构(free the internal datastructures)

void lame_close(lame_global_flags *);

这些都是从api中提取出来的。下面是原文:

The LAME API

This is the simple interface to the encoding part of libmp3lame.so.The library also contains routines for adding id3 tags and mp3 decoding.  These routines are not fully documented,but you can figure them out by looking at "include/lame.h" and the example frontend encoder/decoder source code in frontend/main.c

All of these steps should be done for every MP3 to be encoded.

=========================================================================

1. (optional) Get the version number of the encoder, if you are interested.   void get_lame_version(char *strbuf, size_t buflen, const char *prefix);

2. Error messages.  By default, LAME will write error messages to stderr using vfprintf().  For GUI applications, this is often a problem and you need to set your own error message handlers:

lame_set_errorf(gfp,error_handler_function);

lame_set_debugf(gfp,error_handler_function);

lame_set_msgf(gfp,error_handler_function);

See lame.h for details.

3. Initialize the encoder.  sets default for all encoder parameters.

#include "lame.h"

lame_global_flags *gfp;

gfp = lame_init();

The default (if you set nothing) is a  J-Stereo, 44.1khz 128kbps CBR mp3 file at quality 5.  Override various default settings  as necessary, for example:

lame_set_num_channels(gfp,2);

lame_set_in_samplerate(gfp,44100);

lame_set_brate(gfp,128);

lame_set_mode(gfp,1);

lame_set_quality(gfp,2); /* 2=high 5 = medium 7=low */

See lame.h for the complete list of options.  Note that there are some lame_set_*() calls not documented in lame.h.  These functions are experimental and for testing only.  They may be removed in the future.

4. Set more internal configuration based on data provided above, as well as checking for problems.  Check that ret_code >= 0.

ret_code = lame_init_params(gfp);

5. Encode some data.  input pcm data, output (maybe) mp3 frames.This routine handles all buffering, resampling and filtering for you.The required mp3buffer_size can be computed from num_samples, samplerate and encoding rate, but here is a worst case estimate:

mp3buffer_size (in bytes) = 1.25*num_samples + 7200.

num_samples = the number of PCM samples in each channel. It is

not the sum of the number of samples in the L and R channels.

The return code = number of bytes output in mp3buffer.  This can be 0.If it is <0, an error occured.

int lame_encode_buffer(lame_global_flags *gfp,

short int leftpcm[], short int rightpcm[],

int num_samples,char *mp3buffer,int mp3buffer_size);

There are also routines for various types of input  (float, long, interleaved, etc).  See lame.h for details.

6. lame_encode_flush will flush the buffers and may return a

final few mp3 frames.  mp3buffer should be at least 7200 bytes.

return code = number of bytes output to mp3buffer.  This can be 0.

int lame_encode_flush(lame_global_flags *,char *mp3buffer, int mp3buffer_size);

7.  Write the Xing VBR/INFO tag to mp3 file.

void lame_mp3_tags_fid(lame_global_flags *,FILE* fid);

This adds a valid mp3 frame which contains information about the bitstream some players may find usefull.  It is used for CBR,ABR and VBR.  The routine will attempt to rewind the output stream to the beginning.  If this is not possible, (for example, you are encoding to stdout) you should specifically disable the tag by calling

lame_set_bWriteVbrTag(gfp,0) in step 3 above, and call lame_mp3_tags_fid() with fid=NULL.  If the rewind fails and the tag was not disabled, the first mp3 frame in the bitstream will be all 0's.

8. free the internal data structures.

void lame_close(lame_global_flags *);

下面是一个小例子:

// java中的jstring, 转化为c的一个字符数组

char* Jstring2CStr(JNIEnv* env, jstring jstr)

{

char* rtn = NULL;

jclass clsstring = (*env)->FindClass(env,"java/lang/String");

jstring strencode = (*env)->NewStringUTF(env,"GB2312");

jmethodID mid = (*env)->GetMethodID(env,clsstring, "getBytes", "(Ljava/lang/String;)[B");

jbyteArray barr= (jbyteArray)(*env)->CallObjectMethod(env,jstr,mid,strencode); // String .getByte("GB2312");

jsize alen = (*env)->GetArrayLength(env,barr);

jbyte* ba = (*env)->GetByteArrayElements(env,barr,JNI_FALSE);

if(alen > 0)

{

rtn = (char*)malloc(alen+1); //new char[alen+1]; "\0"

memcpy(rtn,ba,alen);

rtn[alen]=0;

}

(*env)->ReleaseByteArrayElements(env,barr,ba,0); //释放内存

return rtn;

}

JNIEXPORT jstring JNICALL Java_cn_itcast_lame_LameActivity_getLameVersion

(JNIEnv * env, jobject obj){

return (*env)->NewStringUTF(env,get_lame_version() );

}

JNIEXPORT void JNICALL Java_cn_itcast_lame_LameActivity_convertAudio

(JNIEnv * env , jobject obj , jstring jinputname , jstring joutputname){

char* input = Jstring2CStr(env,jinputname);

char* output = Jstring2CStr(env,joutputname);

LOGI("INPUT FILE NAME %s",input);

LOGI("output FILE NAME %s",output);

//只读形式打开源文件的句柄 ,

FILE* wav = fopen(input,"rb");

//目标文件 ,可写的形式打开目标文件

FILE* mp3 = fopen(output,"wb");

//读到的字节数,和写出的字节数

int read, write;

// 开创两个buffer 存放音频转换的中间数据

short int wav_buffer[8192*2];

unsigned char mp3_buffer[8192];

//初始化lame编码器

lame_t lame = lame_init();

//指定采样率

lame_set_in_samplerate(lame,44100);

//指定编码后文件的声道数 双声道

lame_set_num_samples(lame, 2);

//指定编码方式 是vbr

lame_set_VBR(lame,vbr_default);

lame_init_params(lame);

LOGI("INIT LAME FINISH");

do{

//从wav里面读数据

read = fread(wav_buffer, 2*sizeof(short int), 8192, wav);

if(read==0){

//读到了文件的末尾

write = lame_encode_flush(lame,mp3_buffer,8192);

}else{

write = lame_encode_buffer_interleaved(lame,wav_buffer,read,mp3_buffer,8192);

}

fwrite(mp3_buffer,1,write,mp3);

}while(read!=0);

LOGI("CONVER COMPLETE");

//反初始化编码器

lame_close(lame);

fclose(mp3);

fclose(wav);

}

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐