annotate runner/MultiplexedReader.cpp @ 269:39fb206b1153 piper-nopiper

Filter out Xing/LAME info frames, rather than letting them go to the mp3 decoder as if they were audio frames. Fixes the 1152-sample zero pad at start of some decoded mp3 files (distinct from decoder delay). The logic here is based on the madplay code.
author Chris Cannam
date Thu, 24 Nov 2016 13:32:04 +0000
parents 68dc2d99a5b1
children 6122159556bd
rev   line source
Chris@107 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@107 2
Chris@107 3 /*
Chris@107 4 Sonic Annotator
Chris@107 5 A utility for batch feature extraction from audio files.
Chris@107 6 Mark Levy, Chris Sutton and Chris Cannam, Queen Mary, University of London.
Chris@107 7 Copyright 2007-2014 QMUL.
Chris@107 8
Chris@107 9 This program is free software; you can redistribute it and/or
Chris@107 10 modify it under the terms of the GNU General Public License as
Chris@107 11 published by the Free Software Foundation; either version 2 of the
Chris@107 12 License, or (at your option) any later version. See the file
Chris@107 13 COPYING included with this distribution for more information.
Chris@107 14 */
Chris@107 15
Chris@107 16 #include "MultiplexedReader.h"
Chris@107 17
Chris@107 18 MultiplexedReader::MultiplexedReader(QList<AudioFileReader *> readers) :
Chris@107 19 m_readers(readers)
Chris@107 20 {
Chris@107 21 m_channelCount = readers.size();
Chris@107 22 m_sampleRate = readers[0]->getSampleRate();
Chris@107 23
Chris@263 24 SVDEBUG << "MultiplexedReader: channel count: " << m_channelCount
Chris@263 25 << " (i.e. " << m_channelCount << " reader(s) to multiplex)" << endl;
Chris@263 26 SVDEBUG << "MultiplexedReader: sample rate from first reader: "
Chris@263 27 << m_sampleRate << endl;
Chris@263 28
Chris@107 29 m_frameCount = 0;
Chris@107 30 m_quicklySeekable = true;
Chris@107 31
Chris@107 32 foreach (AudioFileReader *r, m_readers) {
Chris@107 33 if (!r->isOK()) {
Chris@107 34 m_channelCount = 0;
Chris@107 35 m_error = r->getError();
Chris@185 36 } else if (r->getSampleRate() != m_sampleRate) {
Chris@185 37 m_channelCount = 0;
Chris@185 38 m_error = "Readers provided to MultiplexedReader must have the same sample rate";
Chris@107 39 } else {
Chris@107 40 if (r->getFrameCount() > m_frameCount) {
Chris@107 41 m_frameCount = r->getFrameCount();
Chris@107 42 }
Chris@107 43 if (!r->isQuicklySeekable()) {
Chris@107 44 m_quicklySeekable = false;
Chris@107 45 }
Chris@107 46 }
Chris@107 47 }
Chris@107 48 }
Chris@107 49
Chris@107 50 MultiplexedReader::~MultiplexedReader()
Chris@107 51 {
Chris@107 52 foreach (AudioFileReader *r, m_readers) {
Chris@107 53 delete r;
Chris@107 54 }
Chris@107 55 }
Chris@107 56
Chris@258 57 std::vector<float>
Chris@195 58 MultiplexedReader::getInterleavedFrames(sv_frame_t start, sv_frame_t frameCount) const
Chris@107 59 {
Chris@114 60 int out_chans = m_readers.size();
Chris@107 61
Chris@114 62 // Allocate and zero
Chris@258 63 std::vector<float> block(frameCount * out_chans, 0.f);
Chris@107 64
Chris@114 65 for (int out_chan = 0; out_chan < out_chans; ++out_chan) {
Chris@107 66
Chris@114 67 AudioFileReader *reader = m_readers[out_chan];
Chris@258 68 auto readerBlock = reader->getInterleavedFrames(start, frameCount);
Chris@107 69
Chris@114 70 int in_chans = reader->getChannelCount();
Chris@107 71
Chris@114 72 for (int frame = 0; frame < frameCount; ++frame) {
Chris@114 73
Chris@114 74 int out_index = frame * out_chans + out_chan;
Chris@114 75
Chris@114 76 for (int in_chan = 0; in_chan < in_chans; ++in_chan) {
Chris@114 77 int in_index = frame * in_chans + in_chan;
Chris@114 78 if (in_index >= (int)readerBlock.size()) break;
Chris@114 79 block[out_index] += readerBlock[in_index];
Chris@107 80 }
Chris@114 81
Chris@114 82 if (in_chans > 1) {
Chris@114 83 block[out_index] /= float(in_chans);
Chris@114 84 }
Chris@107 85 }
Chris@107 86 }
Chris@195 87
Chris@195 88 return block;
Chris@107 89 }
Chris@107 90
Chris@107 91 int
Chris@107 92 MultiplexedReader::getDecodeCompletion() const
Chris@107 93 {
Chris@107 94 int completion = 100;
Chris@107 95 foreach (AudioFileReader *r, m_readers) {
Chris@107 96 int c = r->getDecodeCompletion();
Chris@107 97 if (c < 100) {
Chris@107 98 completion = c;
Chris@107 99 }
Chris@107 100 }
Chris@107 101 return completion;
Chris@107 102 }
Chris@107 103
Chris@107 104 bool
Chris@107 105 MultiplexedReader::isUpdating() const
Chris@107 106 {
Chris@107 107 foreach (AudioFileReader *r, m_readers) {
Chris@107 108 if (r->isUpdating()) return true;
Chris@107 109 }
Chris@107 110 return false;
Chris@107 111 }
Chris@107 112
Chris@107 113
Chris@107 114