Pete Shadbolt 10 лет назад
Родитель
Сommit
1f478ce4b1
3 измененных файлов: 83 добавлений и 79 удалений
  1. +49
    -34
      main.ck
  2. +21
    -6
      main.py
  3. +13
    -39
      scratch.ck

+ 49
- 34
main.ck Просмотреть файл

@@ -1,29 +1,32 @@
//TODO: turn off adcThru when recording, and turn it back on afterwards
//TODO: Effects break panning for some unknown reason
//TODO varying number of bars
NRev reverb => LPF lpf => HPF hpf => Dyno outputLimiter => dac;
outputLimiter.limit();
NRev reverb => LPF lpf => HPF hpf => Dyno fxLimiter => dac;
Dyno outputDryLeft => dac.left;
Dyno outputDryRight => dac.right;
fxLimiter.limit();
outputDryLeft.limit();
outputDryRight.limit();
reverb @=> UGen @ outputWet; // Reference to wet output
outputLimiter @=> UGen @ outputDry; // Reference to dry output
outputLimiter @=> UGen @ mainOutput; // Reference to main output

// Capture mic/line in and monitor through DAC. Limit
adc => Dyno inputLimiter => Gain adcThru => mainOutput; // Monitor input
adc => Dyno inputLimiter => Gain adcThru => fxLimiter; // Monitor input
inputLimiter.limit();
inputLimiter @=> UGen @ mainInput;

// Default parameters
1 => float adcThruLevel;
0 => float adcThruLevel;
1 => int adcThruMute;
adcThruLevel * adcThruMute => adcThru.gain;
10000 => lpf.freq;
10 => hpf.freq;
2::second => dur globalLoopTime;

// Plug in the pedals
LoopPedal pedals[4];
for( 0 => int i; i < pedals.cap(); i++ ) {
pedals[i].recordFrom(mainInput);
pedals[i].outputTo(outputWet, outputDry);
pedals[i].outputTo(outputWet, outputDryLeft, outputDryRight);
}

// Create the metronome
@@ -45,10 +48,10 @@ while (true) {
adcThruLevel * adcThruMute => adcThru.gain;
}
else if(msg.address=="/delay") {
msg.getFloat(0)::second => dur loopTime;
msg.getFloat(0)::second => globalLoopTime;
msg.getFloat(1) => float feedback;
for( 0 => int i; i < pedals.cap(); i++ ) {
pedals[i].setLoopPoint(loopTime);
pedals[i].setLoopPoint(globalLoopTime);
pedals[i].setFeedback(feedback);
}
}
@@ -58,6 +61,10 @@ while (true) {
pedals[i].setPan(msg.getFloat(2));
pedals[i].setWet(msg.getFloat(3));
}
else if(msg.address=="/multiplier"){
msg.getInt(0) => int i;
pedals[i].setLoopPoint(globalLoopTime * msg.getFloat(1));
}
else if(msg.address=="/arm") {
msg.getInt(0) => int channel;
(channel<0) => adcThruMute;
@@ -77,7 +84,10 @@ while (true) {
msg.getFloat(2) => reverb.mix;
}
else if(msg.address=="/master") {
msg.getFloat(0) => mainOutput.gain;
msg.getFloat(0) => float masterGain;
masterGain => outputDryLeft.gain;
masterGain => outputDryRight.gain;
masterGain => fxLimiter.gain;
}
}
}
@@ -87,31 +97,34 @@ class LoopPedal
// We are wrapping a live sampler, LiSa
LiSa sample;
sample => Gain wet;
sample => Gain dry;
dur loopTime;
sample => Pan2 dry;

// Setup
10::second => sample.duration; // Allocate max 10 secs of memory
0::second => sample.recPos => sample.playPos;
1.0 => sample.feedback;
1 => sample.loop;
/*.5 => sample.rate;*/
setLoopPoint(1::second);
dur loopTime;
setLoopPoint(2::second);
setWet(0.5);

public void setLoopPoint( dur length ) { length => loopTime => sample.loopEnd => sample.loopEndRec; }
public void setLoopPoint( dur length ) {
length => loopTime => sample.loopEnd => sample.loopEndRec;
}
public void setFeedback( float fb ) { fb => sample.feedback; }
public void setGain( float gain ) { gain => sample.gain; }
public void setPan( float pan ) { } //pan => panner.pan; }
public void setPan( float pan ) { pan => dry.pan; }
public void setWet( float ratio ) { ratio => wet.gain; 1-ratio => dry.gain;}
public void clear() { sample.clear(); }
public void recordFrom(UGen ugen) { ugen => sample; }
// TODO: maybe this should be % looptime/multiplier?
public dur remaining() { return loopTime - sample.playPos(); }

