Skip to content

Commit

Permalink
Disable midi section, adjust documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
thgrund committed Sep 29, 2024
1 parent 94cd7a2 commit 130a504
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 76 deletions.
58 changes: 6 additions & 52 deletions HelpSource/Classes/SuperDirtMixer.schelp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ categories:: Live Coding
related:: Reference/Architecture

DESCRIPTION::
This is a mixer ui was created for the sound engine strong::SuperDirt:: link::https://github.com/musikinformatik/SuperDirt:: for the strong::TidalCycles:: link::http://tidalcycles.org/:: programming language. The main motivation of this mixer was to get rid of using a DAW like Ableton in a live coding setup, because the author just used it for mixing a live setup. This mixer helps to realize tonal depth, clean frequency separation and a stereo panorama and makes this easily accessible in SuperDirt.
This is a mixer ui was created for the sound engine strong::SuperDirt:: link::https://github.com/musikinformatik/SuperDirt:: for the strong::TidalCycles:: link::http://tidalcycles.org/:: programming language. The main motivation of this mixer was to get rid of using a DAW like Ableton in a live coding setup, because the author just used it for mixing a live setup. This mixer helps to realize tonal depth, clean frequency separation, signal compression and a stereo panorama and makes this easily accessible in SuperDirt..
In general this mixer overwrites the default values of the orbits defaultParentEvents. This means i.e. that it allows to change the value for gain from 1.0 to a different value from 0 to 1.5. These defaultParentEvent values will be used until they get overwritten on the TidalCycles side.

For the EQ of an orbit, this plugin is using EQui (link::https://github.com/muellmusik/EQui::). For this it's needed to add some additional values to the defaultParentEvent to store and change the EQui parameters which will be done during the initialisation of this mixer. The eq functionality was added as a global effect to every orbit. This allows you to change the eq parameters for every orbit and still use all the other filter like hpf or lpf.
Expand All @@ -24,11 +24,11 @@ code::
// More SuperDirt ...

// Initialize the SuperDirtMixer
~mixer = SuperDirtMixer(~dirt, 6010);
~mixer = SuperDirtMixer(~dirt);

// You can adjust parameters before you use the ui
~mixer.setOrbitLabels(["d1 - Lead", "d2 - Bass", "d3 - Key", "d4 - Pad", "d5 - Arp", "d6 - Drums", "d7 - Rhytm Git", "d8 - Lead Git", "d9 - Strings", "d10 - FX", "d11 - Kick", "d12 - Cymbals", "d13 - Snare", "d14 - Toms"]);
~mixer.enableMasterPeakRMS(0)
~mixer.setMasterBus(0)
}
)

Expand Down Expand Up @@ -61,13 +61,13 @@ SUBSECTION:: UI configurations
METHOD:: disableMasterPeakRMS
This will reset the master audio bus and remove the level indicators from the ui.

METHOD:: enableMasterPeakRMS
This will render the level indicator for a master audio bus. This can be the sum of what you will here on a stereo hardware output.
METHOD:: setMasterBus
This will render the level indicator for a master audio bus and enables the stage master section. This represents the sum of what you will here on a stereo hardware output.

ARGUMENT:: masterBus
The recommendation would be to use the output bus that will be used for the stereo hardware output. In most cases this should be simply 0 or can be accessed by Bus.new.

METHOD::orbitLabels
METHOD::setOrbitLabels
This is basically an array with the length of ~dirt.orbits wich allows you to change the label of each orbit controls section.

code::
Expand Down Expand Up @@ -99,58 +99,12 @@ need differ. In the custom VST example below, the value \reverb will be used ins
SUBSECTION:: Communication with TidalCycles
This mixer ui is able to send OSC messages to TidalCycles. This will mainly be used to solo or mute orbits. After the mixer was initialized, it automatically trys to establish a connection on location on the port 6010 (TidalCycles default value).

METHOD:: tidalNetAddr
This method allows to overwrite the default NetAddr to send osc messages to TidalCycles.

code::
~mixer.tidalNetAddr = NetAddr.new("127.0.0.1", 12345);
::


SUBSECTION:: Preset management

METHOD:: presetPath
This is the path to the preset folder. The path is always relative to the source code of the SuperDirtMixer. This will be used to load and save presets and displays all the files as available presets in the ui. The default value is "../presets".

METHOD:: loadPreset
Loads the preset and sets all the orbit defaultParentEvent values to what is defined in the passed preset file.

note::
Right now this will unfortunately not reload the equalizer settings.
::

ARGUMENT:: presetFile
This is the file that is located to the relative path that was specified at link::Classes/SuperDirtMixer#-presetPath::.

METHOD:: savePreset
Saves the current orbit defaultParentEvent values to the passed preset file.

ARGUMENT:: presetFile
This is the file that is located to the relative path that was specified at link::Classes/SuperDirtMixer#-presetPath::.

