基于lame对mp3进行分割的简单实现
一、思路:
利用lame编解码功能,在读取帧时检查下时间即可。
二、实现
1. 根据帧数计算时间:
static float
my_lame_get_current_time(const lame_global_flags *gfp,int frames)
{
int full = lame_get_totalframes(gfp);
int fsize = lame_get_framesize(gfp);
int srate = lame_get_out_samplerate(gfp);
float time_in_sec = (float)frames;
time_in_sec *= fsize;
time_in_sec /= srate;
return time_in_sec;
}
2. 检查时间
lame_encoder()负责编码,其流程是读取每一帧并进行编码。
写了个自己的lame_encoder(),加了两个参数start_time,end_time,
static int
my_lame_encoder(lame_global_flags * gf, FILE * outf, int nogap, char *inPath, char *outPath,float start_time,float end_time);
关键代码:
do {
/* read in 'iread' samples */
iread = get_audio(gf, Buffer);
frame_count++;
current_time = my_lame_get_current_time(gf,frame_count);
if( current_time continue; ...
if( current_time>end_time ) break; } while (iread > 0); 3. 时间参数处理 直接修改frontend/main.c,只接受mp3分割的参数。 3.1 参数处理: if( argc != 5 ) { printf( "lamecut 32bits version 0.99\n" "\n" "usage: lamecut infile outfile start_time end_time\n" "\n" "RECOMMENDED:\n" " lame baby.mp3 baby1.mp3 15.605 17.734" "\n" ); exit(0); } strcpy(inPath,argv[1]); strcpy(outPath,argv[2]); sscanf( argv[3], "%f", &start_time); sscanf( argv[4], "%f", &end_time); input_format = sf_mp123; 注意:input_format 需要设为 sf_mp123; 3.2 调用my_lame_encoder,传入时间参数: ret = my_lame_encoder( gf, outf, 0, inPath, outPath, start_time, end_time ); 三、代码 将frontend/main.c 中的main()函数去掉,再把以下代码拷贝到main.c,重新编译。 生成的lame即可用于分割mp3,建议改名为lamecut。 static float my_lame_get_current_time(const lame_global_flags *gfp,int frames) { int fsize = lame_get_framesize(gfp); int srate = lame_get_out_samplerate(gfp); float time_in_sec = (float)frames; time_in_sec *= fsize; time_in_sec /= srate; return time_in_sec; } static int my_lame_encoder(lame_global_flags * gf, FILE * outf, int nogap, char *inPath, char *outPath,float start_time,float end_time) { unsigned char mp3buffer[LAME_MAXMP3BUFFER]; int Buffer[2][1152]; int iread, imp3, owrite, id3v2_size; int frame_count = 0; int frame_total = 0; float current_time = 0.0f; encoder_progress_begin(gf, inPath, outPath); imp3 = lame_get_id3v2_tag(gf, mp3buffer, sizeof(mp3buffer)); if ((size_t)imp3 > sizeof(mp3buffer)) { encoder_progress_end(gf); error_printf("Error writing ID3v2 tag: buffer too small: buffer size=%d ID3v2 size=%d\n" , sizeof(mp3buffer) , imp3 ); return 1; } owrite = (int) fwrite(mp3buffer, 1, imp3, outf); if (owrite != imp3) { encoder_progress_end(gf); error_printf("Error writing ID3v2 tag \n"); return 1; } if (flush_write == 1) { fflush(outf); } id3v2_size = imp3; /* encode until we hit eof */ do { /* read in 'iread' samples */ iread = get_audio(gf, Buffer); frame_count++; current_time = my_lame_get_current_time(gf,frame_count); if( current_time continue; if( current_time>end_time ) break; if (iread >= 0) { encoder_progress(gf); /* encode */ imp3 = lame_encode_buffer_int(gf, Buffer[0], Buffer[1], iread, mp3buffer, sizeof(mp3buffer)); /* was our output buffer big enough? */ if (imp3 < 0) { if (imp3 == -1) error_printf("mp3 buffer is not big enough... \n"); else error_printf("mp3 internal error: error code=%i\n", imp3); return 1; } owrite = (int) fwrite(mp3buffer, 1, imp3, outf); if (owrite != imp3) { error_printf("Error writing mp3 output \n"); return 1; } } if (flush_write == 1) { fflush(outf); } } while (iread > 0); frame_total = lame_get_totalframes(gf); if (nogap) imp3 = lame_encode_flush_nogap(gf, mp3buffer, sizeof(mp3buffer)); /* may return one more mp3 frame */ else imp3 = lame_encode_flush(gf, mp3buffer, sizeof(mp3buffer)); /* may return one more mp3 frame */ if (imp3 < 0) { if (imp3 == -1) error_printf("mp3 buffer is not big enough... \n"); else error_printf("mp3 internal error: error code=%i\n", imp3); return 1; } encoder_progress_end(gf); owrite = (int) fwrite(mp3buffer, 1, imp3, outf); if (owrite != imp3) { error_printf("Error writing mp3 output \n"); return 1; } if (flush_write == 1) { fflush(outf); } imp3 = lame_get_id3v1_tag(gf, mp3buffer, sizeof(mp3buffer)); if ((size_t)imp3 > sizeof(mp3buffer)) { error_printf("Error writing ID3v1 tag: buffer too small: buffer size=%d ID3v1 size=%d\n" , sizeof(mp3buffer) , imp3 ); } else { if (imp3 > 0) { owrite = (int) fwrite(mp3buffer, 1, imp3, outf); if (owrite != imp3) { error_printf("Error writing ID3v1 tag \n"); return 1; } if (flush_write == 1) { fflush(outf); } } } if (silent <= 0) { print_lame_tag_leading_info(gf); } if (fseek(outf, id3v2_size, SEEK_SET) != 0) { error_printf("fatal error: can't update LAME-tag frame!\n"); } else { write_xing_frame(gf, outf); } if (silent <= 0) { print_trailing_info(gf); } return 0; } int main(int argc, char **argv) { int ret; lame_global_flags *gf; char outPath[PATH_MAX + 1]; char inPath[PATH_MAX + 1]; float start_time=0.0f; float end_time=0.0f; /* add variables for encoder delay/padding */ int enc_delay = -1; int enc_padding = -1; /* support for "nogap" encoding of up to 200 .wav files */ #define MAX_NOGAP 200 char nogap_inPath_[MAX_NOGAP][PATH_MAX+1]; char* nogap_inPath[MAX_NOGAP]; int i; FILE *outf; #if macintosh argc = ccommand(&argv); #endif #if 0 /* rh 061207 the following fix seems to be a workaround for a problem in the parent process calling LAME. It would be better to fix the broken application => code disabled. */ #if defined(_WIN32) /* set affinity back to all CPUs. Fix for EAC/lame on SMP systems from "Todd Richmond" <[email protected]> */ typedef BOOL(WINAPI * SPAMFunc) (HANDLE, DWORD_PTR); SPAMFunc func; SYSTEM_INFO si; if ((func = (SPAMFunc) GetProcAddress(GetModuleHandleW(L"KERNEL32.DLL"), "SetProcessAffinityMask")) != NULL) { GetSystemInfo(&si); func(GetCurrentProcess(), si.dwActiveProcessorMask); } #endif #endif #ifdef __EMX__ /* This gives wildcard expansion on Non-POSIX shells with OS/2 */ _wildcard(&argc, &argv); #endif memset(nogap_inPath_, 0, sizeof(nogap_inPath_)); for (i = 0; i < MAX_NOGAP; ++i) { nogap_inPath[i] = &nogap_inPath_[i][0]; } memset(inPath, 0, sizeof(inPath)); frontend_open_console(); /* initialize libmp3lame */ input_format = sf_unknown; if (NULL == (gf = lame_init())) { error_printf("fatal error during initialization\n"); frontend_close_console(); return 1; } lame_set_errorf(gf, &frontend_errorf); lame_set_debugf(gf, &frontend_debugf); lame_set_msgf(gf, &frontend_msgf); #if 0 if (argc <= 1) { usage(stderr, argv[0]); /* no command-line args, print usage, exit */ lame_close(gf); frontend_close_console(); return 1; } #endif /* parse the command line arguments, setting various flags in the * struct 'gf'. If you want to parse your own arguments, * or call libmp3lame from a program which uses a GUI to set arguments, * skip this call and set the values of interest in the gf struct. * (see the file API and lame.h for documentation about these parameters) */ //parse_args_from_string(gf, getenv("LAMEOPT"), inPath, outPath); //ret = parse_args(gf, argc, argv, inPath, outPath, nogap_inPath, &max_nogap); if( argc != 5 ) { printf( "lamecut 32bits version 0.99\n" "\n" "usage: lamecut infile outfile start_time end_time\n" "\n" "RECOMMENDED:\n" " lame baby.mp3 baby1.mp3 15.605 17.734" "\n" ); exit(0); } strcpy(inPath,argv[1]); strcpy(outPath,argv[2]); sscanf( argv[3], "%f", &start_time); sscanf( argv[4], "%f", &end_time); input_format = sf_mp123; if (update_interval < 0.) update_interval = 2.; outf = init_files(gf, inPath, outPath, &enc_delay, &enc_padding); if (outf == NULL) { lame_close(gf); frontend_close_console(); return -1; } /* turn off automatic writing of ID3 tag data into mp3 stream * we have to call it before 'lame_init_params', because that * function would spit out ID3v2 tag data. */ lame_set_write_id3tag_automatic(gf, 0); /* Now that all the options are set, lame needs to analyze them and * set some more internal options and check for problems */ i = lame_init_params(gf); if (i < 0) { if (i == -1) { display_bitrates(stderr); } error_printf("fatal error during initialization\n"); lame_close(gf); frontend_close_console(); return i; } if (silent > 0) { brhist = 0; /* turn off VBR histogram */ } /* * encode a single input file */ brhist_init_package(gf); //ret = lame_encoder(gf, outf, 0, inPath, outPath); ret = my_lame_encoder( gf, outf, 0, inPath, outPath, start_time, end_time ); fclose(outf); /* close the output file */ close_infile(); /* close the input file */ lame_close(gf); frontend_close_console(); return ret; }