summaryrefslogtreecommitdiffstats
path: root/demos/mobile/guitartuner/src/voiceanalyzer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'demos/mobile/guitartuner/src/voiceanalyzer.cpp')
-rw-r--r--demos/mobile/guitartuner/src/voiceanalyzer.cpp295
1 files changed, 0 insertions, 295 deletions
diff --git a/demos/mobile/guitartuner/src/voiceanalyzer.cpp b/demos/mobile/guitartuner/src/voiceanalyzer.cpp
deleted file mode 100644
index 9990e6d..0000000
--- a/demos/mobile/guitartuner/src/voiceanalyzer.cpp
+++ /dev/null
@@ -1,295 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtDeclarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
-** the names of its contributors may be used to endorse or promote
-** products derived from this software without specific prior written
-** permission.
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-** $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;
-}