annotate data/fileio/OggVorbisFileReader.cpp @ 167:665342c6ec57

* Add a bit of resistance to pane dragging so as to make it harder to inadvertently drag in the other axis from the one you intended
author Chris Cannam
date Fri, 22 Sep 2006 16:46:10 +0000
parents c03ec31005e1
children 06ad01f3e553
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@148 7 This file copyright 2006 Chris Cannam.
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 #ifdef HAVE_OGGZ
Chris@148 17 #ifdef HAVE_FISHSOUND
Chris@148 18
Chris@148 19 #include "OggVorbisFileReader.h"
Chris@148 20 #include "base/Profiler.h"
Chris@150 21 #include "system/System.h"
Chris@148 22
Chris@148 23 #include <sys/types.h>
Chris@148 24 #include <sys/stat.h>
Chris@148 25 #include <sys/mman.h>
Chris@148 26 #include <fcntl.h>
Chris@148 27 #include <cmath>
Chris@148 28
Chris@148 29 #include <QApplication>
Chris@148 30 #include <QFileInfo>
Chris@148 31 #include <QProgressDialog>
Chris@148 32
Chris@148 33 static int instances = 0;
Chris@148 34
Chris@148 35 OggVorbisFileReader::OggVorbisFileReader(QString path, bool showProgress,
Chris@148 36 CacheMode mode) :
Chris@148 37 CodedAudioFileReader(mode),
Chris@148 38 m_path(path),
Chris@148 39 m_progress(0),
Chris@148 40 m_fileSize(0),
Chris@148 41 m_bytesRead(0),
Chris@148 42 m_cancelled(false)
Chris@148 43 {
Chris@148 44 m_frameCount = 0;
Chris@148 45 m_channelCount = 0;
Chris@148 46 m_sampleRate = 0;
Chris@148 47
Chris@148 48 std::cerr << "OggVorbisFileReader::OggVorbisFileReader(" << path.toLocal8Bit().data() << "): now have " << (++instances) << " instances" << std::endl;
Chris@148 49
Chris@148 50 Profiler profiler("OggVorbisFileReader::OggVorbisFileReader", true);
Chris@148 51
Chris@148 52 QFileInfo info(path);
Chris@148 53 m_fileSize = info.size();
Chris@148 54
Chris@148 55 OGGZ *oggz;
Chris@148 56 if (!(oggz = oggz_open(path.toLocal8Bit().data(), OGGZ_READ))) {
Chris@148 57 m_error = QString("File %1 is not an OGG file.").arg(path);
Chris@148 58 return;
Chris@148 59 }
Chris@148 60
Chris@148 61 FishSoundInfo fsinfo;
Chris@148 62 m_fishSound = fish_sound_new(FISH_SOUND_DECODE, &fsinfo);
Chris@148 63
Chris@148 64 fish_sound_set_decoded_callback(m_fishSound, acceptFrames, this);
Chris@148 65 oggz_set_read_callback(oggz, -1, readPacket, this);
Chris@148 66
Chris@148 67 if (showProgress) {
Chris@148 68 m_progress = new QProgressDialog
Chris@148 69 (QObject::tr("Decoding Ogg file..."),
Chris@148 70 QObject::tr("Stop"), 0, 100);
Chris@148 71 m_progress->hide();
Chris@148 72 }
Chris@148 73
Chris@148 74 while (oggz_read(oggz, 1024) > 0);
Chris@148 75
Chris@148 76 fish_sound_delete(m_fishSound);
Chris@148 77 m_fishSound = 0;
Chris@148 78 oggz_close(oggz);
Chris@148 79
Chris@148 80 if (isDecodeCacheInitialised()) finishDecodeCache();
Chris@148 81
Chris@148 82 if (showProgress) {
Chris@148 83 delete m_progress;
Chris@148 84 m_progress = 0;
Chris@148 85 }
Chris@148 86 }
Chris@148 87
Chris@148 88 OggVorbisFileReader::~OggVorbisFileReader()
Chris@148 89 {
Chris@148 90 std::cerr << "OggVorbisFileReader::~OggVorbisFileReader(" << m_path.toLocal8Bit().data() << "): now have " << (--instances) << " instances" << std::endl;
Chris@148 91 }
Chris@148 92
Chris@148 93 int
Chris@148 94 OggVorbisFileReader::readPacket(OGGZ *, ogg_packet *packet, long, void *data)
Chris@148 95 {
Chris@148 96 OggVorbisFileReader *reader = (OggVorbisFileReader *)data;
Chris@148 97 FishSound *fs = reader->m_fishSound;
Chris@148 98
Chris@148 99 fish_sound_prepare_truncation(fs, packet->granulepos, packet->e_o_s);
Chris@148 100 fish_sound_decode(fs, packet->packet, packet->bytes);
Chris@148 101
Chris@148 102 reader->m_bytesRead += packet->bytes;
Chris@148 103
Chris@148 104 if (reader->m_fileSize > 0 && reader->m_progress) {
Chris@148 105 // The number of bytes read by this function is smaller than
Chris@148 106 // the file size because of the packet headers
Chris@148 107 int progress = lrint(double(reader->m_bytesRead) * 114 /
Chris@148 108 double(reader->m_fileSize));
Chris@148 109 if (progress > 99) progress = 99;
Chris@148 110 if (progress > reader->m_progress->value()) {
Chris@148 111 reader->m_progress->setValue(progress);
Chris@148 112 reader->m_progress->show();
Chris@148 113 reader->m_progress->raise();
Chris@148 114 qApp->processEvents();
Chris@148 115 if (reader->m_progress->wasCanceled()) {
Chris@148 116 reader->m_cancelled = true;
Chris@148 117 }
Chris@148 118 }
Chris@148 119 }
Chris@148 120
Chris@148 121 if (reader->m_cancelled) return 1;
Chris@148 122 return 0;
Chris@148 123 }
Chris@148 124
Chris@148 125 int
Chris@148 126 OggVorbisFileReader::acceptFrames(FishSound *fs, float **frames, long nframes,
Chris@148 127 void *data)
Chris@148 128 {
Chris@148 129 OggVorbisFileReader *reader = (OggVorbisFileReader *)data;
Chris@148 130
Chris@148 131 if (reader->m_channelCount == 0) {
Chris@148 132 FishSoundInfo fsinfo;
Chris@148 133 fish_sound_command(fs, FISH_SOUND_GET_INFO,
Chris@148 134 &fsinfo, sizeof(FishSoundInfo));
Chris@148 135 reader->m_channelCount = fsinfo.channels;
Chris@148 136 reader->m_sampleRate = fsinfo.samplerate;
Chris@148 137 reader->initialiseDecodeCache();
Chris@148 138 }
Chris@148 139
Chris@148 140 if (nframes > 0) {
Chris@148 141
Chris@148 142 reader->m_frameCount += nframes;
Chris@148 143
Chris@148 144 for (long i = 0; i < nframes; ++i) {
Chris@148 145 for (size_t c = 0; c < reader->m_channelCount; ++c) {
Chris@148 146 reader->addSampleToDecodeCache(frames[c][i]);
Chris@148 147 // reader->m_data.push_back(frames[c][i]);
Chris@148 148 }
Chris@148 149 }
Chris@148 150
Chris@148 151 MUNLOCK_SAMPLEBLOCK(reader->m_data);
Chris@148 152 }
Chris@148 153
Chris@148 154 if (reader->m_cancelled) return 1;
Chris@148 155 return 0;
Chris@148 156 }
Chris@148 157
Chris@157 158 void
Chris@157 159 OggVorbisFileReader::getSupportedExtensions(std::set<QString> &extensions)
Chris@157 160 {
Chris@157 161 extensions.insert("ogg");
Chris@157 162 }
Chris@157 163
Chris@148 164 #endif
Chris@148 165 #endif