Browse Source

Lovely job. Need to get metronome working

Pete Shadbolt 4 years ago
parent
commit
ba193b290a
4 changed files with 70 additions and 23 deletions
  1. 40
    18
      main.ck
  2. 5
    0
      main.py
  3. 1
    0
      run.sh
  4. 24
    5
      scratch.ck

+ 40
- 18
main.ck View File

@@ -1,52 +1,56 @@
1 1
 // TODO: turn off adcThru when recording
2 2
 // Effects chain
3
-adc => Gain adcThru => Gain mixer => dac; // Monitor input through a mixer
3
+adc => Gain adcThru => dac; // Monitor input through a mixer
4 4
 SampleChan channels[4];
5 5
 
6 6
 // Levels
7 7
 //0 => adc.gain;
8 8
 .5 => adcThru.gain;
9 9
 
10
+// Global loop time
11
+1::second => dur loopTime;
12
+
10 13
 // Each channel should output to the mixer
11
-for( 0 => int i; i < channels.cap(); i++ ) { channels[i].outputTo(mixer); }
14
+for( 0 => int i; i < channels.cap(); i++ ) { channels[i].outputTo(dac); }
12 15
 
13 16
 // Listen to OSC messages
14 17
 OscIn oin; 9000 => oin.port; 
15 18
 oin.listenAll(); 
16 19
 OscMsg msg;
17 20
 
21
+// Start the metronome
22
+0 => int metronomeLevel;
23
+spork ~plip();
24
+
18 25
 // Event loop
19 26
 while (true) { 
20 27
     oin => now; 
21
-    //1::second => now;
22 28
     while (oin.recv(msg)) { 
23
-        if (msg.address=="/input") 
24
-        {
29
+        if (msg.address=="/input") {
25 30
             msg.getFloat(0) => adc.gain;
26 31
             msg.getFloat(1) => adcThru.gain;
27 32
         }
28
-        else if(msg.address=="/delay")
29
-        {
30
-            msg.getFloat(0)::second => dur loopPoint;
33
+        else if(msg.address=="/delay") {
34
+            msg.getFloat(0)::second => loopTime;
31 35
             msg.getFloat(1) => float feedback;
32 36
             for( 0 => int i; i < channels.cap(); i++ ) { 
33
-                channels[i].setLoopPoint(loopPoint); 
37
+                channels[i].setLoopPoint(loopTime); 
34 38
                 channels[i].setFeedback(feedback);
35 39
             }
36 40
          }
37
-        else if(msg.address=="/channel")
38
-        {
41
+        else if(msg.address=="/channel") {
39 42
             msg.getInt(0) => int i;
40 43
             channels[i].setGain(msg.getFloat(1));
41 44
             channels[i].setPan(msg.getFloat(2));
42 45
         }
43
-        else if(msg.address=="/arm")
44
-        {
46
+        else if(msg.address=="/arm") {
45 47
             msg.getInt(0) => int channel;
46 48
             for( 0 => int i; i < channels.cap(); i++ ) { channels[i].arm(i==channel); }
47 49
         }
48
-        else if(msg.address=="/clear")
49
-        {
50
+        else if(msg.address=="/metronome") {
51
+            msg.getInt(0) => metronomeLevel;
52
+        }
53
+        else if(msg.address=="/clear") {
50 54
             msg.getInt(0) => int channel;
51 55
             channels[channel].clear();
52 56
         }
@@ -56,7 +60,7 @@ while (true) {
56 60
 public class SampleChan
57 61
 {
58 62
     // Chain
59
-    adc => LiSa sample => LPF filter;
63
+    adc => LiSa sample => LPF filter => Pan2 panner;
60 64
 
61 65
     // Setup
62 66
     10::second => sample.duration;  //This is the max duration
@@ -71,12 +75,12 @@ public class SampleChan
71 75
     public void setFeedback( float fb ) { fb => sample.feedback; }
72 76
     public void setFilter( float freq ) { freq => filter.freq; }
73 77
     public void setGain( float gain ) { gain => filter.gain; }
74
-    public void setPan( float pan ) { }
78
+    public void setPan( float pan ) { pan => panner.pan; }
75 79
     public void clear() { sample.clear(); }
76 80
 
77 81
     public void outputTo(UGen ugen) { 
78 82
         1 => sample.play; 
79
-        filter => ugen; 
83
+        panner => ugen; 
80 84
     }
81 85
 
82 86
     public void arm(int value) {
@@ -85,3 +89,21 @@ public class SampleChan
85 89
     }
86 90
 }
87 91
 
92
+
93
+// TODO timing here should be done using events
94
+fun void plip()
95
+{
96
+    SinOsc s => dac;
97
+    0.01::second => dur plipTime;
98
+
99
+    while(true){
100
+        for( 0 => int i; i < 4; i++ ) { 
101
+            if (i==0){2000 => s.freq;} else {1000 => s.freq;}
102
+            .1*metronomeLevel => s.gain;
103
+            plipTime => now;
104
+            0 => s.gain;
105
+            loopTime/4 - plipTime => now;
106
+        }
107
+    }
108
+
109
+}

+ 5
- 0
main.py View File

@@ -102,6 +102,7 @@ class DelayPanel(wx.Panel):
102 102
         self.SetSizerAndFit(sizer)
103 103
         self.delayTime.Bind(wx.EVT_SCROLL, self.update)
104 104
         self.feedback.Bind(wx.EVT_SCROLL, self.update)
105
+        self.metronome.Bind(wx.EVT_TOGGLEBUTTON, self.switchMetronome)
105 106
         self.update(None)
106 107
 
107 108
     def update(self, evt):
@@ -110,6 +111,10 @@ class DelayPanel(wx.Panel):
110 111
         b=self.feedback.slider.GetValue()/100.
111 112
         sendOSCMsg("/delay", [a, b])
112 113
 
114
+    def switchMetronome(self, evt):
115
+        """ Send OSC messages """
116
+        sendOSCMsg("/metronome", [int(self.metronome.GetValue())])
117
+
113 118
 class Channel(wx.Panel):
114 119
     """ A single channel """
115 120
     def __init__(self, parent, index):

+ 1
- 0
run.sh View File

@@ -1,4 +1,5 @@
1 1
 #!/bin/bash
2
+#chuck scratch.ck
2 3
 chuck --bufsize64 main.ck &
3 4
 python ./main.py
4 5
 pkill -SIGINT chuck

+ 24
- 5
scratch.ck View File

@@ -1,7 +1,26 @@
1
-SinOsc s => Pan2 p => dac;
2
-1 => p.pan;
1
+1::second => dur loopTime;
3 2
 
4
-while(1::second => now){
5
-    // this will flip the pan from left to right
6
-    p.pan() * -1. => p.pan;
3
+fun void plip()
4
+{
5
+    SinOsc s => dac;
6
+    0.05::second => dur plipTime;
7
+    2000 => s.freq;
8
+
9
+    while(true){
10
+        .1 => s.gain;
11
+        plipTime => now;
12
+        0 => s.gain;
13
+        loopTime - plipTime => now;
14
+    }
15
+
16
+}
17
+
18
+spork ~plip();
19
+
20
+while(true){
21
+    1::second => now;
22
+    loopTime - 0.1::second => loopTime;
7 23
 }
24
+
25
+
26
+