summaryrefslogtreecommitdiffstats
path: root/demos/mobile/guitartuner
diff options
context:
space:
mode:
Diffstat (limited to 'demos/mobile/guitartuner')
-rw-r--r--demos/mobile/guitartuner/guitartuner.pro89
-rw-r--r--demos/mobile/guitartuner/guitartuner.qrc43
-rw-r--r--demos/mobile/guitartuner/images/guitartab.svg174
-rw-r--r--demos/mobile/guitartuner/images/guitartuner_icon.svg247
-rw-r--r--demos/mobile/guitartuner/images/inputMode.svg161
-rw-r--r--demos/mobile/guitartuner/images/note.svg101
-rw-r--r--demos/mobile/guitartuner/images/noteNo.svg105
-rw-r--r--demos/mobile/guitartuner/src/application.qml328
-rw-r--r--demos/mobile/guitartuner/src/constants.h54
-rw-r--r--demos/mobile/guitartuner/src/fastfouriertransformer.cpp184
-rw-r--r--demos/mobile/guitartuner/src/fastfouriertransformer.h67
-rw-r--r--demos/mobile/guitartuner/src/fftpack.c1406
-rw-r--r--demos/mobile/guitartuner/src/guitartuner.cpp359
-rw-r--r--demos/mobile/guitartuner/src/guitartuner.h95
-rw-r--r--demos/mobile/guitartuner/src/guitartuner.rc23
-rw-r--r--demos/mobile/guitartuner/src/guitartuner.ui178
-rw-r--r--demos/mobile/guitartuner/src/guitartunerui.cpp341
-rw-r--r--demos/mobile/guitartuner/src/guitartunerui.h111
-rw-r--r--demos/mobile/guitartuner/src/guitartunerui.ui178
-rw-r--r--demos/mobile/guitartuner/src/main.cpp60
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/Adjuster.qml131
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/Meter.qml112
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/NoteButtonView.qml84
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/NotesModel.qml105
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/ToggleButton.qml110
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/adjustbars.js89
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/images/big_a.pngbin0 -> 575 bytes
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/images/big_b.pngbin0 -> 599 bytes
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/images/big_d.pngbin0 -> 465 bytes
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/images/big_e.pngbin0 -> 327 bytes
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/images/big_g.pngbin0 -> 610 bytes
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/images/glowing_a.pngbin0 -> 2978 bytes
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/images/glowing_b.pngbin0 -> 3084 bytes
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/images/glowing_d.pngbin0 -> 2940 bytes
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/images/glowing_e.pngbin0 -> 2696 bytes
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/images/glowing_g.pngbin0 -> 3046 bytes
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/images/guitartuner_malli.pngbin0 -> 143243 bytes
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/images/guitartuner_skin.pngbin0 -> 129068 bytes
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/images/lcdFrame.pngbin0 -> 176107 bytes
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/images/meterBG.pngbin0 -> 8378 bytes
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/images/mute.pngbin0 -> 3630 bytes
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/images/pointer.pngbin0 -> 965 bytes
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/images/pointerShadow.pngbin0 -> 1694 bytes
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/images/power.pngbin0 -> 3190 bytes
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/images/quit.pngbin0 -> 1363 bytes
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/images/sensitivity.pngbin0 -> 835 bytes
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/images/tuner_a.pngbin0 -> 3233 bytes
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/images/tuner_a_on.pngbin0 -> 3068 bytes
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/images/tuner_auto.pngbin0 -> 3619 bytes
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/images/tuner_auto_on.pngbin0 -> 3281 bytes
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/images/tuner_b.pngbin0 -> 3324 bytes
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/images/tuner_b_on.pngbin0 -> 3132 bytes
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/images/tuner_d.pngbin0 -> 3266 bytes
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/images/tuner_d_on.pngbin0 -> 3009 bytes
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/images/tuner_e.pngbin0 -> 3171 bytes
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/images/tuner_e_on.pngbin0 -> 2955 bytes
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/images/tuner_g.pngbin0 -> 3292 bytes
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/images/tuner_g_on.pngbin0 -> 3089 bytes
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/images/voicemode_off.pngbin0 -> 3775 bytes
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/images/voicemode_on.pngbin0 -> 3484 bytes
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/images/volume.pngbin0 -> 351 bytes
-rw-r--r--demos/mobile/guitartuner/src/mycomponents/images/volume_off.pngbin0 -> 2235 bytes
-rw-r--r--demos/mobile/guitartuner/src/voiceanalyzer.cpp295
-rw-r--r--demos/mobile/guitartuner/src/voiceanalyzer.h93
-rw-r--r--demos/mobile/guitartuner/src/voicegenerator.cpp246
-rw-r--r--demos/mobile/guitartuner/src/voicegenerator.h86
66 files changed, 5655 insertions, 0 deletions
diff --git a/demos/mobile/guitartuner/guitartuner.pro b/demos/mobile/guitartuner/guitartuner.pro
new file mode 100644
index 00000000..62835300
--- /dev/null
+++ b/demos/mobile/guitartuner/guitartuner.pro
@@ -0,0 +1,89 @@
+#-------------------------------------------------
+#
+# Project created by QtCreator 2010-10-22T14:28:56
+#
+#-------------------------------------------------
+
+QT += core gui
+
+TARGET = guitartuner
+TEMPLATE = app
+
+ICON = images/guitartuner_icon.svg
+
+SOURCES += src/main.cpp\
+ src/guitartuner.cpp \
+ src/voicegenerator.cpp \
+ src/voiceanalyzer.cpp \
+ src/guitartunerui.cpp \
+ src/fastfouriertransformer.cpp
+
+HEADERS += src/guitartuner.h \
+ src/voicegenerator.h \
+ src/voiceanalyzer.h \
+ src/constants.h \
+ src/guitartunerui.h \
+ src/fastfouriertransformer.h
+
+FORMS += src/guitartunerui.ui
+
+VERSION = 1.2.0
+
+symbian {
+ INCLUDEPATH += /epoc32/include/mmf/common
+ INCLUDEPATH += /epoc32/include/mmf/server
+ LIBS += -lmmfdevsound
+ TARGET.UID3 = 0xEC46D2C8
+ # TARGET.CAPABILITY +=
+ # TARGET.EPOCSTACKSIZE = 0x14000
+ # TARGET.EPOCHEAPSIZE = 0x020000 0x1000000
+}
+
+RESOURCES += \
+ guitartuner.qrc
+
+# Avoid auto screen rotation
+DEFINES += ORIENTATIONLOCK
+
+symbian {
+ contains(DEFINES, ORIENTATIONLOCK):LIBS += -lavkon -leikcore -leiksrv -lcone
+}
+
+
+# Add mobility into Qt's CONFIG, and add multimedia into MOBILITY.
+
+win32 {
+ QT += multimedia
+ RC_FILE = src/guitartuner.rc
+}
+else {
+ CONFIG += mobility
+ MOBILITY += multimedia
+}
+
+symbian {
+ TARGET.CAPABILITY = UserEnvironment
+}
+
+# Add declarative module
+QT += declarative
+
+OTHER_FILES += \
+ src/application.qml \
+ src/mycomponents/Adjuster.qml \
+ src/mycomponents/adjustbars.js \
+ src/mycomponents/ToggleButton.qml
+
+OTHER_FILES += \
+ src/mycomponents/NotesModel.qml \
+ src/mycomponents/NoteButtonView.qml \
+ src/mycomponents/Meter.qml
+
+unix:!symbian {
+ maemo5 {
+ target.path = /opt/usr/bin
+ } else {
+ target.path = /usr/local/bin
+ }
+ INSTALLS += target
+}
diff --git a/demos/mobile/guitartuner/guitartuner.qrc b/demos/mobile/guitartuner/guitartuner.qrc
new file mode 100644
index 00000000..d8ba0199
--- /dev/null
+++ b/demos/mobile/guitartuner/guitartuner.qrc
@@ -0,0 +1,43 @@
+<RCC>
+ <qresource prefix="/">
+ <file>src/application.qml</file>
+ <file>src/mycomponents/adjustbars.js</file>
+ <file>src/mycomponents/Adjuster.qml</file>
+ <file>src/mycomponents/Meter.qml</file>
+ <file>src/mycomponents/NoteButtonView.qml</file>
+ <file>src/mycomponents/NotesModel.qml</file>
+ <file>src/mycomponents/ToggleButton.qml</file>
+ <file>src/mycomponents/images/meterBG.png</file>
+ <file>src/mycomponents/images/pointerShadow.png</file>
+ <file>src/mycomponents/images/sensitivity.png</file>
+ <file>src/mycomponents/images/tuner_a.png</file>
+ <file>src/mycomponents/images/tuner_a_on.png</file>
+ <file>src/mycomponents/images/tuner_b.png</file>
+ <file>src/mycomponents/images/tuner_b_on.png</file>
+ <file>src/mycomponents/images/tuner_d.png</file>
+ <file>src/mycomponents/images/tuner_d_on.png</file>
+ <file>src/mycomponents/images/tuner_e.png</file>
+ <file>src/mycomponents/images/tuner_e_on.png</file>
+ <file>src/mycomponents/images/tuner_g.png</file>
+ <file>src/mycomponents/images/tuner_g_on.png</file>
+ <file>src/mycomponents/images/voicemode_off.png</file>
+ <file>src/mycomponents/images/voicemode_on.png</file>
+ <file>src/mycomponents/images/volume.png</file>
+ <file>src/mycomponents/images/volume_off.png</file>
+ <file>src/mycomponents/images/guitartuner_skin.png</file>
+ <file>src/mycomponents/images/power.png</file>
+ <file>src/mycomponents/images/tuner_auto.png</file>
+ <file>src/mycomponents/images/tuner_auto_on.png</file>
+ <file>src/mycomponents/images/big_a.png</file>
+ <file>src/mycomponents/images/big_b.png</file>
+ <file>src/mycomponents/images/big_d.png</file>
+ <file>src/mycomponents/images/big_e.png</file>
+ <file>src/mycomponents/images/big_g.png</file>
+ <file>src/mycomponents/images/glowing_a.png</file>
+ <file>src/mycomponents/images/glowing_b.png</file>
+ <file>src/mycomponents/images/glowing_d.png</file>
+ <file>src/mycomponents/images/glowing_e.png</file>
+ <file>src/mycomponents/images/glowing_g.png</file>
+ <file>src/mycomponents/images/pointer.png</file>
+ </qresource>
+</RCC>
diff --git a/demos/mobile/guitartuner/images/guitartab.svg b/demos/mobile/guitartuner/images/guitartab.svg
new file mode 100644
index 00000000..9d88d5d2
--- /dev/null
+++ b/demos/mobile/guitartuner/images/guitartab.svg
@@ -0,0 +1,174 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="70.661781"
+ height="55.997791"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.47 r22583"
+ sodipodi:docname="guitartab.svg">
+ <defs
+ id="defs4">
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective10" />
+ <inkscape:perspective
+ id="perspective3604"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ id="perspective3632"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ id="perspective3632-4"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ id="perspective3632-9"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ id="perspective3632-8"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ id="perspective3632-2"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ id="perspective3690"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ id="perspective3712"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.98994949"
+ inkscape:cx="343.43632"
+ inkscape:cy="198.00574"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1280"
+ inkscape:window-height="888"
+ inkscape:window-x="-4"
+ inkscape:window-y="-4"
+ inkscape:window-maximized="1"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ borderlayer="true" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-45.793001,-702.07386)">
+ <rect
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.96666431;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect3728"
+ width="68.695114"
+ height="54.031128"
+ x="46.776333"
+ y="703.05719" />
+ <g
+ id="g3732"
+ transform="matrix(0.11166616,0,0,0.11166616,41.003771,673.42071)">
+ <path
+ sodipodi:nodetypes="cc"
+ id="path2816"
+ d="m 133.63811,570.46864 0,-225.36571"
+ style="fill:none;stroke:#000000;stroke-width:17.61199951;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path2816-7"
+ d="m 223.89631,570.46864 0,-225.36571"
+ style="fill:none;stroke:#000000;stroke-width:17.61199951;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path2816-0"
+ d="m 314.15451,570.46864 0,-225.36571"
+ style="fill:none;stroke:#000000;stroke-width:17.61199951;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path2816-4"
+ d="m 404.4127,570.46864 0,-225.36571"
+ style="fill:none;stroke:#000000;stroke-width:17.61199951;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path2816-8"
+ d="m 494.6709,570.46864 0,-225.36571"
+ style="fill:none;stroke:#000000;stroke-width:17.61199951;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path2816-45"
+ d="m 584.92911,570.46864 0,-225.36571"
+ style="fill:none;stroke:#000000;stroke-width:17.61199951;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path2816-5"
+ d="m 124.89988,344.21478 468.77277,0"
+ style="fill:none;stroke:#000000;stroke-width:19.51578331;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path2816-5-1"
+ d="m 125.76355,400.6818 467.80305,0"
+ style="fill:none;stroke:#000000;stroke-width:19.4955883;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ </g>
+ </g>
+</svg>
diff --git a/demos/mobile/guitartuner/images/guitartuner_icon.svg b/demos/mobile/guitartuner/images/guitartuner_icon.svg
new file mode 100644
index 00000000..de7ebe0f
--- /dev/null
+++ b/demos/mobile/guitartuner/images/guitartuner_icon.svg
@@ -0,0 +1,247 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 15.0.2, SVG Export Plug-In -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
+]>
+<svg version="1.1"
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
+ x="0px" y="0px" width="128px" height="128px" viewBox="0 0 128 128" overflow="visible" enable-background="new 0 0 128 128"
+ xml:space="preserve">
+<defs>
+</defs>
+<rect x="0" display="none" fill="#1A171B" width="128" height="128"/>
+<circle fill="#13235B" cx="64" cy="64" r="47"/>
+<g>
+ <g>
+ <path fill="#F29400" d="M14.352,113.699c0,0-13.927-13.928-3.122-24.732c7.203-7.205,11.706-2.701,15.308-6.305
+ c3.602-3.601,1.417-6.729,5.28-10.84c7.547-8.035,15.842,3.149,15.842,3.149l4.765,4.765l-7.204,7.204
+ c0,0,5.134,7.943,12.338,0.74c-3.827,10.578-9.411,9.39-13.014,12.99c-3.602,3.603,0.854,8.058-6.303,15.31
+ C27.508,126.855,14.352,113.699,14.352,113.699z"/>
+ </g>
+ <defs>
+ <filter id="Adobe_OpacityMaskFilter" filterUnits="userSpaceOnUse" x="7.122" y="68.918" width="50.437" height="51.368">
+
+ <feColorMatrix type="matrix" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0" color-interpolation-filters="sRGB" result="source"/>
+ </filter>
+ </defs>
+ <mask maskUnits="userSpaceOnUse" x="7.122" y="68.918" width="50.437" height="51.368" id="SVGID_1_">
+ <g filter="url(#Adobe_OpacityMaskFilter)">
+
+ <image overflow="visible" width="55" height="57" xlink:href="data:image/jpeg;base64,/9j/4AAQSkZJRgABAgEASABIAAD/7AARRHVja3kAAQAEAAAAHgAA/+4AIUFkb2JlAGTAAAAAAQMA
+EAMCAwYAAAG8AAACPgAAAr//2wCEABALCwsMCxAMDBAXDw0PFxsUEBAUGx8XFxcXFx8eFxoaGhoX
+Hh4jJSclIx4vLzMzLy9AQEBAQEBAQEBAQEBAQEABEQ8PERMRFRISFRQRFBEUGhQWFhQaJhoaHBoa
+JjAjHh4eHiMwKy4nJycuKzU1MDA1NUBAP0BAQEBAQEBAQEBAQP/CABEIADkANwMBIgACEQEDEQH/
+xAB9AAABBQEBAAAAAAAAAAAAAAAAAgQFBgcBAwEBAAAAAAAAAAAAAAAAAAAAABAAAgMAAgICAwAA
+AAAAAAAAAgMBBAUABhBAMBEhEiMRAAICAQMFAQAAAAAAAAAAAAECABEhEEESIDFRIgMwEgEAAAAA
+AAAAAAAAAAAAAABA/9oADAMBAAIRAxEAAADPwAc+F5Kkx0alEcAdmuaSVq5PFkFles5qQR0J/T8X
+0IuyGbQrdAm4IAAcNwsnjAgpIAAf/9oACAECAAEFAPQ//9oACAEDAAEFAPQ//9oACAEBAAEFAPNa
+k2xx+W5UTExPlYSw8bI/jezBFerWBTeCJGVDrjrEZPT1qZUzgSvZT+qtc2zc516mL25WcuABIBHN
+loQvbZXln3+eruEG5bRJfGnAB27WJKzYbC5TslWfh7YECtNZDoagQvst6LDfNW8+qVbtBCN3sRtF
+jDYfw//aAAgBAgIGPwAH/9oACAEDAgY/AAf/2gAIAQEBBj8A1tRichkSj36FRcljUW12hsQlcHQK
+osnsIC952EH0ZbPkwCo1DaOrigD66cmF5gxMDRrMY4Jl7Tie9wVoTGCnJwIWc2Tov0U43i+0u4aM
+4A3m+i0bHiU5IMKoSSYXc2T+X//Z" transform="matrix(1 0 0 1 5.0005 66)">
+ </image>
+ </g>
+ </mask>
+ <g mask="url(#SVGID_1_)">
+ <path fill="#B20000" d="M14.352,113.699c0,0-13.927-13.928-3.122-24.732c7.203-7.205,11.706-2.701,15.308-6.305
+ c3.602-3.601,1.417-6.729,5.28-10.84c7.547-8.035,15.842,3.149,15.842,3.149l4.765,4.765l-7.204,7.204
+ c0,0,5.134,7.943,12.338,0.74c-3.827,10.578-9.411,9.39-13.014,12.99c-3.602,3.603,0.854,8.058-6.303,15.31
+ C27.508,126.855,14.352,113.699,14.352,113.699z"/>
+ </g>
+</g>
+<g>
+ <path fill="#FFEDB8" d="M37.791,69.168c5.189,0,9.624,5.894,9.692,5.98l4.588,4.588l-7.027,7.027l-0.143,0.143l0.11,0.17
+ c0.102,0.158,2.55,3.875,6.503,3.875c1.808,0,3.63-0.791,5.427-2.352c-2.541,6.327-5.777,7.936-8.649,9.362
+ c-1.422,0.707-2.765,1.374-3.924,2.532c-1.562,1.562-1.672,3.261-1.8,5.227c-0.171,2.633-0.384,5.909-4.504,10.084
+ c-2.771,2.808-5.958,4.231-9.472,4.231c-7.46,0-14-6.448-14.064-6.514c-0.137-0.138-13.625-13.877-3.122-24.379
+ c4.152-4.153,7.301-4.348,10.078-4.519c1.97-0.122,3.67-0.227,5.229-1.786c1.829-1.829,2.218-3.585,2.595-5.284
+ c0.384-1.735,0.782-3.529,2.69-5.562C33.761,70.118,35.709,69.168,37.791,69.168 M37.791,68.918c-1.932,0-3.979,0.781-5.974,2.904
+ c-3.862,4.11-1.678,7.239-5.28,10.84c-3.602,3.604-8.104-0.9-15.308,6.305c-10.805,10.805,3.122,24.732,3.122,24.732
+ s6.586,6.587,14.241,6.587c3.164,0,6.51-1.126,9.649-4.306c7.157-7.252,2.701-11.707,6.303-15.31
+ c3.603-3.601,9.187-2.412,13.014-12.99c-2.248,2.247-4.293,3.021-6.044,3.021c-3.862,0-6.293-3.761-6.293-3.761l7.204-7.204
+ l-4.765-4.765C47.66,74.972,43.17,68.918,37.791,68.918L37.791,68.918z"/>
+</g>
+<rect x="35.983" y="67.296" transform="matrix(-0.7071 0.7071 -0.7071 -0.7071 146.0415 81.7395)" fill="#41281B" width="40.217" height="7.64"/>
+<rect x="35.697" y="84.509" transform="matrix(-0.7073 0.707 -0.707 -0.7073 128.185 124.851)" fill="#ECEDED" width="5.092" height="8.913"/>
+<rect x="27.593" y="92.612" transform="matrix(-0.7072 0.7071 -0.7071 -0.7072 120.0864 144.402)" fill="#ECEDED" width="5.092" height="8.914"/>
+<rect x="24.55" y="96.293" transform="matrix(-0.7071 0.7071 -0.7071 -0.7071 115.1376 156.3543)" fill="#F6F6F6" width="1.273" height="11.46"/>
+<rect x="26.351" y="94.491" transform="matrix(-0.7071 0.7071 -0.7071 -0.7071 116.9377 152.0052)" fill="#F6F6F6" width="1.273" height="11.461"/>
+<line fill="none" stroke="#FFFFFF" stroke-width="0.15" stroke-miterlimit="10" x1="23.499" y1="99.433" x2="66.495" y2="56.438"/>
+<line fill="none" stroke="#FFFFFF" stroke-width="0.15" stroke-miterlimit="10" x1="28" y1="103.934" x2="70.997" y2="60.941"/>
+<line fill="none" stroke="#FFFFFF" stroke-width="0.15" stroke-miterlimit="10" x1="27.101" y1="103.034" x2="70.096" y2="60.04"/>
+<line fill="none" stroke="#FFFFFF" stroke-width="0.15" stroke-miterlimit="10" x1="26.2" y1="102.134" x2="69.196" y2="59.139"/>
+<line fill="none" stroke="#FFFFFF" stroke-width="0.15" stroke-miterlimit="10" x1="25.3" y1="101.233" x2="68.295" y2="58.239"/>
+<line fill="none" stroke="#FFFFFF" stroke-width="0.15" stroke-miterlimit="10" x1="24.4" y1="100.333" x2="67.395" y2="57.339"/>
+<circle fill="#1A171B" cx="26.908" cy="113.596" r="1.761"/>
+<path fill="#1A171B" d="M33.138,107.366c0.688,0.687,0.688,1.804,0,2.493c-0.688,0.686-1.804,0.686-2.492,0
+ c-0.688-0.689-0.688-1.807,0-2.493C31.334,106.678,32.45,106.678,33.138,107.366z"/>
+<circle fill="#FFEDB8" cx="36.848" cy="75.131" r="1.762"/>
+<circle fill="#1A171B" cx="32.31" cy="115.397" r="1.762"/>
+<path fill="#1A171B" d="M38.54,109.167c0.689,0.687,0.689,1.804,0,2.493c-0.688,0.686-1.804,0.686-2.492,0
+ c-0.688-0.689-0.688-1.807,0-2.493C36.736,108.479,37.852,108.479,38.54,109.167z"/>
+<g>
+ <g>
+ <path fill="#ECEDED" d="M105.895,10.52l2.704,2.702L70.764,51.056c0,0-2.702,2.702,0,5.404c2.704,2.702,5.405,0,5.405,0
+ l37.833-37.833l2.704,2.702c0,0-35.132,35.131-37.835,37.833c-2.702,2.702-8.107,2.702-10.81,0s-2.702-8.106,0-10.809
+ C70.765,45.649,105.895,10.52,105.895,10.52z"/>
+ </g>
+ <defs>
+ <filter id="Adobe_OpacityMaskFilter_1_" filterUnits="userSpaceOnUse" x="66.036" y="10.52" width="50.671" height="50.669">
+
+ <feColorMatrix type="matrix" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0" color-interpolation-filters="sRGB" result="source"/>
+ </filter>
+ </defs>
+ <mask maskUnits="userSpaceOnUse" x="66.036" y="10.52" width="50.671" height="50.669" id="SVGID_2_">
+ <g filter="url(#Adobe_OpacityMaskFilter_1_)">
+
+ <image overflow="visible" width="55" height="56" xlink:href="data:image/jpeg;base64,/9j/4AAQSkZJRgABAgEASABIAAD/7AARRHVja3kAAQAEAAAAHgAA/+4AIUFkb2JlAGTAAAAAAQMA
+EAMCAwYAAAGyAAACNwAAA9T/2wCEABALCwsMCxAMDBAXDw0PFxsUEBAUGx8XFxcXFx8eFxoaGhoX
+Hh4jJSclIx4vLzMzLy9AQEBAQEBAQEBAQEBAQEABEQ8PERMRFRISFRQRFBEUGhQWFhQaJhoaHBoa
+JjAjHh4eHiMwKy4nJycuKzU1MDA1NUBAP0BAQEBAQEBAQEBAQP/CABEIADgANwMBIgACEQEDEQH/
+xACCAAEBAQADAAAAAAAAAAAAAAAABgQDBQcBAQAAAAAAAAAAAAAAAAAAAAAQAQEBAAIDAQEAAAAA
+AAAAAAUEBhADACBAAQIRAAIBAgQEBgIDAQAAAAAAAAECAxEEACFREjHBQgUQIGEyUhNBFZEiIwYS
+AQAAAAAAAAAAAAAAAAAAAED/2gAMAwEAAhEDEQAAAPPwDcOwp4w61WCTNwt0YL95scjGN1vxSIv3
+mwzgBUdyENnAAD//2gAIAQIAAQUA+D//2gAIAQMAAQUA+D//2gAIAQEAAQUA9Bx7GLNSHCL3+g49
+jFiKJuMNONS0CLmRkOQ4HHsYsRRNxhppqWgSqqJwxPatd3JeDj2MWIom4w001LQJVVE4Ym66pCrw
+cexixFE3GGmmpaBKqonDE3XVIVcZ+r9JwppqWgSqqJwxN11SFXOV1/8ABHR3bgAvouuqQq9P/9oA
+CAECAgY/AAf/2gAIAQMCBj8AB//aAAgBAQEGPwDyLaWi1Jzdz7UXU4ht7e4+2bb/ALJxofl6eVbS
+0WpObufai6nH6ztlJO4yCskhzNT1vyGPrjrJNId00zZhQepuQx22xhudz3kkcMgNNw3sF3j+fFbS
+0WpObufai6nH6ztlJO4yCskhzNT1vyGPrjrJNId00zZhQepuQwLe3AlvpRkOt3+TaAYXuksm+6SR
+ZVY8AUO5QBoPBbS0WpObufai6nH6ztlJO4yCskhzNT1vyGPrjrJNId00zZhQepuQwLe3AlvpRkOt
+3+TaAYe7u3Mk0hqSeAGg9PBbS0WpObufai6nH6ztlJO4yCskhzNT1vyGPrjrJNId00zZhQepuQwL
+e3AlvpRkOt3+TaAYe7u3Mk0hqSeAGg9PGfuVrFW6ZnBYCpru2Bm9Fx9cdZJpDummbMKD1NyGBb24
+Et9KMh1u/wAm0Aw93duZJpDUk8ANB6eRu33sJnspGJyoSm7j/X8j84ZP+fsgJJM2IT6lB9cqnD3d
+25kmkNSTwA0Hp5f/2Q==" transform="matrix(1 0 0 1 64.0005 8)">
+ </image>
+ </g>
+ </mask>
+ <g opacity="0.77" mask="url(#SVGID_2_)">
+ <path fill="#1C1B1B" d="M105.895,10.52l2.704,2.702L70.764,51.056c0,0-2.702,2.702,0,5.404c2.704,2.702,5.405,0,5.405,0
+ l37.833-37.833l2.704,2.702c0,0-35.132,35.131-37.835,37.833c-2.702,2.702-8.107,2.702-10.81,0s-2.702-8.106,0-10.809
+ C70.765,45.649,105.895,10.52,105.895,10.52z"/>
+ </g>
+</g>
+<line fill="none" stroke="#FFFFFF" stroke-width="0.25" stroke-miterlimit="10" x1="40.044" y1="81.762" x2="45.447" y2="87.166"/>
+<line fill="none" stroke="#FFFFFF" stroke-width="0.25" stroke-miterlimit="10" x1="40.966" y1="80.84" x2="46.37" y2="86.241"/>
+<line fill="none" stroke="#FFFFFF" stroke-width="0.25" stroke-miterlimit="10" x1="41.96" y1="79.846" x2="47.363" y2="85.248"/>
+<line fill="none" stroke="#FFFFFF" stroke-width="0.25" stroke-miterlimit="10" x1="43.168" y1="78.639" x2="48.57" y2="84.042"/>
+<line fill="none" stroke="#FFFFFF" stroke-width="0.25" stroke-miterlimit="10" x1="44.587" y1="77.219" x2="49.99" y2="82.623"/>
+<line fill="none" stroke="#FFFFFF" stroke-width="0.25" stroke-miterlimit="10" x1="46.006" y1="75.801" x2="51.41" y2="81.203"/>
+<line fill="none" stroke="#FFFFFF" stroke-width="0.25" stroke-miterlimit="10" x1="47.285" y1="74.522" x2="52.688" y2="79.925"/>
+<line fill="none" stroke="#FFFFFF" stroke-width="0.25" stroke-miterlimit="10" x1="48.847" y1="72.961" x2="54.249" y2="78.362"/>
+<line fill="none" stroke="#FFFFFF" stroke-width="0.25" stroke-miterlimit="10" x1="50.621" y1="71.185" x2="56.023" y2="76.589"/>
+<line fill="none" stroke="#FFFFFF" stroke-width="0.25" stroke-miterlimit="10" x1="52.489" y1="69.329" x2="57.891" y2="74.731"/>
+<line fill="none" stroke="#FFFFFF" stroke-width="0.25" stroke-miterlimit="10" x1="54.405" y1="67.4" x2="59.709" y2="72.704"/>
+<line fill="none" stroke="#FFFFFF" stroke-width="0.25" stroke-miterlimit="10" x1="56.517" y1="65.392" x2="61.821" y2="70.696"/>
+<line fill="none" stroke="#FFFFFF" stroke-width="0.25" stroke-miterlimit="10" x1="59.166" y1="62.744" x2="64.469" y2="68.047"/>
+<line fill="none" stroke="#FFFFFF" stroke-width="0.25" stroke-miterlimit="10" x1="61.883" y1="60.026" x2="67.187" y2="65.329"/>
+<line fill="none" stroke="#FFFFFF" stroke-width="0.25" stroke-miterlimit="10" x1="64.902" y1="57.007" x2="70.206" y2="62.31"/>
+<g display="none">
+ <g display="inline">
+ <path fill="#F29400" d="M0,24.468C0,24.468,0,9,12,9c8,0,8,5,12,5s4.525-2.95,8.952-3.088C41.605,10.642,40,21.458,40,21.458
+ v5.291h-8c0,0-1.56,7.262,6.44,7.262C30.44,37.762,28,34,24,34c-4,0-4,4.948-12,5C0,39.078,0,24.468,0,24.468z"/>
+ </g>
+ <defs>
+ <filter id="Adobe_OpacityMaskFilter_2_" filterUnits="userSpaceOnUse" x="0" y="9" width="40.118" height="30">
+
+ <feColorMatrix type="matrix" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0" color-interpolation-filters="sRGB" result="source"/>
+ </filter>
+ </defs>
+ <mask maskUnits="userSpaceOnUse" x="0" y="9" width="40.118" height="30" id="SVGID_3_" display="inline">
+ <g filter="url(#Adobe_OpacityMaskFilter_2_)">
+
+ <image overflow="visible" width="46" height="35" xlink:href="data:image/jpeg;base64,/9j/4AAQSkZJRgABAgEASABIAAD/7AARRHVja3kAAQAEAAAAHgAA/+4AIUFkb2JlAGTAAAAAAQMA
+EAMCAwYAAAGrAAACBgAAAl3/2wCEABALCwsMCxAMDBAXDw0PFxsUEBAUGx8XFxcXFx8eFxoaGhoX
+Hh4jJSclIx4vLzMzLy9AQEBAQEBAQEBAQEBAQEABEQ8PERMRFRISFRQRFBEUGhQWFhQaJhoaHBoa
+JjAjHh4eHiMwKy4nJycuKzU1MDA1NUBAP0BAQEBAQEBAQEBAQP/CABEIACMALgMBIgACEQEDEQH/
+xAB+AAABBQEBAAAAAAAAAAAAAAAAAgMFBgcEAQEBAAAAAAAAAAAAAAAAAAAAABAAAgMAAgIDAQAA
+AAAAAAAAAgMBBAUREzAGECAxFBEAAgEEAQMFAAAAAAAAAAAAAAERIUECElEQMYEgIkIDExIBAAAA
+AAAAAAAAAAAAAAAAMP/aAAwDAQACEQMRAAAAoEknQjPuDXogztq4Vo7NJyW2mgQdegRyGUyCwPEg
+AB//2gAIAQIAAQUA8P8A/9oACAEDAAEFAPD/AP/aAAgBAQABBQARkpr4r3DYxLKR6W8zUfA8TzjV
+4dZzMwJB2Mshs4aQm9VWsZAf7vXigbGW4IBllcDp3VwOtrlL+0u2nYmu6jvgIXPZxALHsLnTYdDi
++A/D+n//2gAIAQICBj8AH//aAAgBAwIGPwAf/9oACAEBAQY/AFjipbJdzZLY10c8QbPEi5WsCoVx
+G9UNJGONmxzyI7jhmX1pU5P1uLNdri9w4yHRwbX6/LwX8+j/2Q==" transform="matrix(1 0 0 1 -2.9995 6)">
+ </image>
+ </g>
+ </mask>
+ <g display="inline" mask="url(#SVGID_3_)">
+ <path fill="#B20000" d="M0,24.468C0,24.468,0,9,12,9c8,0,8,5,12,5s4.525-2.95,8.952-3.088C41.605,10.642,40,21.458,40,21.458
+ v5.291h-8c0,0-1.56,7.262,6.44,7.262C30.44,37.762,28,34,24,34c-4,0-4,4.948-12,5C0,39.078,0,24.468,0,24.468z"/>
+ </g>
+</g>
+<g display="none">
+ <path display="inline" fill="#FFEDB8" d="M12,9.25c4.592,0,6.439,1.633,8.07,3.075c1.169,1.033,2.179,1.926,3.93,1.926
+ c2.047,0,3.246-0.764,4.405-1.502c1.171-0.746,2.382-1.518,4.555-1.585c0.104-0.003,0.207-0.005,0.308-0.005
+ c2.021,0,3.606,0.649,4.712,1.931c2.537,2.939,1.782,8.28,1.771,8.37V26.5H32h-0.202l-0.042,0.197
+ c-0.028,0.13-0.663,3.21,1.127,5.426c0.979,1.211,2.483,1.913,4.481,2.093c-1.956,0.813-3.706,1.21-5.323,1.21
+ c-1.76,0-3.121-0.458-4.438-0.9C26.416,34.126,25.295,33.75,24,33.75c-1.755,0-2.766,0.888-3.937,1.916
+ c-1.631,1.432-3.479,3.054-8.064,3.084l-0.095,0C0.388,38.75,0.25,24.61,0.25,24.468C0.25,24.315,0.391,9.25,12,9.25 M12,9
+ C0,9,0,24.468,0,24.468S-0.002,39,11.904,39c0.031,0,0.064,0,0.096,0c8-0.052,8-5,12-5c2.67,0,4.644,1.675,8.041,1.675
+ c1.692,0,3.739-0.416,6.4-1.664c-8,0-6.44-7.262-6.44-7.262h8v-5.291c0,0,1.566-10.551-6.733-10.551
+ c-0.104,0-0.209,0.001-0.316,0.005C28.525,11.05,28,14,24,14S20,9,12,9L12,9z"/>
+</g>
+<rect x="31.032" y="21" display="none" fill="#41281B" width="32.967" height="6"/>
+<rect x="25" y="20.5" display="none" fill="#ECEDED" width="3.999" height="7"/>
+<rect x="16.001" y="20.5" display="none" fill="#ECEDED" width="3.999" height="7"/>
+<rect x="12" y="19.5" display="none" fill="#F6F6F6" width="1" height="9"/>
+<rect x="14" y="19.5" display="none" fill="#F6F6F6" width="1" height="9"/>
+<line display="none" fill="none" stroke="#FFFFFF" stroke-width="0.15" stroke-miterlimit="10" x1="13" y1="21.625" x2="60.75" y2="21.625"/>
+<line display="none" fill="none" stroke="#FFFFFF" stroke-width="0.15" stroke-miterlimit="10" x1="13" y1="26.625" x2="60.75" y2="26.625"/>
+<line display="none" fill="none" stroke="#FFFFFF" stroke-width="0.15" stroke-miterlimit="10" x1="13" y1="25.625" x2="60.75" y2="25.625"/>
+<line display="none" fill="none" stroke="#FFFFFF" stroke-width="0.15" stroke-miterlimit="10" x1="13" y1="24.625" x2="60.75" y2="24.625"/>
+<line display="none" fill="none" stroke="#FFFFFF" stroke-width="0.15" stroke-miterlimit="10" x1="13" y1="23.625" x2="60.75" y2="23.625"/>
+<line display="none" fill="none" stroke="#FFFFFF" stroke-width="0.15" stroke-miterlimit="10" x1="13" y1="22.625" x2="60.75" y2="22.625"/>
+<circle display="none" fill="#1A171B" cx="7.029" cy="31.382" r="1.384"/>
+<circle display="none" fill="#1A171B" cx="12.564" cy="31.382" r="1.384"/>
+<circle display="none" fill="#FFEDB8" cx="33.908" cy="15.543" r="1.384"/>
+<circle display="none" fill="#1A171B" cx="9.029" cy="35.382" r="1.384"/>
+<circle display="none" fill="#1A171B" cx="14.564" cy="35.382" r="1.384"/>
+<g display="none">
+ <g display="inline">
+ <path fill="#ECEDED" d="M124,16v4H68c0,0-4,0-4,4s4,4,4,4h56v4c0,0-52,0-56,0s-8-4-8-8s4-8,8-8C72.001,16,124,16,124,16z"/>
+ </g>
+ <defs>
+ <filter id="Adobe_OpacityMaskFilter_3_" filterUnits="userSpaceOnUse" x="60" y="16" width="64" height="16">
+
+ <feColorMatrix type="matrix" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0" color-interpolation-filters="sRGB" result="source"/>
+ </filter>
+ </defs>
+ <mask maskUnits="userSpaceOnUse" x="60" y="16" width="64" height="16" id="SVGID_4_" display="inline">
+ <g filter="url(#Adobe_OpacityMaskFilter_3_)">
+
+ <image overflow="visible" width="68" height="20" xlink:href="data:image/jpeg;base64,/9j/4AAQSkZJRgABAgEASABIAAD/7AARRHVja3kAAQAEAAAAHgAA/+4AIUFkb2JlAGTAAAAAAQMA
+EAMCAwYAAAGtAAACAQAAAsf/2wCEABALCwsMCxAMDBAXDw0PFxsUEBAUGx8XFxcXFx8eFxoaGhoX
+Hh4jJSclIx4vLzMzLy9AQEBAQEBAQEBAQEBAQEABEQ8PERMRFRISFRQRFBEUGhQWFhQaJhoaHBoa
+JjAjHh4eHiMwKy4nJycuKzU1MDA1NUBAP0BAQEBAQEBAQEBAQP/CABEIABQARAMBIgACEQEDEQH/
+xACMAAEAAQUAAAAAAAAAAAAAAAAABQECAwQGAQEAAAAAAAAAAAAAAAAAAAAAEAABAgQGAwEAAAAA
+AAAAAAAABicCAwQWMBIUBRUlAREXBxEAAAQCBwcEAwAAAAAAAAAAAAERAhIDITGR0hOjREFxBBQ0
+BRVRYUIzIqKDEgEAAAAAAAAAAAAAAAAAAAAw/9oADAMBAAIRAxEAAACH3tvnSTQwmUMJm2IoarAM
+vTgoAC0OdB//2gAIAQIAAQUAwv/aAAgBAwABBQDC/9oACAEBAAEFAEmk4N2gnSvzWTMbUbUbUbUb
+Uj+c5eq5VKwU28pKpQ6lp5lnqUs9SlnqUs9SlnqUiSKjh8aKq1e08nrXL9OUOUOUOUOUR/R8va8r
+/9oACAECAgY/AC//2gAIAQMCBj8AL//aAAgBAQEGPwB3cO4Pwu3S1KtDeZV07CIHLN815trcw5jm
+nucVA1GaNRmjUZo1GaNRmg4Mddn2j5eNi94oUtrHEdjZOKXxZG80UyP8jiadCKXqIC4TGJFjlOI2
+/tCOgmWtvDoJlrbw6CZa28OgmWtvDoJlrbwV3ATCLe28OSwz5lYcOhVRQzxUfN0w4dabV2JvGoT+
+Q1GUNRlDUZQ1GUNRlA48dNv1D5eSi9ooksqH/9k=" transform="matrix(1 0 0 1 58.0005 14)">
+ </image>
+ </g>
+ </mask>
+ <g display="inline" opacity="0.75" mask="url(#SVGID_4_)">
+ <path fill="#1C1B1B" d="M124,16v4H68c0,0-4,0-4,4s4,4,4,4h56v4c0,0-52,0-56,0s-8-4-8-8s4-8,8-8C72.001,16,124,16,124,16z"/>
+ </g>
+</g>
+<line display="none" fill="none" stroke="#FFFFFF" stroke-width="0.25" stroke-miterlimit="10" x1="32" y1="21" x2="32" y2="27"/>
+<line display="none" fill="none" stroke="#FFFFFF" stroke-width="0.25" stroke-miterlimit="10" x1="33.025" y1="21" x2="33.025" y2="27"/>
+<line display="none" fill="none" stroke="#FFFFFF" stroke-width="0.25" stroke-miterlimit="10" x1="34.129" y1="21" x2="34.129" y2="27"/>
+<line display="none" fill="none" stroke="#FFFFFF" stroke-width="0.25" stroke-miterlimit="10" x1="35.469" y1="21" x2="35.469" y2="27"/>
+<line display="none" fill="none" stroke="#FFFFFF" stroke-width="0.25" stroke-miterlimit="10" x1="37.046" y1="21" x2="37.046" y2="27"/>
+<line display="none" fill="none" stroke="#FFFFFF" stroke-width="0.25" stroke-miterlimit="10" x1="38.623" y1="21" x2="38.623" y2="27"/>
+<line display="none" fill="none" stroke="#FFFFFF" stroke-width="0.25" stroke-miterlimit="10" x1="40.042" y1="21" x2="40.042" y2="27"/>
+<line display="none" fill="none" stroke="#FFFFFF" stroke-width="0.25" stroke-miterlimit="10" x1="41.776" y1="21" x2="41.776" y2="27"/>
+<line display="none" fill="none" stroke="#FFFFFF" stroke-width="0.25" stroke-miterlimit="10" x1="43.747" y1="21" x2="43.747" y2="27"/>
+<line display="none" fill="none" stroke="#FFFFFF" stroke-width="0.25" stroke-miterlimit="10" x1="46.033" y1="21" x2="46.033" y2="27"/>
+<line display="none" fill="none" stroke="#FFFFFF" stroke-width="0.25" stroke-miterlimit="10" x1="48.635" y1="21" x2="48.635" y2="27"/>
+<line display="none" fill="none" stroke="#FFFFFF" stroke-width="0.25" stroke-miterlimit="10" x1="51.315" y1="21" x2="51.315" y2="27"/>
+<line display="none" fill="none" stroke="#FFFFFF" stroke-width="0.25" stroke-miterlimit="10" x1="54.311" y1="21" x2="54.311" y2="27"/>
+<line display="none" fill="none" stroke="#FFFFFF" stroke-width="0.25" stroke-miterlimit="10" x1="57.385" y1="21" x2="57.385" y2="27"/>
+</svg>
diff --git a/demos/mobile/guitartuner/images/inputMode.svg b/demos/mobile/guitartuner/images/inputMode.svg
new file mode 100644
index 00000000..f95991af
--- /dev/null
+++ b/demos/mobile/guitartuner/images/inputMode.svg
@@ -0,0 +1,161 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="690.84283"
+ height="597.90881"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.47 r22583"
+ sodipodi:docname="inputMode.svg">
+ <defs
+ id="defs4">
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective10" />
+ <inkscape:perspective
+ id="perspective3604"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ id="perspective3622"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ id="perspective3622-7"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ id="perspective3653"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ id="perspective3653-4"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ id="perspective3653-8"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.7"
+ inkscape:cx="220.15692"
+ inkscape:cy="262.65754"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1280"
+ inkscape:window-height="888"
+ inkscape:window-x="-4"
+ inkscape:window-y="-4"
+ inkscape:window-maximized="1"
+ showguides="true"
+ inkscape:guide-bbox="true" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-9.1421334,-233.17919)">
+ <path
+ sodipodi:type="arc"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path3620"
+ sodipodi:cx="64.649765"
+ sodipodi:cy="472.53461"
+ sodipodi:rx="117.1777"
+ sodipodi:ry="268.70059"
+ d="m 181.82746,472.53461 c 0,148.39924 -52.46224,268.70059 -117.177695,268.70059 -64.71545463,0 -117.177696,-120.30135 -117.177696,-268.70059 0,-148.39924 52.46224137,-268.7006 117.177696,-268.7006 64.715455,0 117.177695,120.30136 117.177695,268.7006 z"
+ transform="matrix(2.8726899,0,0,1.0798196,168.84482,21.881457)" />
+ <g
+ id="g3694"
+ transform="translate(14.702487,2.8571428)">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path2830"
+ d="m 261.68027,406.82393 36.36549,359.61431 82.97781,0 38.24049,-359.61431"
+ style="fill:none;stroke:#000000;stroke-width:14.10000038;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ transform="translate(-11.060917,113.98119)"
+ d="m 442.4468,276.6803 c 0,49.09448 -41.15572,88.89342 -91.92388,88.89342 -50.76816,0 -91.92388,-39.79894 -91.92388,-88.89342 0,-49.09449 41.15572,-88.89343 91.92388,-88.89343 50.76816,0 91.92388,39.79894 91.92388,88.89343 z"
+ sodipodi:ry="88.893425"
+ sodipodi:rx="91.923882"
+ sodipodi:cy="276.6803"
+ sodipodi:cx="350.52292"
+ id="path2826"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:17.61199951;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc" />
+ <path
+ id="path3610"
+ d="M 417.09557,336.26145 265.86811,447.10263"
+ style="fill:none;stroke:#000000;stroke-width:8.15200043;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ id="path3610-1"
+ d="M 370.02409,308.17608 244.86468,399.91085"
+ style="fill:none;stroke:#000000;stroke-width:8.15200043;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ id="path3610-4"
+ d="M 266.87874,335.24091 418.10619,446.08209"
+ style="fill:none;stroke:#000000;stroke-width:8.15200043;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ id="path3610-4-9"
+ d="M 306.03234,300.77574 436.914,396.7046"
+ style="fill:none;stroke:#000000;stroke-width:8.15200043;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ id="path3610-4-8"
+ d="m 246.61065,376.5921 132.66972,97.23942"
+ style="fill:none;stroke:#000000;stroke-width:8.15200043;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ id="path3610-4-2"
+ d="M 433.44049,380.0107 304.57747,474.46002"
+ style="fill:none;stroke:#000000;stroke-width:8.15200043;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ </g>
+ </g>
+</svg>
diff --git a/demos/mobile/guitartuner/images/note.svg b/demos/mobile/guitartuner/images/note.svg
new file mode 100644
index 00000000..c1f1771a
--- /dev/null
+++ b/demos/mobile/guitartuner/images/note.svg
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="690.84283"
+ height="597.90881"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.47 r22583"
+ sodipodi:docname="New document 1">
+ <defs
+ id="defs4">
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective10" />
+ <inkscape:perspective
+ id="perspective3604"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.49497475"
+ inkscape:cx="586.90391"
+ inkscape:cy="224.44944"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1280"
+ inkscape:window-height="888"
+ inkscape:window-x="-4"
+ inkscape:window-y="-4"
+ inkscape:window-maximized="1" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-9.1421334,-233.17919)">
+ <path
+ sodipodi:type="arc"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path3620"
+ sodipodi:cx="64.649765"
+ sodipodi:cy="472.53461"
+ sodipodi:rx="117.1777"
+ sodipodi:ry="268.70059"
+ d="m 181.82746,472.53461 c 0,148.39924 -52.46224,268.70059 -117.177695,268.70059 -64.71545463,0 -117.177696,-120.30135 -117.177696,-268.70059 0,-148.39924 52.46224137,-268.7006 117.177696,-268.7006 64.715455,0 117.177695,120.30136 117.177695,268.7006 z"
+ transform="matrix(2.8726899,0,0,1.0798196,168.84482,21.881457)" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 355.87166,686.47203 0,-381.77521"
+ id="path2816"
+ sodipodi:nodetypes="cc" />
+ <path
+ sodipodi:type="arc"
+ style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:5;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path2818"
+ sodipodi:cx="284.86301"
+ sodipodi:cy="703.85956"
+ sodipodi:rx="80.812202"
+ sodipodi:ry="83.842659"
+ d="m 365.67521,703.85956 c 0,46.30502 -36.18086,83.84266 -80.8122,83.84266 -44.63135,0 -80.81221,-37.53764 -80.81221,-83.84266 0,-46.30502 36.18086,-83.84266 80.81221,-83.84266 44.63134,0 80.8122,37.53764 80.8122,83.84266 z"
+ transform="matrix(0.86662604,0,0,0.86662604,41.962127,84.107402)" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:3.49788642;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ d="M 498.23775,478.96203 C 487.43102,436.20815 446.22124,431.4938 416.5823,423.48582 381.21648,411.5191 365.03425,382.76349 358.75673,339.52089 l -2.02761,-36.99987 c 12.76379,33.73415 40.64336,44.6109 67.22015,53.67478 46.38196,11.01541 67.31525,50.25786 74.72373,107.8334 0.48397,6.08567 0.99901,19.27869 0.75259,19.27869 -0.0715,0 -0.60616,-1.95564 -1.1881,-4.34586 l 0,0 2.6e-4,0 z"
+ id="path3618"
+ sodipodi:nodetypes="ccccccsccc" />
+ </g>
+</svg>
diff --git a/demos/mobile/guitartuner/images/noteNo.svg b/demos/mobile/guitartuner/images/noteNo.svg
new file mode 100644
index 00000000..888d2308
--- /dev/null
+++ b/demos/mobile/guitartuner/images/noteNo.svg
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="690.84283"
+ height="597.90881"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.47 r22583"
+ sodipodi:docname="noteCrossed.svg">
+ <defs
+ id="defs4">
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective10" />
+ <inkscape:perspective
+ id="perspective3604"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.49497475"
+ inkscape:cx="289.91906"
+ inkscape:cy="224.44944"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1280"
+ inkscape:window-height="888"
+ inkscape:window-x="-4"
+ inkscape:window-y="-4"
+ inkscape:window-maximized="1" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-9.1421334,-233.17919)">
+ <path
+ sodipodi:type="arc"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path3620"
+ sodipodi:cx="64.649765"
+ sodipodi:cy="472.53461"
+ sodipodi:rx="117.1777"
+ sodipodi:ry="268.70059"
+ d="m 181.82746,472.53461 c 0,148.39924 -52.46224,268.70059 -117.177695,268.70059 -64.71545463,0 -117.177696,-120.30135 -117.177696,-268.70059 0,-148.39924 52.46224137,-268.7006 117.177696,-268.7006 64.715455,0 117.177695,120.30136 117.177695,268.7006 z"
+ transform="matrix(2.8726899,0,0,1.0798196,168.84482,21.881457)" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 355.87166,686.47203 0,-381.77521"
+ id="path2816"
+ sodipodi:nodetypes="cc" />
+ <path
+ sodipodi:type="arc"
+ style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:5;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path2818"
+ sodipodi:cx="284.86301"
+ sodipodi:cy="703.85956"
+ sodipodi:rx="80.812202"
+ sodipodi:ry="83.842659"
+ d="m 365.67521,703.85956 c 0,46.30502 -36.18086,83.84266 -80.8122,83.84266 -44.63135,0 -80.81221,-37.53764 -80.81221,-83.84266 0,-46.30502 36.18086,-83.84266 80.81221,-83.84266 44.63134,0 80.8122,37.53764 80.8122,83.84266 z"
+ transform="matrix(0.86662604,0,0,0.86662604,41.962127,84.107402)" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:3.49788642;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ d="M 498.23775,478.96203 C 487.43102,436.20815 446.22124,431.4938 416.5823,423.48582 381.21648,411.5191 365.03425,382.76349 358.75673,339.52089 l -2.02761,-36.99987 c 12.76379,33.73415 40.64336,44.6109 67.22015,53.67478 46.38196,11.01541 67.31525,50.25786 74.72373,107.8334 0.48397,6.08567 0.99901,19.27869 0.75259,19.27869 -0.0715,0 -0.60616,-1.95564 -1.1881,-4.34586 l 0,0 2.6e-4,0 z"
+ id="path3618"
+ sodipodi:nodetypes="ccccccsccc" />
+ <path
+ style="fill:none;stroke:#ff0000;stroke-width:16;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 176.92972,346.31704 369.5113,373.55192"
+ id="path2817" />
+ </g>
+</svg>
diff --git a/demos/mobile/guitartuner/src/application.qml b/demos/mobile/guitartuner/src/application.qml
new file mode 100644
index 00000000..c18e64c5
--- /dev/null
+++ b/demos/mobile/guitartuner/src/application.qml
@@ -0,0 +1,328 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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$
+**
+****************************************************************************/
+
+import QtQuick 1.0
+import "mycomponents"
+
+/* The base canvas for all QML drawing. */
+Rectangle {
+ id: application
+
+ property int targetNoteIndex: 0
+ property alias frequency: noteChooser.currentFrequency
+ //Data provided to C++.
+ property bool isInput: true
+ property bool isMuted: false
+ property bool isAuto: true
+ property alias maxVoiceDifference: voiceDifferenceMeter.maxValue
+ property real volume: 0.5
+ property real sensitivity: 0.5
+
+ //Signals to C++.
+ signal volumeChanged(real volume)
+ signal microphoneSensitivityChanged(real sensitivity)
+ signal targetFrequencyChanged(real frequency)
+ signal modeChanged(bool isInput)
+ signal muteStateChanged(bool isMuted)
+
+ //Slots for signals coming from C++.
+ function voiceDifferenceChanged(difference) {
+ if (isAuto) timer.running = true;
+ voiceDifferenceMeter.valueChanged(difference);
+ noteImage.glowing = false
+ }
+ function correctFrequencyObtained() {
+ noteImage.glowing = true
+ }
+ function lowVoice() {
+ noteImage.glowing = false
+ }
+
+ //Private function for changing the target frequency automatically.
+ function calculateTargetFrequency(difference) {
+ var tempDifference = Math.abs(difference);
+ var tempIndex = targetNoteIndex
+ while (!(difference < 0 && tempIndex == 0) &&
+ tempDifference >= notes.get(tempIndex-(difference<0)).interval/2) {
+ tempDifference -= notes.get(tempIndex-(difference<0)).interval;
+ tempIndex += difference/Math.abs(difference);
+ }
+ if (tempIndex != targetNoteIndex) {
+ targetNoteIndex = tempIndex
+ noteChooser.currentFrequency = notes.get(targetNoteIndex).frequency;
+ targetFrequencyChanged(frequency);
+ }
+ }
+
+ width: 360; height: 640
+ color: "black"
+
+ //Provides data for functions.
+ NotesModel {id: notes}
+
+ /* A timer for changing the target frequency automatically.
+ * This is needed for avoiding recursion. */
+ Timer {
+ id: timer
+
+ interval: 1
+ onTriggered: calculateTargetFrequency(voiceDifferenceMeter.value)
+ }
+
+ //A meter for showing the difference between current and target frequency.
+ Meter {
+ id: voiceDifferenceMeter
+
+ maxValue: 12
+ minValue: -maxValue
+ height: imageSize.height/background.sourceSize.height*parent.height
+ width: imageSize.width/background.sourceSize.width*parent.width
+ anchors {
+ topMargin: 100/background.sourceSize.height*parent.height
+ horizontalCenter: parent.horizontalCenter
+ top: parent.top
+ }
+ }
+
+ Image {
+ id: background
+
+ anchors.fill: parent
+ smooth: true
+ source: "./mycomponents/images/guitartuner_skin.png"
+ }
+
+ //A button for quitting the application.
+ Image {
+ id: quitButton
+
+ width: sourceSize.width/background.sourceSize.width*parent.width
+ height: sourceSize.height/background.sourceSize.height*parent.height
+ source: "./mycomponents/images/power.png"
+ smooth: true
+ KeyNavigation.up: volumeAdjuster
+ KeyNavigation.down: modeButton
+ Keys.onEnterPressed: Qt.quit()
+ anchors{
+ leftMargin: 297/background.sourceSize.width*parent.width
+ left: parent.left;
+ topMargin: 17/background.sourceSize.height*parent.height
+ top: parent.top
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: Qt.quit()
+ }
+ }
+
+ //An image for showing the target note.
+ Image {
+ id: noteImage
+
+ property bool glowing: false
+
+ width: sourceSize.width/background.sourceSize.width*parent.width
+ height: sourceSize.height/background.sourceSize.height*parent.height
+ source: glowing ? notes.get(targetNoteIndex).glowSource : notes.get(targetNoteIndex).bigSource
+
+ anchors {
+ topMargin: 273/background.sourceSize.height*parent.height
+ top: parent.top
+ horizontalCenter: parent.horizontalCenter
+ }
+ }
+
+ //A button for choosing the input/output mode.
+ Image {
+ id: modeButton
+
+ function buttonPressed() {
+ isInput = !isInput
+ modeChanged(isInput)
+ if (isInput) {
+ soundIcons.source = "./mycomponents/images/sensitivity.png"
+ source = "./mycomponents/images/voicemode_off.png"
+ volumeAdjuster.setValue(sensitivity)
+ }
+ else {
+ //Change off from "auto" mode
+ if (isAuto) {
+ noteChooser.pushButton(targetNoteIndex)
+ }
+ if (isMuted) {
+ soundIcons.source = "./mycomponents/images/volume_off.png";
+ }
+ else
+ soundIcons.source = "./mycomponents/images/volume.png"
+ source = "./mycomponents/images/voicemode_on.png"
+ volumeAdjuster.setValue(volume)
+ }
+ }
+
+ width: sourceSize.width/background.sourceSize.width*parent.width
+ height: sourceSize.height/background.sourceSize.height*parent.height
+ smooth: true
+ source: "./mycomponents/images/voicemode_off.png"
+ KeyNavigation.up: quitButton
+ KeyNavigation.down: noteChooser
+ Keys.onEnterPressed: buttonPressed()
+ anchors {
+ leftMargin: 16/background.sourceSize.width*parent.width
+ left: parent.left
+ topMargin: 353/background.sourceSize.height*parent.height
+ top: parent.top
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onPressed: {
+ parent.focus = true
+ parent.scale = 0.95
+ }
+ onReleased: {
+ parent.scale = 1/0.95
+ }
+ onClicked: parent.buttonPressed()
+ }
+ }
+
+ //Buttons for choosing the target note.
+ NoteButtonView {
+ id: noteChooser
+
+ width: parent.width*0.95; height: width/model.count
+ onNoteSelected: {
+ if (note == "Auto") {
+ if (!isAuto) {
+ isAuto = true
+ }
+ if (!isInput) {
+ modeButton.buttonPressed()
+ }
+ }
+ else {
+ timer.running = false;
+ isAuto = false
+ targetNoteIndex = index
+ targetFrequencyChanged(frequency)
+ }
+ focus = true
+ }
+ KeyNavigation.up: modeButton
+ KeyNavigation.down: soundIcons
+ anchors {
+ horizontalCenter: parent.horizontalCenter
+ topMargin: 454/background.sourceSize.height*parent.height
+ top: parent.top
+ }
+ }
+
+ //An element for showing the mode and changing the mute state.
+ Image {
+ id: soundIcons
+
+ function stateChanged() {
+ isMuted = !isMuted
+ muteStateChanged(isMuted)
+ if (isMuted) {
+ source = "qrc:/src/mycomponents/images/volume_off.png"
+ }
+ else {
+ source = "qrc:/src/mycomponents/images/volume.png"
+ }
+ }
+
+ width: sourceSize.width/background.sourceSize.width*parent.width
+ height: sourceSize.height/background.sourceSize.height*parent.height
+ smooth: true
+ source: "./mycomponents/images/sensitivity.png"
+ Keys.onEnterPressed: stateChanged()
+ KeyNavigation.up: noteChooser
+ KeyNavigation.down: quitButton
+ KeyNavigation.left: volumeAdjuster
+ KeyNavigation.right: volumeAdjuster
+ anchors {
+ leftMargin: 42/background.sourceSize.width*parent.width
+ left: parent.left
+ topMargin: 565/background.sourceSize.height*parent.height
+ top: parent.top
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ if (!isInput) {
+ parent.stateChanged()
+ }
+ parent.focus = true
+ }
+ }
+ }
+
+ //An element for adjusting volume.
+ Adjuster {
+ id: volumeAdjuster
+
+ max: 1
+ value: 0.5
+ width: 222/background.sourceSize.width*parent.width
+ height: parent.height*0.1
+ onFocusChangedByClick: focus = true
+ onArrowPressedWhenValueOverLimits: soundIcons.focus = true
+ KeyNavigation.up: modeButton
+ KeyNavigation.down: quitButton
+ anchors {
+ leftMargin: 98/background.sourceSize.width*parent.width
+ left: parent.left
+ verticalCenter: soundIcons.verticalCenter
+ }
+ onValueChanged: {
+ if (isInput) {
+ sensitivity = value;
+ microphoneSensitivityChanged(1-sensitivity)
+ }
+ else {
+ volume = value
+ volumeChanged(volume)
+ }
+ }
+ }
+}
diff --git a/demos/mobile/guitartuner/src/constants.h b/demos/mobile/guitartuner/src/constants.h
new file mode 100644
index 00000000..ab53cbea
--- /dev/null
+++ b/demos/mobile/guitartuner/src/constants.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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$
+**
+****************************************************************************/
+
+#ifndef CONSTANTS_H
+#define CONSTANTS_H
+
+#define M_MAX_AMPLITUDE_8BIT_SIGNED 127
+#define M_MAX_AMPLITUDE_8BIT_UNSIGNED 255
+#define M_MAX_AMPLITUDE_16BIT_SIGNED 32767
+#define M_MAX_AMPLITUDE_16BIT_UNSIGNED 65535
+
+#define M_TWELTH_ROOT_OF_2 1.05946309435930000000
+
+// M_SAMPLE_COUNT_MULTIPLIER is 2/(M_TWELTH_ROOT_OF_2 - 1)
+#define M_SAMPLE_COUNT_MULTIPLIER 33.63430749021150000000
+
+#endif // CONSTANTS_H
diff --git a/demos/mobile/guitartuner/src/fastfouriertransformer.cpp b/demos/mobile/guitartuner/src/fastfouriertransformer.cpp
new file mode 100644
index 00000000..275d36b2
--- /dev/null
+++ b/demos/mobile/guitartuner/src/fastfouriertransformer.cpp
@@ -0,0 +1,184 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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 "fastfouriertransformer.h"
+#include "math.h"
+
+#define STIN inline
+#define __STATIC
+
+#include "fftpack.c"
+
+// called by __ogg_fdrffti
+__STATIC void drfti1(int n, float *wa, int *ifac);
+void __ogg_fdrffti(int n, float *wsave, int *ifac);
+void __ogg_fdcosqi(int n, float *wsave, int *ifac);
+// called by drftf1
+STIN void dradf2(int ido,int l1,float *cc,float *ch,float *wa1);
+// called by drftf1
+STIN void dradf4(int ido,int l1,float *cc,float *ch,float *wa1,
+ float *wa2,float *wa3);
+// called by drftf1
+STIN void dradfg(int ido,int ip,int l1,int idl1,float *cc,float *c1,
+ float *c2,float *ch,float *ch2,float *wa);
+// called by drftf1
+STIN void drftf1(int n,float *c,float *ch,float *wa,int *ifac);
+void __ogg_fdrfftf(int n,float *r,float *wsave,int *ifac);
+STIN void dcsqf1(int n,float *x,float *w,float *xh,int *ifac);
+void __ogg_fdcosqf(int n,float *x,float *wsave,int *ifac);
+STIN void dradb2(int ido,int l1,float *cc,float *ch,float *wa1);
+STIN void dradb3(int ido,int l1,float *cc,float *ch,float *wa1,
+ float *wa2);
+STIN void dradb4(int ido,int l1,float *cc,float *ch,float *wa1,
+ float *wa2,float *wa3);
+STIN void dradbg(int ido,int ip,int l1,int idl1,float *cc,float *c1,
+ float *c2,float *ch,float *ch2,float *wa);
+STIN void drftb1(int n, float *c, float *ch, float *wa, int *ifac);
+void __ogg_fdrfftb(int n, float *r, float *wsave, int *ifac);
+STIN void dcsqb1(int n,float *x,float *w,float *xh,int *ifac);
+void __ogg_fdcosqb(int n,float *x,float *wsave,int *ifac);
+
+FastFourierTransformer::FastFourierTransformer(QObject *parent) :
+ QObject(parent),
+ m_waveFloat(0),
+ m_workingArray(0),
+ m_ifac(0),
+ m_last_n(-1)
+{
+}
+
+FastFourierTransformer::~FastFourierTransformer()
+{
+ if (m_waveFloat != 0) {
+ delete [] m_waveFloat;
+ }
+ if (m_workingArray != 0) {
+ delete [] m_workingArray;
+ }
+ if (m_ifac != 0) {
+ delete [] m_ifac;
+ }
+}
+
+/**
+ * Prepares the arrays to be of length n.
+ */
+void FastFourierTransformer::reserve(int n)
+{
+ Q_ASSERT(n>0);
+ if (m_waveFloat != 0) {
+ delete [] m_waveFloat;
+ }
+ if (m_workingArray != 0) {
+ delete [] m_workingArray;
+ }
+ if (m_ifac != 0) {
+ delete [] m_ifac;
+ }
+ m_workingArray = new float[2*n+15];
+ m_waveFloat = new float[n];
+ m_ifac = new int[n];
+ __ogg_fdrffti(n, m_workingArray, m_ifac);
+ m_last_n = n;
+}
+
+/**
+ * Calculates the Fast Fourier Transformation (FFT).
+ */
+void FastFourierTransformer::calculateFFT(QList<qint16> wave)
+{
+ const int n = wave.size();
+ if (m_last_n != n) {
+ reserve(n);
+ }
+ for (int i = 0; i < n; i++) {
+ m_waveFloat[i] = (float) wave.at(i);
+ }
+
+ __ogg_fdrfftf(n, m_waveFloat, m_workingArray, m_ifac);
+
+}
+
+/**
+ * Returns the index which corresponds to the maximum density
+ * of the FFT.
+ */
+int FastFourierTransformer::getMaximumDensityIndex()
+{
+ const int halfN = m_last_n / 2;
+ float maxDensity = 0;
+ int maxDensityIndex = 0;
+ float densitySquared = 0.f;
+ for (int k = 1; k < halfN; k++) {
+ // Here, we calculate the frequency k/N.
+ // k=1, the wave oscillation time is N, and the frequency
+ // is 1/sample.
+ // k=2, the wave oscillation time is N/2, and the frequency
+ // is 2/sample.
+ // k=3, the wave oscillation time is N/3, and the frequency
+ // is 3/sample.
+ // Note, that the documentation is for Fortran, so indexes in the
+ // documentation does not match.
+ // The sine and cosine coefficients are obtained thus as follows:
+ const float cosCoefficient = qAbs(m_waveFloat[2*k-1]);
+ const float sinCoefficient = qAbs(m_waveFloat[2*k]);
+
+ densitySquared = sinCoefficient*sinCoefficient + cosCoefficient*cosCoefficient;
+ if (densitySquared > maxDensity) {
+ maxDensity = densitySquared;
+ maxDensityIndex = k;
+ }
+ }
+
+ if (m_cutOffForDensitySquared < maxDensity) {
+ return maxDensityIndex;
+ }
+ else {
+ return -1;
+ }
+}
+
+/**
+ * Sets the cutoff density.
+ */
+void FastFourierTransformer::setCutOffForDensity(float cutoff)
+{
+ m_cutOffForDensitySquared = cutoff*cutoff;
+}
diff --git a/demos/mobile/guitartuner/src/fastfouriertransformer.h b/demos/mobile/guitartuner/src/fastfouriertransformer.h
new file mode 100644
index 00000000..b8064f7a
--- /dev/null
+++ b/demos/mobile/guitartuner/src/fastfouriertransformer.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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$
+**
+****************************************************************************/
+
+#ifndef FASTFOURIERTRANSFORM_H
+#define FASTFOURIERTRANSFORM_H
+
+#include <QObject>
+#include <QList>
+
+class FastFourierTransformer : public QObject
+{
+ Q_OBJECT
+
+public:
+ FastFourierTransformer(QObject *parent = 0);
+ ~FastFourierTransformer();
+ void reserve(int n);
+ void calculateFFT(QList<qint16> wave);
+ int getMaximumDensityIndex();
+ void setCutOffForDensity(float cutoff);
+
+private:
+ float *m_waveFloat;
+ float *m_workingArray;
+ int *m_ifac;
+ int m_last_n;
+ float m_cutOffForDensitySquared;
+};
+
+#endif // FASTFOURIERTRANSFORM_H
diff --git a/demos/mobile/guitartuner/src/fftpack.c b/demos/mobile/guitartuner/src/fftpack.c
new file mode 100644
index 00000000..43109408
--- /dev/null
+++ b/demos/mobile/guitartuner/src/fftpack.c
@@ -0,0 +1,1406 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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$
+**
+****************************************************************************/
+
+/********************************************************************
+
+ The routines in this file are from http://www.netlib.org/fftpack/.
+ According to the comments in the original file (which are provided below)
+ and according to the wikipedia article about the FFTPACK[1],
+ they are released as public domain.
+
+ For information about the author of the original, Fortran routines,
+ and the author of the C translation these routines,
+ see the comments below.
+
+ [1] http://en.wikipedia.org/wiki/FFTPACK, referenced 2010-12-21.
+
+ ********************************************************************/
+
+/********************************************************************
+
+ file: fft.c
+ function: Fast discrete Fourier and cosine transforms and inverses
+ author: Monty <xiphmont@mit.edu>
+ modifications by: Monty
+ last modification date: Jul 1 1996
+
+ ********************************************************************/
+
+/* These Fourier routines were originally based on the Fourier
+ routines of the same names from the NETLIB bihar and fftpack
+ fortran libraries developed by Paul N. Swarztrauber at the National
+ Center for Atmospheric Research in Boulder, CO USA. They have been
+ reimplemented in C and optimized in a few ways for OggSquish. */
+
+/* As the original fortran libraries are public domain, the C Fourier
+ routines in this file are hereby released to the public domain as
+ well. The C routines here produce output exactly equivalent to the
+ original fortran routines. Of particular interest are the facts
+ that (like the original fortran), these routines can work on
+ arbitrary length vectors that need not be powers of two in
+ length. */
+
+#include <math.h>
+
+__STATIC void drfti1(int n, float *wa, int *ifac){
+ static int ntryh[4] = { 4,2,3,5 };
+ static float tpi = 6.28318530717958647692528676655900577;
+ float arg,argh,argld,fi;
+ int ntry=0,i,j=-1;
+ int k1, l1, l2, ib;
+ int ld, ii, ip, is, nq, nr;
+ int ido, ipm, nfm1;
+ int nl=n;
+ int nf=0;
+
+ L101:
+ j++;
+ if (j < 4)
+ ntry=ntryh[j];
+ else
+ ntry+=2;
+
+ L104:
+ nq=nl/ntry;
+ nr=nl-ntry*nq;
+ if (nr!=0) goto L101;
+
+ nf++;
+ ifac[nf+1]=ntry;
+ nl=nq;
+ if (ntry!=2) goto L107;
+ if (nf==1) goto L107;
+
+ for (i=1;i<nf;i++){
+ ib=nf-i+1;
+ ifac[ib+1]=ifac[ib];
+ }
+ ifac[2] = 2;
+
+ L107:
+ if (nl!=1) goto L104;
+ ifac[0]=n;
+ ifac[1]=nf;
+ argh=tpi/n;
+ is=0;
+ nfm1=nf-1;
+ l1=1;
+
+ if (nfm1==0) return;
+
+ for (k1=0;k1<nfm1;k1++){
+ ip=ifac[k1+2];
+ ld=0;
+ l2=l1*ip;
+ ido=n/l2;
+ ipm=ip-1;
+
+ for (j=0;j<ipm;j++){
+ ld+=l1;
+ i=is;
+ argld=(float)ld*argh;
+ fi=0.;
+ for (ii=2;ii<ido;ii+=2){
+ fi+=1.;
+ arg=fi*argld;
+ wa[i++]=cos(arg);
+ wa[i++]=sin(arg);
+ }
+ is+=ido;
+ }
+ l1=l2;
+ }
+}
+
+void __ogg_fdrffti(int n, float *wsave, int *ifac){
+
+ if (n == 1) return;
+ drfti1(n, wsave+n, ifac);
+}
+
+void __ogg_fdcosqi(int n, float *wsave, int *ifac){
+ static float pih = 1.57079632679489661923132169163975;
+ static int k;
+ static float fk, dt;
+
+ dt=pih/n;
+ fk=0.;
+ for (k=0;k<n;k++){
+ fk+=1.;
+ wsave[k] = cos(fk*dt);
+ }
+
+ __ogg_fdrffti(n, wsave+n,ifac);
+}
+
+STIN void dradf2(int ido,int l1,float *cc,float *ch,float *wa1){
+ int i,k;
+ float ti2,tr2;
+ int t0,t1,t2,t3,t4,t5,t6;
+
+ t1=0;
+ t0=(t2=l1*ido);
+ t3=ido<<1;
+ for (k=0;k<l1;k++){
+ ch[t1<<1]=cc[t1]+cc[t2];
+ ch[(t1<<1)+t3-1]=cc[t1]-cc[t2];
+ t1+=ido;
+ t2+=ido;
+ }
+
+ if (ido<2) return;
+ if (ido==2) goto L105;
+
+ t1=0;
+ t2=t0;
+ for (k=0;k<l1;k++){
+ t3=t2;
+ t4=(t1<<1)+(ido<<1);
+ t5=t1;
+ t6=t1+t1;
+ for (i=2;i<ido;i+=2){
+ t3+=2;
+ t4-=2;
+ t5+=2;
+ t6+=2;
+ tr2=wa1[i-2]*cc[t3-1]+wa1[i-1]*cc[t3];
+ ti2=wa1[i-2]*cc[t3]-wa1[i-1]*cc[t3-1];
+ ch[t6]=cc[t5]+ti2;
+ ch[t4]=ti2-cc[t5];
+ ch[t6-1]=cc[t5-1]+tr2;
+ ch[t4-1]=cc[t5-1]-tr2;
+ }
+ t1+=ido;
+ t2+=ido;
+ }
+
+ if (ido%2==1) return;
+
+ L105:
+ t3=(t2=(t1=ido)-1);
+ t2+=t0;
+ for (k=0;k<l1;k++){
+ ch[t1]=-cc[t2];
+ ch[t1-1]=cc[t3];
+ t1+=ido<<1;
+ t2+=ido;
+ t3+=ido;
+ }
+}
+
+STIN void dradf4(int ido,int l1,float *cc,float *ch,float *wa1,
+ float *wa2,float *wa3){
+ static float hsqt2 = .70710678118654752440084436210485;
+ int i,k,t0,t1,t2,t3,t4,t5,t6;
+ float ci2,ci3,ci4,cr2,cr3,cr4,ti1,ti2,ti3,ti4,tr1,tr2,tr3,tr4;
+ t0=l1*ido;
+
+ t1=t0;
+ t4=t1<<1;
+ t2=t1+(t1<<1);
+ t3=0;
+
+ for (k=0;k<l1;k++){
+ tr1=cc[t1]+cc[t2];
+ tr2=cc[t3]+cc[t4];
+ ch[t5=t3<<2]=tr1+tr2;
+ ch[(ido<<2)+t5-1]=tr2-tr1;
+ ch[(t5+=(ido<<1))-1]=cc[t3]-cc[t4];
+ ch[t5]=cc[t2]-cc[t1];
+
+ t1+=ido;
+ t2+=ido;
+ t3+=ido;
+ t4+=ido;
+ }
+
+ if (ido<2) return;
+ if (ido==2) goto L105;
+
+ t1=0;
+ for (k=0;k<l1;k++){
+ t2=t1;
+ t4=t1<<2;
+ t5=(t6=ido<<1)+t4;
+ for (i=2;i<ido;i+=2){
+ t3=(t2+=2);
+ t4+=2;
+ t5-=2;
+
+ t3+=t0;
+ cr2=wa1[i-2]*cc[t3-1]+wa1[i-1]*cc[t3];
+ ci2=wa1[i-2]*cc[t3]-wa1[i-1]*cc[t3-1];
+ t3+=t0;
+ cr3=wa2[i-2]*cc[t3-1]+wa2[i-1]*cc[t3];
+ ci3=wa2[i-2]*cc[t3]-wa2[i-1]*cc[t3-1];
+ t3+=t0;
+ cr4=wa3[i-2]*cc[t3-1]+wa3[i-1]*cc[t3];
+ ci4=wa3[i-2]*cc[t3]-wa3[i-1]*cc[t3-1];
+
+ tr1=cr2+cr4;
+ tr4=cr4-cr2;
+ ti1=ci2+ci4;
+ ti4=ci2-ci4;
+ ti2=cc[t2]+ci3;
+ ti3=cc[t2]-ci3;
+ tr2=cc[t2-1]+cr3;
+ tr3=cc[t2-1]-cr3;
+
+
+ ch[t4-1]=tr1+tr2;
+ ch[t4]=ti1+ti2;
+
+ ch[t5-1]=tr3-ti4;
+ ch[t5]=tr4-ti3;
+
+ ch[t4+t6-1]=ti4+tr3;
+ ch[t4+t6]=tr4+ti3;
+
+ ch[t5+t6-1]=tr2-tr1;
+ ch[t5+t6]=ti1-ti2;
+ }
+ t1+=ido;
+ }
+ if (ido%2==1) return;
+
+ L105:
+
+ t2=(t1=t0+ido-1)+(t0<<1);
+ t3=ido<<2;
+ t4=ido;
+ t5=ido<<1;
+ t6=ido;
+
+ for (k=0;k<l1;k++){
+ ti1=-hsqt2*(cc[t1]+cc[t2]);
+ tr1=hsqt2*(cc[t1]-cc[t2]);
+ ch[t4-1]=tr1+cc[t6-1];
+ ch[t4+t5-1]=cc[t6-1]-tr1;
+ ch[t4]=ti1-cc[t1+t0];
+ ch[t4+t5]=ti1+cc[t1+t0];
+ t1+=ido;
+ t2+=ido;
+ t4+=t3;
+ t6+=ido;
+ }
+}
+
+STIN void dradfg(int ido,int ip,int l1,int idl1,float *cc,float *c1,
+ float *c2,float *ch,float *ch2,float *wa){
+
+ static float tpi=6.28318530717958647692528676655900577;
+ int idij,ipph,i,j,k,l,ic,ik,is;
+ int t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10;
+ float dc2,ai1,ai2,ar1,ar2,ds2;
+ int nbd;
+ float dcp,arg,dsp,ar1h,ar2h;
+ int idp2,ipp2;
+
+ arg=tpi/(float)ip;
+ dcp=cos(arg);
+ dsp=sin(arg);
+ ipph=(ip+1)>>1;
+ ipp2=ip;
+ idp2=ido;
+ nbd=(ido-1)>>1;
+ t0=l1*ido;
+ t10=ip*ido;
+
+ if (ido==1) goto L119;
+ for (ik=0;ik<idl1;ik++)ch2[ik]=c2[ik];
+
+ t1=0;
+ for (j=1;j<ip;j++){
+ t1+=t0;
+ t2=t1;
+ for (k=0;k<l1;k++){
+ ch[t2]=c1[t2];
+ t2+=ido;
+ }
+ }
+
+ is=-ido;
+ t1=0;
+ if (nbd>l1){
+ for (j=1;j<ip;j++){
+ t1+=t0;
+ is+=ido;
+ t2= -ido+t1;
+ for (k=0;k<l1;k++){
+ idij=is-1;
+ t2+=ido;
+ t3=t2;
+ for (i=2;i<ido;i+=2){
+ idij+=2;
+ t3+=2;
+ ch[t3-1]=wa[idij-1]*c1[t3-1]+wa[idij]*c1[t3];
+ ch[t3]=wa[idij-1]*c1[t3]-wa[idij]*c1[t3-1];
+ }
+ }
+ }
+ }else{
+
+ for (j=1;j<ip;j++){
+ is+=ido;
+ idij=is-1;
+ t1+=t0;
+ t2=t1;
+ for (i=2;i<ido;i+=2){
+ idij+=2;
+ t2+=2;
+ t3=t2;
+ for (k=0;k<l1;k++){
+ ch[t3-1]=wa[idij-1]*c1[t3-1]+wa[idij]*c1[t3];
+ ch[t3]=wa[idij-1]*c1[t3]-wa[idij]*c1[t3-1];
+ t3+=ido;
+ }
+ }
+ }
+ }
+
+ t1=0;
+ t2=ipp2*t0;
+ if (nbd<l1){
+ for (j=1;j<ipph;j++){
+ t1+=t0;
+ t2-=t0;
+ t3=t1;
+ t4=t2;
+ for (i=2;i<ido;i+=2){
+ t3+=2;
+ t4+=2;
+ t5=t3-ido;
+ t6=t4-ido;
+ for (k=0;k<l1;k++){
+ t5+=ido;
+ t6+=ido;
+ c1[t5-1]=ch[t5-1]+ch[t6-1];
+ c1[t6-1]=ch[t5]-ch[t6];
+ c1[t5]=ch[t5]+ch[t6];
+ c1[t6]=ch[t6-1]-ch[t5-1];
+ }
+ }
+ }
+ }else{
+ for (j=1;j<ipph;j++){
+ t1+=t0;
+ t2-=t0;
+ t3=t1;
+ t4=t2;
+ for (k=0;k<l1;k++){
+ t5=t3;
+ t6=t4;
+ for (i=2;i<ido;i+=2){
+ t5+=2;
+ t6+=2;
+ c1[t5-1]=ch[t5-1]+ch[t6-1];
+ c1[t6-1]=ch[t5]-ch[t6];
+ c1[t5]=ch[t5]+ch[t6];
+ c1[t6]=ch[t6-1]-ch[t5-1];
+ }
+ t3+=ido;
+ t4+=ido;
+ }
+ }
+ }
+
+L119:
+ for (ik=0;ik<idl1;ik++)c2[ik]=ch2[ik];
+
+ t1=0;
+ t2=ipp2*idl1;
+ for (j=1;j<ipph;j++){
+ t1+=t0;
+ t2-=t0;
+ t3=t1-ido;
+ t4=t2-ido;
+ for (k=0;k<l1;k++){
+ t3+=ido;
+ t4+=ido;
+ c1[t3]=ch[t3]+ch[t4];
+ c1[t4]=ch[t4]-ch[t3];
+ }
+ }
+
+ ar1=1.;
+ ai1=0.;
+ t1=0;
+ t2=ipp2*idl1;
+ t3=(ip-1)*idl1;
+ for (l=1;l<ipph;l++){
+ t1+=idl1;
+ t2-=idl1;
+ ar1h=dcp*ar1-dsp*ai1;
+ ai1=dcp*ai1+dsp*ar1;
+ ar1=ar1h;
+ t4=t1;
+ t5=t2;
+ t6=t3;
+ t7=idl1;
+
+ for (ik=0;ik<idl1;ik++){
+ ch2[t4++]=c2[ik]+ar1*c2[t7++];
+ ch2[t5++]=ai1*c2[t6++];
+ }
+
+ dc2=ar1;
+ ds2=ai1;
+ ar2=ar1;
+ ai2=ai1;
+
+ t4=idl1;
+ t5=(ipp2-1)*idl1;
+ for (j=2;j<ipph;j++){
+ t4+=idl1;
+ t5-=idl1;
+
+ ar2h=dc2*ar2-ds2*ai2;
+ ai2=dc2*ai2+ds2*ar2;
+ ar2=ar2h;
+
+ t6=t1;
+ t7=t2;
+ t8=t4;
+ t9=t5;
+ for (ik=0;ik<idl1;ik++){
+ ch2[t6++]+=ar2*c2[t8++];
+ ch2[t7++]+=ai2*c2[t9++];
+ }
+ }
+ }
+
+ t1=0;
+ for (j=1;j<ipph;j++){
+ t1+=idl1;
+ t2=t1;
+ for (ik=0;ik<idl1;ik++)ch2[ik]+=c2[t2++];
+ }
+
+ if (ido<l1) goto L132;
+
+ t1=0;
+ t2=0;
+ for (k=0;k<l1;k++){
+ t3=t1;
+ t4=t2;
+ for (i=0;i<ido;i++)cc[t4++]=ch[t3++];
+ t1+=ido;
+ t2+=t10;
+ }
+
+ goto L135;
+
+ L132:
+ for (i=0;i<ido;i++){
+ t1=i;
+ t2=i;
+ for (k=0;k<l1;k++){
+ cc[t2]=ch[t1];
+ t1+=ido;
+ t2+=t10;
+ }
+ }
+
+ L135:
+ t1=0;
+ t2=ido<<1;
+ t3=0;
+ t4=ipp2*t0;
+ for (j=1;j<ipph;j++){
+
+ t1+=t2;
+ t3+=t0;
+ t4-=t0;
+
+ t5=t1;
+ t6=t3;
+ t7=t4;
+
+ for (k=0;k<l1;k++){
+ cc[t5-1]=ch[t6];
+ cc[t5]=ch[t7];
+ t5+=t10;
+ t6+=ido;
+ t7+=ido;
+ }
+ }
+
+ if (ido==1) return;
+ if (nbd<l1) goto L141;
+
+ t1=-ido;
+ t3=0;
+ t4=0;
+ t5=ipp2*t0;
+ for (j=1;j<ipph;j++){
+ t1+=t2;
+ t3+=t2;
+ t4+=t0;
+ t5-=t0;
+ t6=t1;
+ t7=t3;
+ t8=t4;
+ t9=t5;
+ for (k=0;k<l1;k++){
+ for (i=2;i<ido;i+=2){
+ ic=idp2-i;
+ cc[i+t7-1]=ch[i+t8-1]+ch[i+t9-1];
+ cc[ic+t6-1]=ch[i+t8-1]-ch[i+t9-1];
+ cc[i+t7]=ch[i+t8]+ch[i+t9];
+ cc[ic+t6]=ch[i+t9]-ch[i+t8];
+ }
+ t6+=t10;
+ t7+=t10;
+ t8+=ido;
+ t9+=ido;
+ }
+ }
+ return;
+
+ L141:
+
+ t1=-ido;
+ t3=0;
+ t4=0;
+ t5=ipp2*t0;
+ for (j=1;j<ipph;j++){
+ t1+=t2;
+ t3+=t2;
+ t4+=t0;
+ t5-=t0;
+ for (i=2;i<ido;i+=2){
+ t6=idp2+t1-i;
+ t7=i+t3;
+ t8=i+t4;
+ t9=i+t5;
+ for (k=0;k<l1;k++){
+ cc[t7-1]=ch[t8-1]+ch[t9-1];
+ cc[t6-1]=ch[t8-1]-ch[t9-1];
+ cc[t7]=ch[t8]+ch[t9];
+ cc[t6]=ch[t9]-ch[t8];
+ t6+=t10;
+ t7+=t10;
+ t8+=ido;
+ t9+=ido;
+ }
+ }
+ }
+}
+
+STIN void drftf1(int n,float *c,float *ch,float *wa,int *ifac){
+ int i,k1,l1,l2;
+ int na,kh,nf;
+ int ip,iw,ido,idl1,ix2,ix3;
+
+ nf=ifac[1];
+ na=1;
+ l2=n;
+ iw=n;
+
+ for (k1=0;k1<nf;k1++){
+ kh=nf-k1;
+ ip=ifac[kh+1];
+ l1=l2/ip;
+ ido=n/l2;
+ idl1=ido*l1;
+ iw-=(ip-1)*ido;
+ na=1-na;
+
+ if (ip!=4) goto L102;
+
+ ix2=iw+ido;
+ ix3=ix2+ido;
+ if (na!=0)
+ dradf4(ido,l1,ch,c,wa+iw-1,wa+ix2-1,wa+ix3-1);
+ else
+ dradf4(ido,l1,c,ch,wa+iw-1,wa+ix2-1,wa+ix3-1);
+ goto L110;
+
+ L102:
+ if (ip!=2) goto L104;
+ if (na!=0) goto L103;
+
+ dradf2(ido,l1,c,ch,wa+iw-1);
+ goto L110;
+
+ L103:
+ dradf2(ido,l1,ch,c,wa+iw-1);
+ goto L110;
+
+ L104:
+ if (ido==1)na=1-na;
+ if (na!=0) goto L109;
+
+ dradfg(ido,ip,l1,idl1,c,c,c,ch,ch,wa+iw-1);
+ na=1;
+ goto L110;
+
+ L109:
+ dradfg(ido,ip,l1,idl1,ch,ch,ch,c,c,wa+iw-1);
+ na=0;
+
+ L110:
+ l2=l1;
+ }
+
+ if (na==1) return;
+
+ for (i=0;i<n;i++)c[i]=ch[i];
+}
+
+void __ogg_fdrfftf(int n,float *r,float *wsave,int *ifac){
+ if (n==1) return;
+ drftf1(n,r,wsave,wsave+n,ifac);
+}
+
+STIN void dcsqf1(int n,float *x,float *w,float *xh,int *ifac){
+ int modn,i,k,kc;
+ int np2,ns2;
+ float xim1;
+
+ ns2=(n+1)>>1;
+ np2=n;
+
+ kc=np2;
+ for (k=1;k<ns2;k++){
+ kc--;
+ xh[k]=x[k]+x[kc];
+ xh[kc]=x[k]-x[kc];
+ }
+
+ modn=n%2;
+ if (modn==0)xh[ns2]=x[ns2]+x[ns2];
+
+ for (k=1;k<ns2;k++){
+ kc=np2-k;
+ x[k]=w[k-1]*xh[kc]+w[kc-1]*xh[k];
+ x[kc]=w[k-1]*xh[k]-w[kc-1]*xh[kc];
+ }
+
+ if (modn==0)x[ns2]=w[ns2-1]*xh[ns2];
+
+ __ogg_fdrfftf(n,x,xh,ifac);
+
+ for (i=2;i<n;i+=2){
+ xim1=x[i-1]-x[i];
+ x[i]=x[i-1]+x[i];
+ x[i-1]=xim1;
+ }
+}
+
+void __ogg_fdcosqf(int n,float *x,float *wsave,int *ifac){
+ static float sqrt2=1.4142135623730950488016887242097;
+ float tsqx;
+
+ switch (n){
+ case 0:case 1:
+ return;
+ case 2:
+ tsqx=sqrt2*x[1];
+ x[1]=x[0]-tsqx;
+ x[0]+=tsqx;
+ return;
+ default:
+ dcsqf1(n,x,wsave,wsave+n,ifac);
+ return;
+ }
+}
+
+STIN void dradb2(int ido,int l1,float *cc,float *ch,float *wa1){
+ int i,k,t0,t1,t2,t3,t4,t5,t6;
+ float ti2,tr2;
+
+ t0=l1*ido;
+
+ t1=0;
+ t2=0;
+ t3=(ido<<1)-1;
+ for (k=0;k<l1;k++){
+ ch[t1]=cc[t2]+cc[t3+t2];
+ ch[t1+t0]=cc[t2]-cc[t3+t2];
+ t2=(t1+=ido)<<1;
+ }
+
+ if (ido<2) return;
+ if (ido==2) goto L105;
+
+ t1=0;
+ t2=0;
+ for (k=0;k<l1;k++){
+ t3=t1;
+ t5=(t4=t2)+(ido<<1);
+ t6=t0+t1;
+ for (i=2;i<ido;i+=2){
+ t3+=2;
+ t4+=2;
+ t5-=2;
+ t6+=2;
+ ch[t3-1]=cc[t4-1]+cc[t5-1];
+ tr2=cc[t4-1]-cc[t5-1];
+ ch[t3]=cc[t4]-cc[t5];
+ ti2=cc[t4]+cc[t5];
+ ch[t6-1]=wa1[i-2]*tr2-wa1[i-1]*ti2;
+ ch[t6]=wa1[i-2]*ti2+wa1[i-1]*tr2;
+ }
+ t2=(t1+=ido)<<1;
+ }
+
+ if (ido%2==1) return;
+
+L105:
+ t1=ido-1;
+ t2=ido-1;
+ for (k=0;k<l1;k++){
+ ch[t1]=cc[t2]+cc[t2];
+ ch[t1+t0]=-(cc[t2+1]+cc[t2+1]);
+ t1+=ido;
+ t2+=ido<<1;
+ }
+}
+
+STIN void dradb3(int ido,int l1,float *cc,float *ch,float *wa1,
+ float *wa2){
+ static float taur = -.5;
+ static float taui = .86602540378443864676372317075293618;
+ int i,k,t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10;
+ float ci2,ci3,di2,di3,cr2,cr3,dr2,dr3,ti2,tr2;
+ t0=l1*ido;
+
+ t1=0;
+ t2=t0<<1;
+ t3=ido<<1;
+ t4=ido+(ido<<1);
+ t5=0;
+ for (k=0;k<l1;k++){
+ tr2=cc[t3-1]+cc[t3-1];
+ cr2=cc[t5]+(taur*tr2);
+ ch[t1]=cc[t5]+tr2;
+ ci3=taui*(cc[t3]+cc[t3]);
+ ch[t1+t0]=cr2-ci3;
+ ch[t1+t2]=cr2+ci3;
+ t1+=ido;
+ t3+=t4;
+ t5+=t4;
+ }
+
+ if (ido==1) return;
+
+ t1=0;
+ t3=ido<<1;
+ for (k=0;k<l1;k++){
+ t7=t1+(t1<<1);
+ t6=(t5=t7+t3);
+ t8=t1;
+ t10=(t9=t1+t0)+t0;
+
+ for (i=2;i<ido;i+=2){
+ t5+=2;
+ t6-=2;
+ t7+=2;
+ t8+=2;
+ t9+=2;
+ t10+=2;
+ tr2=cc[t5-1]+cc[t6-1];
+ cr2=cc[t7-1]+(taur*tr2);
+ ch[t8-1]=cc[t7-1]+tr2;
+ ti2=cc[t5]-cc[t6];
+ ci2=cc[t7]+(taur*ti2);
+ ch[t8]=cc[t7]+ti2;
+ cr3=taui*(cc[t5-1]-cc[t6-1]);
+ ci3=taui*(cc[t5]+cc[t6]);
+ dr2=cr2-ci3;
+ dr3=cr2+ci3;
+ di2=ci2+cr3;
+ di3=ci2-cr3;
+ ch[t9-1]=wa1[i-2]*dr2-wa1[i-1]*di2;
+ ch[t9]=wa1[i-2]*di2+wa1[i-1]*dr2;
+ ch[t10-1]=wa2[i-2]*dr3-wa2[i-1]*di3;
+ ch[t10]=wa2[i-2]*di3+wa2[i-1]*dr3;
+ }
+ t1+=ido;
+ }
+}
+
+STIN void dradb4(int ido,int l1,float *cc,float *ch,float *wa1,
+ float *wa2,float *wa3){
+ static float sqrt2=1.4142135623730950488016887242097;
+ int i,k,t0,t1,t2,t3,t4,t5,t6,t7,t8;
+ float ci2,ci3,ci4,cr2,cr3,cr4,ti1,ti2,ti3,ti4,tr1,tr2,tr3,tr4;
+ t0=l1*ido;
+
+ t1=0;
+ t2=ido<<2;
+ t3=0;
+ t6=ido<<1;
+ for (k=0;k<l1;k++){
+ t4=t3+t6;
+ t5=t1;
+ tr3=cc[t4-1]+cc[t4-1];
+ tr4=cc[t4]+cc[t4];
+ tr1=cc[t3]-cc[(t4+=t6)-1];
+ tr2=cc[t3]+cc[t4-1];
+ ch[t5]=tr2+tr3;
+ ch[t5+=t0]=tr1-tr4;
+ ch[t5+=t0]=tr2-tr3;
+ ch[t5+=t0]=tr1+tr4;
+ t1+=ido;
+ t3+=t2;
+ }
+
+ if (ido<2) return;
+ if (ido==2) goto L105;
+
+ t1=0;
+ for (k=0;k<l1;k++){
+ t5=(t4=(t3=(t2=t1<<2)+t6))+t6;
+ t7=t1;
+ for (i=2;i<ido;i+=2){
+ t2+=2;
+ t3+=2;
+ t4-=2;
+ t5-=2;
+ t7+=2;
+ ti1=cc[t2]+cc[t5];
+ ti2=cc[t2]-cc[t5];
+ ti3=cc[t3]-cc[t4];
+ tr4=cc[t3]+cc[t4];
+ tr1=cc[t2-1]-cc[t5-1];
+ tr2=cc[t2-1]+cc[t5-1];
+ ti4=cc[t3-1]-cc[t4-1];
+ tr3=cc[t3-1]+cc[t4-1];
+ ch[t7-1]=tr2+tr3;
+ cr3=tr2-tr3;
+ ch[t7]=ti2+ti3;
+ ci3=ti2-ti3;
+ cr2=tr1-tr4;
+ cr4=tr1+tr4;
+ ci2=ti1+ti4;
+ ci4=ti1-ti4;
+
+ ch[(t8=t7+t0)-1]=wa1[i-2]*cr2-wa1[i-1]*ci2;
+ ch[t8]=wa1[i-2]*ci2+wa1[i-1]*cr2;
+ ch[(t8+=t0)-1]=wa2[i-2]*cr3-wa2[i-1]*ci3;
+ ch[t8]=wa2[i-2]*ci3+wa2[i-1]*cr3;
+ ch[(t8+=t0)-1]=wa3[i-2]*cr4-wa3[i-1]*ci4;
+ ch[t8]=wa3[i-2]*ci4+wa3[i-1]*cr4;
+ }
+ t1+=ido;
+ }
+
+ if (ido%2 == 1) return;
+
+ L105:
+
+ t1=ido;
+ t2=ido<<2;
+ t3=ido-1;
+ t4=ido+(ido<<1);
+ for (k=0;k<l1;k++){
+ t5=t3;
+ ti1=cc[t1]+cc[t4];
+ ti2=cc[t4]-cc[t1];
+ tr1=cc[t1-1]-cc[t4-1];
+ tr2=cc[t1-1]+cc[t4-1];
+ ch[t5]=tr2+tr2;
+ ch[t5+=t0]=sqrt2*(tr1-ti1);
+ ch[t5+=t0]=ti2+ti2;
+ ch[t5+=t0]=-sqrt2*(tr1+ti1);
+
+ t3+=ido;
+ t1+=t2;
+ t4+=t2;
+ }
+}
+
+STIN void dradbg(int ido,int ip,int l1,int idl1,float *cc,float *c1,
+ float *c2,float *ch,float *ch2,float *wa){
+ static float tpi=6.28318530717958647692528676655900577;
+ int idij,ipph,i,j,k,l,ik,is,t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,
+ t11,t12;
+ float dc2,ai1,ai2,ar1,ar2,ds2;
+ int nbd;
+ float dcp,arg,dsp,ar1h,ar2h;
+ int ipp2;
+
+ t10=ip*ido;
+ t0=l1*ido;
+ arg=tpi/(float)ip;
+ dcp=cos(arg);
+ dsp=sin(arg);
+ nbd=(ido-1)>>1;
+ ipp2=ip;
+ ipph=(ip+1)>>1;
+ if (ido<l1) goto L103;
+
+ t1=0;
+ t2=0;
+ for (k=0;k<l1;k++){
+ t3=t1;
+ t4=t2;
+ for (i=0;i<ido;i++){
+ ch[t3]=cc[t4];
+ t3++;
+ t4++;
+ }
+ t1+=ido;
+ t2+=t10;
+ }
+ goto L106;
+
+ L103:
+ t1=0;
+ for (i=0;i<ido;i++){
+ t2=t1;
+ t3=t1;
+ for (k=0;k<l1;k++){
+ ch[t2]=cc[t3];
+ t2+=ido;
+ t3+=t10;
+ }
+ t1++;
+ }
+
+ L106:
+ t1=0;
+ t2=ipp2*t0;
+ t7=(t5=ido<<1);
+ for (j=1;j<ipph;j++){
+ t1+=t0;
+ t2-=t0;
+ t3=t1;
+ t4=t2;
+ t6=t5;
+ for (k=0;k<l1;k++){
+ ch[t3]=cc[t6-1]+cc[t6-1];
+ ch[t4]=cc[t6]+cc[t6];
+ t3+=ido;
+ t4+=ido;
+ t6+=t10;
+ }
+ t5+=t7;
+ }
+
+ if (ido == 1) goto L116;
+ if (nbd<l1) goto L112;
+
+ t1=0;
+ t2=ipp2*t0;
+ t7=0;
+ for (j=1;j<ipph;j++){
+ t1+=t0;
+ t2-=t0;
+ t3=t1;
+ t4=t2;
+
+ t7+=(ido<<1);
+ t8=t7;
+ for (k=0;k<l1;k++){
+ t5=t3;
+ t6=t4;
+ t9=t8;
+ t11=t8;
+ for (i=2;i<ido;i+=2){
+ t5+=2;
+ t6+=2;
+ t9+=2;
+ t11-=2;
+ ch[t5-1]=cc[t9-1]+cc[t11-1];
+ ch[t6-1]=cc[t9-1]-cc[t11-1];
+ ch[t5]=cc[t9]-cc[t11];
+ ch[t6]=cc[t9]+cc[t11];
+ }
+ t3+=ido;
+ t4+=ido;
+ t8+=t10;
+ }
+ }
+ goto L116;
+
+ L112:
+ t1=0;
+ t2=ipp2*t0;
+ t7=0;
+ for (j=1;j<ipph;j++){
+ t1+=t0;
+ t2-=t0;
+ t3=t1;
+ t4=t2;
+ t7+=(ido<<1);
+ t8=t7;
+ t9=t7;
+ for (i=2;i<ido;i+=2){
+ t3+=2;
+ t4+=2;
+ t8+=2;
+ t9-=2;
+ t5=t3;
+ t6=t4;
+ t11=t8;
+ t12=t9;
+ for (k=0;k<l1;k++){
+ ch[t5-1]=cc[t11-1]+cc[t12-1];
+ ch[t6-1]=cc[t11-1]-cc[t12-1];
+ ch[t5]=cc[t11]-cc[t12];
+ ch[t6]=cc[t11]+cc[t12];
+ t5+=ido;
+ t6+=ido;
+ t11+=t10;
+ t12+=t10;
+ }
+ }
+ }
+
+L116:
+ ar1=1.;
+ ai1=0.;
+ t1=0;
+ t9=(t2=ipp2*idl1);
+ t3=(ip-1)*idl1;
+ for (l=1;l<ipph;l++){
+ t1+=idl1;
+ t2-=idl1;
+
+ ar1h=dcp*ar1-dsp*ai1;
+ ai1=dcp*ai1+dsp*ar1;
+ ar1=ar1h;
+ t4=t1;
+ t5=t2;
+ t6=0;
+ t7=idl1;
+ t8=t3;
+ for (ik=0;ik<idl1;ik++){
+ c2[t4++]=ch2[t6++]+ar1*ch2[t7++];
+ c2[t5++]=ai1*ch2[t8++];
+ }
+ dc2=ar1;
+ ds2=ai1;
+ ar2=ar1;
+ ai2=ai1;
+
+ t6=idl1;
+ t7=t9-idl1;
+ for (j=2;j<ipph;j++){
+ t6+=idl1;
+ t7-=idl1;
+ ar2h=dc2*ar2-ds2*ai2;
+ ai2=dc2*ai2+ds2*ar2;
+ ar2=ar2h;
+ t4=t1;
+ t5=t2;
+ t11=t6;
+ t12=t7;
+ for (ik=0;ik<idl1;ik++){
+ c2[t4++]+=ar2*ch2[t11++];
+ c2[t5++]+=ai2*ch2[t12++];
+ }
+ }
+ }
+
+ t1=0;
+ for (j=1;j<ipph;j++){
+ t1+=idl1;
+ t2=t1;
+ for (ik=0;ik<idl1;ik++)ch2[ik]+=ch2[t2++];
+ }
+
+ t1=0;
+ t2=ipp2*t0;
+ for (j=1;j<ipph;j++){
+ t1+=t0;
+ t2-=t0;
+ t3=t1;
+ t4=t2;
+ for (k=0;k<l1;k++){
+ ch[t3]=c1[t3]-c1[t4];
+ ch[t4]=c1[t3]+c1[t4];
+ t3+=ido;
+ t4+=ido;
+ }
+ }
+
+ if (ido==1) goto L132;
+ if (nbd<l1) goto L128;
+
+ t1=0;
+ t2=ipp2*t0;
+ for (j=1;j<ipph;j++){
+ t1+=t0;
+ t2-=t0;
+ t3=t1;
+ t4=t2;
+ for (k=0;k<l1;k++){
+ t5=t3;
+ t6=t4;
+ for (i=2;i<ido;i+=2){
+ t5+=2;
+ t6+=2;
+ ch[t5-1]=c1[t5-1]-c1[t6];
+ ch[t6-1]=c1[t5-1]+c1[t6];
+ ch[t5]=c1[t5]+c1[t6-1];
+ ch[t6]=c1[t5]-c1[t6-1];
+ }
+ t3+=ido;
+ t4+=ido;
+ }
+ }
+ goto L132;
+
+ L128:
+ t1=0;
+ t2=ipp2*t0;
+ for (j=1;j<ipph;j++){
+ t1+=t0;
+ t2-=t0;
+ t3=t1;
+ t4=t2;
+ for (i=2;i<ido;i+=2){
+ t3+=2;
+ t4+=2;
+ t5=t3;
+ t6=t4;
+ for (k=0;k<l1;k++){
+ ch[t5-1]=c1[t5-1]-c1[t6];
+ ch[t6-1]=c1[t5-1]+c1[t6];
+ ch[t5]=c1[t5]+c1[t6-1];
+ ch[t6]=c1[t5]-c1[t6-1];
+ t5+=ido;
+ t6+=ido;
+ }
+ }
+ }
+
+L132:
+ if (ido==1) return;
+
+ for (ik=0;ik<idl1;ik++)c2[ik]=ch2[ik];
+
+ t1=0;
+ for (j=1;j<ip;j++){
+ t2=(t1+=t0);
+ for (k=0;k<l1;k++){
+ c1[t2]=ch[t2];
+ t2+=ido;
+ }
+ }
+
+ if (nbd>l1) goto L139;
+
+ is= -ido-1;
+ t1=0;
+ for (j=1;j<ip;j++){
+ is+=ido;
+ t1+=t0;
+ idij=is;
+ t2=t1;
+ for (i=2;i<ido;i+=2){
+ t2+=2;
+ idij+=2;
+ t3=t2;
+ for (k=0;k<l1;k++){
+ c1[t3-1]=wa[idij-1]*ch[t3-1]-wa[idij]*ch[t3];
+ c1[t3]=wa[idij-1]*ch[t3]+wa[idij]*ch[t3-1];
+ t3+=ido;
+ }
+ }
+ }
+ return;
+
+ L139:
+ is= -ido-1;
+ t1=0;
+ for (j=1;j<ip;j++){
+ is+=ido;
+ t1+=t0;
+ t2=t1;
+ for (k=0;k<l1;k++){
+ idij=is;
+ t3=t2;
+ for (i=2;i<ido;i+=2){
+ idij+=2;
+ t3+=2;
+ c1[t3-1]=wa[idij-1]*ch[t3-1]-wa[idij]*ch[t3];
+ c1[t3]=wa[idij-1]*ch[t3]+wa[idij]*ch[t3-1];
+ }
+ t2+=ido;
+ }
+ }
+}
+
+STIN void drftb1(int n, float *c, float *ch, float *wa, int *ifac){
+ int i,k1,l1,l2;
+ int na;
+ int nf,ip,iw,ix2,ix3,ido,idl1;
+
+ nf=ifac[1];
+ na=0;
+ l1=1;
+ iw=1;
+
+ for (k1=0;k1<nf;k1++){
+ ip=ifac[k1 + 2];
+ l2=ip*l1;
+ ido=n/l2;
+ idl1=ido*l1;
+ if (ip!=4) goto L103;
+ ix2=iw+ido;
+ ix3=ix2+ido;
+
+ if (na!=0)
+ dradb4(ido,l1,ch,c,wa+iw-1,wa+ix2-1,wa+ix3-1);
+ else
+ dradb4(ido,l1,c,ch,wa+iw-1,wa+ix2-1,wa+ix3-1);
+ na=1-na;
+ goto L115;
+
+ L103:
+ if (ip!=2) goto L106;
+
+ if (na!=0)
+ dradb2(ido,l1,ch,c,wa+iw-1);
+ else
+ dradb2(ido,l1,c,ch,wa+iw-1);
+ na=1-na;
+ goto L115;
+
+ L106:
+ if (ip!=3) goto L109;
+
+ ix2=iw+ido;
+ if (na!=0)
+ dradb3(ido,l1,ch,c,wa+iw-1,wa+ix2-1);
+ else
+ dradb3(ido,l1,c,ch,wa+iw-1,wa+ix2-1);
+ na=1-na;
+ goto L115;
+
+ L109:
+/* The radix five case can be translated later..... */
+/* if (ip!=5) goto L112;
+
+ ix2=iw+ido;
+ ix3=ix2+ido;
+ ix4=ix3+ido;
+ if (na!=0)
+ dradb5(ido,l1,ch,c,wa+iw-1,wa+ix2-1,wa+ix3-1,wa+ix4-1);
+ else
+ dradb5(ido,l1,c,ch,wa+iw-1,wa+ix2-1,wa+ix3-1,wa+ix4-1);
+ na=1-na;
+ goto L115;
+
+ L112:*/
+ if (na!=0)
+ dradbg(ido,ip,l1,idl1,ch,ch,ch,c,c,wa+iw-1);
+ else
+ dradbg(ido,ip,l1,idl1,c,c,c,ch,ch,wa+iw-1);
+ if (ido==1)na=1-na;
+
+ L115:
+ l1=l2;
+ iw+=(ip-1)*ido;
+ }
+
+ if (na==0) return;
+
+ for (i=0;i<n;i++)c[i]=ch[i];
+}
+
+void __ogg_fdrfftb(int n, float *r, float *wsave, int *ifac){
+ if (n == 1) return;
+ drftb1(n, r, wsave, wsave+n, ifac);
+}
+
+STIN void dcsqb1(int n,float *x,float *w,float *xh,int *ifac){
+ int modn,i,k,kc;
+ int np2,ns2;
+ float xim1;
+
+ ns2=(n+1)>>1;
+ np2=n;
+
+ for (i=2;i<n;i+=2){
+ xim1=x[i-1]+x[i];
+ x[i]-=x[i-1];
+ x[i-1]=xim1;
+ }
+
+ x[0]+=x[0];
+ modn=n%2;
+ if (modn==0)x[n-1]+=x[n-1];
+
+ __ogg_fdrfftb(n,x,xh,ifac);
+
+ kc=np2;
+ for (k=1;k<ns2;k++){
+ kc--;
+ xh[k]=w[k-1]*x[kc]+w[kc-1]*x[k];
+ xh[kc]=w[k-1]*x[k]-w[kc-1]*x[kc];
+ }
+
+ if (modn==0)x[ns2]=w[ns2-1]*(x[ns2]+x[ns2]);
+
+ kc=np2;
+ for (k=1;k<ns2;k++){
+ kc--;
+ x[k]=xh[k]+xh[kc];
+ x[kc]=xh[k]-xh[kc];
+ }
+ x[0]+=x[0];
+}
+
+void __ogg_fdcosqb(int n,float *x,float *wsave,int *ifac){
+ static float tsqrt2 = 2.8284271247461900976033774484194;
+ float x1;
+
+ if (n<2){
+ x[0]*=4;
+ return;
+ }
+ if (n==2){
+ x1=(x[0]+x[1])*4;
+ x[1]=tsqrt2*(x[0]-x[1]);
+ x[0]=x1;
+ return;
+ }
+
+ dcsqb1(n,x,wsave,wsave+n,ifac);
+}
+
+
+
diff --git a/demos/mobile/guitartuner/src/guitartuner.cpp b/demos/mobile/guitartuner/src/guitartuner.cpp
new file mode 100644
index 00000000..43222f2d
--- /dev/null
+++ b/demos/mobile/guitartuner/src/guitartuner.cpp
@@ -0,0 +1,359 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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
+}
diff --git a/demos/mobile/guitartuner/src/guitartuner.h b/demos/mobile/guitartuner/src/guitartuner.h
new file mode 100644
index 00000000..fbb16f7c
--- /dev/null
+++ b/demos/mobile/guitartuner/src/guitartuner.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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$
+**
+****************************************************************************/
+
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QMainWindow>
+#include <QtDeclarative>
+#include <QAudioDeviceInfo>
+#include <QAudioOutput>
+#include <QAudioInput>
+#include "voicegenerator.h"
+#include "voiceanalyzer.h"
+
+const int DataFrequencyHzOutput = 44100;
+const int DataFrequencyHzInput = 48000;
+
+#define MAX_INPUT_VALUE 50
+#define MIN_INPUT_VALUE -50
+
+class GuitarTuner : public QMainWindow
+{
+ Q_OBJECT
+public:
+ enum Orientation {
+ LockPortrait,
+ LockLandscape,
+ Auto
+ };
+ explicit GuitarTuner(QWidget *parent = 0);
+ qreal getVolume();
+ qreal getMicrophoneSensitivity();
+ bool getMuteState();
+ void setOrientation(Orientation orientation);
+
+signals:
+
+public slots:
+ void modeChanged(bool isInput);
+ void muteStateChanged(bool isMuted);
+ void targetFrequencyChanged(qreal targetFrequency);
+ void outputStateChanged(QAudio::State state);
+ void setMaxVolumeLevel(qreal);
+
+private:
+ void initAudioOutput();
+ void initAudioInput();
+ VoiceGenerator *m_voicegenerator;
+ VoiceAnalyzer *m_analyzer;
+ QObject *qmlObject;
+ QAudioOutput *m_audioOutput;
+ QAudioInput *m_audioInput;
+ QAudioFormat m_format_output;
+ QAudioFormat m_format_input;
+ QDeclarativeView *m_guitarTunerUI;
+};
+
+#endif // MAINWINDOW_H
diff --git a/demos/mobile/guitartuner/src/guitartuner.rc b/demos/mobile/guitartuner/src/guitartuner.rc
new file mode 100644
index 00000000..5cd35118
--- /dev/null
+++ b/demos/mobile/guitartuner/src/guitartuner.rc
@@ -0,0 +1,23 @@
+IDI_ICON1 ICON DISCARDABLE "/../images/guitartuner_icon.ico"
+
+1 VERSIONINFO
+FILEVERSION 1,2,0,0
+PRODUCTVERSION 1,2,0,0
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904E4"
+ BEGIN
+ VALUE "CompanyName", "Nokia Corporation\0"
+ VALUE "FileDescription", "Qt Quick example application.\0"
+ VALUE "FileVersion", "1.2.0\0"
+ VALUE "LegalCopyright", "Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)."
+ VALUE "ProductName", "Guitar Tuner\0"
+ VALUE "ProductVersion", "1.2.0\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1252
+ END
+END
diff --git a/demos/mobile/guitartuner/src/guitartuner.ui b/demos/mobile/guitartuner/src/guitartuner.ui
new file mode 100644
index 00000000..36ee1bd8
--- /dev/null
+++ b/demos/mobile/guitartuner/src/guitartuner.ui
@@ -0,0 +1,178 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>GuitarTuner</class>
+ <widget class="QWidget" name="GuitarTuner">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>187</width>
+ <height>279</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>GuitarTuner</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QLabel" name="tabulatorIcon">
+ <property name="text">
+ <string notr="true"/>
+ </property>
+ <property name="pixmap">
+ <pixmap resource="../guitartuner.qrc">:/images/guitartab.svg</pixmap>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSlider" name="correctSoundSlider">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </property>
+ <property name="minimum">
+ <number>-50</number>
+ </property>
+ <property name="maximum">
+ <number>50</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksAbove</enum>
+ </property>
+ <property name="tickInterval">
+ <number>50</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QToolButton" name="buttonPrev">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="arrowType">
+ <enum>Qt::LeftArrow</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="noteLabel">
+ <property name="text">
+ <string>A</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="buttonNext">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="autoRaise">
+ <bool>false</bool>
+ </property>
+ <property name="arrowType">
+ <enum>Qt::RightArrow</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QPushButton" name="modeButton">
+ <property name="text">
+ <string>Change mode</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="Line" name="line">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QSlider" name="soundSlider">
+ <property name="value">
+ <number>65</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="soundButton">
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="icon">
+ <iconset resource="../guitartuner.qrc">
+ <normaloff>:/images/note.svg</normaloff>
+ <normalon>:/images/noteNo.svg</normalon>
+ <activeon>:/images/noteNo.svg</activeon>:/images/note.svg</iconset>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>30</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="autoRaise">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="micSensitivityLabel">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>microphone
+sensitivity</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <resources>
+ <include location="../guitartuner.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/demos/mobile/guitartuner/src/guitartunerui.cpp b/demos/mobile/guitartuner/src/guitartunerui.cpp
new file mode 100644
index 00000000..24357b3b
--- /dev/null
+++ b/demos/mobile/guitartuner/src/guitartunerui.cpp
@@ -0,0 +1,341 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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 <QTimer>
+
+#include "guitartunerui.h"
+#include "ui_guitartunerui.h"
+
+GuitarTunerUI::GuitarTunerUI(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::GuitarTunerUI),
+ m_maximumPrecision(0)
+{
+ ui->setupUi(this);
+
+ // Set up the class attributes to proper values.
+ m_outputActive = false;
+ m_muted = false;
+ m_outputVolumeLevel = getVolumeFromSoundSlider();
+ m_inputVolumeLevel = 1.0 - m_outputVolumeLevel;
+
+ // Set up the current tone, the frequency, and the name for it.
+ m_currentToneIndex = 5;
+ updateFrequencyByToneIndex(m_currentToneIndex);
+
+ // Connect the signals from UI into proper slots.
+ connect(ui->soundSlider, SIGNAL(valueChanged(int)),
+ SLOT(changeVolume()));
+ connect(ui->soundButton, SIGNAL(toggled(bool)),
+ SLOT(toggleSound(bool)));
+ connect(ui->modeButton, SIGNAL(clicked()),
+ SLOT(toggleInputOrOutput()));
+ connect(ui->buttonNext, SIGNAL(clicked()), SLOT(next()));
+ connect(ui->buttonPrev, SIGNAL(clicked()), SLOT(prev()));
+
+ // Initialise up the UI by calling toggleInputOrOutput
+ // for the first time.
+ toggleInputOrOutput();
+}
+
+GuitarTunerUI::~GuitarTunerUI()
+{
+ delete ui;
+}
+
+void GuitarTunerUI::changeEvent(QEvent *e)
+{
+ QWidget::changeEvent(e);
+ switch (e->type()) {
+ case QEvent::LanguageChange:
+ ui->retranslateUi(this);
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * Returns a value from 0 to 1, representing the volume.
+ */
+qreal GuitarTunerUI::getVolumeFromSoundSlider() const
+{
+ qreal value = ui->soundSlider->value();
+ return value/ui->soundSlider->maximum();
+}
+
+/**
+ * Updates the m_currentToneFrequency and m_currentToneString,
+ * according to the given index. Also updates the UI.
+ */
+void GuitarTunerUI::updateFrequencyByToneIndex(int index)
+{
+
+ switch (index) {
+ case 0: {
+ m_currentToneFrequency = FrequencyE;
+ m_currentToneString = "E";
+ break;
+ }
+ case 1: {
+ m_currentToneFrequency = FrequencyA;
+ m_currentToneString = "A";
+ break;
+ }
+ case 2: {
+ m_currentToneFrequency = FrequencyD;
+ m_currentToneString = "D";
+ break;
+ }
+ case 3: {
+ m_currentToneFrequency = FrequencyG;
+ m_currentToneString = "G";
+ break;
+ }
+ case 4: {
+ m_currentToneFrequency = FrequencyB;
+ m_currentToneString = "B";
+ break;
+ }
+ case 5: {
+ m_currentToneFrequency = FrequencyE2;
+ m_currentToneString = "e";
+ break;
+ }
+ default: {
+ qDebug() << "invalid index!" << index;
+ }
+ }
+ // Set the noteLabel text according to the current tone.
+ ui->noteLabel->setText(m_currentToneString);
+}
+
+/**
+ * Returns the volume.
+ */
+qreal GuitarTunerUI::getVolume() const
+{
+ return m_outputVolumeLevel;
+}
+
+/**
+ * Returns true if the sound is muted.
+ */
+bool GuitarTunerUI::getMuteState() const
+{
+ return m_muted;
+}
+
+
+/**
+ * Returns the microphone sensitivity.
+ */
+qreal GuitarTunerUI::getMicrophoneSensitivity() const
+{
+ return m_inputVolumeLevel;
+}
+
+/**
+ * Returns whether the input mode is active.
+ */
+bool GuitarTunerUI::isInputModeActive() const
+{
+ return !m_outputActive;
+}
+
+/**
+ * Returns the current target frequency.
+ */
+qreal GuitarTunerUI::getFrequency() const
+{
+ return m_currentToneFrequency;
+}
+
+/**
+ * Toggles the sound according to the parameter.
+ * Has no effect if output is not active.
+ */
+void GuitarTunerUI::toggleSound(bool noSound)
+{
+ if (!m_outputActive) {
+ return;
+ }
+ m_muted = noSound;
+ emit muteChanged(m_muted);
+}
+
+/**
+ * Changes the volume or microphone sensitivity.
+ */
+void GuitarTunerUI::changeVolume()
+{
+ qreal resultingAmplitude = getVolumeFromSoundSlider();
+ qDebug() << "resultingAmplitude" << resultingAmplitude;
+ if (m_outputActive) {
+ m_outputVolumeLevel = resultingAmplitude;
+ emit volumeChanged(resultingAmplitude);
+ }
+ else {
+ m_inputVolumeLevel = resultingAmplitude;
+ emit microphoneSensitivityChanged(1.0-resultingAmplitude);
+ }
+}
+
+/**
+ * Toggles input or output, depending of the current state.
+ */
+void GuitarTunerUI::toggleInputOrOutput()
+{
+ // If output mode is active:
+ if (m_outputActive) {
+ // Change UI to correspond to the input mode.
+ m_outputActive = false;
+ ui->soundSlider->setValue(m_inputVolumeLevel*100);
+ ui->soundButton->setDisabled(true);
+ ui->soundButton->hide();
+ ui->micSensitivityLabel->show();
+ emit modeChanged(true);
+ ui->modeButton->setText("To tone mode");
+ }
+ // Else:
+ else {
+ // Change UI to correspond to the output mode.
+ m_outputActive = true;
+ ui->soundSlider->setValue(m_outputVolumeLevel*100);
+ ui->soundButton->setDisabled(false);
+ ui->micSensitivityLabel->hide();
+ ui->soundButton->show();
+ emit modeChanged(false);
+ ui->modeButton->setText("To listen mode");
+ }
+}
+
+/**
+ * Receives the low voice signal.
+ */
+void GuitarTunerUI::lowVoice()
+{
+ if (ui->noteLabel->font().bold()) {
+ QFont font;
+ font.setBold(false);
+ font.setUnderline(false);
+ ui->noteLabel->setFont(font);
+ }
+}
+
+/**
+ * Receives the voice difference signal.
+ * The difference is qreal, where increase of 1 corresponds
+ * to increase of 1 tone to the target frequency.
+ */
+void GuitarTunerUI::voiceDifference(qreal difference)
+{
+ if (ui->noteLabel->font().bold()) {
+ QFont font;
+ font.setBold(false);
+ font.setUnderline(false);
+ ui->noteLabel->setFont(font);
+ }
+ ui->correctSoundSlider->setValue(difference*m_maximumPrecision);
+}
+
+/**
+ * Receives the correct frequency signal.
+ * Makes the UI to visualize correct frequency event.
+ */
+void GuitarTunerUI::correctFrequencyObtained()
+{
+ qDebug() << "CORRECT FREQUENCY";
+ QFont font;
+ font.setBold(true);
+ font.setUnderline(true);
+ ui->noteLabel->setFont(font);
+}
+
+/**
+ * Sets up the maximum voice difference.
+ */
+void GuitarTunerUI::setMaximumVoiceDifference(int max)
+{
+ // Assert that the maximum precision is known.
+ Q_ASSERT(m_maximumPrecision != 0);
+ // Set the maximum and minimum values of the correctSoundSlider
+ // to the +- max*m_maximumPrecision, and set the tick interval
+ // to be m_maximumPrecision.
+ ui->correctSoundSlider->setMaximum(max*m_maximumPrecision);
+ ui->correctSoundSlider->setMinimum(-max*m_maximumPrecision);
+ ui->correctSoundSlider->setTickInterval(max*m_maximumPrecision);
+}
+
+/**
+ * Stores the maximum precision per note. Used to setup the
+ * correct sound slider.
+ */
+void GuitarTunerUI::setMaximumPrecisionPerNote(int max)
+{
+ m_maximumPrecision = max;
+}
+
+/**
+ * Changes the tone to the next value.
+ */
+void GuitarTunerUI::next()
+{
+ changeTone((m_currentToneIndex + 1) % 6);
+}
+
+/**
+ * Changes the tone to the previous value.
+ */
+void GuitarTunerUI::prev()
+{
+ changeTone((m_currentToneIndex + 5) % 6);
+}
+
+/**
+ * Changes the tone according to the new index.
+ */
+void GuitarTunerUI::changeTone(int newIndex)
+{
+ m_currentToneIndex = newIndex;
+ updateFrequencyByToneIndex(m_currentToneIndex);
+ qDebug() << "targetFrequencyChanged" << m_currentToneFrequency;
+ emit targetFrequencyChanged(m_currentToneFrequency);
+}
diff --git a/demos/mobile/guitartuner/src/guitartunerui.h b/demos/mobile/guitartuner/src/guitartunerui.h
new file mode 100644
index 00000000..79c92e3e
--- /dev/null
+++ b/demos/mobile/guitartuner/src/guitartunerui.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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$
+**
+****************************************************************************/
+
+#ifndef GUITARTUNERUI_H
+#define GUITARTUNERUI_H
+
+#include <QWidget>
+#include <QDebug>
+
+namespace Ui {
+ class GuitarTunerUI;
+}
+
+const qreal FrequencyE = 82.407;
+const qreal FrequencyA = 110.00;
+const qreal FrequencyD = 146.83;
+const qreal FrequencyG = 196.00;
+const qreal FrequencyB = 246.94;
+const qreal FrequencyE2 = 329.63;
+
+class GuitarTunerUI : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit GuitarTunerUI(QWidget *parent = 0);
+ ~GuitarTunerUI();
+
+ qreal getVolume() const;
+ bool getMuteState() const;
+ qreal getMicrophoneSensitivity() const;
+ bool isInputModeActive() const;
+ qreal getFrequency() const;
+ int getScaleMaximumValue() const;
+ void setMaximumVoiceDifference(int max);
+ void setMaximumPrecisionPerNote(int max);
+
+public slots:
+ void toggleSound(bool off);
+ void next();
+ void prev();
+ void changeVolume();
+ void toggleInputOrOutput();
+
+ void lowVoice();
+ void voiceDifference(qreal difference);
+ void correctFrequencyObtained();
+
+signals:
+ void modeChanged(bool isInput);
+ void volumeChanged(qreal volume);
+ void microphoneSensitivityChanged(qreal sensitivity);
+ void muteChanged(bool isMuted);
+ void targetFrequencyChanged(qreal targetFrequency);
+
+protected:
+ void changeEvent(QEvent *e);
+
+private:
+ Ui::GuitarTunerUI *ui;
+ void changeTone(int newIndex);
+ qreal getVolumeFromSoundSlider() const;
+ int m_currentToneIndex;
+ QString m_currentToneString;
+ qreal m_currentToneFrequency;
+ void updateFrequencyByToneIndex(int index);
+ bool m_outputActive;
+ bool m_muted;
+ qreal m_outputVolumeLevel;
+ qreal m_inputVolumeLevel;
+ int m_maximumPrecision;
+};
+
+#endif // GUITARTUNERUI_H
diff --git a/demos/mobile/guitartuner/src/guitartunerui.ui b/demos/mobile/guitartuner/src/guitartunerui.ui
new file mode 100644
index 00000000..af7b585b
--- /dev/null
+++ b/demos/mobile/guitartuner/src/guitartunerui.ui
@@ -0,0 +1,178 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>GuitarTunerUI</class>
+ <widget class="QWidget" name="GuitarTunerUI">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>187</width>
+ <height>279</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>GuitarTunerUI</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QLabel" name="tabulatorIcon">
+ <property name="text">
+ <string notr="true"/>
+ </property>
+ <property name="pixmap">
+ <pixmap resource="../GuitarTuner.qrc">:/images/guitartab.svg</pixmap>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSlider" name="correctSoundSlider">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </property>
+ <property name="minimum">
+ <number>-50</number>
+ </property>
+ <property name="maximum">
+ <number>50</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksAbove</enum>
+ </property>
+ <property name="tickInterval">
+ <number>50</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QToolButton" name="buttonPrev">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="arrowType">
+ <enum>Qt::LeftArrow</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="noteLabel">
+ <property name="text">
+ <string>A</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="buttonNext">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="autoRaise">
+ <bool>false</bool>
+ </property>
+ <property name="arrowType">
+ <enum>Qt::RightArrow</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QPushButton" name="modeButton">
+ <property name="text">
+ <string>Change mode</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="Line" name="line">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QSlider" name="soundSlider">
+ <property name="value">
+ <number>65</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="soundButton">
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="icon">
+ <iconset resource="../GuitarTuner.qrc">
+ <normaloff>:/images/note.svg</normaloff>
+ <normalon>:/images/noteNo.svg</normalon>
+ <activeon>:/images/noteNo.svg</activeon>:/images/note.svg</iconset>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>30</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="autoRaise">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="micSensitivityLabel">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>microphone
+sensitivity</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <resources>
+ <include location="../GuitarTuner.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/demos/mobile/guitartuner/src/main.cpp b/demos/mobile/guitartuner/src/main.cpp
new file mode 100644
index 00000000..7ddd1f78
--- /dev/null
+++ b/demos/mobile/guitartuner/src/main.cpp
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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 <QtGui/QApplication>
+#include "guitartuner.h"
+
+int main(int argc, char *argv[])
+{
+ QApplication a(argc, argv);
+ GuitarTuner w;
+ w.setOrientation(GuitarTuner::LockPortrait);
+
+#ifdef Q_OS_SYMBIAN
+ w.showFullScreen();
+#elif defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6)
+ w.showMaximized();
+#else
+ w.show();
+#endif
+
+ return a.exec();
+}
+
diff --git a/demos/mobile/guitartuner/src/mycomponents/Adjuster.qml b/demos/mobile/guitartuner/src/mycomponents/Adjuster.qml
new file mode 100644
index 00000000..e5e67eb8
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/Adjuster.qml
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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$
+**
+****************************************************************************/
+
+import QtQuick 1.0
+import "adjustbars.js" as AdjustBars
+
+/* A barchart-like adjuster component. */
+Rectangle {
+ id: adjuster
+
+ property real max: 100
+ property real value: 0
+ property bool created: false
+
+ signal valueChanged(real value)
+ signal focusChangedByClick()
+ signal arrowPressedWhenValueOverLimits()
+
+ function setValue(pValue) {
+ value = pValue;
+ AdjustBars.fillBars(value/max*AdjustBars.maxBars);
+ valueChanged(value);
+ }
+
+ height: 60; width: 300
+ color: "transparent"
+ Keys.onRightPressed: {
+ var val = value+max/AdjustBars.maxBars;
+ if (val <= max) {
+ value = val;
+ AdjustBars.fillBars(value/max*AdjustBars.maxBars);
+ valueChanged(value);
+ }
+ else {
+ arrowPressedWhenValueOverLimits()
+ }
+ }
+ Keys.onLeftPressed: {
+ var val = value-max/AdjustBars.maxBars;
+ if (0 <= val) {
+ value = val;
+ AdjustBars.fillBars(value/max*AdjustBars.maxBars);
+ valueChanged(value);
+ }
+ else {
+ arrowPressedWhenValueOverLimits()
+ }
+ }
+ Component.onCompleted: {
+ AdjustBars.createBars();
+ AdjustBars.fillBars(value/max*AdjustBars.maxBars);
+ created = true;
+ }
+ Component.onDestruction: {
+ AdjustBars.destroyBars;
+ }
+ //Dynamic objects have to be recreated when the window size changes.
+ onWidthChanged: {
+ if (created) {
+ AdjustBars.destroyBars();
+ AdjustBars.createBars();
+ AdjustBars.fillBars(value/max*AdjustBars.maxBars);
+ }
+ }
+ onHeightChanged: {
+ if (created) {
+ AdjustBars.destroyBars();
+ AdjustBars.createBars();
+ AdjustBars.fillBars(value/max*AdjustBars.maxBars);
+ }
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onPositionChanged: {
+ focusChangedByClick();
+ var val = mouse.x/parent.width*parent.max;
+ if (0 < val && val < max) {
+ parent.value = val;
+ AdjustBars.fillBars(parent.value/parent.max*AdjustBars.maxBars);
+ valueChanged(parent.value);
+ }
+ }
+ onClicked: {
+ focusChangedByClick();
+ var val = mouse.x/parent.width*parent.max;
+ if (0 < val && val < max) {
+ parent.value = val;
+ AdjustBars.fillBars(parent.value/parent.max*AdjustBars.maxBars);
+ valueChanged(parent.value);
+ }
+ }
+ }
+}
diff --git a/demos/mobile/guitartuner/src/mycomponents/Meter.qml b/demos/mobile/guitartuner/src/mycomponents/Meter.qml
new file mode 100644
index 00000000..1b175493
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/Meter.qml
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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$
+**
+****************************************************************************/
+
+import QtQuick 1.0
+
+/* A meter component. */
+Rectangle {
+ id: meter
+
+ property real value: 0
+ property real minValue: -1
+ property real maxValue: 1
+ property alias imageSize: meterImage.sourceSize
+
+ function valueChanged(pValue) {
+ value = pValue;
+ scaleValueToAngle();
+ }
+ function scaleValueToAngle() {
+ pointer.angle = (((value-minValue)/(maxValue-minValue))*
+ (pointer.angleMax-pointer.angleMin))+
+ pointer.angleMin;
+ }
+
+ color: "transparent"
+
+ Image {
+ id: meterImage
+
+ smooth: true
+ source: "./images/meterBG.png"
+ anchors.fill: parent
+ }
+
+ Image {
+ id:pointerShadow
+
+ x: pointer.x - 2
+ y: pointer.y - 2
+ height: pointer.height
+ smooth: true
+ source: "./images/pointerShadow.png"
+ transform: Rotation {
+ origin.x: 2
+ origin.y: height
+ angle: -pointer.angle
+ }
+ }
+
+ Image {
+ id: pointer
+
+ property real angle: 0
+ property real angleMax: -45
+ property real angleMin: 45
+
+ height: parent.height*0.92
+ transformOrigin: "Bottom"
+ rotation: -angle
+ smooth: true
+ source: "./images/pointer.png"
+ anchors {
+ bottomMargin: 2
+ bottom: parent.bottom;
+ horizontalCenter: parent.horizontalCenter
+ }
+
+ Behavior on angle {
+ SpringAnimation {
+ spring: 1.4
+ damping: 0.15
+ }
+ }
+ }
+}
diff --git a/demos/mobile/guitartuner/src/mycomponents/NoteButtonView.qml b/demos/mobile/guitartuner/src/mycomponents/NoteButtonView.qml
new file mode 100644
index 00000000..04a78dd4
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/NoteButtonView.qml
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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$
+**
+****************************************************************************/
+
+import QtQuick 1.0
+
+/* A view component for buttons for choosing notes. */
+ListView {
+ id: noteChooser
+
+ property real currentFrequency: 82.407
+
+ signal noteSelected(string note, real frequency, int index)
+
+ //Press down the button corresponding to the given note.
+ function pushButton(index) {
+ currentIndex = index;
+ }
+
+ width: 50*model.count + spacing*(model.count-1); height: 50
+ orientation: ListView.Horizontal
+ model: NotesModel {}
+ delegate: notesDelegate
+ keyNavigationWraps: true
+ boundsBehavior: Flickable.StopAtBounds
+
+ Component {
+ id: notesDelegate
+
+ ToggleButton {
+ id: noteButton
+
+ width: height; height: noteChooser.height
+ offImageSource: offSource
+ onImageSource: onSource
+ state: noteButton.ListView.isCurrentItem ? "pressed" : "unPressed"
+ onSelected: {
+ noteChooser.noteSelected(note, frequency, index)
+ if (note != "Auto") {
+ currentFrequency = frequency
+ }
+ }
+ onPushed: {
+ noteButton.ListView.view.currentIndex = index
+ }
+ }
+ }
+}
diff --git a/demos/mobile/guitartuner/src/mycomponents/NotesModel.qml b/demos/mobile/guitartuner/src/mycomponents/NotesModel.qml
new file mode 100644
index 00000000..1aecc051
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/NotesModel.qml
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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$
+**
+****************************************************************************/
+
+import QtQuick 1.0
+
+/* The model component for the NoteButtonView. */
+ListModel {
+ ListElement {
+ note: "E"
+ offSource: "./images/tuner_e.png"
+ onSource: "./images/tuner_e_on.png"
+ bigSource: "./mycomponents/images/big_e.png"
+ glowSource: "./mycomponents/images/glowing_e.png"
+ frequency: "82.407"
+ interval: "5"
+ }
+ ListElement {
+ note: "A"
+ offSource: "./images/tuner_a.png"
+ onSource: "./images/tuner_a_on.png"
+ bigSource: "./mycomponents/images/big_a.png"
+ glowSource: "./mycomponents/images/glowing_a.png"
+ frequency: "110.00"
+ interval: "5"
+ }
+ ListElement {
+ note: "D"
+ offSource: "./images/tuner_d.png"
+ onSource: "./images/tuner_d_on.png"
+ bigSource: "./mycomponents/images/big_d.png"
+ glowSource: "./mycomponents/images/glowing_d.png"
+ frequency: "146.83"
+ interval: "5"
+ }
+ ListElement {
+ note: "G"
+ offSource: "./images/tuner_g.png"
+ onSource: "./images/tuner_g_on.png"
+ bigSource: "./mycomponents/images/big_g.png"
+ glowSource: "./mycomponents/images/glowing_g.png"
+ frequency: "196.00"
+ interval: "4"
+ }
+ ListElement {
+ note: "B"
+ offSource: "./images/tuner_b.png"
+ onSource: "./images/tuner_b_on.png"
+ bigSource: "./mycomponents/images/big_b.png"
+ glowSource: "./mycomponents/images/glowing_b.png"
+ frequency: "246.94"
+ interval: "5"
+ }
+ ListElement {
+ note: "e"
+ offSource: "./images/tuner_e.png"
+ onSource: "./images/tuner_e_on.png"
+ bigSource: "./mycomponents/images/big_e.png"
+ glowSource: "./mycomponents/images/glowing_e.png"
+ frequency: "329.63"
+ interval: "9999" //Big enough that we can't move over this note
+ }
+ ListElement {
+ note: "Auto"
+ offSource: "./images/tuner_auto.png"
+ onSource: "./images/tuner_auto_on.png"
+ frequency: "82.407"
+ }
+}
diff --git a/demos/mobile/guitartuner/src/mycomponents/ToggleButton.qml b/demos/mobile/guitartuner/src/mycomponents/ToggleButton.qml
new file mode 100644
index 00000000..de46b9f0
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/ToggleButton.qml
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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$
+**
+****************************************************************************/
+
+import QtQuick 1.0
+
+/* A toggle button component. */
+Rectangle {
+ id: toggleButton
+
+ property url offImageSource: ""
+ property url onImageSource: ""
+ property alias imageSource: buttonImage.source
+
+ signal selected()
+ signal pushed()
+
+ color: "transparent"
+ state: "unPressed"
+ onStateChanged: {
+ if (state == "pressed") {
+ selected()
+ }
+ }
+
+ Image {
+ id: buttonImage
+
+ smooth: true
+ anchors.fill: parent
+ }
+ MouseArea {
+ id: mouseArea
+
+ anchors.fill: parent
+ onPressed: {
+ if (parent.state == "unPressed") {
+ pushed()
+ }
+ }
+ }
+
+ states: [
+ State {
+ name: "pressed"
+ PropertyChanges {
+ target: toggleButton
+ scale: 0.95
+ imageSource: onImageSource
+ }
+ },
+ State {
+ name: "unPressed"
+ PropertyChanges {
+ target: toggleButton
+ scale: 1/0.95
+ imageSource: offImageSource
+ }
+ }
+ ]
+
+ transitions: [
+ Transition {
+ from: "unPressed"
+ to: "pressed"
+ reversible: true
+ PropertyAnimation {
+ target: toggleButton
+ properties: "scale"
+ duration: 100
+ }
+ }
+ ]
+}
diff --git a/demos/mobile/guitartuner/src/mycomponents/adjustbars.js b/demos/mobile/guitartuner/src/mycomponents/adjustbars.js
new file mode 100644
index 00000000..ba652a6f
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/adjustbars.js
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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$
+**
+****************************************************************************/
+
+/* JavaScript functions for creating, handling and
+ * destroying the bars of the adjuster component. */
+
+var maxBars = 10;
+var firstBarHeight = 5;
+var bars = new Array(maxBars);
+var colors = new Array(maxBars);
+var barWidthFactor = 2.3;
+
+function createBars() {
+ var barWidth = adjuster.width/maxBars/barWidthFactor;
+ for (var i = 1; i <= maxBars; i++) {
+ //Create, configure and store the bars.
+ var bar = Qt.createQmlObject('import QtQuick 1.0; Rectangle {smooth: true}', adjuster, "dynamicBar");
+ bar.width = barWidth;
+ bar.height = firstBarHeight+(i/maxBars)*(adjuster.height*0.8-firstBarHeight);
+ bar.radius = bar.width/2;
+ bar.x = (i-1)*(barWidthFactor*barWidth);
+ bar.y = adjuster.height/2 - bar.height/2;
+ bars[i-1] = bar;
+
+ //Calculate and store the colors
+ if (i < maxBars/2) {
+ colors[i-1] = Qt.rgba(1-i/(maxBars/2), 1, 1-i/(maxBars/2), i);
+ }
+ else {
+ colors[i-1] = Qt.rgba((i-(maxBars/2))/(maxBars/2), 1-((i-(maxBars/2))/(maxBars/2)), 0, i);
+ }
+ }
+}
+
+function destroyBars() {
+ for (var i = 0; i < maxBars; i++) {
+ bars[i].color = "transparent" //Colors must be set to transparent or otherwise the bars will stay appeared.
+ bars[i].destroy();
+ }
+}
+
+function fillBars(barNumber) {
+ //Set the color for the bars (transparent from the selected bar to the end).
+ for (var i = 0; i < maxBars; i++) {
+ if (i < barNumber) {
+ bars[i].color = colors[i];
+ }
+ else {
+ bars[i].color = "black";
+ }
+ }
+}
diff --git a/demos/mobile/guitartuner/src/mycomponents/images/big_a.png b/demos/mobile/guitartuner/src/mycomponents/images/big_a.png
new file mode 100644
index 00000000..3838e766
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/images/big_a.png
Binary files differ
diff --git a/demos/mobile/guitartuner/src/mycomponents/images/big_b.png b/demos/mobile/guitartuner/src/mycomponents/images/big_b.png
new file mode 100644
index 00000000..114b32d3
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/images/big_b.png
Binary files differ
diff --git a/demos/mobile/guitartuner/src/mycomponents/images/big_d.png b/demos/mobile/guitartuner/src/mycomponents/images/big_d.png
new file mode 100644
index 00000000..3ede9f0f
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/images/big_d.png
Binary files differ
diff --git a/demos/mobile/guitartuner/src/mycomponents/images/big_e.png b/demos/mobile/guitartuner/src/mycomponents/images/big_e.png
new file mode 100644
index 00000000..cc1f4885
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/images/big_e.png
Binary files differ
diff --git a/demos/mobile/guitartuner/src/mycomponents/images/big_g.png b/demos/mobile/guitartuner/src/mycomponents/images/big_g.png
new file mode 100644
index 00000000..804177b3
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/images/big_g.png
Binary files differ
diff --git a/demos/mobile/guitartuner/src/mycomponents/images/glowing_a.png b/demos/mobile/guitartuner/src/mycomponents/images/glowing_a.png
new file mode 100644
index 00000000..b6fd0e20
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/images/glowing_a.png
Binary files differ
diff --git a/demos/mobile/guitartuner/src/mycomponents/images/glowing_b.png b/demos/mobile/guitartuner/src/mycomponents/images/glowing_b.png
new file mode 100644
index 00000000..b5fa016a
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/images/glowing_b.png
Binary files differ
diff --git a/demos/mobile/guitartuner/src/mycomponents/images/glowing_d.png b/demos/mobile/guitartuner/src/mycomponents/images/glowing_d.png
new file mode 100644
index 00000000..32f1a291
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/images/glowing_d.png
Binary files differ
diff --git a/demos/mobile/guitartuner/src/mycomponents/images/glowing_e.png b/demos/mobile/guitartuner/src/mycomponents/images/glowing_e.png
new file mode 100644
index 00000000..4be9f2a7
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/images/glowing_e.png
Binary files differ
diff --git a/demos/mobile/guitartuner/src/mycomponents/images/glowing_g.png b/demos/mobile/guitartuner/src/mycomponents/images/glowing_g.png
new file mode 100644
index 00000000..4216d828
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/images/glowing_g.png
Binary files differ
diff --git a/demos/mobile/guitartuner/src/mycomponents/images/guitartuner_malli.png b/demos/mobile/guitartuner/src/mycomponents/images/guitartuner_malli.png
new file mode 100644
index 00000000..dbe3fc79
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/images/guitartuner_malli.png
Binary files differ
diff --git a/demos/mobile/guitartuner/src/mycomponents/images/guitartuner_skin.png b/demos/mobile/guitartuner/src/mycomponents/images/guitartuner_skin.png
new file mode 100644
index 00000000..5d53df9b
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/images/guitartuner_skin.png
Binary files differ
diff --git a/demos/mobile/guitartuner/src/mycomponents/images/lcdFrame.png b/demos/mobile/guitartuner/src/mycomponents/images/lcdFrame.png
new file mode 100644
index 00000000..ff8dffc6
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/images/lcdFrame.png
Binary files differ
diff --git a/demos/mobile/guitartuner/src/mycomponents/images/meterBG.png b/demos/mobile/guitartuner/src/mycomponents/images/meterBG.png
new file mode 100644
index 00000000..4046355c
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/images/meterBG.png
Binary files differ
diff --git a/demos/mobile/guitartuner/src/mycomponents/images/mute.png b/demos/mobile/guitartuner/src/mycomponents/images/mute.png
new file mode 100644
index 00000000..382e6047
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/images/mute.png
Binary files differ
diff --git a/demos/mobile/guitartuner/src/mycomponents/images/pointer.png b/demos/mobile/guitartuner/src/mycomponents/images/pointer.png
new file mode 100644
index 00000000..d0cb21b8
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/images/pointer.png
Binary files differ
diff --git a/demos/mobile/guitartuner/src/mycomponents/images/pointerShadow.png b/demos/mobile/guitartuner/src/mycomponents/images/pointerShadow.png
new file mode 100644
index 00000000..a7086391
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/images/pointerShadow.png
Binary files differ
diff --git a/demos/mobile/guitartuner/src/mycomponents/images/power.png b/demos/mobile/guitartuner/src/mycomponents/images/power.png
new file mode 100644
index 00000000..8ec0c5ce
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/images/power.png
Binary files differ
diff --git a/demos/mobile/guitartuner/src/mycomponents/images/quit.png b/demos/mobile/guitartuner/src/mycomponents/images/quit.png
new file mode 100644
index 00000000..2a9443ec
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/images/quit.png
Binary files differ
diff --git a/demos/mobile/guitartuner/src/mycomponents/images/sensitivity.png b/demos/mobile/guitartuner/src/mycomponents/images/sensitivity.png
new file mode 100644
index 00000000..c3d2ea31
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/images/sensitivity.png
Binary files differ
diff --git a/demos/mobile/guitartuner/src/mycomponents/images/tuner_a.png b/demos/mobile/guitartuner/src/mycomponents/images/tuner_a.png
new file mode 100644
index 00000000..a1823e59
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/images/tuner_a.png
Binary files differ
diff --git a/demos/mobile/guitartuner/src/mycomponents/images/tuner_a_on.png b/demos/mobile/guitartuner/src/mycomponents/images/tuner_a_on.png
new file mode 100644
index 00000000..7c78cbd8
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/images/tuner_a_on.png
Binary files differ
diff --git a/demos/mobile/guitartuner/src/mycomponents/images/tuner_auto.png b/demos/mobile/guitartuner/src/mycomponents/images/tuner_auto.png
new file mode 100644
index 00000000..b9e494bd
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/images/tuner_auto.png
Binary files differ
diff --git a/demos/mobile/guitartuner/src/mycomponents/images/tuner_auto_on.png b/demos/mobile/guitartuner/src/mycomponents/images/tuner_auto_on.png
new file mode 100644
index 00000000..d5608d85
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/images/tuner_auto_on.png
Binary files differ
diff --git a/demos/mobile/guitartuner/src/mycomponents/images/tuner_b.png b/demos/mobile/guitartuner/src/mycomponents/images/tuner_b.png
new file mode 100644
index 00000000..94977f87
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/images/tuner_b.png
Binary files differ
diff --git a/demos/mobile/guitartuner/src/mycomponents/images/tuner_b_on.png b/demos/mobile/guitartuner/src/mycomponents/images/tuner_b_on.png
new file mode 100644
index 00000000..78841dc0
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/images/tuner_b_on.png
Binary files differ
diff --git a/demos/mobile/guitartuner/src/mycomponents/images/tuner_d.png b/demos/mobile/guitartuner/src/mycomponents/images/tuner_d.png
new file mode 100644
index 00000000..293ee55a
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/images/tuner_d.png
Binary files differ
diff --git a/demos/mobile/guitartuner/src/mycomponents/images/tuner_d_on.png b/demos/mobile/guitartuner/src/mycomponents/images/tuner_d_on.png
new file mode 100644
index 00000000..705de41d
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/images/tuner_d_on.png
Binary files differ
diff --git a/demos/mobile/guitartuner/src/mycomponents/images/tuner_e.png b/demos/mobile/guitartuner/src/mycomponents/images/tuner_e.png
new file mode 100644
index 00000000..569d2c65
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/images/tuner_e.png
Binary files differ
diff --git a/demos/mobile/guitartuner/src/mycomponents/images/tuner_e_on.png b/demos/mobile/guitartuner/src/mycomponents/images/tuner_e_on.png
new file mode 100644
index 00000000..1342a914
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/images/tuner_e_on.png
Binary files differ
diff --git a/demos/mobile/guitartuner/src/mycomponents/images/tuner_g.png b/demos/mobile/guitartuner/src/mycomponents/images/tuner_g.png
new file mode 100644
index 00000000..a8f0de57
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/images/tuner_g.png
Binary files differ
diff --git a/demos/mobile/guitartuner/src/mycomponents/images/tuner_g_on.png b/demos/mobile/guitartuner/src/mycomponents/images/tuner_g_on.png
new file mode 100644
index 00000000..6fdca419
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/images/tuner_g_on.png
Binary files differ
diff --git a/demos/mobile/guitartuner/src/mycomponents/images/voicemode_off.png b/demos/mobile/guitartuner/src/mycomponents/images/voicemode_off.png
new file mode 100644
index 00000000..0701dd34
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/images/voicemode_off.png
Binary files differ
diff --git a/demos/mobile/guitartuner/src/mycomponents/images/voicemode_on.png b/demos/mobile/guitartuner/src/mycomponents/images/voicemode_on.png
new file mode 100644
index 00000000..986d589a
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/images/voicemode_on.png
Binary files differ
diff --git a/demos/mobile/guitartuner/src/mycomponents/images/volume.png b/demos/mobile/guitartuner/src/mycomponents/images/volume.png
new file mode 100644
index 00000000..46fdb7fa
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/images/volume.png
Binary files differ
diff --git a/demos/mobile/guitartuner/src/mycomponents/images/volume_off.png b/demos/mobile/guitartuner/src/mycomponents/images/volume_off.png
new file mode 100644
index 00000000..a97e4224
--- /dev/null
+++ b/demos/mobile/guitartuner/src/mycomponents/images/volume_off.png
Binary files differ
diff --git a/demos/mobile/guitartuner/src/voiceanalyzer.cpp b/demos/mobile/guitartuner/src/voiceanalyzer.cpp
new file mode 100644
index 00000000..5c179638
--- /dev/null
+++ b/demos/mobile/guitartuner/src/voiceanalyzer.cpp
@@ -0,0 +1,295 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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;
+}
diff --git a/demos/mobile/guitartuner/src/voiceanalyzer.h b/demos/mobile/guitartuner/src/voiceanalyzer.h
new file mode 100644
index 00000000..8957c2e9
--- /dev/null
+++ b/demos/mobile/guitartuner/src/voiceanalyzer.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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$
+**
+****************************************************************************/
+
+#ifndef VOICEANALYZER_H
+#define VOICEANALYZER_H
+
+#include <QObject>
+#include <QAudioFormat>
+#include <QDebug>
+#include <QtCore/qmath.h>
+#include <QtCore/qendian.h>
+#include <QVariant>
+
+#include "constants.h"
+#include "fastfouriertransformer.h"
+#include "math.h"
+
+class VoiceAnalyzer : public QIODevice
+{
+ Q_OBJECT
+public:
+ VoiceAnalyzer(const QAudioFormat &format, QObject *parent = 0);
+ qint64 readData(char *data, qint64 maxlen);
+ qint64 writeData(const char *data, qint64 maxlen);
+ void start(qreal frequency);
+ void stop();
+ qreal frequency();
+ int getMaximumVoiceDifference();
+ int getMaximumPrecisionPerNote();
+
+public slots:
+ void setCutOffPercentage(qreal cutoff);
+
+private:
+ const QAudioFormat m_format;
+ QList<qint16> m_samples;
+ int m_totalSampleCount;
+ int m_maximumVoiceDifference;
+
+ qint16 getValueInt16(const uchar *ptr);
+ int m_stepSize;
+ qreal m_frequency;
+ qint64 m_position;
+ FastFourierTransformer *m_fftHelper;
+ void analyzeVoice();
+signals:
+ void voiceDifference(QVariant frequency);
+ void correctFrequency();
+ void lowVoice();
+
+public slots:
+
+};
+
+
+#endif // VOICEANALYZER_H
diff --git a/demos/mobile/guitartuner/src/voicegenerator.cpp b/demos/mobile/guitartuner/src/voicegenerator.cpp
new file mode 100644
index 00000000..046f75ef
--- /dev/null
+++ b/demos/mobile/guitartuner/src/voicegenerator.cpp
@@ -0,0 +1,246 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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 "voicegenerator.h"
+
+const int BufferSizeMilliseconds = 100;
+
+VoiceGenerator::VoiceGenerator(const QAudioFormat &format,
+ qreal frequency, qreal amplitude,
+ QObject *parent) :
+ QIODevice(parent),
+ m_format(format),
+ m_amplitude(0.5)
+{
+ Q_ASSERT(m_format.sampleSize() % 8 == 0);
+ int sampleBytes = m_format.channels() * (m_format.sampleSize() / 8);
+ // + 1 to round up, just to be sure that all samples fit.
+ qint64 samplesInBuffer = m_format.sampleRate()
+ * BufferSizeMilliseconds / 1000 + 1;
+ qint64 length = samplesInBuffer * sampleBytes;
+ m_buffer.resize(length);
+ m_max_position = 0;
+ m_position = 0;
+ m_amplitude = amplitude;
+ setFrequency(frequency);
+}
+
+VoiceGenerator::~VoiceGenerator()
+{
+}
+
+/**
+ * Opens the parent QIODevice.
+ */
+void VoiceGenerator::start()
+{
+ open(QIODevice::ReadOnly);
+}
+
+/**
+ * Closes the parent QIODevice. Resets the m_position to zero.
+ */
+void VoiceGenerator::stop()
+{
+ close();
+ m_position = 0;
+}
+
+/**
+ * Sets the frequency to new frequency.
+ */
+void VoiceGenerator::setFrequency(qreal frequency)
+{
+ Q_ASSERT(1 / frequency < BufferSizeMilliseconds);
+ this->m_frequency = frequency;
+ refreshData();
+}
+
+/**
+ * Sets the amplitude for the voice.
+ */
+void VoiceGenerator::setAmplitude(qreal amplitude)
+{
+ Q_ASSERT(amplitude >= 0);
+ m_amplitude = amplitude;
+ refreshData();
+}
+
+/**
+ * Returns the current frequency.
+ */
+qreal VoiceGenerator::frequency()
+{
+ return m_frequency;
+}
+
+/**
+ * Generates voice data corresponding a sine voice with target frequency.
+ * The number of data generated is calculated
+ * and stored to m_max_position.
+ */
+void VoiceGenerator::refreshData()
+{
+ const int channelBytes = m_format.sampleSize() / 8;
+ const int sampleSize = m_format.channels() * channelBytes;
+ const qint64 voiceOscillationsInBuffer = BufferSizeMilliseconds
+ * m_frequency / 1000;
+ const qint64 voiceSamplesInBuffer = voiceOscillationsInBuffer
+ * m_format.sampleRate() / m_frequency;
+ m_max_position = voiceSamplesInBuffer * sampleSize;
+ qint64 dataGenerationLength = m_buffer.size();
+
+
+ Q_ASSERT(m_max_position % (sampleSize) == 0);
+ Q_ASSERT(dataGenerationLength <= m_buffer.size());
+
+ short *t = (short*)m_buffer.data();
+
+
+/*
+ int te ;
+ static float fpos = 0.0f;
+ //dataGenerationLength>>=1; // in words
+ for (int f=0; f<dataGenerationLength; f++) {
+ te = (short)((sinf(fpos))* (65536.0f/2.0f));
+ fpos += m_frequency/2000.0f;
+ t[f]= te;
+ };
+
+ m_amplitude = 1.0f; */
+ uchar *ptr = reinterpret_cast<uchar *>(m_buffer.data());
+ int sampleIndex = 0;
+ while (dataGenerationLength > 0) {
+ qreal realValue = 0;
+ if (sampleIndex < voiceSamplesInBuffer) {
+ realValue = m_amplitude
+ *qSin(2.0f * M_PI * m_frequency
+ * qreal(sampleIndex % m_format.sampleRate())
+ / m_format.sampleRate());
+ }
+ for (int i=0; i<m_format.channels(); ++i) {
+ setValue(ptr, realValue);
+ ptr += channelBytes;
+ dataGenerationLength -= channelBytes;
+ }
+ ++sampleIndex;
+ }
+}
+
+/**
+ * Stores the realValue into bytes pointed by ptr as an int value.
+ * Align-safe.
+ */
+void VoiceGenerator::setValue(uchar *ptr, qreal realValue) {
+ if (m_format.sampleSize() == 8)
+ {
+ quint8 value = 0;
+ if (m_format.sampleType() == QAudioFormat::UnSignedInt) {
+ value = static_cast<quint8>(
+ qRound((1.0 + realValue) / 2
+ * M_MAX_AMPLITUDE_8BIT_UNSIGNED));
+ } else if (m_format.sampleType() == QAudioFormat::SignedInt) {
+ value = static_cast<qint8>(
+ qRound(realValue
+ * M_MAX_AMPLITUDE_8BIT_SIGNED));
+ }
+ *reinterpret_cast<quint8*>(ptr) = value;
+ } else if (m_format.sampleSize() == 16) {
+ quint16 value = 0;
+ if (m_format.sampleType() == QAudioFormat::UnSignedInt) {
+ value = static_cast<quint16>(
+ qRound((1.0 + realValue) / 2
+ * M_MAX_AMPLITUDE_16BIT_UNSIGNED));
+ } else if (m_format.sampleType() == QAudioFormat::SignedInt) {
+ value = static_cast<qint16>(
+ qRound(realValue
+ * M_MAX_AMPLITUDE_16BIT_SIGNED));
+ }
+ if (m_format.byteOrder() == QAudioFormat::LittleEndian)
+ qToLittleEndian<qint16>(value, ptr);
+ else
+ qToBigEndian<qint16>(value, ptr);
+ }
+}
+
+qint64 VoiceGenerator::bytesAvailable() const
+{
+ return m_max_position + QIODevice::bytesAvailable();
+}
+
+/**
+ * Called by the QIODevice. Puts maxlen amount of voice
+ * samples into the data array.
+ */
+qint64 VoiceGenerator::readData(char *data, qint64 maxlen)
+{
+ qint64 total = 0;
+ qint64 chunk = 0;
+ while (total < maxlen) {
+ if (maxlen - total >= m_max_position - m_position) {
+ // the needed buffer is longer than the currently
+ // available buffer from m_position to the m_max_position
+ chunk = m_max_position - m_position;
+ memcpy(data, m_buffer.constData() + m_position, chunk);
+ m_position = 0;
+ }
+ else {
+ // we can copy the needed data directly, and the loop will end
+ chunk = maxlen - total;
+ memcpy(data, m_buffer.constData() + m_position, chunk);
+ m_position = (m_position + chunk) % m_max_position;
+ }
+ data += chunk;
+ total += chunk;
+ }
+ return total;
+}
+
+/**
+ * Empty implementation for writeData, since no data is provided
+ * for the VoiceGenerator class.
+ */
+qint64 VoiceGenerator::writeData(const char *data, qint64 maxlen)
+{
+ Q_UNUSED(data);
+ Q_UNUSED(maxlen);
+
+ return 0;
+}
diff --git a/demos/mobile/guitartuner/src/voicegenerator.h b/demos/mobile/guitartuner/src/voicegenerator.h
new file mode 100644
index 00000000..ed2292b7
--- /dev/null
+++ b/demos/mobile/guitartuner/src/voicegenerator.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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$
+**
+****************************************************************************/
+
+#ifndef VOICEGENERATOR_H
+#define VOICEGENERATOR_H
+
+#include <QIODevice>
+#include <QByteArray>
+#include <QAudioFormat>
+#include <QtCore/qmath.h>
+#include <QtCore/qendian.h>
+#include <QDebug>
+
+#include "constants.h"
+
+
+class VoiceGenerator : public QIODevice
+{
+ Q_OBJECT
+public:
+ VoiceGenerator(const QAudioFormat &format, qreal frequency, qreal amplitude, QObject *parent = 0);
+ ~VoiceGenerator();
+ void setFrequency(qreal frequency);
+ qint64 readData(char *data, qint64 maxlen);
+ qint64 writeData(const char *data, qint64 maxlen);
+ qint64 bytesAvailable() const;
+ qreal frequency();
+signals:
+
+public slots:
+ void setAmplitude(qreal amplitude);
+ void start();
+ void stop();
+
+private:
+ void setValue(uchar *ptr, qreal realValue);
+ void refreshData();
+ const QAudioFormat m_format;
+ // buffer to store the data
+ QByteArray m_buffer;
+ // current position in buffer
+ qint64 m_position;
+ // max position depends on the sample rate of format and the frequency of voice
+ qint64 m_max_position;
+ qreal m_amplitude;
+ qreal m_frequency;
+};
+
+#endif // VOICEGENERATOR_H