基于lame对mp3进行分割的简单实现

来源:互联网 发布:端口号和ip地址 编辑:程序博客网 时间:2024/05/29 08:48

基于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,floatend_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<start_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,floatend_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<start_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" <todd.richmond@openwave.com> */

    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_, 0sizeof(nogap_inPath_));

    for (i = 0; i < MAX_NOGAP; ++i) {

        nogap_inPath[i] = &nogap_inPath_[i][0];

    }


    memset(inPath, 0sizeof(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;

}