public void outputTo(UGen wetSink, UGen drySink) {
public void outputTo(UGen wetSink, UGen drySinkLeft, UGen drySinkRight) {
1 => sample.play;
wet => wetSink;
dry => drySink;
dry.left => drySinkLeft;
dry.right => drySinkRight;
}

public void arm(int value) {
@@ -125,7 +138,9 @@ class Metronome
{
// A simple metronome
SinOsc s => ADSR a;
60 => s.freq;
0.5 => s.gain;
0.6 => s.gain;
a.set(0.001, .1, .5, .13);
10::ms => dur plipTime;

@@ -134,21 +149,21 @@ class Metronome
}

fun void run() {
while(true) {
// Compute the beat time
pedals[0].loopTime/4. - plipTime => dur beatTime;
// Beep four times
50 => s.freq;
a.keyOn(); plipTime => now; a.keyOff();
beatTime => now;
50 => s.freq;
a.keyOn(); plipTime => now; a.keyOff();
beatTime => now;
a.keyOn(); plipTime => now; a.keyOff();
beatTime => now;
a.keyOn(); plipTime => now; a.keyOff();
pedals[0].remaining() => now; // Sync
}
while(true) {
// Compute the beat time
globalLoopTime/4. - plipTime => dur beatTime;
// Beep four times
0.15::second => a.releaseTime;
a.keyOn(); plipTime => now; a.keyOff();
beatTime => now;
0.1::second => a.releaseTime;
a.keyOn(); plipTime => now; a.keyOff();
beatTime => now;
a.keyOn(); plipTime => now; a.keyOff();
beatTime => now;
a.keyOn(); plipTime => now; a.keyOff();
pedals[0].remaining() => now; // Sync
}
}
}

+ 21
- 6
main.py Просмотреть файл

@@ -188,16 +188,18 @@ class Channel(wx.Panel):
self.speed.SetValue(choices[0])
sizer.Add(self.speed, 0, wx.ALL | wx.EXPAND, 3)

choices = ["Live →", "Live ←", "Live ↔", "loop1.wav", "loop2.wav", "loop3.wav"]
self.speed = wx.ComboBox(self, choices=choices, style=wx.CB_READONLY, size=(25, 25))
self.speed.SetValue(choices[0])
sizer.Add(self.speed, 0, wx.ALL | wx.EXPAND, 3)
choices = ["Live →", "Live ←", "Live ↔", "Half speed"]
self.direction = wx.ComboBox(self, choices=choices, style=wx.CB_READONLY, size=(25, 25))
self.direction.SetValue(choices[0])
sizer.Add(self.direction, 0, wx.ALL | wx.EXPAND, 3)

self.SetSizerAndFit(sizer)

self.gain.Bind(wx.EVT_SCROLL, self.update)
self.pan.Bind(wx.EVT_SCROLL, self.update)
self.fxsend.Bind(wx.EVT_SCROLL, self.update)
self.speed.Bind(wx.EVT_COMBOBOX, self.update_multiplier)
self.direction.Bind(wx.EVT_TOGGLEBUTTON, self.update_direction)
self.mute.Bind(wx.EVT_TOGGLEBUTTON, self.update)
self.update()

@@ -205,10 +207,23 @@ class Channel(wx.Panel):
gain = self.gain.GetValue()
pan = self.pan.GetValue()
fxsend = self.fxsend.GetValue()
if self.mute.GetValue():
gain = 0.0
if self.mute.GetValue(): gain = 0.0
sendOSCSafe("/channel", [self.index, gain, pan, fxsend])

def update_multiplier(self, evt=None):
multiplierTable = {"1 bar": 1., "2 bars": 2., "4 bars": 4., "Dephase": 1.3}
multiplier = multiplierTable[self.speed.GetValue()]
sendOSCSafe("/multiplier", [self.index, multiplier])

def update_direction(self, evt=None):
#multiplierTable = {"1 bar": 1., "2 bars": 2., "4 bars": 4., "Dephase": 1.3}
directionTable = {"Live →":0, "Live ←"1, "Live ↔"2, "Half speed"3}

direction = directionTable[self.speed.GetValue()]
sendOSCSafe("/direction", [self.index, direction])




class Mixer(wx.Panel):



+ 13
- 39
scratch.ck Просмотреть файл

@@ -1,44 +1,18 @@
// the event
KBHit kb;
Dyno d;
SinOsc s => Pan2 p;
p.left => JCRev revr => dac.left;
p.right => JCRev revl => dac.right;
100 => s.freq;
.2 => s.gain;
.1 => p.gain;

class MetronomeEvent extends Event{ int value; }
-1 => p.pan;
1::second => now;

class Metronome {
MetronomeEvent metronomeEvent;
spork ~pulse();
0 => p.pan;
1::second => now;

fun void listen(){
while (true){
metronomeEvent => now;
<<<"Metronome got event " + metronomeEvent.value>>>;
if (metronomeEvent.value==0){
spork ~pulse();
}
}
}
1 => p.pan;
1::second => now;

fun void pulse(){
1::second => now;
0=>metronomeEvent.value;
metronomeEvent.signal();
}

fun void signal(){
1=>metronomeEvent.value;
metronomeEvent.signal();
}
}

Metronome m;
spork ~m.listen();

// time-loop
while( true )
{
kb => now;
while( kb.more() )
{
<<< "ascii: ", kb.getchar() >>>;
m.signal();
}
}

Загрузка…
Отмена
Сохранить