static bool twolame_encoder_write(struct encoder *_encoder, const void *data, size_t length, G_GNUC_UNUSED GError **error) { struct twolame_encoder *encoder = (struct twolame_encoder *)_encoder; unsigned num_frames; const int16_t *src = (const int16_t*)data; int bytes_out; assert(encoder->buffer_length == 0); num_frames = length / audio_format_frame_size(&encoder->audio_format); bytes_out = twolame_encode_buffer_interleaved(encoder->options, src, num_frames, encoder->buffer, sizeof(encoder->buffer)); if (bytes_out < 0) { g_set_error(error, twolame_encoder_quark(), 0, "twolame encoder failed"); return false; } encoder->buffer_length = (size_t)bytes_out; return true; }
static int encode_twolame(audio_encoder_t *encoder, uint8_t *dest, void *src, int len, int max_size) { mpae_twolame_ctx *ctx = (mpae_twolame_ctx *)encoder->priv; int ret_size = 0, r2; len /= (2*encoder->params.channels); ret_size = twolame_encode_buffer_interleaved(ctx->twolame_ctx, src, len, dest, max_size); r2 = mp_decode_mp3_header(dest); mp_msg(MSGT_MENCODER, MSGL_DBG2, "\nSIZE: %d, max: %d, r2: %d\n", ret_size, max_size, r2); if(r2 > 0) ret_size = r2; return ret_size; }
static block_t *Encode( encoder_t *p_enc, block_t *p_aout_buf ) { encoder_sys_t *p_sys = p_enc->p_sys; /* FIXME:p_aout_buf is NULL when it's time to flush, does twolame has buffer to flush?*/ if( unlikely( !p_aout_buf ) ) return NULL; int16_t *p_buffer = (int16_t *)p_aout_buf->p_buffer; int i_nb_samples = p_aout_buf->i_nb_samples; block_t *p_chain = NULL; p_sys->i_pts = p_aout_buf->i_pts - (mtime_t)1000000 * (mtime_t)p_sys->i_nb_samples / (mtime_t)p_enc->fmt_out.audio.i_rate; while ( p_sys->i_nb_samples + i_nb_samples >= MPEG_FRAME_SIZE ) { int i_used; block_t *p_block; Bufferize( p_enc, p_buffer, MPEG_FRAME_SIZE - p_sys->i_nb_samples ); i_nb_samples -= MPEG_FRAME_SIZE - p_sys->i_nb_samples; p_buffer += (MPEG_FRAME_SIZE - p_sys->i_nb_samples) * 2; i_used = twolame_encode_buffer_interleaved( p_sys->p_twolame, p_sys->p_buffer, MPEG_FRAME_SIZE, p_sys->p_out_buffer, MAX_CODED_FRAME_SIZE ); p_sys->i_nb_samples = 0; p_block = block_Alloc( i_used ); memcpy( p_block->p_buffer, p_sys->p_out_buffer, i_used ); p_block->i_length = (mtime_t)1000000 * (mtime_t)MPEG_FRAME_SIZE / (mtime_t)p_enc->fmt_out.audio.i_rate; p_block->i_dts = p_block->i_pts = p_sys->i_pts; p_sys->i_pts += p_block->i_length; block_ChainAppend( &p_chain, p_block ); } if ( i_nb_samples ) { Bufferize( p_enc, p_buffer, i_nb_samples ); p_sys->i_nb_samples += i_nb_samples; } return p_chain; }
static block_t *Encode( encoder_t *p_enc, aout_buffer_t *p_aout_buf ) { encoder_sys_t *p_sys = p_enc->p_sys; int16_t *p_buffer = (int16_t *)p_aout_buf->p_buffer; int i_nb_samples = p_aout_buf->i_nb_samples; block_t *p_chain = NULL; p_sys->i_pts = p_aout_buf->start_date - (mtime_t)1000000 * (mtime_t)p_sys->i_nb_samples / (mtime_t)p_enc->fmt_out.audio.i_rate; while ( p_sys->i_nb_samples + i_nb_samples >= MPEG_FRAME_SIZE ) { int i_used; block_t *p_block; Bufferize( p_enc, p_buffer, MPEG_FRAME_SIZE - p_sys->i_nb_samples ); i_nb_samples -= MPEG_FRAME_SIZE - p_sys->i_nb_samples; p_buffer += (MPEG_FRAME_SIZE - p_sys->i_nb_samples) * 2; i_used = twolame_encode_buffer_interleaved( p_sys->p_twolame, p_sys->p_buffer, MPEG_FRAME_SIZE, p_sys->p_out_buffer, MAX_CODED_FRAME_SIZE ); p_sys->i_nb_samples = 0; p_block = block_New( p_enc, i_used ); vlc_memcpy( p_block->p_buffer, p_sys->p_out_buffer, i_used ); p_block->i_length = (mtime_t)1000000 * (mtime_t)MPEG_FRAME_SIZE / (mtime_t)p_enc->fmt_out.audio.i_rate; p_block->i_dts = p_block->i_pts = p_sys->i_pts; p_sys->i_pts += p_block->i_length; block_ChainAppend( &p_chain, p_block ); } if ( i_nb_samples ) { Bufferize( p_enc, p_buffer, i_nb_samples ); p_sys->i_nb_samples += i_nb_samples; } return p_chain; }
/** \fn getPacket */ bool AUDMEncoder_Twolame::encode(uint8_t *dest, uint32_t *len, uint32_t *samples) { int nbout; int channels=wavheader.channels; *samples = 1152; //FIXME *len = 0; ADM_assert(tmptail>=tmphead); if(!refillBuffer(_chunk )) { return false; } if(tmptail-tmphead<_chunk) { return false; } dither16(&(tmpbuffer[tmphead]),_chunk,channels); ADM_assert(tmptail>=tmphead); if (channels == 1) { nbout =twolame_encode_buffer(OPTIONS, (int16_t *)&(tmpbuffer[tmphead]),(int16_t *)&(tmpbuffer[tmphead]), _chunk, dest, 16 * 1024); } else { nbout = twolame_encode_buffer_interleaved(OPTIONS, (int16_t *)&(tmpbuffer[tmphead]), _chunk/2, dest, 16 * 1024); } tmphead+=_chunk; ADM_assert(tmptail>=tmphead); if (nbout < 0) { printf("[TwoLame] Error !!! : %d\n", nbout); return false; } *len=nbout; return true; }
uint8_t AUDMEncoder_Twolame::getPacket(uint8_t *dest, uint32_t *len, uint32_t *samples) { int nbout; *samples = 1152; //FIXME *len = 0; ADM_assert(tmptail>=tmphead); if(!refillBuffer(_chunk )) { return 0; } if(tmptail-tmphead<_chunk) { return 0; } dither16(&(tmpbuffer[tmphead]),_chunk,_wavheader->channels); ADM_assert(tmptail>=tmphead); if (_wavheader->channels == 1) { nbout =twolame_encode_buffer(OPTIONS, (int16_t *)&(tmpbuffer[tmphead]),(int16_t *)&(tmpbuffer[tmphead]), _chunk, dest, 16 * 1024); } else { nbout = twolame_encode_buffer_interleaved(OPTIONS, (int16_t *)&(tmpbuffer[tmphead]), _chunk/2, dest, 16 * 1024); } tmphead+=_chunk; ADM_assert(tmptail>=tmphead); if (nbout < 0) { printf("\n Error !!! : %ld\n", nbout); return 0; } *len=nbout; return 1; }
int ExportMP2::Export(AudacityProject *project, int channels, const wxString &fName, bool selectionOnly, double t0, double t1, MixerSpec *mixerSpec, const Tags *metadata, int WXUNUSED(subformat)) { bool stereo = (channels == 2); long bitrate = gPrefs->Read(wxT("/FileFormats/MP2Bitrate"), 160); double rate = project->GetRate(); const TrackList *tracks = project->GetTracks(); wxLogNull logNo; /* temporarily disable wxWidgets error messages */ twolame_options *encodeOptions; encodeOptions = twolame_init(); twolame_set_in_samplerate(encodeOptions, (int)(rate + 0.5)); twolame_set_out_samplerate(encodeOptions, (int)(rate + 0.5)); twolame_set_bitrate(encodeOptions, bitrate); twolame_set_num_channels(encodeOptions, stereo ? 2 : 1); if (twolame_init_params(encodeOptions) != 0) { wxMessageBox(_("Cannot export MP2 with this sample rate and bit rate"), _("Error"), wxICON_STOP); twolame_close(&encodeOptions); return false; } // Put ID3 tags at beginning of file if (metadata == NULL) metadata = project->GetTags(); FileIO outFile(fName, FileIO::Output); if (!outFile.IsOpened()) { wxMessageBox(_("Unable to open target file for writing")); twolame_close(&encodeOptions); return false; } char *id3buffer = NULL; int id3len; bool endOfFile; id3len = AddTags(project, &id3buffer, &endOfFile, metadata); if (id3len && !endOfFile) outFile.Write(id3buffer, id3len); // Values taken from the twolame simple encoder sample const int pcmBufferSize = 9216 / 2; // number of samples const int mp2BufferSize = 16384; // bytes // We allocate a buffer which is twice as big as the // input buffer, which should always be enough. // We have to multiply by 4 because one sample is 2 bytes wide! unsigned char* mp2Buffer = new unsigned char[mp2BufferSize]; const WaveTrackConstArray waveTracks = tracks->GetWaveTrackConstArray(selectionOnly, false); int updateResult = eProgressSuccess; { auto mixer = CreateMixer(waveTracks, tracks->GetTimeTrack(), t0, t1, stereo ? 2 : 1, pcmBufferSize, true, rate, int16Sample, true, mixerSpec); ProgressDialog progress(wxFileName(fName).GetName(), selectionOnly ? wxString::Format(_("Exporting selected audio at %ld kbps"), bitrate) : wxString::Format(_("Exporting entire file at %ld kbps"), bitrate)); while (updateResult == eProgressSuccess) { sampleCount pcmNumSamples = mixer->Process(pcmBufferSize); if (pcmNumSamples == 0) break; short *pcmBuffer = (short *)mixer->GetBuffer(); int mp2BufferNumBytes = twolame_encode_buffer_interleaved( encodeOptions, pcmBuffer, pcmNumSamples, mp2Buffer, mp2BufferSize); outFile.Write(mp2Buffer, mp2BufferNumBytes); updateResult = progress.Update(mixer->MixGetCurrentTime() - t0, t1 - t0); } } int mp2BufferNumBytes = twolame_encode_flush( encodeOptions, mp2Buffer, mp2BufferSize); if (mp2BufferNumBytes > 0) outFile.Write(mp2Buffer, mp2BufferNumBytes); twolame_close(&encodeOptions); delete[] mp2Buffer; /* Write ID3 tag if it was supposed to be at the end of the file */ if (id3len && endOfFile) outFile.Write(id3buffer, id3len); if (id3buffer) { free(id3buffer); } /* Close file */ outFile.Close(); return updateResult; }
static GstFlowReturn gst_two_lame_chain (GstPad * pad, GstBuffer * buf) { GstTwoLame *twolame; guchar *mp3_data; gint mp3_buffer_size, mp3_size; gint64 duration; GstFlowReturn result; gint num_samples; guint8 *data; guint size; twolame = GST_TWO_LAME (GST_PAD_PARENT (pad)); GST_LOG_OBJECT (twolame, "entered chain"); if (!twolame->setup) goto not_setup; data = GST_BUFFER_DATA (buf); size = GST_BUFFER_SIZE (buf); if (twolame->float_input) num_samples = size / 4; else num_samples = size / 2; /* allocate space for output */ mp3_buffer_size = 1.25 * num_samples + 16384; mp3_data = g_malloc (mp3_buffer_size); if (twolame->num_channels == 1) { if (twolame->float_input) mp3_size = twolame_encode_buffer_float32 (twolame->glopts, (float *) data, (float *) data, num_samples, mp3_data, mp3_buffer_size); else mp3_size = twolame_encode_buffer (twolame->glopts, (short int *) data, (short int *) data, num_samples, mp3_data, mp3_buffer_size); } else { if (twolame->float_input) mp3_size = twolame_encode_buffer_float32_interleaved (twolame->glopts, (float *) data, num_samples / twolame->num_channels, mp3_data, mp3_buffer_size); else mp3_size = twolame_encode_buffer_interleaved (twolame->glopts, (short int *) data, num_samples / twolame->num_channels, mp3_data, mp3_buffer_size); } GST_LOG_OBJECT (twolame, "encoded %d bytes of audio to %d bytes of mp3", size, mp3_size); if (twolame->float_input) duration = gst_util_uint64_scale_int (size, GST_SECOND, 4 * twolame->samplerate * twolame->num_channels); else duration = gst_util_uint64_scale_int (size, GST_SECOND, 2 * twolame->samplerate * twolame->num_channels); if (GST_BUFFER_DURATION (buf) != GST_CLOCK_TIME_NONE && GST_BUFFER_DURATION (buf) != duration) { GST_DEBUG_OBJECT (twolame, "incoming buffer had incorrect duration %" GST_TIME_FORMAT ", outgoing buffer will have correct duration %" GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_TIME_ARGS (duration)); } if (twolame->last_ts == GST_CLOCK_TIME_NONE) { twolame->last_ts = GST_BUFFER_TIMESTAMP (buf); twolame->last_offs = GST_BUFFER_OFFSET (buf); twolame->last_duration = duration; } else { twolame->last_duration += duration; } gst_buffer_unref (buf); if (mp3_size < 0) { g_warning ("error %d", mp3_size); } if (mp3_size > 0) { GstBuffer *outbuf; outbuf = gst_buffer_new (); GST_BUFFER_DATA (outbuf) = mp3_data; GST_BUFFER_MALLOCDATA (outbuf) = mp3_data; GST_BUFFER_SIZE (outbuf) = mp3_size; GST_BUFFER_TIMESTAMP (outbuf) = twolame->last_ts; GST_BUFFER_OFFSET (outbuf) = twolame->last_offs; GST_BUFFER_DURATION (outbuf) = twolame->last_duration; gst_buffer_set_caps (outbuf, GST_PAD_CAPS (twolame->srcpad)); result = gst_pad_push (twolame->srcpad, outbuf); twolame->last_flow = result; if (result != GST_FLOW_OK) { GST_DEBUG_OBJECT (twolame, "flow return: %s", gst_flow_get_name (result)); } if (GST_CLOCK_TIME_IS_VALID (twolame->last_ts)) twolame->eos_ts = twolame->last_ts + twolame->last_duration; else twolame->eos_ts = GST_CLOCK_TIME_NONE; twolame->last_ts = GST_CLOCK_TIME_NONE; } else { g_free (mp3_data); result = GST_FLOW_OK; } return result; /* ERRORS */ not_setup: { gst_buffer_unref (buf); GST_ELEMENT_ERROR (twolame, CORE, NEGOTIATION, (NULL), ("encoder not initialized (input is not audio?)")); return GST_FLOW_ERROR; } }
int main(int argc, char **argv) { twolame_options *encopts = NULL; SNDFILE *inputfile = NULL; FILE *outputfile = NULL; short int *pcmaudio = NULL; int samples_read = 0; unsigned int frame_count = 0; unsigned char *mp2buffer = NULL; int mp2fill_size = 0; int audioReadSize = 0; // Allocate memory for the PCM audio data if ((pcmaudio = (short int *) calloc(AUDIOBUFSIZE, 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(MP2BUFSIZE, 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); // Open the input file inputfile = open_input_file( inputfilename ); twolame_set_num_channels( encopts, sfinfo.channels ); twolame_set_in_samplerate( encopts, sfinfo.samplerate ); // Open the output file outputfile = open_output_file( outputfilename ); // display file settings print_file_config( inputfile, twolame_get_verbosity(encopts) ); // 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 = 1152; else audioReadSize = AUDIOBUFSIZE; // Now do the reading/encoding/writing while ((samples_read = sf_read_short( 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, MP2BUFSIZE); // 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_WRITING_OUTPUT); } // Write the encoded audio out 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); } // Only single frame ? if (single_frame_mode) break; // Display Progress frame_count += (samples_read / 1152); if (twolame_get_verbosity(encopts)>0) { fprintf(stderr, "[%04i", frame_count); //fprintf(stderr, "/%04i", (int)(sfinfo.frames / sfinfo.channels / 1152)); fprintf(stderr, "]\r"); fflush(stderr); } } // // 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, MP2BUFSIZE); if (mp2fill_size>0) { 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); } } if (twolame_get_verbosity(encopts)>1) { fprintf(stderr, "\nEncoding Finished.\n"); } // Close input and output files sf_close( inputfile ); fclose( outputfile ); // Close the libtwolame encoder twolame_close(&encopts); // Free up memory free(pcmaudio); free(mp2buffer); return (ERR_NO_ERROR); }
static block_t *Encode( encoder_t *p_enc, block_t *p_aout_buf ) { encoder_sys_t *p_sys = p_enc->p_sys; block_t *p_chain = NULL; if( unlikely( !p_aout_buf ) ) { int i_used = 0; block_t *p_block; i_used = twolame_encode_flush( p_sys->p_twolame, p_sys->p_out_buffer, MAX_CODED_FRAME_SIZE ); if( i_used <= 0 ) return NULL; p_block = block_Alloc( i_used ); if( !p_block ) return NULL; memcpy( p_block->p_buffer, p_sys->p_out_buffer, i_used ); p_block->i_length = vlc_tick_from_samples( MPEG_FRAME_SIZE, p_enc->fmt_out.audio.i_rate ); p_block->i_dts = p_block->i_pts = p_sys->i_pts; p_sys->i_pts += p_block->i_length; return p_block; } int16_t *p_buffer = (int16_t *)p_aout_buf->p_buffer; int i_nb_samples = p_aout_buf->i_nb_samples; p_sys->i_pts = p_aout_buf->i_pts - vlc_tick_from_samples( p_sys->i_nb_samples, p_enc->fmt_out.audio.i_rate ); while ( p_sys->i_nb_samples + i_nb_samples >= MPEG_FRAME_SIZE ) { int i_used; block_t *p_block; Bufferize( p_enc, p_buffer, MPEG_FRAME_SIZE - p_sys->i_nb_samples ); i_nb_samples -= MPEG_FRAME_SIZE - p_sys->i_nb_samples; p_buffer += (MPEG_FRAME_SIZE - p_sys->i_nb_samples) * 2; i_used = twolame_encode_buffer_interleaved( p_sys->p_twolame, p_sys->p_buffer, MPEG_FRAME_SIZE, p_sys->p_out_buffer, MAX_CODED_FRAME_SIZE ); /* On error, buffer samples and return what was already encoded */ if( i_used < 0 ) { msg_Err( p_enc, "encoder error: %d", i_used ); break; } p_sys->i_nb_samples = 0; p_block = block_Alloc( i_used ); if( !p_block ) { if( p_chain ) block_ChainRelease( p_chain ); return NULL; } memcpy( p_block->p_buffer, p_sys->p_out_buffer, i_used ); p_block->i_length = vlc_tick_from_samples( MPEG_FRAME_SIZE, p_enc->fmt_out.audio.i_rate ); p_block->i_dts = p_block->i_pts = p_sys->i_pts; p_sys->i_pts += p_block->i_length; block_ChainAppend( &p_chain, p_block ); } if ( i_nb_samples ) { Bufferize( p_enc, p_buffer, i_nb_samples ); p_sys->i_nb_samples += i_nb_samples; } return p_chain; }
static GstFlowReturn gst_two_lame_handle_frame (GstAudioEncoder * enc, GstBuffer * buf) { GstTwoLame *twolame; gint mp3_buffer_size, mp3_size; GstBuffer *mp3_buf; GstFlowReturn result; gint num_samples; GstMapInfo map, mp3_map; twolame = GST_TWO_LAME (enc); /* squeeze remaining and push */ if (G_UNLIKELY (buf == NULL)) return gst_two_lame_flush_full (twolame, TRUE); gst_buffer_map (buf, &map, GST_MAP_READ); if (twolame->float_input) num_samples = map.size / 4; else num_samples = map.size / 2; /* allocate space for output */ mp3_buffer_size = 1.25 * num_samples + 16384; mp3_buf = gst_buffer_new_and_alloc (mp3_buffer_size); gst_buffer_map (mp3_buf, &mp3_map, GST_MAP_WRITE); if (twolame->num_channels == 1) { if (twolame->float_input) mp3_size = twolame_encode_buffer_float32 (twolame->glopts, (float *) map.data, (float *) map.data, num_samples, mp3_map.data, mp3_buffer_size); else mp3_size = twolame_encode_buffer (twolame->glopts, (short int *) map.data, (short int *) map.data, num_samples, mp3_map.data, mp3_buffer_size); } else { if (twolame->float_input) mp3_size = twolame_encode_buffer_float32_interleaved (twolame->glopts, (float *) map.data, num_samples / twolame->num_channels, mp3_map.data, mp3_buffer_size); else mp3_size = twolame_encode_buffer_interleaved (twolame->glopts, (short int *) map.data, num_samples / twolame->num_channels, mp3_map.data, mp3_buffer_size); } GST_LOG_OBJECT (twolame, "encoded %" G_GSIZE_FORMAT " bytes of audio " "to %d bytes of mp3", map.size, mp3_size); gst_buffer_unmap (buf, &map); gst_buffer_unmap (mp3_buf, &mp3_map); if (mp3_size > 0) { gst_buffer_set_size (mp3_buf, mp3_size); result = gst_audio_encoder_finish_frame (enc, mp3_buf, -1); } else { if (mp3_size < 0) { /* eat error ? */ g_warning ("error %d", mp3_size); } gst_buffer_unref (mp3_buf); result = GST_FLOW_OK; } return result; }
int main(int argc, char **argv) { twolame_options *encodeOptions; char *inputfilename = argv[1]; char *outputfilename = argv[2]; FILE *outfile, *fpSrc = NULL; short int *pcmaudio; unsigned char *mp2buffer; int num_samples = 0; int mp2fill_size = 0; int frames = 0; wave_info_t *wave_info = NULL; int nReadSize = 0; if (argc != 3) usage(); /* Allocate some space for the PCM audio data */ if ((pcmaudio = (short *) calloc(AUDIOBUFSIZE, sizeof(short))) == NULL) { fprintf(stderr, "pcmaudio alloc failed\n"); exit(99); } /* Allocate some space for the encoded MP2 audio data */ if ((mp2buffer = (unsigned char *) calloc(MP2BUFSIZE, sizeof(unsigned char))) == NULL) { fprintf(stderr, "mp2buffer alloc failed\n"); exit(99); } /* grab a set of default encode options */ encodeOptions = twolame_init(); printf("Using libtwolame version %s.\n", get_twolame_version()); /* Open the wave file */ if ((wave_info = wave_init(inputfilename)) == NULL) { fprintf(stderr, "Not a recognised WAV file.\n"); exit(99); } // Use sound file to over-ride preferences for // mono/stereo and sampling-frequency twolame_set_num_channels(encodeOptions, wave_info->channels); if (wave_info->channels == 1) { twolame_set_mode(encodeOptions, TWOLAME_MONO); } else { twolame_set_mode(encodeOptions, TWOLAME_STEREO); } /* Set the input and output sample rate to the same */ twolame_set_in_samplerate(encodeOptions, wave_info->samplerate); twolame_set_out_samplerate(encodeOptions, wave_info->samplerate); /* Set the bitrate to 192 kbps */ twolame_set_bitrate(encodeOptions, 64); /* initialise twolame with this set of options */ if (twolame_init_params(encodeOptions) != 0) { fprintf(stderr, "Error: configuring libtwolame encoder failed.\n"); exit(99); } /* Open the output file for the encoded MP2 data */ if ((outfile = fopen(outputfilename, "wb")) == 0) { fprintf(stderr, "error opening output file %s\n", outputfilename); exit(99); } // Read num_samples of audio data *per channel* from the input file //while ((num_samples = wave_get_samples(wave_info, pcmaudio, AUDIOBUFSIZE/2)) != 0) { fpSrc = fopen( "a2002011001-e02.wav", "rb" ); while(1) { num_samples = fread( pcmaudio, sizeof( char ), AUDIOBUFSIZE/2, fpSrc ); // Encode the audio!2024*4 if( num_samples != AUDIOBUFSIZE/2 ) break; num_samples /= 2; mp2fill_size = twolame_encode_buffer_interleaved(encodeOptions, pcmaudio, num_samples/2, mp2buffer, MP2BUFSIZE); // Write the MPEG bitstream to the file fwrite(mp2buffer, sizeof(unsigned char), mp2fill_size, outfile); // Display the number of MPEG audio frames we have encoded frames += (num_samples / TWOLAME_SAMPLES_PER_FRAME); printf("[%04i]\r", frames); fflush(stdout); } /* 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(encodeOptions, mp2buffer, MP2BUFSIZE); fwrite(mp2buffer, sizeof(unsigned char), mp2fill_size, outfile); twolame_close(&encodeOptions); free(pcmaudio); printf("\nFinished nicely.\n"); return (0); }
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) { int bytes_out = fwrite(mp2buffer, sizeof(unsigned char), mp2fill_size, outputfile); frame_count++; 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); }