Warning, file /multimedia/k3b/libk3b/plugin/k3baudiodecoder.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 SPDX-FileCopyrightText: 1998-2009 Sebastian Trueg <trueg@k3b.org> 0003 SPDX-License-Identifier: GPL-2.0-or-later 0004 */ 0005 #include <config-libk3b.h> 0006 0007 #include "k3bcore.h" 0008 #include "k3baudiodecoder.h" 0009 #include "k3bpluginmanager.h" 0010 #include "k3b_i18n.h" 0011 0012 #include <KFileMetaData/ExtractionResult> 0013 #include <KFileMetaData/Extractor> 0014 #include <KFileMetaData/ExtractorCollection> 0015 #include <KFileMetaData/Properties> 0016 0017 #include <QDebug> 0018 #include <QMap> 0019 #include <QMimeDatabase> 0020 #include <QMimeType> 0021 0022 #include <math.h> 0023 0024 #include <samplerate.h> 0025 0026 #if !(HAVE_LRINT && HAVE_LRINTF) 0027 #define lrint(dbl) ((int) (dbl+0.5)) 0028 #define lrintf(flt) ((int) (flt+0.5)) 0029 #endif 0030 0031 // use a one second buffer 0032 static const int DECODING_BUFFER_SIZE = 75*2352; 0033 0034 namespace 0035 { 0036 0037 typedef QMap<K3b::AudioDecoder::MetaDataField, QString> MetaInfoMap; 0038 0039 class ExtractionResult : public KFileMetaData::ExtractionResult 0040 { 0041 public: 0042 ExtractionResult( const QString& filename, const QString& mimetype, MetaInfoMap& metaInfoMap ) 0043 : KFileMetaData::ExtractionResult( filename, mimetype, KFileMetaData::ExtractionResult::ExtractMetaData ), 0044 metaInfoMap_( metaInfoMap ) {} 0045 0046 void append(const QString& /*text*/) override {} 0047 0048 void addType(KFileMetaData::Type::Type /*type*/) override {} 0049 0050 void add(KFileMetaData::Property::Property property, const QVariant& value) override 0051 { 0052 switch(property) 0053 { 0054 case KFileMetaData::Property::Title: 0055 metaInfoMap_.insert( K3b::AudioDecoder::META_TITLE, value.toString() ); 0056 break; 0057 case KFileMetaData::Property::Artist: 0058 metaInfoMap_.insert( K3b::AudioDecoder::META_ARTIST, value.toString() ); 0059 break; 0060 case KFileMetaData::Property::Lyricist: 0061 metaInfoMap_.insert( K3b::AudioDecoder::META_SONGWRITER, value.toString() ); 0062 break; 0063 case KFileMetaData::Property::Composer: 0064 metaInfoMap_.insert( K3b::AudioDecoder::META_COMPOSER, value.toString() ); 0065 break; 0066 case KFileMetaData::Property::Comment: 0067 metaInfoMap_.insert( K3b::AudioDecoder::META_COMMENT, value.toString() ); 0068 break; 0069 default: 0070 break; 0071 } 0072 } 0073 0074 private: 0075 MetaInfoMap& metaInfoMap_; 0076 }; 0077 0078 } // namespace 0079 0080 class K3b::AudioDecoder::Private 0081 { 0082 public: 0083 Private() 0084 : metaDataCollection(NULL), 0085 resampleState(0), 0086 resampleData(0), 0087 inBuffer(0), 0088 inBufferPos(0), 0089 inBufferFill(0), 0090 outBuffer(0), 0091 monoBuffer(0), 0092 decodingBufferPos(0), 0093 decodingBufferFill(0), 0094 valid(true) { 0095 } 0096 0097 // the current position of the decoder 0098 // This does NOT include the decodingBuffer 0099 K3b::Msf currentPos; 0100 0101 // since the current position above is measured in frames 0102 // there might be a little offset since the decoded data is not 0103 // always a multiple of 2353 bytes 0104 int currentPosOffset; 0105 0106 // already decoded bytes from last init or last seek 0107 // TODO: replace alreadyDecoded with currentPos 0108 unsigned long alreadyDecoded; 0109 0110 K3b::Msf decodingStartPos; 0111 0112 KFileMetaData::ExtractorCollection *metaDataCollection; 0113 QMimeDatabase mimeDatabase; 0114 QMimeType mimeType; 0115 0116 // set to true once decodeInternal() returned 0 0117 bool decoderFinished; 0118 0119 // resampling 0120 SRC_STATE* resampleState; 0121 SRC_DATA* resampleData; 0122 0123 float* inBuffer; 0124 float* inBufferPos; 0125 int inBufferFill; 0126 0127 float* outBuffer; 0128 0129 int samplerate; 0130 int channels; 0131 0132 // mono -> stereo conversion 0133 char* monoBuffer; 0134 0135 char decodingBuffer[DECODING_BUFFER_SIZE]; 0136 char* decodingBufferPos; 0137 int decodingBufferFill; 0138 0139 QMap<QString, QString> technicalInfoMap; 0140 MetaInfoMap metaInfoMap; 0141 0142 bool valid; 0143 }; 0144 0145 0146 0147 K3b::AudioDecoder::AudioDecoder( QObject* parent ) 0148 : QObject( parent ) 0149 { 0150 d = new Private(); 0151 } 0152 0153 0154 K3b::AudioDecoder::~AudioDecoder() 0155 { 0156 cleanup(); 0157 0158 if( d->inBuffer ) delete [] d->inBuffer; 0159 if( d->outBuffer ) delete [] d->outBuffer; 0160 if( d->monoBuffer ) delete [] d->monoBuffer; 0161 0162 delete d->resampleData; 0163 if (d->resampleState) { 0164 src_delete(d->resampleState); 0165 d->resampleState = NULL; 0166 } 0167 delete d; 0168 } 0169 0170 0171 void K3b::AudioDecoder::setFilename( const QString& filename ) 0172 { 0173 m_fileName = filename; 0174 d->mimeType = QMimeType(); 0175 } 0176 0177 0178 bool K3b::AudioDecoder::isValid() const 0179 { 0180 return d->valid; 0181 } 0182 0183 0184 bool K3b::AudioDecoder::analyseFile() 0185 { 0186 d->technicalInfoMap.clear(); 0187 d->metaInfoMap.clear(); 0188 d->mimeType = QMimeType(); 0189 0190 cleanup(); 0191 0192 bool ret = analyseFileInternal( m_length, d->samplerate, d->channels ); 0193 if( ret && ( d->channels == 1 || d->channels == 2 ) && m_length > 0 ) { 0194 d->valid = initDecoder(); 0195 return d->valid; 0196 } 0197 else { 0198 d->valid = false; 0199 return false; 0200 } 0201 } 0202 0203 0204 bool K3b::AudioDecoder::initDecoder( const K3b::Msf& startOffset ) 0205 { 0206 if( initDecoder() ) { 0207 if( startOffset > 0 ) 0208 return seek( startOffset ); 0209 else 0210 return true; 0211 } 0212 else 0213 return false; 0214 } 0215 0216 0217 bool K3b::AudioDecoder::initDecoder() 0218 { 0219 cleanup(); 0220 0221 if( d->resampleState ) 0222 src_reset( d->resampleState ); 0223 0224 d->alreadyDecoded = 0; 0225 d->currentPos = 0; 0226 d->currentPosOffset = 0; 0227 d->decodingBufferFill = 0; 0228 d->decodingBufferPos = 0; 0229 d->decodingStartPos = 0; 0230 d->inBufferFill = 0; 0231 0232 d->decoderFinished = false; 0233 0234 return initDecoderInternal(); 0235 } 0236 0237 0238 int K3b::AudioDecoder::decode( char* _data, int maxLen ) 0239 { 0240 unsigned long lengthToDecode = (m_length - d->decodingStartPos).audioBytes(); 0241 0242 if( d->alreadyDecoded >= lengthToDecode ) 0243 return 0; 0244 0245 if( maxLen <= 0 ) 0246 return 0; 0247 0248 int read = 0; 0249 0250 if( d->decodingBufferFill == 0 ) { 0251 // 0252 // now we decode into the decoding buffer 0253 // to ensure a minimum buffer size 0254 // 0255 d->decodingBufferFill = 0; 0256 d->decodingBufferPos = d->decodingBuffer; 0257 0258 if( !d->decoderFinished ) { 0259 if( d->samplerate != 44100 ) { 0260 0261 // check if we have data left from some previous conversion 0262 if( d->inBufferFill > 0 ) { 0263 read = resample( d->decodingBuffer, DECODING_BUFFER_SIZE ); 0264 } 0265 else { 0266 if( !d->inBuffer ) { 0267 d->inBuffer = new float[DECODING_BUFFER_SIZE/2]; 0268 } 0269 0270 if( (read = decodeInternal( d->decodingBuffer, DECODING_BUFFER_SIZE )) == 0 ) 0271 d->decoderFinished = true; 0272 0273 d->inBufferFill = read/2; 0274 d->inBufferPos = d->inBuffer; 0275 from16bitBeSignedToFloat( d->decodingBuffer, d->inBuffer, d->inBufferFill ); 0276 0277 read = resample( d->decodingBuffer, DECODING_BUFFER_SIZE ); 0278 } 0279 } 0280 else if( d->channels == 1 ) { 0281 if( !d->monoBuffer ) { 0282 d->monoBuffer = new char[DECODING_BUFFER_SIZE/2]; 0283 } 0284 0285 // we simply duplicate every frame 0286 if( (read = decodeInternal( d->monoBuffer, DECODING_BUFFER_SIZE/2 )) == 0 ) 0287 d->decoderFinished = true; 0288 0289 for( int i = 0; i < read; i+=2 ) { 0290 d->decodingBuffer[2*i] = d->decodingBuffer[2*i+2] = d->monoBuffer[i]; 0291 d->decodingBuffer[2*i+1] = d->decodingBuffer[2*i+3] = d->monoBuffer[i+1]; 0292 } 0293 0294 read *= 2; 0295 } 0296 else { 0297 if( (read = decodeInternal( d->decodingBuffer, DECODING_BUFFER_SIZE )) == 0 ) 0298 d->decoderFinished = true; 0299 } 0300 } 0301 0302 if( read < 0 ) { 0303 return -1; 0304 } 0305 else if( read == 0 ) { 0306 // check if we need to pad 0307 int bytesToPad = lengthToDecode - d->alreadyDecoded; 0308 if( bytesToPad > 0 ) { 0309 qDebug() << "(K3b::AudioDecoder) track length: " << lengthToDecode 0310 << "; decoded module data: " << d->alreadyDecoded 0311 << "; we need to pad " << bytesToPad << " bytes." << Qt::endl; 0312 0313 if( DECODING_BUFFER_SIZE < bytesToPad ) 0314 bytesToPad = DECODING_BUFFER_SIZE; 0315 0316 ::memset( d->decodingBuffer, 0, bytesToPad ); 0317 0318 qDebug() << "(K3b::AudioDecoder) padded " << bytesToPad << " bytes."; 0319 0320 read = bytesToPad; 0321 } 0322 else { 0323 qDebug() << "(K3b::AudioDecoder) decoded " << d->alreadyDecoded << " bytes."; 0324 return 0; 0325 } 0326 } 0327 else { 0328 0329 // check if we decoded too much 0330 if( d->alreadyDecoded + read > lengthToDecode ) { 0331 qDebug() << "(K3b::AudioDecoder) we decoded too much. Cutting output by " 0332 << (read + d->alreadyDecoded - lengthToDecode) << Qt::endl; 0333 read = lengthToDecode - d->alreadyDecoded; 0334 } 0335 } 0336 0337 d->decodingBufferFill = read; 0338 } 0339 0340 0341 // clear out the decoding buffer 0342 read = qMin( maxLen, d->decodingBufferFill ); 0343 ::memcpy( _data, d->decodingBufferPos, read ); 0344 d->decodingBufferPos += read; 0345 d->decodingBufferFill -= read; 0346 0347 d->alreadyDecoded += read; 0348 d->currentPos += (read+d->currentPosOffset)/2352; 0349 d->currentPosOffset = (read+d->currentPosOffset)%2352; 0350 0351 return read; 0352 } 0353 0354 0355 // resample data in d->inBufferPos and save the result to data 0356 // 0357 // 0358 int K3b::AudioDecoder::resample( char* data, int maxLen ) 0359 { 0360 if( !d->resampleState ) { 0361 d->resampleState = src_new( SRC_SINC_MEDIUM_QUALITY, d->channels, 0 ); 0362 if( !d->resampleState ) { 0363 qDebug() << "(K3b::AudioDecoder) unable to initialize resampler."; 0364 return -1; 0365 } 0366 d->resampleData = new SRC_DATA; 0367 } 0368 0369 if( !d->outBuffer ) { 0370 d->outBuffer = new float[DECODING_BUFFER_SIZE/2]; 0371 } 0372 0373 d->resampleData->data_in = d->inBufferPos; 0374 d->resampleData->data_out = d->outBuffer; 0375 d->resampleData->input_frames = d->inBufferFill/d->channels; 0376 d->resampleData->output_frames = maxLen/2/2; // in case of mono files we need the space anyway 0377 d->resampleData->src_ratio = 44100.0/(double)d->samplerate; 0378 if( d->inBufferFill == 0 ) 0379 d->resampleData->end_of_input = 1; // this should force libsamplerate to output the last frames 0380 else 0381 d->resampleData->end_of_input = 0; 0382 0383 int len = 0; 0384 if( (len = src_process( d->resampleState, d->resampleData ) ) ) { 0385 qDebug() << "(K3b::AudioDecoder) error while resampling: " << src_strerror(len); 0386 return -1; 0387 } 0388 0389 if( d->channels == 2 ) 0390 fromFloatTo16BitBeSigned( d->outBuffer, data, d->resampleData->output_frames_gen*d->channels ); 0391 else { 0392 for( int i = 0; i < d->resampleData->output_frames_gen; ++i ) { 0393 fromFloatTo16BitBeSigned( &d->outBuffer[i], &data[4*i], 1 ); 0394 fromFloatTo16BitBeSigned( &d->outBuffer[i], &data[4*i+2], 1 ); 0395 } 0396 } 0397 0398 d->inBufferPos += d->resampleData->input_frames_used*d->channels; 0399 d->inBufferFill -= d->resampleData->input_frames_used*d->channels; 0400 if( d->inBufferFill <= 0 ) { 0401 d->inBufferPos = d->inBuffer; 0402 d->inBufferFill = 0; 0403 } 0404 0405 // 16 bit frames, so we need to multiply by 2 0406 // and we always have two channels 0407 return d->resampleData->output_frames_gen*2*2; 0408 } 0409 0410 0411 void K3b::AudioDecoder::from16bitBeSignedToFloat( char* src, float* dest, int samples ) 0412 { 0413 while( samples ) { 0414 samples--; 0415 dest[samples] = static_cast<float>( qint16(((src[2*samples]<<8)&0xff00)|(src[2*samples+1]&0x00ff)) / 32768.0 ); 0416 } 0417 } 0418 0419 0420 void K3b::AudioDecoder::fromFloatTo16BitBeSigned( float* src, char* dest, int samples ) 0421 { 0422 while( samples ) { 0423 samples--; 0424 0425 float scaled = src[samples] * 32768.0; 0426 qint16 val = 0; 0427 0428 // clipping 0429 if( scaled >= ( 1.0 * 0x7FFF ) ) 0430 val = 32767; 0431 else if( scaled <= ( -8.0 * 0x1000 ) ) 0432 val = -32768; 0433 else 0434 val = lrintf(scaled); 0435 0436 dest[2*samples] = val>>8; 0437 dest[2*samples+1] = val; 0438 } 0439 } 0440 0441 0442 void K3b::AudioDecoder::from8BitTo16BitBeSigned( char* src, char* dest, int samples ) 0443 { 0444 while( samples ) { 0445 samples--; 0446 0447 float scaled = static_cast<float>(quint8(src[samples])-128) / 128.0 * 32768.0; 0448 qint16 val = 0; 0449 0450 // clipping 0451 if( scaled >= ( 1.0 * 0x7FFF ) ) 0452 val = 32767; 0453 else if( scaled <= ( -8.0 * 0x1000 ) ) 0454 val = -32768; 0455 else 0456 val = lrintf(scaled); 0457 0458 dest[2*samples] = val>>8; 0459 dest[2*samples+1] = val; 0460 } 0461 } 0462 0463 0464 bool K3b::AudioDecoder::seek( const K3b::Msf& pos ) 0465 { 0466 qDebug() << "(K3b::AudioDecoder) seek from " << d->currentPos.toString() << " (+" << d->currentPosOffset 0467 << ") to " << pos.toString() << Qt::endl; 0468 0469 if( pos > length() ) 0470 return false; 0471 0472 d->decoderFinished = false; 0473 0474 if( pos == d->currentPos && d->currentPosOffset == 0 ) 0475 return true; 0476 0477 if( pos == 0 ) 0478 return initDecoder(); 0479 0480 bool success = false; 0481 0482 // 0483 // First check if we may do a "perfect seek". 0484 // We cannot rely on the decoding plugins to seek perfectly. Especially 0485 // the mp3 decoder does not. But in case we want to split a live recording 0486 // it is absolutely necessary to perform a perfect seek. 0487 // So if we did not already decode past the seek position and the difference 0488 // between the current position and the seek position is less than some fixed 0489 // value we simply decode up to the seek position. 0490 // 0491 if( ( pos > d->currentPos || 0492 ( pos == d->currentPos && d->currentPosOffset == 0 ) ) 0493 && 0494 ( pos - d->currentPos < K3b::Msf(0,10,0) ) ) { // < 10 seconds is ok 0495 qDebug() << "(K3b::AudioDecoder) performing perfect seek from " << d->currentPos.toString() 0496 << " to " << pos.toString() << ". :)" << Qt::endl; 0497 0498 qint64 bytesToDecode = pos.audioBytes() - d->currentPos.audioBytes() - d->currentPosOffset; 0499 qDebug() << "(K3b::AudioDecoder) seeking " << bytesToDecode << " bytes."; 0500 char buffi[10*2352]; 0501 while( bytesToDecode > 0 ) { 0502 int read = decode( buffi, qMin(( qint64 )( 10*2352 ), bytesToDecode) ); 0503 if( read <= 0 ) 0504 return false; 0505 0506 bytesToDecode -= read; 0507 } 0508 0509 qDebug() << "(K3b::AudioDecoder) perfect seek done."; 0510 0511 success = true; 0512 } 0513 else { 0514 // 0515 // Here we have to reset the resampling stuff since we restart decoding at another position. 0516 // 0517 if( d->resampleState ) 0518 src_reset( d->resampleState ); 0519 d->inBufferFill = 0; 0520 0521 // 0522 // And also reset the decoding buffer to not return any garbage from previous decoding. 0523 // 0524 d->decodingBufferFill = 0; 0525 0526 success = seekInternal( pos ); 0527 } 0528 0529 d->alreadyDecoded = 0; 0530 d->currentPos = d->decodingStartPos = pos; 0531 d->currentPosOffset = 0; 0532 0533 return success; 0534 } 0535 0536 0537 void K3b::AudioDecoder::cleanup() 0538 { 0539 if (d->metaDataCollection) { 0540 delete d->metaDataCollection; 0541 d->metaDataCollection = NULL; 0542 } 0543 } 0544 0545 0546 QString K3b::AudioDecoder::metaInfo( MetaDataField f ) 0547 { 0548 if( d->metaInfoMap.contains( f ) ) 0549 return d->metaInfoMap[f]; 0550 0551 // fall back to KFileMetaData 0552 if( !d->mimeType.isValid() ) 0553 { 0554 d->mimeType = d->mimeDatabase.mimeTypeForFile( m_fileName ); 0555 if (!d->metaDataCollection) 0556 d->metaDataCollection = new KFileMetaData::ExtractorCollection; 0557 for( KFileMetaData::Extractor* plugin : d->metaDataCollection->fetchExtractors( d->mimeType.name() ) ) 0558 { 0559 ExtractionResult extractionResult(m_fileName, d->mimeType.name(), d->metaInfoMap); 0560 plugin->extract(&extractionResult); 0561 } 0562 0563 if( d->metaInfoMap.contains( f ) ) 0564 return d->metaInfoMap[f]; 0565 } 0566 0567 return QString(); 0568 } 0569 0570 0571 void K3b::AudioDecoder::addMetaInfo( MetaDataField f, const QString& value ) 0572 { 0573 if( !value.isEmpty() ) 0574 d->metaInfoMap[f] = value; 0575 else 0576 qDebug() << "(K3b::AudioDecoder) empty meta data field."; 0577 } 0578 0579 0580 QStringList K3b::AudioDecoder::supportedTechnicalInfos() const 0581 { 0582 QStringList l; 0583 for( QMap<QString, QString>::const_iterator it = d->technicalInfoMap.constBegin(); 0584 it != d->technicalInfoMap.constEnd(); ++it ) 0585 l.append( it.key() ); 0586 return l; 0587 } 0588 0589 0590 QString K3b::AudioDecoder::technicalInfo( const QString& key ) const 0591 { 0592 return d->technicalInfoMap[key]; 0593 } 0594 0595 0596 void K3b::AudioDecoder::addTechnicalInfo( const QString& key, const QString& value ) 0597 { 0598 d->technicalInfoMap[key] = value; 0599 } 0600 0601 0602 K3b::AudioDecoder* K3b::AudioDecoderFactory::createDecoder( const QUrl& url ) 0603 { 0604 qDebug() << "(K3b::AudioDecoderFactory::createDecoder( " << url.toLocalFile() << " )"; 0605 QList<K3b::Plugin*> fl = k3bcore->pluginManager()->plugins( "AudioDecoder" ); 0606 0607 // first search for a single format decoder 0608 Q_FOREACH( K3b::Plugin* plugin, fl ) { 0609 K3b::AudioDecoderFactory* f = dynamic_cast<K3b::AudioDecoderFactory*>( plugin ); 0610 if( f && !f->multiFormatDecoder() && f->canDecode( url ) ) { 0611 qDebug() << "1"; return f->createDecoder();} 0612 } 0613 0614 // no single format decoder. Search for a multi format decoder 0615 Q_FOREACH( K3b::Plugin* plugin, fl ) { 0616 K3b::AudioDecoderFactory* f = dynamic_cast<K3b::AudioDecoderFactory*>( plugin ); 0617 if( f && f->multiFormatDecoder() && f->canDecode( url ) ) { 0618 qDebug() << "2"; return f->createDecoder();} 0619 } 0620 0621 qDebug() << "(K3b::AudioDecoderFactory::createDecoder( " << url.toLocalFile() << " ) no success"; 0622 0623 // nothing found 0624 return 0; 0625 } 0626 0627 0628 QString K3b::AudioDecoderFactory::categoryName() const 0629 { 0630 return i18nc( "plugin type", "Audio Decoder" ); 0631 } 0632 0633 #include "moc_k3baudiodecoder.cpp"