├── .gitignore ├── LICENSE.txt ├── README.md ├── doc ├── Interactive Demo │ ├── Demo Anleitung.pdf │ ├── Demo Manual.pdf │ ├── S2L Demo.s2l │ ├── Sound2Light Demo Deutsch.esf │ └── Sound2Light Demo English.esf ├── Sound2Light_Magic_Sheet_Example.esf ├── Sound2Light_Tool_Anleitung.pdf ├── Sound2Light_Tool_Manual_en.pdf ├── s2l_changelog.md └── screenshot_main_window.png └── src ├── AudioInputInterface.h ├── BPMDetector.cpp ├── BPMDetector.h ├── BPMOscControler.cpp ├── BPMOscControler.h ├── BPMTapDetector.cpp ├── BPMTapDetector.h ├── BasicFFTInterface.h ├── FFTAnalyzer.cpp ├── FFTAnalyzer.h ├── FFTRealWrapper.h ├── LICENSE.txt ├── MainController.cpp ├── MainController.h ├── MonoAudioBuffer.cpp ├── MonoAudioBuffer.h ├── OSCMapping.cpp ├── OSCMapping.h ├── OSCMessage.cpp ├── OSCMessage.h ├── OSCNetworkManager.cpp ├── OSCNetworkManager.h ├── OSCParser.cpp ├── OSCParser.h ├── QAudioInputWrapper.cpp ├── QAudioInputWrapper.h ├── QCircularBuffer.h ├── README.md ├── S2L.pro ├── ScaledSpectrum.cpp ├── ScaledSpectrum.h ├── TriggerFilter.cpp ├── TriggerFilter.h ├── TriggerGenerator.cpp ├── TriggerGenerator.h ├── TriggerGeneratorInterface.h ├── TriggerGuiController.cpp ├── TriggerGuiController.h ├── TriggerOscParameters.cpp ├── TriggerOscParameters.h ├── deployment.pri ├── ffft ├── Array.h ├── Array.hpp ├── DynArray.h ├── DynArray.hpp ├── FFTReal.h ├── FFTReal.hpp ├── FFTRealFixLen.h ├── FFTRealFixLen.hpp ├── FFTRealFixLenParam.h ├── FFTRealPassDirect.h ├── FFTRealPassDirect.hpp ├── FFTRealPassInverse.h ├── FFTRealPassInverse.hpp ├── FFTRealSelect.h ├── FFTRealSelect.hpp ├── FFTRealUseTrigo.h ├── FFTRealUseTrigo.hpp ├── OscSinCos.h ├── OscSinCos.hpp └── def.h ├── images.qrc ├── images ├── backgroundBlue.png ├── backgroundGray.png ├── edit.png ├── icons │ ├── etcicon.icns │ ├── etcicon.ico │ └── etclogo.png ├── maximize.png ├── minimize.png ├── pause.png ├── play.png └── trash_icon.png ├── main.cpp ├── qml.qrc ├── qml ├── AboutDialog.qml ├── BPMOscMessageDialog.qml ├── BPMOscMessagesCobaltArea.qml ├── BPMOscMessagesCobaltOldArea.qml ├── BPMOscMessagesEosArea.qml ├── BPMOscMessagesOtherArea.qml ├── BPMSettings.qml ├── BandpassPreviewInSpectrum.qml ├── NoInputDeviceDialog.qml ├── NumericInput.qml ├── OscLogDialog.qml ├── OscMessageDialog.qml ├── OscMessagesCobaltArea.qml ├── OscMessagesCobaltOldArea.qml ├── OscMessagesColorSourceArea.qml ├── OscMessagesEosArea.qml ├── OscMessagesHog4Area.qml ├── PresetListDialog.qml ├── PresetsDialog.qml ├── SettingsDialog.qml ├── SpectrumPlot.qml ├── SpectrumWithControls.qml ├── TouchArea.qml ├── TriggerSettings.qml ├── TriggerSettingsArea.qml ├── TriggerSettingsLegend.qml ├── WavePlot.qml ├── main.qml ├── oscUtils.js └── style │ ├── CenterLabel.qml │ ├── DarkBlueStripedBackground.qml │ ├── DarkButton.qml │ ├── DarkCheckBox.qml │ ├── DarkComboBox.qml │ ├── DarkRadioButton.qml │ ├── DarkSpinBox.qml │ ├── DarkSplitView.qml │ ├── DarkTabView.qml │ ├── DarkTextField.qml │ ├── GreyText.qml │ ├── NumBlockButton.qml │ └── SliderWithIndicator.qml ├── sound2light_installer_data_windows.zip ├── utils.h └── versionInfo.h /.gitignore: -------------------------------------------------------------------------------- 1 | # C++ objects and libs 2 | 3 | *.slo 4 | *.lo 5 | *.o 6 | *.a 7 | *.la 8 | *.lai 9 | *.so 10 | *.dll 11 | *.dylib 12 | 13 | # Qt-es 14 | 15 | /.qmake.cache 16 | /.qmake.stash 17 | *.pro.user 18 | *.pro.user.* 19 | *.qbs.user 20 | *.qbs.user.* 21 | *.moc 22 | moc_*.cpp 23 | qrc_*.cpp 24 | ui_*.h 25 | Makefile* 26 | *-build-* 27 | 28 | # QtCreator 29 | 30 | *.autosave 31 | build-* 32 | 33 | #QtCtreator Qml 34 | *.qmlproject.user 35 | *.qmlproject.user.* 36 | 37 | .DS_Store 38 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Electronic Theatre Controls, Inc., http://www.etcconnect.com 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Sound2Light Tool 2 | 3 | The Sound2Light tool converts live audio signals to trigger events that can be sent as OSC messages. It can reproduce the sound-to-light function of the NT/NTX consoles with systems of the Eos-, Cobalt- and ColorSource-family. It can also be remotely controlled by OSC. 4 | 5 | ## About this ETCLabs Project 6 | The Sound2Light Tool is open-source software designed to interact with Electronic Theatre Controls products. This is not official ETC software. 7 | ETC Support is not familiar with this software and will not be able to assist if issues arise. 8 | 9 | We also welcome pull requests for bug fixes and feature additions. 10 | 11 | # Download 12 | 13 | The current release for Windows and Mac is available here: [Download](https://github.com/ElectronicTheatreControlsLabs/Sound2Light/releases) 14 | 15 | The manual can be found here: [Manual](https://github.com/ElectronicTheatreControlsLabs/Sound2Light/blob/master/doc/Sound2Light_Tool_Manual_en.pdf) 16 | 17 | # Screenshot 18 | 19 | ![screenshot](https://github.com/ElectronicTheatreControlsLabs/Sound2Light/blob/master/doc/screenshot_main_window.png) 20 | -------------------------------------------------------------------------------- /doc/Interactive Demo/Demo Anleitung.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ETCLabs/Sound2Light/b5c5cac01232a4b9bf8c8cc12364792e1b7fe947/doc/Interactive Demo/Demo Anleitung.pdf -------------------------------------------------------------------------------- /doc/Interactive Demo/Demo Manual.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ETCLabs/Sound2Light/b5c5cac01232a4b9bf8c8cc12364792e1b7fe947/doc/Interactive Demo/Demo Manual.pdf -------------------------------------------------------------------------------- /doc/Interactive Demo/S2L Demo.s2l: -------------------------------------------------------------------------------- 1 | [General] 2 | agcEnabled=true 3 | changedAt=Mi. Sep. 14 18:52:14 2016 4 | consoleType=Eos 5 | dbConversion=false 6 | fftCompression=1 7 | fftGain=3.4759669303894043 8 | formatVersion=1 9 | lowSoloMode=false 10 | version=0.0.2.1.0.6 11 | waveformVisible=true 12 | 13 | [bass] 14 | maxHold=0 15 | midFreq=118 16 | offDelay=0 17 | onDelay=0 18 | osc\labelText=Cue 1 19 | osc\levelMessage= 20 | osc\maxLevelValue=1 21 | osc\minLevelValue=0 22 | osc\offMessage=/eos/user//cue/1/2/fire 23 | osc\onMessage=/eos/user//cue/1/1/fire 24 | threshold=0.17600537909836067 25 | width=0.10000000000000001 26 | 27 | [bpm] 28 | Active=true 29 | Min=0 30 | osc\0=/eos/user/0/newcmd/Effect/1/BPM//# 31 | osc\count=1 32 | 33 | [envelope] 34 | maxHold=0 35 | midFreq=100 36 | offDelay=2 37 | onDelay=0.5 38 | osc\labelText= 39 | osc\levelMessage= 40 | osc\maxLevelValue=1 41 | osc\minLevelValue=0 42 | osc\offMessage= 43 | osc\onMessage= 44 | threshold=0.10000000000000001 45 | width=0.050000000000000003 46 | 47 | [hiMid] 48 | maxHold=0 49 | midFreq=1621 50 | offDelay=0 51 | onDelay=0 52 | osc\labelText=Channel 1 53 | osc\levelMessage="/eos/user//chan/1=" 54 | osc\maxLevelValue=100 55 | osc\minLevelValue=0 56 | osc\offMessage= 57 | osc\onMessage= 58 | threshold=0.49431139002732238 59 | width=0.10000000000000001 60 | 61 | [high] 62 | maxHold=0 63 | midFreq=5000 64 | offDelay=0 65 | onDelay=0 66 | osc\labelText= 67 | osc\levelMessage= 68 | osc\maxLevelValue=1 69 | osc\minLevelValue=0 70 | osc\offMessage= 71 | osc\onMessage= 72 | threshold=0.5 73 | width=0.10000000000000001 74 | 75 | [loMid] 76 | maxHold=0 77 | midFreq=976 78 | offDelay=0 79 | onDelay=0 80 | osc\labelText=Bump 1 81 | osc\levelMessage= 82 | osc\maxLevelValue=1 83 | osc\minLevelValue=0 84 | osc\offMessage="/eos/user//sub/1/fire=0.0" 85 | osc\onMessage="/eos/user//sub/1/fire=1.0" 86 | threshold=0.30137892759562845 87 | width=0.20000000000000001 88 | 89 | [silence] 90 | maxHold=0 91 | midFreq=100 92 | offDelay=0 93 | onDelay=3 94 | osc\labelText=Macro 2 95 | osc\levelMessage= 96 | osc\maxLevelValue=1 97 | osc\minLevelValue=0 98 | osc\offMessage= 99 | osc\onMessage="/eos/user//macro/fire=2" 100 | threshold=0.78703703703703698 101 | width=0.050000000000000003 102 | -------------------------------------------------------------------------------- /doc/Interactive Demo/Sound2Light Demo Deutsch.esf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ETCLabs/Sound2Light/b5c5cac01232a4b9bf8c8cc12364792e1b7fe947/doc/Interactive Demo/Sound2Light Demo Deutsch.esf -------------------------------------------------------------------------------- /doc/Interactive Demo/Sound2Light Demo English.esf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ETCLabs/Sound2Light/b5c5cac01232a4b9bf8c8cc12364792e1b7fe947/doc/Interactive Demo/Sound2Light Demo English.esf -------------------------------------------------------------------------------- /doc/Sound2Light_Magic_Sheet_Example.esf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ETCLabs/Sound2Light/b5c5cac01232a4b9bf8c8cc12364792e1b7fe947/doc/Sound2Light_Magic_Sheet_Example.esf -------------------------------------------------------------------------------- /doc/Sound2Light_Tool_Anleitung.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ETCLabs/Sound2Light/b5c5cac01232a4b9bf8c8cc12364792e1b7fe947/doc/Sound2Light_Tool_Anleitung.pdf -------------------------------------------------------------------------------- /doc/Sound2Light_Tool_Manual_en.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ETCLabs/Sound2Light/b5c5cac01232a4b9bf8c8cc12364792e1b7fe947/doc/Sound2Light_Tool_Manual_en.pdf -------------------------------------------------------------------------------- /doc/screenshot_main_window.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ETCLabs/Sound2Light/b5c5cac01232a4b9bf8c8cc12364792e1b7fe947/doc/screenshot_main_window.png -------------------------------------------------------------------------------- /src/AudioInputInterface.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Electronic Theatre Controls, Inc., http://www.etcconnect.com 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #ifndef AUDIOINPUTINTERFACE_H 22 | #define AUDIOINPUTINTERFACE_H 23 | 24 | #include "MonoAudioBuffer.h" 25 | 26 | #include 27 | #include 28 | 29 | // An interface for an audio input. 30 | // The input device can be selected 31 | // and the volume can be changed. 32 | // Calls putSamples() of MonoAudioBuffer when new data is available. 33 | 34 | class AudioInputInterface 35 | { 36 | 37 | public: 38 | explicit AudioInputInterface(MonoAudioBuffer* buffer) : m_buffer(buffer) {} 39 | virtual ~AudioInputInterface() {} 40 | 41 | // returns a list of the names of all available input devices 42 | virtual QStringList getAvailableInputs() const = 0; 43 | 44 | // returns the name of the default input device 45 | // returns an empty string if there are no input devices 46 | virtual QString getDefaultInputName() const = 0; 47 | 48 | // returns the name of the currently used input device 49 | virtual QString getActiveInputName() const = 0; 50 | // changes the used input device by its name 51 | virtual void setInputByName(const QString& name) = 0; 52 | 53 | // returns the volume of the input device [0...1] 54 | virtual qreal getVolume() const = 0; 55 | // sets the volume of the input device [0...1] 56 | virtual void setVolume(const qreal& value) = 0; 57 | 58 | protected: 59 | MonoAudioBuffer* m_buffer; // a buffer storing the last audio samples 60 | }; 61 | 62 | 63 | #endif // AUDIOINPUTINTERFACE_H 64 | -------------------------------------------------------------------------------- /src/BPMOscControler.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Electronic Theatre Controls, Inc., http://www.etcconnect.com 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #include "BPMOscControler.h" 22 | 23 | BPMOscControler::BPMOscControler(OSCNetworkManager &osc) : 24 | m_bpmMute(false) 25 | , m_osc(osc) 26 | , m_oscCommands() 27 | { 28 | } 29 | 30 | void BPMOscControler::setBPMMute(bool mute) 31 | { 32 | m_bpmMute = mute; 33 | 34 | m_osc.sendMessage("/s2l/out/bpm/mute", (m_bpmMute ? "1" : "0"), true); 35 | } 36 | 37 | void BPMOscControler::toggleBPMMute() 38 | { 39 | m_bpmMute = !m_bpmMute; 40 | m_osc.sendMessage("/s2l/out/bpm/mute", (m_bpmMute ? "1" : "0"), true); 41 | } 42 | 43 | // Restore the commands from e.g. a preset or whatever else 44 | void BPMOscControler::restore(QSettings& settings) 45 | { 46 | int count = settings.value("bpm/osc/count").toInt(); 47 | 48 | m_oscCommands.clear(); 49 | for (int index = 0; index < count; ++index) { 50 | QString command = settings.value("bpm/osc/" + QString::number(index)).toString(); 51 | m_oscCommands.append(command); 52 | } 53 | } 54 | 55 | // Save the commands for e.g. a preset 56 | void BPMOscControler::save(QSettings& settings) { 57 | // Save the number of commands 58 | settings.setValue("bpm/osc/count", m_oscCommands.size()); 59 | 60 | // Store each command under the key "bpm/osc/*index*" 61 | for (int index = 0; index < m_oscCommands.size(); ++index) { 62 | settings.setValue("bpm/osc/" + QString::number(index), m_oscCommands[index]); 63 | } 64 | } 65 | 66 | // Called by the bpm detector to make the controller send the new bpm to the clients 67 | void BPMOscControler::transmitBPM(float bpm) 68 | { 69 | // Don't transmit if mute is engaged 70 | if (m_bpmMute) return; 71 | 72 | // Send user specified commands 73 | 74 | for (QString& command : m_oscCommands) { 75 | //Continue if the command is invalid, e.g. because it doesn't have a BPM 76 | if (command.indexOf("", "0" + QString::number(qRound(bpm))); 84 | message.replace("", "0" + QString::number(qRound(bpm))); 85 | message.replace("", "0" + QString::number(qRound(bpm*0.5f))); 86 | message.replace("", "0" + QString::number(qRound(bpm*0.25f))); 87 | message.replace("", "0" + QString::number(qRound(bpm*0.125f))); 88 | message.replace("", "0" + QString::number(qRound(bpm*0.0625f))); 89 | message.replace("", "0" + QString::number(qRound(bpm*0.03125f))); 90 | message.replace("", "0" + QString::number(qRound(bpm*2))); 91 | message.replace("", "0" + QString::number(qRound(bpm*4))); 92 | message.replace("", "0" + QString::number(qRound(bpm*8))); 93 | message.replace("", "0" + QString::number(qRound(bpm*16))); 94 | message.replace("", "0" + QString::number(qRound(bpm*32))); 95 | m_osc.sendMessage(message); 96 | } 97 | 98 | // Send information command 99 | m_osc.sendMessage("/s2l/out/bpm=" + QString::number(qRound(bpm)), true); 100 | } 101 | -------------------------------------------------------------------------------- /src/BPMOscControler.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Electronic Theatre Controls, Inc., http://www.etcconnect.com 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #ifndef BPMOSCCONTROLER_H 22 | #define BPMOSCCONTROLER_H 23 | 24 | #include "OSCNetworkManager.h" 25 | #include 26 | 27 | class BPMOscControler 28 | { 29 | public: 30 | BPMOscControler(OSCNetworkManager& osc); 31 | 32 | // Getter/Setter for mute 33 | bool getBPMMute() { return m_bpmMute; } 34 | void setBPMMute(bool mute); 35 | void toggleBPMMute(); 36 | 37 | // Called by the bpm detector to make the controller send the new bpm to the clients 38 | void transmitBPM(float bpm); 39 | 40 | // Restores the state from e.g. a preset 41 | void restore(QSettings& settings); 42 | 43 | // Save the commands for e.g. a preset 44 | void save(QSettings& settings); 45 | 46 | // --------------------------------------- GUI Functions ----------------------------------------------- 47 | // Returns the commands 48 | QStringList getCommands() { return m_oscCommands; } 49 | 50 | // Sets the command at the given index 51 | void setCommands(QStringList commands) { 52 | m_oscCommands = QStringList(commands); 53 | } 54 | 55 | 56 | protected: 57 | bool m_bpmMute; // If the bpm osc is muted 58 | OSCNetworkManager& m_osc; // The network manager to send network signals thorugh 59 | QStringList m_oscCommands; // The osc messages to be sent on a tempo changed. Delivered as finished strings with the (, etc. for fractions from 1/4 to 4) qualifier to be changed. The message is generated in the qml because thats the way tim did it with the other osc messages 60 | }; 61 | 62 | #endif // BPMOSCCONTROLER_H 63 | -------------------------------------------------------------------------------- /src/BPMTapDetector.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Electronic Theatre Controls, Inc., http://www.etcconnect.com 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #include "BPMTapDetector.h" 22 | 23 | BPMTapDetector::BPMTapDetector(BPMOscControler *osc) : 24 | m_bpm(0) 25 | , m_lastBeats(BpmConstants::HISTORY_LENGTH) 26 | , m_lastValue(0) 27 | , m_minBPM(75) 28 | , m_oscController(osc) 29 | { 30 | m_startTime = HighResTime::now(); 31 | } 32 | 33 | inline float bpmInRange(float bpm, const int minBPM) { 34 | if (minBPM > 0) { 35 | while (bpm < minBPM && bpm != 0) { 36 | bpm *= 2; 37 | } 38 | while (bpm >= minBPM*2) { 39 | bpm /= 2; 40 | } 41 | } 42 | 43 | while (bpm < BpmConstants::GLOBAL_MIN_BPM && bpm != 0) { 44 | bpm *= 2; 45 | } 46 | while (bpm >= BpmConstants::GLOBAL_MAX_BPM) { 47 | bpm /= 2; 48 | } 49 | 50 | return bpm; 51 | } 52 | 53 | // Sets the minimum bpm of the range, and rounds it to one of the allowed values 54 | void BPMTapDetector::setMinBPM(int value) { 55 | if (value == 0) { 56 | m_minBPM = 0; 57 | } else if (value < 63) { 58 | m_minBPM = 50; 59 | } else if (value < 88) { 60 | m_minBPM = 75; 61 | } else if (value < 125) { 62 | m_minBPM = 100; 63 | } else { 64 | m_minBPM = 150; 65 | } 66 | m_bpm = bpmInRange(m_bpm, m_minBPM); 67 | } 68 | 69 | void BPMTapDetector::triggerBeat() { 70 | double beatTime = HighResTime::elapsedSecSince(m_startTime); 71 | // check if history should be discarded: 72 | if (!m_lastBeats.isEmpty()) { 73 | double secSinceLast = beatTime - m_lastBeats.last(); 74 | if (secSinceLast > 60. / BpmConstants::MIN_BPM) { 75 | // yes last beat is too old -> discard history: 76 | m_lastBeats.clear(); 77 | } 78 | } 79 | m_lastBeats.append(beatTime); 80 | 81 | // check if there are at least 2 values: 82 | if (m_lastBeats.size() < 2) return; 83 | 84 | double sumBeatDuration = 0; // in sec 85 | for (int i=1; itransmitBPM(m_bpm); 92 | } 93 | 94 | void BPMTapDetector::reset() { 95 | m_startTime = HighResTime::now(); 96 | m_lastValue = 0; 97 | m_lastBeats.clear(); 98 | m_bpm = 0; 99 | } 100 | -------------------------------------------------------------------------------- /src/BPMTapDetector.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Electronic Theatre Controls, Inc., http://www.etcconnect.com 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | // Copied largely from Luminosus. Edited to work with sound2light by Hendrik Noeller 22 | // (edits mainly involved removing luminosus block and gui functions and adding 23 | // s2l gui functions) 24 | 25 | #ifndef BPMTAPDETECTOR_H 26 | #define BPMTAPDETECTOR_H 27 | 28 | #include "utils.h" 29 | 30 | #include "QCircularBuffer.h" 31 | 32 | #include "BPMOscControler.h" 33 | 34 | /** 35 | * @brief The BpmConstants namespace contains all constants used in BpmTapDetection 36 | */ 37 | namespace BpmConstants { 38 | /** 39 | * @brief HISTORY_LENGTH is the length of the beat duration history to evaluate 40 | */ 41 | static const int HISTORY_LENGTH = 3; 42 | 43 | static const int MIN_BPM = 30; // for deciding when a beat is too old 44 | 45 | static const int GLOBAL_MIN_BPM = 50; 46 | static const int GLOBAL_MAX_BPM = 300; 47 | } 48 | 49 | 50 | class BPMTapDetector 51 | { 52 | 53 | public: 54 | 55 | explicit BPMTapDetector(BPMOscControler* osc); 56 | 57 | void triggerBeat(); // "Tap" impulse 58 | 59 | void reset(); // Reset all information 60 | 61 | bool hasBpm() { return m_bpm != 0; } // Wether there is a value 62 | 63 | float getBpm() const { return m_bpm; } // Get the current bpm 64 | void setBpm(float value) { m_bpm = value; m_oscController->transmitBPM(m_bpm);} // Set the bpm (if a user enters a value by keypad) 65 | 66 | void setMinBPM(int value); // Sets the minimum bpm of the range 67 | 68 | int getMinBPM() { return m_minBPM; } // Returns the minium bpm of the range 69 | 70 | protected: 71 | /** 72 | * @brief m_bpm current detected BPM value 73 | */ 74 | float m_bpm; 75 | /** 76 | * @brief m_startTime stores the time when this object was created or rest 77 | */ 78 | HighResTime::time_point_t m_startTime; 79 | /** 80 | * @brief m_lastBeats stores the times of the last beats in seconds since start 81 | */ 82 | Qt3DCore::QCircularBuffer m_lastBeats; 83 | /** 84 | * @brief m_lastValue stores the last input value 85 | */ 86 | double m_lastValue; 87 | 88 | int m_minBPM; 89 | BPMOscControler* m_oscController; // the object responsible for handling osc output 90 | }; 91 | 92 | #endif // BPMTAPDETECTOR_H 93 | -------------------------------------------------------------------------------- /src/BasicFFTInterface.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Electronic Theatre Controls, Inc., http://www.etcconnect.com 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #ifndef BASICFFTINTERFACE_H 22 | #define BASICFFTINTERFACE_H 23 | 24 | // A very basic interface to a FFT implementation. 25 | class BasicFFTInterface 26 | { 27 | public: 28 | virtual ~BasicFFTInterface() {} 29 | 30 | // Calculates the FFT of a float array and writes the result to the output array. 31 | virtual void doFft(float* output, const float* input) = 0; 32 | }; 33 | 34 | #endif // BASICFFTINTERFACE_H 35 | -------------------------------------------------------------------------------- /src/FFTAnalyzer.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Electronic Theatre Controls, Inc., http://www.etcconnect.com 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #include "FFTAnalyzer.h" 22 | 23 | #include "FFTRealWrapper.h" 24 | 25 | FFTAnalyzer::FFTAnalyzer(const MonoAudioBuffer& buffer,QVector& triggerContainer) 26 | : m_inputBuffer(buffer) 27 | , m_triggerContainer(triggerContainer) 28 | , m_fft(0) 29 | , m_buffer(NUM_SAMPLES) 30 | , m_window(NUM_SAMPLES) 31 | , m_fftOutput(NUM_SAMPLES) 32 | , m_linearSpectrum(NUM_SAMPLES / 2) 33 | , m_scaledSpectrum(SCALED_SPECTRUM_BASE_FREQ, SCALED_SPECTRUM_LENGTH) 34 | { 35 | m_fft = (BasicFFTInterface*) new FFTRealWrapper(); 36 | calculateWindow(); 37 | } 38 | 39 | FFTAnalyzer::~FFTAnalyzer() 40 | { 41 | delete m_fft; 42 | } 43 | 44 | void FFTAnalyzer::calculateWindow() 45 | { 46 | // Hann Window function 47 | // used to prepare the PCM data for FFT 48 | for (int i=0; idoFft(m_fftOutput.data(), m_buffer.constData()); 63 | 64 | // convert complex output of FFT to real numbers: 65 | for (int i=0; i < NUM_SAMPLES / 2; ++i) { 66 | const float real = m_fftOutput[i]; 67 | const float img = m_fftOutput[NUM_SAMPLES / 2 + i]; 68 | const float energy = qSqrt(real*real + img*img) / 10; 69 | m_linearSpectrum[i] = energy; 70 | } 71 | // first value is 0Hz / DC value and is not usefull: 72 | m_linearSpectrum[0] = 0.0; 73 | 74 | // give linear spectrum to ScaledSpectrum object to be scalled: 75 | m_scaledSpectrum.updateWithLinearSpectrum(m_linearSpectrum); 76 | 77 | // next element in processing chain: TriggerGenerators 78 | bool triggered = false; 79 | for (int i=0; iisBandpass()) { 82 | bool active = trigger->checkForTrigger(m_scaledSpectrum, lowSoloMode && triggered); 83 | triggered = triggered || active; 84 | } else { 85 | trigger->checkForTrigger(m_scaledSpectrum, false); 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/FFTAnalyzer.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Electronic Theatre Controls, Inc., http://www.etcconnect.com 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #ifndef FFTWRAPPER_H 22 | #define FFTWRAPPER_H 23 | 24 | #include "BasicFFTInterface.h" 25 | #include "ScaledSpectrum.h" 26 | #include "TriggerGeneratorInterface.h" 27 | #include "MonoAudioBuffer.h" 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | // the number of samples used for FFT expressed as an exponent of 2 35 | static const int NUM_SAMPLES_EXPONENT = 12; 36 | 37 | // the real number of samples calculated from NUM_SAMPLES_EXPONENT 38 | static const int NUM_SAMPLES = qPow(2, NUM_SAMPLES_EXPONENT); 39 | 40 | // maximum absolute value in the result of the FFT 41 | // estimated from previous tests (exponent/samples: max value): 42 | // 11/2048: 51, 12/4096: 96, 13/8192: 195, 14/16384: 350 43 | static const int MAX_FFT_VALUE = 96; 44 | 45 | // number of frequency bins in the resulting ScaledSpectrum 46 | static const int SCALED_SPECTRUM_LENGTH = 200; 47 | 48 | // base frequency of the ScaledSpectrum in Hz 49 | static const int SCALED_SPECTRUM_BASE_FREQ = 20; // ms 50 | 51 | // A class to prepare the content of an audio buffer for FFT, 52 | // calculate the FFT and create a ScaledSpectrum of the results. 53 | // Calls checkForTrigger() of a TriggerGeneratorContainer object when a new FFT is done. 54 | class FFTAnalyzer 55 | { 56 | 57 | public: 58 | explicit FFTAnalyzer(const MonoAudioBuffer& buffer, QVector& m_triggerContainer); 59 | ~FFTAnalyzer(); 60 | 61 | // calculates the FFT based on the data in the inputBuffer and updates the ScaledSpectrum 62 | // - usually called periodically 44 times per second 63 | void calculateFFT(bool lowSoloMode); 64 | 65 | // returns the normalized spectrum of the ScaledSpectrum 66 | const QVector& getNormalizedSpectrum() const { return m_scaledSpectrum.getNormalizedSpectrum(); } 67 | 68 | // returns a const ScaledSpectrum reference to read the last FFT results 69 | const ScaledSpectrum& getScaledSpectrum() const { return m_scaledSpectrum; } 70 | 71 | // returns a modifiable ScaledSpectrum reference to change its parameters 72 | ScaledSpectrum& getScaledSpectrum() { return m_scaledSpectrum; } 73 | 74 | protected: 75 | // calculates a Hann Window for FFT and saves it to m_window 76 | void calculateWindow(); 77 | 78 | const MonoAudioBuffer& m_inputBuffer; // buffer that stores the audio samples 79 | QVector& m_triggerContainer; // list of all controlled triggerGenerators 80 | BasicFFTInterface* m_fft; // FFT implementation 81 | QVector m_buffer; // buffer for prepared data (intermediate result) 82 | QVector m_window; // array with window data 83 | QVector m_fftOutput; // buffer containing the FFT output (intermediate result) 84 | QVector m_linearSpectrum; // buffer containing the non-scaled spectrum data (intermediate result) 85 | ScaledSpectrum m_scaledSpectrum; // stores the scaled data of the spectrum 86 | }; 87 | 88 | #endif // FFTWRAPPER_H 89 | -------------------------------------------------------------------------------- /src/FFTRealWrapper.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Electronic Theatre Controls, Inc., http://www.etcconnect.com 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #ifndef FFTREALWRAPPER_H 22 | #define FFTREALWRAPPER_H 23 | 24 | #include "BasicFFTInterface.h" 25 | #include "ffft/FFTRealFixLen.h" 26 | 27 | // An Implementation of the BasicFFTInterface with FFTReal 28 | // see BasicFFTInterface.h for overridden functions 29 | // LENGTH_EXPONENT is the number of samples used expressed as an exponent of two 30 | 31 | template 32 | class FFTRealWrapper : public BasicFFTInterface 33 | { 34 | 35 | public: 36 | explicit FFTRealWrapper() { } 37 | 38 | void doFft(float *output, const float *input) override { m_fftreal.do_fft(output, input); } 39 | 40 | protected: 41 | ffft::FFTRealFixLen m_fftreal; 42 | }; 43 | 44 | #endif // FFTREALWRAPPER_H 45 | -------------------------------------------------------------------------------- /src/LICENSE.txt: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Electronic Theatre Controls, Inc., http://www.etcconnect.com 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /src/MonoAudioBuffer.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Electronic Theatre Controls, Inc., http://www.etcconnect.com 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #include "MonoAudioBuffer.h" 22 | 23 | #include "FFTAnalyzer.h" 24 | 25 | MonoAudioBuffer::MonoAudioBuffer(int capacity) 26 | : m_capacity(capacity) 27 | , m_buffer(capacity) 28 | , m_numPutSamples(0) 29 | { 30 | for (int i=0; i < m_buffer.capacity(); ++i) { 31 | m_buffer.push_back(0.0); 32 | } 33 | } 34 | 35 | void MonoAudioBuffer::putSamples(QVector& data, const int& channelCount) 36 | { 37 | // convert incoming mulitchannel audio to mono: 38 | convertToMonoInplace(data, channelCount); 39 | 40 | for (int i=0; i& data, const int& channelCount) const { 48 | // - assumes that data for two channels A and B looks like ABABABABAB... 49 | // - channels are average to get mono signal 50 | // - result will be written inplace and data object will be decreased in size 51 | switch (channelCount) { 52 | case 1: 53 | break; 54 | case 2: 55 | for (int i=0; i 27 | 28 | 29 | // A class that receives audio samples and buffers these with circular buffering. 30 | class MonoAudioBuffer 31 | { 32 | 33 | public: 34 | explicit MonoAudioBuffer(int capacity); 35 | 36 | // puts samples in the buffer 37 | // - usually called by an AudioInputInterface object 38 | void putSamples(QVector& data, const int& channelCount); 39 | 40 | // returns the value in the buffer at index i 41 | const qreal& at(int i) const { return m_buffer[i]; } 42 | 43 | // returns the number of samples that have ever been put in the buffer 44 | int64_t getNumPutSamples() const { return m_numPutSamples; } 45 | int getCapacity() const { return m_capacity; } 46 | 47 | protected: 48 | // Converts PCM data with multiple channels to mono by averaging all channels. 49 | // Result is saved inplace and data object will be resized. 50 | void convertToMonoInplace(QVector& data, const int& channelCount) const; 51 | 52 | const int m_capacity; // max capacity of the buffer, should be length of FFT 53 | Qt3DCore::QCircularBuffer m_buffer; // a circular buffer, removing the oldest elements when inserting new ones 54 | int64_t m_numPutSamples; // the number of samples that have ever been put into the buffer 55 | }; 56 | 57 | #endif // MONOAUDIOBUFFER_H 58 | -------------------------------------------------------------------------------- /src/OSCMapping.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Electronic Theatre Controls, Inc., http://www.etcconnect.com 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #ifndef OSCMAPPING_H 22 | #define OSCMAPPING_H 23 | 24 | #include "OSCMessage.h" 25 | 26 | #include 27 | 28 | 29 | // Forward declaration 30 | class MainController; 31 | 32 | 33 | // This class maps application specific OSC messages to function calls 34 | // and returns some information as feedback. 35 | class OSCMapping : public QObject 36 | { 37 | Q_OBJECT 38 | public: 39 | explicit OSCMapping(MainController* controller, QObject *parent = 0); 40 | 41 | public slots: 42 | 43 | // maps incoming messages to function calls 44 | void handleMessage(OSCMessage msg); 45 | 46 | // sends the current audio levels as OSC messages 47 | void sendLevelFeedback(); 48 | 49 | // sends the current state (Preset Name + Trigger Output) as OSC messages 50 | void sendCurrentState(); 51 | 52 | // returns if OSC input is enabled and if incoming messages will be handled 53 | bool getInputEnabled() const { return m_inputIsEnabled; } 54 | 55 | // enables or disables OSC input 56 | void setInputEnabled(bool value) { m_inputIsEnabled = value; } 57 | 58 | protected: 59 | MainController* m_controller; // pointer to MainController instance 60 | bool m_inputIsEnabled; // true if input is enabled and incoming messages will be handled 61 | }; 62 | 63 | #endif // OSCMAPPING_H 64 | -------------------------------------------------------------------------------- /src/OSCMessage.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Electronic Theatre Controls, Inc., http://www.etcconnect.com 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #ifndef OSCMESSAGE_H 22 | #define OSCMESSAGE_H 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | // This class represents an OSC Message. 30 | 31 | // currently supported argument types: 32 | // - bool (FALSE, TRUE) 33 | // - int (INT32, INT64, optional from STRING) 34 | // - double (FLOAT32, FLOAT64, optional from STRING) 35 | // - string (STRING) 36 | 37 | class OSCMessage 38 | { 39 | 40 | public: 41 | // creates an empty message 42 | OSCMessage(); 43 | 44 | // creates a message from the raw OSC packet data (without frame) 45 | OSCMessage(const QByteArray& data, bool convertNumberStrings = false); 46 | 47 | // sets the data from the raw OSC packet data (without frame) 48 | void setData(const QByteArray& data, bool convertNumberStrings = false); 49 | 50 | // returns if the message is valid and not emtpy 51 | bool isValid() const { return m_isValid; } 52 | 53 | // returns the path as a list of strings 54 | const QStringList& path() const { return m_path; } 55 | 56 | // returns a specific part of the path 57 | const QString& pathPart(int index) const; 58 | 59 | // returns if the path starts with a given string 60 | bool pathStartsWith(QString value) const; 61 | 62 | // returns the path as a single string 63 | const QString& pathString() const { return m_pathString; } 64 | 65 | // returns a the arguments as a vector of QVariants 66 | const QVector& arguments() const { return m_arguments; } 67 | 68 | // returns true if there are no arguments or if the first argument is true or 1 69 | bool isTrue(); 70 | 71 | // returns the value of the first argument if it exists and is a number, otherwise return 0.0 72 | qreal value(); 73 | 74 | // ------------- Debug ---------------------- 75 | 76 | // returns the arguments as a human readable string for debugging 77 | QString getArgumentsAsDebugString(); 78 | 79 | // prints the message in human readable form to QDebug 80 | // for debugging only 81 | void printToQDebug() const; 82 | 83 | private: 84 | // extracts the path string from the raw OSC packet data (without frame) 85 | static QString getPathFromMessage(const QByteArray& data); 86 | 87 | protected: 88 | QString m_pathString; // stores the path as a string 89 | QStringList m_path; // stores the path as a list of strings (separated at slashes) 90 | QVector m_arguments; // list of arguments as QVariants 91 | bool m_isValid; // true, if the message is valid (a path exists) 92 | }; 93 | 94 | #endif // OSCMESSAGE_H 95 | -------------------------------------------------------------------------------- /src/QAudioInputWrapper.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Electronic Theatre Controls, Inc., http://www.etcconnect.com 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #include "QAudioInputWrapper.h" 22 | 23 | #include "utils.h" 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include 31 | 32 | QAudioInputWrapper::QAudioInputWrapper(MonoAudioBuffer *buffer) 33 | : AudioInputInterface(buffer) 34 | , m_audioInput(0) 35 | , m_audioIODevice(0) 36 | { 37 | // Set up the desired format: 38 | // If the input device doesn't support this the nearest format will be used. 39 | m_desiredAudioFormat.setSampleRate(44100); 40 | m_desiredAudioFormat.setChannelCount(2); 41 | m_desiredAudioFormat.setSampleSize(16); 42 | m_desiredAudioFormat.setCodec("audio/pcm"); 43 | m_desiredAudioFormat.setByteOrder(QAudioFormat::LittleEndian); 44 | m_desiredAudioFormat.setSampleType(QAudioFormat::SignedInt); 45 | } 46 | 47 | QAudioInputWrapper::~QAudioInputWrapper() 48 | { 49 | // Close and delete previous input device: 50 | if (m_audioInput) { 51 | m_audioInput->stop(); 52 | } 53 | if (m_audioIODevice && m_audioIODevice->isOpen()) { 54 | m_audioIODevice->close(); 55 | } 56 | delete m_audioInput; 57 | } 58 | 59 | QStringList QAudioInputWrapper::getAvailableInputs() const 60 | { 61 | // get List of input device names from QList: 62 | QStringList deviceList; 63 | QList devices = QAudioDeviceInfo::availableDevices(QAudio::AudioInput); 64 | foreach(QAudioDeviceInfo device, devices) { 65 | deviceList.append(device.deviceName()); 66 | } 67 | return deviceList; 68 | } 69 | 70 | QString QAudioInputWrapper::getDefaultInputName() const 71 | { 72 | QStringList devices = getAvailableInputs(); 73 | // if there are no devices, return empty string: 74 | if (devices.size() <= 0) return ""; 75 | QString defaultInputName = QAudioDeviceInfo::defaultInputDevice().deviceName(); 76 | return defaultInputName; 77 | } 78 | 79 | void QAudioInputWrapper::setInputByName(const QString &inputName) 80 | { 81 | // Close and delete previous input device: 82 | if (m_audioInput) { 83 | m_audioInput->stop(); 84 | } 85 | if (m_audioIODevice && m_audioIODevice->isOpen()) { 86 | disconnect(m_audioIODevice, SIGNAL(readyRead()), this, SLOT(audioDataReady())); 87 | m_audioIODevice->close(); 88 | } 89 | delete m_audioInput; 90 | m_audioInput = 0; 91 | 92 | // Get device info of new input: 93 | QList devices = QAudioDeviceInfo::availableDevices(QAudio::AudioInput); 94 | QAudioDeviceInfo info = *devices.begin(); 95 | foreach(QAudioDeviceInfo device, devices) { 96 | if (device.deviceName() == inputName) { 97 | info = device; 98 | } 99 | } 100 | 101 | // check if desired format is supported: 102 | if (!info.isFormatSupported(m_desiredAudioFormat)) { 103 | qWarning() << "Default audio format not supported, trying to use the nearest."; 104 | m_actualAudioFormat = info.nearestFormat(m_desiredAudioFormat); 105 | } else { 106 | m_actualAudioFormat = m_desiredAudioFormat; 107 | } 108 | 109 | // create new input: 110 | m_activeInputName = inputName; 111 | m_audioInput = new QAudioInput(info, m_actualAudioFormat, this); 112 | m_audioInput->setVolume(1.0); 113 | m_audioIODevice = m_audioInput->start(); 114 | connect(m_audioIODevice, SIGNAL(readyRead()), this, SLOT(audioDataReady())); 115 | } 116 | 117 | qreal QAudioInputWrapper::getVolume() const 118 | { 119 | if (!m_audioInput) return 0.0; 120 | return m_audioInput->volume(); 121 | } 122 | 123 | void QAudioInputWrapper::setVolume(const qreal &value) 124 | { 125 | if (!m_audioInput) return; 126 | m_audioInput->setVolume(limit(0, value, 1)); 127 | } 128 | 129 | void QAudioInputWrapper::audioDataReady() 130 | { 131 | // read data from input as QByteArray: 132 | QByteArray data = m_audioIODevice->readAll(); 133 | const int bytesPerSample = m_actualAudioFormat.sampleSize() / 8; 134 | const std::size_t numSamples = data.size() / bytesPerSample; 135 | QVector realData(numSamples); 136 | const char *ptr = data.constData(); 137 | 138 | for (std::size_t i=0; i(ptr); 141 | // convert to real and scale down to range [-1.0, 1.0]: 142 | const qreal scaled = qreal(pcmSample) / 32768; 143 | realData[i] = scaled; 144 | ptr += bytesPerSample; 145 | } 146 | 147 | // Call MonoAudioBuffer as next element in processing chain: 148 | m_buffer->putSamples(realData, m_actualAudioFormat.channelCount()); 149 | } 150 | -------------------------------------------------------------------------------- /src/QAudioInputWrapper.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Electronic Theatre Controls, Inc., http://www.etcconnect.com 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #ifndef QAUDIOINPUTWRAPPER_H 22 | #define QAUDIOINPUTWRAPPER_H 23 | 24 | #include "AudioInputInterface.h" 25 | #include "MonoAudioBuffer.h" 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | 35 | // An AudioInputInterface implementation with QAudioInput 36 | // see AudioInputInterface.h for documentation of overridden functions 37 | class QAudioInputWrapper : public QObject, public AudioInputInterface 38 | { 39 | Q_OBJECT 40 | 41 | public: 42 | explicit QAudioInputWrapper(MonoAudioBuffer* m_buffer); 43 | ~QAudioInputWrapper() override; 44 | 45 | QStringList getAvailableInputs() const override; 46 | 47 | QString getDefaultInputName() const override; 48 | 49 | QString getActiveInputName() const override { return m_activeInputName; } 50 | void setInputByName(const QString& name) override; 51 | 52 | qreal getVolume() const override; 53 | void setVolume(const qreal& value) override; 54 | 55 | 56 | private slots: 57 | // Converts the incoming QByteArray to QVector 58 | // and scales down the values to [-1...1] 59 | // - called by Qt singal when audio data is ready 60 | void audioDataReady(); 61 | 62 | protected: 63 | QAudioFormat m_desiredAudioFormat; // the desired audio format, may not be available 64 | QAudioFormat m_actualAudioFormat; // the actual audio format used for recording 65 | QAudioInput* m_audioInput; // a pointer to the used audio input object 66 | QIODevice* m_audioIODevice; // a pointer to the stream like "device" used while recording 67 | QString m_activeInputName; // the name of the active audio input 68 | }; 69 | 70 | #endif // QAUDIOINPUTWRAPPER_H 71 | -------------------------------------------------------------------------------- /src/README.md: -------------------------------------------------------------------------------- 1 | # Sound2Light Tool 2 | 3 | The Sound2Light tool converts live audio signals to trigger events that can be sent as OSC messages. It can reproduce the sound-to-light function of the NT/NTX consoles with systems of the Eos-, Cobalt- and ColorSource-family. It can also be remotely controlled by OSC. 4 | 5 | ## About this ETCLabs Project 6 | The Sound2Light Tool is open-source software designed to interact with Electronic Theatre Controls products. This is not official ETC software. 7 | ETC Support is not familiar with this software and will not be able to assist if issues arise. 8 | 9 | We also welcome pull requests for bug fixes and feature additions. 10 | 11 | # Download 12 | 13 | The current release for Windows and Mac is available here: [Download](https://github.com/ElectronicTheatreControlsLabs/Sound2Light/releases) 14 | 15 | The manual can be found here: [Manual](https://github.com/ElectronicTheatreControlsLabs/Sound2Light/blob/master/doc/Sound2Light_Tool_Manual_en.pdf) 16 | 17 | # Screenshot 18 | 19 | ![screenshot](https://github.com/ElectronicTheatreControlsLabs/Sound2Light/blob/master/doc/screenshot_main_window.png) 20 | -------------------------------------------------------------------------------- /src/S2L.pro: -------------------------------------------------------------------------------- 1 | TARGET = s2l 2 | LANGUAGE = C++ 3 | 4 | TEMPLATE = app 5 | 6 | QT += qml quick multimedia quickwidgets network widgets 7 | 8 | CONFIG += c++11 thread 9 | 10 | QMAKE_CXXFLAGS += -Wall 11 | 12 | SOURCES += main.cpp \ 13 | FFTAnalyzer.cpp \ 14 | MainController.cpp \ 15 | MonoAudioBuffer.cpp \ 16 | QAudioInputWrapper.cpp \ 17 | ScaledSpectrum.cpp \ 18 | TriggerFilter.cpp \ 19 | OSCParser.cpp \ 20 | TriggerGenerator.cpp \ 21 | TriggerGuiController.cpp \ 22 | TriggerOscParameters.cpp \ 23 | OSCMessage.cpp \ 24 | OSCMapping.cpp \ 25 | OSCNetworkManager.cpp \ 26 | BPMDetector.cpp \ 27 | BPMOscControler.cpp \ 28 | BPMTapDetector.cpp 29 | 30 | RESOURCES += qml.qrc \ 31 | images.qrc 32 | 33 | # Additional import path used to resolve QML modules in Qt Creator's code model 34 | QML_IMPORT_PATH = 35 | 36 | # Default rules for deployment. 37 | # include(deployment.pri) 38 | 39 | HEADERS += \ 40 | ffft/Array.h \ 41 | ffft/Array.hpp \ 42 | ffft/def.h \ 43 | ffft/DynArray.h \ 44 | ffft/DynArray.hpp \ 45 | ffft/FFTReal.h \ 46 | ffft/FFTReal.hpp \ 47 | ffft/FFTRealFixLen.h \ 48 | ffft/FFTRealFixLen.hpp \ 49 | ffft/FFTRealFixLenParam.h \ 50 | ffft/FFTRealPassDirect.h \ 51 | ffft/FFTRealPassDirect.hpp \ 52 | ffft/FFTRealPassInverse.h \ 53 | ffft/FFTRealPassInverse.hpp \ 54 | ffft/FFTRealSelect.h \ 55 | ffft/FFTRealSelect.hpp \ 56 | ffft/FFTRealUseTrigo.h \ 57 | ffft/FFTRealUseTrigo.hpp \ 58 | ffft/OscSinCos.h \ 59 | ffft/OscSinCos.hpp \ 60 | AudioInputInterface.h \ 61 | BasicFFTInterface.h \ 62 | FFTAnalyzer.h \ 63 | FFTRealWrapper.h \ 64 | MainController.h \ 65 | MonoAudioBuffer.h \ 66 | QAudioInputWrapper.h \ 67 | ScaledSpectrum.h \ 68 | TriggerGeneratorInterface.h \ 69 | TriggerFilter.h \ 70 | OSCParser.h \ 71 | utils.h \ 72 | TriggerGenerator.h \ 73 | TriggerGuiController.h \ 74 | TriggerOscParameters.h \ 75 | versionInfo.h \ 76 | OSCMessage.h \ 77 | OSCMapping.h \ 78 | OSCNetworkManager.h \ 79 | QCircularBuffer.h \ 80 | BPMDetector.h \ 81 | BPMOscControler.h \ 82 | BPMTapDetector.h 83 | 84 | DISTFILES += \ 85 | LICENSE.txt \ 86 | README.md 87 | -------------------------------------------------------------------------------- /src/TriggerFilter.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Electronic Theatre Controls, Inc., http://www.etcconnect.com 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #include "TriggerFilter.h" 22 | 23 | #include "OSCNetworkManager.h" 24 | 25 | #include 26 | #include 27 | 28 | TriggerFilter::TriggerFilter(OSCNetworkManager* osc, TriggerOscParameters& oscParameters, bool mute) 29 | : QObject(0) 30 | , m_mute(mute) 31 | , m_onDelay(0.0) 32 | , m_offDelay(0.0) 33 | , m_maxHold(0.0) 34 | , m_outputIsActive(false) 35 | , m_osc(osc) 36 | , m_oscParameters(oscParameters) 37 | { 38 | m_onDelayTimer.setSingleShot(true); 39 | connect(&m_onDelayTimer, SIGNAL(timeout()), this, SLOT(onOnDelayEnd())); 40 | m_maxHoldTimer.setSingleShot(true); 41 | connect(&m_maxHoldTimer, SIGNAL(timeout()), this, SLOT(onMaxHoldEnd())); 42 | m_offDelayTimer.setSingleShot(true); 43 | connect(&m_offDelayTimer, SIGNAL(timeout()), this, SLOT(onOffDelayEnd())); 44 | } 45 | 46 | void TriggerFilter::triggerOn() 47 | { 48 | // stop releaseDelayTimer if it is running: 49 | m_offDelayTimer.stop(); 50 | 51 | // ignore triggerOn if output is still active: 52 | if (m_outputIsActive) return; 53 | 54 | // ignore triggerOn if onDelayTimer of previous triggerOn is still running: 55 | if (m_onDelayTimer.isActive()) return; 56 | 57 | // call onOnDelayEnd() after onDelay time: 58 | m_onDelayTimer.start(m_onDelay * 1000); 59 | } 60 | 61 | void TriggerFilter::triggerOff() 62 | { 63 | // stop onDelayTimer if it is running: 64 | m_onDelayTimer.stop(); 65 | 66 | // ignore triggerOff if output is not active: 67 | if (!m_outputIsActive) return; 68 | 69 | // ignore triggerOff if offDelayTimer of previous triggerOff is still running: 70 | if (m_offDelayTimer.isActive()) return; 71 | 72 | // call onOffDelayEnd() after offDelay time: 73 | m_offDelayTimer.start(m_offDelay * 1000); 74 | } 75 | 76 | void TriggerFilter::sendOnSignal() 77 | { 78 | QString message = m_oscParameters.getOnMessage(); 79 | if (!message.isEmpty() && !m_mute) m_osc->sendMessage(message); 80 | emit onSignalSent(); 81 | } 82 | 83 | void TriggerFilter::sendOffSignal() 84 | { 85 | QString message = m_oscParameters.getOffMessage(); 86 | if (!message.isEmpty() && !m_mute) m_osc->sendMessage(message); 87 | emit offSignalSent(); 88 | } 89 | 90 | void TriggerFilter::save(const QString name, QSettings &settings) const 91 | { 92 | settings.setValue(name + "/onDelay", m_onDelay); 93 | settings.setValue(name + "/offDelay", m_offDelay); 94 | settings.setValue(name + "/maxHold", m_maxHold); 95 | } 96 | 97 | void TriggerFilter::restore(const QString name, QSettings &settings) 98 | { 99 | setOnDelay(settings.value(name + "/onDelay").toReal()); 100 | setOffDelay(settings.value(name + "/offDelay").toReal()); 101 | setMaxHold(settings.value(name + "/maxHold").toReal()); 102 | } 103 | 104 | void TriggerFilter::onOnDelayEnd() 105 | { 106 | Q_ASSERT(!m_outputIsActive); 107 | 108 | m_outputIsActive = true; 109 | sendOnSignal(); 110 | 111 | // if maxHold is set, call onMaxHoldEnd after maxHold time: 112 | if (m_maxHold > 0) { 113 | m_maxHoldTimer.start(m_maxHold * 1000); 114 | } 115 | } 116 | 117 | void TriggerFilter::onMaxHoldEnd() 118 | { 119 | Q_ASSERT(m_outputIsActive); 120 | 121 | m_outputIsActive = false; 122 | sendOffSignal(); 123 | 124 | // if offDelayTimer is running, stop it: 125 | m_offDelayTimer.stop(); 126 | } 127 | 128 | void TriggerFilter::onOffDelayEnd() 129 | { 130 | Q_ASSERT(m_outputIsActive); 131 | 132 | m_outputIsActive = false; 133 | sendOffSignal(); 134 | 135 | // if maxHoldTimer is running, stop it: 136 | m_maxHoldTimer.stop(); 137 | } 138 | -------------------------------------------------------------------------------- /src/TriggerFilter.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Electronic Theatre Controls, Inc., http://www.etcconnect.com 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #ifndef TRIGGERFILTER_H 22 | #define TRIGGERFILTER_H 23 | 24 | #include "TriggerOscParameters.h" 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | 33 | // Forward declaration to reduce dependencies: 34 | class OSCNetworkManager; 35 | 36 | 37 | // This class is used to receive trigger signals from a TriggerGenerator 38 | // and filter them in time domain accordingly to some parameters. 39 | class TriggerFilter : public QObject 40 | { 41 | Q_OBJECT 42 | 43 | public: 44 | explicit TriggerFilter(OSCNetworkManager* osc, TriggerOscParameters& oscParameters, bool mute); 45 | 46 | void setMute(bool mute) { m_mute = mute; } 47 | 48 | // returns the on delay time in seconds 49 | qreal getOnDelay() const { return m_onDelay; } 50 | 51 | // sets the on delay time in seconds 52 | void setOnDelay(const qreal& value) { m_onDelay = qMax(0.0, value); } 53 | 54 | 55 | // returns the off delay time in seconds 56 | qreal getOffDelay() const { return m_offDelay; } 57 | 58 | // sets the off delay time in seconds 59 | void setOffDelay(const qreal& value) { m_offDelay = qMax(0.0, value); } 60 | 61 | 62 | // returns the max hold time in seconds 63 | qreal getMaxHold() const { return m_maxHold; } 64 | 65 | // sets the max hold time in seconds 66 | void setMaxHold(const qreal& value) { m_maxHold = qMax(0.0, value); } 67 | 68 | 69 | // to be called when the trigger from the raw signal is activated 70 | // - starts onDelayTimer 71 | void triggerOn(); 72 | // to be called when the trigger from the raw signal is released 73 | // - starts offDelayTimer 74 | void triggerOff(); 75 | 76 | // to be called when the filtered on signal should be sent 77 | void sendOnSignal(); 78 | // to be called when the filtered off signal should be sent 79 | void sendOffSignal(); 80 | 81 | // returns if trigger output is active 82 | bool getOutputIsActive() const { return m_outputIsActive; } 83 | 84 | // saves parameters in QSettings 85 | void save(const QString name, QSettings& settings) const; 86 | 87 | // restores parameters from QSettings 88 | void restore(const QString name, QSettings& settings); 89 | 90 | signals: 91 | // will be emitted when filtered on signal is sent 92 | void onSignalSent(); 93 | // will be emitted when filtered off signal is sent 94 | void offSignalSent(); 95 | 96 | public slots: 97 | // will be called after on delay time if no triggerOff happend 98 | // - calls sendOnSignal() and starts holdMaxTimer 99 | void onOnDelayEnd(); 100 | 101 | // will be called after off delay time if no triggerOn happend 102 | // - calls sendOffSignal() 103 | void onOffDelayEnd(); 104 | 105 | // will be called after max hold time if no triggerOff happend 106 | // - calls sendOffSignal() 107 | void onMaxHoldEnd(); 108 | 109 | protected: 110 | bool m_mute; // Wether the associated band is muted 111 | qreal m_onDelay; // On delay in seconds 112 | qreal m_offDelay; // Off delay in seconds 113 | qreal m_maxHold; // max hold time (decay) in seconds 114 | bool m_outputIsActive; // true if trigger is activated and not yet released 115 | 116 | QTimer m_onDelayTimer; // Timer object for On delay 117 | QTimer m_maxHoldTimer; // Timer object for max hold (decay) 118 | QTimer m_offDelayTimer; // Timer object for Off delay 119 | 120 | OSCNetworkManager* m_osc; // pointer to OSCNetworkManager instance (i.e. of MainController) 121 | TriggerOscParameters& m_oscParameters; // Reference to OSC parameters (message strings) to use 122 | 123 | }; 124 | 125 | #endif // TRIGGERFILTER_H 126 | -------------------------------------------------------------------------------- /src/TriggerGenerator.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Electronic Theatre Controls, Inc., http://www.etcconnect.com 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #include "TriggerGenerator.h" 22 | 23 | #include "OSCNetworkManager.h" 24 | 25 | #include 26 | #include 27 | 28 | TriggerGenerator::TriggerGenerator(QString name, OSCNetworkManager* osc, bool isBandpass, bool invert, int midFreq) 29 | : TriggerGeneratorInterface(isBandpass) 30 | , m_name(name) 31 | , m_osc(osc) 32 | , m_invert(invert) 33 | , m_mute(false) 34 | , m_midFreq(midFreq) 35 | , m_defaultMidFreq(midFreq) 36 | , m_width(0.1) 37 | , m_threshold(0.5) 38 | , m_isActive(false) 39 | , m_oscParameters() 40 | , m_filter(osc, m_oscParameters, m_mute) 41 | { 42 | resetParameters(); 43 | } 44 | 45 | // toggles mute on and off 46 | void TriggerGenerator::toggleMute() 47 | { 48 | m_mute = !m_mute; 49 | m_filter.setMute(m_mute); 50 | m_osc->sendMessage("/s2l/out/" + m_name + "/mute", (m_mute ? "1" : "0"), true); 51 | } 52 | 53 | // toggles mute on and off 54 | void TriggerGenerator::setMute(bool mute) 55 | { 56 | m_mute = mute; 57 | m_filter.setMute(m_mute); 58 | m_osc->sendMessage("/s2l/out/" + m_name + "/mute", (m_mute ? "1" : "0"), true); 59 | } 60 | 61 | bool TriggerGenerator::checkForTrigger(ScaledSpectrum &spectrum, bool forceRelease) 62 | { 63 | qreal value; 64 | if (m_isBandpass) { 65 | value = spectrum.getMaxLevel(m_midFreq, m_width); 66 | } else { 67 | value = spectrum.getMaxLevel(); 68 | } 69 | if (m_invert) value = 1 - value; 70 | 71 | // check for trigger: 72 | if ((!m_isActive && value >= m_threshold) && !forceRelease) { 73 | // activate trigger: 74 | m_isActive = true; 75 | m_filter.triggerOn(); 76 | } else if ((m_isActive && value < m_threshold) || forceRelease) { 77 | // release trigger: 78 | m_isActive = false; 79 | m_filter.triggerOff(); 80 | } 81 | 82 | // send level if levelMessage is set and band is not muted: 83 | // and if difference to last value is greater than 0.001: 84 | qreal diff = qAbs(m_lastValue - value); 85 | if (diff > 0.001 && !m_oscParameters.getLevelMessage().isEmpty() && m_threshold > 0 && !m_mute) { 86 | qreal valueUnderThreshold = limit(0, (value / m_threshold), 1); 87 | qreal minValue = m_oscParameters.getMinLevelValue(); 88 | qreal maxValue = m_oscParameters.getMaxLevelValue(); 89 | qreal scaledValue = minValue + valueUnderThreshold * (maxValue - minValue); 90 | QString oscMessage = m_oscParameters.getLevelMessage() + QString::number(scaledValue, 'f', 3); 91 | m_osc->sendMessage(oscMessage); 92 | } 93 | 94 | m_lastValue = value; 95 | return m_isActive; 96 | } 97 | 98 | void TriggerGenerator::save(QSettings& settings) const 99 | { 100 | settings.setValue(m_name + "/mute", m_mute); 101 | settings.setValue(m_name + "/threshold", m_threshold); 102 | settings.setValue(m_name + "/midFreq", m_midFreq); 103 | settings.setValue(m_name + "/width", m_width); 104 | m_filter.save(m_name, settings); 105 | m_oscParameters.save(m_name, settings); 106 | } 107 | 108 | void TriggerGenerator::restore(QSettings& settings) 109 | { 110 | m_mute = settings.value(m_name + "/mute", false).toBool(); 111 | setThreshold(settings.value(m_name + "/threshold").toReal()); 112 | setMidFreq(settings.value(m_name + "/midFreq").toReal()); 113 | setWidth(settings.value(m_name + "/width").toReal()); 114 | m_filter.restore(m_name, settings); 115 | m_oscParameters.restore(m_name, settings); 116 | } 117 | 118 | void TriggerGenerator::resetParameters() 119 | { 120 | setMidFreq(m_defaultMidFreq); 121 | setWidth(0.1); 122 | m_mute = false; 123 | if (m_isBandpass) { 124 | setThreshold(0.5); 125 | // default Bandpass settings: 126 | m_filter.setOnDelay(0.0); 127 | m_filter.setOffDelay(0.0); 128 | m_filter.setMaxHold(0.0); 129 | } else if (!m_invert) { 130 | // default Level settings: 131 | setThreshold(0.1); 132 | m_filter.setOnDelay(0.5); 133 | m_filter.setOffDelay(2.0); 134 | m_filter.setMaxHold(0.0); 135 | } else { 136 | // default Silence settings: 137 | setThreshold(0.9); 138 | m_filter.setOnDelay(2.5); 139 | m_filter.setOffDelay(1.0); 140 | m_filter.setMaxHold(0.0); 141 | } 142 | m_oscParameters.resetParameters(); 143 | } 144 | -------------------------------------------------------------------------------- /src/TriggerGenerator.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Electronic Theatre Controls, Inc., http://www.etcconnect.com 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #ifndef BANDPASSTRIGGERGENERATOR_H 22 | #define BANDPASSTRIGGERGENERATOR_H 23 | 24 | #include "TriggerGeneratorInterface.h" 25 | #include "ScaledSpectrum.h" 26 | #include "TriggerOscParameters.h" 27 | #include "utils.h" 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | 34 | // Forward declaration to reduce dependencies: 35 | class OSCNetworkManager; 36 | 37 | 38 | // A trigger generator that is activated when the max level 39 | // either within a band of frequencies or in the total spectrum 40 | // is over a certain threshold. 41 | class TriggerGenerator : public TriggerGeneratorInterface 42 | { 43 | 44 | public: 45 | // Creates a new TriggerGenerator object with the name name and an OSCWrapper instance osc. 46 | // This will be a bandpass trigger generator if isBandpass is true. If not it is a "level" / "envelope" trigger generator. 47 | // If invert is true the max level will be inverted. 48 | explicit TriggerGenerator(QString name, OSCNetworkManager* osc, bool isBandpass = true, bool invert = false, 49 | int midFreq = 1000); 50 | 51 | // ---------------- Parameters ------------- 52 | 53 | // returns wether the frequency band is muted 54 | bool getMute() const { return m_mute; } 55 | 56 | // toggles mute on and off 57 | void toggleMute(); 58 | 59 | // toggles mute on and off 60 | void setMute(bool mute); 61 | 62 | 63 | // returns the middle frequency of the frequency band [20...22050] 64 | int getMidFreq() const { return m_midFreq; } 65 | 66 | // sets the middle frequency of the frequency band [20...22050] 67 | void setMidFreq(const int& value) { m_midFreq = limit(10, value, 22050); } 68 | 69 | 70 | // returns the width of the frequency band [0...1] 71 | qreal getWidth() const { return m_width; } 72 | 73 | // sets the width of the frequency band ]0...1] 74 | void setWidth(const qreal& value) { m_width = limit(0.00001, value, 1); } 75 | 76 | 77 | // returns the threshold that is used to generate the trigger [0...1] 78 | qreal getThreshold() const { return m_threshold; } 79 | 80 | // sets the threshold that is used to generate the trigger [0...1] 81 | void setThreshold(const qreal& value) { m_threshold = limit(0, value, 1); } 82 | 83 | // returns a reference to the internal TriggerFilter 84 | TriggerFilter& getTriggerFilter() override { return m_filter; } 85 | 86 | // returns a reference to the OSC message settings of this trigger 87 | TriggerOscParameters& getOscParameters() { return m_oscParameters; } 88 | 89 | 90 | // --------------- calculate Level and Trigger ----------- 91 | 92 | // returns the last maximum value within the frequency band [0...1] 93 | qreal getCurrentLevel() const { return m_lastValue; } 94 | 95 | // checks if the max level within the frequency band is greater than the threshold 96 | bool checkForTrigger(ScaledSpectrum& spectrum, bool forceRelease) override; 97 | 98 | // ---------------- Save and Restore --------------- 99 | 100 | // saves parameters in QSettings 101 | void save(QSettings& settings) const override; 102 | 103 | // restores parameters from QSettings 104 | void restore(QSettings& settings) override; 105 | 106 | // resets all parameters to default values 107 | void resetParameters(); 108 | 109 | protected: 110 | const QString m_name; // name of the Trigger (used for save, restore and UI) 111 | OSCNetworkManager* m_osc; // pointer to OSCNetworkManager instance (i.e. of MainController) 112 | const bool m_invert; // true if signal values should be inverted (i.e. for "silence" trigger) 113 | bool m_mute; // true if the band is muted, which will supress OSC Output 114 | int m_midFreq; // middle frequency of bandpass in Hz 115 | const int m_defaultMidFreq; // default midFreq in Hz, used for reset 116 | qreal m_width; // width of bandpass [0...1] 117 | qreal m_threshold; // threshold for Trigger generation [0...1] 118 | bool m_isActive; // true if value is above threshold 119 | qreal m_lastValue; // last value (used to check if new level message should be sent) 120 | TriggerOscParameters m_oscParameters; // OSC parameter object (stores OSC messages) 121 | TriggerFilter m_filter; // TriggerFilter instance (for "filtering" in time domain: delays and decay) 122 | 123 | }; 124 | 125 | #endif // BANDPASSTRIGGERGENERATOR_H 126 | -------------------------------------------------------------------------------- /src/TriggerGeneratorInterface.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Electronic Theatre Controls, Inc., http://www.etcconnect.com 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #ifndef TRIGGERGENERATORINTERFACE_H 22 | #define TRIGGERGENERATORINTERFACE_H 23 | 24 | #include "ScaledSpectrum.h" 25 | #include "TriggerFilter.h" 26 | 27 | #include 28 | 29 | 30 | // Forward declaration to reduce dependencies: 31 | class OSCNetworkManager; 32 | 33 | 34 | // An interface that describes an object that can generate trigger signals. 35 | class TriggerGeneratorInterface 36 | { 37 | 38 | public: 39 | explicit TriggerGeneratorInterface(bool isBandpass) 40 | : m_isBandpass(isBandpass) {} 41 | virtual ~TriggerGeneratorInterface() {} 42 | 43 | // checks if a signal should be triggered by analyzing the given spectrum 44 | // forceRelease is true when low solo mode is active and a lower trigger was activated 45 | virtual bool checkForTrigger(ScaledSpectrum& spectrum, bool forceRelease) = 0; 46 | 47 | // returns a reference to the internal TriggerFilter 48 | virtual TriggerFilter& getTriggerFilter() = 0; 49 | 50 | // saves parameters in QSettings 51 | virtual void save(QSettings& settings) const = 0; 52 | 53 | // restores parameters from QSettings 54 | virtual void restore(QSettings& settings) = 0; 55 | 56 | // returns if this is a Bandpass trigger generator 57 | bool isBandpass() const { return m_isBandpass; } 58 | 59 | protected: 60 | const bool m_isBandpass; // true if this is a bandpass (with frequency and width parameter) 61 | }; 62 | 63 | 64 | #endif // TRIGGERGENERATORINTERFACE_H 65 | -------------------------------------------------------------------------------- /src/TriggerGuiController.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Electronic Theatre Controls, Inc., http://www.etcconnect.com 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #include "TriggerGuiController.h" 22 | 23 | #include "FFTAnalyzer.h" 24 | #include "ScaledSpectrum.h" 25 | 26 | TriggerGuiController::TriggerGuiController(TriggerGenerator *trigger, QObject *parent) 27 | : QObject(parent) 28 | , m_trigger(trigger) 29 | { 30 | // connect on and off signals of TriggerFilter with the signals of this controller: 31 | connect(&(trigger->getTriggerFilter()), SIGNAL(onSignalSent()), this, SIGNAL(triggerOn())); 32 | connect(&(trigger->getTriggerFilter()), SIGNAL(offSignalSent()), this, SIGNAL(triggerOff())); 33 | connect(&(trigger->getTriggerFilter()), SIGNAL(onSignalSent()), this, SIGNAL(activeChanged())); 34 | connect(&(trigger->getTriggerFilter()), SIGNAL(offSignalSent()), this, SIGNAL(activeChanged())); 35 | } 36 | 37 | void TriggerGuiController::resetParameters() 38 | { 39 | m_trigger->resetParameters(); 40 | emit parameterChanged(); 41 | emit oscLabelTextChanged(); 42 | } 43 | 44 | qreal TriggerGuiController::getMidFreqNormalized() const 45 | { 46 | // TODO: remove dependency from ScaledSpectrum constants 47 | ScaledSpectrum spectrum(SCALED_SPECTRUM_BASE_FREQ, SCALED_SPECTRUM_LENGTH); 48 | int index = spectrum.getIndexForFreq(m_trigger->getMidFreq()); 49 | qreal normalized = index / qreal(SCALED_SPECTRUM_LENGTH); 50 | return normalized; 51 | } 52 | 53 | void TriggerGuiController::setMidFreqNormalized(const qreal &value) 54 | { 55 | // TODO: remove dependency from ScaledSpectrum constants 56 | ScaledSpectrum spectrum(SCALED_SPECTRUM_BASE_FREQ, SCALED_SPECTRUM_LENGTH); 57 | double freq = spectrum.getFreqAtPosition(value); 58 | setMidFreq(freq); 59 | } 60 | -------------------------------------------------------------------------------- /src/TriggerOscParameters.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Electronic Theatre Controls, Inc., http://www.etcconnect.com 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #include "TriggerOscParameters.h" 22 | 23 | TriggerOscParameters::TriggerOscParameters() 24 | : m_onMessage() 25 | , m_offMessage() 26 | , m_levelMessage() 27 | , m_minLevelValue(0) 28 | , m_maxLevelValue(1) 29 | , m_labelText() 30 | { 31 | 32 | } 33 | 34 | void TriggerOscParameters::save(const QString name, QSettings &settings) const 35 | { 36 | settings.setValue(name + "/osc/onMessage", m_onMessage); 37 | settings.setValue(name + "/osc/offMessage", m_offMessage); 38 | settings.setValue(name + "/osc/levelMessage", m_levelMessage); 39 | settings.setValue(name + "/osc/minLevelValue", m_minLevelValue); 40 | settings.setValue(name + "/osc/maxLevelValue", m_maxLevelValue); 41 | settings.setValue(name + "/osc/labelText", m_labelText); 42 | } 43 | 44 | void TriggerOscParameters::restore(const QString name, QSettings &settings) 45 | { 46 | setOnMessage(settings.value(name + "/osc/onMessage").toString()); 47 | setOffMessage(settings.value(name + "/osc/offMessage").toString()); 48 | setLevelMessage(settings.value(name + "/osc/levelMessage").toString()); 49 | setMinLevelValue(settings.value(name + "/osc/minLevelValue").toReal()); 50 | setMaxLevelValue(settings.value(name + "/osc/maxLevelValue").toReal()); 51 | setLabelText(settings.value(name + "/osc/labelText").toString()); 52 | } 53 | 54 | void TriggerOscParameters::resetParameters() 55 | { 56 | setOnMessage(""); 57 | setOffMessage(""); 58 | setLevelMessage(""); 59 | setMinLevelValue(0.0); 60 | setMaxLevelValue(1.0); 61 | setLabelText(""); 62 | } 63 | -------------------------------------------------------------------------------- /src/TriggerOscParameters.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Electronic Theatre Controls, Inc., http://www.etcconnect.com 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #ifndef TRIGGEROSCSETTINGS_H 22 | #define TRIGGEROSCSETTINGS_H 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | 29 | // A class to store OSC parameters (messages and min and max values). 30 | class TriggerOscParameters 31 | { 32 | public: 33 | TriggerOscParameters(); 34 | 35 | // returns the OSC message to be sent when the trigger is activated 36 | QString getOnMessage() const { return m_onMessage; } 37 | // sets the OSC message to be sent when the trigger is activated 38 | void setOnMessage(const QString& value) { m_onMessage = value; } 39 | 40 | // returns the OSC message to be sent when the trigger is released 41 | QString getOffMessage() const { return m_offMessage; } 42 | // sets the OSC message to be sent when the trigger is released 43 | void setOffMessage(const QString& value) { m_offMessage = value; } 44 | 45 | // returns the OSC path where the level value should be sent to 46 | QString getLevelMessage() const { return m_levelMessage; } 47 | // sets the OSC path where the level value should be sent to 48 | void setLevelMessage(const QString& value) { m_levelMessage = value; } 49 | 50 | // returns the value to send when the trigger level is zero 51 | qreal getMinLevelValue() const { return m_minLevelValue; } 52 | // sets the value to send when the trigger level is zero 53 | void setMinLevelValue(const qreal& value) { m_minLevelValue = value; } 54 | 55 | // returns the value to send when the trigger level is at its maximum 56 | qreal getMaxLevelValue() const { return m_maxLevelValue; } 57 | // sets the value to send when the trigger level is at its maximum 58 | void setMaxLevelValue(const qreal& value) { m_maxLevelValue = value; } 59 | 60 | // returns a short label that describes the OSC target 61 | QString getLabelText() const { return m_labelText; } 62 | // sets a short label that describes the OSC target 63 | void setLabelText(const QString& value) { m_labelText = value; } 64 | 65 | // --------------------- Save / Restore --------------------- 66 | 67 | // saves the parameters to QSettings with the given name 68 | void save(const QString name, QSettings& settings) const; 69 | // restores the parameters from QSettings with the given name 70 | void restore(const QString name, QSettings& settings); 71 | 72 | // resets all parameters to default values 73 | void resetParameters(); 74 | 75 | protected: 76 | QString m_onMessage; // On message ("/path/value=argument") 77 | QString m_offMessage; // Off message ("/path/value=argument") 78 | QString m_levelMessage; // Level message ("/path/value=") 79 | qreal m_minLevelValue; // min value to be used for Level message 80 | qreal m_maxLevelValue; // max value to be used for Level message 81 | QString m_labelText; // Short description text of parameters to be displayed in UI 82 | 83 | }; 84 | 85 | #endif // TRIGGEROSCSETTINGS_H 86 | -------------------------------------------------------------------------------- /src/deployment.pri: -------------------------------------------------------------------------------- 1 | unix:!android { 2 | isEmpty(target.path) { 3 | qnx { 4 | target.path = /tmp/$${TARGET}/bin 5 | } else { 6 | target.path = /opt/$${TARGET}/bin 7 | } 8 | export(target.path) 9 | } 10 | INSTALLS += target 11 | } 12 | 13 | export(INSTALLS) 14 | -------------------------------------------------------------------------------- /src/ffft/Array.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | Array.h 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if ! defined (ffft_Array_HEADER_INCLUDED) 19 | #define ffft_Array_HEADER_INCLUDED 20 | 21 | #if defined (_MSC_VER) 22 | #pragma once 23 | #pragma warning (4 : 4250) // "Inherits via dominance." 24 | #endif 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | 31 | 32 | namespace ffft 33 | { 34 | 35 | 36 | 37 | template 38 | class Array 39 | { 40 | 41 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 42 | 43 | public: 44 | 45 | typedef T DataType; 46 | 47 | Array (); 48 | 49 | inline const DataType & 50 | operator [] (long pos) const; 51 | inline DataType & 52 | operator [] (long pos); 53 | 54 | static inline long 55 | size (); 56 | 57 | 58 | 59 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 60 | 61 | protected: 62 | 63 | 64 | 65 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 66 | 67 | private: 68 | 69 | DataType _data_arr [LEN]; 70 | 71 | 72 | 73 | /*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 74 | 75 | private: 76 | 77 | Array (const Array &other); 78 | Array & operator = (const Array &other); 79 | bool operator == (const Array &other); 80 | bool operator != (const Array &other); 81 | 82 | }; // class Array 83 | 84 | 85 | 86 | } // namespace ffft 87 | 88 | 89 | 90 | #include "ffft/Array.hpp" 91 | 92 | 93 | 94 | #endif // ffft_Array_HEADER_INCLUDED 95 | 96 | 97 | 98 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 99 | -------------------------------------------------------------------------------- /src/ffft/Array.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | Array.hpp 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if defined (ffft_Array_CURRENT_CODEHEADER) 19 | #error Recursive inclusion of Array code header. 20 | #endif 21 | #define ffft_Array_CURRENT_CODEHEADER 22 | 23 | #if ! defined (ffft_Array_CODEHEADER_INCLUDED) 24 | #define ffft_Array_CODEHEADER_INCLUDED 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | #include 31 | 32 | 33 | 34 | namespace ffft 35 | { 36 | 37 | 38 | 39 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 40 | 41 | 42 | 43 | template 44 | Array ::Array () 45 | { 46 | // Nothing 47 | } 48 | 49 | 50 | 51 | template 52 | const typename Array ::DataType & Array ::operator [] (long pos) const 53 | { 54 | assert (pos >= 0); 55 | assert (pos < LEN); 56 | 57 | return (_data_arr [pos]); 58 | } 59 | 60 | 61 | 62 | template 63 | typename Array ::DataType & Array ::operator [] (long pos) 64 | { 65 | assert (pos >= 0); 66 | assert (pos < LEN); 67 | 68 | return (_data_arr [pos]); 69 | } 70 | 71 | 72 | 73 | template 74 | long Array ::size () 75 | { 76 | return (LEN); 77 | } 78 | 79 | 80 | 81 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 82 | 83 | 84 | 85 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 86 | 87 | 88 | 89 | } // namespace ffft 90 | 91 | 92 | 93 | #endif // ffft_Array_CODEHEADER_INCLUDED 94 | 95 | #undef ffft_Array_CURRENT_CODEHEADER 96 | 97 | 98 | 99 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 100 | -------------------------------------------------------------------------------- /src/ffft/DynArray.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | DynArray.h 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if ! defined (ffft_DynArray_HEADER_INCLUDED) 19 | #define ffft_DynArray_HEADER_INCLUDED 20 | 21 | #if defined (_MSC_VER) 22 | #pragma once 23 | #pragma warning (4 : 4250) // "Inherits via dominance." 24 | #endif 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | 31 | 32 | namespace ffft 33 | { 34 | 35 | 36 | 37 | template 38 | class DynArray 39 | { 40 | 41 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 42 | 43 | public: 44 | 45 | typedef T DataType; 46 | 47 | DynArray (); 48 | explicit DynArray (long size); 49 | ~DynArray (); 50 | 51 | inline long size () const; 52 | inline void resize (long size); 53 | 54 | inline const DataType & 55 | operator [] (long pos) const; 56 | inline DataType & 57 | operator [] (long pos); 58 | 59 | 60 | 61 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 62 | 63 | protected: 64 | 65 | 66 | 67 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 68 | 69 | private: 70 | 71 | DataType * _data_ptr; 72 | long _len; 73 | 74 | 75 | 76 | /*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 77 | 78 | private: 79 | 80 | DynArray (const DynArray &other); 81 | DynArray & operator = (const DynArray &other); 82 | bool operator == (const DynArray &other); 83 | bool operator != (const DynArray &other); 84 | 85 | }; // class DynArray 86 | 87 | 88 | 89 | } // namespace ffft 90 | 91 | 92 | 93 | #include "ffft/DynArray.hpp" 94 | 95 | 96 | 97 | #endif // ffft_DynArray_HEADER_INCLUDED 98 | 99 | 100 | 101 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 102 | -------------------------------------------------------------------------------- /src/ffft/DynArray.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | DynArray.hpp 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if defined (ffft_DynArray_CURRENT_CODEHEADER) 19 | #error Recursive inclusion of DynArray code header. 20 | #endif 21 | #define ffft_DynArray_CURRENT_CODEHEADER 22 | 23 | #if ! defined (ffft_DynArray_CODEHEADER_INCLUDED) 24 | #define ffft_DynArray_CODEHEADER_INCLUDED 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | #include 31 | 32 | 33 | 34 | namespace ffft 35 | { 36 | 37 | 38 | 39 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 40 | 41 | 42 | 43 | template 44 | DynArray ::DynArray () 45 | : _data_ptr (0) 46 | , _len (0) 47 | { 48 | // Nothing 49 | } 50 | 51 | 52 | 53 | template 54 | DynArray ::DynArray (long size) 55 | : _data_ptr (0) 56 | , _len (0) 57 | { 58 | assert (size >= 0); 59 | if (size > 0) 60 | { 61 | _data_ptr = new DataType [size]; 62 | _len = size; 63 | } 64 | } 65 | 66 | 67 | 68 | template 69 | DynArray ::~DynArray () 70 | { 71 | delete [] _data_ptr; 72 | _data_ptr = 0; 73 | _len = 0; 74 | } 75 | 76 | 77 | 78 | template 79 | long DynArray ::size () const 80 | { 81 | return (_len); 82 | } 83 | 84 | 85 | 86 | template 87 | void DynArray ::resize (long size) 88 | { 89 | assert (size >= 0); 90 | if (size > 0) 91 | { 92 | DataType * old_data_ptr = _data_ptr; 93 | DataType * tmp_data_ptr = new DataType [size]; 94 | 95 | _data_ptr = tmp_data_ptr; 96 | _len = size; 97 | 98 | delete [] old_data_ptr; 99 | } 100 | } 101 | 102 | 103 | 104 | template 105 | const typename DynArray ::DataType & DynArray ::operator [] (long pos) const 106 | { 107 | assert (pos >= 0); 108 | assert (pos < _len); 109 | 110 | return (_data_ptr [pos]); 111 | } 112 | 113 | 114 | 115 | template 116 | typename DynArray ::DataType & DynArray ::operator [] (long pos) 117 | { 118 | assert (pos >= 0); 119 | assert (pos < _len); 120 | 121 | return (_data_ptr [pos]); 122 | } 123 | 124 | 125 | 126 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 127 | 128 | 129 | 130 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 131 | 132 | 133 | 134 | } // namespace ffft 135 | 136 | 137 | 138 | #endif // ffft_DynArray_CODEHEADER_INCLUDED 139 | 140 | #undef ffft_DynArray_CURRENT_CODEHEADER 141 | 142 | 143 | 144 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 145 | -------------------------------------------------------------------------------- /src/ffft/FFTReal.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | FFTReal.h 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if ! defined (ffft_FFTReal_HEADER_INCLUDED) 19 | #define ffft_FFTReal_HEADER_INCLUDED 20 | 21 | #if defined (_MSC_VER) 22 | #pragma once 23 | #pragma warning (4 : 4250) // "Inherits via dominance." 24 | #endif 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | #include "ffft/def.h" 31 | #include "ffft/DynArray.h" 32 | #include "ffft/OscSinCos.h" 33 | 34 | 35 | 36 | namespace ffft 37 | { 38 | 39 | 40 | 41 | template 42 | class FFTReal 43 | { 44 | 45 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 46 | 47 | public: 48 | 49 | enum { MAX_BIT_DEPTH = 30 }; // So length can be represented as long int 50 | 51 | typedef DT DataType; 52 | 53 | explicit FFTReal (long length); 54 | virtual ~FFTReal () {} 55 | 56 | long get_length () const; 57 | void do_fft (DataType f [], const DataType x []) const; 58 | void do_ifft (const DataType f [], DataType x []) const; 59 | void rescale (DataType x []) const; 60 | DataType * use_buffer () const; 61 | 62 | 63 | 64 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 65 | 66 | protected: 67 | 68 | 69 | 70 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 71 | 72 | private: 73 | 74 | // Over this bit depth, we use direct calculation for sin/cos 75 | enum { TRIGO_BD_LIMIT = 12 }; 76 | 77 | typedef OscSinCos OscType; 78 | 79 | void init_br_lut (); 80 | void init_trigo_lut (); 81 | void init_trigo_osc (); 82 | 83 | ffft_FORCEINLINE const long * 84 | get_br_ptr () const; 85 | ffft_FORCEINLINE const DataType * 86 | get_trigo_ptr (int level) const; 87 | ffft_FORCEINLINE long 88 | get_trigo_level_index (int level) const; 89 | 90 | inline void compute_fft_general (DataType f [], const DataType x []) const; 91 | inline void compute_direct_pass_1_2 (DataType df [], const DataType x []) const; 92 | inline void compute_direct_pass_3 (DataType df [], const DataType sf []) const; 93 | inline void compute_direct_pass_n (DataType df [], const DataType sf [], int pass) const; 94 | inline void compute_direct_pass_n_lut (DataType df [], const DataType sf [], int pass) const; 95 | inline void compute_direct_pass_n_osc (DataType df [], const DataType sf [], int pass) const; 96 | 97 | inline void compute_ifft_general (const DataType f [], DataType x []) const; 98 | inline void compute_inverse_pass_n (DataType df [], const DataType sf [], int pass) const; 99 | inline void compute_inverse_pass_n_osc (DataType df [], const DataType sf [], int pass) const; 100 | inline void compute_inverse_pass_n_lut (DataType df [], const DataType sf [], int pass) const; 101 | inline void compute_inverse_pass_3 (DataType df [], const DataType sf []) const; 102 | inline void compute_inverse_pass_1_2 (DataType x [], const DataType sf []) const; 103 | 104 | const long _length; 105 | const int _nbr_bits; 106 | DynArray 107 | _br_lut; 108 | DynArray 109 | _trigo_lut; 110 | mutable DynArray 111 | _buffer; 112 | mutable DynArray 113 | _trigo_osc; 114 | 115 | 116 | 117 | /*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 118 | 119 | private: 120 | 121 | FFTReal (); 122 | FFTReal (const FFTReal &other); 123 | FFTReal & operator = (const FFTReal &other); 124 | bool operator == (const FFTReal &other); 125 | bool operator != (const FFTReal &other); 126 | 127 | }; // class FFTReal 128 | 129 | 130 | 131 | } // namespace ffft 132 | 133 | 134 | 135 | #include "ffft/FFTReal.hpp" 136 | 137 | 138 | 139 | #endif // ffft_FFTReal_HEADER_INCLUDED 140 | 141 | 142 | 143 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 144 | -------------------------------------------------------------------------------- /src/ffft/FFTRealFixLen.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | FFTRealFixLen.h 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if ! defined (ffft_FFTRealFixLen_HEADER_INCLUDED) 19 | #define ffft_FFTRealFixLen_HEADER_INCLUDED 20 | 21 | #if defined (_MSC_VER) 22 | #pragma once 23 | #pragma warning (4 : 4250) // "Inherits via dominance." 24 | #endif 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | #include "ffft/Array.h" 31 | #include "ffft/DynArray.h" 32 | #include "ffft/FFTRealFixLenParam.h" 33 | #include "ffft/OscSinCos.h" 34 | 35 | 36 | 37 | namespace ffft 38 | { 39 | 40 | 41 | 42 | template 43 | class FFTRealFixLen 44 | { 45 | typedef int CompileTimeCheck1 [(LL2 >= 0) ? 1 : -1]; 46 | typedef int CompileTimeCheck2 [(LL2 <= 30) ? 1 : -1]; 47 | 48 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 49 | 50 | public: 51 | 52 | typedef FFTRealFixLenParam::DataType DataType; 53 | typedef OscSinCos OscType; 54 | 55 | enum { FFT_LEN_L2 = LL2 }; 56 | enum { FFT_LEN = 1 << FFT_LEN_L2 }; 57 | 58 | FFTRealFixLen (); 59 | 60 | inline long get_length () const; 61 | void do_fft (DataType f [], const DataType x []); 62 | void do_ifft (const DataType f [], DataType x []); 63 | void rescale (DataType x []) const; 64 | 65 | 66 | 67 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 68 | 69 | protected: 70 | 71 | 72 | 73 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 74 | 75 | private: 76 | 77 | enum { TRIGO_BD_LIMIT = FFTRealFixLenParam::TRIGO_BD_LIMIT }; 78 | 79 | enum { BR_ARR_SIZE_L2 = ((FFT_LEN_L2 - 3) < 0) ? 0 : (FFT_LEN_L2 - 2) }; 80 | enum { BR_ARR_SIZE = 1 << BR_ARR_SIZE_L2 }; 81 | 82 | enum { TRIGO_BD = ((FFT_LEN_L2 - TRIGO_BD_LIMIT) < 0) 83 | ? (int)FFT_LEN_L2 84 | : (int)TRIGO_BD_LIMIT }; 85 | enum { TRIGO_TABLE_ARR_SIZE_L2 = (LL2 < 4) ? 0 : (TRIGO_BD - 2) }; 86 | enum { TRIGO_TABLE_ARR_SIZE = 1 << TRIGO_TABLE_ARR_SIZE_L2 }; 87 | 88 | enum { NBR_TRIGO_OSC = FFT_LEN_L2 - TRIGO_BD }; 89 | enum { TRIGO_OSC_ARR_SIZE = (NBR_TRIGO_OSC > 0) ? NBR_TRIGO_OSC : 1 }; 90 | 91 | void build_br_lut (); 92 | void build_trigo_lut (); 93 | void build_trigo_osc (); 94 | 95 | DynArray 96 | _buffer; 97 | DynArray 98 | _br_data; 99 | DynArray 100 | _trigo_data; 101 | Array 102 | _trigo_osc; 103 | 104 | 105 | 106 | /*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 107 | 108 | private: 109 | 110 | FFTRealFixLen (const FFTRealFixLen &other); 111 | FFTRealFixLen& operator = (const FFTRealFixLen &other); 112 | bool operator == (const FFTRealFixLen &other); 113 | bool operator != (const FFTRealFixLen &other); 114 | 115 | }; // class FFTRealFixLen 116 | 117 | 118 | 119 | } // namespace ffft 120 | 121 | 122 | 123 | #include "ffft/FFTRealFixLen.hpp" 124 | 125 | 126 | 127 | #endif // ffft_FFTRealFixLen_HEADER_INCLUDED 128 | 129 | 130 | 131 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 132 | -------------------------------------------------------------------------------- /src/ffft/FFTRealFixLenParam.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | FFTRealFixLenParam.h 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if ! defined (ffft_FFTRealFixLenParam_HEADER_INCLUDED) 19 | #define ffft_FFTRealFixLenParam_HEADER_INCLUDED 20 | 21 | #if defined (_MSC_VER) 22 | #pragma once 23 | #pragma warning (4 : 4250) // "Inherits via dominance." 24 | #endif 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | 31 | 32 | namespace ffft 33 | { 34 | 35 | 36 | 37 | class FFTRealFixLenParam 38 | { 39 | 40 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 41 | 42 | public: 43 | 44 | // Over this bit depth, we use direct calculation for sin/cos 45 | enum { TRIGO_BD_LIMIT = 12 }; 46 | 47 | typedef float DataType; 48 | 49 | 50 | 51 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 52 | 53 | protected: 54 | 55 | 56 | 57 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 58 | 59 | private: 60 | 61 | 62 | 63 | /*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 64 | 65 | private: 66 | 67 | FFTRealFixLenParam (); 68 | FFTRealFixLenParam (const FFTRealFixLenParam &other); 69 | FFTRealFixLenParam & 70 | operator = (const FFTRealFixLenParam &other); 71 | bool operator == (const FFTRealFixLenParam &other); 72 | bool operator != (const FFTRealFixLenParam &other); 73 | 74 | }; // class FFTRealFixLenParam 75 | 76 | 77 | 78 | } // namespace ffft 79 | 80 | 81 | 82 | //#include "ffft/FFTRealFixLenParam.hpp" 83 | 84 | 85 | 86 | #endif // ffft_FFTRealFixLenParam_HEADER_INCLUDED 87 | 88 | 89 | 90 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 91 | -------------------------------------------------------------------------------- /src/ffft/FFTRealPassDirect.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | FFTRealPassDirect.h 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if ! defined (ffft_FFTRealPassDirect_HEADER_INCLUDED) 19 | #define ffft_FFTRealPassDirect_HEADER_INCLUDED 20 | 21 | #if defined (_MSC_VER) 22 | #pragma once 23 | #pragma warning (4 : 4250) // "Inherits via dominance." 24 | #endif 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | #include "ffft/def.h" 31 | #include "ffft/FFTRealFixLenParam.h" 32 | #include "ffft/OscSinCos.h" 33 | 34 | 35 | 36 | namespace ffft 37 | { 38 | 39 | 40 | 41 | template 42 | class FFTRealPassDirect 43 | { 44 | 45 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 46 | 47 | public: 48 | 49 | typedef FFTRealFixLenParam::DataType DataType; 50 | typedef OscSinCos OscType; 51 | 52 | ffft_FORCEINLINE static void 53 | process (long len, DataType dest_ptr [], DataType src_ptr [], const DataType x_ptr [], const DataType cos_ptr [], long cos_len, const long br_ptr [], OscType osc_list []); 54 | 55 | 56 | 57 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 58 | 59 | protected: 60 | 61 | 62 | 63 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 64 | 65 | private: 66 | 67 | 68 | 69 | /*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 70 | 71 | private: 72 | 73 | FFTRealPassDirect (); 74 | FFTRealPassDirect (const FFTRealPassDirect &other); 75 | FFTRealPassDirect & 76 | operator = (const FFTRealPassDirect &other); 77 | bool operator == (const FFTRealPassDirect &other); 78 | bool operator != (const FFTRealPassDirect &other); 79 | 80 | }; // class FFTRealPassDirect 81 | 82 | 83 | 84 | } // namespace ffft 85 | 86 | 87 | 88 | #include "ffft/FFTRealPassDirect.hpp" 89 | 90 | 91 | 92 | #endif // ffft_FFTRealPassDirect_HEADER_INCLUDED 93 | 94 | 95 | 96 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 97 | -------------------------------------------------------------------------------- /src/ffft/FFTRealPassInverse.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | FFTRealPassInverse.h 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if ! defined (ffft_FFTRealPassInverse_HEADER_INCLUDED) 19 | #define ffft_FFTRealPassInverse_HEADER_INCLUDED 20 | 21 | #if defined (_MSC_VER) 22 | #pragma once 23 | #pragma warning (4 : 4250) // "Inherits via dominance." 24 | #endif 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | #include "ffft/def.h" 31 | #include "ffft/FFTRealFixLenParam.h" 32 | #include "ffft/OscSinCos.h" 33 | 34 | 35 | 36 | 37 | namespace ffft 38 | { 39 | 40 | 41 | 42 | template 43 | class FFTRealPassInverse 44 | { 45 | 46 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 47 | 48 | public: 49 | 50 | typedef FFTRealFixLenParam::DataType DataType; 51 | typedef OscSinCos OscType; 52 | 53 | ffft_FORCEINLINE static void 54 | process (long len, DataType dest_ptr [], DataType src_ptr [], const DataType f_ptr [], const DataType cos_ptr [], long cos_len, const long br_ptr [], OscType osc_list []); 55 | ffft_FORCEINLINE static void 56 | process_rec (long len, DataType dest_ptr [], DataType src_ptr [], const DataType cos_ptr [], long cos_len, const long br_ptr [], OscType osc_list []); 57 | ffft_FORCEINLINE static void 58 | process_internal (long len, DataType dest_ptr [], const DataType src_ptr [], const DataType cos_ptr [], long cos_len, const long br_ptr [], OscType osc_list []); 59 | 60 | 61 | 62 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 63 | 64 | protected: 65 | 66 | 67 | 68 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 69 | 70 | private: 71 | 72 | 73 | 74 | /*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 75 | 76 | private: 77 | 78 | FFTRealPassInverse (); 79 | FFTRealPassInverse (const FFTRealPassInverse &other); 80 | FFTRealPassInverse & 81 | operator = (const FFTRealPassInverse &other); 82 | bool operator == (const FFTRealPassInverse &other); 83 | bool operator != (const FFTRealPassInverse &other); 84 | 85 | }; // class FFTRealPassInverse 86 | 87 | 88 | 89 | } // namespace ffft 90 | 91 | 92 | 93 | #include "ffft/FFTRealPassInverse.hpp" 94 | 95 | 96 | 97 | #endif // ffft_FFTRealPassInverse_HEADER_INCLUDED 98 | 99 | 100 | 101 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 102 | -------------------------------------------------------------------------------- /src/ffft/FFTRealSelect.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | FFTRealSelect.h 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if ! defined (ffft_FFTRealSelect_HEADER_INCLUDED) 19 | #define ffft_FFTRealSelect_HEADER_INCLUDED 20 | 21 | #if defined (_MSC_VER) 22 | #pragma once 23 | #endif 24 | 25 | 26 | 27 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 28 | 29 | #include "ffft/def.h" 30 | 31 | 32 | 33 | namespace ffft 34 | { 35 | 36 | 37 | 38 | template 39 | class FFTRealSelect 40 | { 41 | 42 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 43 | 44 | public: 45 | 46 | ffft_FORCEINLINE static float * 47 | sel_bin (float *e_ptr, float *o_ptr); 48 | 49 | 50 | 51 | /*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 52 | 53 | private: 54 | 55 | FFTRealSelect (); 56 | ~FFTRealSelect (); 57 | FFTRealSelect (const FFTRealSelect &other); 58 | FFTRealSelect& operator = (const FFTRealSelect &other); 59 | bool operator == (const FFTRealSelect &other); 60 | bool operator != (const FFTRealSelect &other); 61 | 62 | }; // class FFTRealSelect 63 | 64 | 65 | 66 | } // namespace ffft 67 | 68 | 69 | 70 | #include "ffft/FFTRealSelect.hpp" 71 | 72 | 73 | 74 | #endif // ffft_FFTRealSelect_HEADER_INCLUDED 75 | 76 | 77 | 78 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 79 | -------------------------------------------------------------------------------- /src/ffft/FFTRealSelect.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | FFTRealSelect.hpp 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if defined (ffft_FFTRealSelect_CURRENT_CODEHEADER) 19 | #error Recursive inclusion of FFTRealSelect code header. 20 | #endif 21 | #define ffft_FFTRealSelect_CURRENT_CODEHEADER 22 | 23 | #if ! defined (ffft_FFTRealSelect_CODEHEADER_INCLUDED) 24 | #define ffft_FFTRealSelect_CODEHEADER_INCLUDED 25 | 26 | 27 | 28 | namespace ffft 29 | { 30 | 31 | 32 | 33 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 34 | 35 | 36 | 37 | template 38 | float * FFTRealSelect

