From 2741eb217aec6ee55f96a4d08d072f30838d3631 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 15 Jul 2009 10:20:38 -0700 Subject: [PATCH] LameLibrary - separated lame functionality LameLibrary can now be easily used to access lame functionality. This way we can use the same lame structure for SampleBuffer --- TODO | 2 + include/audio_file_mp3.h | 94 +-------------- include/lame_library.h | 132 +++++++++++++++++++++ src/core/audio/audio_file_mp3.cpp | 184 +++++------------------------- src/core/lame_library.cpp | 166 +++++++++++++++++++++++++++ 5 files changed, 332 insertions(+), 246 deletions(-) create mode 100644 include/lame_library.h create mode 100644 src/core/lame_library.cpp diff --git a/TODO b/TODO index bc718fe63..937f4bf88 100644 --- a/TODO +++ b/TODO @@ -56,6 +56,8 @@ Andrew Kelley's todo: play the sample * select the output file format based on what you selected in file->save as * ability to read mp3 samples +* load asdlol.mmpz. if you render it without playing it, or if you play it + the first time, you hear unwanted artifacts. - automation recording: diff --git a/include/audio_file_mp3.h b/include/audio_file_mp3.h index 33b3c880b..b36144a65 100644 --- a/include/audio_file_mp3.h +++ b/include/audio_file_mp3.h @@ -29,16 +29,11 @@ #define _AUDIO_FILE_MP3_H #include -#include +#include "lame_library.h" #include "lmmsconfig.h" #include "audio_file_device.h" -#include "lame.h" - -#include - - class AudioFileMp3 : public audioFileDevice { public: @@ -74,58 +69,6 @@ public: private: - // functions we'll be importing from lame - typedef lame_global_flags *lame_init_t(void); - typedef int lame_init_params_t(lame_global_flags*); - typedef const char* get_lame_version_t(void); - - typedef int lame_encode_buffer_t ( - lame_global_flags* gf, - const short int buffer_l [], - const short int buffer_r [], - const int nsamples, - unsigned char * mp3buf, - const int mp3buf_size ); - - typedef int lame_encode_buffer_interleaved_t( - lame_global_flags* gf, - short int pcm[], - int num_samples, /* per channel */ - unsigned char* mp3buf, - int mp3buf_size ); - - typedef int lame_encode_flush_t( - lame_global_flags *gf, - unsigned char* mp3buf, - int size ); - - typedef int lame_close_t(lame_global_flags*); - - typedef int lame_set_in_samplerate_t(lame_global_flags*, int); - typedef int lame_set_out_samplerate_t(lame_global_flags*, int); - typedef int lame_set_num_channels_t(lame_global_flags*, int ); - typedef int lame_set_quality_t(lame_global_flags*, int); - typedef int lame_set_brate_t(lame_global_flags*, int); - typedef int lame_set_VBR_t(lame_global_flags *, vbr_mode); - typedef int lame_set_VBR_q_t(lame_global_flags *, int); - typedef int lame_set_VBR_min_bitrate_kbps_t(lame_global_flags *, int); - typedef int lame_set_mode_t(lame_global_flags *, MPEG_mode); - typedef int lame_set_preset_t(lame_global_flags *, int); - typedef int lame_set_error_protection_t(lame_global_flags *, int); - typedef int lame_set_disable_reservoir_t(lame_global_flags *, int); - typedef int lame_set_padding_type_t(lame_global_flags *, Padding_type); - typedef int lame_set_bWriteVbrTag_t(lame_global_flags *, int); - typedef size_t lame_get_lametag_frame_t(const lame_global_flags *, unsigned char* buffer, size_t size); - typedef void lame_mp3_tags_fid_t(lame_global_flags *, FILE *); - - typedef int lame_set_findReplayGain_t(lame_global_flags *, int); - typedef int lame_set_VBR_quality_t(lame_global_flags *, float); - typedef int lame_set_VBR_mean_bitrate_kbps_t(lame_global_flags *, int); - typedef int lame_set_VBR_max_bitrate_kbps_t(lame_global_flags *, int); - - - - bool initLame(QString libpath); short int rescale(float sample); // convert float flame to short int frame // overloaded functions @@ -136,45 +79,14 @@ private: bool startEncoding( void ); void finishEncoding( void ); - bool m_ok; // true if we need to close the handle in finishEncoding - // handle to lame lame_global_flags *m_lgf; - QLibrary * m_lame; // lame .so file + LameLibrary m_lame; + QFile * m_outfile; bool m_hq_mode; // true if we want really high quality - - /* function pointers to the symbols we get from the library */ - lame_init_t* lame_init; - lame_init_params_t* lame_init_params; - lame_encode_buffer_t* lame_encode_buffer; - lame_encode_buffer_interleaved_t* lame_encode_buffer_interleaved; - lame_encode_flush_t* lame_encode_flush; - lame_close_t* lame_close; - get_lame_version_t* get_lame_version; - - lame_set_in_samplerate_t* lame_set_in_samplerate; - lame_set_out_samplerate_t* lame_set_out_samplerate; - lame_set_num_channels_t* lame_set_num_channels; - lame_set_quality_t* lame_set_quality; - lame_set_brate_t* lame_set_brate; - lame_set_VBR_t* lame_set_VBR; - lame_set_VBR_q_t* lame_set_VBR_q; - lame_set_VBR_min_bitrate_kbps_t* lame_set_VBR_min_bitrate_kbps; - lame_set_mode_t* lame_set_mode; - lame_set_preset_t* lame_set_preset; - lame_set_error_protection_t* lame_set_error_protection; - lame_set_disable_reservoir_t *lame_set_disable_reservoir; - lame_set_padding_type_t *lame_set_padding_type; - lame_set_bWriteVbrTag_t *lame_set_bWriteVbrTag; - lame_get_lametag_frame_t *lame_get_lametag_frame; - lame_mp3_tags_fid_t *lame_mp3_tags_fid; - lame_set_findReplayGain_t *lame_set_findReplayGain; - lame_set_VBR_quality_t *lame_set_VBR_quality; - lame_set_VBR_mean_bitrate_kbps_t *lame_set_VBR_mean_bitrate_kbps; - lame_set_VBR_max_bitrate_kbps_t *lame_set_VBR_max_bitrate_kbps; } ; diff --git a/include/lame_library.h b/include/lame_library.h new file mode 100644 index 000000000..322546a74 --- /dev/null +++ b/include/lame_library.h @@ -0,0 +1,132 @@ +/* + * lame_library.h - Manages loading and unloading of lame library dynamically + * + * + * Copyright (c) 2004-2008 Tobias Doerffel + * 2009 Andrew Kelley + * + * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net + * + * 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + + +#ifndef _LAME_LIBRARY_H_ +#define _LAME_LIBRARY_H_ + +#include +#include "lame.h" + +#include "config_mgr.h" + +class LameLibrary { + private: + // functions we'll be importing from lame + typedef lame_global_flags *lame_init_t(void); + typedef int lame_init_params_t(lame_global_flags*); + typedef const char* get_lame_version_t(void); + + typedef int lame_encode_buffer_t ( + lame_global_flags* gf, + const short int buffer_l [], + const short int buffer_r [], + const int nsamples, + unsigned char * mp3buf, + const int mp3buf_size ); + + typedef int lame_encode_buffer_interleaved_t( + lame_global_flags* gf, + short int pcm[], + int num_samples, /* per channel */ + unsigned char* mp3buf, + int mp3buf_size ); + + typedef int lame_encode_flush_t( + lame_global_flags *gf, + unsigned char* mp3buf, + int size ); + + typedef int lame_close_t(lame_global_flags*); + + typedef int lame_set_in_samplerate_t(lame_global_flags*, int); + typedef int lame_set_out_samplerate_t(lame_global_flags*, int); + typedef int lame_set_num_channels_t(lame_global_flags*, int ); + typedef int lame_set_quality_t(lame_global_flags*, int); + typedef int lame_set_brate_t(lame_global_flags*, int); + typedef int lame_set_VBR_t(lame_global_flags *, vbr_mode); + typedef int lame_set_VBR_q_t(lame_global_flags *, int); + typedef int lame_set_VBR_min_bitrate_kbps_t(lame_global_flags *, int); + typedef int lame_set_mode_t(lame_global_flags *, MPEG_mode); + typedef int lame_set_preset_t(lame_global_flags *, int); + typedef int lame_set_error_protection_t(lame_global_flags *, int); + typedef int lame_set_disable_reservoir_t(lame_global_flags *, int); + typedef int lame_set_padding_type_t(lame_global_flags *, Padding_type); + typedef int lame_set_bWriteVbrTag_t(lame_global_flags *, int); + typedef size_t lame_get_lametag_frame_t(const lame_global_flags *, unsigned char* buffer, size_t size); + typedef void lame_mp3_tags_fid_t(lame_global_flags *, FILE *); + + typedef int lame_set_findReplayGain_t(lame_global_flags *, int); + typedef int lame_set_VBR_quality_t(lame_global_flags *, float); + typedef int lame_set_VBR_mean_bitrate_kbps_t(lame_global_flags *, int); + typedef int lame_set_VBR_max_bitrate_kbps_t(lame_global_flags *, int); + + + public: + + LameLibrary(); // loads lame library + ~LameLibrary(); // unloads lame library + + + bool isLoaded(); // returns whether or not lame is correctly attached + + /* function pointers to the symbols we get from the library */ + lame_init_t* lame_init; + lame_init_params_t* lame_init_params; + lame_encode_buffer_t* lame_encode_buffer; + lame_encode_buffer_interleaved_t* lame_encode_buffer_interleaved; + lame_encode_flush_t* lame_encode_flush; + lame_close_t* lame_close; + get_lame_version_t* get_lame_version; + + lame_set_in_samplerate_t* lame_set_in_samplerate; + lame_set_out_samplerate_t* lame_set_out_samplerate; + lame_set_num_channels_t* lame_set_num_channels; + lame_set_quality_t* lame_set_quality; + lame_set_brate_t* lame_set_brate; + lame_set_VBR_t* lame_set_VBR; + lame_set_VBR_q_t* lame_set_VBR_q; + lame_set_VBR_min_bitrate_kbps_t* lame_set_VBR_min_bitrate_kbps; + lame_set_mode_t* lame_set_mode; + lame_set_preset_t* lame_set_preset; + lame_set_error_protection_t* lame_set_error_protection; + lame_set_disable_reservoir_t *lame_set_disable_reservoir; + lame_set_padding_type_t *lame_set_padding_type; + lame_set_bWriteVbrTag_t *lame_set_bWriteVbrTag; + lame_get_lametag_frame_t *lame_get_lametag_frame; + lame_mp3_tags_fid_t *lame_mp3_tags_fid; + lame_set_findReplayGain_t *lame_set_findReplayGain; + lame_set_VBR_quality_t *lame_set_VBR_quality; + lame_set_VBR_mean_bitrate_kbps_t *lame_set_VBR_mean_bitrate_kbps; + lame_set_VBR_max_bitrate_kbps_t *lame_set_VBR_max_bitrate_kbps; + + private: + QLibrary * m_lameLib; // lame .so file + +}; + + +#endif diff --git a/src/core/audio/audio_file_mp3.cpp b/src/core/audio/audio_file_mp3.cpp index a6519d99f..0ba4cbe89 100644 --- a/src/core/audio/audio_file_mp3.cpp +++ b/src/core/audio/audio_file_mp3.cpp @@ -24,12 +24,9 @@ * */ -#include - -#include "lame.h" +#include "lame_library.h" #include "audio_file_mp3.h" -#include #include using namespace std; @@ -38,134 +35,18 @@ using namespace std; AudioFileMp3::AudioFileMp3( const sample_rate_t _sample_rate, - const ch_cnt_t _channels, bool & _success_ful, - const QString & _file, - const bool _use_vbr, - const bitrate_t _nom_bitrate, - const bitrate_t _min_bitrate, - const bitrate_t _max_bitrate, - const int _depth, - mixer * _mixer ) : - audioFileDevice( _sample_rate, _channels, _file, _use_vbr, - _nom_bitrate, _min_bitrate, _max_bitrate, - _depth, _mixer ), + const ch_cnt_t _channels, bool & _success_ful, const QString & _file, + const bool _use_vbr, const bitrate_t _nom_bitrate, + const bitrate_t _min_bitrate, const bitrate_t _max_bitrate, + const int _depth, mixer * _mixer ) : + audioFileDevice( _sample_rate, _channels, _file, _use_vbr, _nom_bitrate, + _min_bitrate, _max_bitrate, _depth, _mixer ), m_lgf( NULL ), - m_lame( NULL ), + m_lame( LameLibrary() ), m_outfile( NULL ), m_hq_mode( false ) { - // connect to lame - m_ok = initLame(configManager::inst()->lameLibrary()); - m_ok = _success_ful = m_ok && startEncoding(); - - if( ! m_ok ) - { - // pop an informative message box - QMessageBox::information( NULL, QObject::tr( "Unable to load LAME" ), - QObject::tr( "LMMS was unable to load Lame MP3 encoder. " - "Please make sure " - "you have Lame installed and then check your folder settings " - "and make sure you tell LMMS where libmp3lame.so.0 is." ), - QMessageBox::Ok | QMessageBox::Default ); - } -} - - -bool AudioFileMp3::initLame(QString libpath) -{ - // dynamically load the .so file - m_lame = new QLibrary(libpath); - - if( ! m_lame->load() ) return false; - - // grab the functions and stuff we need - lame_init = (lame_init_t *) - m_lame->resolve("lame_init"); - get_lame_version = (get_lame_version_t *) - m_lame->resolve("get_lame_version"); - lame_init_params = (lame_init_params_t *) - m_lame->resolve("lame_init_params"); - lame_encode_buffer = (lame_encode_buffer_t *) - m_lame->resolve("lame_encode_buffer"); - lame_encode_buffer_interleaved = (lame_encode_buffer_interleaved_t *) - m_lame->resolve("lame_encode_buffer_interleaved"); - lame_encode_flush = (lame_encode_flush_t *) - m_lame->resolve("lame_encode_flush"); - lame_close = (lame_close_t *) - m_lame->resolve("lame_close"); - - lame_set_in_samplerate = (lame_set_in_samplerate_t *) - m_lame->resolve("lame_set_in_samplerate"); - lame_set_out_samplerate = (lame_set_out_samplerate_t *) - m_lame->resolve("lame_set_out_samplerate"); - lame_set_num_channels = (lame_set_num_channels_t *) - m_lame->resolve("lame_set_num_channels"); - lame_set_quality = (lame_set_quality_t *) - m_lame->resolve("lame_set_quality"); - lame_set_brate = (lame_set_brate_t *) - m_lame->resolve("lame_set_brate"); - lame_set_VBR = (lame_set_VBR_t *) - m_lame->resolve("lame_set_VBR"); - lame_set_VBR_q = (lame_set_VBR_q_t *) - m_lame->resolve("lame_set_VBR_q"); - lame_set_VBR_min_bitrate_kbps = (lame_set_VBR_min_bitrate_kbps_t *) - m_lame->resolve("lame_set_VBR_min_bitrate_kbps"); - lame_set_mode = (lame_set_mode_t *) - m_lame->resolve("lame_set_mode"); - lame_set_preset = (lame_set_preset_t *) - m_lame->resolve("lame_set_preset"); - lame_set_error_protection = (lame_set_error_protection_t *) - m_lame->resolve("lame_set_error_protection"); - lame_set_disable_reservoir = (lame_set_disable_reservoir_t *) - m_lame->resolve("lame_set_disable_reservoir"); - lame_set_padding_type = (lame_set_padding_type_t *) - m_lame->resolve("lame_set_padding_type"); - lame_set_bWriteVbrTag = (lame_set_bWriteVbrTag_t *) - m_lame->resolve("lame_set_bWriteVbrTag"); - - lame_set_findReplayGain = (lame_set_findReplayGain_t *) - m_lame->resolve("lame_set_findReplayGain"); - lame_set_VBR_quality = (lame_set_VBR_quality_t *) - m_lame->resolve("lame_set_VBR_quality"); - lame_set_VBR_mean_bitrate_kbps = (lame_set_VBR_mean_bitrate_kbps_t *) - m_lame->resolve("lame_set_VBR_mean_bitrate_kbps"); - lame_set_VBR_max_bitrate_kbps = (lame_set_VBR_max_bitrate_kbps_t *) - m_lame->resolve("lame_set_VBR_max_bitrate_kbps"); - - // These are optional - lame_get_lametag_frame = (lame_get_lametag_frame_t *) - m_lame->resolve("lame_get_lametag_frame"); - lame_mp3_tags_fid = (lame_mp3_tags_fid_t *) - m_lame->resolve("lame_mp3_tags_fid"); - - if (!lame_init || - !get_lame_version || - !lame_init_params || - !lame_encode_buffer || - !lame_encode_buffer_interleaved || - !lame_encode_flush || - !lame_close || - !lame_set_in_samplerate || - !lame_set_out_samplerate || - !lame_set_num_channels || - !lame_set_quality || - !lame_set_brate || - !lame_set_VBR || - !lame_set_VBR_q || - !lame_set_mode || - !lame_set_preset || - !lame_set_error_protection || - !lame_set_disable_reservoir || - !lame_set_padding_type || - !lame_set_bWriteVbrTag) - { - // some symbols are missing - printf("AudioFileMp3: some symbols are missing from the lame library\n"); - m_lame->unload(); - return false; - } - - return true; + _success_ful = m_lame.isLoaded() && startEncoding(); } @@ -174,15 +55,6 @@ AudioFileMp3::~AudioFileMp3() { finishEncoding(); - if( m_lame ) - { - if( m_lame->isLoaded() ) - m_lame->unload(); - - delete m_lame; - m_lame = NULL; - } - if( m_outfile ) { if( m_outfile->isOpen() ) @@ -200,7 +72,7 @@ void AudioFileMp3::finishEncoding( void ) // flush int bufSize = 7200; unsigned char * out = new unsigned char[bufSize]; - int rc = lame_encode_flush(m_lgf, out, bufSize); + int rc = m_lame.lame_encode_flush(m_lgf, out, bufSize); if( m_outfile && m_outfile->isOpen() ){ m_outfile->write( (const char *) out, rc ); @@ -214,7 +86,7 @@ void AudioFileMp3::finishEncoding( void ) delete[] out; // close any open handles we may have - lame_close(m_lgf); + m_lame.lame_close(m_lgf); m_lgf = NULL; } } @@ -223,7 +95,7 @@ void AudioFileMp3::finishEncoding( void ) bool AudioFileMp3::startEncoding( void ) { // open any handles, files, etc - m_lgf = lame_init(); + m_lgf = m_lame.lame_init(); if( m_lgf == NULL ){ printf("AudioFileMp3: Unable to initialize lame\n"); return false; @@ -232,32 +104,32 @@ bool AudioFileMp3::startEncoding( void ) if( channels() > 2 ) printf("I don't think lame can do more than 2 channels\n"); - lame_set_in_samplerate(m_lgf, sampleRate() ); - lame_set_num_channels(m_lgf, channels() ); + m_lame.lame_set_in_samplerate(m_lgf, sampleRate() ); + m_lame.lame_set_num_channels(m_lgf, channels() ); if( m_hq_mode ) - lame_set_quality(m_lgf, 0); // best, very slow + m_lame.lame_set_quality(m_lgf, 0); // best, very slow else - lame_set_quality(m_lgf, 2); // near-best, not too slow + m_lame.lame_set_quality(m_lgf, 2); // near-best, not too slow - lame_set_mode(m_lgf, STEREO); - lame_set_findReplayGain(m_lgf, 1); // perform ReplayGain analysis + m_lame.lame_set_mode(m_lgf, STEREO); + m_lame.lame_set_findReplayGain(m_lgf, 1); // perform ReplayGain analysis if( useVBR() == 0 ) { - lame_set_VBR(m_lgf, vbr_off); - lame_set_brate(m_lgf, nominalBitrate() ); + m_lame.lame_set_VBR(m_lgf, vbr_off); + m_lame.lame_set_brate(m_lgf, nominalBitrate() ); } else { - lame_set_VBR(m_lgf, vbr_abr); - lame_set_VBR_quality(m_lgf, 2); - lame_set_VBR_mean_bitrate_kbps(m_lgf, nominalBitrate() ); - lame_set_VBR_min_bitrate_kbps(m_lgf, minBitrate() ); - lame_set_VBR_max_bitrate_kbps(m_lgf, maxBitrate() ); + m_lame.lame_set_VBR(m_lgf, vbr_abr); + m_lame.lame_set_VBR_quality(m_lgf, 2); + m_lame.lame_set_VBR_mean_bitrate_kbps(m_lgf, nominalBitrate() ); + m_lame.lame_set_VBR_min_bitrate_kbps(m_lgf, minBitrate() ); + m_lame.lame_set_VBR_max_bitrate_kbps(m_lgf, maxBitrate() ); } - if( lame_init_params( m_lgf ) < 0 ) + if( m_lame.lame_init_params( m_lgf ) < 0 ) return false; // open the file @@ -269,6 +141,7 @@ bool AudioFileMp3::startEncoding( void ) } // write the headers and such + // TODO: add a comment "created with LMMS" return true; @@ -295,7 +168,8 @@ void AudioFileMp3::writeBuffer( const surroundSampleFrame * _ab, in[i*2+1] = rescale( _ab[i][1] ); } - int rc = lame_encode_buffer_interleaved( m_lgf, in, _frames, out, bufSize); + int rc = m_lame.lame_encode_buffer_interleaved( m_lgf, in, _frames, + out, bufSize); switch(rc){ case -1: diff --git a/src/core/lame_library.cpp b/src/core/lame_library.cpp new file mode 100644 index 000000000..01a6a7ff2 --- /dev/null +++ b/src/core/lame_library.cpp @@ -0,0 +1,166 @@ +/* + * lame_library.cpp - Manages loading and unloading of lame library dynamically + * + * + * Copyright (c) 2004-2008 Tobias Doerffel + * 2009 Andrew Kelley + * + * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net + * + * 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + + +#include +#include + + +#include "lame_library.h" + +LameLibrary::LameLibrary() : + m_lameLib( NULL ) +{ + // dynamically load the lame library + m_lameLib = new QLibrary(configManager::inst()->lameLibrary()); + if( ! m_lameLib->load() ) + { + QMessageBox::information( NULL, QObject::tr( "Unable to load LAME" ), + QObject::tr( "LMMS was unable to load Lame MP3 encoder. " + "Please make sure " + "you have Lame installed and then check your folder settings " + "and make sure you tell LMMS where libmp3lame.so.0 is." ), + QMessageBox::Ok | QMessageBox::Default ); + delete m_lameLib; + m_lameLib = NULL; + } + + // grab the functions and stuff we need + lame_init = (lame_init_t *) + m_lameLib->resolve("lame_init"); + get_lame_version = (get_lame_version_t *) + m_lameLib->resolve("get_lame_version"); + lame_init_params = (lame_init_params_t *) + m_lameLib->resolve("lame_init_params"); + lame_encode_buffer = (lame_encode_buffer_t *) + m_lameLib->resolve("lame_encode_buffer"); + lame_encode_buffer_interleaved = (lame_encode_buffer_interleaved_t *) + m_lameLib->resolve("lame_encode_buffer_interleaved"); + lame_encode_flush = (lame_encode_flush_t *) + m_lameLib->resolve("lame_encode_flush"); + lame_close = (lame_close_t *) + m_lameLib->resolve("lame_close"); + + lame_set_in_samplerate = (lame_set_in_samplerate_t *) + m_lameLib->resolve("lame_set_in_samplerate"); + lame_set_out_samplerate = (lame_set_out_samplerate_t *) + m_lameLib->resolve("lame_set_out_samplerate"); + lame_set_num_channels = (lame_set_num_channels_t *) + m_lameLib->resolve("lame_set_num_channels"); + lame_set_quality = (lame_set_quality_t *) + m_lameLib->resolve("lame_set_quality"); + lame_set_brate = (lame_set_brate_t *) + m_lameLib->resolve("lame_set_brate"); + lame_set_VBR = (lame_set_VBR_t *) + m_lameLib->resolve("lame_set_VBR"); + lame_set_VBR_q = (lame_set_VBR_q_t *) + m_lameLib->resolve("lame_set_VBR_q"); + lame_set_VBR_min_bitrate_kbps = (lame_set_VBR_min_bitrate_kbps_t *) + m_lameLib->resolve("lame_set_VBR_min_bitrate_kbps"); + lame_set_mode = (lame_set_mode_t *) + m_lameLib->resolve("lame_set_mode"); + lame_set_preset = (lame_set_preset_t *) + m_lameLib->resolve("lame_set_preset"); + lame_set_error_protection = (lame_set_error_protection_t *) + m_lameLib->resolve("lame_set_error_protection"); + lame_set_disable_reservoir = (lame_set_disable_reservoir_t *) + m_lameLib->resolve("lame_set_disable_reservoir"); + lame_set_padding_type = (lame_set_padding_type_t *) + m_lameLib->resolve("lame_set_padding_type"); + lame_set_bWriteVbrTag = (lame_set_bWriteVbrTag_t *) + m_lameLib->resolve("lame_set_bWriteVbrTag"); + + lame_set_findReplayGain = (lame_set_findReplayGain_t *) + m_lameLib->resolve("lame_set_findReplayGain"); + lame_set_VBR_quality = (lame_set_VBR_quality_t *) + m_lameLib->resolve("lame_set_VBR_quality"); + lame_set_VBR_mean_bitrate_kbps = (lame_set_VBR_mean_bitrate_kbps_t *) + m_lameLib->resolve("lame_set_VBR_mean_bitrate_kbps"); + lame_set_VBR_max_bitrate_kbps = (lame_set_VBR_max_bitrate_kbps_t *) + m_lameLib->resolve("lame_set_VBR_max_bitrate_kbps"); + + // These are optional + lame_get_lametag_frame = (lame_get_lametag_frame_t *) + m_lameLib->resolve("lame_get_lametag_frame"); + lame_mp3_tags_fid = (lame_mp3_tags_fid_t *) + m_lameLib->resolve("lame_mp3_tags_fid"); + + if (!lame_init || + !get_lame_version || + !lame_init_params || + !lame_encode_buffer || + !lame_encode_buffer_interleaved || + !lame_encode_flush || + !lame_close || + !lame_set_in_samplerate || + !lame_set_out_samplerate || + !lame_set_num_channels || + !lame_set_quality || + !lame_set_brate || + !lame_set_VBR || + !lame_set_VBR_q || + !lame_set_mode || + !lame_set_preset || + !lame_set_error_protection || + !lame_set_disable_reservoir || + !lame_set_padding_type || + !lame_set_bWriteVbrTag || + !lame_set_findReplayGain || + !lame_set_VBR_quality || + !lame_set_VBR_mean_bitrate_kbps || + !lame_set_VBR_max_bitrate_kbps) + { + // some symbols are missing + QMessageBox::information( NULL, QObject::tr( "LAME missing symbols" ), + QObject::tr( "Some symbols are missing from your Lame library. " + "Make sure you have the latest version of Lame and/or LMMS " + "installed." ), QMessageBox::Ok | QMessageBox::Default ); + m_lameLib->unload(); + delete m_lameLib; + m_lameLib = NULL; + } +} + + +LameLibrary::~LameLibrary() +{ + // release resources + if( m_lameLib ) + { + if( m_lameLib->isLoaded() ) + m_lameLib->unload(); + + delete m_lameLib; + m_lameLib = NULL; + } +} + +// returns whether or not lame is correctly attached +bool LameLibrary::isLoaded() +{ + return m_lameLib != NULL; +} +