METHOD:: receivePresetLoad
This method will be called whenever you load a preset in the ui. This will help you to extend presets with additional informations. The argument of the callback function is the name of the preset file that was loaded.

code::
(
~mixer.receivePresetLoad = ({
|presetFile| presetFile.postln;
});
)
::

SUBSECTION:: Direct feature access (without using the UI)

METHOD:: startEQEffect
You can use this method to run the eq global effects for every orbit manually. This will be used by the link::Classes/SuperDirtMixer#-gui:: function internally to start the eq effects.

METHOD:: stopEQEffect
You can use this method to stop the eq global effects for every orbit manually. This will be used by the link::Classes/SuperDirtMixer#-gui:: function internally to stop the eq effects when you close the ui window.

METHOD:: initDefaultParentEvents
In general this is used internally but you can use it to reset every value in each orbit.


EXAMPLES::

These are a set of examples to change the mixer ui with osc messages from the outside. To use this properly, you need to
Expand Down
68 changes: 68 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,74 @@ And then you can render the gui with executing this in any SuperCollider file

For more in depth configuration options you can have a look into the helpfile. This is accessable in SuperCollider when your cursor is on `SuperDirtMixer` and you press i.e. `Command + D` on MacOS.

## Control the mixer with TidalCycles

It's possible to directly change the orbit values within your regular tidal patterns, but then you wouldn't see the changes reflected in the ui. In any case you need to evaluate the code in `tidal/src/PatternFunctions.hs`.

To control the SuperDirtMixer with TidalCycles and to see the changeds reflected in the ui, you need to create a new target in your `BootTidal.hs` . Here is the template for it:

```haskell
let superDirtMixerTarget = Target {
oName = "superDirtMixer", oAddress = "localhost"
, oPort = 57121, oLatency = 0.2, oSchedule = Live
, oWindow = Nothing, oHandshake = False
, oBusPort = Nothing }
oscplay = OSC "/SuperDirtMixer" Named {requiredArgs = ["orbit"]}
oscmap = [(superDirtMixerTarget, [oscplay])]

superDirtMixer <- startStream (defaultConfig {cCtrlPort = 6011}) oscmap

let x1 = streamReplace superDirtMixer 1 . (|< orbit 0)
x2 = streamReplace superDirtMixer 2 . (|< orbit 1)
x3 = streamReplace superDirtMixer 3 . (|< orbit 2)
x4 = streamReplace superDirtMixer 4 . (|< orbit 3)
x5 = streamReplace superDirtMixer 5 . (|< orbit 4)
x6 = streamReplace superDirtMixer 6 . (|< orbit 5)
x7 = streamReplace superDirtMixer 7 . (|< orbit 6)
x8 = streamReplace superDirtMixer 8 . (|< orbit 7)
x9 = streamReplace superDirtMixer 9 . (|< orbit 8)
x10 = streamReplace superDirtMixer 10 . (|< orbit 9)
x11 = streamReplace superDirtMixer 11 . (|< orbit 10)
x12 = streamReplace superDirtMixer 12 . (|< orbit 11)
x13 = streamReplace superDirtMixer 13 . (|< orbit 12)
x14 = streamReplace superDirtMixer 14 . (|< orbit 13)

-- This is needed to silence all patterns from both streams
hush = do
streamHush tidal
streamHush superDirtMixer

```

Then you should be able to run these TidalCycles patterns independently from. your other patterns and see the changes in the ui. I.e.
```haskell
x1 $
stack [
-- Equalizer
every 2 rev $ loShelfFreq "100"
<| loShelfGain
(segment 64 $ range "-8" 16 sine)
,loPeakGain "<-10 -5 8>"
<| (slow 2 $ loPeakFreq
(segment 64 $ range 100 5000 sine))
, midPeakGain "<10>"
<| midPeakFreq
(slow 2 $ segment 64 $ range 400 2000 isaw)
, hiPeakGain "<12 -6 -8>"
<| hiPeakFreq
(slow 2 $ segment 64 $ range 8000 1000 cosine)
, loPassFreq "<7000 5000 10000 1000>"
, loPassBypass "<1 0>"
, hiShelfFreq "7000"
<| hiShelfGain
(segment 64 $ range "-8" 16 sine)
-- Compressor
, cpThresh "<-40 -20 -10 0>" <| cpRatio "1 2 3 4" # cpGain "<10 4 2 0>"
, pan "[0 0.25 0.5 0.75 1]"
]

```

## Shoutouts

