annotate data/fileio/WavFileReader.cpp @ 263:71dfc6ab3b54

* Threaded mp3/ogg file reading. Not activated yet, as it doesn't work in context (SV needs to know the duration of its main model at the outset)
author Chris Cannam
date Thu, 24 May 2007 16:20:22 +0000
parents dc46851837d6
children 20028c634494
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@175 21
Chris@176 22 WavFileReader::WavFileReader(QString path, bool fileUpdating) :
Chris@148 23 m_file(0),
Chris@148 24 m_path(path),
Chris@148 25 m_buffer(0),
Chris@148 26 m_bufsiz(0),
Chris@148 27 m_lastStart(0),
Chris@176 28 m_lastCount(0),
Chris@176 29 m_updating(fileUpdating)
Chris@148 30 {
Chris@148 31 m_frameCount = 0;
Chris@148 32 m_channelCount = 0;
Chris@148 33 m_sampleRate = 0;
Chris@148 34
Chris@148 35 m_fileInfo.format = 0;
Chris@148 36 m_fileInfo.frames = 0;
Chris@148 37 m_file = sf_open(m_path.toLocal8Bit(), SFM_READ, &m_fileInfo);
Chris@148 38
Chris@187 39 if (!m_file || (!fileUpdating && m_fileInfo.channels <= 0)) {
Chris@148 40 std::cerr << "WavFileReader::initialize: Failed to open file ("
Chris@148 41 << sf_strerror(m_file) << ")" << std::endl;
Chris@148 42
Chris@148 43 if (m_file) {
Chris@148 44 m_error = QString("Couldn't load audio file '%1':\n%2")
Chris@148 45 .arg(m_path).arg(sf_strerror(m_file));
Chris@148 46 } else {
Chris@148 47 m_error = QString("Failed to open audio file '%1'")
Chris@148 48 .arg(m_path);
Chris@148 49 }
Chris@148 50 return;
Chris@148 51 }
Chris@148 52
Chris@187 53 if (m_fileInfo.channels > 0) {
Chris@187 54 m_frameCount = m_fileInfo.frames;
Chris@187 55 m_channelCount = m_fileInfo.channels;
Chris@187 56 m_sampleRate = m_fileInfo.samplerate;
Chris@187 57 }
Chris@175 58
Chris@259 59 // std::cerr << "WavFileReader: Frame count " << m_frameCount << ", channel count " << m_channelCount << ", sample rate " << m_sampleRate << std::endl;
Chris@175 60
Chris@148 61 }
Chris@148 62
Chris@148 63 WavFileReader::~WavFileReader()
Chris@148 64 {
Chris@148 65 if (m_file) sf_close(m_file);
Chris@148 66 }
Chris@148 67
Chris@148 68 void
Chris@175 69 WavFileReader::updateFrameCount()
Chris@175 70 {
Chris@175 71 QMutexLocker locker(&m_mutex);
Chris@175 72
Chris@175 73 size_t prevCount = m_fileInfo.frames;
Chris@175 74
Chris@175 75 if (m_file) {
Chris@175 76 sf_close(m_file);
Chris@175 77 m_file = sf_open(m_path.toLocal8Bit(), SFM_READ, &m_fileInfo);
Chris@175 78 if (!m_file || m_fileInfo.channels <= 0) {
Chris@175 79 std::cerr << "WavFileReader::updateFrameCount: Failed to open file ("
Chris@175 80 << sf_strerror(m_file) << ")" << std::endl;
Chris@175 81 }
Chris@175 82 }
Chris@175 83
Chris@188 84 // std::cerr << "WavFileReader::updateFrameCount: now " << m_fileInfo.frames << std::endl;
Chris@175 85
Chris@176 86 m_frameCount = m_fileInfo.frames;
Chris@176 87
Chris@187 88 if (m_channelCount == 0) {
Chris@187 89 m_channelCount = m_fileInfo.channels;
Chris@187 90 m_sampleRate = m_fileInfo.samplerate;
Chris@187 91 }
Chris@187 92
Chris@258 93 if (m_frameCount != prevCount) {
Chris@258 94 // std::cerr << "frameCountChanged" << std::endl;
Chris@258 95 emit frameCountChanged();
Chris@258 96 }
Chris@176 97 }
Chris@176 98
Chris@176 99 void
Chris@176 100 WavFileReader::updateDone()
Chris@176 101 {
Chris@176 102 updateFrameCount();
Chris@176 103 m_updating = false;
Chris@175 104 }
Chris@175 105
Chris@175 106 void
Chris@148 107 WavFileReader::getInterleavedFrames(size_t start, size_t count,
Chris@148 108 SampleBlock &results) const
Chris@148 109 {
Chris@175 110 if (count == 0) return;
Chris@148 111 results.clear();
Chris@175 112
Chris@175 113 QMutexLocker locker(&m_mutex);
Chris@175 114
Chris@175 115 if (!m_file || !m_channelCount) {
Chris@175 116 return;
Chris@175 117 }
Chris@148 118
Chris@148 119 if ((long)start >= m_fileInfo.frames) {
Chris@175 120 // std::cerr << "WavFileReader::getInterleavedFrames: " << start
Chris@175 121 // << " > " << m_fileInfo.frames << std::endl;
Chris@148 122 return;
Chris@148 123 }
Chris@148 124
Chris@148 125 if (long(start + count) > m_fileInfo.frames) {
Chris@148 126 count = m_fileInfo.frames - start;
Chris@148 127 }
Chris@148 128
Chris@148 129 sf_count_t readCount = 0;
Chris@148 130
Chris@148 131 if (start != m_lastStart || count != m_lastCount) {
Chris@148 132
Chris@148 133 if (sf_seek(m_file, start, SEEK_SET) < 0) {
Chris@175 134 // std::cerr << "sf_seek failed" << std::endl;
Chris@148 135 return;
Chris@148 136 }
Chris@148 137
Chris@148 138 if (count * m_fileInfo.channels > m_bufsiz) {
Chris@148 139 // std::cerr << "WavFileReader: Reallocating buffer for " << count
Chris@148 140 // << " frames, " << m_fileInfo.channels << " channels: "
Chris@148 141 // << m_bufsiz << " floats" << std::endl;
Chris@148 142 m_bufsiz = count * m_fileInfo.channels;
Chris@148 143 delete[] m_buffer;
Chris@148 144 m_buffer = new float[m_bufsiz];
Chris@148 145 }
Chris@148 146
Chris@148 147 if ((readCount = sf_readf_float(m_file, m_buffer, count)) < 0) {
Chris@175 148 // std::cerr << "sf_readf_float failed" << std::endl;
Chris@148 149 return;
Chris@148 150 }
Chris@148 151
Chris@148 152 m_lastStart = start;
Chris@148 153 m_lastCount = readCount;
Chris@148 154 }
Chris@148 155
Chris@148 156 for (size_t i = 0; i < count * m_fileInfo.channels; ++i) {
Chris@232 157 if (i >= m_bufsiz) {
Chris@232 158 std::cerr << "INTERNAL ERROR: WavFileReader::getInterleavedFrames: " << i << " >= " << m_bufsiz << std::endl;
Chris@232 159 }
Chris@148 160 results.push_back(m_buffer[i]);
Chris@148 161 }
Chris@148 162
Chris@148 163 return;
Chris@148 164 }
Chris@148 165
Chris@157 166 void
Chris@157 167 WavFileReader::getSupportedExtensions(std::set<QString> &extensions)
Chris@157 168 {
Chris@157 169 int count;
Chris@157 170
Chris@157 171 if (sf_command(0, SFC_GET_FORMAT_MAJOR_COUNT, &count, sizeof(count))) {
Chris@157 172 extensions.insert("wav");
Chris@157 173 extensions.insert("aiff");
Chris@157 174 extensions.insert("aif");
Chris@157 175 return;
Chris@157 176 }
Chris@157 177
Chris@157 178 SF_FORMAT_INFO info;
Chris@157 179 for (int i = 0; i < count; ++i) {
Chris@157 180 info.format = i;
Chris@157 181 if (!sf_command(0, SFC_GET_FORMAT_MAJOR, &info, sizeof(info))) {
Chris@157 182 extensions.insert(info.extension);
Chris@157 183 }
Chris@157 184 }
Chris@157 185 }