Mercurial > hg > svcore
comparison data/fileio/CodedAudioFileReader.cpp @ 148:1a42221a1522
* Reorganising code base. This revision will not compile.
author | Chris Cannam |
---|---|
date | Mon, 31 Jul 2006 11:49:58 +0000 |
parents | |
children | 900ac6667eab |
comparison
equal
deleted
inserted
replaced
147:3a13b0d4934e | 148:1a42221a1522 |
---|---|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ | |
2 | |
3 /* | |
4 Sonic Visualiser | |
5 An audio file viewer and annotation editor. | |
6 Centre for Digital Music, Queen Mary, University of London. | |
7 This file copyright 2006 Chris Cannam. | |
8 | |
9 This program is free software; you can redistribute it and/or | |
10 modify it under the terms of the GNU General Public License as | |
11 published by the Free Software Foundation; either version 2 of the | |
12 License, or (at your option) any later version. See the file | |
13 COPYING included with this distribution for more information. | |
14 */ | |
15 | |
16 #include "CodedAudioFileReader.h" | |
17 | |
18 #include "WavFileReader.h" | |
19 #include "base/TempDirectory.h" | |
20 #include "base/Exceptions.h" | |
21 | |
22 #include <iostream> | |
23 #include <QDir> | |
24 | |
25 CodedAudioFileReader::CodedAudioFileReader(CacheMode cacheMode) : | |
26 m_cacheMode(cacheMode), | |
27 m_initialised(false), | |
28 m_cacheFileWritePtr(0), | |
29 m_cacheFileReader(0), | |
30 m_cacheWriteBuffer(0), | |
31 m_cacheWriteBufferIndex(0), | |
32 m_cacheWriteBufferSize(16384) | |
33 { | |
34 } | |
35 | |
36 CodedAudioFileReader::~CodedAudioFileReader() | |
37 { | |
38 if (m_cacheFileWritePtr) sf_close(m_cacheFileWritePtr); | |
39 if (m_cacheFileReader) delete m_cacheFileReader; | |
40 if (m_cacheWriteBuffer) delete[] m_cacheWriteBuffer; | |
41 | |
42 if (m_cacheFileName != "") { | |
43 if (!QFile(m_cacheFileName).remove()) { | |
44 std::cerr << "WARNING: CodedAudioFileReader::~CodedAudioFileReader: Failed to delete cache file \"" << m_cacheFileName.toStdString() << "\"" << std::endl; | |
45 } | |
46 } | |
47 } | |
48 | |
49 void | |
50 CodedAudioFileReader::initialiseDecodeCache() | |
51 { | |
52 if (m_cacheMode == CacheInTemporaryFile) { | |
53 | |
54 m_cacheWriteBuffer = new float[m_cacheWriteBufferSize * m_channelCount]; | |
55 m_cacheWriteBufferIndex = 0; | |
56 | |
57 try { | |
58 QDir dir(TempDirectory::getInstance()->getPath()); | |
59 m_cacheFileName = dir.filePath(QString("decoded_%1.wav") | |
60 .arg((intptr_t)this)); | |
61 | |
62 SF_INFO fileInfo; | |
63 fileInfo.samplerate = m_sampleRate; | |
64 fileInfo.channels = m_channelCount; | |
65 fileInfo.format = SF_FORMAT_WAV | SF_FORMAT_FLOAT; | |
66 | |
67 m_cacheFileWritePtr = sf_open(m_cacheFileName.toLocal8Bit(), | |
68 SFM_WRITE, &fileInfo); | |
69 | |
70 if (!m_cacheFileWritePtr) { | |
71 std::cerr << "CodedAudioFileReader::initialiseDecodeCache: failed to open cache file \"" << m_cacheFileName.toStdString() << "\" (" << m_channelCount << " channels, sample rate " << m_sampleRate << " for writing, falling back to in-memory cache" << std::endl; | |
72 m_cacheMode = CacheInMemory; | |
73 } | |
74 } catch (DirectoryCreationFailed f) { | |
75 std::cerr << "CodedAudioFileReader::initialiseDecodeCache: failed to create temporary directory! Falling back to in-memory cache" << std::endl; | |
76 m_cacheMode = CacheInMemory; | |
77 } | |
78 } | |
79 | |
80 if (m_cacheMode == CacheInMemory) { | |
81 m_data.clear(); | |
82 } | |
83 | |
84 m_initialised = true; | |
85 } | |
86 | |
87 void | |
88 CodedAudioFileReader::addSampleToDecodeCache(float sample) | |
89 { | |
90 if (!m_initialised) return; | |
91 | |
92 switch (m_cacheMode) { | |
93 | |
94 case CacheInTemporaryFile: | |
95 | |
96 m_cacheWriteBuffer[m_cacheWriteBufferIndex++] = sample; | |
97 | |
98 if (m_cacheWriteBufferIndex == | |
99 m_cacheWriteBufferSize * m_channelCount) { | |
100 | |
101 //!!! check for return value! out of disk space, etc! | |
102 sf_writef_float(m_cacheFileWritePtr, | |
103 m_cacheWriteBuffer, | |
104 m_cacheWriteBufferSize); | |
105 | |
106 m_cacheWriteBufferIndex = 0; | |
107 } | |
108 break; | |
109 | |
110 case CacheInMemory: | |
111 m_data.push_back(sample); | |
112 break; | |
113 } | |
114 } | |
115 | |
116 void | |
117 CodedAudioFileReader::finishDecodeCache() | |
118 { | |
119 if (!m_initialised) { | |
120 std::cerr << "WARNING: CodedAudioFileReader::finishDecodeCache: Cache was never initialised!" << std::endl; | |
121 return; | |
122 } | |
123 | |
124 switch (m_cacheMode) { | |
125 | |
126 case CacheInTemporaryFile: | |
127 | |
128 if (m_cacheWriteBufferIndex > 0) { | |
129 //!!! check for return value! out of disk space, etc! | |
130 sf_writef_float(m_cacheFileWritePtr, | |
131 m_cacheWriteBuffer, | |
132 m_cacheWriteBufferIndex / m_channelCount); | |
133 } | |
134 | |
135 if (m_cacheWriteBuffer) { | |
136 delete[] m_cacheWriteBuffer; | |
137 m_cacheWriteBuffer = 0; | |
138 } | |
139 | |
140 m_cacheWriteBufferIndex = 0; | |
141 | |
142 sf_close(m_cacheFileWritePtr); | |
143 m_cacheFileWritePtr = 0; | |
144 | |
145 m_cacheFileReader = new WavFileReader(m_cacheFileName); | |
146 | |
147 if (!m_cacheFileReader->isOK()) { | |
148 std::cerr << "ERROR: CodedAudioFileReader::finishDecodeCache: Failed to construct WAV file reader for temporary file: " << m_cacheFileReader->getError().toStdString() << std::endl; | |
149 delete m_cacheFileReader; | |
150 m_cacheFileReader = 0; | |
151 } | |
152 break; | |
153 | |
154 case CacheInMemory: | |
155 // nothing to do | |
156 break; | |
157 } | |
158 } | |
159 | |
160 void | |
161 CodedAudioFileReader::getInterleavedFrames(size_t start, size_t count, | |
162 SampleBlock &frames) const | |
163 { | |
164 if (!m_initialised) return; | |
165 | |
166 switch (m_cacheMode) { | |
167 | |
168 case CacheInTemporaryFile: | |
169 if (m_cacheFileReader) { | |
170 m_cacheFileReader->getInterleavedFrames(start, count, frames); | |
171 } | |
172 break; | |
173 | |
174 case CacheInMemory: | |
175 { | |
176 frames.clear(); | |
177 if (!isOK()) return; | |
178 if (count == 0) return; | |
179 | |
180 // slownessabounds | |
181 | |
182 for (size_t i = start; i < start + count; ++i) { | |
183 for (size_t ch = 0; ch < m_channelCount; ++ch) { | |
184 size_t index = i * m_channelCount + ch; | |
185 if (index >= m_data.size()) return; | |
186 frames.push_back(m_data[index]); | |
187 } | |
188 } | |
189 } | |
190 } | |
191 } | |
192 |