1 /****************************************************************************
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
6 ** This file is part of the QtDeclarative module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:BSD$
9 ** You may use this file under the terms of the BSD license as follows:
11 ** "Redistribution and use in source and binary forms, with or without
12 ** modification, are permitted provided that the following conditions are
14 ** * Redistributions of source code must retain the above copyright
15 ** notice, this list of conditions and the following disclaimer.
16 ** * Redistributions in binary form must reproduce the above copyright
17 ** notice, this list of conditions and the following disclaimer in
18 ** the documentation and/or other materials provided with the
20 ** * Neither the name of The Qt Company Ltd nor the names of its
21 ** contributors may be used to endorse or promote products derived
22 ** from this software without specific prior written permission.
25 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
39 ****************************************************************************/
41 #include "guitartuner.h"
44 #include <SoundDevice.h>
45 #endif // Q_OS_SYMBIAN
47 #if defined(Q_OS_SYMBIAN) && defined(ORIENTATIONLOCK)
52 #endif // Q_OS_SYMBIAN && ORIENTATIONLOCK
54 GuitarTuner::GuitarTuner(QWidget *parent) :
59 m_guitarTunerUI = new QDeclarativeView(QUrl("qrc:/src/application.qml"), this);
60 setCentralWidget(m_guitarTunerUI);
61 m_guitarTunerUI->setResizeMode(QDeclarativeView::SizeRootObjectToView);
62 qmlObject = m_guitarTunerUI->rootObject();
64 // Init audio output and input.
68 // Connect the quit signal of m_guitarTunerUI
69 // into the close slot of this.
70 connect(m_guitarTunerUI->engine(), SIGNAL(quit()), SLOT(close()));
72 // Connect the signals from qmlObject into proper slots
73 // of this and m_voicegenerator.
74 connect(qmlObject, SIGNAL(muteStateChanged(bool)),
75 SLOT(muteStateChanged(bool)));
76 connect(qmlObject, SIGNAL(volumeChanged(qreal)),
77 m_voicegenerator, SLOT(setAmplitude(qreal)));
78 connect(qmlObject, SIGNAL(volumeChanged(qreal)),
79 SLOT(setMaxVolumeLevel(qreal)));
81 // Connect the modeChanged signal from qmlObject
82 // into modeChanged slot of this class.
83 connect(qmlObject, SIGNAL(modeChanged(bool)),
84 SLOT(modeChanged(bool)));
86 // Connect the microphoneSensitivityChanged signal from
87 // m_guitarTunerUI into setCutOffPercentage slot of m_analyzer class.
88 connect(qmlObject, SIGNAL(microphoneSensitivityChanged(qreal)),
89 m_analyzer, SLOT(setCutOffPercentage(qreal)));
91 // Connect the signals from m_analyzer into slots of qmlObject.
92 connect(m_analyzer, SIGNAL(lowVoice()),
93 qmlObject, SLOT(lowVoice()));
94 connect(m_analyzer, SIGNAL(correctFrequency()),
95 qmlObject, SLOT(correctFrequencyObtained()));
96 connect(m_analyzer, SIGNAL(voiceDifference(QVariant)),
97 qmlObject, SLOT(voiceDifferenceChanged(QVariant)));
99 // Initialise the MaximumVoiceDifference
100 // value of qmlObject with the value obtained from m_analyzer.
101 qmlObject->setProperty("maxVoiceDifference",
102 m_analyzer->getMaximumVoiceDifference());
104 // Connect the targetFrequencyChanged signal of qmlObject
105 // into targetFrequencyChanged slot of this class.
106 connect(qmlObject, SIGNAL(targetFrequencyChanged(qreal)),
107 SLOT(targetFrequencyChanged(qreal)));
109 // Start voice output or input by using the modeChanged function,
110 // depending of the current mode.
111 modeChanged(qmlObject->property("isInput").toBool());
116 * Inits audio output.
118 void GuitarTuner::initAudioOutput()
120 // Set up the output format.
121 m_format_output.setFrequency(DataFrequencyHzOutput);
122 m_format_output.setCodec("audio/pcm");
123 m_format_output.setSampleSize(16);
124 m_format_output.setChannels(1);
125 m_format_output.setByteOrder(QAudioFormat::LittleEndian);
126 m_format_output.setSampleType(QAudioFormat::SignedInt);
128 // Obtain a default output device, and if the format is not
129 // supported, find the nearest format available.
130 QAudioDeviceInfo outputDeviceInfo(
131 QAudioDeviceInfo::defaultOutputDevice());
132 if (!outputDeviceInfo.isFormatSupported(m_format_output)) {
133 m_format_output = outputDeviceInfo.nearestFormat(m_format_output);
136 // Create new QAudioOutput and VoiceGenerator instances, and store
137 // them in m_audioOutput and m_voicegenerator, respectively.
138 m_audioOutput = new QAudioOutput(outputDeviceInfo,
139 m_format_output, this);
140 m_voicegenerator = new VoiceGenerator(m_format_output,
141 qmlObject->property("frequency").toReal(),
142 qmlObject->property("volume").toReal(),
145 // Connect m_audioOutput stateChanged signal to outputStateChanged.
146 connect(m_audioOutput, SIGNAL(stateChanged(QAudio::State)),
147 SLOT(outputStateChanged(QAudio::State)));
153 void GuitarTuner::initAudioInput()
155 // Set up the input format.
156 m_format_input.setFrequency(DataFrequencyHzInput);
157 m_format_input.setCodec("audio/pcm");
158 m_format_input.setSampleSize(16);
159 m_format_input.setChannels(1);
160 m_format_input.setByteOrder(QAudioFormat::LittleEndian);
161 m_format_input.setSampleType(QAudioFormat::SignedInt);
163 // Obtain a default input device, and if the format is not
164 // supported, find the nearest format available.
165 QAudioDeviceInfo inputDeviceInfo(
166 QAudioDeviceInfo::defaultInputDevice());
167 if (!inputDeviceInfo.isFormatSupported(m_format_input)) {
168 m_format_input = inputDeviceInfo.nearestFormat(m_format_input);
171 // Create new QAudioInput and VoiceAnalyzer instances, and store
172 // them in m_audioInput and m_analyzer, respectively.
173 // Remember to set the cut-off percentage for voice analyzer.
174 m_audioInput = new QAudioInput(inputDeviceInfo, m_format_input, this);
175 m_analyzer = new VoiceAnalyzer(m_format_input, this);
176 m_analyzer->setCutOffPercentage(qmlObject->property("sensitivity").toReal());
181 * Receives a mode changed signal.
183 void GuitarTuner::modeChanged(bool isInput)
188 // If the mode must be changed to input mode:
191 // Stop audio output and audio generator.
192 m_audioOutput->stop();
193 m_voicegenerator->stop();
194 // Start the audio analyzer and then the audio input.
195 m_analyzer->start(qmlObject->property("frequency").toReal());
196 m_audioInput->start(m_analyzer);
202 // Stop audio input and audio analyzer.
203 m_audioInput->stop();
206 // Set up the audio output.
208 // If the current frequency of voice generator
209 // is not the same as the target frequency selected in the UI,
210 // update voice generator's frequency.
211 if (m_voicegenerator->frequency() != qmlObject->property("frequency").toReal()) {
212 m_voicegenerator->setFrequency(qmlObject->property("frequency").toReal());
215 // Start the voice generator and then the audio output.
216 m_voicegenerator->start();
217 m_audioOutput->start(m_voicegenerator);
218 // Call setMaxVolumeLevel(1) to set the maximum volume louder.
219 setMaxVolumeLevel(qmlObject->property("volume").toReal());
221 // If the voice is muted, the voice is suspended
222 // in the outputStateChanged slot.
228 * Receives a output state changed signal.
229 * Suspends the audio output, if the state is ActiveState
230 * and the voice is muted.
232 void GuitarTuner::outputStateChanged(QAudio::State state)
234 if (QAudio::ActiveState == state && qmlObject->property("isMuted").toBool()) {
235 // If the voice is muted, suspend the voice.
236 m_audioOutput->suspend();
241 * Receives a mute state changed signal.
242 * Suspends the audio output or resumes it, depending of the
245 void GuitarTuner::muteStateChanged(bool isMuted)
248 m_audioOutput->suspend();
251 m_audioOutput->resume();
256 * Receives a target frequency signal.
258 void GuitarTuner::targetFrequencyChanged(qreal targetFrequency)
260 // If the output mode is active:
261 if (!qmlObject->property("isInput").toBool()) {
262 // Stop the audio output and voice generator.
263 m_audioOutput->stop();
264 m_voicegenerator->stop();
265 // Set the voice generator's frequency to the target frequency.
266 m_voicegenerator->setFrequency(targetFrequency);
267 // Start the voice generator and audio output.
268 m_voicegenerator->start();
269 m_audioOutput->start(m_voicegenerator);
270 // Call setMaxVolumeLevel(1) to set the maximum volume louder.
271 setMaxVolumeLevel(qmlObject->property("volume").toReal());
273 // If the voice is muted, the voice is suspended
274 // in the outputStateChanged slot.
280 // Stop the audio input and voice analyzer.
281 m_audioInput->stop();
283 // Start the voice analyzer with new frequency and audio input.
284 m_analyzer->start(targetFrequency);
285 m_audioInput->start(m_analyzer);
291 * This method provides a hack to set the maximum volume level in
294 void GuitarTuner::setMaxVolumeLevel(qreal percent)
296 if (percent >= 1.0) {
299 else if (percent <= 0.0) {
302 percent = percent*0.5 + 0.5;
303 // Warning! This is a hack, which can break when the QtMobility
304 // changes. Use at your own risk.
306 unsigned int *pointer_to_abstract_audio
307 = (unsigned int*)( (unsigned char*)m_audioOutput + 8 );
308 unsigned int *dev_sound_wrapper
309 = (unsigned int*)(*pointer_to_abstract_audio) + 16;
311 = ((unsigned int*)(*dev_sound_wrapper) + 6);
312 CMMFDevSound *dev_sound = (CMMFDevSound*)(*temp);
313 dev_sound->SetVolume((unsigned int)
314 (percent*(float)dev_sound->MaxVolume()));
319 * A function used to lock the orientation.
321 void GuitarTuner::setOrientation(Orientation orientation)
324 if (orientation != Auto) {
325 #if defined(ORIENTATIONLOCK)
326 const CAknAppUiBase::TAppUiOrientation uiOrientation =
327 (orientation == LockPortrait)
328 ? CAknAppUi::EAppUiOrientationPortrait
329 : CAknAppUi::EAppUiOrientationLandscape;
330 CAknAppUi* appUi = dynamic_cast<CAknAppUi*>
331 (CEikonEnv::Static()->AppUi());
334 appUi->SetOrientationL(uiOrientation);
336 #else // ORIENTATIONLOCK
337 qWarning(QString("'ORIENTATIONLOCK' needs to be defined on")
338 +QString(" Symbian when locking the orientation."));
339 #endif // ORIENTATIONLOCK
341 #elif defined(Q_WS_MAEMO_5)
342 Qt::WidgetAttribute attribute;
343 switch (orientation) {
345 attribute = Qt::WA_Maemo5PortraitOrientation;
348 attribute = Qt::WA_Maemo5LandscapeOrientation;
352 attribute = Qt::WA_Maemo5AutoOrientation;
355 setAttribute(attribute, true);
356 #else // Q_OS_SYMBIAN
357 Q_UNUSED(orientation);
358 #endif // Q_OS_SYMBIAN