/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /*************************************************************************** * liblame_wrapper.cc * * Sat Jul 2 11:11:34 CEST 2005 * Copyright 2005 Bent Bisballe * deva@aasimon.org ****************************************************************************/ /* * This file is part of MIaV. * * MIaV is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * MIaV is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with MIaV; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #include #include "liblame_wrapper.h" #include "miav_config.h" LibLAMEWrapper::LibLAMEWrapper(Info *i) { info = i; // Init library. if( (gfp = lame_init()) == NULL) { info->error("LAME initialization failed (due to malloc failure!)"); return; } lame_set_in_samplerate(gfp, INPUT_SAMPLE_RATE); lame_set_out_samplerate(gfp, OUTPUT_SAMPLE_RATE); lame_set_num_channels(gfp, CHANNELS); // lame_set_num_samples(gfp, 1152); // lame_set_num_samples(gfp, SAMPLES); // lame_set_num_samples(gfp, 0); lame_set_quality(gfp, config->readInt("mp3_quality")); lame_set_mode(gfp, STEREO); lame_set_brate(gfp, config->readInt("mp3_bitrate")); lame_set_strict_ISO(gfp, 1); // 1 = write a Xing VBR header frame. lame_set_bWriteVbrTag(gfp, 0); // Types of VBR. default = vbr_off = CBR // lame_set_VBR(gfp, vbr_rh); // VBR quality level. 0=highest 9=lowest // lame_set_VBR_q(gfp, 6); lame_set_copyright(gfp, 0); // is there a copyright on the encoded data? lame_set_original(gfp, 1); // is the encoded data on the original media? lame_set_error_protection(gfp, 0);// add 2 byte CRC protection to each frame? lame_set_padding_type(gfp, PAD_NO); // PAD_NO, PAD_ALL, PAD_ADJUST, PAD_MAX_INDICATOR // 0 = do not pad frames // 1 = always pad frames // 2 = adjust padding to satisfy bit rate lame_set_extension(gfp, 0); // private extension bit if (lame_init_params(gfp) < 0) { info->error("LAME parameter initialization failed."); return; } audio_buffer[0] = new int16_t[AUDIO_BUFFER_SIZE]; audio_buffer[1] = new int16_t[AUDIO_BUFFER_SIZE]; // And now for the dv decoder! decoder = NULL; calc_bitrate = 0; frame_number = 0; } LibLAMEWrapper::~LibLAMEWrapper() { delete audio_buffer[0]; delete audio_buffer[1]; } Frame *LibLAMEWrapper::close(Frame *oldframe) { Frame *frame = new Frame(NULL, oldframe->size + 7200); frame->number = oldframe->number; memcpy(frame->data, oldframe->data, oldframe->size); int flush; flush = lame_encode_finish(gfp, frame->data + oldframe->size, 7200); frame->size = oldframe->size + flush; calc_bitrate += flush; frame->bitrate = (unsigned int)((double)calc_bitrate / (double)(frame_number)) * 25; delete oldframe; return frame; } Frame *LibLAMEWrapper::encode(Frame *dvframe) { if(!decoder) { decoder = dv_decoder_new(FALSE/*this value is unused*/, FALSE, FALSE); decoder->quality = DV_QUALITY_BEST; dv_parse_header(decoder, dvframe->data); decoder->system = e_dv_system_625_50; // PAL lines, PAL framerate decoder->sampling = e_dv_sample_422; // 4 bytes y, 2 bytes u, 2 bytes v decoder->std = e_dv_std_iec_61834; decoder->num_dif_seqs = 12; } /** * Decode audio using libdv */ dv_decode_full_audio( decoder, dvframe->data, audio_buffer ); /** * input pcm data, output (maybe) mp3 frames. * This routine handles all buffering, resampling and filtering for you. * * The required mp3buf_size can be computed from num_samples, * samplerate and encoding rate, but here is a worst case estimate: * * return code number of bytes output in mp3buffer. can be 0 * if return code = -1: mp3buffer was too small * * mp3buf_size in bytes = 1.25*num_samples + 7200 * * I think a tighter bound could be: (mt, March 2000) * MPEG1: * num_samples*(bitrate/8)/samplerate + 4*1152*(bitrate/8)/samplerate + 512 * MPEG2: * num_samples*(bitrate/8)/samplerate + 4*576*(bitrate/8)/samplerate + 256 * * but test first if you use that! * * set mp3buf_size = 0 and LAME will not check if mp3buf_size is * large enough. * * NOTE: * if gfp->num_channels=2, but gfp->mode = 3 (mono), the L & R channels * will be averaged into the L channel before encoding only the L channel * This will overwrite the data in buffer_l[] and buffer_r[]. * */ Frame* audio_frame = new Frame(NULL, (int)(1.25 * SAMPLES + 7200)); const short int *buffer_l = audio_buffer[0]; // PCM data for left channel const short int *buffer_r = audio_buffer[1]; // PCM data for right channel const int nsamples = SAMPLES; // number of samples per channel unsigned char* mp3buf = audio_frame->data; // pointer to encoded MP3 stream const int mp3buf_size = audio_frame->size; // number of valid octets in this int val; val = lame_encode_buffer(gfp, buffer_l, buffer_r, nsamples, mp3buf, mp3buf_size); // val = lame_encode_mp3_frame(gfp, buffer_l, buffer_r, mp3buf, mp3buf_size); // info->info("Framenr: %d", lame_get_frameNum(gfp)); if(val < 0) { switch(val) { case -1: // mp3buf was too small info->error("Lame encoding failed, mp3buf was too small."); break; case -2: // malloc() problem info->error("Lame encoding failed, due to malloc() problem."); break; case -3: // lame_init_params() not called info->error("Lame encoding failed, lame_init_params() not called."); break; case -4: // psycho acoustic problems info->error("Lame encoding failed, due to psycho acoustic problems."); break; default: info->error("Lame encoding failed, due to unknown error."); break; } } /** * OPTIONAL: * lame_encode_flush_nogap will flush the internal mp3 buffers and pad * the last frame with ancillary data so it is a complete mp3 frame. * * 'mp3buf' should be at least 7200 bytes long * to hold all possible emitted data. * * After a call to this routine, the outputed mp3 data is complete, but * you may continue to encode new PCM samples and write future mp3 data * to a different file. The two mp3 files will play back with no gaps * if they are concatenated together. * * This routine will NOT write id3v1 tags into the bitstream. * * return code = number of bytes output to mp3buf. Can be 0 */ int flush_sz = 0; /* flush_sz = lame_encode_flush_nogap(gfp, // global context handle mp3buf + val, // pointer to encoded MP3 stream mp3buf_size - val); // number of valid octets in this stream */ info->info("VAL: %d - FLUSH_SZ: %d - TOTAL: %d", val, flush_sz, (val + flush_sz)); audio_frame->size = val + flush_sz; /* int bitrate_kbps[14]; // lame_bitrate_kbps(gfp, bitrate_kbps); lame_bitrate_hist(gfp, bitrate_kbps); // 32 40 48 56 64 80 96 112 128 160 192 224 256 320 info->info("%d %d %d %d %d %d %d %d %d %d %d %d %d %d", bitrate_kbps[0], bitrate_kbps[1], bitrate_kbps[2], bitrate_kbps[3], bitrate_kbps[4], bitrate_kbps[5], bitrate_kbps[6], bitrate_kbps[7], bitrate_kbps[8], bitrate_kbps[9], bitrate_kbps[10], bitrate_kbps[11], bitrate_kbps[12], bitrate_kbps[13]); */ // while(frame_number != lame_get_frameNum(gfp)) { calc_bitrate += audio_frame->size;//lame_get_framesize(gfp); frame_number ++;//= 1;//lame_get_frameNum(gfp); // info->info("lame_get_frameNum(gfp) %d ?= frame_number %d", lame_get_frameNum(gfp), frame_number); // } // Bits pr. second // 25 * 7 frames pr.second (it seems!) audio_frame->bitrate = (unsigned int)((double)calc_bitrate / (double)(frame_number)) * 25; /* info->info("Audio size: %d, bitrate: %.4f", audio_frame->bitrate, (float)(config->readInt("mp3_bitrate") * 1000)/(float)(audio_frame->bitrate)); */ return audio_frame; }