File indexing completed on 2024-05-19 04:52:39
0001 /* 0002 SPDX-FileCopyrightText: 2010 Michal Malek <michalm@jabster.pl> 0003 SPDX-FileCopyrightText: 1998-2008 Sebastian Trueg <trueg@k3b.org> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "k3blameencoder.h" 0009 #include "k3blameencoderdefaults.h" 0010 #include "k3blametyes.h" 0011 #include "k3bplugin_i18n.h" 0012 #include "k3bcore.h" 0013 #include <config-k3b.h> 0014 0015 #include <KConfig> 0016 #include <KConfigGroup> 0017 #include <KSharedConfig> 0018 #include <QDebug> 0019 #include <QTextCodec> 0020 0021 #include <stdio.h> 0022 #include <lame/lame.h> 0023 0024 #include <QFile> 0025 0026 0027 K_PLUGIN_CLASS_WITH_JSON(K3bLameEncoder, "k3blameencoder.json") 0028 0029 0030 class K3bLameEncoder::Private 0031 { 0032 public: 0033 Private() 0034 : flags(0), 0035 fid(0) { 0036 } 0037 0038 lame_global_flags* flags; 0039 0040 char buffer[8000]; 0041 0042 QString filename; 0043 FILE* fid; 0044 }; 0045 0046 0047 0048 0049 K3bLameEncoder::K3bLameEncoder( QObject* parent, const QVariantList& ) 0050 : K3b::AudioEncoder( parent ) 0051 { 0052 d = new Private(); 0053 } 0054 0055 0056 K3bLameEncoder::~K3bLameEncoder() 0057 { 0058 closeFile(); 0059 0060 delete d; 0061 } 0062 0063 0064 bool K3bLameEncoder::openFile( const QString& extension, const QString& filename, const K3b::Msf& length, const MetaData& metaData ) 0065 { 0066 closeFile(); 0067 0068 d->filename = filename; 0069 d->fid = ::fopen( QFile::encodeName( filename ), "w+" ); 0070 if( d->fid ) 0071 return initEncoder( extension, length, metaData ); 0072 else 0073 return false; 0074 } 0075 0076 0077 bool K3bLameEncoder::isOpen() const 0078 { 0079 return ( d->fid != 0 ); 0080 } 0081 0082 0083 void K3bLameEncoder::closeFile() 0084 { 0085 if( isOpen() ) { 0086 finishEncoder(); 0087 ::fclose( d->fid ); 0088 d->fid = 0; 0089 d->filename.truncate(0); 0090 } 0091 } 0092 0093 0094 QString K3bLameEncoder::filename() const 0095 { 0096 return d->filename; 0097 } 0098 0099 0100 bool K3bLameEncoder::initEncoderInternal( const QString&, const K3b::Msf& length, const MetaData& metaData ) 0101 { 0102 KSharedConfig::Ptr c = KSharedConfig::openConfig(); 0103 KConfigGroup grp(c, QStringLiteral("K3bLameEncoderPlugin") ); 0104 0105 d->flags = lame_init(); 0106 0107 if( d->flags == 0 ) { 0108 qDebug() << "(K3bLameEncoder) lame_init failed."; 0109 return false; 0110 } 0111 0112 // 0113 // set the format of the input data 0114 // 0115 lame_set_num_samples( d->flags, length.lba()*588 ); 0116 lame_set_in_samplerate( d->flags, 44100 ); 0117 lame_set_num_channels( d->flags, 2 ); 0118 0119 // 0120 // Lame by default determines the samplerate based on the bitrate 0121 // since we have no option for the user to influence this yet 0122 // we just keep to the good old 44.1 khz 0123 // 0124 lame_set_out_samplerate( d->flags, 44100 ); 0125 0126 // 0127 // Choose the quality level 0128 // 0129 if( grp.readEntry( "Manual Bitrate Settings", DEFAULT_MANUAL_BITRATE ) ) { 0130 // 0131 // Mode 0132 // 0133 QString mode = grp.readEntry( "Mode", DEFAULT_MODE ); 0134 if( mode == "stereo" ) 0135 lame_set_mode( d->flags, STEREO ); 0136 else if( mode == "joint" ) 0137 lame_set_mode( d->flags, JOINT_STEREO ); 0138 else // mono 0139 lame_set_mode( d->flags, MONO ); 0140 0141 // 0142 // Variable Bitrate 0143 // 0144 if( grp.readEntry( "VBR", DEFAULT_VBR ) ) { 0145 // we use the default algorithm here 0146 lame_set_VBR( d->flags, vbr_default ); 0147 0148 if( grp.readEntry( "Use Maximum Bitrate", DEFAULT_USE_MAXIMUM_BITRATE ) ) { 0149 lame_set_VBR_max_bitrate_kbps( d->flags, grp.readEntry( "Maximum Bitrate", DEFAULT_MAXIMUM_BITRATE ) ); 0150 } 0151 if( grp.readEntry( "Use Minimum Bitrate", DEFAULT_USE_MINIMUM_BITRATE ) ) { 0152 lame_set_VBR_min_bitrate_kbps( d->flags, grp.readEntry( "Minimum Bitrate", DEFAULT_MINIMUM_BITRATE ) ); 0153 0154 // TODO: lame_set_hard_min 0155 } 0156 if( grp.readEntry( "Use Average Bitrate", DEFAULT_USE_AVERAGE_BITRATE ) ) { 0157 lame_set_VBR( d->flags, vbr_abr ); 0158 lame_set_VBR_mean_bitrate_kbps( d->flags, grp.readEntry( "Average Bitrate", DEFAULT_AVERAGE_BITRATE ) ); 0159 } 0160 } 0161 0162 // 0163 // Constant Bitrate 0164 // 0165 else { 0166 lame_set_VBR( d->flags, vbr_off ); 0167 lame_set_brate( d->flags, grp.readEntry( "Constant Bitrate", DEFAULT_CONSTANT_BITRATE ) ); 0168 } 0169 } 0170 0171 else { 0172 // 0173 // In lame 0 is the highest quality. Since that is just confusing for the user 0174 // if we call the setting "Quality" we simply invert the value. 0175 // 0176 int q = grp.readEntry( "Quality Level", DEFAULT_QUALITY_LEVEL ); 0177 if( q < 0 ) q = 0; 0178 if( q > 9 ) q = 9; 0179 0180 qDebug() << "(K3bLameEncoder) setting preset encoding value to " << q; 0181 0182 if ( q < 2 || q > 8 ) { 0183 lame_set_VBR( d->flags, vbr_abr ); 0184 } 0185 else { 0186 lame_set_VBR( d->flags, vbr_default ); 0187 } 0188 lame_set_preset( d->flags, s_lame_presets[q] ); 0189 0190 if( q < 2 ) 0191 lame_set_mode( d->flags, MONO ); 0192 } 0193 0194 0195 // 0196 // file options 0197 // 0198 lame_set_copyright( d->flags, grp.readEntry( "Copyright", DEFAULT_COPYRIGHT ) ); 0199 lame_set_original( d->flags, grp.readEntry( "Original", DEFAULT_ORIGINAL ) ); 0200 lame_set_strict_ISO( d->flags, grp.readEntry( "ISO compliance", DEFAULT_ISO_COMPLIANCE ) ); 0201 lame_set_error_protection( d->flags, grp.readEntry( "Error Protection", DEFAULT_ERROR_PROTECTION ) ); 0202 0203 0204 // 0205 // Used Algorithm 0206 // 0207 // default to 2 which is the same as the -h lame option 0208 // THIS HAS NO INFLUENCE ON THE SIZE OF THE FILE! 0209 // 0210 // 0211 // In lame 0 is the highest quality. Since that is just confusing for the user 0212 // if we call the setting "Quality" we simply invert the value. 0213 // 0214 int q = grp.readEntry( "Encoder Quality", DEFAULT_ENCODER_QUALITY ); 0215 if( q < 0 ) q = 0; 0216 if( q > 9 ) q = 9; 0217 lame_set_quality( d->flags, 9-q ); 0218 0219 // 0220 // ID3 settings 0221 // 0222 // for now we default to both v1 and v2 tags 0223 id3tag_add_v2( d->flags ); 0224 id3tag_pad_v2( d->flags ); 0225 0226 // let's not use UTF-8 here since I don't know how to tell lame... 0227 // FIXME: when we use the codec we only get garbage. Why? 0228 QTextCodec* codec = 0;//QTextCodec::codecForName( "ISO8859-1" ); 0229 // if( !codec ) 0230 // qDebug() << "(K3bLameEncoder) could not find codec ISO8859-1."; 0231 0232 for( MetaData::const_iterator it = metaData.constBegin(); it != metaData.constEnd(); ++it ) { 0233 QByteArray value = codec ? codec->fromUnicode( it.value().toString() ).data() 0234 : it.value().toString().toLatin1().data(); 0235 switch( it.key() ) { 0236 case META_TRACK_TITLE: 0237 id3tag_set_title( d->flags, value ); 0238 break; 0239 case META_TRACK_ARTIST: 0240 id3tag_set_artist( d->flags, value ); 0241 break; 0242 case META_ALBUM_TITLE: 0243 id3tag_set_album( d->flags, value ); 0244 break; 0245 case META_ALBUM_COMMENT: 0246 id3tag_set_comment( d->flags, value ); 0247 break; 0248 case META_YEAR: 0249 id3tag_set_year( d->flags, value ); 0250 break; 0251 case META_TRACK_NUMBER: 0252 id3tag_set_track( d->flags, value ); 0253 break; 0254 case META_GENRE: 0255 if( id3tag_set_genre( d->flags, value ) ) 0256 qDebug() << "(K3bLameEncoder) unable to set genre."; 0257 break; 0258 default: 0259 break; 0260 } 0261 } 0262 0263 return( lame_init_params( d->flags ) != -1 ); 0264 } 0265 0266 0267 qint64 K3bLameEncoder::encodeInternal( const char* data, qint64 len ) 0268 { 0269 // FIXME: we may have to swap data here 0270 int size = lame_encode_buffer_interleaved( d->flags, 0271 (short int*)data, 0272 len/4, 0273 (unsigned char*)d->buffer, 0274 8000 ); 0275 if( size < 0 ) { 0276 qDebug() << "(K3bLameEncoder) lame_encode_buffer_interleaved failed."; 0277 return -1; 0278 } 0279 0280 return ::fwrite( d->buffer, 1, size, d->fid ); 0281 } 0282 0283 0284 void K3bLameEncoder::finishEncoderInternal() 0285 { 0286 int size = lame_encode_flush( d->flags, 0287 (unsigned char*)d->buffer, 0288 8000 ); 0289 if( size > 0 ) 0290 ::fwrite( d->buffer, 1, size, d->fid ); 0291 0292 lame_mp3_tags_fid( d->flags, d->fid ); 0293 0294 lame_close( d->flags ); 0295 d->flags = 0; 0296 } 0297 0298 0299 QStringList K3bLameEncoder::extensions() const 0300 { 0301 return QStringList( "mp3" ); 0302 } 0303 0304 0305 QString K3bLameEncoder::fileTypeComment( const QString& ) const 0306 { 0307 return "MPEG1 Layer III (mp3)"; 0308 } 0309 0310 0311 long long K3bLameEncoder::fileSize( const QString&, const K3b::Msf& msf ) const 0312 { 0313 KSharedConfig::Ptr c = KSharedConfig::openConfig(); 0314 KConfigGroup grp(c, QStringLiteral("K3bLameEncoderPlugin") ); 0315 int bitrate = 0; 0316 if( grp.readEntry( "Manual Bitrate Settings", DEFAULT_MANUAL_BITRATE ) ) { 0317 if( grp.readEntry( "VBR", DEFAULT_VBR ) ) { 0318 if( grp.readEntry( "Use Maximum Bitrate", DEFAULT_USE_MAXIMUM_BITRATE ) ) 0319 bitrate = grp.readEntry( "Maximum Bitrate", DEFAULT_MAXIMUM_BITRATE ); 0320 if( grp.readEntry( "Use Minimum Bitrate", DEFAULT_USE_MINIMUM_BITRATE ) ) 0321 bitrate = ( bitrate > 0 0322 ? (bitrate - grp.readEntry( "Minimum Bitrate", DEFAULT_MINIMUM_BITRATE )) / 2 0323 : grp.readEntry( "Minimum Bitrate", DEFAULT_MINIMUM_BITRATE ) ); 0324 if( grp.readEntry( "Use Average Bitrate", DEFAULT_USE_AVERAGE_BITRATE ) ) 0325 bitrate = grp.readEntry( "Average Bitrate", DEFAULT_AVERAGE_BITRATE ); 0326 } 0327 else { 0328 bitrate = grp.readEntry( "Constant Bitrate", DEFAULT_CONSTANT_BITRATE ); 0329 } 0330 } 0331 else { 0332 int q = grp.readEntry( "Quality Level", DEFAULT_ENCODER_QUALITY ); 0333 if( q < 0 ) q = 0; 0334 if( q > 9 ) q = 9; 0335 bitrate = s_lame_preset_approx_bitrates[q]; 0336 } 0337 0338 return (msf.totalFrames()/75 * bitrate * 1000)/8; 0339 } 0340 0341 #include "k3blameencoder.moc" 0342 0343 #include "moc_k3blameencoder.cpp"