Mercurial > hg > svcore
diff data/fileio/WavFileReader.cpp @ 1527:710e6250a401 zoom
Merge from default branch
author | Chris Cannam |
---|---|
date | Mon, 17 Sep 2018 13:51:14 +0100 |
parents | 954d0cf29ca7 |
children | 70e172e6cc59 f8e3dcbafb4d |
line wrap: on
line diff
--- a/data/fileio/WavFileReader.cpp Mon Dec 12 15:18:52 2016 +0000 +++ b/data/fileio/WavFileReader.cpp Mon Sep 17 13:51:14 2018 +0100 @@ -25,13 +25,17 @@ using namespace std; -WavFileReader::WavFileReader(FileSource source, bool fileUpdating) : +WavFileReader::WavFileReader(FileSource source, + bool fileUpdating, + Normalisation normalisation) : m_file(0), m_source(source), m_path(source.getLocalFilename()), m_seekable(false), m_lastStart(0), m_lastCount(0), + m_normalisation(normalisation), + m_max(0.f), m_updating(fileUpdating) { m_frameCount = 0; @@ -40,21 +44,26 @@ m_fileInfo.format = 0; m_fileInfo.frames = 0; + +#ifdef Q_OS_WIN + m_file = sf_wchar_open((LPCWSTR)m_path.utf16(), SFM_READ, &m_fileInfo); +#else m_file = sf_open(m_path.toLocal8Bit(), SFM_READ, &m_fileInfo); +#endif if (!m_file || (!fileUpdating && m_fileInfo.channels <= 0)) { - SVDEBUG << "WavFileReader::initialize: Failed to open file at \"" + SVDEBUG << "WavFileReader::initialize: Failed to open file at \"" << m_path << "\" (" << sf_strerror(m_file) << ")" << endl; - if (m_file) { - m_error = QString("Couldn't load audio file '%1':\n%2") - .arg(m_path).arg(sf_strerror(m_file)); - } else { - m_error = QString("Failed to open audio file '%1'") - .arg(m_path); - } - return; + if (m_file) { + m_error = QString("Couldn't load audio file '%1':\n%2") + .arg(m_path).arg(sf_strerror(m_file)); + } else { + m_error = QString("Failed to open audio file '%1'") + .arg(m_path); + } + return; } if (m_fileInfo.channels > 0) { @@ -82,9 +91,13 @@ // and mark those (basically only non-adaptive WAVs). m_seekable = true; } + + if (m_normalisation != Normalisation::None && !m_updating) { + m_max = getMax(); + } } - SVDEBUG << "WavFileReader: Filename " << m_path << ", frame count " << m_frameCount << ", channel count " << m_channelCount << ", sample rate " << m_sampleRate << ", format " << m_fileInfo.format << ", seekable " << m_fileInfo.seekable << " adjusted to " << m_seekable << endl; + SVDEBUG << "WavFileReader: Filename " << m_path << ", frame count " << m_frameCount << ", channel count " << m_channelCount << ", sample rate " << m_sampleRate << ", format " << m_fileInfo.format << ", seekable " << m_fileInfo.seekable << " adjusted to " << m_seekable << ", normalisation " << int(m_normalisation) << endl; } WavFileReader::~WavFileReader() @@ -101,7 +114,11 @@ if (m_file) { sf_close(m_file); +#ifdef Q_OS_WIN + m_file = sf_wchar_open((LPCWSTR)m_path.utf16(), SFM_READ, &m_fileInfo); +#else m_file = sf_open(m_path.toLocal8Bit(), SFM_READ, &m_fileInfo); +#endif if (!m_file || m_fileInfo.channels <= 0) { SVDEBUG << "WavFileReader::updateFrameCount: Failed to open file at \"" << m_path << "\" (" << sf_strerror(m_file) << ")" << endl; @@ -127,11 +144,31 @@ { updateFrameCount(); m_updating = false; + if (m_normalisation != Normalisation::None) { + m_max = getMax(); + } } -vector<float> +floatvec_t WavFileReader::getInterleavedFrames(sv_frame_t start, sv_frame_t count) const { + floatvec_t frames = getInterleavedFramesUnnormalised(start, count); + + if (m_normalisation == Normalisation::None || m_max == 0.f) { + return frames; + } + + for (int i = 0; in_range_for(frames, i); ++i) { + frames[i] /= m_max; + } + + return frames; +} + +floatvec_t +WavFileReader::getInterleavedFramesUnnormalised(sv_frame_t start, + sv_frame_t count) const +{ static HitCount lastRead("WavFileReader: last read"); if (count == 0) return {}; @@ -147,11 +184,11 @@ if (start >= m_fileInfo.frames) { // SVDEBUG << "WavFileReader::getInterleavedFrames: " << start // << " > " << m_fileInfo.frames << endl; - return {}; + return {}; } if (start + count > m_fileInfo.frames) { - count = m_fileInfo.frames - start; + count = m_fileInfo.frames - start; } // Because WaveFileModel::getSummaries() is called separately for @@ -175,7 +212,7 @@ return {}; } - vector<float> data; + floatvec_t data; sv_frame_t n = count * m_fileInfo.channels; data.resize(n); @@ -191,6 +228,43 @@ return data; } +float +WavFileReader::getMax() const +{ + if (!m_file || !m_channelCount) { + return 0.f; + } + + // First try for a PEAK chunk + + double sfpeak = 0.0; + if (sf_command(m_file, SFC_GET_SIGNAL_MAX, &sfpeak, sizeof(sfpeak)) + == SF_TRUE) { + SVDEBUG << "File has a PEAK chunk reporting max level " << sfpeak + << endl; + return float(fabs(sfpeak)); + } + + // Failing that, read all the samples + + float peak = 0.f; + sv_frame_t ix = 0, chunk = 65536; + + while (ix < m_frameCount) { + auto frames = getInterleavedFrames(ix, chunk); + for (float x: frames) { + float level = fabsf(x); + if (level > peak) { + peak = level; + } + } + ix += chunk; + } + + SVDEBUG << "Measured file peak max level as " << peak << endl; + return peak; +} + void WavFileReader::getSupportedExtensions(set<QString> &extensions) {