- Wouter Snoei for the MasterEQ which influenced the EQui
Expand Down
7 changes: 3 additions & 4 deletions classes/SuperDirtMixer.sc
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
/*
Optional TODOs
- [] Disable MIDI Part section
- [] Release everything when GUI is closed
- [] Add a documentation for the remote control (BootTidal adjustment - hush, stream etc., add pattern functions)
- [] Create a reel to preset the features (mixer, equalizer, compressor, stage master, preset management)
*/
SuperDirtMixer {
var dirt;
var <>presetPath = "../../presets/";
var <>prMasterBus;
var <>switchControlButtonEvent;
var >midiInternalOut;
var reverbVariableName = \room;
var reverbNativeSize = 0.95;
var oscMasterLevelSender;
Expand Down Expand Up @@ -91,7 +90,7 @@ SuperDirtMixer {
reverbVariableName = variableName;
}

enableMasterPeakRMS { |masterBus|
setMasterBus { |masterBus|
this.prMasterBus = masterBus;

oscMasterLevelSender = {
Expand All @@ -113,7 +112,7 @@ SuperDirtMixer {
var mixerUI = MixerUI.new(eventHandler, dirt.orbits);
var utilityUI = UtilityUI.new(eventHandler, dirt.orbits, presetPath);
var equalizerUI = EqualizerUI.new(eventHandler, dirt.orbits);
var midiControlUI = MidiControlUI.new(switchControlButtonEvent);
var midiControlUI = MidiControlUI.new(switchControlButtonEvent, midiInternalOut);
var compressorUI = CompressorUI.new(eventHandler, dirt.orbits);

mixerUI.reverbVariableName = reverbVariableName;
Expand Down
4 changes: 2 additions & 2 deletions classes/uiComponents/CompressorUI.sc
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,9 @@ CompressorUI : UIFactories {
var effect = orbit.globalEffects.detect({| effect | effect.name.asSymbol == \dirt_global_compressor.asSymbol; });

if(orbit.get(\activeCompressor) == 1, {
effect.bypass_(false);
effect.active_(true);
}, {
effect.bypass_(true);
effect.active_(false);
});
}

Expand Down
4 changes: 2 additions & 2 deletions classes/uiComponents/EqualizerUI.sc
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,9 @@ EqualizerUI : UIFactories{
var effect = this.searchForEffectSynth(orbit);

if(orbit.get(\activeEq) == 1, {
effect.bypass_(false);
effect.active_(true);
}, {
effect.bypass_(true);
effect.active_(false);
});
}

Expand Down
38 changes: 22 additions & 16 deletions classes/uiComponents/MidiControlUI.sc
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
MidiControlUI {
var midiControlButtons;
var switchControlButtonEvent;
var midiOut;

*new { |initSwitchControlButtonEvent|
^super.new.init(initSwitchControlButtonEvent);
*new { |initSwitchControlButtonEvent, initMidiOut|
^super.new.init(initSwitchControlButtonEvent, initMidiOut);
}

init { |initSwitchControlButtonEvent|
init { |initSwitchControlButtonEvent, initMidiOut|
midiControlButtons = Array.new(20);
switchControlButtonEvent = initSwitchControlButtonEvent;
midiOut = initMidiOut;

this.addMidiControlButtonListener;
}
Expand All @@ -23,7 +25,7 @@ MidiControlUI {
16.do({|item|
var button = Button.new
.action_({
~midiInternalOut.control(0, item + 100, 0);
midiOut.control(0, item + 100, 0);
})
.string_(item + 1).minHeight_(36).minWidth_(36);

Expand All @@ -34,18 +36,22 @@ MidiControlUI {

reshapedMidiControlButtons = midiControlButtons.reshape(8,2);

^VLayout(
StaticText.new.string_("MIDI Part Switch").fixedHeight_(15).align_(\center),
HLayout(*reshapedMidiControlButtons[0]),
HLayout(*reshapedMidiControlButtons[1]),
HLayout(*reshapedMidiControlButtons[2]),
HLayout(*reshapedMidiControlButtons[3]),
HLayout(*reshapedMidiControlButtons[4]),
HLayout(*reshapedMidiControlButtons[5]),
HLayout(*reshapedMidiControlButtons[6]),
HLayout(*reshapedMidiControlButtons[7]),
100
);
if (midiOut.isNil.not,{
^VLayout(
StaticText.new.string_("MIDI Part Switch").fixedHeight_(15).align_(\center),
HLayout(*reshapedMidiControlButtons[0]),
HLayout(*reshapedMidiControlButtons[1]),
HLayout(*reshapedMidiControlButtons[2]),
HLayout(*reshapedMidiControlButtons[3]),
HLayout(*reshapedMidiControlButtons[4]),
HLayout(*reshapedMidiControlButtons[5]),
HLayout(*reshapedMidiControlButtons[6]),
HLayout(*reshapedMidiControlButtons[7]),
100
);
}, {
^VLayout()
});
}

addMidiControlButtonListener {
Expand Down
3 changes: 3 additions & 0 deletions tidal/src/PatternFunctions.hs
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,6 @@ let cpAttack = pF "cpAttack"
cpHpf = pF "cpHpf"
cpKnee = pF "cpKnee"
cpBias = pF "cpBias"

-- Mixer
let masterGain = pF "masterGain"

0 comments on commit 130a504

Please sign in to comment.