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 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_seekable(false), 00028 m_buffer(0), 00029 m_bufsiz(0), 00030 m_lastStart(0), 00031 m_lastCount(0), 00032 m_updating(fileUpdating) 00033 { 00034 m_frameCount = 0; 00035 m_channelCount = 0; 00036 m_sampleRate = 0; 00037 00038 m_fileInfo.format = 0; 00039 m_fileInfo.frames = 0; 00040 m_file = sf_open(m_path.toLocal8Bit(), SFM_READ, &m_fileInfo); 00041 00042 if (!m_file || (!fileUpdating && m_fileInfo.channels <= 0)) { 00043 cerr << "WavFileReader::initialize: Failed to open file at \"" 00044 << m_path << "\" (" 00045 << sf_strerror(m_file) << ")" << endl; 00046 00047 if (m_file) { 00048 m_error = QString("Couldn't load audio file '%1':\n%2") 00049 .arg(m_path).arg(sf_strerror(m_file)); 00050 } else { 00051 m_error = QString("Failed to open audio file '%1'") 00052 .arg(m_path); 00053 } 00054 return; 00055 } 00056 00057 if (m_fileInfo.channels > 0) { 00058 00059 m_frameCount = m_fileInfo.frames; 00060 m_channelCount = m_fileInfo.channels; 00061 m_sampleRate = m_fileInfo.samplerate; 00062 00063 m_seekable = (m_fileInfo.seekable != 0); 00064 00065 // Our m_seekable reports whether a file is rapidly seekable, 00066 // so things like Ogg don't qualify. We cautiously report 00067 // every file type of "at least" the historical period of Ogg 00068 // or FLAC as non-seekable. 00069 int type = m_fileInfo.format & SF_FORMAT_TYPEMASK; 00070 // cerr << "WavFileReader: format type is " << type << " (flac, ogg are " << SF_FORMAT_FLAC << ", " << SF_FORMAT_OGG << ")" << endl; 00071 if (type >= SF_FORMAT_FLAC || type >= SF_FORMAT_OGG) { 00072 // cerr << "WavFileReader: Recording as non-seekable" << endl; 00073 m_seekable = false; 00074 } 00075 } 00076 00077 // cerr << "WavFileReader: Frame count " << m_frameCount << ", channel count " << m_channelCount << ", sample rate " << m_sampleRate << ", seekable " << m_seekable << endl; 00078 00079 } 00080 00081 WavFileReader::~WavFileReader() 00082 { 00083 if (m_file) sf_close(m_file); 00084 delete[] m_buffer; 00085 } 00086 00087 void 00088 WavFileReader::updateFrameCount() 00089 { 00090 QMutexLocker locker(&m_mutex); 00091 00092 int prevCount = m_fileInfo.frames; 00093 00094 if (m_file) { 00095 sf_close(m_file); 00096 m_file = sf_open(m_path.toLocal8Bit(), SFM_READ, &m_fileInfo); 00097 if (!m_file || m_fileInfo.channels <= 0) { 00098 cerr << "WavFileReader::updateFrameCount: Failed to open file at \"" << m_path << "\" (" 00099 << sf_strerror(m_file) << ")" << endl; 00100 } 00101 } 00102 00103 // SVDEBUG << "WavFileReader::updateFrameCount: now " << m_fileInfo.frames << endl; 00104 00105 m_frameCount = m_fileInfo.frames; 00106 00107 if (m_channelCount == 0) { 00108 m_channelCount = m_fileInfo.channels; 00109 m_sampleRate = m_fileInfo.samplerate; 00110 } 00111 00112 if (m_frameCount != prevCount) { 00113 // cerr << "frameCountChanged" << endl; 00114 emit frameCountChanged(); 00115 } 00116 } 00117 00118 void 00119 WavFileReader::updateDone() 00120 { 00121 updateFrameCount(); 00122 m_updating = false; 00123 } 00124 00125 void 00126 WavFileReader::getInterleavedFrames(int start, int count, 00127 SampleBlock &results) const 00128 { 00129 if (count == 0) return; 00130 results.clear(); 00131 results.reserve(count * m_fileInfo.channels); 00132 00133 QMutexLocker locker(&m_mutex); 00134 00135 if (!m_file || !m_channelCount) { 00136 return; 00137 } 00138 00139 if ((long)start >= m_fileInfo.frames) { 00140 // SVDEBUG << "WavFileReader::getInterleavedFrames: " << start 00141 // << " > " << m_fileInfo.frames << endl; 00142 return; 00143 } 00144 00145 if (long(start + count) > m_fileInfo.frames) { 00146 count = m_fileInfo.frames - start; 00147 } 00148 00149 sf_count_t readCount = 0; 00150 00151 if (start != m_lastStart || count != m_lastCount) { 00152 00153 if (sf_seek(m_file, start, SEEK_SET) < 0) { 00154 // cerr << "sf_seek failed" << endl; 00155 return; 00156 } 00157 00158 if (count * m_fileInfo.channels > m_bufsiz) { 00159 // cerr << "WavFileReader: Reallocating buffer for " << count 00160 // << " frames, " << m_fileInfo.channels << " channels: " 00161 // << m_bufsiz << " floats" << endl; 00162 m_bufsiz = count * m_fileInfo.channels; 00163 delete[] m_buffer; 00164 m_buffer = new float[m_bufsiz]; 00165 } 00166 00167 if ((readCount = sf_readf_float(m_file, m_buffer, count)) < 0) { 00168 // cerr << "sf_readf_float failed" << endl; 00169 return; 00170 } 00171 00172 m_lastStart = start; 00173 m_lastCount = readCount; 00174 } 00175 00176 for (int i = 0; i < count * m_fileInfo.channels; ++i) { 00177 if (i >= m_bufsiz) { 00178 cerr << "INTERNAL ERROR: WavFileReader::getInterleavedFrames: " << i << " >= " << m_bufsiz << endl; 00179 } 00180 results.push_back(m_buffer[i]); 00181 } 00182 00183 return; 00184 } 00185 00186 void 00187 WavFileReader::getSupportedExtensions(std::set<QString> &extensions) 00188 { 00189 int count; 00190 00191 if (sf_command(0, SFC_GET_FORMAT_MAJOR_COUNT, &count, sizeof(count))) { 00192 extensions.insert("wav"); 00193 extensions.insert("aiff"); 00194 extensions.insert("aifc"); 00195 extensions.insert("aif"); 00196 return; 00197 } 00198 00199 SF_FORMAT_INFO info; 00200 for (int i = 0; i < count; ++i) { 00201 info.format = i; 00202 if (!sf_command(0, SFC_GET_FORMAT_MAJOR, &info, sizeof(info))) { 00203 QString ext = QString(info.extension).toLower(); 00204 extensions.insert(ext); 00205 if (ext == "oga") { 00206 // libsndfile is awfully proper, it says it only 00207 // supports .oga but lots of Ogg audio files in the 00208 // wild are .ogg and it will accept that 00209 extensions.insert("ogg"); 00210 } 00211 } 00212 } 00213 } 00214 00215 bool 00216 WavFileReader::supportsExtension(QString extension) 00217 { 00218 std::set<QString> extensions; 00219 getSupportedExtensions(extensions); 00220 return (extensions.find(extension.toLower()) != extensions.end()); 00221 } 00222 00223 bool 00224 WavFileReader::supportsContentType(QString type) 00225 { 00226 return (type == "audio/x-wav" || 00227 type == "audio/x-aiff" || 00228 type == "audio/basic"); 00229 } 00230 00231 bool 00232 WavFileReader::supports(FileSource &source) 00233 { 00234 return (supportsExtension(source.getExtension()) || 00235 supportsContentType(source.getContentType())); 00236 } 00237 00238