Mixxx

/home/maxime/Projets/Mixxx/1.10/mixxx/src/soundsourceoggvorbis.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                           soundsourceoggvorbis.cpp  -  ogg vorbis decoder
00003                              -------------------
00004     copyright            : (C) 2003 by Svein Magne Bang
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/vorbisfile.h>
00018 
00019 #include "trackinfoobject.h"
00020 #include "soundsourceoggvorbis.h"
00021 #include <QtDebug>
00022 #ifdef __WINDOWS__
00023 #include <io.h>
00024 #include <fcntl.h>
00025 #endif
00026 
00027 #ifdef __APPLE__
00028 #ifdef __i386
00029 #define OV_ENDIAN_ARG 0
00030 #else
00031 #define OV_ENDIAN_ARG 1
00032 #endif
00033 #endif
00034 
00035 #ifdef __LINUX__
00036 #include <endian.h>
00037 #if __BYTE_ORDER == __LITTLE_ENDIAN
00038 #define OV_ENDIAN_ARG 0
00039 #else
00040 #define OV_ENDIAN_ARG 1
00041 #endif
00042 #else
00043 #define OV_ENDIAN_ARG 0
00044 #endif
00045 
00046 /*
00047    Class for reading Ogg Vorbis
00048  */
00049 
00050 SoundSourceOggVorbis::SoundSourceOggVorbis(QString qFilename)
00051 : Mixxx::SoundSource(qFilename)
00052 {
00053     filelength = 0;
00054 }
00055 
00056 SoundSourceOggVorbis::~SoundSourceOggVorbis()
00057 {
00058     if (filelength > 0){
00059         ov_clear(&vf);
00060     }
00061 }
00062 
00063 int SoundSourceOggVorbis::open()
00064 {
00065 #ifdef __WINDOWS__
00066     QByteArray qBAFilename = m_qFilename.toLocal8Bit();
00067     if(ov_fopen(qBAFilename.data(), &vf) < 0) {
00068         qDebug() << "oggvorbis: Input does not appear to be an Ogg bitstream.";
00069         filelength = 0;
00070         return ERR;
00071     }
00072 #else
00073     QByteArray qBAFilename = m_qFilename.toUtf8();
00074     FILE *vorbisfile =  fopen(qBAFilename.data(), "r");
00075 
00076     if (!vorbisfile) {
00077         qDebug() << "oggvorbis: cannot open" << m_qFilename;
00078         return ERR;
00079     }
00080 
00081     if(ov_open(vorbisfile, &vf, NULL, 0) < 0) {
00082         qDebug() << "oggvorbis: Input does not appear to be an Ogg bitstream.";
00083         filelength = 0;
00084         return ERR;
00085     }
00086 #endif
00087 
00088     // lookup the ogg's channels and samplerate
00089     vorbis_info * vi = ov_info(&vf, -1);
00090 
00091     channels = vi->channels;
00092     m_iSampleRate = vi->rate;
00093 
00094     if(channels > 2){
00095         qDebug() << "oggvorbis: No support for more than 2 channels!";
00096         ov_clear(&vf);
00097         filelength = 0;
00098         return ERR;
00099     }
00100 
00101     // ov_pcm_total returns the total number of frames in the ogg file. The
00102     // frame is the channel-independent measure of samples. The total samples in
00103     // the file is channels * ov_pcm_total. rryan 7/2009 I verified this by
00104     // hand. a 30 second long 48khz mono ogg and a 48khz stereo ogg both report
00105     // 1440000 for ov_pcm_total.
00106     ogg_int64_t ret = ov_pcm_total(&vf, -1);
00107 
00108     if (ret >= 0) {
00109         // We pretend that the file is stereo to the rest of the world.
00110         filelength = ret * 2;
00111     }
00112     else //error
00113     {
00114       if (ret == OV_EINVAL) {
00115           //The file is not seekable. Not sure if any action is needed.
00116       }
00117     }
00118 
00119     return OK;
00120 
00121 }
00122 
00123 /*
00124    seek to <filepos>
00125  */
00126 
00127 long SoundSourceOggVorbis::seek(long filepos)
00128 {
00129     // In our speak, filepos is a sample in the file abstraction (i.e. it's
00130     // stereo no matter what). filepos/2 is the frame we want to seek to.
00131     Q_ASSERT(filepos%2==0);
00132 
00133     if (ov_seekable(&vf)){
00134         if(ov_pcm_seek(&vf, filepos/2) != 0) {
00135             // This is totally common (i.e. you're at EOF). Let's not leave this
00136             // qDebug on.
00137 
00138             // qDebug() << "ogg vorbis: Seek ERR on seekable.";
00139         }
00140 
00141         // Even if an error occured, return them the current position because
00142         // that's what we promised. (Double it because ov_pcm_tell returns
00143         // frames and we pretend to the world that everything is stereo)
00144         return ov_pcm_tell(&vf) * 2;
00145     } else{
00146         qDebug() << "ogg vorbis: Seek ERR.";
00147         return 0;
00148     }
00149 }
00150 
00151 
00152 /*
00153    read <size> samples into <destination>, and return the number of
00154    samples actually read.
00155  */
00156 
00157 unsigned SoundSourceOggVorbis::read(volatile unsigned long size, const SAMPLE * destination)
00158 {
00159 
00160     Q_ASSERT(size%2==0);
00161 
00162     char *pRead  = (char*) destination;
00163     SAMPLE *dest   = (SAMPLE*) destination;
00164 
00165 
00166 
00167     // 'needed' is size of buffer in bytes. 'size' is size in SAMPLEs,
00168     // which is 2 bytes.  If the stream is mono, we read 'size' bytes,
00169     // so that half the buffer is full, then below we double each
00170     // sample on the left and right channel. If the stream is stereo,
00171     // then ov_read interleaves the samples into the full length of
00172     // the buffer.
00173 
00174     // ov_read speaks bytes, we speak words.  needed is the bytes to
00175     // read, not words to read.
00176 
00177     // size is the maximum space in words that we have in
00178     // destination. For stereo files, read the full buffer (size*2
00179     // bytes). For mono files, only read half the buffer (size bytes),
00180     // and we will double the buffer to be in stereo later.
00181     unsigned int needed = size * channels;
00182 
00183     unsigned int index=0,ret=0;
00184 
00185     // loop until requested number of samples has been retrieved
00186     while (needed > 0) {
00187         // read samples into buffer
00188         ret = ov_read(&vf, pRead+index, needed, OV_ENDIAN_ARG, 2, 1, &current_section);
00189 
00190         if (ret <= 0) {
00191             // An error or EOF occured, break out and return what we have sofar.
00192             break;
00193         }
00194 
00195         index  += ret;
00196         needed -= ret;
00197     }
00198 
00199     // As of here, index is the total bytes read. (index/2/channels) is the
00200     // total frames read.
00201 
00202     // convert into stereo if file is mono
00203     if (channels == 1) {
00204         // rryan 2/2009
00205         // Mini-proof of the below:
00206         // size = 20, destination is a 20 element array 0-19
00207         // readNo = 10 (or less, but 10 in this case)
00208         // i = 10-1 = 9, so dest[9*2] and dest[9*2+1],
00209         // so the first iteration touches the very ends of destination
00210         // on the last iteration, dest[0] and dest[1] are assigned to dest[0]
00211         for(int i=(index/2-1); i>=0; i--) {
00212             dest[i*2]     = dest[i];
00213             dest[(i*2)+1] = dest[i];
00214         }
00215 
00216         // Pretend we read twice as many bytes as we did, since we just repeated
00217         // each pair of bytes.
00218         index *= 2;
00219     }
00220 
00221     // index is the total bytes read, so the words read is index/2
00222     return index / 2;
00223 }
00224 
00225 /*
00226    Parse the the file to get metadata
00227  */
00228 int SoundSourceOggVorbis::parseHeader() {
00229     setType("ogg");
00230 
00231 #ifdef __WINDOWS__
00232     /* From Tobias: A Utf-8 string did not work on my Windows XP (German edition)
00233      * If you try this conversion, f.isValid() will return false in many cases
00234      * and processTaglibFile() will fail
00235      *
00236      * The method toLocal8Bit() returns the local 8-bit representation of the string as a QByteArray.
00237      * The returned byte array is undefined if the string contains characters not supported
00238      * by the local 8-bit encoding.
00239      */
00240     QByteArray qBAFilename = m_qFilename.toLocal8Bit();
00241 #else
00242     QByteArray qBAFilename = m_qFilename.toUtf8();
00243 #endif
00244     TagLib::Ogg::Vorbis::File f(qBAFilename.constData());
00245 
00246     // Takes care of all the default metadata
00247     bool result = processTaglibFile(f);
00248 
00249 
00250     TagLib::Ogg::XiphComment *tag = f.tag();
00251 
00252     if (tag) {
00253         processXiphComment(tag);
00254     }
00255 
00256     if (result)
00257         return OK;
00258     return ERR;
00259 }
00260 
00261 /*
00262    Return the length of the file in samples.
00263  */
00264 
00265 inline long unsigned SoundSourceOggVorbis::length()
00266 {
00267     return filelength;
00268 }
00269 
00270 QList<QString> SoundSourceOggVorbis::supportedFileExtensions()
00271 {
00272     QList<QString> list;
00273     list.push_back("ogg");
00274     return list;
00275 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines