svcore
1.9
|
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ 00002 00003 /* 00004 Sonic Visualiser 00005 An audio file viewer and annotation editor. 00006 Centre for Digital Music, Queen Mary, University of London. 00007 This file copyright 2006 Chris Cannam. 00008 00009 This program is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU General Public License as 00011 published by the Free Software Foundation; either version 2 of the 00012 License, or (at your option) any later version. See the file 00013 COPYING included with this distribution for more information. 00014 */ 00015 00016 #ifdef HAVE_MAD 00017 00018 #include "MP3FileReader.h" 00019 #include "base/ProgressReporter.h" 00020 00021 #include "system/System.h" 00022 00023 #include <sys/types.h> 00024 #include <sys/stat.h> 00025 #include <fcntl.h> 00026 00027 #include <iostream> 00028 00029 #include <cstdlib> 00030 #include <unistd.h> 00031 00032 #ifdef HAVE_ID3TAG 00033 #include <id3tag.h> 00034 #endif 00035 //#define DEBUG_ID3TAG 1 00036 00037 #include <QFileInfo> 00038 00039 MP3FileReader::MP3FileReader(FileSource source, DecodeMode decodeMode, 00040 CacheMode mode, int targetRate, 00041 bool normalised, 00042 ProgressReporter *reporter) : 00043 CodedAudioFileReader(mode, targetRate, normalised), 00044 m_source(source), 00045 m_path(source.getLocalFilename()), 00046 m_decodeThread(0) 00047 { 00048 m_channelCount = 0; 00049 m_fileRate = 0; 00050 m_fileSize = 0; 00051 m_bitrateNum = 0; 00052 m_bitrateDenom = 0; 00053 m_cancelled = false; 00054 m_completion = 0; 00055 m_done = false; 00056 m_reporter = reporter; 00057 00058 struct stat stat; 00059 if (::stat(m_path.toLocal8Bit().data(), &stat) == -1 || stat.st_size == 0) { 00060 m_error = QString("File %1 does not exist.").arg(m_path); 00061 return; 00062 } 00063 00064 m_fileSize = stat.st_size; 00065 00066 m_filebuffer = 0; 00067 m_samplebuffer = 0; 00068 m_samplebuffersize = 0; 00069 00070 int fd = -1; 00071 if ((fd = ::open(m_path.toLocal8Bit().data(), O_RDONLY 00072 #ifdef _WIN32 00073 | O_BINARY 00074 #endif 00075 , 0)) < 0) { 00076 m_error = QString("Failed to open file %1 for reading.").arg(m_path); 00077 return; 00078 } 00079 00080 try { 00081 m_filebuffer = new unsigned char[m_fileSize]; 00082 } catch (...) { 00083 m_error = QString("Out of memory"); 00084 ::close(fd); 00085 return; 00086 } 00087 00088 ssize_t sz = 0; 00089 int offset = 0; 00090 while (offset < m_fileSize) { 00091 sz = ::read(fd, m_filebuffer + offset, m_fileSize - offset); 00092 if (sz < 0) { 00093 m_error = QString("Read error for file %1 (after %2 bytes)") 00094 .arg(m_path).arg(offset); 00095 delete[] m_filebuffer; 00096 ::close(fd); 00097 return; 00098 } else if (sz == 0) { 00099 cerr << QString("MP3FileReader::MP3FileReader: Warning: reached EOF after only %1 of %2 bytes") 00100 .arg(offset).arg(m_fileSize) << endl; 00101 m_fileSize = offset; 00102 break; 00103 } 00104 offset += sz; 00105 } 00106 00107 ::close(fd); 00108 00109 loadTags(); 00110 00111 if (decodeMode == DecodeAtOnce) { 00112 00113 if (m_reporter) { 00114 connect(m_reporter, SIGNAL(cancelled()), this, SLOT(cancelled())); 00115 m_reporter->setMessage 00116 (tr("Decoding %1...").arg(QFileInfo(m_path).fileName())); 00117 } 00118 00119 if (!decode(m_filebuffer, m_fileSize)) { 00120 m_error = QString("Failed to decode file %1.").arg(m_path); 00121 } 00122 00123 delete[] m_filebuffer; 00124 m_filebuffer = 0; 00125 00126 if (isDecodeCacheInitialised()) finishDecodeCache(); 00127 endSerialised(); 00128 00129 } else { 00130 00131 if (m_reporter) m_reporter->setProgress(100); 00132 00133 m_decodeThread = new DecodeThread(this); 00134 m_decodeThread->start(); 00135 00136 while ((m_channelCount == 0 || m_fileRate == 0 || m_sampleRate == 0) 00137 && !m_done) { 00138 usleep(10); 00139 } 00140 00141 cerr << "MP3FileReader ctor: exiting with file rate = " << m_fileRate << endl; 00142 } 00143 00144 if (m_error != "") { 00145 cerr << "MP3FileReader::MP3FileReader(\"" << m_path << "\"): ERROR: " << m_error << endl; 00146 } 00147 } 00148 00149 MP3FileReader::~MP3FileReader() 00150 { 00151 if (m_decodeThread) { 00152 m_cancelled = true; 00153 m_decodeThread->wait(); 00154 delete m_decodeThread; 00155 } 00156 } 00157 00158 void 00159 MP3FileReader::cancelled() 00160 { 00161 m_cancelled = true; 00162 } 00163 00164 void 00165 MP3FileReader::loadTags() 00166 { 00167 m_title = ""; 00168 00169 #ifdef HAVE_ID3TAG 00170 00171 id3_file *file = id3_file_open(m_path.toLocal8Bit().data(), 00172 ID3_FILE_MODE_READONLY); 00173 if (!file) return; 00174 00175 // We can do this a lot more elegantly, but we'll leave that for 00176 // when we implement support for more than just the one tag! 00177 00178 id3_tag *tag = id3_file_tag(file); 00179 if (!tag) { 00180 #ifdef DEBUG_ID3TAG 00181 SVDEBUG << "MP3FileReader::loadTags: No ID3 tag found" << endl; 00182 #endif 00183 id3_file_close(file); 00184 return; 00185 } 00186 00187 m_title = loadTag(tag, "TIT2"); // work title 00188 if (m_title == "") m_title = loadTag(tag, "TIT1"); 00189 00190 m_maker = loadTag(tag, "TPE1"); // "lead artist" 00191 if (m_maker == "") m_maker = loadTag(tag, "TPE2"); 00192 00193 for (unsigned int i = 0; i < tag->nframes; ++i) { 00194 if (tag->frames[i]) { 00195 QString value = loadTag(tag, tag->frames[i]->id); 00196 if (value != "") m_tags[tag->frames[i]->id] = value; 00197 } 00198 } 00199 00200 id3_file_close(file); 00201 00202 #else 00203 #ifdef DEBUG_ID3TAG 00204 SVDEBUG << "MP3FileReader::loadTags: ID3 tag support not compiled in" 00205 << endl; 00206 #endif 00207 #endif 00208 } 00209 00210 QString 00211 MP3FileReader::loadTag(void *vtag, const char *name) 00212 { 00213 #ifdef HAVE_ID3TAG 00214 id3_tag *tag = (id3_tag *)vtag; 00215 00216 id3_frame *frame = id3_tag_findframe(tag, name, 0); 00217 if (!frame) { 00218 #ifdef DEBUG_ID3TAG 00219 SVDEBUG << "MP3FileReader::loadTags: No \"" << name << "\" in ID3 tag" << endl; 00220 #endif 00221 return ""; 00222 } 00223 00224 if (frame->nfields < 2) { 00225 SVDEBUG << "MP3FileReader::loadTags: WARNING: Not enough fields (" << frame->nfields << ") for \"" << name << "\" in ID3 tag" << endl; 00226 return ""; 00227 } 00228 00229 unsigned int nstrings = id3_field_getnstrings(&frame->fields[1]); 00230 if (nstrings == 0) { 00231 #ifdef DEBUG_ID3TAG 00232 SVDEBUG << "MP3FileReader::loadTags: No strings for \"" << name << "\" in ID3 tag" << endl; 00233 #endif 00234 return ""; 00235 } 00236 00237 id3_ucs4_t const *ustr = id3_field_getstrings(&frame->fields[1], 0); 00238 if (!ustr) { 00239 #ifdef DEBUG_ID3TAG 00240 SVDEBUG << "MP3FileReader::loadTags: Invalid or absent data for \"" << name << "\" in ID3 tag" << endl; 00241 #endif 00242 return ""; 00243 } 00244 00245 id3_utf8_t *u8str = id3_ucs4_utf8duplicate(ustr); 00246 if (!u8str) { 00247 cerr << "MP3FileReader::loadTags: ERROR: Internal error: Failed to convert UCS4 to UTF8 in ID3 title" << endl; 00248 return ""; 00249 } 00250 00251 QString rv = QString::fromUtf8((const char *)u8str); 00252 free(u8str); 00253 00254 #ifdef DEBUG_ID3TAG 00255 SVDEBUG << "MP3FileReader::loadTags: tag \"" << name << "\" -> \"" 00256 << rv << "\"" << endl; 00257 #endif 00258 00259 00260 return rv; 00261 00262 #else 00263 return ""; 00264 #endif 00265 } 00266 00267 void 00268 MP3FileReader::DecodeThread::run() 00269 { 00270 if (!m_reader->decode(m_reader->m_filebuffer, m_reader->m_fileSize)) { 00271 m_reader->m_error = QString("Failed to decode file %1.").arg(m_reader->m_path); 00272 } 00273 00274 delete[] m_reader->m_filebuffer; 00275 m_reader->m_filebuffer = 0; 00276 00277 if (m_reader->m_samplebuffer) { 00278 for (int c = 0; c < m_reader->m_channelCount; ++c) { 00279 delete[] m_reader->m_samplebuffer[c]; 00280 } 00281 delete[] m_reader->m_samplebuffer; 00282 m_reader->m_samplebuffer = 0; 00283 } 00284 00285 if (m_reader->isDecodeCacheInitialised()) m_reader->finishDecodeCache(); 00286 00287 m_reader->m_done = true; 00288 m_reader->m_completion = 100; 00289 00290 m_reader->endSerialised(); 00291 } 00292 00293 bool 00294 MP3FileReader::decode(void *mm, int sz) 00295 { 00296 DecoderData data; 00297 struct mad_decoder decoder; 00298 00299 data.start = (unsigned char const *)mm; 00300 data.length = (unsigned long)sz; 00301 data.reader = this; 00302 00303 mad_decoder_init(&decoder, &data, input, 0, 0, output, error, 0); 00304 mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC); 00305 mad_decoder_finish(&decoder); 00306 00307 m_done = true; 00308 return true; 00309 } 00310 00311 enum mad_flow 00312 MP3FileReader::input(void *dp, struct mad_stream *stream) 00313 { 00314 DecoderData *data = (DecoderData *)dp; 00315 00316 if (!data->length) return MAD_FLOW_STOP; 00317 00318 unsigned char const *start = data->start; 00319 unsigned long length = data->length; 00320 00321 #ifdef HAVE_ID3TAG 00322 if (length > ID3_TAG_QUERYSIZE) { 00323 int taglen = id3_tag_query(start, ID3_TAG_QUERYSIZE); 00324 if (taglen > 0) { 00325 // cerr << "ID3 tag length to skip: " << taglen << endl; 00326 start += taglen; 00327 length -= taglen; 00328 } 00329 } 00330 #endif 00331 00332 mad_stream_buffer(stream, start, length); 00333 data->length = 0; 00334 00335 return MAD_FLOW_CONTINUE; 00336 } 00337 00338 enum mad_flow 00339 MP3FileReader::output(void *dp, 00340 struct mad_header const *header, 00341 struct mad_pcm *pcm) 00342 { 00343 DecoderData *data = (DecoderData *)dp; 00344 return data->reader->accept(header, pcm); 00345 } 00346 00347 enum mad_flow 00348 MP3FileReader::accept(struct mad_header const *header, 00349 struct mad_pcm *pcm) 00350 { 00351 int channels = pcm->channels; 00352 int frames = pcm->length; 00353 00354 if (header) { 00355 m_bitrateNum += header->bitrate; 00356 m_bitrateDenom ++; 00357 } 00358 00359 if (frames < 1) return MAD_FLOW_CONTINUE; 00360 00361 if (m_channelCount == 0) { 00362 00363 m_fileRate = pcm->samplerate; 00364 m_channelCount = channels; 00365 00366 initialiseDecodeCache(); 00367 00368 if (m_cacheMode == CacheInTemporaryFile) { 00369 // SVDEBUG << "MP3FileReader::accept: channel count " << m_channelCount << ", file rate " << m_fileRate << ", about to start serialised section" << endl; 00370 startSerialised("MP3FileReader::Decode"); 00371 } 00372 } 00373 00374 if (m_bitrateDenom > 0) { 00375 double bitrate = m_bitrateNum / m_bitrateDenom; 00376 double duration = double(m_fileSize * 8) / bitrate; 00377 double elapsed = double(m_frameCount) / m_sampleRate; 00378 double percent = 100; 00379 if (duration > 0.0) percent = ((elapsed * 100.0) / duration); 00380 int p = int(percent); 00381 if (p < 1) p = 1; 00382 if (p > 99) p = 99; 00383 if (m_completion != p && m_reporter) { 00384 m_completion = p; 00385 m_reporter->setProgress(m_completion); 00386 } 00387 } 00388 00389 if (m_cancelled) return MAD_FLOW_STOP; 00390 00391 if (!isDecodeCacheInitialised()) { 00392 initialiseDecodeCache(); 00393 } 00394 00395 if (int(m_samplebuffersize) < frames) { 00396 if (!m_samplebuffer) { 00397 m_samplebuffer = new float *[channels]; 00398 for (int c = 0; c < channels; ++c) { 00399 m_samplebuffer[c] = 0; 00400 } 00401 } 00402 for (int c = 0; c < channels; ++c) { 00403 delete[] m_samplebuffer[c]; 00404 m_samplebuffer[c] = new float[frames]; 00405 } 00406 m_samplebuffersize = frames; 00407 } 00408 00409 int activeChannels = int(sizeof(pcm->samples) / sizeof(pcm->samples[0])); 00410 00411 for (int ch = 0; ch < channels; ++ch) { 00412 00413 for (int i = 0; i < frames; ++i) { 00414 00415 mad_fixed_t sample = 0; 00416 if (ch < activeChannels) { 00417 sample = pcm->samples[ch][i]; 00418 } 00419 float fsample = float(sample) / float(MAD_F_ONE); 00420 00421 m_samplebuffer[ch][i] = fsample; 00422 } 00423 } 00424 00425 addSamplesToDecodeCache(m_samplebuffer, frames); 00426 00427 return MAD_FLOW_CONTINUE; 00428 } 00429 00430 enum mad_flow 00431 MP3FileReader::error(void * /* dp */, 00432 struct mad_stream * /* stream */, 00433 struct mad_frame *) 00434 { 00435 // DecoderData *data = (DecoderData *)dp; 00436 00437 // fprintf(stderr, "decoding error 0x%04x (%s) at byte offset %lu\n", 00438 // stream->error, mad_stream_errorstr(stream), 00439 // (unsigned long)(stream->this_frame - data->start)); 00440 00441 return MAD_FLOW_CONTINUE; 00442 } 00443 00444 void 00445 MP3FileReader::getSupportedExtensions(std::set<QString> &extensions) 00446 { 00447 extensions.insert("mp3"); 00448 } 00449 00450 bool 00451 MP3FileReader::supportsExtension(QString extension) 00452 { 00453 std::set<QString> extensions; 00454 getSupportedExtensions(extensions); 00455 return (extensions.find(extension.toLower()) != extensions.end()); 00456 } 00457 00458 bool 00459 MP3FileReader::supportsContentType(QString type) 00460 { 00461 return (type == "audio/mpeg"); 00462 } 00463 00464 bool 00465 MP3FileReader::supports(FileSource &source) 00466 { 00467 return (supportsExtension(source.getExtension()) || 00468 supportsContentType(source.getContentType())); 00469 } 00470 00471 00472 #endif