annotate data/fileio/WavFileReader.cpp @ 808:67003fb58ba4

Merge from branch "qt5". This revision actually builds with Qt4 (late releases) or Qt5, though it will warn on configure with Qt4.
author Chris Cannam
date Tue, 14 May 2013 12:36:05 +0100
parents 459235dccff6
children f0558e69a074
rev   line source
Chris@148 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@148 2
Chris@148 3 /*
Chris@148 4 Sonic Visualiser
Chris@148 5 An audio file viewer and annotation editor.
Chris@148 6 Centre for Digital Music, Queen Mary, University of London.
Chris@202 7 This file copyright 2006 Chris Cannam and QMUL.
Chris@148 8
Chris@148 9 This program is free software; you can redistribute it and/or
Chris@148 10 modify it under the terms of the GNU General Public License as
Chris@148 11 published by the Free Software Foundation; either version 2 of the
Chris@148 12 License, or (at your option) any later version. See the file
Chris@148 13 COPYING included with this distribution for more information.
Chris@148 14 */
Chris@148 15
Chris@148 16 #include "WavFileReader.h"
Chris@148 17
Chris@148 18 #include <iostream>
Chris@148 19
Chris@175 20 #include <QMutexLocker>
Chris@316 21 #include <QFileInfo>
Chris@175 22
Chris@317 23 WavFileReader::WavFileReader(FileSource source, bool fileUpdating) :
Chris@148 24 m_file(0),
Chris@316 25 m_source(source),
Chris@316 26 m_path(source.getLocalFilename()),
Chris@148 27 m_buffer(0),
Chris@148 28 m_bufsiz(0),
Chris@148 29 m_lastStart(0),
Chris@176 30 m_lastCount(0),
Chris@176 31 m_updating(fileUpdating)
Chris@148 32 {
Chris@148 33 m_frameCount = 0;
Chris@148 34 m_channelCount = 0;
Chris@148 35 m_sampleRate = 0;
Chris@148 36
Chris@148 37 m_fileInfo.format = 0;
Chris@148 38 m_fileInfo.frames = 0;
Chris@290 39 m_file = sf_open(m_path.toLocal8Bit(), SFM_READ, &m_fileInfo);
Chris@148 40
Chris@187 41 if (!m_file || (!fileUpdating && m_fileInfo.channels <= 0)) {
Chris@682 42 std::cerr << "WavFileReader::initialize: Failed to open file at \""
Chris@686 43 << m_path << "\" ("
Chris@148 44 << sf_strerror(m_file) << ")" << std::endl;
Chris@148 45
Chris@148 46 if (m_file) {
Chris@290 47 m_error = QString("Couldn't load audio file '%1':\n%2")
Chris@290 48 .arg(m_path).arg(sf_strerror(m_file));
Chris@148 49 } else {
Chris@290 50 m_error = QString("Failed to open audio file '%1'")
Chris@290 51 .arg(m_path);
Chris@148 52 }
Chris@148 53 return;
Chris@148 54 }
Chris@148 55
Chris@187 56 if (m_fileInfo.channels > 0) {
Chris@187 57 m_frameCount = m_fileInfo.frames;
Chris@187 58 m_channelCount = m_fileInfo.channels;
Chris@187 59 m_sampleRate = m_fileInfo.samplerate;
Chris@187 60 }
Chris@175 61
Chris@259 62 // std::cerr << "WavFileReader: Frame count " << m_frameCount << ", channel count " << m_channelCount << ", sample rate " << m_sampleRate << std::endl;
Chris@175 63
Chris@148 64 }
Chris@148 65
Chris@148 66 WavFileReader::~WavFileReader()
Chris@148 67 {
Chris@148 68 if (m_file) sf_close(m_file);
Chris@564 69 delete[] m_buffer;
Chris@148 70 }
Chris@148 71
Chris@148 72 void
Chris@175 73 WavFileReader::updateFrameCount()
Chris@175 74 {
Chris@175 75 QMutexLocker locker(&m_mutex);
Chris@175 76
Chris@175 77 size_t prevCount = m_fileInfo.frames;
Chris@175 78
Chris@175 79 if (m_file) {
Chris@175 80 sf_close(m_file);
Chris@290 81 m_file = sf_open(m_path.toLocal8Bit(), SFM_READ, &m_fileInfo);
Chris@175 82 if (!m_file || m_fileInfo.channels <= 0) {
Chris@686 83 std::cerr << "WavFileReader::updateFrameCount: Failed to open file at \"" << m_path << "\" ("
Chris@175 84 << sf_strerror(m_file) << ")" << std::endl;
Chris@175 85 }
Chris@175 86 }
Chris@175 87
Chris@690 88 // SVDEBUG << "WavFileReader::updateFrameCount: now " << m_fileInfo.frames << endl;
Chris@175 89
Chris@176 90 m_frameCount = m_fileInfo.frames;
Chris@176 91
Chris@187 92 if (m_channelCount == 0) {
Chris@187 93 m_channelCount = m_fileInfo.channels;
Chris@187 94 m_sampleRate = m_fileInfo.samplerate;
Chris@187 95 }
Chris@187 96
Chris@258 97 if (m_frameCount != prevCount) {
Chris@258 98 // std::cerr << "frameCountChanged" << std::endl;
Chris@258 99 emit frameCountChanged();
Chris@258 100 }
Chris@176 101 }
Chris@176 102
Chris@176 103 void
Chris@176 104 WavFileReader::updateDone()
Chris@176 105 {
Chris@176 106 updateFrameCount();
Chris@176 107 m_updating = false;
Chris@175 108 }
Chris@175 109
Chris@175 110 void
Chris@148 111 WavFileReader::getInterleavedFrames(size_t start, size_t count,
Chris@148 112 SampleBlock &results) const
Chris@148 113 {
Chris@175 114 if (count == 0) return;
Chris@148 115 results.clear();
Chris@377 116 results.reserve(count * m_fileInfo.channels);
Chris@175 117
Chris@175 118 QMutexLocker locker(&m_mutex);
Chris@175 119
Chris@175 120 if (!m_file || !m_channelCount) {
Chris@175 121 return;
Chris@175 122 }
Chris@148 123
Chris@148 124 if ((long)start >= m_fileInfo.frames) {
Chris@690 125 // SVDEBUG << "WavFileReader::getInterleavedFrames: " << start
Chris@687 126 // << " > " << m_fileInfo.frames << endl;
Chris@148 127 return;
Chris@148 128 }
Chris@148 129
Chris@148 130 if (long(start + count) > m_fileInfo.frames) {
Chris@148 131 count = m_fileInfo.frames - start;
Chris@148 132 }
Chris@148 133
Chris@148 134 sf_count_t readCount = 0;
Chris@148 135
Chris@148 136 if (start != m_lastStart || count != m_lastCount) {
Chris@148 137
Chris@148 138 if (sf_seek(m_file, start, SEEK_SET) < 0) {
Chris@175 139 // std::cerr << "sf_seek failed" << std::endl;
Chris@148 140 return;
Chris@148 141 }
Chris@148 142
Chris@148 143 if (count * m_fileInfo.channels > m_bufsiz) {
Chris@148 144 // std::cerr << "WavFileReader: Reallocating buffer for " << count
Chris@148 145 // << " frames, " << m_fileInfo.channels << " channels: "
Chris@148 146 // << m_bufsiz << " floats" << std::endl;
Chris@148 147 m_bufsiz = count * m_fileInfo.channels;
Chris@148 148 delete[] m_buffer;
Chris@148 149 m_buffer = new float[m_bufsiz];
Chris@148 150 }
Chris@148 151
Chris@148 152 if ((readCount = sf_readf_float(m_file, m_buffer, count)) < 0) {
Chris@175 153 // std::cerr << "sf_readf_float failed" << std::endl;
Chris@148 154 return;
Chris@148 155 }
Chris@148 156
Chris@148 157 m_lastStart = start;
Chris@148 158 m_lastCount = readCount;
Chris@148 159 }
Chris@148 160
Chris@148 161 for (size_t i = 0; i < count * m_fileInfo.channels; ++i) {
Chris@232 162 if (i >= m_bufsiz) {
Chris@232 163 std::cerr << "INTERNAL ERROR: WavFileReader::getInterleavedFrames: " << i << " >= " << m_bufsiz << std::endl;
Chris@232 164 }
Chris@148 165 results.push_back(m_buffer[i]);
Chris@148 166 }
Chris@148 167
Chris@148 168 return;
Chris@148 169 }
Chris@148 170
Chris@157 171 void
Chris@290 172 WavFileReader::getSupportedExtensions(std::set<QString> &extensions)
Chris@157 173 {
Chris@157 174 int count;
Chris@157 175
Chris@157 176 if (sf_command(0, SFC_GET_FORMAT_MAJOR_COUNT, &count, sizeof(count))) {
Chris@157 177 extensions.insert("wav");
Chris@157 178 extensions.insert("aiff");
Chris@316 179 extensions.insert("aifc");
Chris@157 180 extensions.insert("aif");
Chris@157 181 return;
Chris@157 182 }
Chris@157 183
Chris@157 184 SF_FORMAT_INFO info;
Chris@157 185 for (int i = 0; i < count; ++i) {
Chris@157 186 info.format = i;
Chris@157 187 if (!sf_command(0, SFC_GET_FORMAT_MAJOR, &info, sizeof(info))) {
Chris@783 188 QString ext = QString(info.extension).toLower();
Chris@783 189 extensions.insert(ext);
Chris@783 190 if (ext == "oga") {
Chris@783 191 // libsndfile is awfully proper, it says it only
Chris@783 192 // supports .oga but lots of Ogg audio files in the
Chris@783 193 // wild are .ogg and it will accept that
Chris@783 194 extensions.insert("ogg");
Chris@783 195 }
Chris@157 196 }
Chris@157 197 }
Chris@157 198 }
Chris@316 199
Chris@316 200 bool
Chris@316 201 WavFileReader::supportsExtension(QString extension)
Chris@316 202 {
Chris@316 203 std::set<QString> extensions;
Chris@316 204 getSupportedExtensions(extensions);
Chris@316 205 return (extensions.find(extension.toLower()) != extensions.end());
Chris@316 206 }
Chris@316 207
Chris@316 208 bool
Chris@316 209 WavFileReader::supportsContentType(QString type)
Chris@316 210 {
Chris@316 211 return (type == "audio/x-wav" ||
Chris@316 212 type == "audio/x-aiff" ||
Chris@316 213 type == "audio/basic");
Chris@316 214 }
Chris@316 215
Chris@316 216 bool
Chris@317 217 WavFileReader::supports(FileSource &source)
Chris@316 218 {
Chris@316 219 return (supportsExtension(source.getExtension()) ||
Chris@316 220 supportsContentType(source.getContentType()));
Chris@316 221 }
Chris@316 222
Chris@316 223