diff options
Diffstat (limited to 'demos/mobile/guitartuner/src/guitartuner.cpp')
-rw-r--r-- | demos/mobile/guitartuner/src/guitartuner.cpp | 359 |
1 files changed, 359 insertions, 0 deletions
diff --git a/demos/mobile/guitartuner/src/guitartuner.cpp b/demos/mobile/guitartuner/src/guitartuner.cpp new file mode 100644 index 0000000..1750e6a --- /dev/null +++ b/demos/mobile/guitartuner/src/guitartuner.cpp @@ -0,0 +1,359 @@ +/**************************************************************************** +** +** 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 "guitartuner.h" + +#ifdef Q_OS_SYMBIAN +#include <SoundDevice.h> +#endif // Q_OS_SYMBIAN + +#if defined(Q_OS_SYMBIAN) && defined(ORIENTATIONLOCK) +#include <eikenv.h> +#include <eikappui.h> +#include <aknenv.h> +#include <aknappui.h> +#endif // Q_OS_SYMBIAN && ORIENTATIONLOCK + +GuitarTuner::GuitarTuner(QWidget *parent) : + QMainWindow(parent) +{ + + // Set up the QML. + m_guitarTunerUI = new QDeclarativeView(QUrl("qrc:/src/application.qml"), this); + setCentralWidget(m_guitarTunerUI); + m_guitarTunerUI->setResizeMode(QDeclarativeView::SizeRootObjectToView); + qmlObject = m_guitarTunerUI->rootObject(); + + // Init audio output and input. + initAudioOutput(); + initAudioInput(); + + // Connect the quit signal of m_guitarTunerUI + // into the close slot of this. + connect(m_guitarTunerUI->engine(), SIGNAL(quit()), SLOT(close())); + + // Connect the signals from qmlObject into proper slots + // of this and m_voicegenerator. + connect(qmlObject, SIGNAL(muteStateChanged(bool)), + SLOT(muteStateChanged(bool))); + connect(qmlObject, SIGNAL(volumeChanged(qreal)), + m_voicegenerator, SLOT(setAmplitude(qreal))); + connect(qmlObject, SIGNAL(volumeChanged(qreal)), + SLOT(setMaxVolumeLevel(qreal))); + + // Connect the modeChanged signal from qmlObject + // into modeChanged slot of this class. + connect(qmlObject, SIGNAL(modeChanged(bool)), + SLOT(modeChanged(bool))); + + // Connect the microphoneSensitivityChanged signal from + // m_guitarTunerUI into setCutOffPercentage slot of m_analyzer class. + connect(qmlObject, SIGNAL(microphoneSensitivityChanged(qreal)), + m_analyzer, SLOT(setCutOffPercentage(qreal))); + + // Connect the signals from m_analyzer into slots of qmlObject. + connect(m_analyzer, SIGNAL(lowVoice()), + qmlObject, SLOT(lowVoice())); + connect(m_analyzer, SIGNAL(correctFrequency()), + qmlObject, SLOT(correctFrequencyObtained())); + connect(m_analyzer, SIGNAL(voiceDifference(QVariant)), + qmlObject, SLOT(voiceDifferenceChanged(QVariant))); + + // Initialise the MaximumVoiceDifference + // value of qmlObject with the value obtained from m_analyzer. + qmlObject->setProperty("maxVoiceDifference", + m_analyzer->getMaximumVoiceDifference()); + + // Connect the targetFrequencyChanged signal of qmlObject + // into targetFrequencyChanged slot of this class. + connect(qmlObject, SIGNAL(targetFrequencyChanged(qreal)), + SLOT(targetFrequencyChanged(qreal))); + + // Start voice output or input by using the modeChanged function, + // depending of the current mode. + modeChanged(qmlObject->property("isInput").toBool()); + +} + +/** + * Inits audio output. + */ +void GuitarTuner::initAudioOutput() +{ + // Set up the output format. + m_format_output.setFrequency(DataFrequencyHzOutput); + m_format_output.setCodec("audio/pcm"); + m_format_output.setSampleSize(16); + m_format_output.setChannels(1); + m_format_output.setByteOrder(QAudioFormat::LittleEndian); + m_format_output.setSampleType(QAudioFormat::SignedInt); + + // Obtain a default output device, and if the format is not + // supported, find the nearest format available. + QAudioDeviceInfo outputDeviceInfo( + QAudioDeviceInfo::defaultOutputDevice()); + if (!outputDeviceInfo.isFormatSupported(m_format_output)) { + m_format_output = outputDeviceInfo.nearestFormat(m_format_output); + } + + // Create new QAudioOutput and VoiceGenerator instances, and store + // them in m_audioOutput and m_voicegenerator, respectively. + m_audioOutput = new QAudioOutput(outputDeviceInfo, + m_format_output, this); + m_voicegenerator = new VoiceGenerator(m_format_output, + qmlObject->property("frequency").toReal(), + qmlObject->property("volume").toReal(), + this); + + // Connect m_audioOutput stateChanged signal to outputStateChanged. + connect(m_audioOutput, SIGNAL(stateChanged(QAudio::State)), + SLOT(outputStateChanged(QAudio::State))); +} + +/** + * Inits audio input. + */ +void GuitarTuner::initAudioInput() +{ + // Set up the input format. + m_format_input.setFrequency(DataFrequencyHzInput); + m_format_input.setCodec("audio/pcm"); + m_format_input.setSampleSize(16); + m_format_input.setChannels(1); + m_format_input.setByteOrder(QAudioFormat::LittleEndian); + m_format_input.setSampleType(QAudioFormat::SignedInt); + + // Obtain a default input device, and if the format is not + // supported, find the nearest format available. + QAudioDeviceInfo inputDeviceInfo( + QAudioDeviceInfo::defaultInputDevice()); + if (!inputDeviceInfo.isFormatSupported(m_format_input)) { + m_format_input = inputDeviceInfo.nearestFormat(m_format_input); + } + + // Create new QAudioInput and VoiceAnalyzer instances, and store + // them in m_audioInput and m_analyzer, respectively. + // Remember to set the cut-off percentage for voice analyzer. + m_audioInput = new QAudioInput(inputDeviceInfo, m_format_input, this); + m_analyzer = new VoiceAnalyzer(m_format_input, this); + m_analyzer->setCutOffPercentage(qmlObject->property("sensitivity").toReal()); + +} + +/** + * Receives a mode changed signal. + */ +void GuitarTuner::modeChanged(bool isInput) +{ + + + + // If the mode must be changed to input mode: + if (isInput) { + + // Stop audio output and audio generator. + m_audioOutput->stop(); + m_voicegenerator->stop(); + // Start the audio analyzer and then the audio input. + m_analyzer->start(qmlObject->property("frequency").toReal()); + m_audioInput->start(m_analyzer); + + } + // Else: + else { + + // Stop audio input and audio analyzer. + m_audioInput->stop(); + m_analyzer->stop(); + + // Set up the audio output. + + // If the current frequency of voice generator + // is not the same as the target frequency selected in the UI, + // update voice generator's frequency. + if (m_voicegenerator->frequency() != qmlObject->property("frequency").toReal()) { + m_voicegenerator->setFrequency(qmlObject->property("frequency").toReal()); + } + + // Start the voice generator and then the audio output. + m_voicegenerator->start(); + m_audioOutput->start(m_voicegenerator); + // Call setMaxVolumeLevel(1) to set the maximum volume louder. + setMaxVolumeLevel(qmlObject->property("volume").toReal()); + + // If the voice is muted, the voice is suspended + // in the outputStateChanged slot. + + } +} + +/** + * Receives a output state changed signal. + * Suspends the audio output, if the state is ActiveState + * and the voice is muted. + */ +void GuitarTuner::outputStateChanged(QAudio::State state) +{ + if (QAudio::ActiveState == state && qmlObject->property("isMuted").toBool()) { + // If the voice is muted, suspend the voice. + m_audioOutput->suspend(); + } +} + +/** + * Receives a mute state changed signal. + * Suspends the audio output or resumes it, depending of the + * isMuted parameter. + */ +void GuitarTuner::muteStateChanged(bool isMuted) +{ + if (isMuted) { + m_audioOutput->suspend(); + } + else { + m_audioOutput->resume(); + } +} + +/** + * Receives a target frequency signal. + */ +void GuitarTuner::targetFrequencyChanged(qreal targetFrequency) +{ + // If the output mode is active: + if (!qmlObject->property("isInput").toBool()) { + // Stop the audio output and voice generator. + m_audioOutput->stop(); + m_voicegenerator->stop(); + // Set the voice generator's frequency to the target frequency. + m_voicegenerator->setFrequency(targetFrequency); + // Start the voice generator and audio output. + m_voicegenerator->start(); + m_audioOutput->start(m_voicegenerator); + // Call setMaxVolumeLevel(1) to set the maximum volume louder. + setMaxVolumeLevel(qmlObject->property("volume").toReal()); + + // If the voice is muted, the voice is suspended + // in the outputStateChanged slot. + + } + // Else: + else { + + // Stop the audio input and voice analyzer. + m_audioInput->stop(); + m_analyzer->stop(); + // Start the voice analyzer with new frequency and audio input. + m_analyzer->start(targetFrequency); + m_audioInput->start(m_analyzer); + + } +} + +/** + * This method provides a hack to set the maximum volume level in + * Symbian. + */ +void GuitarTuner::setMaxVolumeLevel(qreal percent) +{ + if (percent >= 1.0) { + percent = 1.0; + } + else if (percent <= 0.0) { + percent = 0.0; + } + percent = percent*0.5 + 0.5; + // Warning! This is a hack, which can break when the QtMobility + // changes. Use at your own risk. +#ifdef Q_OS_SYMBIAN + unsigned int *pointer_to_abstract_audio + = (unsigned int*)( (unsigned char*)m_audioOutput + 8 ); + unsigned int *dev_sound_wrapper + = (unsigned int*)(*pointer_to_abstract_audio) + 16; + unsigned int *temp + = ((unsigned int*)(*dev_sound_wrapper) + 6); + CMMFDevSound *dev_sound = (CMMFDevSound*)(*temp); + dev_sound->SetVolume((unsigned int) + (percent*(float)dev_sound->MaxVolume())); +#endif +} + +/** + * A function used to lock the orientation. + */ +void GuitarTuner::setOrientation(Orientation orientation) +{ +#ifdef Q_OS_SYMBIAN + if (orientation != Auto) { +#if defined(ORIENTATIONLOCK) + const CAknAppUiBase::TAppUiOrientation uiOrientation = + (orientation == LockPortrait) + ? CAknAppUi::EAppUiOrientationPortrait + : CAknAppUi::EAppUiOrientationLandscape; + CAknAppUi* appUi = dynamic_cast<CAknAppUi*> + (CEikonEnv::Static()->AppUi()); + TRAPD(error, + if (appUi) + appUi->SetOrientationL(uiOrientation); + ); +#else // ORIENTATIONLOCK + qWarning(QString("'ORIENTATIONLOCK' needs to be defined on") + +QString(" Symbian when locking the orientation.")); +#endif // ORIENTATIONLOCK + } +#elif defined(Q_WS_MAEMO_5) + Qt::WidgetAttribute attribute; + switch (orientation) { + case LockPortrait: + attribute = Qt::WA_Maemo5PortraitOrientation; + break; + case LockLandscape: + attribute = Qt::WA_Maemo5LandscapeOrientation; + break; + case Auto: + default: + attribute = Qt::WA_Maemo5AutoOrientation; + break; + } + setAttribute(attribute, true); +#else // Q_OS_SYMBIAN + Q_UNUSED(orientation); +#endif // Q_OS_SYMBIAN +} |