![]() |
Mixxx
|
00001 00007 /*************************************************************************** 00008 * * 00009 * This program is free software; you can redistribute it and/or modify * 00010 * it under the terms of the GNU General Public License as published by * 00011 * the Free Software Foundation; either version 2 of the License, or * 00012 * (at your option) any later version. * 00013 * * 00014 ***************************************************************************/ 00015 00016 #include <cstring> // memcpy 00017 #include <QtDebug> 00018 #include <taglib/flacfile.h> 00019 00020 #include "soundsourceflac.h" 00021 00022 SoundSourceFLAC::SoundSourceFLAC(QString filename) 00023 : Mixxx::SoundSource(filename) 00024 , m_file(filename) 00025 , m_decoder(NULL) 00026 , m_samples(0) 00027 , m_bps(0) 00028 , m_minBlocksize(0) 00029 , m_maxBlocksize(0) 00030 , m_minFramesize(0) 00031 , m_maxFramesize(0) 00032 , m_flacBuffer(NULL) 00033 , m_flacBufferLength(0) 00034 , m_leftoverBuffer(NULL) 00035 , m_leftoverBufferLength(0) { 00036 } 00037 00038 SoundSourceFLAC::~SoundSourceFLAC() { 00039 if (m_flacBuffer != NULL) { 00040 delete [] m_flacBuffer; 00041 m_flacBuffer = NULL; 00042 } 00043 if (m_leftoverBuffer != NULL) { 00044 delete [] m_leftoverBuffer; 00045 m_leftoverBuffer = NULL; 00046 } 00047 if (m_decoder) { 00048 FLAC__stream_decoder_finish(m_decoder); 00049 FLAC__stream_decoder_delete(m_decoder); // frees memory 00050 m_decoder = NULL; 00051 } 00052 } 00053 00054 // soundsource overrides 00055 int SoundSourceFLAC::open() { 00056 m_file.open(QIODevice::ReadOnly); 00057 m_decoder = FLAC__stream_decoder_new(); 00058 if (m_decoder == NULL) { 00059 qWarning() << "SSFLAC: decoder allocation failed!"; 00060 return ERR; 00061 } 00062 FLAC__StreamDecoderInitStatus initStatus( 00063 FLAC__stream_decoder_init_stream( 00064 m_decoder, FLAC_read_cb, FLAC_seek_cb, FLAC_tell_cb, FLAC_length_cb, 00065 FLAC_eof_cb, FLAC_write_cb, FLAC_metadata_cb, FLAC_error_cb, 00066 (void*) this) 00067 ); 00068 if (initStatus != FLAC__STREAM_DECODER_INIT_STATUS_OK) { 00069 qWarning() << "SSFLAC: decoder init failed!"; 00070 goto decoderError; 00071 } 00072 if (!FLAC__stream_decoder_process_until_end_of_metadata(m_decoder)) { 00073 qWarning() << "SSFLAC: process to end of meta failed!"; 00074 qWarning() << "SSFLAC: decoder state: " << FLAC__stream_decoder_get_state(m_decoder); 00075 goto decoderError; 00076 } // now number of samples etc. should be populated 00077 if (m_flacBuffer == NULL) { 00078 // we want 2 samples per frame, see ::flacWrite code -- bkgood 00079 m_flacBuffer = new FLAC__int16[m_maxBlocksize * 2 /*m_iChannels*/]; 00080 } 00081 if (m_leftoverBuffer == NULL) { 00082 m_leftoverBuffer = new FLAC__int16[m_maxBlocksize * 2 /*m_iChannels*/]; 00083 } 00084 // qDebug() << "SSFLAC: Total samples: " << m_samples; 00085 // qDebug() << "SSFLAC: Sampling rate: " << m_iSampleRate << " Hz"; 00086 // qDebug() << "SSFLAC: Channels: " << m_iChannels; 00087 // qDebug() << "SSFLAC: BPS: " << m_bps; 00088 return OK; 00089 decoderError: 00090 FLAC__stream_decoder_finish(m_decoder); 00091 FLAC__stream_decoder_delete(m_decoder); 00092 m_decoder = NULL; 00093 return ERR; 00094 } 00095 00096 long SoundSourceFLAC::seek(long filepos) { 00097 if (!m_decoder) return 0; 00098 // important division here, filepos is in audio samples (i.e. shorts) 00099 // but libflac expects a number in time samples. I _think_ this should 00100 // be hard-coded at two because *2 is the assumption the caller makes 00101 // -- bkgood 00102 FLAC__stream_decoder_seek_absolute(m_decoder, filepos / 2); 00103 m_leftoverBufferLength = 0; // clear internal buffer since we moved 00104 return filepos; 00105 } 00106 00107 unsigned int SoundSourceFLAC::read(unsigned long size, const SAMPLE *destination) { 00108 if (!m_decoder) return 0; 00109 SAMPLE *destBuffer(const_cast<SAMPLE*>(destination)); 00110 unsigned int samplesWritten = 0; 00111 unsigned int i = 0; 00112 while (samplesWritten < size) { 00113 // if our buffer from libflac is empty (either because we explicitly cleared 00114 // it or because we've simply used all the samples), ask for a new buffer 00115 if (m_flacBufferLength == 0) { 00116 i = 0; 00117 if (!FLAC__stream_decoder_process_single(m_decoder)) { 00118 qWarning() << "SSFLAC: decoder_process_single returned false"; 00119 break; 00120 } else if (m_flacBufferLength == 0) { 00121 // EOF 00122 break; 00123 } 00124 } 00125 destBuffer[samplesWritten++] = m_flacBuffer[i++]; 00126 --m_flacBufferLength; 00127 } 00128 if (m_flacBufferLength != 0) { 00129 memcpy(m_leftoverBuffer, &m_flacBuffer[i], 00130 m_flacBufferLength * sizeof(m_flacBuffer[0])); // safe because leftoverBuffer 00131 // is as long as flacbuffer 00132 memcpy(m_flacBuffer, m_leftoverBuffer, 00133 m_flacBufferLength * sizeof(m_leftoverBuffer[0])); 00134 // this whole if block could go away if this just used a ring buffer but I'd 00135 // rather do that after I've gotten off the inital happiness of getting this right, 00136 // if I see SIGSEGV one more time I'll pop -- bkgood 00137 } 00138 return samplesWritten; 00139 } 00140 00141 inline unsigned long SoundSourceFLAC::length() { 00142 return m_samples * m_iChannels; 00143 } 00144 00145 int SoundSourceFLAC::parseHeader() { 00146 setType("flac"); 00147 #ifdef __WINDOWS__ 00148 /* From Tobias: A Utf-8 string did not work on my Windows XP (German edition) 00149 * If you try this conversion, f.isValid() will return false in many cases 00150 * and processTaglibFile() will fail 00151 * 00152 * The method toLocal8Bit() returns the local 8-bit representation of the string as a QByteArray. 00153 * The returned byte array is undefined if the string contains characters not supported 00154 * by the local 8-bit encoding. 00155 */ 00156 QByteArray qBAFilename = m_qFilename.toLocal8Bit(); 00157 #else 00158 QByteArray qBAFilename = m_qFilename.toUtf8(); 00159 #endif 00160 TagLib::FLAC::File f(qBAFilename.constData()); 00161 bool result = processTaglibFile(f); 00162 TagLib::ID3v2::Tag *id3v2(f.ID3v2Tag()); 00163 TagLib::Ogg::XiphComment *xiph(f.xiphComment()); 00164 if (id3v2) { 00165 processID3v2Tag(id3v2); 00166 } 00167 if (xiph) { 00168 processXiphComment(xiph); 00169 } 00170 return result ? OK : ERR; 00171 } 00172 00177 inline int SoundSourceFLAC::getShift() const { 00178 return 16 - m_bps; 00179 } 00180 00184 inline FLAC__int16 SoundSourceFLAC::shift(FLAC__int32 sample) const { 00185 // this is how libsndfile does this operation and is wonderfully 00186 // straightforward. Just shift the sample left or right so that 00187 // it fits in a 16-bit short. -- bkgood 00188 int shift(getShift()); 00189 if (shift == 0) { 00190 return sample; 00191 } else if (shift < 0) { 00192 return sample >> abs(shift); 00193 } else { 00194 return sample << shift; 00195 } 00196 }; 00197 00198 // static 00199 QList<QString> SoundSourceFLAC::supportedFileExtensions() { 00200 QList<QString> list; 00201 list.push_back("flac"); 00202 return list; 00203 } 00204 00205 00206 // flac callback methods 00207 FLAC__StreamDecoderReadStatus SoundSourceFLAC::flacRead(FLAC__byte buffer[], size_t *bytes) { 00208 *bytes = m_file.read((char*) buffer, *bytes); 00209 if (*bytes > 0) { 00210 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; 00211 } else if (*bytes == 0) { 00212 return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; 00213 } else { 00214 return FLAC__STREAM_DECODER_READ_STATUS_ABORT; 00215 } 00216 } 00217 00218 FLAC__StreamDecoderSeekStatus SoundSourceFLAC::flacSeek(FLAC__uint64 offset) { 00219 if (m_file.seek(offset)) { 00220 return FLAC__STREAM_DECODER_SEEK_STATUS_OK; 00221 } else { 00222 return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR; 00223 } 00224 } 00225 00226 FLAC__StreamDecoderTellStatus SoundSourceFLAC::flacTell(FLAC__uint64 *offset) { 00227 if (m_file.isSequential()) { 00228 return FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED; 00229 } 00230 *offset = m_file.pos(); 00231 return FLAC__STREAM_DECODER_TELL_STATUS_OK; 00232 } 00233 00234 FLAC__StreamDecoderLengthStatus SoundSourceFLAC::flacLength(FLAC__uint64 *length) { 00235 if (m_file.isSequential()) { 00236 return FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED; 00237 } 00238 *length = m_file.size(); 00239 return FLAC__STREAM_DECODER_LENGTH_STATUS_OK; 00240 } 00241 00242 FLAC__bool SoundSourceFLAC::flacEOF() { 00243 if (m_file.isSequential()) { 00244 return false; 00245 } 00246 return m_file.atEnd(); 00247 } 00248 00249 FLAC__StreamDecoderWriteStatus SoundSourceFLAC::flacWrite(const FLAC__Frame *frame, 00250 const FLAC__int32 *const buffer[]) { 00251 unsigned int i(0); 00252 m_flacBufferLength = 0; 00253 if (frame->header.channels > 1) { 00254 // stereo (or greater) 00255 for (i = 0; i < frame->header.blocksize; ++i) { 00256 m_flacBuffer[m_flacBufferLength++] = shift(buffer[0][i]); // left channel 00257 m_flacBuffer[m_flacBufferLength++] = shift(buffer[1][i]); // right channel 00258 } 00259 } else { 00260 // mono 00261 for (i = 0; i < frame->header.blocksize; ++i) { 00262 m_flacBuffer[m_flacBufferLength++] = shift(buffer[0][i]); // left channel 00263 m_flacBuffer[m_flacBufferLength++] = shift(buffer[0][i]); // mono channel 00264 } 00265 } 00266 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; // can't anticipate any errors here 00267 } 00268 00269 void SoundSourceFLAC::flacMetadata(const FLAC__StreamMetadata *metadata) { 00270 switch (metadata->type) { 00271 case FLAC__METADATA_TYPE_STREAMINFO: 00272 m_samples = metadata->data.stream_info.total_samples; 00273 m_iChannels = metadata->data.stream_info.channels; 00274 m_iSampleRate = metadata->data.stream_info.sample_rate; 00275 m_bps = metadata->data.stream_info.bits_per_sample; 00276 m_minBlocksize = metadata->data.stream_info.min_blocksize; 00277 m_maxBlocksize = metadata->data.stream_info.max_blocksize; 00278 m_minFramesize = metadata->data.stream_info.min_framesize; 00279 m_maxFramesize = metadata->data.stream_info.max_framesize; 00280 // qDebug() << "FLAC file " << m_qFilename; 00281 // qDebug() << m_iChannels << " @ " << m_iSampleRate << " Hz, " << m_samples 00282 // << " total, " << m_bps << " bps"; 00283 // qDebug() << "Blocksize in [" << m_minBlocksize << ", " << m_maxBlocksize 00284 // << "], Framesize in [" << m_minFramesize << ", " << m_maxFramesize << "]"; 00285 break; 00286 default: 00287 break; 00288 } 00289 } 00290 00291 void SoundSourceFLAC::flacError(FLAC__StreamDecoderErrorStatus status) { 00292 QString error; 00293 // not much can be done at this point -- luckly the decoder seems to be 00294 // pretty forgiving -- bkgood 00295 switch (status) { 00296 case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC: 00297 error = "STREAM_DECODER_ERROR_STATUS_LOST_SYNC"; 00298 break; 00299 case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER: 00300 error = "STREAM_DECODER_ERROR_STATUS_BAD_HEADER"; 00301 break; 00302 case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH: 00303 error = "STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH"; 00304 break; 00305 case FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM: 00306 error = "STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM"; 00307 break; 00308 } 00309 qWarning() << "SSFLAC got error" << error << "from libFLAC for file" 00310 << m_file.fileName(); 00311 // not much else to do here... whatever function that initiated whatever 00312 // decoder method resulted in this error will return an error, and the caller 00313 // will bail. libFLAC docs say to not close the decoder here -- bkgood 00314 } 00315 00316 // begin callbacks (have to be regular functions because normal libFLAC isn't C++-aware) 00317 00318 FLAC__StreamDecoderReadStatus FLAC_read_cb(const FLAC__StreamDecoder*, FLAC__byte buffer[], 00319 size_t *bytes, void *client_data) { 00320 return ((SoundSourceFLAC*) client_data)->flacRead(buffer, bytes); 00321 } 00322 00323 FLAC__StreamDecoderSeekStatus FLAC_seek_cb(const FLAC__StreamDecoder*, 00324 FLAC__uint64 absolute_byte_offset, void *client_data) { 00325 return ((SoundSourceFLAC*) client_data)->flacSeek(absolute_byte_offset); 00326 } 00327 00328 FLAC__StreamDecoderTellStatus FLAC_tell_cb(const FLAC__StreamDecoder*, 00329 FLAC__uint64 *absolute_byte_offset, void *client_data) { 00330 return ((SoundSourceFLAC*) client_data)->flacTell(absolute_byte_offset); 00331 } 00332 00333 FLAC__StreamDecoderLengthStatus FLAC_length_cb(const FLAC__StreamDecoder*, 00334 FLAC__uint64 *stream_length, void *client_data) { 00335 return ((SoundSourceFLAC*) client_data)->flacLength(stream_length); 00336 } 00337 00338 FLAC__bool FLAC_eof_cb(const FLAC__StreamDecoder*, void *client_data) { 00339 return ((SoundSourceFLAC*) client_data)->flacEOF(); 00340 } 00341 00342 FLAC__StreamDecoderWriteStatus FLAC_write_cb(const FLAC__StreamDecoder*, const FLAC__Frame *frame, 00343 const FLAC__int32 *const buffer[], void *client_data) { 00344 return ((SoundSourceFLAC*) client_data)->flacWrite(frame, buffer); 00345 } 00346 00347 void FLAC_metadata_cb(const FLAC__StreamDecoder*, const FLAC__StreamMetadata *metadata, void *client_data) { 00348 ((SoundSourceFLAC*) client_data)->flacMetadata(metadata); 00349 } 00350 00351 void FLAC_error_cb(const FLAC__StreamDecoder*, FLAC__StreamDecoderErrorStatus status, void *client_data) { 00352 ((SoundSourceFLAC*) client_data)->flacError(status); 00353 } 00354 // end callbacks