summaryrefslogtreecommitdiffstats
path: root/examples/mobile/guitartuner/src/voiceanalyzer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'examples/mobile/guitartuner/src/voiceanalyzer.cpp')
-rw-r--r--examples/mobile/guitartuner/src/voiceanalyzer.cpp296
1 files changed, 0 insertions, 296 deletions
diff --git a/examples/mobile/guitartuner/src/voiceanalyzer.cpp b/examples/mobile/guitartuner/src/voiceanalyzer.cpp
deleted file mode 100644
index d53b5ebb..00000000
--- a/examples/mobile/guitartuner/src/voiceanalyzer.cpp
+++ /dev/null
@@ -1,296 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the demonstration applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "voiceanalyzer.h"
-
-/**
- * Constant used to scale the cut-off density for the fft helper.
- */
-const static float CutOffScaler = 0.05;
-
-/**
- * Force the precision to be "1/PrecisionPerNote" notes
- * near the target frequency.
- */
-const static int PrecisionPerNote = 4;
-
-/**
- * TargetFrequencyParameter is a constant which implies the index at
- * which corresponds to the target frequency.
- * 0.5 * N * 1/TargetFrequencyParameter is (about) the index which
- * corresponds to the given target frequency.
- * Effectively TargetFrequencyParameter = 2^z, and the z*TargetFrequency
- * is the maximum frequency that can be noticed.
- */
-const static int TargetFrequencyParameter = 4;
-
-
-VoiceAnalyzer::VoiceAnalyzer(const QAudioFormat &format, QObject *parent):
- QIODevice(parent),
- m_format(format),
- m_frequency(0),
- m_position(0),
- m_fftHelper(new FastFourierTransformer(this))
-{
- Q_ASSERT(qFuzzyCompare(M_SAMPLE_COUNT_MULTIPLIER,
- float(2)/(M_TWELTH_ROOT_OF_2 -1.0)));
- m_totalSampleCount = qRound(qreal(PrecisionPerNote)
- *TargetFrequencyParameter
- *M_SAMPLE_COUNT_MULTIPLIER);
- m_samples.reserve(m_totalSampleCount);
- int i = 2;
- int j = 1;
- for (; i < TargetFrequencyParameter; i *= 2) {
- j++;
- }
- m_maximumVoiceDifference = j*12;
-
- setCutOffPercentage(CutOffScaler);
-}
-
-/**
- * Opens the parent QIODevice. Sets up the analysation parameters.
- */
-void VoiceAnalyzer::start(qreal frequency)
-{
- m_stepSize = (qreal) 1.0 * m_format.sampleRate()
- / (TargetFrequencyParameter*2*frequency);
- m_frequency = frequency;
- open(QIODevice::WriteOnly);
-}
-
-/**
- * Closes the parent QIODevice, thus the voice is not analysed anymore.
- * Resets the m_samples QList.
- */
-void VoiceAnalyzer::stop()
-{
- m_samples.clear();
- m_samples.reserve(m_totalSampleCount);
- close();
-}
-
-/**
- * Called when data is obtained. Stores each m_stepSize sample
- * into a QList to be analysed.
- */
-qint64 VoiceAnalyzer::writeData(const char *data, qint64 maxlen)
-{
- const int channelBytes = m_format.sampleSize() / 8;
- int sampleSize = m_format.channels() * channelBytes;
- int m_stepSizeInBytes = m_stepSize*sampleSize;
- // assert that each sample fits fully into the data
- Q_ASSERT((m_position % sampleSize)==0);
- const uchar *ptr = reinterpret_cast<const uchar *>(data);
- while (m_position < maxlen) {
- if (m_samples.size() < m_totalSampleCount) {
- m_samples.append(getValueInt16(ptr+m_position));
- }
- else {
- analyzeVoice();
- m_samples.clear();
- m_samples.reserve(m_totalSampleCount);
- // fast forward position to the first position after maxlen or to the maxlen
- m_position += ((m_stepSizeInBytes - 1 + maxlen - m_position) /
- m_stepSizeInBytes) * m_stepSizeInBytes;
- break;
- }
- m_position += m_stepSizeInBytes;
- }
- m_position -= maxlen;
- return maxlen;
-}
-
-/**
- * Interprets ptr as a pointer to int value and returns it.
- */
-qint16 VoiceAnalyzer::getValueInt16(const uchar *ptr)
-{
- qint16 realValue = 0;
- if (m_format.sampleSize() == 8)
- {
- const qint16 value = *reinterpret_cast<const quint8*>(ptr);
- if (m_format.sampleType() == QAudioFormat::UnSignedInt) {
- realValue = value - M_MAX_AMPLITUDE_8BIT_SIGNED - 1;
- } else if (m_format.sampleType() == QAudioFormat::SignedInt) {
- realValue = value;
- }
- } else if (m_format.sampleSize() == 16) {
- qint16 value = 0;
- if (m_format.byteOrder() == QAudioFormat::LittleEndian)
- value = qFromLittleEndian<quint16>(ptr);
- else
- value = qFromBigEndian<quint16>(ptr);
-
- if (m_format.sampleType() == QAudioFormat::UnSignedInt) {
- realValue = value - M_MAX_AMPLITUDE_16BIT_SIGNED;
- } else if (m_format.sampleType() == QAudioFormat::SignedInt) {
- realValue = value;
- }
- }
- return realValue;
-}
-
-/**
- * Takes a number between 0 and 1, scales it with CutOffScaler,
- * multiplies it with maximum density, and then gives it
- * to the fft helper.
- */
-void VoiceAnalyzer::setCutOffPercentage(qreal cutoff)
-{
- cutoff = CutOffScaler*cutoff;
- if (m_format.sampleSize() == 8) {
- float t = cutoff*m_totalSampleCount*M_MAX_AMPLITUDE_8BIT_SIGNED;
- m_fftHelper->setCutOffForDensity(t);
- }
- else if (m_format.sampleSize() == 16) {
- float t = cutoff*m_totalSampleCount*M_MAX_AMPLITUDE_16BIT_SIGNED;
- m_fftHelper->setCutOffForDensity(t);
- }
-}
-
-/**
- * Returns the current target frequency.
- */
-qreal VoiceAnalyzer::frequency()
-{
- return m_frequency;
-}
-
-/**
- * Returns the maximum absolute value sent by
- * the voiceDifference() signal.
- */
-int VoiceAnalyzer::getMaximumVoiceDifference()
-{
- return m_maximumVoiceDifference;
-}
-
-/**
- * Returns the maximum precision per note
- * near the target frequency.
- */
-int VoiceAnalyzer::getMaximumPrecisionPerNote()
-{
- return PrecisionPerNote;
-}
-
-/**
- * Analyzes the voice frequency and emits appropriate signals.
- */
-void VoiceAnalyzer::analyzeVoice()
-{
- m_fftHelper->calculateFFT(m_samples);
- int index = m_fftHelper->getMaximumDensityIndex();
-
- // If index == -1
- if (index == -1) {
- // The voice is to be filtered away.
- // Emit the lowVoice signal and return.
- emit lowVoice();
- qDebug() << "low voice";
- return;
- }
- // Else, continue
-
- // Let the correctIndex to be
- // the nearest index corresponding to the correct frequency.
- qreal stepSizeInFrequency = (qreal)m_format.sampleRate()
- / (m_totalSampleCount * m_stepSize);
- qreal newFrequency = qreal(index) * stepSizeInFrequency;
- // Calculate the nearest index corresponding to the correct frequency.
- int correctIndex = qRound(m_frequency / stepSizeInFrequency);
- qreal value = 0;
-
- // If the obtained frequency is more than
- // log_2(TargetFrequencyParameter) octaves less than the m_frequency:
-
- // Note:
- // Instead of m_frequency/TargetFrequencyParameter > newFrequency,
- // the comparison is done without a div instructions by
- // m_frequency > newFrequency * TargetFrequencyParameter.
-
- if (m_frequency > newFrequency * TargetFrequencyParameter) {
- // Set the difference value to be -m_maximumVoiceDifference.
- qDebug() << "compare" << "low" << newFrequency << m_frequency - stepSizeInFrequency * correctIndex << (m_frequency - stepSizeInFrequency * correctIndex) / stepSizeInFrequency;
- value = -m_maximumVoiceDifference;
- }
- // Else, if the obtained frequency is more than
- // log_2(TargetFrequencyParameter) octaves more than the m_frequency:
- else if (m_frequency*TargetFrequencyParameter < newFrequency) {
- // Set the difference value to be m_maximumVoiceDifference.
- qDebug() << "compare" << "high" << newFrequency << m_frequency - stepSizeInFrequency * correctIndex << (m_frequency - stepSizeInFrequency * correctIndex) / stepSizeInFrequency;
- value = m_maximumVoiceDifference;
- }
- // Else:
- else {
- // Calculate the difference between the obtained and the correct
- // frequency in tones.
- // Use stepSizeInFrequency * correctIndex instead of
- // m_frequency so that the value is zero when there is correct
- // voice obtained. Set the difference value to be
- // log(frequency / target frequency) * 12 / log(2).
- value = log(newFrequency / (stepSizeInFrequency * correctIndex))
- * 12 / M_LN2;
- qDebug() << "compare" << value << newFrequency << m_frequency - stepSizeInFrequency * correctIndex << (m_frequency - stepSizeInFrequency * correctIndex) / stepSizeInFrequency;
- }
-
- // Emit voiceDifference signal.
- QVariant valueVar(value); //Has to be QVariant for QML
- emit voiceDifference(valueVar);
-
- // If the correctIndex is index, emit the correctFrequency signal.
- if (correctIndex == index) {
- emit(correctFrequency());
- }
-}
-
-/**
- * Empty implementation for readData, since no data is provided
- * by the VoiceAnalyzer class.
- */
-qint64 VoiceAnalyzer::readData(char *data, qint64 maxlen)
-{
- Q_UNUSED(data);
- Q_UNUSED(maxlen);
-
- return 0;
-}