::sel_bin (float *e_ptr, float *o_ptr) 39 | { 40 | Q_UNUSED(e_ptr); 41 | return (o_ptr); 42 | } 43 | 44 | 45 | 46 | template <> 47 | inline float * FFTRealSelect <0>::sel_bin (float *e_ptr, float *o_ptr) 48 | { 49 | Q_UNUSED(o_ptr); 50 | return (e_ptr); 51 | } 52 | 53 | 54 | 55 | } // namespace ffft 56 | 57 | 58 | 59 | #endif // ffft_FFTRealSelect_CODEHEADER_INCLUDED 60 | 61 | #undef ffft_FFTRealSelect_CURRENT_CODEHEADER 62 | 63 | 64 | 65 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 66 | -------------------------------------------------------------------------------- /src/ffft/FFTRealUseTrigo.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | FFTRealUseTrigo.h 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if ! defined (ffft_FFTRealUseTrigo_HEADER_INCLUDED) 19 | #define ffft_FFTRealUseTrigo_HEADER_INCLUDED 20 | 21 | #if defined (_MSC_VER) 22 | #pragma once 23 | #pragma warning (4 : 4250) // "Inherits via dominance." 24 | #endif 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | #include "ffft/def.h" 31 | #include "ffft/FFTRealFixLenParam.h" 32 | #include "ffft/OscSinCos.h" 33 | 34 | 35 | 36 | namespace ffft 37 | { 38 | 39 | 40 | 41 | template 42 | class FFTRealUseTrigo 43 | { 44 | 45 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 46 | 47 | public: 48 | 49 | typedef FFTRealFixLenParam::DataType DataType; 50 | typedef OscSinCos OscType; 51 | 52 | ffft_FORCEINLINE static void 53 | prepare (OscType &osc); 54 | ffft_FORCEINLINE static void 55 | iterate (OscType &osc, DataType &c, DataType &s, const DataType cos_ptr [], long index_c, long index_s); 56 | 57 | 58 | 59 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 60 | 61 | protected: 62 | 63 | 64 | 65 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 66 | 67 | private: 68 | 69 | 70 | 71 | /*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 72 | 73 | private: 74 | 75 | FFTRealUseTrigo (); 76 | ~FFTRealUseTrigo (); 77 | FFTRealUseTrigo (const FFTRealUseTrigo &other); 78 | FFTRealUseTrigo & 79 | operator = (const FFTRealUseTrigo &other); 80 | bool operator == (const FFTRealUseTrigo &other); 81 | bool operator != (const FFTRealUseTrigo &other); 82 | 83 | }; // class FFTRealUseTrigo 84 | 85 | 86 | 87 | } // namespace ffft 88 | 89 | 90 | 91 | #include "ffft/FFTRealUseTrigo.hpp" 92 | 93 | 94 | 95 | #endif // ffft_FFTRealUseTrigo_HEADER_INCLUDED 96 | 97 | 98 | 99 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 100 | -------------------------------------------------------------------------------- /src/ffft/FFTRealUseTrigo.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | FFTRealUseTrigo.hpp 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if defined (ffft_FFTRealUseTrigo_CURRENT_CODEHEADER) 19 | #error Recursive inclusion of FFTRealUseTrigo code header. 20 | #endif 21 | #define ffft_FFTRealUseTrigo_CURRENT_CODEHEADER 22 | 23 | #if ! defined (ffft_FFTRealUseTrigo_CODEHEADER_INCLUDED) 24 | #define ffft_FFTRealUseTrigo_CODEHEADER_INCLUDED 25 | 26 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 27 | 28 | #include "ffft/OscSinCos.h" 29 | 30 | 31 | 32 | namespace ffft 33 | { 34 | 35 | 36 | 37 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 38 | 39 | 40 | 41 | template 42 | void FFTRealUseTrigo ::prepare (OscType &osc) 43 | { 44 | osc.clear_buffers (); 45 | } 46 | 47 | template <> 48 | inline void FFTRealUseTrigo <0>::prepare (OscType &osc) 49 | { 50 | Q_UNUSED(osc); 51 | // Nothing 52 | } 53 | 54 | 55 | 56 | template 57 | void FFTRealUseTrigo ::iterate (OscType &osc, DataType &c, DataType &s, const DataType cos_ptr [], long index_c, long index_s) 58 | { 59 | Q_UNUSED(cos_ptr); 60 | Q_UNUSED(index_c); 61 | Q_UNUSED(index_s); 62 | osc.step (); 63 | c = osc.get_cos (); 64 | s = osc.get_sin (); 65 | } 66 | 67 | template <> 68 | inline void FFTRealUseTrigo <0>::iterate (OscType &osc, DataType &c, DataType &s, const DataType cos_ptr [], long index_c, long index_s) 69 | { 70 | Q_UNUSED(osc); 71 | c = cos_ptr [index_c]; 72 | s = cos_ptr [index_s]; 73 | } 74 | 75 | 76 | 77 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 78 | 79 | 80 | 81 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 82 | 83 | 84 | 85 | } // namespace ffft 86 | 87 | 88 | 89 | #endif // ffft_FFTRealUseTrigo_CODEHEADER_INCLUDED 90 | 91 | #undef ffft_FFTRealUseTrigo_CURRENT_CODEHEADER 92 | 93 | 94 | 95 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 96 | -------------------------------------------------------------------------------- /src/ffft/OscSinCos.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | OscSinCos.h 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if ! defined (ffft_OscSinCos_HEADER_INCLUDED) 19 | #define ffft_OscSinCos_HEADER_INCLUDED 20 | 21 | #if defined (_MSC_VER) 22 | #pragma once 23 | #pragma warning (4 : 4250) // "Inherits via dominance." 24 | #endif 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | #include "ffft/def.h" 31 | 32 | 33 | 34 | namespace ffft 35 | { 36 | 37 | 38 | 39 | template 40 | class OscSinCos 41 | { 42 | 43 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 44 | 45 | public: 46 | 47 | typedef T DataType; 48 | 49 | OscSinCos (); 50 | 51 | ffft_FORCEINLINE void 52 | set_step (double angle_rad); 53 | 54 | ffft_FORCEINLINE DataType 55 | get_cos () const; 56 | ffft_FORCEINLINE DataType 57 | get_sin () const; 58 | ffft_FORCEINLINE void 59 | step (); 60 | ffft_FORCEINLINE void 61 | clear_buffers (); 62 | 63 | 64 | 65 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 66 | 67 | protected: 68 | 69 | 70 | 71 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 72 | 73 | private: 74 | 75 | DataType _pos_cos; // Current phase expressed with sin and cos. [-1 ; 1] 76 | DataType _pos_sin; // - 77 | DataType _step_cos; // Phase increment per step, [-1 ; 1] 78 | DataType _step_sin; // - 79 | 80 | 81 | 82 | /*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 83 | 84 | private: 85 | 86 | OscSinCos (const OscSinCos &other); 87 | OscSinCos & operator = (const OscSinCos &other); 88 | bool operator == (const OscSinCos &other); 89 | bool operator != (const OscSinCos &other); 90 | 91 | }; // class OscSinCos 92 | 93 | 94 | 95 | } // namespace ffft 96 | 97 | 98 | 99 | #include "ffft/OscSinCos.hpp" 100 | 101 | 102 | 103 | #endif // ffft_OscSinCos_HEADER_INCLUDED 104 | 105 | 106 | 107 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 108 | -------------------------------------------------------------------------------- /src/ffft/OscSinCos.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | OscSinCos.hpp 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if defined (ffft_OscSinCos_CURRENT_CODEHEADER) 19 | #error Recursive inclusion of OscSinCos code header. 20 | #endif 21 | #define ffft_OscSinCos_CURRENT_CODEHEADER 22 | 23 | #if ! defined (ffft_OscSinCos_CODEHEADER_INCLUDED) 24 | #define ffft_OscSinCos_CODEHEADER_INCLUDED 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | #include 31 | 32 | namespace std { } 33 | 34 | 35 | 36 | namespace ffft 37 | { 38 | 39 | 40 | 41 | /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 42 | 43 | 44 | 45 | template 46 | OscSinCos ::OscSinCos () 47 | : _pos_cos (1) 48 | , _pos_sin (0) 49 | , _step_cos (1) 50 | , _step_sin (0) 51 | { 52 | // Nothing 53 | } 54 | 55 | 56 | 57 | template 58 | void OscSinCos ::set_step (double angle_rad) 59 | { 60 | using namespace std; 61 | 62 | _step_cos = static_cast (cos (angle_rad)); 63 | _step_sin = static_cast (sin (angle_rad)); 64 | } 65 | 66 | 67 | 68 | template 69 | typename OscSinCos ::DataType OscSinCos ::get_cos () const 70 | { 71 | return (_pos_cos); 72 | } 73 | 74 | 75 | 76 | template 77 | typename OscSinCos ::DataType OscSinCos ::get_sin () const 78 | { 79 | return (_pos_sin); 80 | } 81 | 82 | 83 | 84 | template 85 | void OscSinCos ::step () 86 | { 87 | const DataType old_cos = _pos_cos; 88 | const DataType old_sin = _pos_sin; 89 | 90 | _pos_cos = old_cos * _step_cos - old_sin * _step_sin; 91 | _pos_sin = old_cos * _step_sin + old_sin * _step_cos; 92 | } 93 | 94 | 95 | 96 | template 97 | void OscSinCos ::clear_buffers () 98 | { 99 | _pos_cos = static_cast (1); 100 | _pos_sin = static_cast (0); 101 | } 102 | 103 | 104 | 105 | /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 106 | 107 | 108 | 109 | /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 110 | 111 | 112 | 113 | } // namespace ffft 114 | 115 | 116 | 117 | #endif // ffft_OscSinCos_CODEHEADER_INCLUDED 118 | 119 | #undef ffft_OscSinCos_CURRENT_CODEHEADER 120 | 121 | 122 | 123 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 124 | -------------------------------------------------------------------------------- /src/ffft/def.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | def.h 4 | By Laurent de Soras 5 | 6 | --- Legal stuff --- 7 | 8 | This program is free software. It comes without any warranty, to 9 | the extent permitted by applicable law. You can redistribute it 10 | and/or modify it under the terms of the Do What The Fuck You Want 11 | To Public License, Version 2, as published by Sam Hocevar. See 12 | http://sam.zoy.org/wtfpl/COPYING for more details. 13 | 14 | *Tab=3***********************************************************************/ 15 | 16 | 17 | 18 | #if ! defined (ffft_def_HEADER_INCLUDED) 19 | #define ffft_def_HEADER_INCLUDED 20 | 21 | #if defined (_MSC_VER) 22 | #pragma once 23 | #pragma warning (4 : 4250) // "Inherits via dominance." 24 | #endif 25 | 26 | 27 | 28 | /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 29 | 30 | 31 | 32 | namespace ffft 33 | { 34 | 35 | 36 | 37 | const double PI = 3.1415926535897932384626433832795; 38 | const double SQRT2 = 1.41421356237309514547462185873883; 39 | 40 | #if defined (_MSC_VER) 41 | 42 | #define ffft_FORCEINLINE __forceinline 43 | 44 | #else 45 | 46 | #define ffft_FORCEINLINE inline 47 | 48 | #endif 49 | 50 | 51 | 52 | } // namespace ffft 53 | 54 | 55 | 56 | #endif // ffft_def_HEADER_INCLUDED 57 | 58 | 59 | 60 | /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ 61 | -------------------------------------------------------------------------------- /src/images.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | images/backgroundBlue.png 4 | images/backgroundGray.png 5 | images/trash_icon.png 6 | images/icons/etcicon.icns 7 | images/icons/etclogo.png 8 | images/icons/etcicon.ico 9 | images/maximize.png 10 | images/minimize.png 11 | images/edit.png 12 | images/play.png 13 | images/pause.png 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/images/backgroundBlue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ETCLabs/Sound2Light/b5c5cac01232a4b9bf8c8cc12364792e1b7fe947/src/images/backgroundBlue.png -------------------------------------------------------------------------------- /src/images/backgroundGray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ETCLabs/Sound2Light/b5c5cac01232a4b9bf8c8cc12364792e1b7fe947/src/images/backgroundGray.png -------------------------------------------------------------------------------- /src/images/edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ETCLabs/Sound2Light/b5c5cac01232a4b9bf8c8cc12364792e1b7fe947/src/images/edit.png -------------------------------------------------------------------------------- /src/images/icons/etcicon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ETCLabs/Sound2Light/b5c5cac01232a4b9bf8c8cc12364792e1b7fe947/src/images/icons/etcicon.icns -------------------------------------------------------------------------------- /src/images/icons/etcicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ETCLabs/Sound2Light/b5c5cac01232a4b9bf8c8cc12364792e1b7fe947/src/images/icons/etcicon.ico -------------------------------------------------------------------------------- /src/images/icons/etclogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ETCLabs/Sound2Light/b5c5cac01232a4b9bf8c8cc12364792e1b7fe947/src/images/icons/etclogo.png -------------------------------------------------------------------------------- /src/images/maximize.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ETCLabs/Sound2Light/b5c5cac01232a4b9bf8c8cc12364792e1b7fe947/src/images/maximize.png -------------------------------------------------------------------------------- /src/images/minimize.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ETCLabs/Sound2Light/b5c5cac01232a4b9bf8c8cc12364792e1b7fe947/src/images/minimize.png -------------------------------------------------------------------------------- /src/images/pause.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ETCLabs/Sound2Light/b5c5cac01232a4b9bf8c8cc12364792e1b7fe947/src/images/pause.png -------------------------------------------------------------------------------- /src/images/play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ETCLabs/Sound2Light/b5c5cac01232a4b9bf8c8cc12364792e1b7fe947/src/images/play.png -------------------------------------------------------------------------------- /src/images/trash_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ETCLabs/Sound2Light/b5c5cac01232a4b9bf8c8cc12364792e1b7fe947/src/images/trash_icon.png -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Electronic Theatre Controls, Inc., http://www.etcconnect.com 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #include "MainController.h" 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | 32 | int main(int argc, char *argv[]) { 33 | QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); 34 | QApplication app(argc, argv); 35 | app.setWindowIcon(QIcon(":/images/icons/etcicon.ico")); 36 | 37 | // these parameters are used by QSettings: 38 | QCoreApplication::setOrganizationName("ETC"); 39 | QCoreApplication::setApplicationName("Sound2Light"); 40 | QSettings::setDefaultFormat(QSettings::IniFormat); 41 | 42 | // ----------- Show Splash Screen -------- 43 | QPixmap pixmap(":/images/icons/etclogo.png"); 44 | QSplashScreen splash(pixmap); 45 | splash.show(); 46 | 47 | // call processEvents() to load image in Splash Screen: 48 | app.processEvents(); 49 | 50 | // ----------- Load QML --------------- 51 | 52 | // create QmlEngine and MainController: 53 | QQmlApplicationEngine engine; 54 | MainController* controller = new MainController(&engine); 55 | 56 | // set global QML variable "controller" to a pointer to the MainController: 57 | engine.rootContext()->setContextProperty("controller", controller); 58 | 59 | // quit QGuiApplication when quit signal is emitted: 60 | QObject::connect(&engine, SIGNAL(quit()), &app, SLOT(quit())); 61 | // call onExit() method of controller when app is about to quit: 62 | QObject::connect(&app, SIGNAL(aboutToQuit()), controller, SLOT(onExit())); 63 | 64 | controller->initBeforeQmlIsLoaded(); 65 | engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml"))); 66 | controller->initAfterQmlIsLoaded(); 67 | 68 | // ---------- Hide Splash Screen --------- 69 | splash.hide(); 70 | 71 | // start main application loop: 72 | return app.exec(); 73 | } 74 | -------------------------------------------------------------------------------- /src/qml.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | qml/AboutDialog.qml 4 | qml/BandpassPreviewInSpectrum.qml 5 | qml/main.qml 6 | qml/NoInputDeviceDialog.qml 7 | qml/OscMessageDialog.qml 8 | qml/OscMessagesCobaltArea.qml 9 | qml/OscMessagesEosArea.qml 10 | qml/SettingsDialog.qml 11 | qml/SpectrumPlot.qml 12 | qml/SpectrumWithControls.qml 13 | qml/TouchArea.qml 14 | qml/TriggerSettings.qml 15 | qml/TriggerSettingsArea.qml 16 | qml/TriggerSettingsLegend.qml 17 | qml/style/DarkBlueStripedBackground.qml 18 | qml/style/DarkButton.qml 19 | qml/style/DarkCheckBox.qml 20 | qml/style/DarkComboBox.qml 21 | qml/style/DarkRadioButton.qml 22 | qml/style/DarkSpinBox.qml 23 | qml/style/DarkSplitView.qml 24 | qml/style/DarkTabView.qml 25 | qml/style/DarkTextField.qml 26 | qml/style/GreyText.qml 27 | qml/style/SliderWithIndicator.qml 28 | qml/style/CenterLabel.qml 29 | qml/PresetsDialog.qml 30 | qml/PresetListDialog.qml 31 | qml/oscUtils.js 32 | qml/NumericInput.qml 33 | qml/style/NumBlockButton.qml 34 | qml/OscLogDialog.qml 35 | qml/OscMessagesCobaltOldArea.qml 36 | qml/OscMessagesColorSourceArea.qml 37 | qml/BPMSettings.qml 38 | qml/WavePlot.qml 39 | qml/BPMOscMessageDialog.qml 40 | qml/BPMOscMessagesEosArea.qml 41 | qml/BPMOscMessagesOtherArea.qml 42 | qml/BPMOscMessagesCobaltArea.qml 43 | qml/BPMOscMessagesCobaltOldArea.qml 44 | qml/OscMessagesHog4Area.qml 45 | 46 | 47 | -------------------------------------------------------------------------------- /src/qml/AboutDialog.qml: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Electronic Theatre Controls, Inc., http://www.etcconnect.com 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | import QtQuick 2.5 22 | import QtQuick.Controls 1.4 23 | import QtQuick.Dialogs 1.2 24 | 25 | import "style" // import all files in style dir 26 | 27 | // ---------------------------- About Dialog ---------------------- 28 | Dialog { 29 | id: dialog 30 | title: "About" 31 | 32 | contentItem: Item { 33 | implicitWidth: 600 34 | implicitHeight: 400 35 | 36 | DarkBlueStripedBackground {} 37 | 38 | // ------------------------ Top Area with Text and Logo ---------------- 39 | Column { 40 | anchors.margins: 20 41 | anchors.fill: parent 42 | 43 | Row { 44 | width: parent.width 45 | height: parent.height - 40 46 | 47 | // ------------------------ Left Area with Text -------------------- 48 | Column { 49 | id: textArea 50 | height: parent.height 51 | width: parent.width - logoArea.width 52 | 53 | GreyText { 54 | width: parent.width 55 | height: 40 56 | font.pointSize: 14 57 | text: "Sound2Light" 58 | } 59 | GreyText { 60 | width: parent.width 61 | height: 30 62 | font.pointSize: 10 63 | text: "Version: " + controller.getVersionString() 64 | } 65 | } 66 | 67 | // ------------------------- ETC Logo on the right --------------------- 68 | Item { 69 | id: logoArea 70 | height: parent.height 71 | width: 200 72 | Image { 73 | source: "qrc:/images/icons/etclogo.png" 74 | width: 200 75 | height: 200 76 | anchors.centerIn: parent 77 | MouseArea { 78 | anchors.fill: parent 79 | onClicked: Qt.openUrlExternally("http://www.etcconnect.com") 80 | } 81 | } 82 | } 83 | } 84 | 85 | // --------------- Bottom Area with OK Button and Copyright notes ------------- 86 | Row { 87 | id: bottomRow 88 | width: parent.width 89 | height: 40 90 | GreyText { 91 | height: parent.height 92 | width: parent.width * 0.4 93 | text: "www.etcconnect.com" 94 | font.underline: true 95 | verticalAlignment: Text.AlignBottom 96 | horizontalAlignment: Text.AlignHCenter 97 | MouseArea { 98 | anchors.fill: parent 99 | onClicked: Qt.openUrlExternally("http://www.etcconnect.com") 100 | } 101 | } 102 | DarkButton { 103 | height: parent.height 104 | width: parent.width * 0.2 105 | text: "OK" 106 | onClicked: { 107 | dialog.close() 108 | controller.dialogIsClosed(dialog) 109 | } 110 | } 111 | GreyText { 112 | height: parent.height 113 | width: parent.width * 0.4 114 | text: "© ETC GmbH" 115 | verticalAlignment: Text.AlignBottom 116 | horizontalAlignment: Text.AlignHCenter 117 | } 118 | 119 | } 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/qml/BPMOscMessageDialog.qml: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Electronic Theatre Controls, Inc., http://www.etcconnect.com 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | import QtQuick 2.5 22 | import QtQuick.Controls 1.4 23 | import QtQuick.Controls.Styles 1.4 24 | import QtQuick.Dialogs 1.2 25 | 26 | import "style" // import all files in style dir 27 | 28 | // ----------- A dialog to configure the OSC messages of the BPM Detector --------- 29 | Dialog { 30 | id: dialog 31 | title: "OSC Message" 32 | 33 | // update consoleType when dialog becomes visible 34 | // because it could have changed: 35 | onVisibleChanged: mainArea.updateConsoleType() 36 | 37 | contentItem: Item { 38 | id: content 39 | implicitWidth: 380 40 | implicitHeight: 600 41 | 42 | DarkBlueStripedBackground {} 43 | 44 | Column { 45 | anchors.fill: parent 46 | anchors.margins: 20 47 | 48 | // --------------------- Message Type and Settings Area ----------------- 49 | 50 | Loader { 51 | // This loader loads the corresponding QML file for Eos or Cobalt consoles: 52 | id: mainArea 53 | active: dialog.visible 54 | width: parent.width 55 | height: parent.height - 30 56 | Component.onCompleted: updateConsoleType() 57 | 58 | // sets the right component for this loader based on the chosen console type 59 | // - called when Component is complete and when "visible" of dialog changes 60 | function updateConsoleType() { 61 | var consoleType = controller.getConsoleType(); 62 | var sourceUrl = "" 63 | if (consoleType === "Eos" || consoleType === "EOS") { 64 | sourceUrl = "qrc:/qml/BPMOscMessagesEosArea.qml" 65 | } else if (consoleType === "Cobalt 7.3+") { 66 | sourceUrl = "qrc:/qml/BPMOscMessagesCobaltArea.qml" 67 | } else if (consoleType === "Cobalt 7.2") { 68 | sourceUrl = "qrc:/qml/BPMOscMessagesCobaltOldArea.qml" 69 | } else { 70 | sourceUrl = "qrc:/qml/BPMOscMessagesOtherArea.qml" 71 | } 72 | 73 | if (sourceUrl !== source) { 74 | source = sourceUrl 75 | } 76 | } 77 | 78 | // returns an object containing information about 79 | // the chosen OSC messages (on, off, level, min, max, shortText) 80 | // - called when "Test" or "OK" button is pressed 81 | // - calles getMessages() method of currently displayed Item 82 | function getMessages() { 83 | var messages = item.getMessages() 84 | return messages 85 | } 86 | } 87 | 88 | Item { // spacer 89 | width: parent.width 90 | height: 10 91 | } 92 | 93 | // --------------------- Test and OK Buttons ----------------- 94 | Row { 95 | width: parent.width 96 | height: 30 97 | DarkButton { 98 | width: parent.width * 0.25 99 | height: parent.height 100 | text: "Add" 101 | onPressedChanged: { 102 | if (pressed) { 103 | mainArea.item.addMessage() 104 | } 105 | } 106 | } 107 | Item { // spacer 108 | width: parent.width * 0.1 109 | height: parent.height 110 | } 111 | DarkButton { 112 | width: parent.width * 0.25 113 | height: parent.height 114 | text: "Cancel" 115 | onClicked: { 116 | dialog.close() 117 | controller.dialogIsClosed(dialog) 118 | } 119 | } 120 | Item { // spacer 121 | width: parent.width * 0.1 122 | height: parent.height 123 | } 124 | DarkButton { 125 | width: parent.width * 0.3 126 | height: parent.height 127 | text: "OK" 128 | onClicked: { 129 | var messages = mainArea.getMessages() 130 | controller.setBPMOscCommands(messages) 131 | dialog.close() 132 | controller.dialogIsClosed(dialog) 133 | } 134 | } 135 | } // buttons end 136 | } // column end 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/qml/BPMOscMessagesOtherArea.qml: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Electronic Theatre Controls, Inc., http://www.etcconnect.com 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | import QtQuick 2.5 22 | import QtQuick.Controls 1.4 23 | import QtQuick.Dialogs 1.2 24 | 25 | import "oscUtils.js" as Utils 26 | 27 | import "style" // import all files in style dir 28 | 29 | 30 | 31 | // ----------- Content of the BPM OSC dialog for an unsupported console type ----------- 32 | Item { 33 | id: otherArea 34 | anchors.fill: parent 35 | 36 | property var messages 37 | 38 | Component.onCompleted: { 39 | messages = controller.getBPMOscCommands() 40 | } 41 | 42 | 43 | function getMessages() { 44 | return messages 45 | } 46 | 47 | GreyText { 48 | // Console Label in the top right corner 49 | id: consoleLabel 50 | text: "Unsupported Console" 51 | height: 30 52 | anchors.right: parent.right 53 | font.pointSize: 12 54 | font.bold: true 55 | } 56 | 57 | CenterLabel { 58 | id: noEffectsText 59 | 60 | y: consoleLabel.height 61 | anchors.fill: parent 62 | 63 | text: "Transmitting BPM Information to the selected Console is not \n available in this Version of Sound2Light" 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/qml/NoInputDeviceDialog.qml: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Electronic Theatre Controls, Inc., http://www.etcconnect.com 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | import QtQuick 2.5 22 | import QtQuick.Dialogs 1.2 23 | 24 | // --------------- Dialog that is displayed when no input device is available ------ 25 | MessageDialog { 26 | title: "No Input Device" 27 | text: "Could not find any input devices." 28 | 29 | icon: StandardIcon.Critical 30 | standardButtons: StandardButton.Retry | StandardButton.Close 31 | modality: Qt.ApplicationModal 32 | 33 | onAccepted: { 34 | visible = false 35 | controller.initAudioInput() 36 | } 37 | onRejected: { 38 | visible = false 39 | Qt.quit() 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/qml/OscLogDialog.qml: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Electronic Theatre Controls, Inc., http://www.etcconnect.com 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | import QtQuick 2.5 22 | import QtQuick.Controls 1.4 23 | import QtQuick.Controls.Styles 1.4 24 | import QtQuick.Dialogs 1.2 25 | 26 | import "style" // import all files in style dir 27 | 28 | // --------------------- A dialog to show the OSC log / monitor ------------- 29 | Dialog { 30 | id: root 31 | title: "OSC Monitor" 32 | modality: Qt.platform.os == "osx" ? Qt.NonModal : Qt.WindowModal 33 | 34 | contentItem: Item { 35 | implicitWidth: 700 36 | implicitHeight: 500 37 | 38 | Component.onCompleted: { 39 | // initialize checkbox values: 40 | logIncomingCheckbox.checked = controller.getOscLogIncomingIsEnabled() 41 | logOutgoingCheckbox.checked = controller.getOscLogOutgoingIsEnabled() 42 | } 43 | 44 | DarkBlueStripedBackground {} 45 | 46 | Column { 47 | anchors.margins: 10 48 | anchors.fill: parent 49 | spacing: 0 50 | 51 | // ---------------------- Incoming / Outgoing Checkboxes ----------- 52 | 53 | Row { 54 | width: parent.width 55 | height: 30 56 | DarkCheckBox { 57 | id: logIncomingCheckbox 58 | width: parent.width / 2 59 | height: 30 60 | onClicked: controller.enableOscLogging(logIncomingCheckbox.checked, logOutgoingCheckbox.checked) 61 | text: "Incoming Messages" 62 | textColor: "#88d" 63 | } 64 | DarkCheckBox { 65 | id: logOutgoingCheckbox 66 | width: parent.width / 2 67 | height: 30 68 | onClicked: controller.enableOscLogging(logIncomingCheckbox.checked, logOutgoingCheckbox.checked) 69 | text: "Outgoing Messages" 70 | } 71 | } 72 | 73 | // --------------- ListView with Log ------------- 74 | 75 | Item { 76 | // this item either displays the listview or a label "No Messages" 77 | width: parent.width 78 | height: parent.height - 30 - 40 79 | 80 | ScrollView { 81 | id: scrollView 82 | anchors.fill: parent 83 | visible: logList.count !== 0 84 | ListView { 85 | id: logList 86 | model: controller.getOscLog() 87 | clip: true 88 | verticalLayoutDirection: ListView.BottomToTop 89 | delegate: Text { 90 | height: contentHeight + 3 91 | width: parent.width 92 | wrapMode: Text.Wrap 93 | text: modelData 94 | color: (modelData.indexOf("[In]") !== -1) ? "#88d" : "#aaa" 95 | font.pointSize: 10 96 | } // end delegate 97 | 98 | onCountChanged: { 99 | // emit contentYChanged signal, otherwise scrollbar position will be wrong 100 | contentYChanged() 101 | } 102 | 103 | Connections { 104 | target: controller 105 | onOscLogChanged: { 106 | logList.model = controller.getOscLog() 107 | } 108 | } 109 | } // end ListView 110 | } // end ScrollView 111 | 112 | CenterLabel { 113 | text: "No Messages" 114 | visible: logList.count === 0 115 | } 116 | } 117 | 118 | // -------------------------- Clear and Close Button ------------------------- 119 | 120 | Item { // spacer between Log and Buttons 121 | width: 1 122 | height: 10 123 | } 124 | 125 | Row { 126 | width: parent.width 127 | height: 30 128 | DarkButton { 129 | height: 30 130 | width: 100 131 | text: "Clear" 132 | onClicked: controller.clearOscLog() 133 | } 134 | 135 | Item { // spacer between both buttons 136 | height: 1 137 | width: 20 138 | } 139 | 140 | DarkButton { 141 | width: parent.width - 120 142 | height: 30 143 | text: "Close" 144 | onClicked: { 145 | root.close() 146 | controller.dialogIsClosed(root) 147 | } 148 | } 149 | } 150 | } 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /src/qml/OscMessageDialog.qml: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Electronic Theatre Controls, Inc., http://www.etcconnect.com 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | import QtQuick 2.5 22 | import QtQuick.Controls 1.4 23 | import QtQuick.Controls.Styles 1.4 24 | import QtQuick.Dialogs 1.2 25 | 26 | import "style" // import all files in style dir 27 | 28 | // ----------- A dialog to configure the OSC messages of a triggerController --------- 29 | Dialog { 30 | id: dialog 31 | title: "OSC Message" 32 | 33 | property QtObject triggerController 34 | 35 | // update consoleType when dialog becomes visible 36 | // because it could have changed: 37 | onVisibleChanged: mainArea.updateConsoleType() 38 | 39 | contentItem: Item { 40 | id: content 41 | implicitWidth: 400 42 | implicitHeight: 300 43 | 44 | DarkBlueStripedBackground {} 45 | 46 | Column { 47 | anchors.fill: parent 48 | anchors.margins: 10 49 | 50 | // --------------------- Message Type and Settings Area ----------------- 51 | 52 | Loader { 53 | // This loader loads the corresponding QML file for Eos or Cobalt consoles: 54 | id: mainArea 55 | active: dialog.visible 56 | width: parent.width 57 | height: parent.height - 30 58 | Component.onCompleted: updateConsoleType() 59 | property alias triggerController: dialog.triggerController 60 | 61 | // sets the right conent for this loader based on the chosen console type 62 | // - called when Component is complete and when "visible" of dialog changes 63 | function updateConsoleType() { 64 | var consoleType = controller.getConsoleType(); 65 | var sourceUrl = "" 66 | if (consoleType === "Eos" || consoleType === "EOS") { 67 | sourceUrl = "qrc:/qml/OscMessagesEosArea.qml" 68 | } else if (consoleType === "Cobalt 7.3+") { 69 | sourceUrl = "qrc:/qml/OscMessagesCobaltArea.qml" 70 | } else if (consoleType === "Cobalt 7.2") { 71 | sourceUrl = "qrc:/qml/OscMessagesCobaltOldArea.qml" 72 | } else if (consoleType === "ColorSource") { 73 | sourceUrl = "qrc:/qml/OscMessagesColorSourceArea.qml" 74 | } else if (consoleType === "Hog 4") { 75 | sourceUrl = "qrc:/qml/OscMessagesHog4Area.qml" 76 | } 77 | if (sourceUrl !== source) { 78 | source = sourceUrl 79 | } 80 | } 81 | 82 | // returns an object containing information about 83 | // the chosen OSC messages (on, off, level, min, max, shortText) 84 | // - called when "Test" or "OK" button is pressed 85 | // - calles getMessages() method of currently displayed Item 86 | function getMessages() { 87 | var messages = item.getMessages() 88 | return messages 89 | } 90 | } 91 | // --------------------- Test and OK Buttons ----------------- 92 | Row { 93 | width: parent.width 94 | height: 30 95 | DarkButton { 96 | width: parent.width * 0.25 97 | height: parent.height 98 | text: "Test" 99 | onPressedChanged: { 100 | var messages = mainArea.getMessages() 101 | if (pressed) { 102 | if (messages["on"]) { 103 | controller.sendOscTestMessage(messages["on"]) 104 | } else if (messages["level"]) { 105 | controller.sendOscTestMessage(messages["level"] + messages["levelMax"]) 106 | } 107 | } else { 108 | if (messages["off"]) { 109 | controller.sendOscTestMessage(messages["off"]) 110 | } else if (messages["level"]) { 111 | controller.sendOscTestMessage(messages["level"] + messages["levelMin"]) 112 | } 113 | } 114 | } 115 | } 116 | Item { // spacer 117 | width: parent.width * 0.1 118 | height: parent.height 119 | } 120 | DarkButton { 121 | width: parent.width * 0.25 122 | height: parent.height 123 | text: "Cancel" 124 | onClicked: { 125 | dialog.close() 126 | controller.dialogIsClosed(dialog) 127 | } 128 | } 129 | Item { // spacer 130 | width: parent.width * 0.1 131 | height: parent.height 132 | } 133 | DarkButton { 134 | width: parent.width * 0.3 135 | height: parent.height 136 | text: "OK" 137 | onClicked: { 138 | var messages = mainArea.getMessages() 139 | triggerController.setOscMessages(messages["on"], messages["off"], messages["level"], messages["levelMin"], messages["levelMax"], messages["shortText"]) 140 | dialog.close() 141 | controller.dialogIsClosed(dialog) 142 | } 143 | } 144 | } // buttons end 145 | } // column end 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /src/qml/SpectrumPlot.qml: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Electronic Theatre Controls, Inc., http://www.etcconnect.com 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | import QtQuick 2.5 22 | 23 | import "style" // import all files in style dir 24 | 25 | // ------------------------- A widget that displayes a spectrum --------------- 26 | Grid { 27 | columns: 2 28 | spacing: 0 29 | 30 | // ----------------------- Legend at the left ------------- 31 | Rectangle { 32 | id: leftLegend 33 | width: 20 34 | height: parent.height - bottomLegend.height 35 | color: "#272727" 36 | GreyText { 37 | text: "dB" 38 | x: 2 39 | visible: controller.decibelConversion 40 | } 41 | GreyText { 42 | text: "0" 43 | x: 2 44 | y: 20 45 | visible: controller.decibelConversion 46 | } 47 | GreyText { 48 | text: "-60" 49 | x: 2 50 | y: parent.height - 20 51 | visible: controller.decibelConversion 52 | } 53 | } 54 | 55 | // ----------------------- Spectrum Plot ----------------------- 56 | Canvas { 57 | id: canvas 58 | width: parent.width - leftLegend.width 59 | height: parent.height - bottomLegend.height 60 | onPaint: { 61 | // --- Prepare --- 62 | var points = controller.getSpectrumPoints() 63 | var pointCount = points.length; 64 | var pointWidth = width / pointCount 65 | var ctx = canvas.getContext('2d'); 66 | ctx.fillStyle = "#272727"; 67 | ctx.fillRect (0, 0, width, height); 68 | 69 | // --- Spectrum Geometry --- 70 | ctx.beginPath(); 71 | ctx.moveTo(0, height); 72 | var lastValue = 1.0 73 | for (var i=0; i= control.value) ? handleActiveColor : "#555" 49 | border.color: "gray" 50 | border.width: 2 51 | implicitWidth: 18 52 | implicitHeight: 18 53 | radius: 9 54 | visible: control.enabled 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/sound2light_installer_data_windows.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ETCLabs/Sound2Light/b5c5cac01232a4b9bf8c8cc12364792e1b7fe947/src/sound2light_installer_data_windows.zip -------------------------------------------------------------------------------- /src/utils.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Electronic Theatre Controls, Inc., http://www.etcconnect.com 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #ifndef UTILS_H 22 | #define UTILS_H 23 | 24 | #include 25 | #include 26 | 27 | // This file includes some often used utility functions. 28 | 29 | 30 | // Limits / saturates a value with min and max bounds: 31 | template 32 | T2 limit(T1 min, T2 value, T3 max) { 33 | return qMax(T2(min), qMin(value, T2(max))); 34 | } 35 | 36 | 37 | namespace HighResTime { // ------------------- 38 | 39 | typedef std::chrono::time_point time_point_t; 40 | 41 | inline time_point_t now() { 42 | return std::chrono::system_clock::now(); 43 | } 44 | 45 | inline double elapsedSecSince(time_point_t start) { 46 | time_point_t now = HighResTime::now(); 47 | std::chrono::duration elapsed_seconds_duration = now - start; 48 | double elapsedSeconds = elapsed_seconds_duration.count(); 49 | return elapsedSeconds; 50 | } 51 | 52 | inline double diff(time_point_t end, time_point_t start) { 53 | std::chrono::duration elapsed_seconds_duration = end - start; 54 | return elapsed_seconds_duration.count(); 55 | } 56 | 57 | inline double getElapsedSecAndUpdate(time_point_t& lastTime) { 58 | time_point_t now = HighResTime::now(); 59 | double elapsedSeconds = diff(now, lastTime); 60 | lastTime = now; 61 | return elapsedSeconds; 62 | } 63 | 64 | } // end namespace HighResTime ----------------- 65 | 66 | 67 | #endif // UTILS_H 68 | -------------------------------------------------------------------------------- /src/versionInfo.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Electronic Theatre Controls, Inc., http://www.etcconnect.com 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #ifndef VERSIONINFO_H 22 | #define VERSIONINFO_H 23 | 24 | #include 25 | 26 | // This file includes the version number of this software. 27 | 28 | static const QString VERSION_STRING = "0.0.3.1.0.2"; 29 | static const int SETTINGS_FORMAT_VERSION = 1; 30 | 31 | #endif // VERSIONINFO_H 32 | --------------------------------------------------------------------------------