int main(int argc, char **argv) { twolame_options *encopts = NULL; audioin_t *inputfile = NULL; FILE *outputfile = NULL; short int *pcmaudio = NULL; unsigned int frame_count = 0; unsigned int total_frames = 0; unsigned int frame_len = 0; unsigned int total_bytes = 0; unsigned char *mp2buffer = NULL; int samples_read = 0; int mp2fill_size = 0; int audioReadSize = 0; // Allocate memory for the PCM audio data if ((pcmaudio = (short int *) calloc(AUDIO_BUF_SIZE, sizeof(short int))) == NULL) { fprintf(stderr, "Error: pcmaudio memory allocation failed\n"); exit(ERR_MEM_ALLOC); } // Allocate memory for the encoded MP2 audio data if ((mp2buffer = (unsigned char *) calloc(MP2_BUF_SIZE, sizeof(unsigned char))) == NULL) { fprintf(stderr, "Error: mp2buffer memory allocation failed\n"); exit(ERR_MEM_ALLOC); } // Initialise Encoder Options Structure encopts = twolame_init(); if (encopts == NULL) { fprintf(stderr, "Error: initializing libtwolame encoder failed.\n"); exit(ERR_MEM_ALLOC); } // Get options and parameters from the command line parse_args(argc, argv, encopts); // Display the filenames print_filenames( twolame_get_verbosity(encopts) ); // Open the input file if (use_raw) { // use raw input handler inputfile = open_audioin_raw( inputfilename, &sfinfo, sample_size ); } else { // use libsndfile inputfile = open_audioin_sndfile( inputfilename, &sfinfo ); } // Display input information if (twolame_get_verbosity(encopts)>1) { inputfile->print_info( inputfile ); } // Use information from input file to configure libtwolame twolame_set_num_channels( encopts, sfinfo.channels ); twolame_set_in_samplerate( encopts, sfinfo.samplerate ); // Open the output file outputfile = open_output_file( outputfilename ); // initialise twolame with this set of options if (twolame_init_params( encopts ) != 0) { fprintf(stderr, "Error: configuring libtwolame encoder failed.\n"); exit(ERR_INVALID_PARAM); } // display encoder settings twolame_print_config( encopts ); // Only encode a single frame of mpeg audio ? if (single_frame_mode) audioReadSize = TWOLAME_SAMPLES_PER_FRAME; else audioReadSize = AUDIO_BUF_SIZE; // Calculate the size and number of frames we are going to encode frame_len = twolame_get_framelength( encopts ); if (sfinfo.frames) total_frames = sfinfo.frames / TWOLAME_SAMPLES_PER_FRAME; // Now do the reading/encoding/writing while ((samples_read = inputfile->read( inputfile, pcmaudio, audioReadSize )) > 0) { int bytes_out = 0; // Force byte swapping if requested if (byteswap) { int i; for (i = 0; i<samples_read; i++) { short tmp = pcmaudio[i]; char *src = (char*)&tmp; char *dst = (char*)&pcmaudio[i]; dst[0] = src[1]; dst[1] = src[0]; } } // Calculate the number of samples we have (per channel) samples_read /= sfinfo.channels; // Do swapping of left and right channels if requested if (channelswap && sfinfo.channels == 2) { int i; for(i=0; i<samples_read; i++) { short tmp = pcmaudio[(2*i)]; pcmaudio[(2*i)] = pcmaudio[(2*i)+1]; pcmaudio[(2*i)+1] = tmp; } } // Encode the audio to MP2 mp2fill_size = twolame_encode_buffer_interleaved( encopts, pcmaudio, samples_read, mp2buffer, MP2_BUF_SIZE); // Stop if we don't have any bytes (probably don't have enough audio for a full frame of mpeg audio) if (mp2fill_size==0) break; if (mp2fill_size<0) { fprintf(stderr,"error while encoding audio: %d\n", mp2fill_size); exit(ERR_ENCODING); } // Check that a whole number of frame was written //if (mp2fill_size % frame_len != 0) { // fprintf(stderr,"error while encoding audio: non-whole number of frames written\n"); // exit(ERR_ENCODING); //} // Write the encoded audio out bytes_out = fwrite(mp2buffer, sizeof(unsigned char), mp2fill_size, outputfile); if (bytes_out != mp2fill_size) { perror("error while writing to output file"); exit(ERR_WRITING_OUTPUT); } total_bytes += bytes_out; // Only single frame ? if (single_frame_mode) break; // Display Progress frame_count += (mp2fill_size / frame_len); if (twolame_get_verbosity(encopts)>0) { fprintf(stderr, "\rEncoding frame: %i", frame_count ); if (total_frames) { fprintf(stderr, "/%i (%i%%)", total_frames, (frame_count*100)/total_frames); } fflush(stderr); } } // Was there an error reading the audio? if (inputfile->error_str( inputfile )) { fprintf(stderr, "Error reading from input file: %s\n", inputfile->error_str(inputfile) ); } // // flush any remaining audio. (don't send any new audio data) There // should only ever be a max of 1 frame on a flush. There may be zero // frames if the audio data was an exact multiple of 1152 // mp2fill_size = twolame_encode_flush( encopts, mp2buffer, MP2_BUF_SIZE); if (mp2fill_size>0) { frame_count++; int bytes_out = fwrite(mp2buffer, sizeof(unsigned char), mp2fill_size, outputfile); if (bytes_out<=0) { perror("error while writing to output file"); exit(ERR_WRITING_OUTPUT); } total_bytes += bytes_out; } if (twolame_get_verbosity(encopts)>1) { char* filesize = format_filesize_string( total_bytes ); fprintf(stderr, "\nEncoding Finished.\n"); fprintf(stderr, "Total bytes written: %s.\n",filesize); free(filesize); } // Close input and output streams inputfile->close( inputfile ); fclose( outputfile ); // Close the libtwolame encoder twolame_close(&encopts); // Free up memory free(pcmaudio); free(mp2buffer); return (ERR_NO_ERROR); }
static int OpenEncoder( vlc_object_t *p_this ) { encoder_t *p_enc = (encoder_t *)p_this; encoder_sys_t *p_sys; int i_frequency; if( p_enc->fmt_out.i_codec != VLC_CODEC_MP2 && p_enc->fmt_out.i_codec != VLC_CODEC_MPGA && p_enc->fmt_out.i_codec != VLC_FOURCC( 'm', 'p', '2', 'a' ) && !p_enc->b_force ) { return VLC_EGENERIC; } if( p_enc->fmt_in.audio.i_channels > 2 ) { msg_Err( p_enc, "doesn't support > 2 channels" ); return VLC_EGENERIC; } for ( i_frequency = 0; i_frequency < 6; i_frequency++ ) { if ( p_enc->fmt_out.audio.i_rate == mpa_freq_tab[i_frequency] ) break; } if ( i_frequency == 6 ) { msg_Err( p_enc, "MPEG audio doesn't support frequency=%d", p_enc->fmt_out.audio.i_rate ); return VLC_EGENERIC; } /* Allocate the memory needed to store the decoder's structure */ if( ( p_sys = (encoder_sys_t *)malloc(sizeof(encoder_sys_t)) ) == NULL ) return VLC_ENOMEM; p_enc->p_sys = p_sys; p_enc->fmt_in.i_codec = VLC_CODEC_S16N; p_enc->fmt_out.i_cat = AUDIO_ES; p_enc->fmt_out.i_codec = VLC_CODEC_MPGA; config_ChainParse( p_enc, ENC_CFG_PREFIX, ppsz_enc_options, p_enc->p_cfg ); p_sys->p_twolame = twolame_init(); /* Set options */ twolame_set_in_samplerate( p_sys->p_twolame, p_enc->fmt_out.audio.i_rate ); twolame_set_out_samplerate( p_sys->p_twolame, p_enc->fmt_out.audio.i_rate ); if( var_GetBool( p_enc, ENC_CFG_PREFIX "vbr" ) ) { float f_quality = var_GetFloat( p_enc, ENC_CFG_PREFIX "quality" ); if ( f_quality > 50.0 ) f_quality = 50.0; if ( f_quality < 0.0 ) f_quality = 0.0; twolame_set_VBR( p_sys->p_twolame, 1 ); twolame_set_VBR_q( p_sys->p_twolame, f_quality ); } else { int i; for ( i = 1; i < 14; i++ ) { if ( p_enc->fmt_out.i_bitrate / 1000 <= mpa_bitrate_tab[i_frequency / 3][i] ) break; } if ( p_enc->fmt_out.i_bitrate / 1000 != mpa_bitrate_tab[i_frequency / 3][i] ) { msg_Warn( p_enc, "MPEG audio doesn't support bitrate=%d, using %d", p_enc->fmt_out.i_bitrate, mpa_bitrate_tab[i_frequency / 3][i] * 1000 ); p_enc->fmt_out.i_bitrate = mpa_bitrate_tab[i_frequency / 3][i] * 1000; } twolame_set_bitrate( p_sys->p_twolame, p_enc->fmt_out.i_bitrate / 1000 ); } if ( p_enc->fmt_in.audio.i_channels == 1 ) { twolame_set_num_channels( p_sys->p_twolame, 1 ); twolame_set_mode( p_sys->p_twolame, TWOLAME_MONO ); } else { twolame_set_num_channels( p_sys->p_twolame, 2 ); switch( var_GetInteger( p_enc, ENC_CFG_PREFIX "mode" ) ) { case 1: twolame_set_mode( p_sys->p_twolame, TWOLAME_DUAL_CHANNEL ); break; case 2: twolame_set_mode( p_sys->p_twolame, TWOLAME_JOINT_STEREO ); break; case 0: default: twolame_set_mode( p_sys->p_twolame, TWOLAME_STEREO ); break; } } twolame_set_psymodel( p_sys->p_twolame, var_GetInteger( p_enc, ENC_CFG_PREFIX "psy" ) ); if ( twolame_init_params( p_sys->p_twolame ) ) { msg_Err( p_enc, "twolame initialization failed" ); return -VLC_EGENERIC; } p_enc->pf_encode_audio = Encode; p_sys->i_nb_samples = 0; return VLC_SUCCESS; }
int mpae_init_twolame(audio_encoder_t *encoder) { int mode; mpae_twolame_ctx *ctx = NULL; if(encoder->params.channels == 1) { mp_msg(MSGT_MENCODER, MSGL_INFO, "ae_twolame, 1 audio channel, forcing mono mode\n"); mode = TWOLAME_MONO; } else if(encoder->params.channels == 2) { if(! strcasecmp(param_mode, "dual")) mode = TWOLAME_DUAL_CHANNEL; else if(! strcasecmp(param_mode, "jstereo")) mode = TWOLAME_JOINT_STEREO; else if(! strcasecmp(param_mode, "stereo")) mode = TWOLAME_STEREO; else { mp_msg(MSGT_MENCODER, MSGL_ERR, "ae_twolame, unknown mode %s, exiting\n", param_mode); } } else mp_msg(MSGT_MENCODER, MSGL_ERR, "ae_twolame, Twolame can't encode > 2 channels, exiting\n"); ctx = calloc(1, sizeof(mpae_twolame_ctx)); if(ctx == NULL) { mp_msg(MSGT_MENCODER, MSGL_ERR, "ae_twolame, couldn't alloc a %d bytes context, exiting\n", sizeof(mpae_twolame_ctx)); return 0; } ctx->twolame_ctx = twolame_init(); if(ctx->twolame_ctx == NULL) { mp_msg(MSGT_MENCODER, MSGL_ERR, "ae_twolame, couldn't initial parameters from libtwolame, exiting\n"); free(ctx); return 0; } ctx->vbr = 0; if(twolame_set_num_channels(ctx->twolame_ctx, encoder->params.channels) != 0) return 0; if(twolame_set_mode(ctx->twolame_ctx, mode) != 0) return 0; if(twolame_set_in_samplerate(ctx->twolame_ctx, encoder->params.sample_rate) != 0) return 0; if(twolame_set_out_samplerate(ctx->twolame_ctx, encoder->params.sample_rate) != 0) return 0; if(encoder->params.sample_rate < 32000) twolame_set_version(ctx->twolame_ctx, TWOLAME_MPEG2); else twolame_set_version(ctx->twolame_ctx, TWOLAME_MPEG1); if(twolame_set_psymodel(ctx->twolame_ctx, param_psy) != 0) return 0; if(twolame_set_bitrate(ctx->twolame_ctx, param_bitrate) != 0) return 0; if(param_errprot) if(twolame_set_error_protection(ctx->twolame_ctx, TRUE) != 0) return 0; if(param_vbr != 0) { if(twolame_set_VBR(ctx->twolame_ctx, TRUE) != 0) return 0; if(twolame_set_VBR_q(ctx->twolame_ctx, param_vbr) != 0) return 0; if(twolame_set_padding(ctx->twolame_ctx, FALSE) != 0) return 0; if(param_maxvbr) { if(twolame_set_VBR_max_bitrate_kbps(ctx->twolame_ctx, param_maxvbr) != 0) return 0; } ctx->vbr = 1; } if(twolame_set_verbosity(ctx->twolame_ctx, param_debug) != 0) return 0; if(twolame_init_params(ctx->twolame_ctx) != 0) return 0; encoder->params.bitrate = param_bitrate * 1000; encoder->params.samples_per_frame = 1152; encoder->priv = ctx; encoder->decode_buffer_size = 1152 * 2 * encoder->params.channels; encoder->bind = bind_twolame; encoder->get_frame_size = get_frame_size; encoder->encode = encode_twolame; encoder->close = close_twolame; return 1; }