![]() |
Mixxx
|
00001 /*************************************************************************** 00002 soundsourcemp3.cpp - description 00003 ------------------- 00004 copyright : (C) 2002 by Tue and Ken Haste Andersen 00005 email : 00006 ***************************************************************************/ 00007 00008 /*************************************************************************** 00009 * * 00010 * This program is free software; you can redistribute it and/or modify * 00011 * it under the terms of the GNU General Public License as published by * 00012 * the Free Software Foundation; either version 2 of the License, or * 00013 * (at your option) any later version. * 00014 * * 00015 ***************************************************************************/ 00016 00017 #include <taglib/mpegfile.h> 00018 00019 #include "soundsourcemp3.h" 00020 #include <QtDebug> 00021 00022 00023 SoundSourceMp3::SoundSourceMp3(QString qFilename) : 00024 Mixxx::SoundSource(qFilename), 00025 m_file(qFilename) 00026 { 00027 inputbuf = NULL; 00028 Stream = new mad_stream; 00029 mad_stream_init(Stream); 00030 Synth = new mad_synth; 00031 mad_synth_init(Synth); 00032 Frame = new mad_frame; 00033 mad_frame_init(Frame); 00034 00035 m_currentSeekFrameIndex = 0; 00036 m_iAvgFrameSize = 0; 00037 m_iChannels = 0; 00038 rest = 0; 00039 } 00040 00041 SoundSourceMp3::~SoundSourceMp3() 00042 { 00043 mad_stream_finish(Stream); 00044 delete Stream; 00045 00046 mad_frame_finish(Frame); 00047 delete Frame; 00048 00049 mad_synth_finish(Synth); 00050 delete Synth; 00051 00052 // Unmap inputbuf. 00053 m_file.unmap(inputbuf); 00054 inputbuf = NULL; 00055 m_file.close(); 00056 00057 //Free the pointers in our seek list, LIBERATE THEM!!! 00058 for (int i = 0; i < m_qSeekList.count(); i++) 00059 { 00060 delete m_qSeekList[i]; 00061 } 00062 m_qSeekList.clear(); 00063 } 00064 00065 QList<QString> SoundSourceMp3::supportedFileExtensions() 00066 { 00067 QList<QString> list; 00068 list.push_back("mp3"); 00069 return list; 00070 } 00071 00072 int SoundSourceMp3::open() 00073 { 00074 m_file.setFileName(m_qFilename); 00075 if (!m_file.open(QIODevice::ReadOnly)) { 00076 //qDebug() << "MAD: Open failed:" << m_qFilename; 00077 return ERR; 00078 } 00079 00080 // Get a pointer to the file using memory mapped IO 00081 inputbuf_len = m_file.size(); 00082 inputbuf = m_file.map(0, inputbuf_len); 00083 00084 // Transfer it to the mad stream-buffer: 00085 mad_stream_init(Stream); 00086 mad_stream_options(Stream, MAD_OPTION_IGNORECRC); 00087 mad_stream_buffer(Stream, inputbuf, inputbuf_len); 00088 00089 /* 00090 Decode all the headers, and fill in stats: 00091 */ 00092 mad_header Header; 00093 mad_header_init(&Header); 00094 filelength = mad_timer_zero; 00095 bitrate = 0; 00096 currentframe = 0; 00097 pos = mad_timer_zero; 00098 00099 while ((Stream->bufend - Stream->this_frame) > 0) 00100 { 00101 if (mad_header_decode (&Header, Stream) == -1) { 00102 if (!MAD_RECOVERABLE (Stream->error)) 00103 break; 00104 if (Stream->error == MAD_ERROR_LOSTSYNC) { 00105 // ignore LOSTSYNC due to ID3 tags 00106 int tagsize = id3_tag_query (Stream->this_frame,Stream->bufend - Stream->this_frame); 00107 if (tagsize > 0) { 00108 //qDebug() << "SSMP3::SSMP3() : skipping ID3 tag size " << tagsize; 00109 mad_stream_skip (Stream, tagsize); 00110 continue; 00111 } 00112 } 00113 00114 // qDebug() << "MAD: ERR decoding header " 00115 // << currentframe << ": " 00116 // << mad_stream_errorstr(Stream) 00117 // << " (len=" << mad_timer_count(filelength,MAD_UNITS_MILLISECONDS) 00118 // << ")"; 00119 continue; 00120 } 00121 00122 // Grab data from Header 00123 00124 // This warns us only when the reported sample rate changes. (and when 00125 // it is first set) 00126 if (m_iSampleRate == 0 && Header.samplerate > 0) { 00127 setSampleRate(Header.samplerate); 00128 } else if (m_iSampleRate != Header.samplerate) { 00129 qDebug() << "SSMP3: file has differing samplerate in some headers:" 00130 << m_qFilename 00131 << m_iSampleRate << "vs" << Header.samplerate; 00132 } 00133 00134 m_iChannels = MAD_NCHANNELS(&Header); 00135 mad_timer_add (&filelength, Header.duration); 00136 bitrate += Header.bitrate; 00137 00138 // Add frame to list of frames 00139 MadSeekFrameType * p = new MadSeekFrameType; 00140 p->m_pStreamPos = (unsigned char *)Stream->this_frame; 00141 p->pos = length(); 00142 m_qSeekList.append(p); 00143 currentframe++; 00144 } 00145 //qDebug() << "channels " << m_iChannels; 00146 00147 mad_header_finish (&Header); // This is a macro for nothing. 00148 00149 // This is not a working MP3 file. 00150 if (currentframe == 0) { 00151 return ERR; 00152 } 00153 00154 // Find average frame size 00155 m_iAvgFrameSize = (currentframe == 0) ? 0 : length()/currentframe; 00156 // And average bitrate 00157 bitrate = (currentframe == 0) ? 0 : bitrate / currentframe; 00158 framecount = currentframe; 00159 currentframe = 0; 00160 00161 //Recalculate the duration by using the average frame size. Our first guess at 00162 //the duration of VBR MP3s in parseHeader() goes for speed over accuracy 00163 //since it runs during a library scan. When we open() an MP3 for playback, 00164 //we had to seek through the entire thing to build a seek table, so we've 00165 //also counted the number of frames in it. We need that to better estimate 00166 //the length of VBR MP3s. 00167 if (getSampleRate() > 0 && m_iChannels > 0) //protect again divide by zero 00168 { 00169 //qDebug() << "SSMP3::open() - Setting duration to:" << framecount * m_iAvgFrameSize / getSampleRate() / m_iChannels; 00170 setDuration(framecount * m_iAvgFrameSize / getSampleRate() / m_iChannels); 00171 } 00172 00173 //TODO: Emit metadata updated signal? 00174 00175 /* 00176 qDebug() << "length = " << filelength.seconds << "d sec."; 00177 qDebug() << "frames = " << framecount; 00178 qDebug() << "bitrate = " << bitrate/1000; 00179 qDebug() << "Size = " << length(); 00180 */ 00181 00182 // Re-init buffer: 00183 seek(0); 00184 00185 return OK; 00186 } 00187 00188 bool SoundSourceMp3::isValid() const { 00189 return framecount > 0; 00190 } 00191 00192 MadSeekFrameType* SoundSourceMp3::getSeekFrame(long frameIndex) const { 00193 if (frameIndex < 0 || frameIndex >= m_qSeekList.size()) { 00194 return NULL; 00195 } 00196 return m_qSeekList.at(frameIndex); 00197 } 00198 00199 long SoundSourceMp3::seek(long filepos) { 00200 // Ensure that we are seeking to an even filepos 00201 Q_ASSERT(filepos%2==0); 00202 00203 if (!isValid()) { 00204 return 0; 00205 } 00206 00207 // qDebug() << "SEEK " << filepos; 00208 00209 MadSeekFrameType* cur = NULL; 00210 00211 if (filepos==0) 00212 { 00213 // Seek to beginning of file 00214 00215 // Re-init buffer: 00216 mad_stream_finish(Stream); 00217 mad_stream_init(Stream); 00218 mad_stream_options(Stream, MAD_OPTION_IGNORECRC); 00219 mad_stream_buffer(Stream, (unsigned char *) inputbuf, inputbuf_len); 00220 mad_frame_init(Frame); 00221 mad_synth_init(Synth); 00222 rest=-1; 00223 00224 m_currentSeekFrameIndex = 0; 00225 cur = getSeekFrame(0); 00226 //frameIterator.toFront(); //Might not need to do this -- Albert June 19/2010 (during Qt3 purge) 00227 } 00228 else 00229 { 00230 //qDebug() << "seek precise"; 00231 // Perform precise seek accomplished by using a frame in the seek list 00232 00233 // Find the frame to seek to in the list 00234 /* 00235 MadSeekFrameType *cur = m_qSeekList.last(); 00236 int k=0; 00237 while (cur!=0 && cur->pos>filepos) 00238 { 00239 cur = m_qSeekList.prev(); 00240 ++k; 00241 } 00242 */ 00243 00244 int framePos = findFrame(filepos); 00245 if (framePos==0 || framePos>filepos || m_currentSeekFrameIndex < 5) 00246 { 00247 //qDebug() << "Problem finding good seek frame (wanted " << filepos << ", got " << framePos << "), starting from 0"; 00248 00249 // Re-init buffer: 00250 mad_stream_finish(Stream); 00251 mad_stream_init(Stream); 00252 mad_stream_options(Stream, MAD_OPTION_IGNORECRC); 00253 mad_stream_buffer(Stream, (unsigned char *) inputbuf, inputbuf_len); 00254 mad_frame_init(Frame); 00255 mad_synth_init(Synth); 00256 rest = -1; 00257 m_currentSeekFrameIndex = 0; 00258 cur = getSeekFrame(m_currentSeekFrameIndex); 00259 } 00260 else 00261 { 00262 // qDebug() << "frame pos " << cur->pos; 00263 00264 // Start four frame before wanted frame to get in sync... 00265 m_currentSeekFrameIndex -= 4; 00266 cur = getSeekFrame(m_currentSeekFrameIndex); 00267 if (cur != NULL) { 00268 // Start from the new frame 00269 mad_stream_finish(Stream); 00270 mad_stream_init(Stream); 00271 mad_stream_options(Stream, MAD_OPTION_IGNORECRC); 00272 // qDebug() << "mp3 restore " << cur->m_pStreamPos; 00273 mad_stream_buffer(Stream, (const unsigned char *)cur->m_pStreamPos, 00274 inputbuf_len-(long int)(cur->m_pStreamPos-(unsigned char *)inputbuf)); 00275 00276 // Mute'ing is done here to eliminate potential pops/clicks from skipping 00277 // Rob Leslie explains why here: 00278 // http://www.mars.org/mailman/public/mad-dev/2001-August/000321.html 00279 mad_synth_mute(Synth); 00280 mad_frame_mute(Frame); 00281 00282 // Decode the three frames before 00283 mad_frame_decode(Frame,Stream); 00284 mad_frame_decode(Frame,Stream); 00285 mad_frame_decode(Frame,Stream); 00286 mad_frame_decode(Frame,Stream); 00287 00288 // this is also explained in the above mad-dev post 00289 mad_synth_frame(Synth, Frame); 00290 00291 // Set current position 00292 rest = -1; 00293 m_currentSeekFrameIndex += 4; 00294 cur = getSeekFrame(m_currentSeekFrameIndex); 00295 } 00296 } 00297 00298 // Synthesize the the samples from the frame which should be discard to reach the requested position 00299 if (cur != NULL) //the "if" prevents crashes on bad files. 00300 discard(filepos-cur->pos); 00301 } 00302 /* 00303 else 00304 { 00305 qDebug() << "seek unprecise"; 00306 // Perform seek which is can not be done precise because no frames is in the seek list 00307 00308 int newpos = (int)(inputbuf_len * ((float)filepos/(float)length())); 00309 // qDebug() << "Seek to " << filepos << " " << inputbuf_len << " " << newpos; 00310 00311 // Go to an approximate position: 00312 mad_stream_buffer(Stream, (unsigned char *) (inputbuf+newpos), inputbuf_len-newpos); 00313 mad_synth_mute(Synth); 00314 mad_frame_mute(Frame); 00315 00316 // Decode a few (possible wrong) buffers: 00317 int no = 0; 00318 int succesfull = 0; 00319 while ((no<10) && (succesfull<2)) 00320 { 00321 if (!mad_frame_decode(Frame, Stream)) 00322 succesfull ++; 00323 no ++; 00324 } 00325 00326 // Discard the first synth: 00327 mad_synth_frame(Synth, Frame); 00328 00329 // Remaining samples in buffer are useless 00330 rest = -1; 00331 00332 // Reset seek frame list 00333 m_qSeekList.clear(); 00334 MadSeekFrameType *p = new MadSeekFrameType; 00335 p->m_pStreamPos = (unsigned char*)Stream->this_frame; 00336 p->pos = filepos; 00337 m_qSeekList.append(p); 00338 m_iSeekListMinPos = filepos; 00339 m_iSeekListMaxPos = filepos; 00340 m_iCurFramePos = filepos; 00341 } 00342 */ 00343 00344 // Unfortunately we don't know the exact fileposition. The returned position is thus an 00345 // approximation only: 00346 return filepos; 00347 00348 } 00349 00350 inline long unsigned SoundSourceMp3::length() { 00351 enum mad_units units; 00352 00353 switch (m_iSampleRate) 00354 { 00355 case 8000: 00356 units = MAD_UNITS_8000_HZ; 00357 break; 00358 case 11025: 00359 units = MAD_UNITS_11025_HZ; 00360 break; 00361 case 12000: 00362 units = MAD_UNITS_12000_HZ; 00363 break; 00364 case 16000: 00365 units = MAD_UNITS_16000_HZ; 00366 break; 00367 case 22050: 00368 units = MAD_UNITS_22050_HZ; 00369 break; 00370 case 24000: 00371 units = MAD_UNITS_24000_HZ; 00372 break; 00373 case 32000: 00374 units = MAD_UNITS_32000_HZ; 00375 break; 00376 case 44100: 00377 units = MAD_UNITS_44100_HZ; 00378 break; 00379 case 48000: 00380 units = MAD_UNITS_48000_HZ; 00381 break; 00382 default: //By the MP3 specs, an MP3 _has_ to have one of the above samplerates... 00383 units = MAD_UNITS_44100_HZ; 00384 qWarning() << "MP3 with corrupt samplerate (" << m_iSampleRate << "), defaulting to 44100"; 00385 00386 m_iSampleRate = 44100; //Prevents division by zero errors. 00387 } 00388 00389 return (long unsigned) 2 *mad_timer_count(filelength, units); 00390 } 00391 00392 /* 00393 decode the chosen number of samples and discard 00394 */ 00395 00396 unsigned long SoundSourceMp3::discard(unsigned long samples_wanted) 00397 { 00398 unsigned long Total_samples_decoded = 0; 00399 int no; 00400 00401 if(rest > 0) 00402 Total_samples_decoded += 2*(Synth->pcm.length-rest); 00403 00404 while (Total_samples_decoded < samples_wanted) 00405 { 00406 if(mad_frame_decode(Frame,Stream)) 00407 { 00408 if(MAD_RECOVERABLE(Stream->error)) 00409 { 00410 continue; 00411 } else if(Stream->error==MAD_ERROR_BUFLEN) { 00412 break; 00413 } else { 00414 break; 00415 } 00416 } 00417 mad_synth_frame(Synth,Frame); 00418 no = math_min(Synth->pcm.length,(samples_wanted-Total_samples_decoded)/2); 00419 Total_samples_decoded += 2*no; 00420 } 00421 00422 if (Synth->pcm.length > no) 00423 rest = no; 00424 else 00425 rest = -1; 00426 00427 00428 return Total_samples_decoded; 00429 } 00430 00431 /* 00432 read <size> samples into <destination>, and return the number of 00433 samples actually read. 00434 */ 00435 unsigned SoundSourceMp3::read(unsigned long samples_wanted, const SAMPLE * _destination) 00436 { 00437 if (!isValid()) 00438 return 0; 00439 00440 // Ensure that we are reading an even number of samples. Otherwise this function may 00441 // go into an infinite loop 00442 Q_ASSERT(samples_wanted%2==0); 00443 // qDebug() << "frame list " << m_qSeekList.count(); 00444 00445 SAMPLE * destination = (SAMPLE *)_destination; 00446 unsigned Total_samples_decoded = 0; 00447 int i; 00448 00449 // If samples are left from previous read, then copy them to start of destination 00450 // Make sure to take into account the case where there are more samples left over 00451 // from the previous read than the client requested. 00452 if (rest > 0) 00453 { 00454 for (i=rest; i<Synth->pcm.length && Total_samples_decoded < samples_wanted; i++) 00455 { 00456 // Left channel 00457 *(destination++) = madScale(Synth->pcm.samples[0][i]); 00458 00459 /* Right channel. If the decoded stream is monophonic then 00460 * the right output channel is the same as the left one. */ 00461 if (m_iChannels>1) 00462 *(destination++) = madScale(Synth->pcm.samples[1][i]); 00463 else 00464 *(destination++) = madScale(Synth->pcm.samples[0][i]); 00465 00466 // This is safe because we have Q_ASSERTed that samples_wanted is even. 00467 Total_samples_decoded += 2; 00468 00469 } 00470 00471 if(Total_samples_decoded >= samples_wanted) { 00472 if(i < Synth->pcm.length) 00473 rest = i; 00474 else 00475 rest = -1; 00476 return Total_samples_decoded; 00477 } 00478 00479 } 00480 00481 // qDebug() << "Decoding"; 00482 int no = 0; 00483 unsigned int frames = 0; 00484 while (Total_samples_decoded < samples_wanted) 00485 { 00486 // qDebug() << "no " << Total_samples_decoded; 00487 if(mad_frame_decode(Frame,Stream)) 00488 { 00489 if(MAD_RECOVERABLE(Stream->error)) 00490 { 00491 if(Stream->error == MAD_ERROR_LOSTSYNC) { 00492 // Ignore LOSTSYNC due to ID3 tags 00493 int tagsize = id3_tag_query(Stream->this_frame, Stream->bufend - Stream->this_frame); 00494 if(tagsize > 0) { 00495 //qDebug() << "SSMP3::Read Skipping ID3 tag size: " << tagsize; 00496 mad_stream_skip(Stream, tagsize); 00497 } 00498 continue; 00499 } 00500 //qDebug() << "MAD: Recoverable frame level ERR (" << mad_stream_errorstr(Stream) << ")"; 00501 continue; 00502 } else if(Stream->error==MAD_ERROR_BUFLEN) { 00503 // qDebug() << "MAD: buflen ERR"; 00504 break; 00505 } else { 00506 // qDebug() << "MAD: Unrecoverable frame level ERR (" << mad_stream_errorstr(Stream) << ")."; 00507 break; 00508 } 00509 } 00510 00511 ++frames; 00512 00513 /* Once decoded the frame is synthesized to PCM samples. No ERRs 00514 * are reported by mad_synth_frame(); 00515 */ 00516 mad_synth_frame(Synth,Frame); 00517 00518 // Number of channels in frame 00519 //ch = MAD_NCHANNELS(&Frame->header); 00520 00521 /* Synthesized samples must be converted from mad's fixed 00522 * point number to the consumer format (16 bit). Integer samples 00523 * are temporarily stored in a buffer that is flushed when 00524 * full. 00525 */ 00526 00527 00528 // qDebug() << "synthlen " << Synth->pcm.length << ", remain " << (samples_wanted-Total_samples_decoded); 00529 no = math_min(Synth->pcm.length,(samples_wanted-Total_samples_decoded)/2); 00530 for (i=0; i<no; i++) 00531 { 00532 // Left channel 00533 *(destination++) = madScale(Synth->pcm.samples[0][i]); 00534 00535 /* Right channel. If the decoded stream is monophonic then 00536 * the right output channel is the same as the left one. */ 00537 if (m_iChannels==2) 00538 *(destination++) = madScale(Synth->pcm.samples[1][i]); 00539 else 00540 *(destination++) = madScale(Synth->pcm.samples[0][i]); 00541 } 00542 Total_samples_decoded += 2*no; 00543 00544 // qDebug() << "decoded: " << Total_samples_decoded << ", wanted: " << samples_wanted; 00545 } 00546 00547 // If samples are still left in buffer, set rest to the index of the unused samples 00548 if (Synth->pcm.length > no) 00549 rest = no; 00550 else 00551 rest = -1; 00552 00553 // qDebug() << "decoded " << Total_samples_decoded << " samples in " << frames << " frames, rest: " << rest << ", chan " << m_iChannels; 00554 return Total_samples_decoded; 00555 } 00556 00557 int SoundSourceMp3::parseHeader() 00558 { 00559 setType("mp3"); 00560 #ifdef __WINDOWS__ 00561 /* From Tobias: A Utf-8 string did not work on my Windows XP (German edition) 00562 * If you try this conversion, f.isValid() will return false in many cases 00563 * and processTaglibFile() will fail 00564 * 00565 * The method toLocal8Bit() returns the local 8-bit representation of the string as a QByteArray. 00566 * The returned byte array is undefined if the string contains characters not supported 00567 * by the local 8-bit encoding. 00568 */ 00569 QByteArray qBAFilename = m_qFilename.toLocal8Bit(); 00570 #else 00571 QByteArray qBAFilename = m_qFilename.toUtf8(); 00572 #endif 00573 TagLib::MPEG::File f(qBAFilename.constData()); 00574 00575 // Takes care of all the default metadata 00576 bool result = processTaglibFile(f); 00577 00578 // Now look for MP3 specific metadata (e.g. BPM) 00579 TagLib::ID3v2::Tag* id3v2 = f.ID3v2Tag(); 00580 if (id3v2) { 00581 processID3v2Tag(id3v2); 00582 } 00583 00584 TagLib::APE::Tag *ape = f.APETag(); 00585 if (ape) { 00586 processAPETag(ape); 00587 } 00588 00589 if (result) 00590 return OK; 00591 return ERR; 00592 } 00593 00594 int SoundSourceMp3::findFrame(int pos) 00595 { 00596 // Guess position of frame in m_qSeekList based on average frame size 00597 m_currentSeekFrameIndex = math_min(m_qSeekList.count()-1, 00598 m_iAvgFrameSize ? (unsigned int)(pos/m_iAvgFrameSize) : 0); 00599 MadSeekFrameType* temp = getSeekFrame(m_currentSeekFrameIndex); 00600 00601 /* 00602 if (temp!=0) 00603 qDebug() << "find " << pos << ", got " << temp->pos; 00604 else 00605 qDebug() << "find " << pos << ", tried idx " << math_min(m_qSeekList.count()-1 << ", total " << pos/m_iAvgFrameSize); 00606 */ 00607 00608 // Ensure that the list element is not at a greater position than pos 00609 while (temp != NULL && temp->pos > pos) 00610 { 00611 m_currentSeekFrameIndex--; 00612 temp = getSeekFrame(m_currentSeekFrameIndex); 00613 // if (temp!=0) qDebug() << "backing " << pos << ", got " << temp->pos; 00614 } 00615 00616 // Ensure that the following position is also not smaller than pos 00617 if (temp != NULL) 00618 { 00619 temp = getSeekFrame(m_currentSeekFrameIndex); 00620 while (temp != NULL && temp->pos < pos) 00621 { 00622 m_currentSeekFrameIndex++; 00623 temp = getSeekFrame(m_currentSeekFrameIndex); 00624 // if (temp!=0) qDebug() << "fwd'ing " << pos << ", got " << temp->pos; 00625 } 00626 00627 if (temp == NULL) 00628 m_currentSeekFrameIndex = m_qSeekList.count()-1; 00629 else 00630 m_currentSeekFrameIndex--; 00631 00632 temp = getSeekFrame(m_currentSeekFrameIndex); 00633 } 00634 00635 if (temp != NULL) 00636 { 00637 // qDebug() << "ended at " << pos << ", got " << temp->pos; 00638 return temp->pos; 00639 } 00640 else 00641 { 00642 // qDebug() << "ended at 0"; 00643 return 0; 00644 } 00645 } 00646 00647 inline signed int SoundSourceMp3::madScale(mad_fixed_t sample) 00648 { 00649 sample += (1L << (MAD_F_FRACBITS - 16)); 00650 00651 if (sample >= MAD_F_ONE) 00652 sample = MAD_F_ONE - 1; 00653 else if (sample < -MAD_F_ONE) 00654 sample = -MAD_F_ONE; 00655 00656 return sample >> (MAD_F_FRACBITS + 1 - 16); 00657 } 00658