diff --git a/main.ck b/main.ck index 877b140..8615755 100644 --- a/main.ck +++ b/main.ck @@ -1,6 +1,10 @@ // TODO: turn off adcThru when recording // Effects chain -adc => Gain adcThru => dac; // Monitor input through a mixer +adc => Dyno limitIn => Gain adcThru => dac; // Monitor input through a mixer +// Global effects break panning for some unknown reason +/*Dyno limitOut => JCRev rev => dac;*/ +/*Dyno limitOut => JCRev rev => dac;*/ +limitIn.limit(); limitOut.limit(); SampleChan channels[4]; // Levels @@ -11,7 +15,7 @@ SampleChan channels[4]; 1::second => dur loopTime; // Each channel should output to the mixer -for( 0 => int i; i < channels.cap(); i++ ) { channels[i].outputTo(dac); } +for( 0 => int i; i < channels.cap(); i++ ) { channels[i].outputTo(limitOut); } // Listen to OSC messages OscIn oin; 9000 => oin.port; @@ -20,7 +24,8 @@ OscMsg msg; // Start the metronome 0 => int metronomeLevel; -spork ~plip(); +//spork ~plip(); +//spork ~vu_meter(); // Event loop while (true) { @@ -60,21 +65,18 @@ while (true) { public class SampleChan { // Chain - adc => LiSa sample => LPF filter => Pan2 panner; + adc => LiSa sample => Pan2 panner; // Setup 10::second => sample.duration; //This is the max duration 0::second => sample.recPos => sample.playPos; 1.0 => sample.feedback; 1 => sample.loop; - 1 => filter.Q; setLoopPoint(1::second); - setFilter(10000); public void setLoopPoint( dur length ) { length => sample.loopEnd => sample.loopEndRec; } public void setFeedback( float fb ) { fb => sample.feedback; } - public void setFilter( float freq ) { freq => filter.freq; } - public void setGain( float gain ) { gain => filter.gain; } + public void setGain( float gain ) { gain => panner.gain; } public void setPan( float pan ) { pan => panner.pan; } public void clear() { sample.clear(); } @@ -89,6 +91,28 @@ public class SampleChan } } +fun void vu_meter() +{ + // Analysis stuff + adc => FFT fft =^ RMS rms => blackhole; + 1<<12 => int fftsize; + fftsize => fft.size; + Windowing.hann(fftsize) => fft.window; + + // Comms + OscOut xmit; xmit.dest( "localhost", 6649 ); + + // Infinite loop: get RMS and send to GUI + while(true) + { + rms.upchuck() @=> UAnaBlob blob; + xmit.start("/vu"); + blob.fval(0) => xmit.add; + xmit.send(); + fft.size()::samp => now; + } +} + // TODO timing here should be done using events fun void plip() diff --git a/main.py b/main.py index fecd843..522edba 100644 --- a/main.py +++ b/main.py @@ -31,8 +31,11 @@ class CommsPanel(wx.Panel): font = label.GetFont(); font.SetWeight(wx.BOLD); label.SetFont(font) sizer.Add(label, 0, wx.TOP|wx.BOTTOM|wx.RIGHT|wx.EXPAND, 5) - self.master = wx.ToggleButton(self, 1, "Master/Minion") - sizer.Add(self.master, 0, wx.ALL, 3) + + choices=["Master", "Minion"] + self.master= wx.ComboBox(self, choices=choices, style=wx.CB_READONLY, size=(25,25)) + sizer.Add(self.master, 1, wx.ALL, 3) + self.master.SetValue(choices[0]) self.ip=wx.TextCtrl(self, value="127.0.0.1") sizer.Add(self.ip, 0, wx.ALL, 3) @@ -42,7 +45,6 @@ class CommsPanel(wx.Panel): self.SetSizerAndFit(sizer) - class InputPanel(wx.Panel): ''' Handle the ADC input settings ''' def __init__(self, parent): @@ -50,7 +52,7 @@ class InputPanel(wx.Panel): wx.Panel.__init__(self, parent) sizer = wx.BoxSizer(wx.HORIZONTAL) - label = wx.StaticText(self, label="Line in:") + label = wx.StaticText(self, label="Input:") font = label.GetFont(); font.SetWeight(wx.BOLD); label.SetFont(font) sizer.Add(label, 0, wx.TOP|wx.BOTTOM|wx.RIGHT, 5) @@ -59,7 +61,7 @@ class InputPanel(wx.Panel): self.thru = OSCSlider(self, "Thru", default_value=.5, align=False) sizer.Add(self.thru, 1, wx.ALL, 5) - self.mute = wx.ToggleButton(self, 1, "Mute") + self.mute = wx.ToggleButton(self, 0, "Mute") #self.mute.SetValue(1) sizer.Add(self.mute, 0) self.SetSizerAndFit(sizer) @@ -82,19 +84,19 @@ class DelayPanel(wx.Panel): def __init__(self, parent): ''' Constructor ''' wx.Panel.__init__(self, parent) - sizer = wx.BoxSizer(wx.VERTICAL) + sizer = wx.BoxSizer(wx.HORIZONTAL) - label = wx.StaticText(self, label="Delay lines:") + label = wx.StaticText(self, label="Loop:") font = label.GetFont(); font.SetWeight(wx.BOLD); label.SetFont(font) sizer.Add(label, 0, wx.TOP|wx.BOTTOM|wx.RIGHT, 5) - self.delayTime=OSCSlider(self, "Delay time (s)", default_value=1, max_value=10) - sizer.Add(self.delayTime, 0, wx.EXPAND|wx.ALL, 5) + self.delayTime=OSCSlider(self, "Time", default_value=1, max_value=10, align=False) + sizer.Add(self.delayTime, 1, wx.EXPAND|wx.ALL, 5) - self.feedback=OSCSlider(self, "Feedback", default_value=.99) - sizer.Add(self.feedback, 0, wx.EXPAND|wx.ALL, 5) + self.feedback=OSCSlider(self, "Hold", default_value=.99, align=False) + sizer.Add(self.feedback, 1, wx.EXPAND|wx.ALL, 5) - self.metronome=wx.ToggleButton(self, 0, "Metronome") + self.metronome=wx.ToggleButton(self, 0, "Click") sizer.Add(self.metronome, 0, wx.EXPAND|wx.ALL, 5) self.SetSizerAndFit(sizer) @@ -113,6 +115,21 @@ class DelayPanel(wx.Panel): """ Send OSC messages """ sendOSCSafe("/metronome", [int(self.metronome.GetValue())]) +class ButtonArray(wx.Panel): + ''' Handle the ADC input settings ''' + def __init__(self, parent, index): + wx.Panel.__init__(self, parent) + w=40 + sizer = wx.BoxSizer(wx.HORIZONTAL) + self.record = wx.ToggleButton(self, 0, "Arm", size=(w,25)) + sizer.Add(self.record, 1, wx.ALL, 0) + self.mute = wx.ToggleButton(self, 0, "Mute", size=(w,25)) + sizer.Add(self.mute, 1, wx.ALL, 0) + self.clear = wx.Button(self, 0, "Clear", size=(w,25)) + sizer.Add(self.clear, 1, wx.ALL, 0) + self.buttons=(self.record, self.mute, self.clear) + self.SetSizerAndFit(sizer) + class Channel(wx.Panel): """ A single channel """ def __init__(self, parent, index): @@ -120,9 +137,9 @@ class Channel(wx.Panel): wx.Panel.__init__(self, parent) sizer = wx.BoxSizer(wx.VERTICAL) - label = wx.StaticText(self, label="CH%d" % self.index) - font = label.GetFont(); font.SetWeight(wx.BOLD); label.SetFont(font) - sizer.Add(label, 0, wx.TOP|wx.BOTTOM|wx.RIGHT, 5) + #label = wx.StaticText(self, label="CH%d" % self.index) + #font = label.GetFont(); font.SetWeight(wx.BOLD); label.SetFont(font) + #sizer.Add(label, 0, wx.TOP|wx.BOTTOM|wx.RIGHT, 5) self.gain = OSCSlider(self, "Gain", default_value=1, max_value=1.3, align=False) sizer.Add(self.gain, 0, wx.ALL|wx.EXPAND, 3) @@ -133,15 +150,11 @@ class Channel(wx.Panel): self.fxsend = OSCSlider(self, "Dry/Wet", default_value=0, min_value=0, max_value=1, align=False) sizer.Add(self.fxsend, 0, wx.ALL|wx.EXPAND, 3) - self.record = wx.ToggleButton(self, 1, "Arm") - sizer.Add(self.record, 0, wx.ALL|wx.EXPAND if index==0 else wx.ALL|wx.EXPAND, 3) - - self.mute = wx.ToggleButton(self, 1, "Mute") - sizer.Add(self.mute, 0, wx.ALL|wx.EXPAND, 3) - self.clear = wx.Button(self, 1, "Clear") - sizer.Add(self.clear, 0, wx.ALL|wx.EXPAND, 3) + self.buttons=ButtonArray(self, index) + self.record, self.mute, self.clear = self.buttons.buttons + sizer.Add(self.buttons, 0, wx.ALL|wx.EXPAND, 3) - choices=["1 bar", "2 bars", "4 bars", "Dephase"] + choices=["1 bar", "2 bars", "4 bars", "Dephase", "1/2 rate"] self.speed= wx.ComboBox(self, choices=choices, style=wx.CB_READONLY, size=(25,25)) self.speed.SetValue("1 bar") sizer.Add(self.speed, 0, wx.ALL|wx.EXPAND, 3) @@ -198,19 +211,19 @@ class FXPanel(wx.Panel): def __init__(self, parent): ''' Constructor ''' wx.Panel.__init__(self, parent) - sizer = wx.BoxSizer(wx.VERTICAL) + sizer = wx.BoxSizer(wx.HORIZONTAL) label = wx.StaticText(self, label="FX:") font = label.GetFont(); font.SetWeight(wx.BOLD); label.SetFont(font) - sizer.Add(label, 0, wx.TOP|wx.BOTTOM|wx.RIGHT, 5) + sizer.Add(label, 0, wx.EXPAND|wx.TOP|wx.BOTTOM|wx.RIGHT, 5) choices=["Low pass filter", "High pass filter", "Reverb"] self.fxtype= wx.ComboBox(self, choices=choices, style=wx.CB_READONLY, size=(25,25)) - sizer.Add(self.fxtype, 0, wx.ALL|wx.EXPAND, 5) + sizer.Add(self.fxtype, 1, wx.ALL|wx.EXPAND, 5) self.fxtype.SetValue(choices[0]) - self.delayTime=OSCSlider(self, "Strength", default_value=0) - sizer.Add(self.delayTime, 0, wx.EXPAND|wx.ALL, 5) + self.fxStrength=OSCSlider(self, "", default_value=0, align=False) + sizer.Add(self.fxStrength, 2, wx.EXPAND|wx.ALL, 5) self.SetSizerAndFit(sizer) #self.update(None) @@ -223,6 +236,32 @@ class FXPanel(wx.Panel): sendOSCSafe("/delay", [a, b]) """ +class OutputPanel(wx.Panel): + ''' Handle the ADC input settings ''' + def __init__(self, parent): + ''' Constructor ''' + wx.Panel.__init__(self, parent) + sizer = wx.BoxSizer(wx.HORIZONTAL) + + label = wx.StaticText(self, label="Output:") + font = label.GetFont(); font.SetWeight(wx.BOLD); label.SetFont(font) + sizer.Add(label, 0, wx.TOP|wx.BOTTOM|wx.RIGHT, 5) + + self.level=OSCSlider(self, "Level", default_value=.8, align=False) + sizer.Add(self.level, 2, wx.EXPAND|wx.ALL, 5) + + self.gauge = wx.Gauge(self, size=(40,10)) + sizer.Add(self.gauge, 1, wx.EXPAND|wx.ALL, 5) + + self.SetSizerAndFit(sizer) + + """ + def update(self, evt): + a=self.delayTime.slider.GetValue()/100. + b=self.feedback.slider.GetValue()/100. + sendOSCSafe("/delay", [a, b]) + """ + class MainGUI(wx.Frame): """ A simple GUI to talk to Chuck """ @@ -231,7 +270,12 @@ class MainGUI(wx.Frame): # Build the interface self.app = wx.App(False) self.build() - self.app.MainLoop() + + def run(self): self.app.MainLoop() + + def update_vu(self, a,b,c,d): + level=int(1000000*c[0]) + self.output.gauge.SetValue(level) def build(self): """ Builds the various pieces of the GUI """ @@ -257,13 +301,18 @@ class MainGUI(wx.Frame): line=wx.StaticLine(self); self.mainsizer.Add(line, 0, wx.EXPAND|wx.ALL, 1) self.mixer = Mixer(self) - self.mainsizer.Add(self.mixer, 1, wx.EXPAND|wx.ALL, 5) + self.mainsizer.Add(self.mixer, 0, wx.EXPAND|wx.ALL, 5) line=wx.StaticLine(self); self.mainsizer.Add(line, 0, wx.EXPAND|wx.ALL, 1) self.fx = FXPanel(self) self.mainsizer.Add(self.fx, 0, wx.EXPAND|wx.ALL, 5) + line=wx.StaticLine(self); self.mainsizer.Add(line, 0, wx.EXPAND|wx.ALL, 1) + + self.output = OutputPanel(self) + self.mainsizer.Add(self.output, 0, wx.EXPAND|wx.ALL, 5) + # Put things together self.SetSizerAndFit(self.mainsizer) self.Show() @@ -281,4 +330,7 @@ class MainGUI(wx.Frame): if __name__ == "__main__": initOSCClient(ip="127.0.0.1", port=9000) g=MainGUI() + #initOSCServer(ip="127.0.0.1", port=6649, mode=0) + #setOSCHandler("/vu", g.update_vu) + g.run() closeOSC()