// tonalisa - software to look at overtone-structures
// Copyright (C) 2016 Dominik Schmidt-Philipp
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
//
import QtQuick 2.3
import QtQuick.Window 2.2
import QtQuick.Controls 1.2
import QtQuick.Dialogs 1.2
import QtQml 2.2
import art.freakaria.ton 1.0
Window {
id: root
visible: true
width:900;height:400
Rectangle {
anchors.fill:parent
color:Qt.hsla(.5,0,1,.5)
}
Item {
id:buffer
property var spectrumR0: []
property var spectrumR1: []
property var spectrumF0: [110, 1, 220, 0.5, 330, 0.25, 440, 0.125, 550, 0.1, 660, 0.1, 770, 0.1, 880, 0.1]
property var spectrumF1: []
property var gridTunedStep:9
property var gridPitch:440
property var gridLowest:27
property var gridHighest:8000
property var grid:[0, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100]
onGridChanged: {
keyboard.calculate_spectrum()
}
onSpectrumR0Changed:{spectrumR1 = spectrumR0 }
onSpectrumF0Changed:{
dissonanceCalculator.prepare_spectrum()
}
}
Item {
width: 300//Math.min(parent.width, parent.height)
height:300//Math.min(parent.width, parent.height)
SpiralView {
id:spiral
anchors.fill:parent
paintAxes:true
paintGrid:true
fBase:27.5 // sub kontra A
octaves:8
gridTunedStep:buffer.gridTunedStep
gridPitch:buffer.gridPitch
gridLowest:buffer.gridLowest
gridHighest:buffer.gridHighest
grid:buffer.grid
peaks:buffer.spectrumF0
}
}
Item {
x:300;y:300
width:600; height:100
Keyboard {
id:keyboard
transpose:-2
inSpectrum:buffer.spectrumR0
onInSpectrumChanged: { calculate_spectrum() }
}
SpinBox {
id:keyTranspose
minimumValue: -5
maximumValue: 8
value:-2
onValueChanged: {
keyboard.transpose = value
keyboard.calculate_spectrum()
}
anchors.right:parent.right
}
}
Item {
x:0;y:300
width:300;height:100
Rectangle {
anchors.fill:parent
color:"#fff"
Column {
Row {
id:spiralDisplayOptions
spacing:5
CheckBox {
text:qsTr("Raster")
onCheckedChanged: { spiral.paintGrid=checked }
checked:true
}
CheckBox {
text:qsTr("Spirale")
onCheckedChanged: { spiral.paintAxes=checked }
checked:true
}
}
Row {
id:harmonicGenerator
spacing:5
SpinBox {
id:nPartials
onValueChanged: parent.update_spectrum()
minimumValue: 1
maximumValue: 81
}
CheckBox {
id:filterEven
text:qsTr("nur ungerade Teiltöne")
onCheckedChanged:parent.update_spectrum()
}
SpinBox {
id:inharmonicity
onValueChanged: parent.update_spectrum()
minimumValue:-999
maximumValue:999
value:0
}
function update_spectrum() {
var y=[]
var log2=Math.log(2)
for(var i=1;i<=nPartials.value;i++) {
if(filterEven.checked && ((i%2)==0)) continue;
y.push(Math.pow(2+(inharmonicity.value/1000),Math.log(i)/log2))
//y.push(i)
y.push(1/i)
}
buffer.spectrumR0 = y
}
}
Row {
id:gridGenerator
spacing:5
Text { text:qsTr("Raster: von") }
TextInput {
text:"27"
onEditingFinished:{buffer.gridLowest = text }
validator: IntValidator{bottom:0; top:10000}
selectByMouse:true
}
Text { text:qsTr("bis") }
TextInput {
text:"8000"
onEditingFinished:{buffer.gridHighest= text }
validator: IntValidator{bottom:0; top:20000}
selectByMouse:true
}
Text { text:qsTr("Stimmton") }
TextInput {
text:"440"
onEditingFinished:{buffer.gridPitch = text }
validator: IntValidator{bottom:0; top:10000}
selectByMouse:true
}
}
}
Row {
id:mainMenu
spacing:1
anchors.bottom:parent.bottom
Button {
text:qsTr("AUDIO")
onClicked: { audioWindow.visible=true }
}
Button {
text:qsTr("CDC-5")
onClicked: { cdc5Window.visible=true }
}
Button {
text:qsTr("Skalen")
onClicked: { scaleWindow.visible=true }
}
Button {
text:qsTr("DB")
onClicked: { databaseWindow.visible=true }
width:50
}
}
}
}
Cartesian {
id: cartesian
x:300; y:0
height: 283; width: 600
fillColor:"#fff"
leftHz:55
rightHz:8000
logx:logToggle.checked
paintGrid:cartesianGridToggle.checked
paintFFT:audioWindow.visible
gridTunedStep:buffer.gridTunedStep
gridPitch:buffer.gridPitch
gridLowest:buffer.gridLowest
gridHighest:buffer.gridHighest
grid:buffer.grid
peaks:buffer.spectrumF0
fftData: audio.audio.spectrum
sampleRate:audio.audio.sampleRate
pointerFreq:spiral.pointerFreq
pointerAmp:spiral.pointerAmp
Rectangle {
width:4;height:4;radius:2;
color:"red";
x: parent.pointerPos.x
y: parent.pointerPos.y
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
function getFreqAmp(x,y){
var result = {"freq":0.0,"amp":0.0}
result.freq=(parent.rightHz-parent.leftHz)/parent.width * x + parent.leftHz
result.amp=Math.pow(10,y/parent.height*parent.dbFloor/20)
return result;
}
onPositionChanged: {
var pos = getFreqAmp(mouseX,mouseY);
spiral.pointerFreq = pos.freq
spiral.pointerAmp = pos.amp
}
}
}
Item {
id:cartesianOptions
width:600;height:20
x:300;y:283
Row {
spacing:5
CheckBox{
id:logToggle
text:qsTr("logarithmische Achse")
}
CheckBox {
id:cartesianGridToggle
text:qsTr("Raster")
checked:true
}
}
Item {
anchors.right:parent.right
width:120; height:17
Row {
spacing:5
Text {text:qsTr("zeige")}
TextInput {
text:"55"
onEditingFinished:{cartesian.leftHz = text }
validator: IntValidator{bottom:0; top:10000}
selectByMouse:true
focus:true
}
Text { text:qsTr("bis") }
TextInput {
text:"8000"
onEditingFinished:{cartesian.rightHz = text }
validator: IntValidator{bottom:81; top:20000}
selectByMouse:true
focus:true
}
Text { text:qsTr("Hz") }
}
}
}
Window {
id:scaleWindow
title:qsTr("Skalen")
visible:true
width:170;height:400
ScaleBrowser {
id:scales
anchors.fill:parent
}
}
Window {
id:audioWindow
title:qsTr("Audio Analyse")
visible:false
width:700;height:200
// onVisibleChanged: {}
AudioSegment {
id:audio
anchors.fill:parent
}
}
Window {
id:databaseWindow
title:qsTr("Datenbank")
visible:false
width:200;height:300
SpectrumBrowser {
id:spectra
anchors.fill:parent
}
}
Window {
id:cdc5Window
title:qsTr("Dissonanz Berechnungen")
visible:false
width:600;height:300
property var grundton:440
onGrundtonChanged: { dissonanceCalculator.prepare_spectrum() }
Row {
anchors.bottom:parent.bottom
height:17
spacing:5
Text {
text:qsTr("Grundton "+buffer.spectrumF0[0]+"Hz | ")
}
Text {
text:qsTr("Maximal darstellbare Rauhigkeit")
}
TextInput {
text:"0.5"
onEditingFinished:{dissonanceCurve.maxDissonance = text }
validator: DoubleValidator{bottom:0.000001; top:20;decimals:5}
selectByMouse:true
focus:true
}
}
Dissonance {
id:dissonanceCalculator
function prepare_spectrum() {
if (cdc5Window.visible) {
var f=[];
var a=[];
for(var i=0;i