WavFileReader.cpp

Go to the documentation of this file.
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 and QMUL.
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 #include "WavFileReader.h"
00017 
00018 #include <iostream>
00019 
00020 #include <QMutexLocker>
00021 #include <QFileInfo>
00022 
00023 WavFileReader::WavFileReader(FileSource source, bool fileUpdating) :
00024     m_file(0),
00025     m_source(source),
00026     m_path(source.getLocalFilename()),
00027     m_buffer(0),
00028     m_bufsiz(0),
00029     m_lastStart(0),
00030     m_lastCount(0),
00031     m_updating(fileUpdating)
00032 {
00033     m_frameCount = 0;
00034     m_channelCount = 0;
00035     m_sampleRate = 0;
00036 
00037     m_fileInfo.format = 0;
00038     m_fileInfo.frames = 0;
00039     m_file = sf_open(m_path.toLocal8Bit(), SFM_READ, &m_fileInfo);
00040 
00041     if (!m_file || (!fileUpdating && m_fileInfo.channels <= 0)) {
00042         std::cerr << "WavFileReader::initialize: Failed to open file ("
00043                   << sf_strerror(m_file) << ")" << std::endl;
00044 
00045         if (m_file) {
00046             m_error = QString("Couldn't load audio file '%1':\n%2")
00047                 .arg(m_path).arg(sf_strerror(m_file));
00048         } else {
00049             m_error = QString("Failed to open audio file '%1'")
00050                 .arg(m_path);
00051         }
00052         return;
00053     }
00054 
00055     if (m_fileInfo.channels > 0) {
00056         m_frameCount = m_fileInfo.frames;
00057         m_channelCount = m_fileInfo.channels;
00058         m_sampleRate = m_fileInfo.samplerate;
00059     }
00060 
00061 //    std::cerr << "WavFileReader: Frame count " << m_frameCount << ", channel count " << m_channelCount << ", sample rate " << m_sampleRate << std::endl;
00062 
00063 }
00064 
00065 WavFileReader::~WavFileReader()
00066 {
00067     if (m_file) sf_close(m_file);
00068 }
00069 
00070 void
00071 WavFileReader::updateFrameCount()
00072 {
00073     QMutexLocker locker(&m_mutex);
00074 
00075     size_t prevCount = m_fileInfo.frames;
00076 
00077     if (m_file) {
00078         sf_close(m_file);
00079         m_file = sf_open(m_path.toLocal8Bit(), SFM_READ, &m_fileInfo);
00080         if (!m_file || m_fileInfo.channels <= 0) {
00081             std::cerr << "WavFileReader::updateFrameCount: Failed to open file ("
00082                       << sf_strerror(m_file) << ")" << std::endl;
00083         }
00084     }
00085 
00086 //    std::cerr << "WavFileReader::updateFrameCount: now " << m_fileInfo.frames << std::endl;
00087 
00088     m_frameCount = m_fileInfo.frames;
00089 
00090     if (m_channelCount == 0) {
00091         m_channelCount = m_fileInfo.channels;
00092         m_sampleRate = m_fileInfo.samplerate;
00093     }
00094 
00095     if (m_frameCount != prevCount) {
00096 //        std::cerr << "frameCountChanged" << std::endl;
00097         emit frameCountChanged();
00098     }
00099 }
00100 
00101 void
00102 WavFileReader::updateDone()
00103 {
00104     updateFrameCount();
00105     m_updating = false;
00106 }
00107 
00108 void
00109 WavFileReader::getInterleavedFrames(size_t start, size_t count,
00110                                     SampleBlock &results) const
00111 {
00112     if (count == 0) return;
00113     results.clear();
00114     results.reserve(count * m_fileInfo.channels);
00115 
00116     QMutexLocker locker(&m_mutex);
00117 
00118     if (!m_file || !m_channelCount) {
00119         return;
00120     }
00121 
00122     if ((long)start >= m_fileInfo.frames) {
00123 //        std::cerr << "WavFileReader::getInterleavedFrames: " << start
00124 //                  << " > " << m_fileInfo.frames << std::endl;
00125         return;
00126     }
00127 
00128     if (long(start + count) > m_fileInfo.frames) {
00129         count = m_fileInfo.frames - start;
00130     }
00131 
00132     sf_count_t readCount = 0;
00133 
00134     if (start != m_lastStart || count != m_lastCount) {
00135 
00136         if (sf_seek(m_file, start, SEEK_SET) < 0) {
00137 //            std::cerr << "sf_seek failed" << std::endl;
00138             return;
00139         }
00140         
00141         if (count * m_fileInfo.channels > m_bufsiz) {
00142 //          std::cerr << "WavFileReader: Reallocating buffer for " << count
00143 //                    << " frames, " << m_fileInfo.channels << " channels: "
00144 //                    << m_bufsiz << " floats" << std::endl;
00145             m_bufsiz = count * m_fileInfo.channels;
00146             delete[] m_buffer;
00147             m_buffer = new float[m_bufsiz];
00148         }
00149         
00150         if ((readCount = sf_readf_float(m_file, m_buffer, count)) < 0) {
00151 //            std::cerr << "sf_readf_float failed" << std::endl;
00152             return;
00153         }
00154 
00155         m_lastStart = start;
00156         m_lastCount = readCount;
00157     }
00158 
00159     for (size_t i = 0; i < count * m_fileInfo.channels; ++i) {
00160         if (i >= m_bufsiz) {
00161             std::cerr << "INTERNAL ERROR: WavFileReader::getInterleavedFrames: " << i << " >= " << m_bufsiz << std::endl;
00162         }
00163         results.push_back(m_buffer[i]);
00164     }
00165 
00166     return;
00167 }
00168 
00169 void
00170 WavFileReader::getSupportedExtensions(std::set<QString> &extensions)
00171 {
00172     int count;
00173 
00174     if (sf_command(0, SFC_GET_FORMAT_MAJOR_COUNT, &count, sizeof(count))) {
00175         extensions.insert("wav");
00176         extensions.insert("aiff");
00177         extensions.insert("aifc");
00178         extensions.insert("aif");
00179         return;
00180     }
00181 
00182     SF_FORMAT_INFO info;
00183     for (int i = 0; i < count; ++i) {
00184         info.format = i;
00185         if (!sf_command(0, SFC_GET_FORMAT_MAJOR, &info, sizeof(info))) {
00186             extensions.insert(QString(info.extension).toLower());
00187         }
00188     }
00189 }
00190 
00191 bool
00192 WavFileReader::supportsExtension(QString extension)
00193 {
00194     std::set<QString> extensions;
00195     getSupportedExtensions(extensions);
00196     return (extensions.find(extension.toLower()) != extensions.end());
00197 }
00198 
00199 bool
00200 WavFileReader::supportsContentType(QString type)
00201 {
00202     return (type == "audio/x-wav" ||
00203             type == "audio/x-aiff" ||
00204             type == "audio/basic");
00205 }
00206 
00207 bool
00208 WavFileReader::supports(FileSource &source)
00209 {
00210     return (supportsExtension(source.getExtension()) ||
00211             supportsContentType(source.getContentType()));
00212 }
00213 
00214 

Generated on Wed Feb 20 15:45:30 2008 for SonicVisualiser by  doxygen 1.5.1