Mercurial > hg > svcore
comparison data/fileio/MP3FileReader.cpp @ 297:c022976d18e8
* Merge from sv-match-alignment branch (excluding alignment-specific document).
- add aggregate wave model (not yet complete enough to be added as a true
model in a layer, but there's potential)
- add play solo mode
- add alignment model -- unused in plain SV
- fix two plugin leaks
- add m3u playlist support (opens all files at once, potentially hazardous)
- fix retrieval of pre-encoded URLs
- add ability to resample audio files on import, so as to match rates with
other files previously loaded; add preference for same
- add preliminary support in transform code for range and rate of transform
input
- reorganise preferences dialog, move dark-background option to preferences,
add option for temporary directory location
author | Chris Cannam |
---|---|
date | Fri, 28 Sep 2007 13:56:38 +0000 |
parents | 92e8dbde73cd |
children | 3a6725f285d6 |
comparison
equal
deleted
inserted
replaced
296:2b6c99b607f1 | 297:c022976d18e8 |
---|---|
32 | 32 |
33 #include <QApplication> | 33 #include <QApplication> |
34 #include <QFileInfo> | 34 #include <QFileInfo> |
35 #include <QProgressDialog> | 35 #include <QProgressDialog> |
36 | 36 |
37 MP3FileReader::MP3FileReader(QString path, DecodeMode decodeMode, CacheMode mode) : | 37 MP3FileReader::MP3FileReader(QString path, DecodeMode decodeMode, |
38 CodedAudioFileReader(mode), | 38 CacheMode mode, size_t targetRate) : |
39 CodedAudioFileReader(mode, targetRate), | |
39 m_path(path), | 40 m_path(path), |
40 m_decodeThread(0) | 41 m_decodeThread(0) |
41 { | 42 { |
42 m_frameCount = 0; | |
43 m_channelCount = 0; | 43 m_channelCount = 0; |
44 m_sampleRate = 0; | 44 m_fileRate = 0; |
45 m_fileSize = 0; | 45 m_fileSize = 0; |
46 m_bitrateNum = 0; | 46 m_bitrateNum = 0; |
47 m_bitrateDenom = 0; | 47 m_bitrateDenom = 0; |
48 m_frameCount = 0; | |
49 m_cancelled = false; | 48 m_cancelled = false; |
50 m_completion = 0; | 49 m_completion = 0; |
51 m_done = false; | 50 m_done = false; |
52 m_progress = 0; | 51 m_progress = 0; |
53 | 52 |
68 m_error = QString("Failed to open file %1 for reading.").arg(path); | 67 m_error = QString("Failed to open file %1 for reading.").arg(path); |
69 return; | 68 return; |
70 } | 69 } |
71 | 70 |
72 m_filebuffer = 0; | 71 m_filebuffer = 0; |
72 m_samplebuffer = 0; | |
73 m_samplebuffersize = 0; | |
73 | 74 |
74 try { | 75 try { |
75 m_filebuffer = new unsigned char[m_fileSize]; | 76 m_filebuffer = new unsigned char[m_fileSize]; |
76 } catch (...) { | 77 } catch (...) { |
77 m_error = QString("Out of memory"); | 78 m_error = QString("Out of memory"); |
224 m_reader->m_error = QString("Failed to decode file %1.").arg(m_reader->m_path); | 225 m_reader->m_error = QString("Failed to decode file %1.").arg(m_reader->m_path); |
225 } | 226 } |
226 | 227 |
227 delete[] m_reader->m_filebuffer; | 228 delete[] m_reader->m_filebuffer; |
228 m_reader->m_filebuffer = 0; | 229 m_reader->m_filebuffer = 0; |
229 | 230 |
231 if (m_reader->m_samplebuffer) { | |
232 for (size_t c = 0; c < m_reader->m_channelCount; ++c) { | |
233 delete[] m_reader->m_samplebuffer[c]; | |
234 } | |
235 delete[] m_reader->m_samplebuffer; | |
236 m_reader->m_samplebuffer = 0; | |
237 } | |
238 | |
230 if (m_reader->isDecodeCacheInitialised()) m_reader->finishDecodeCache(); | 239 if (m_reader->isDecodeCacheInitialised()) m_reader->finishDecodeCache(); |
231 | 240 |
232 m_reader->m_done = true; | 241 m_reader->m_done = true; |
233 m_reader->m_completion = 100; | 242 m_reader->m_completion = 100; |
243 | |
244 m_reader->endSerialised(); | |
234 } | 245 } |
235 | 246 |
236 bool | 247 bool |
237 MP3FileReader::decode(void *mm, size_t sz) | 248 MP3FileReader::decode(void *mm, size_t sz) |
238 { | 249 { |
285 } | 296 } |
286 | 297 |
287 if (frames < 1) return MAD_FLOW_CONTINUE; | 298 if (frames < 1) return MAD_FLOW_CONTINUE; |
288 | 299 |
289 if (m_channelCount == 0) { | 300 if (m_channelCount == 0) { |
301 | |
302 m_fileRate = pcm->samplerate; | |
290 m_channelCount = channels; | 303 m_channelCount = channels; |
291 m_sampleRate = pcm->samplerate; | 304 |
305 initialiseDecodeCache(); | |
306 | |
307 if (m_cacheMode == CacheInTemporaryFile) { | |
308 m_completion = 1; | |
309 std::cerr << "MP3FileReader::accept: channel count " << m_channelCount << ", file rate " << m_fileRate << ", about to start serialised section" << std::endl; | |
310 startSerialised("MP3FileReader::Decode"); | |
311 } | |
292 } | 312 } |
293 | 313 |
294 if (m_bitrateDenom > 0) { | 314 if (m_bitrateDenom > 0) { |
295 double bitrate = m_bitrateNum / m_bitrateDenom; | 315 double bitrate = m_bitrateNum / m_bitrateDenom; |
296 double duration = double(m_fileSize * 8) / bitrate; | 316 double duration = double(m_fileSize * 8) / bitrate; |
313 } | 333 } |
314 } | 334 } |
315 | 335 |
316 if (m_cancelled) return MAD_FLOW_STOP; | 336 if (m_cancelled) return MAD_FLOW_STOP; |
317 | 337 |
318 m_frameCount += frames; | |
319 | |
320 if (!isDecodeCacheInitialised()) { | 338 if (!isDecodeCacheInitialised()) { |
321 initialiseDecodeCache(); | 339 initialiseDecodeCache(); |
322 } | 340 } |
323 | 341 |
324 for (int i = 0; i < frames; ++i) { | 342 if (m_samplebuffersize < frames) { |
325 | 343 if (!m_samplebuffer) { |
326 for (int ch = 0; ch < channels; ++ch) { | 344 m_samplebuffer = new float *[channels]; |
345 for (int c = 0; c < channels; ++c) { | |
346 m_samplebuffer[c] = 0; | |
347 } | |
348 } | |
349 for (int c = 0; c < channels; ++c) { | |
350 delete[] m_samplebuffer[c]; | |
351 m_samplebuffer[c] = new float[frames]; | |
352 } | |
353 m_samplebuffersize = frames; | |
354 } | |
355 | |
356 int activeChannels = int(sizeof(pcm->samples) / sizeof(pcm->samples[0])); | |
357 | |
358 for (int ch = 0; ch < channels; ++ch) { | |
359 | |
360 for (int i = 0; i < frames; ++i) { | |
361 | |
327 mad_fixed_t sample = 0; | 362 mad_fixed_t sample = 0; |
328 if (ch < int(sizeof(pcm->samples) / sizeof(pcm->samples[0]))) { | 363 if (ch < activeChannels) { |
329 sample = pcm->samples[ch][i]; | 364 sample = pcm->samples[ch][i]; |
330 } | 365 } |
331 float fsample = float(sample) / float(MAD_F_ONE); | 366 float fsample = float(sample) / float(MAD_F_ONE); |
332 addSampleToDecodeCache(fsample); | 367 |
368 m_samplebuffer[ch][i] = fsample; | |
333 } | 369 } |
334 | 370 } |
335 if (! (i & 0xffff)) { | 371 |
336 // periodically munlock to ensure we don't exhaust real memory | 372 addSamplesToDecodeCache(m_samplebuffer, frames); |
337 // if running with memory locked down | |
338 MUNLOCK_SAMPLEBLOCK(m_data); | |
339 } | |
340 } | |
341 | |
342 if (frames > 0) { | |
343 MUNLOCK_SAMPLEBLOCK(m_data); | |
344 } | |
345 | 373 |
346 return MAD_FLOW_CONTINUE; | 374 return MAD_FLOW_CONTINUE; |
347 } | 375 } |
348 | 376 |
349 enum mad_flow | 377 enum mad_flow |