/* reencode.c * - Functions for reencoding in ices * Copyright (c) 2000 Alexander Haväng * Copyright (c) 2001-3 Brendan Cully * * This program 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. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "definitions.h" #ifdef HAVE_LAME_LAME_H # include #else # include #endif extern ices_config_t ices_config; /* Global function definitions */ /* Initialize the reencoding engine in ices, initialize * the liblame structures and be happy */ void ices_reencode_initialize (void) { ices_stream_t* stream; /* are any streams reencoding? */ for (stream = ices_config.streams; stream; stream = stream->next) if (stream->reencode) { ices_config.reencode = 1; break; } if (! ices_config.reencode) return; ices_log_debug ("Using LAME version %s", get_lame_version ()); } /* For each song, reset the liblame engine, otherwise it craps out if * the bitrate or sample rate changes */ void ices_reencode_reset (input_stream_t* source) { ices_stream_t* stream; lame_global_flags* lame; static int init_decoder = 1; #ifdef HAVE_LAME_DECODE_EXIT if (!init_decoder) { if (lame_decode_exit () < 0) { ices_log ("LAME: error shutting down decoder"); ices_setup_shutdown (); } init_decoder = 1; } #endif if (init_decoder) { if (lame_decode_init () < 0) { ices_log ("LAME: error initialising decoder"); ices_setup_shutdown (); } init_decoder = 0; } for (stream = ices_config.streams; stream; stream = stream->next) { if (! stream->reencode) continue; /* only reset encoder if audio format changes */ lame = (lame_global_flags*)stream->encoder_state; if (lame) { if (lame_get_in_samplerate (lame) == source->samplerate) continue; lame_close (lame); } if (! (stream->encoder_state = lame_init ())) { ices_log ("LAME: error resetting encoder."); ices_setup_shutdown (); } lame = (lame_global_flags*)stream->encoder_state; lame_set_in_samplerate (lame, source->samplerate); /* Lame won't reencode mono to stereo for some reason, so we have to * duplicate left into right by hand. */ if (source->channels == 1 && stream->out_numchannels == 1) lame_set_num_channels (lame, source->channels); lame_set_brate (lame, stream->bitrate); if (stream->out_numchannels == 1) lame_set_mode (lame, MONO); if (stream->out_samplerate > 0) lame_set_out_samplerate (lame, stream->out_samplerate); lame_set_original (lame, 0); /* lame_init_params isn't more specific about the problem */ if (lame_init_params (lame) < 0) { ices_log ("LAME: error resetting sample rate."); lame_close (lame); ices_setup_shutdown (); } /* adjust default stream sample rate to LAME default for lazy reencoding tests */ if (stream->out_samplerate <= 0) stream->out_samplerate = lame_get_out_samplerate (lame); } } /* If initialized, shutdown the reencoding engine */ void ices_reencode_shutdown (void) { ices_stream_t* stream; for (stream = ices_config.streams; stream; stream = stream->next) if (stream->encoder_state) { lame_close ((lame_global_flags*) stream->encoder_state); stream->encoder_state = NULL; } } /* decode buffer, of length buflen, into left and right. Stream-independent * (do this once per chunk, not per stream). Result is number of samples * for ices_reencode_reencode_chunk. */ int ices_reencode_decode (unsigned char* buf, size_t blen, size_t olen, int16_t* left, int16_t* right) { return lame_decode (buf, blen, left, right); } /* reencode buff, of len buflen, put max outlen reencoded bytes in outbuf */ int ices_reencode (ices_stream_t* stream, int nsamples, int16_t* left, int16_t* right, unsigned char *outbuf, int outlen) { lame_global_flags* lame = (lame_global_flags*) stream->encoder_state; return lame_encode_buffer (lame, left, right, nsamples, outbuf, outlen); } /* At EOF of each file, flush the liblame buffers and get some extra candy */ int ices_reencode_flush (ices_stream_t* stream, unsigned char *outbuf, int maxlen) { lame_global_flags* lame = (lame_global_flags*) stream->encoder_state; int rc; rc = lame_encode_flush_nogap (lame, (char *)outbuf, maxlen); return rc; }