Skip to content

Commit f8b60f8

Browse files
Added source of v0.0.2.1.0.9
1 parent d7a2240 commit f8b60f8

25 files changed

+253
-33
lines changed

doc/Sound2Light_Tool_Anleitung.pdf

46.4 KB
Binary file not shown.

doc/Sound2Light_Tool_Manual_en.pdf

47 KB
Binary file not shown.

doc/s2l_changelog.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11

22
# Sound2Light Change Log
33

4+
### Version 0.0.2.1.0.9 - 1 Mar 2017
5+
6+
- Supports Muting the OSC output of individual channels
7+
48
### Version 0.0.2.1.0.8 - 1 Mar 2017
59

610
- Fixed BPM OSC Messages with a one digit value being interpreted falsely on EOS

doc/screenshot_main_window.png

43 KB
Loading

src/BPMOscControler.cpp

+18-1
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,25 @@
2121
#include "BPMOscControler.h"
2222

2323
BPMOscControler::BPMOscControler(OSCNetworkManager &osc) :
24-
m_osc(osc)
24+
m_bpmMute(false)
25+
, m_osc(osc)
2526
, m_oscCommands()
2627
{
2728
}
2829

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+
2943
// Restore the commands from e.g. a preset or whatever else
3044
void BPMOscControler::restore(QSettings& settings)
3145
{
@@ -55,6 +69,9 @@ inline int round(float value) { return (fmod(value,1.0) < 0.5) ? value : value +
5569
// Called by the bpm detector to make the controller send the new bpm to the clients
5670
void BPMOscControler::transmitBPM(float bpm)
5771
{
72+
// Don't transmit if mute is engaged
73+
if (m_bpmMute) return;
74+
5875
// Send user specified commands
5976

6077
for (QString& command : m_oscCommands) {

src/BPMOscControler.h

+6
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ class BPMOscControler
2929
public:
3030
BPMOscControler(OSCNetworkManager& osc);
3131

32+
// Getter/Setter for mute
33+
bool getBPMMute() { return m_bpmMute; }
34+
void setBPMMute(bool mute);
35+
void toggleBPMMute();
36+
3237
// Called by the bpm detector to make the controller send the new bpm to the clients
3338
void transmitBPM(float bpm);
3439

@@ -49,6 +54,7 @@ class BPMOscControler
4954

5055

5156
protected:
57+
bool m_bpmMute; // If the bpm osc is muted
5258
OSCNetworkManager& m_osc; // The network manager to send network signals thorugh
5359
QStringList m_oscCommands; // The osc messages to be sent on a tempo changed. Delivered as finished strings with the <BPM> (<BPM1-2>, <BPM4> 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
5460
};

src/LICENSE.txt

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
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.

src/MainController.cpp

+14-1
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,8 @@ void MainController::loadPreset(const QString &constFileName, bool createIfNotEx
474474
// Restore the manual BPM
475475
m_bpmTap.setBpm(settings.value("bpm/tapvalue", 60).toInt());
476476

477+
m_bpmOSC.setBPMMute(settings.value("bpm/mute", false).toBool());
478+
477479

478480
// this is now the loaded preset, update the preset name:
479481
m_currentPresetFilename = fileName; emit presetNameChanged();
@@ -491,6 +493,7 @@ void MainController::loadPreset(const QString &constFileName, bool createIfNotEx
491493
emit bpmActiveChanged();
492494
emit bpmRangeChanged();
493495
emit waveformVisibleChanged();
496+
emit bpmMuteChanged();
494497

495498
emit m_bassController->parameterChanged();
496499
emit m_loMidController->parameterChanged();
@@ -505,6 +508,13 @@ void MainController::loadPreset(const QString &constFileName, bool createIfNotEx
505508
emit m_highController->oscLabelTextChanged();
506509
emit m_envelopeController->oscLabelTextChanged();
507510
emit m_silenceController->oscLabelTextChanged();
511+
512+
emit m_bassController->muteChanged();
513+
emit m_loMidController->muteChanged();
514+
emit m_hiMidController->muteChanged();
515+
emit m_highController->muteChanged();
516+
emit m_envelopeController->muteChanged();
517+
emit m_silenceController->muteChanged();
508518
}
509519

510520
void MainController::savePresetAs(const QString &constFileName, bool isAutosave)
@@ -547,9 +557,12 @@ void MainController::savePresetAs(const QString &constFileName, bool isAutosave)
547557
// save the settings in the BPMOscController
548558
m_bpmOSC.save(settings);
549559

550-
// Restore the manual BPM
560+
// save the manual BPM
551561
settings.setValue("bpm/tapvalue", m_bpmTap.getBpm());
552562

563+
// save bpm mute
564+
settings.setValue("bpm/mute", m_bpmOSC.getBPMMute());
565+
553566
if (!isAutosave) {
554567
// this is now the loaded preset, update the preset name:
555568
m_currentPresetFilename = fileName; emit presetNameChanged();

src/MainController.h

+7
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,9 @@ class MainController : public QObject
130130
// emitted if the waveform visiblity changed
131131
void waveformVisibleChanged();
132132

133+
// emitted if the bpm mute changed
134+
void bpmMuteChanged();
135+
133136
// forwarded from OSCNetworkManager:
134137
void messageReceived(OSCMessage msg);
135138
void packetSent();
@@ -246,6 +249,10 @@ public slots:
246249
// gets the minium bpm of the range
247250
int getMinBPM() { return m_bpm.getMinBPM(); }
248251

252+
// set/get bpm mute
253+
bool getBPMMute() { return m_bpmOSC.getBPMMute(); }
254+
void toggleBPMMute() { m_bpmOSC.toggleBPMMute(); emit bpmMuteChanged(); }
255+
249256
// set/get the waveform visibility
250257
bool getWaveformVisible() { return m_waveformVisible & m_bpmActive; }
251258
void setWaveformVisible(bool value) { m_waveformVisible = value; emit waveformVisibleChanged();}

src/OSCMapping.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,20 @@ void OSCMapping::handleMessage(OSCMessage msg)
8282
if (msg.arguments().size() == 0 || msg.arguments().at(0).toBool()) {
8383
m_controller->triggerBeat();
8484
}
85+
} else if (msg.pathStartsWith("/s2l/bpm/mute")) {
86+
m_controller->toggleBPMMute();
87+
} else if (msg.pathStartsWith("/s2l/bass/mute")) {
88+
m_controller->m_bassController->toggleMute();
89+
} else if (msg.pathStartsWith("/s2l/lo_mid/mute")) {
90+
m_controller->m_loMidController->toggleMute();
91+
} else if (msg.pathStartsWith("/s2l/hi_mid/mute")) {
92+
m_controller->m_hiMidController->toggleMute();
93+
} else if (msg.pathStartsWith("/s2l/high/mute")) {
94+
m_controller->m_highController->toggleMute();
95+
} else if (msg.pathStartsWith("/s2l/level/mute")) {
96+
m_controller->m_envelopeController->toggleMute();
97+
} else if (msg.pathStartsWith("/s2l/silence/mute")) {
98+
m_controller->m_silenceController->toggleMute();
8599
}
86100
}
87101

src/README.md

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
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)

src/TriggerFilter.cpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,9 @@
2525
#include <QDebug>
2626
#include <QTimer>
2727

28-
TriggerFilter::TriggerFilter(OSCNetworkManager* osc, TriggerOscParameters& oscParameters)
28+
TriggerFilter::TriggerFilter(OSCNetworkManager* osc, TriggerOscParameters& oscParameters, bool mute)
2929
: QObject(0)
30+
, m_mute(mute)
3031
, m_onDelay(0.0)
3132
, m_offDelay(0.0)
3233
, m_maxHold(0.0)
@@ -75,14 +76,14 @@ void TriggerFilter::triggerOff()
7576
void TriggerFilter::sendOnSignal()
7677
{
7778
QString message = m_oscParameters.getOnMessage();
78-
if (!message.isEmpty()) m_osc->sendMessage(message);
79+
if (!message.isEmpty() && !m_mute) m_osc->sendMessage(message);
7980
emit onSignalSent();
8081
}
8182

8283
void TriggerFilter::sendOffSignal()
8384
{
8485
QString message = m_oscParameters.getOffMessage();
85-
if (!message.isEmpty()) m_osc->sendMessage(message);
86+
if (!message.isEmpty() && !m_mute) m_osc->sendMessage(message);
8687
emit offSignalSent();
8788
}
8889

src/TriggerFilter.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@ class TriggerFilter : public QObject
4141
Q_OBJECT
4242

4343
public:
44-
explicit TriggerFilter(OSCNetworkManager* osc, TriggerOscParameters& oscParameters);
44+
explicit TriggerFilter(OSCNetworkManager* osc, TriggerOscParameters& oscParameters, bool mute);
45+
46+
void setMute(bool mute) { m_mute = mute; }
4547

4648
// returns the on delay time in seconds
4749
qreal getOnDelay() const { return m_onDelay; }
@@ -105,6 +107,7 @@ public slots:
105107
void onMaxHoldEnd();
106108

107109
protected:
110+
bool m_mute; // Wether the associated band is muted
108111
qreal m_onDelay; // On delay in seconds
109112
qreal m_offDelay; // Off delay in seconds
110113
qreal m_maxHold; // max hold time (decay) in seconds

src/TriggerGenerator.cpp

+36-16
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,34 @@ TriggerGenerator::TriggerGenerator(QString name, OSCNetworkManager* osc, bool is
3030
, m_name(name)
3131
, m_osc(osc)
3232
, m_invert(invert)
33+
, m_mute(false)
3334
, m_midFreq(midFreq)
3435
, m_defaultMidFreq(midFreq)
3536
, m_width(0.1)
3637
, m_threshold(0.5)
3738
, m_isActive(false)
3839
, m_oscParameters()
39-
, m_filter(osc, m_oscParameters)
40+
, m_filter(osc, m_oscParameters, m_mute)
4041
{
4142
resetParameters();
4243
}
4344

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+
4461
bool TriggerGenerator::checkForTrigger(ScaledSpectrum &spectrum, bool forceRelease)
4562
{
4663
qreal value;
@@ -51,7 +68,7 @@ bool TriggerGenerator::checkForTrigger(ScaledSpectrum &spectrum, bool forceRelea
5168
}
5269
if (m_invert) value = 1 - value;
5370

54-
// check for trigger:
71+
// check for trigger:
5572
if ((!m_isActive && value >= m_threshold) && !forceRelease) {
5673
// activate trigger:
5774
m_isActive = true;
@@ -60,27 +77,28 @@ bool TriggerGenerator::checkForTrigger(ScaledSpectrum &spectrum, bool forceRelea
6077
// release trigger:
6178
m_isActive = false;
6279
m_filter.triggerOff();
63-
}
80+
}
6481

65-
// send level if levelMessage is set:
82+
// send level if levelMessage is set and band is not muted:
6683
// and if difference to last value is greater than 0.001:
67-
qreal diff = qAbs(m_lastValue - value);
68-
if (diff > 0.001 && !m_oscParameters.getLevelMessage().isEmpty() && m_threshold > 0) {
69-
qreal valueUnderThreshold = limit(0, (value / m_threshold), 1);
70-
qreal minValue = m_oscParameters.getMinLevelValue();
71-
qreal maxValue = m_oscParameters.getMaxLevelValue();
72-
qreal scaledValue = minValue + valueUnderThreshold * (maxValue - minValue);
73-
QString oscMessage = m_oscParameters.getLevelMessage() + QString::number(scaledValue, 'f', 3);
74-
m_osc->sendMessage(oscMessage);
75-
}
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+
}
7693

7794
m_lastValue = value;
7895
return m_isActive;
7996
}
8097

8198
void TriggerGenerator::save(QSettings& settings) const
8299
{
83-
settings.setValue(m_name + "/threshold", m_threshold);
100+
settings.setValue(m_name + "/mute", m_mute);
101+
settings.setValue(m_name + "/threshold", m_threshold);
84102
settings.setValue(m_name + "/midFreq", m_midFreq);
85103
settings.setValue(m_name + "/width", m_width);
86104
m_filter.save(m_name, settings);
@@ -89,17 +107,19 @@ void TriggerGenerator::save(QSettings& settings) const
89107

90108
void TriggerGenerator::restore(QSettings& settings)
91109
{
110+
m_mute = settings.value(m_name + "/mute", false).toBool();
92111
setThreshold(settings.value(m_name + "/threshold").toReal());
93112
setMidFreq(settings.value(m_name + "/midFreq").toReal());
94113
setWidth(settings.value(m_name + "/width").toReal());
95114
m_filter.restore(m_name, settings);
96-
m_oscParameters.restore(m_name, settings);
115+
m_oscParameters.restore(m_name, settings);
97116
}
98117

99118
void TriggerGenerator::resetParameters()
100119
{
101-
setMidFreq(m_defaultMidFreq);
120+
setMidFreq(m_defaultMidFreq);
102121
setWidth(0.1);
122+
m_mute = false;
103123
if (m_isBandpass) {
104124
setThreshold(0.5);
105125
// default Bandpass settings:

src/TriggerGenerator.h

+12-1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,16 @@ class TriggerGenerator : public TriggerGeneratorInterface
5050

5151
// ---------------- Parameters -------------
5252

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+
5363
// returns the middle frequency of the frequency band [20...22050]
5464
int getMidFreq() const { return m_midFreq; }
5565

@@ -97,9 +107,10 @@ class TriggerGenerator : public TriggerGeneratorInterface
97107
void resetParameters();
98108

99109
protected:
100-
const QString m_name; // name of the Trigger (used for save, restore and UI)
110+
const QString m_name; // name of the Trigger (used for save, restore and UI)
101111
OSCNetworkManager* m_osc; // pointer to OSCNetworkManager instance (i.e. of MainController)
102112
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
103114
int m_midFreq; // middle frequency of bandpass in Hz
104115
const int m_defaultMidFreq; // default midFreq in Hz, used for reset
105116
qreal m_width; // width of bandpass [0...1]

src/TriggerGuiController.h

+6
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,18 @@ class TriggerGuiController : public QObject
5858
void oscLabelTextChanged();
5959
// emitted when a value of the preset changed
6060
void presetChanged();
61+
// emmited when mute changes
62+
void muteChanged();
6163

6264
public slots:
6365

6466
// forward calls to TriggerGenerator
6567
// see TriggerGenerator.h for documentation
6668

69+
bool getMute() const { return m_trigger->getMute(); }
70+
void toggleMute() { m_trigger->toggleMute(); emit muteChanged(); }
71+
void setMute(bool mute) { m_trigger->setMute(mute); emit muteChanged(); }
72+
6773
int getMidFreq() const { return m_trigger->getMidFreq(); }
6874
void setMidFreq(const int& value) { m_trigger->setMidFreq(value); emit parameterChanged(); emit presetChanged(); }
6975

0 commit comments

Comments
 (0)