Revision 1:b5bcad8e7803

View differences:

CollidoscopeTeensy/CollidoscopeTeensy_new.ino
1

  
2
/******************************************************************************
3

  
4
 *  Ben Bengler
5
 *  mail@benbengler.com
6
 *  02.05.2016
7
 *
8
 *  Collidoscope 
9
 *  
10
 *  Teensy 2 ++ pinout: https://www.pjrc.com/teensy/card4b.pdf
11
 *  
12
 *  ANALOG INPUTS:
13
 *  Wavejet   -> F0 (38) [Horizontal rail 1]
14
 *  Wavejet   -> F1 (39) [Horizontal rail 2]
15
 *  Filter 1  -> F2 (40) [Vertical rail 1]
16
 *  Filter 2  -> F4 (42) [Vertical rail 2] 
17
 *
18
 *  DIGITAL INPUTS [INTERRUPTS]:
19
 *  Sel. length 1  -> INT0/INT1 (0, 1)  [Encoder 1]
20
 *  Sel. length 2  -> INT2/INT3 (2, 3)  [Encoder 2]
21
 *  Duration 1     -> INT4/INT5 (36, 37)[Encoder 3] 
22
 *  Duration 2     -> INT6/INT7 (18, 19)[Encoder 4] 
23
 *
24
 *  DIGITAL INPUTS:
25
 *  Play1 toggle  -> B0 (20)
26
 *  Record1       -> B1 (21)
27
 *  Play2 toggle  -> B3 (22)
28
 *  Record2       -> B4 (24)
29
 *  
30
 *  DIGITAL OUTPUTS:
31
 *  Record Button 1 Led -> D4 (4)
32
 *  Record Button 2 Led -> D5 (5)
33

  
34
 ******************************************************************************/ 
35

  
36

  
37
#include <Encoder.h>
38
#include <Bounce.h>
39

  
40
///////////////////////////////////////////////////
41
//MIDI settings
42
const int midi_chan_inst1 = 1; // MIDI channel for Instrument 1
43
const int midi_chan_inst2 = 2; // MIDI channel for Instrument 2
44

  
45
const int cc_length = 1;    // MIDI cc controlling selection length
46
const int cc_duration = 2;  // MIDI cc controlling duration
47
const int cc_filter = 7;    // MIDI cc controlling LP filter
48
const int cc_play = 4;      // MIDI cc controlling PLAY
49
const int cc_record = 5;    // MIDI cc controlling RECORD
50
//const int cc_reset = 100; // MIDI cc controlling instrument RESET
51

  
52
///////////////////////////////////////////////////
53
//Default Values:
54
const int  Enc_def = 64; //default selection length  
55
int MIDI_led_state = LOW;
56
//boolean reset1 = true;
57
//boolean reset2 = true;
58

  
59
///////////////////////////////////////////////////
60
// Interface Inputs
61

  
62
//Buttons:
63

  
64
const int Pin_play1 = 20;       //B0    
65
const int Pin_record1 = 21;     //B1
66
const int Pin_play2 = 23;       //B3
67
const int Pin_record2 = 24;     //B4
68
const int Pin_record1_led =  4; //D4
69
const int Pin_record2_led =  5; //D5
70
const int Pin_MIDIled =  6;
71

  
72
//const int Pin_reset1 = 22;    //B2, not in use
73
//const int Pin_reset2 = 25;    //B5, not in use
74

  
75
Bounce button1 = Bounce(Pin_play1, 5); 
76
Bounce button2 = Bounce(Pin_record1, 5); 
77
Bounce button3 = Bounce(Pin_play2, 5); 
78
Bounce button4 = Bounce(Pin_record2, 5); 
79

  
80
 
81
//Encoder
82
Encoder Enc1 (0, 1);  //Encoder for section length on Wavejet 1
83
Encoder Enc2 (2, 3);  //Encoder for section length on Wavejet 2
84
Encoder Enc3 (36, 37);  //Encoder for duration of Wavejet 1 [granularisation effect]
85
Encoder Enc4 (18, 19);  //Encoder for duration of Wavejet 2 [granularisation effect]
86

  
87
// Variables
88
const int jitter_thresh = 10; //7threshold value for analog INs to suppress sending MIDI due to input jitter 
89
const int jitter_thresh_short = 5;
90

  
91
void setup() {  
92

  
93
pinMode(Pin_play1, INPUT_PULLUP); 
94
pinMode(Pin_record1, INPUT_PULLUP);
95
pinMode(Pin_play2, INPUT_PULLUP);
96
pinMode(Pin_record2, INPUT_PULLUP);
97

  
98

  
99
pinMode(Pin_MIDIled, OUTPUT); 
100
pinMode(Pin_record1_led, OUTPUT);
101
pinMode(Pin_record2_led, OUTPUT);
102
}
103

  
104
//Store recent values to detect parameter change
105
long Enc1_old = -999;
106
long Enc2_old = -999;
107
long Enc3_old = -999;
108
long Enc4_old = -999;
109

  
110
uint16_t Jet1_old = 0;
111
int16_t Jet1_old_MIDI = -1;
112
uint16_t Jet2_old = 0;
113
int16_t Jet2_old_MIDI = -1;
114
uint16_t filter1_old = 0;
115
int16_t filter1_old_MIDI = -1;
116
uint16_t filter2_old = 0;
117
int16_t filter2_old_MIDI = -1;
118

  
119
void loop() {
120

  
121
  digitalWrite(Pin_MIDIled, LOW);
122
  digitalWrite(Pin_record1_led, HIGH);
123
  digitalWrite(Pin_record2_led, HIGH);
124
  button1.update();
125
  button2.update();
126
  button3.update();
127
  button4.update();
128

  
129
  
130
  uint16_t Jet1_new = analogRead(0); //read Wavejet/Rail 1
131
  uint16_t Jet2_new = analogRead(1); //read Wavejet/Rail 2
132
  uint16_t filter1_new = analogRead(2);   //read filter Instrument 1; ADJUST INPUT RANGE ACCORDING TO SENSOR    
133
  uint16_t filter2_new = analogRead(4);   //read filter Instrument 2; ADJUST INPUT RANGE ACCORDING TO SENSOR  
134

  
135

  
136
  
137
  //Encoder 1 [Controls selection length of wave 1]
138
  long Enc1_new = Enc1.read();
139
  Enc1_new = constrain(Enc1_new, 0, 127); //constrain to 7-bit MIDI range
140
  
141
  //Dynamic reset of counter to MIDI range 
142
  if (Enc1_new <= 0){
143
    Enc1.write(0); 
144
  }
145
  else if (Enc1_new >= 127){
146
    Enc1.write(127); 
147
  }
148
     
149
  //Encoder 2 [Controls selection length of wave 2]
150
  long Enc2_new = Enc2.read();
151
  Enc2_new = constrain(Enc2_new, 0, 127); //constrain to 7-bit MIDI range
152
  
153
  //Dynamic reset of counter to MIDI range 
154
  if (Enc2_new <= 0){
155
    Enc2.write(0); 
156
  }
157
  else if (Enc2_new >= 127){
158
    Enc2.write(127); 
159
  }
160

  
161
  //Encoder 3 [Controls duration of wave 1]
162
  long Enc3_new = Enc3.read();
163
  Enc3_new = constrain(Enc3_new, 0, 127); //constrain to 7-bit MIDI range
164
  
165
  //Dynamic reset of counter to MIDI range 
166
  if (Enc3_new <= 0){
167
    Enc3.write(0); 
168
  }
169
  else if (Enc3_new >= 127){
170
    Enc3.write(127); 
171
  }
172

  
173
  //Encoder 4 [Controls duration of wave 2]
174
  long Enc4_new = Enc4.read();
175
  Enc4_new = constrain(Enc4_new, 0, 127); //constrain to 7-bit MIDI range
176
  
177
  //Dynamic reset of counter to MIDI range 
178
  if (Enc4_new <= 0){
179
    Enc4.write(0); 
180
  }
181
  else if (Enc4_new >= 127){
182
    Enc4.write(127); 
183
  }
184

  
185
 
186
 //Instrument 1 Controls//////////////////////////////////////  
187
 
188
 //Loop/Keymode Switch Instrument 1 
189
   
190
 if (button1.risingEdge()) {   
191
   //Serial.println("Loop mode");
192
   usbMIDI.sendControlChange(cc_play, 1, midi_chan_inst1);
193
 }
194
   
195
 if (button1.fallingEdge()) {   
196
   //Serial.println("Keyboardmode mode");
197
   usbMIDI.sendControlChange(cc_play, 0, midi_chan_inst1);
198
 }
199
     
200
   
201
 //Record Instrument 1
202
 if (button2.fallingEdge()) {   
203
   //Serial.println("RECORD! Instrument 1");
204
   usbMIDI.sendControlChange(cc_record, 1, midi_chan_inst1);
205
 }
206

  
207
 //send MIDI Wavejet 1 [Position Instrument 1]
208
 if (Jet1_new > Jet1_old+jitter_thresh || Jet1_new < Jet1_old-jitter_thresh) {
209
    
210
    int16_t midiVal = constrain( map(Jet1_new, 988, 121, 0, 149), 0, 149 );
211
    // int16_t midiVal = constrain( map( Jet1_new, 23, 928, 0, 149 ), 0, 149 ); old collidoscope 
212
    if( midiVal != Jet1_old_MIDI ){
213
      Jet1_old_MIDI = midiVal;
214
      usbMIDI.sendPitchBend( midiVal, midi_chan_inst1 );
215
    }
216

  
217
    Jet1_old = Jet1_new;
218
    digitalWrite(Pin_MIDIled, HIGH);
219
 }
220

  
221

  
222
 //send MIDI Filter 1 [Filter Instrument 1]
223

  
224
 if ( filter1_new > filter1_old+jitter_thresh_short || filter1_new < filter1_old-jitter_thresh_short ) {         // maybe adding jitter threshold needed, see Jet1_new  
225
 
226
    int16_t midiVal = constrain( map(filter1_new, 145, 756, 0, 127), 0, 127 );
227
    if( midiVal != filter1_old_MIDI){
228
      //Serial.println( midiVal );
229
      filter1_old_MIDI = midiVal;
230
      usbMIDI.sendControlChange(cc_filter, midiVal, midi_chan_inst1);
231
    }
232
    
233
    filter1_old = filter1_new;
234
    digitalWrite(Pin_MIDIled, HIGH);
235
  }
236

  
237
  //send MIDI Encoder 1 [Selection length Instrument 1]
238
  if (Enc1_new != Enc1_old) {
239
    Enc1_old = Enc1_new;
240
    //Serial.println("Encoder 1: ");
241
    //Serial.println(Enc1_new);
242
    usbMIDI.sendControlChange(cc_length, Enc1_new, midi_chan_inst1);
243
    digitalWrite(Pin_MIDIled, HIGH);
244
  }
245

  
246
  //send MIDI Encoder 3 [Duration Instrument 1]
247
  if (Enc3_new != Enc3_old) {
248
    Enc3_old = Enc3_new;
249
    //Serial.println("Encoder 3: ");
250
    //Serial.println(Enc3_new);
251
    usbMIDI.sendControlChange(cc_duration, Enc3_new, midi_chan_inst1);
252
    digitalWrite(Pin_MIDIled, HIGH);
253
  }
254
  
255
  
256
  //Instrument 2 Controls//////////////////////////////////////  
257
  
258
  //Loop/Keymode Switch Instrument 2
259
   
260
  if (button3.risingEdge()) {   
261
    //Serial.println("Loop mode");
262
    usbMIDI.sendControlChange(cc_play, 1, midi_chan_inst2);
263
  }
264
  
265
  if (button3.fallingEdge()) {   
266
    //Serial.println("Keyboardmode mode");
267
    usbMIDI.sendControlChange(cc_play, 0, midi_chan_inst2);
268
  }
269
  
270
  //Record Instrument 2
271
  if (button4.fallingEdge()) {   
272
    //Serial.println("RECORD! Instrument 2");
273
    usbMIDI.sendControlChange(cc_record, 1, midi_chan_inst2);
274
  }
275

  
276
  //send MIDI Wavejet 2 [Position Instrument 2]
277
  
278
  if (Jet2_new > Jet2_old+jitter_thresh || Jet2_new < Jet2_old-jitter_thresh) {
279
    //Serial.println("RECORD! Instrument 2");
280
    int16_t midiVal = constrain( map( Jet2_new, 109, 992, 149, 0 ), 0, 149 );
281
    if( midiVal != Jet2_old_MIDI ){
282
      Jet2_old_MIDI = midiVal;
283
      usbMIDI.sendPitchBend( midiVal, midi_chan_inst2 );
284
    }
285

  
286
    Jet2_old = Jet2_new;
287
    digitalWrite(Pin_MIDIled, HIGH);
288
  }
289
  
290
 //Serial.println(filter2_new);
291
   if ( filter2_new > filter2_old+jitter_thresh_short || filter2_new < filter2_old-jitter_thresh_short ) {         // maybe adding jitter threshold needed, see Jet1_new  
292
    int16_t midiVal = constrain( map(filter2_new, 132, 700, 0, 127), 0, 127 );
293
    if( midiVal != filter2_old_MIDI){
294
      //Serial.println( midiVal );
295
      filter2_old_MIDI = midiVal;
296
      usbMIDI.sendControlChange(cc_filter, midiVal, midi_chan_inst2);
297
    }
298
    
299
    filter2_old = filter2_new;
300
    digitalWrite(Pin_MIDIled, HIGH);
301
  }
302
   
303
  
304
  //send MIDI Encoder 2 [Selection length Instrument 2]
305
  if (Enc2_new != Enc2_old) {
306
    Enc2_old = Enc2_new;
307
    //Serial.println("Encoder 2: ");
308
    //Serial.println(Enc2_new);
309
    usbMIDI.sendControlChange(cc_length, Enc2_new, midi_chan_inst2);
310
    digitalWrite(Pin_MIDIled, HIGH);
311
  }
312

  
313
  //send MIDI Encoder 4 [Duration Instrument 2]
314
  if (Enc4_new != Enc4_old) {
315
    Enc4_old = Enc4_new;
316
    //Serial.println("Encoder 4: ");
317
    //Serial.println(Enc4_new);
318
    usbMIDI.sendControlChange(cc_duration, Enc4_new, midi_chan_inst2);
319
    digitalWrite(Pin_MIDIled, HIGH);
320
  }
321
    
322
}
323

  
CollidoscopeTeensy/CollidoscopeTeensy_original.ino
1

  
2
/******************************************************************************
3

  
4
 *  Ben Bengler
5
 *  mail@benbengler.com
6
 *  02.05.2016
7
 *
8
 *  Collidoscope 
9
 *  
10
 *  Teensy 2 ++ pinout: https://www.pjrc.com/teensy/card4b.pdf
11
 *  
12
 *  ANALOG INPUTS:
13
 *  Wavejet   -> F0 (38) [Horizontal rail 1]
14
 *  Wavejet   -> F1 (39) [Horizontal rail 2]
15
 *  Filter 1  -> F2 (40) [Vertical rail 1]
16
 *  Filter 2  -> F4 (42) [Vertical rail 2] 
17
 *
18
 *  DIGITAL INPUTS [INTERRUPTS]:
19
 *  Sel. length 1  -> INT0/INT1 (0, 1)  [Encoder 1]
20
 *  Sel. length 2  -> INT2/INT3 (2, 3)  [Encoder 2]
21
 *  Duration 1     -> INT4/INT5 (36, 37)[Encoder 3] 
22
 *  Duration 2     -> INT6/INT7 (18, 19)[Encoder 4] 
23
 *
24
 *  DIGITAL INPUTS:
25
 *  Play1 toggle  -> B0 (20)
26
 *  Record1       -> B1 (21)
27
 *  Play2 toggle  -> B3 (22)
28
 *  Record2       -> B4 (24)
29
 *  
30
 *  DIGITAL OUTPUTS:
31
 *  Record Button 1 Led -> D4 (4)
32
 *  Record Button 2 Led -> D5 (5)
33

  
34
 ******************************************************************************/ 
35

  
36

  
37
#include <Encoder.h>
38
#include <Bounce.h>
39

  
40
///////////////////////////////////////////////////
41
//MIDI settings
42
const int midi_chan_inst1 = 1; // MIDI channel for Instrument 1
43
const int midi_chan_inst2 = 2; // MIDI channel for Instrument 2
44

  
45
const int cc_length = 1;    // MIDI cc controlling selection length
46
const int cc_duration = 2;  // MIDI cc controlling duration
47
const int cc_filter = 7;    // MIDI cc controlling LP filter
48
const int cc_play = 4;      // MIDI cc controlling PLAY
49
const int cc_record = 5;    // MIDI cc controlling RECORD
50
//const int cc_reset = 100; // MIDI cc controlling instrument RESET
51

  
52
///////////////////////////////////////////////////
53
//Default Values:
54
const int  Enc_def = 64; //default selection length  
55
int MIDI_led_state = LOW;
56
//boolean reset1 = true;
57
//boolean reset2 = true;
58

  
59
///////////////////////////////////////////////////
60
// Interface Inputs
61

  
62
//Buttons:
63

  
64
const int Pin_play1 = 20;       //B0    
65
const int Pin_record1 = 21;     //B1
66
const int Pin_play2 = 23;       //B3
67
const int Pin_record2 = 24;     //B4
68
const int Pin_record1_led =  4; //D4
69
const int Pin_record2_led =  5; //D5
70
const int Pin_MIDIled =  6;
71

  
72
//const int Pin_reset1 = 22;    //B2, not in use
73
//const int Pin_reset2 = 25;    //B5, not in use
74

  
75
Bounce button1 = Bounce(Pin_play1, 5); 
76
Bounce button2 = Bounce(Pin_record1, 5); 
77
Bounce button3 = Bounce(Pin_play2, 5); 
78
Bounce button4 = Bounce(Pin_record2, 5); 
79

  
80
 
81
//Encoder
82
Encoder Enc1 (0, 1);  //Encoder for section length on Wavejet 1
83
Encoder Enc2 (2, 3);  //Encoder for section length on Wavejet 2
84

  
85

  
86
// Variables
87
const int jitter_thresh = 10; //7threshold value for analog INs to suppress sending MIDI due to input jitter 
88

  
89
void setup() {  
90

  
91
pinMode(Pin_play1, INPUT_PULLUP); 
92
pinMode(Pin_record1, INPUT_PULLUP);
93
pinMode(Pin_play2, INPUT_PULLUP);
94
pinMode(Pin_record2, INPUT_PULLUP);
95

  
96

  
97
pinMode(Pin_MIDIled, OUTPUT); 
98
pinMode(Pin_record1_led, OUTPUT);
99
pinMode(Pin_record2_led, OUTPUT);
100
}
101

  
102
//Store recent values to detect parameter change
103
long Enc1_old = -999;
104
long Enc2_old = -999;
105

  
106
uint16_t Jet1_old = 0;
107
int16_t Jet1_old_MIDI = -1;
108
uint16_t Jet2_old = 0;
109
int16_t Jet2_old_MIDI = -1;
110

  
111
uint16_t filter1_old = 0;
112
int16_t filter1_old_MIDI = -1;
113
uint16_t filter2_old = 0;
114
int16_t filter2_old_MIDI = -1;
115

  
116
uint16_t dur1_old = 0;
117
int16_t dur1_old_MIDI = -1;
118
uint16_t dur2_old = 0;
119
int16_t dur2_old_MIDI = -1;
120

  
121
void loop() {
122

  
123
  digitalWrite(Pin_MIDIled, LOW);
124
  digitalWrite(Pin_record1_led, HIGH);
125
  digitalWrite(Pin_record2_led, HIGH);
126
  button1.update();
127
  button2.update();
128
  button3.update();
129
  button4.update();
130

  
131
  
132
  uint16_t Jet1_new = analogRead(0); //read Wavejet/Rail 1
133
  uint16_t Jet2_new = analogRead(1); //read Wavejet/Rail 2
134
  uint16_t filter1_new = analogRead(2);   //read filter Instrument 1; ADJUST INPUT RANGE ACCORDING TO SENSOR    
135
  uint16_t filter2_new = analogRead(4);   //read filter Instrument 2; ADJUST INPUT RANGE ACCORDING TO SENSOR  
136
  uint16_t dur1_new = analogRead(3); 
137
  uint16_t dur2_new = analogRead(5);
138

  
139
  
140
  //Encoder 1 [Controls selection length of wave 1]
141
  long Enc1_new = Enc1.read();
142
  Enc1_new = constrain(Enc1_new, 0, 127); //constrain to 7-bit MIDI range
143
  
144
  //Dynamic reset of counter to MIDI range 
145
  if (Enc1_new <= 0){
146
    Enc1.write(0); 
147
  }
148
  else if (Enc1_new >= 127){
149
    Enc1.write(127); 
150
  }
151
     
152
  //Encoder 2 [Controls selection length of wave 2]
153
  long Enc2_new = Enc2.read();
154
  Enc2_new = constrain(Enc2_new, 0, 127); //constrain to 7-bit MIDI range
155
  
156
  //Dynamic reset of counter to MIDI range 
157
  if (Enc2_new <= 0){
158
    Enc2.write(0); 
159
  }
160
  else if (Enc2_new >= 127){
161
    Enc2.write(127); 
162
  }
163

  
164
 //Instrument 1 Controls//////////////////////////////////////  
165
 
166
 //Loop/Keymode Switch Instrument 1 
167
   
168
 if (button1.risingEdge()) {   
169
   //Serial.println("Loop mode");
170
   usbMIDI.sendControlChange(cc_play, 1, midi_chan_inst1);
171
 }
172
   
173
 if (button1.fallingEdge()) {   
174
   //Serial.println("Keyboardmode mode");
175
   usbMIDI.sendControlChange(cc_play, 0, midi_chan_inst1);
176
 }
177
     
178
   
179
 //Record Instrument 1
180
 if (button2.fallingEdge()) {   
181
   //Serial.println("RECORD! Instrument 1");
182
   usbMIDI.sendControlChange(cc_record, 1, midi_chan_inst1);
183
 }
184

  
185
 //send MIDI Wavejet 1 [Position Instrument 1]
186
 
187
 if (Jet1_new > Jet1_old+jitter_thresh || Jet1_new < Jet1_old-jitter_thresh) {
188
    
189
    int16_t midiVal = constrain( map(Jet1_new, 24, 926, 0, 149), 0, 149 );
190
    // int16_t midiVal = constrain( map( Jet1_new, 23, 928, 0, 149 ), 0, 149 ); old collidoscope 
191
    if( midiVal != Jet1_old_MIDI ){
192
      Jet1_old_MIDI = midiVal;
193
      usbMIDI.sendPitchBend( midiVal, midi_chan_inst1 );
194
    }
195

  
196
    Jet1_old = Jet1_new;
197
    digitalWrite(Pin_MIDIled, HIGH);
198
 }
199

  
200

  
201
 //send MIDI Filter 1 [Filter Instrument 1]
202

  
203
 if ( filter1_new != filter1_old ) {         // maybe adding jitter threshold needed, see Jet1_new  
204

  
205
    int16_t midiVal = constrain( map(filter1_new, 0, 1024, 0, 127), 0, 127 );
206
    if( midiVal != filter1_old_MIDI){
207
      //Serial.println( midiVal );
208
      filter1_old_MIDI = midiVal;
209
      usbMIDI.sendControlChange(cc_filter, midiVal, midi_chan_inst1);
210
    }
211
    
212
    filter1_old = filter1_new;
213
    digitalWrite(Pin_MIDIled, HIGH);
214
  }
215

  
216
  if ( dur1_new != dur1_old ) {         // maybe adding jitter threshold needed, see Jet1_new  
217
 
218
    int16_t midiVal = constrain( map(dur1_new, 0, 1024, 0, 127), 0, 127 );
219
    if( midiVal != dur1_old_MIDI){
220
      //Serial.println( midiVal );
221
      dur1_old_MIDI = midiVal;
222
      usbMIDI.sendControlChange(cc_duration, midiVal, midi_chan_inst1);
223
    }
224
    
225
    dur1_old = dur1_new;
226
    digitalWrite(Pin_MIDIled, HIGH);
227
  }
228

  
229
  //send MIDI Encoder 1 [Selection length Instrument 1]
230
  if (Enc1_new != Enc1_old) {
231
    Enc1_old = Enc1_new;
232
    //Serial.println("Encoder 1: ");
233
    //Serial.println(Enc1_new);
234
    usbMIDI.sendControlChange(cc_length, Enc1_new, midi_chan_inst1);
235
    digitalWrite(Pin_MIDIled, HIGH);
236
  }
237

  
238
  
239
  
240
  //Instrument 2 Controls//////////////////////////////////////  
241
  
242
  //Loop/Keymode Switch Instrument 2
243
   
244
  if (button3.risingEdge()) {   
245
    //Serial.println("Loop mode");
246
    usbMIDI.sendControlChange(cc_play, 1, midi_chan_inst2);
247
  }
248
  
249
  if (button3.fallingEdge()) {   
250
    //Serial.println("Keyboardmode mode");
251
    usbMIDI.sendControlChange(cc_play, 0, midi_chan_inst2);
252
  }
253
  
254
  //Record Instrument 2
255
  if (button4.fallingEdge()) {   
256
    //Serial.println("RECORD! Instrument 2");
257
    usbMIDI.sendControlChange(cc_record, 1, midi_chan_inst2);
258
  }
259

  
260
  //send MIDI Wavejet 2 [Position Instrument 2]
261
  
262
  if (Jet2_new > Jet2_old+jitter_thresh || Jet2_new < Jet2_old-jitter_thresh) {
263
    //Serial.println("RECORD! Instrument 2");
264
    int16_t midiVal = constrain( map( Jet2_new, 925, 18, 149, 0 ), 0, 149 );
265
    if( midiVal != Jet2_old_MIDI ){
266
      Jet2_old_MIDI = midiVal;
267
      usbMIDI.sendPitchBend( midiVal, midi_chan_inst2 );
268
    }
269

  
270
    Jet2_old = Jet2_new;
271
    digitalWrite(Pin_MIDIled, HIGH);
272
  }
273
  
274
 //Serial.println(filter2_new);
275
   if ( filter2_new != filter2_old ) {         // maybe adding jitter threshold needed, see Jet1_new  
276
    int16_t midiVal = constrain( map(filter2_new, 0, 1024, 0, 127), 0, 127 );
277
    if( midiVal != filter2_old_MIDI){
278
      //Serial.println( midiVal );
279
      filter2_old_MIDI = midiVal;
280
      usbMIDI.sendControlChange(cc_filter, midiVal, midi_chan_inst2);
281
    }
282
    
283
    filter2_old = filter2_new;
284
    digitalWrite(Pin_MIDIled, HIGH);
285
   }
286

  
287
   if ( dur2_new != dur2_old ) {         // maybe adding jitter threshold needed, see Jet1_new  
288
    int16_t midiVal = constrain( map(dur2_new, 0, 1024, 0, 127), 0, 127 );
289
    if( midiVal != dur2_old_MIDI){
290
      //Serial.println( midiVal );
291
      dur2_old_MIDI = midiVal;
292
      usbMIDI.sendControlChange(cc_duration, midiVal, midi_chan_inst2);
293
    }
294
    
295
    dur2_old = dur2_new;
296
    digitalWrite(Pin_MIDIled, HIGH);
297
   }
298
   
299
  
300
  //send MIDI Encoder 2 [Selection length Instrument 2]
301
  if (Enc2_new != Enc2_old) {
302
    Enc2_old = Enc2_new;
303
    //Serial.println("Encoder 2: ");
304
    //Serial.println(Enc2_new);
305
    usbMIDI.sendControlChange(cc_length, Enc2_new, midi_chan_inst2);
306
    digitalWrite(Pin_MIDIled, HIGH);
307
  }
308
    
309
}
310

  
JackDevice/ContextJack.cpp
1
/*
2
 Copyright (c) 2015, The Cinder Project
3

  
4
 This code is intended to be used with the Cinder C++ library, http://libcinder.org
5

  
6
 Redistribution and use in source and binary forms, with or without modification, are permitted provided that
7
 the following conditions are met:
8

  
9
    * Redistributions of source code must retain the above copyright notice, this list of conditions and
10
	the following disclaimer.
11
    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
12
	the following disclaimer in the documentation and/or other materials provided with the distribution.
13

  
14
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
15
 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
16
 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
17
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
18
 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19
 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
20
 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
21
 POSSIBILITY OF SUCH DAMAGE.
22
*/
23

  
24
#include "cinder/audio/linux/ContextJack.h"
25
#include "cinder/audio/Exception.h"
26

  
27
namespace cinder { namespace audio { namespace linux {
28

  
29
inline void zeroJackPort( jack_port_t *port, jack_nframes_t nframes )
30
{   
31
  // memset(port, 0, sizeof(jack_default_audio_sample_t) * nframes); 
32
}
33

  
34
inline void copyToJackPort(jack_port_t *port, float *source, jack_nframes_t nframes )
35
{
36
    // dest, source, n 
37
    jack_default_audio_sample_t *out;
38
    out = (jack_default_audio_sample_t *) jack_port_get_buffer( port, nframes );
39

  
40
    memcpy( out, source, sizeof(jack_default_audio_sample_t) * nframes ) ;
41
}
42

  
43
inline void copyFromJackPort(jack_port_t *port, float *dest, jack_nframes_t nframes )
44
{
45
    // dest, source, n 
46
    jack_default_audio_sample_t *in;
47
    in = (jack_default_audio_sample_t *) jack_port_get_buffer( port, nframes );
48

  
49
    memcpy( dest, in, sizeof(jack_default_audio_sample_t) * nframes ) ;
50
}
51

  
52

  
53
int OutputDeviceNodeJack::jackCallback(jack_nframes_t nframes, void* userData)
54
{
55
	RenderData *renderData = static_cast<RenderData *>( userData );
56

  
57
	OutputDeviceNodeJack *outputDeviceNode = static_cast<OutputDeviceNodeJack *>( renderData->outputNode );
58

  
59
	auto ctx = renderData->outputNode->getContext();
60
	if( ! ctx ) {
61
        for( size_t chan = 0; chan < 2; chan++)
62
            // FIXME segfault at shutdown 
63
		    zeroJackPort( outputDeviceNode->mOutputPorts[chan], nframes );
64

  
65
		return 0;
66
	}
67

  
68
	std::lock_guard<std::mutex> lock( ctx->getMutex() );
69
    
70
	// verify associated context still exists, which may not be true if we blocked in ~Context() and were then deallocated.
71
	ctx = renderData->outputNode->getContext();
72
	if( ! ctx ) {
73

  
74
        for( size_t chan = 0; chan < 2; chan++)
75
		    zeroJackPort( outputDeviceNode->mOutputPorts[chan], nframes );
76

  
77
		return 0;
78
	}
79

  
80

  
81
	Buffer *internalBuffer = outputDeviceNode->getInternalBuffer();
82
	internalBuffer->zero();
83

  
84
	ctx->preProcess();
85
	outputDeviceNode->pullInputs( internalBuffer );
86
    
87
	// if clip detection is enabled and buffer clipped, silence it
88
	if( false && outputDeviceNode->checkNotClipping() ){
89
        for( size_t chan = 0; chan < 2; chan++)
90
		    zeroJackPort( outputDeviceNode->mOutputPorts[chan], nframes );
91
	} 
92
    else {
93
        for( size_t chan = 0; chan < 2; chan++)
94
            copyToJackPort( outputDeviceNode->mOutputPorts[chan], internalBuffer->getChannel( chan ), nframes  );
95
    }
96

  
97
	ctx->postProcess();
98

  
99
    return 0;
100
}
101

  
102
inline void OutputDeviceNodeJack::setInput( InputDeviceNodeRef inputDeviceNode) 
103
{
104
    mInputDeviceNode = std::static_pointer_cast<InputDeviceNodeJack>(inputDeviceNode);
105
}
106

  
107
ContextJack::ContextJack()
108
{
109

  
110
}
111

  
112
ContextJack::~ContextJack()
113
{
114

  
115
}
116

  
117

  
118
OutputDeviceNodeRef	ContextJack::createOutputDeviceNode( const DeviceRef &device, const Node::Format &format )
119
{
120
	
121
    if( mOutputDeviceNode  == nullptr ) {
122
        auto thisRef = std::static_pointer_cast<ContextJack>( shared_from_this() );
123

  
124
        mOutputDeviceNode = makeNode( new OutputDeviceNodeJack( device, Node::Format().channels(2), thisRef ) ) ;
125

  
126
        if( mInputDeviceNode != nullptr){
127
            auto castedOutputDeviceNode = std::static_pointer_cast<OutputDeviceNodeJack>( mOutputDeviceNode );
128
            castedOutputDeviceNode->setInput( mInputDeviceNode );   
129
        }
130
    }
131

  
132
	return mOutputDeviceNode;
133
}
134

  
135
InputDeviceNodeRef ContextJack::createInputDeviceNode( const DeviceRef &device, const Node::Format &format  )
136
{
137
    if( mInputDeviceNode  == nullptr ) {
138
        auto thisRef = std::static_pointer_cast<ContextJack>( shared_from_this() );
139

  
140
        mInputDeviceNode = makeNode( new InputDeviceNodeJack( device, Node::Format().channels(2), thisRef ) ) ;
141

  
142
        if( mOutputDeviceNode != nullptr){
143
            auto castedOutputDeviceNode = std::static_pointer_cast<OutputDeviceNodeJack>( mOutputDeviceNode );
144
            castedOutputDeviceNode->setInput( mInputDeviceNode );   
145
        }
146
    }
147

  
148
	return mInputDeviceNode;
149
}
150

  
151

  
152
// OutputDeviceNodeJack 
153

  
154
OutputDeviceNodeJack::OutputDeviceNodeJack( const DeviceRef &device, const Format &format, const std::shared_ptr<ContextJack> &context ):
155
    OutputDeviceNode( device, format),
156
    mCinderContext( context )
157
{
158
}
159

  
160
void OutputDeviceNodeJack::initialize()
161
{
162

  
163
    const char *client_name = "Collidoscope";
164
    const char *server_name = NULL;
165
    jack_options_t options = JackNullOption;
166
    jack_status_t status;
167

  
168
    // connect to JAck server 
169
    mClient = jack_client_open (client_name, options, &status, server_name);
170
    if( mClient == NULL){
171

  
172
        std::string msg = "jack_client_open() failed. "; 
173
        if(status & JackServerFailed) 
174
            msg += "Unable to connect to Jack server";
175

  
176
        throw cinder::audio::AudioContextExc(msg);
177
    }
178

  
179
    
180
    mRenderData.outputNode = this;
181
    mRenderData.inputNode = mInputDeviceNode.get();
182
    CI_ASSERT(mInputDeviceNode != nullptr);
183
    mRenderData.context = static_cast<ContextJack *>( getContext().get() );
184

  
185
    // install callback
186
    jack_set_process_callback (mClient, jackCallback, &mRenderData );
187

  
188
    // jack shutdown ? 
189
    
190

  
191
    // setup output ports 
192
    mOutputPorts[0] = jack_port_register (mClient, "output1",
193
                       JACK_DEFAULT_AUDIO_TYPE,
194
                       JackPortIsOutput, 0);
195
    
196
    mOutputPorts[1] = jack_port_register (mClient, "output2",
197
                       JACK_DEFAULT_AUDIO_TYPE,
198
                       JackPortIsOutput, 0);
199
    
200
     if ((mOutputPorts[0] == NULL) || (mOutputPorts[0] == NULL)) {
201
        throw cinder::audio::AudioContextExc("no more JACK ports available");
202
     }
203

  
204
    // setup input ports 
205
    mInputDeviceNode->mInputPorts[0] = jack_port_register (mClient, "input1",
206
                       JACK_DEFAULT_AUDIO_TYPE,
207
                       JackPortIsInput, 0);
208

  
209
    mInputDeviceNode->mInputPorts[1] = jack_port_register (mClient, "input2",
210
                       JACK_DEFAULT_AUDIO_TYPE,
211
                       JackPortIsInput, 0);
212

  
213

  
214
    /* Tell the JACK server that we are ready to roll.  Our callback will start running now. */
215
    if (jack_activate (mClient)) {
216
        throw cinder::audio::AudioContextExc("cannot activate client");
217
    }
218

  
219
    // connect input ports to physical device (microphones)
220
    const char **mikePorts = jack_get_ports (mClient, NULL, NULL,
221
		JackPortIsPhysical|JackPortIsOutput);
222

  
223
	if (mikePorts == NULL) {
224
        throw cinder::audio::AudioContextExc("no physical input ports available");
225
	}
226

  
227
	if (jack_connect (mClient,  mikePorts[0], jack_port_name (mInputDeviceNode->mInputPorts[0]))) {
228
        throw cinder::audio::AudioContextExc("cannot connect input port 0");
229
	}
230

  
231
	if (jack_connect (mClient, mikePorts[1], jack_port_name( mInputDeviceNode->mInputPorts[1]) )) {
232
        throw cinder::audio::AudioContextExc("cannot connect input port 1");
233
	}
234

  
235
    // connect output ports to physical device (audio out )
236
    const char **speakerPorts = jack_get_ports (mClient, NULL, NULL,
237
				JackPortIsPhysical|JackPortIsInput);
238

  
239
	if (speakerPorts == NULL) {
240
        throw cinder::audio::AudioContextExc("no physical output ports available");
241
	}
242

  
243
	if (jack_connect (mClient, jack_port_name (mOutputPorts[0]), speakerPorts[0])) {
244
        throw cinder::audio::AudioContextExc("cannot connect output port 0");
245
	}
246

  
247
	if (jack_connect (mClient, jack_port_name (mOutputPorts[1]), speakerPorts[1])) {
248
        throw cinder::audio::AudioContextExc("cannot connect output port 1");
249
	}
250

  
251
	jack_free( mikePorts );
252
	jack_free( speakerPorts );
253
}
254

  
255

  
256
void OutputDeviceNodeJack::uninitialize()
257
{
258
    jack_client_close( mClient );
259
}
260

  
261
void OutputDeviceNodeJack::enableProcessing()
262
{
263
}
264

  
265
void OutputDeviceNodeJack::disableProcessing()
266
{
267
}
268

  
269

  
270
//-------------------------- InputDeviceNodeJack -------------------------------
271

  
272

  
273
InputDeviceNodeJack::InputDeviceNodeJack( const DeviceRef &device, const Format &format, const std::shared_ptr<ContextJack> &context ):
274
    InputDeviceNode( device, format)
275
{
276
}
277

  
278
void InputDeviceNodeJack::initialize() 
279
{
280
}
281

  
282
void InputDeviceNodeJack::uninitialize()
283
{
284
}
285

  
286
void InputDeviceNodeJack::enableProcessing()
287
{
288
}
289

  
290
void InputDeviceNodeJack::disableProcessing()
291
{
292
}
293

  
294
void InputDeviceNodeJack::process( Buffer *buffer )
295
{
296
    for( size_t chan = 0; chan < 2; chan++){
297
       copyFromJackPort(mInputPorts[chan], buffer->getChannel( chan ), buffer->getNumFrames() ); 
298
    }
299
}
300

  
301
} } } // namespace cinder::audio::linux
1
/*
2
 Copyright (c) 2015, The Cinder Project
3

  
4
 This code is intended to be used with the Cinder C++ library, http://libcinder.org
5

  
6
 Redistribution and use in source and binary forms, with or without modification, are permitted provided that
7
 the following conditions are met:
8

  
9
    * Redistributions of source code must retain the above copyright notice, this list of conditions and
10
	the following disclaimer.
11
    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
12
	the following disclaimer in the documentation and/or other materials provided with the distribution.
13

  
14
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
15
 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
16
 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
17
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
18
 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19
 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
20
 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
21
 POSSIBILITY OF SUCH DAMAGE.
22
*/
23

  
24
#include "cinder/audio/linux/ContextJack.h"
25
#include "cinder/audio/Exception.h"
26

  
27
namespace cinder { namespace audio { namespace linux {
28

  
29
inline void zeroJackPort( jack_port_t *port, jack_nframes_t nframes )
30
{   
31
  // memset(port, 0, sizeof(jack_default_audio_sample_t) * nframes); 
32
}
33

  
34
inline void copyToJackPort(jack_port_t *port, float *source, jack_nframes_t nframes )
35
{
36
    // dest, source, n 
37
    jack_default_audio_sample_t *out;
38
    out = (jack_default_audio_sample_t *) jack_port_get_buffer( port, nframes );
39

  
40
    memcpy( out, source, sizeof(jack_default_audio_sample_t) * nframes ) ;
41
}
42

  
43
inline void copyFromJackPort(jack_port_t *port, float *dest, jack_nframes_t nframes )
44
{
45
    // dest, source, n 
46
    jack_default_audio_sample_t *in;
47
    in = (jack_default_audio_sample_t *) jack_port_get_buffer( port, nframes );
48

  
49
    memcpy( dest, in, sizeof(jack_default_audio_sample_t) * nframes ) ;
50
}
51

  
52

  
53
int OutputDeviceNodeJack::jackCallback(jack_nframes_t nframes, void* userData)
54
{
55
	RenderData *renderData = static_cast<RenderData *>( userData );
56

  
57
	OutputDeviceNodeJack *outputDeviceNode = static_cast<OutputDeviceNodeJack *>( renderData->outputNode );
58

  
59
	auto ctx = renderData->outputNode->getContext();
60
	if( ! ctx ) {
61
        for( size_t chan = 0; chan < 2; chan++)
62
            // FIXME segfault at shutdown 
63
		    zeroJackPort( outputDeviceNode->mOutputPorts[chan], nframes );
64

  
65
		return 0;
66
	}
67

  
68
	std::lock_guard<std::mutex> lock( ctx->getMutex() );
69
    
70
	// verify associated context still exists, which may not be true if we blocked in ~Context() and were then deallocated.
71
	ctx = renderData->outputNode->getContext();
72
	if( ! ctx ) {
73

  
74
        for( size_t chan = 0; chan < 2; chan++)
75
		    zeroJackPort( outputDeviceNode->mOutputPorts[chan], nframes );
76

  
77
		return 0;
78
	}
79

  
80

  
81
	Buffer *internalBuffer = outputDeviceNode->getInternalBuffer();
82
	internalBuffer->zero();
83

  
84
	ctx->preProcess();
85
	outputDeviceNode->pullInputs( internalBuffer );
86
    
87
	// if clip detection is enabled and buffer clipped, silence it
88
	if( false && outputDeviceNode->checkNotClipping() ){
89
        for( size_t chan = 0; chan < 2; chan++)
90
		    zeroJackPort( outputDeviceNode->mOutputPorts[chan], nframes );
91
	} 
92
    else {
93
        for( size_t chan = 0; chan < 2; chan++)
94
            copyToJackPort( outputDeviceNode->mOutputPorts[chan], internalBuffer->getChannel( chan ), nframes  );
95
    }
96

  
97
	ctx->postProcess();
98

  
99
    return 0;
100
}
101

  
102
inline void OutputDeviceNodeJack::setInput( InputDeviceNodeRef inputDeviceNode) 
103
{
104
    mInputDeviceNode = std::static_pointer_cast<InputDeviceNodeJack>(inputDeviceNode);
105
}
106

  
107
ContextJack::ContextJack()
108
{
109

  
110
}
111

  
112
ContextJack::~ContextJack()
113
{
114

  
115
}
116

  
117

  
118
OutputDeviceNodeRef	ContextJack::createOutputDeviceNode( const DeviceRef &device, const Node::Format &format )
119
{
120
	
121
    if( mOutputDeviceNode  == nullptr ) {
122
        auto thisRef = std::static_pointer_cast<ContextJack>( shared_from_this() );
123

  
124
        mOutputDeviceNode = makeNode( new OutputDeviceNodeJack( device, Node::Format().channels(2), thisRef ) ) ;
125

  
126
        if( mInputDeviceNode != nullptr){
127
            auto castedOutputDeviceNode = std::static_pointer_cast<OutputDeviceNodeJack>( mOutputDeviceNode );
128
            castedOutputDeviceNode->setInput( mInputDeviceNode );   
129
        }
130
    }
131

  
132
	return mOutputDeviceNode;
133
}
134

  
135
InputDeviceNodeRef ContextJack::createInputDeviceNode( const DeviceRef &device, const Node::Format &format  )
136
{
137
    if( mInputDeviceNode  == nullptr ) {
138
        auto thisRef = std::static_pointer_cast<ContextJack>( shared_from_this() );
139

  
140
        mInputDeviceNode = makeNode( new InputDeviceNodeJack( device, Node::Format().channels(2), thisRef ) ) ;
141

  
142
        if( mOutputDeviceNode != nullptr){
143
            auto castedOutputDeviceNode = std::static_pointer_cast<OutputDeviceNodeJack>( mOutputDeviceNode );
144
            castedOutputDeviceNode->setInput( mInputDeviceNode );   
145
        }
146
    }
147

  
148
	return mInputDeviceNode;
149
}
150

  
151

  
152
// OutputDeviceNodeJack 
153

  
154
OutputDeviceNodeJack::OutputDeviceNodeJack( const DeviceRef &device, const Format &format, const std::shared_ptr<ContextJack> &context ):
155
    OutputDeviceNode( device, format),
156
    mCinderContext( context )
157
{
158
}
159

  
160
void OutputDeviceNodeJack::initialize()
161
{
162

  
163
    const char *client_name = "Collidoscope";
164
    const char *server_name = NULL;
165
    jack_options_t options = JackNullOption;
166
    jack_status_t status;
167

  
168
    // connect to JAck server 
169
    mClient = jack_client_open (client_name, options, &status, server_name);
170
    if( mClient == NULL){
171

  
172
        std::string msg = "jack_client_open() failed. "; 
173
        if(status & JackServerFailed) 
174
            msg += "Unable to connect to Jack server";
175

  
176
        throw cinder::audio::AudioContextExc(msg);
177
    }
178

  
179
    
180
    mRenderData.outputNode = this;
181
    mRenderData.inputNode = mInputDeviceNode.get();
182
    CI_ASSERT(mInputDeviceNode != nullptr);
183
    mRenderData.context = static_cast<ContextJack *>( getContext().get() );
184

  
185
    // install callback
186
    jack_set_process_callback (mClient, jackCallback, &mRenderData );
187

  
188
    // jack shutdown ? 
189
    
190

  
191
    // setup output ports 
192
    mOutputPorts[0] = jack_port_register (mClient, "output1",
193
                       JACK_DEFAULT_AUDIO_TYPE,
194
                       JackPortIsOutput, 0);
195
    
196
    mOutputPorts[1] = jack_port_register (mClient, "output2",
197
                       JACK_DEFAULT_AUDIO_TYPE,
198
                       JackPortIsOutput, 0);
199
    
200
     if ((mOutputPorts[0] == NULL) || (mOutputPorts[0] == NULL)) {
201
        throw cinder::audio::AudioContextExc("no more JACK ports available");
202
     }
203

  
204
    // setup input ports 
205
    mInputDeviceNode->mInputPorts[0] = jack_port_register (mClient, "input1",
206
                       JACK_DEFAULT_AUDIO_TYPE,
207
                       JackPortIsInput, 0);
208

  
209
    mInputDeviceNode->mInputPorts[1] = jack_port_register (mClient, "input2",
210
                       JACK_DEFAULT_AUDIO_TYPE,
211
                       JackPortIsInput, 0);
212

  
213

  
214
    /* Tell the JACK server that we are ready to roll.  Our callback will start running now. */
215
    if (jack_activate (mClient)) {
216
        throw cinder::audio::AudioContextExc("cannot activate client");
217
    }
218

  
219
    // connect input ports to physical device (microphones)
220
    const char **mikePorts = jack_get_ports (mClient, NULL, NULL,
221
		JackPortIsPhysical|JackPortIsOutput);
222

  
223
	if (mikePorts == NULL) {
224
        throw cinder::audio::AudioContextExc("no physical input ports available");
225
	}
226

  
227
	if (jack_connect (mClient,  mikePorts[0], jack_port_name (mInputDeviceNode->mInputPorts[0]))) {
228
        throw cinder::audio::AudioContextExc("cannot connect input port 0");
229
	}
230

  
231
	if (jack_connect (mClient, mikePorts[1], jack_port_name( mInputDeviceNode->mInputPorts[1]) )) {
232
        throw cinder::audio::AudioContextExc("cannot connect input port 1");
233
	}
234

  
235
    // connect output ports to physical device (audio out )
236
    const char **speakerPorts = jack_get_ports (mClient, NULL, NULL,
237
				JackPortIsPhysical|JackPortIsInput);
238

  
239
	if (speakerPorts == NULL) {
240
        throw cinder::audio::AudioContextExc("no physical output ports available");
241
	}
242

  
243
	if (jack_connect (mClient, jack_port_name (mOutputPorts[0]), speakerPorts[0])) {
244
        throw cinder::audio::AudioContextExc("cannot connect output port 0");
245
	}
246

  
247
	if (jack_connect (mClient, jack_port_name (mOutputPorts[1]), speakerPorts[1])) {
248
        throw cinder::audio::AudioContextExc("cannot connect output port 1");
249
	}
250

  
251
	jack_free( mikePorts );
252
	jack_free( speakerPorts );
253
}
254

  
255

  
256
void OutputDeviceNodeJack::uninitialize()
257
{
258
    jack_client_close( mClient );
259
}
260

  
261
void OutputDeviceNodeJack::enableProcessing()
262
{
263
}
264

  
265
void OutputDeviceNodeJack::disableProcessing()
266
{
267
}
268

  
269

  
270
//-------------------------- InputDeviceNodeJack -------------------------------
271

  
272

  
273
InputDeviceNodeJack::InputDeviceNodeJack( const DeviceRef &device, const Format &format, const std::shared_ptr<ContextJack> &context ):
274
    InputDeviceNode( device, format)
275
{
276
}
277

  
278
void InputDeviceNodeJack::initialize() 
279
{
280
}
281

  
282
void InputDeviceNodeJack::uninitialize()
283
{
284
}
285

  
286
void InputDeviceNodeJack::enableProcessing()
287
{
288
}
289

  
290
void InputDeviceNodeJack::disableProcessing()
291
{
292
}
293

  
294
void InputDeviceNodeJack::process( Buffer *buffer )
295
{
296
    for( size_t chan = 0; chan < 2; chan++){
297
       copyFromJackPort(mInputPorts[chan], buffer->getChannel( chan ), buffer->getNumFrames() ); 
298
    }
299
}
300

  
301
} } } // namespace cinder::audio::linux
JackDevice/ContextJack.h
1
/*
2
 Copyright (c) 2015, The Cinder Project
3

  
4
 This code is intended to be used with the Cinder C++ library, http://libcinder.org
5

  
6
 Redistribution and use in source and binary forms, with or without modification, are permitted provided that
7
 the following conditions are met:
8

  
9
    * Redistributions of source code must retain the above copyright notice, this list of conditions and
10
	the following disclaimer.
11
    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
12
	the following disclaimer in the documentation and/or other materials provided with the distribution.
13

  
14
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
15
 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
16
 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
17
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
18
 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19
 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
20
 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
21
 POSSIBILITY OF SUCH DAMAGE.
22
*/
23

  
24
#pragma once
25

  
26
#include "cinder/audio/Context.h" 
27
#include <jack/jack.h>
28

  
29
namespace cinder { namespace audio { namespace linux {
30

  
31
class ContextJack;
32
class InputDeviceNodeJack;
33

  
34
class OutputDeviceNodeJack : public OutputDeviceNode {
35
  public:
36
	OutputDeviceNodeJack( const DeviceRef &device, const Format &format, const std::shared_ptr<ContextJack> &context );
37

  
38
    void setInput(InputDeviceNodeRef inputDeviceNode);
39

  
40
  protected:
41
	void initialize()				override;
42
	void uninitialize()				override;
43
	void enableProcessing()			override;
44
	void disableProcessing()		override;
45
	bool supportsProcessInPlace() const	override	{ return false; }
46

  
47
  private:
48
    static int jackCallback(jack_nframes_t nframes, void* userData);
49

  
50

  
51
	void renderToBufferFromInputs();
52

  
53
    struct RenderData{
54
        RenderData() : inputNode(nullptr), outputNode(nullptr), context(nullptr){}
55
        ~RenderData() { inputNode = nullptr; outputNode = nullptr;  context = nullptr; }
56
        Node* outputNode;
57
        Node* inputNode;
58
        ContextJack* context;
59
    } mRenderData;
60

  
61
    std::weak_ptr<ContextJack>  mCinderContext;
62

  
63
	jack_client_t *mClient;
64

  
65
    std::array< jack_port_t*, 2 > mOutputPorts;
66

  
67
    std::shared_ptr<InputDeviceNodeJack> mInputDeviceNode;
68
};
69

  
70
class InputDeviceNodeJack : public InputDeviceNode {
71
  friend OutputDeviceNodeJack;
72

  
73
  public:
74
	InputDeviceNodeJack( const DeviceRef &device, const Format &format, const std::shared_ptr<ContextJack> &context );
75

  
76
  protected:
77
	void initialize()				override;
78
	void uninitialize()				override;
79
	void enableProcessing()			override;
80
	void disableProcessing()		override;
81
	void process( Buffer *buffer )	override;
82

  
83
  private:
84
    std::array< jack_port_t*, 2 > mInputPorts;
85
};
86

  
87
class ContextJack : public Context {
88
  public:
89
	ContextJack();
90
	virtual ~ContextJack();
91
    
92

  
93
	OutputDeviceNodeRef	createOutputDeviceNode( const DeviceRef &device, const Node::Format &format = Node::Format() ) override;
94
	InputDeviceNodeRef	createInputDeviceNode( const DeviceRef &device, const Node::Format &format = Node::Format()  ) override;
95

  
96
    OutputDeviceNodeRef	mOutputDeviceNode;
97
    InputDeviceNodeRef	mInputDeviceNode;
98

  
99

  
100
  private:
101
};	
102

  
103
} } } // namespace cinder::audio::linux
1
/*
2
 Copyright (c) 2015, The Cinder Project
3

  
4
 This code is intended to be used with the Cinder C++ library, http://libcinder.org
5

  
6
 Redistribution and use in source and binary forms, with or without modification, are permitted provided that
7
 the following conditions are met:
8

  
9
    * Redistributions of source code must retain the above copyright notice, this list of conditions and
10
	the following disclaimer.
11
    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
12
	the following disclaimer in the documentation and/or other materials provided with the distribution.
13

  
14
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
15
 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
16
 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
17
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
18
 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19
 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
20
 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
21
 POSSIBILITY OF SUCH DAMAGE.
22
*/
23

  
24
#pragma once
25

  
26
#include "cinder/audio/Context.h" 
27
#include <jack/jack.h>
28

  
29
namespace cinder { namespace audio { namespace linux {
30

  
31
class ContextJack;
32
class InputDeviceNodeJack;
33

  
34
class OutputDeviceNodeJack : public OutputDeviceNode {
35
  public:
36
	OutputDeviceNodeJack( const DeviceRef &device, const Format &format, const std::shared_ptr<ContextJack> &context );
37

  
38
    void setInput(InputDeviceNodeRef inputDeviceNode);
39

  
40
  protected:
41
	void initialize()				override;
42
	void uninitialize()				override;
43
	void enableProcessing()			override;
44
	void disableProcessing()		override;
45
	bool supportsProcessInPlace() const	override	{ return false; }
46

  
47
  private:
48
    static int jackCallback(jack_nframes_t nframes, void* userData);
49

  
50

  
51
	void renderToBufferFromInputs();
52

  
53
    struct RenderData{
54
        RenderData() : inputNode(nullptr), outputNode(nullptr), context(nullptr){}
55
        ~RenderData() { inputNode = nullptr; outputNode = nullptr;  context = nullptr; }
56
        Node* outputNode;
57
        Node* inputNode;
58
        ContextJack* context;
59
    } mRenderData;
60

  
61
    std::weak_ptr<ContextJack>  mCinderContext;
62

  
63
	jack_client_t *mClient;
64

  
65
    std::array< jack_port_t*, 2 > mOutputPorts;
66

  
67
    std::shared_ptr<InputDeviceNodeJack> mInputDeviceNode;
68
};
69

  
70
class InputDeviceNodeJack : public InputDeviceNode {
71
  friend OutputDeviceNodeJack;
72

  
73
  public:
74
	InputDeviceNodeJack( const DeviceRef &device, const Format &format, const std::shared_ptr<ContextJack> &context );
75

  
76
  protected:
77
	void initialize()				override;
78
	void uninitialize()				override;
79
	void enableProcessing()			override;
80
	void disableProcessing()		override;
81
	void process( Buffer *buffer )	override;
82

  
83
  private:
84
    std::array< jack_port_t*, 2 > mInputPorts;
85
};
86

  
87
class ContextJack : public Context {
88
  public:
89
	ContextJack();
90
	virtual ~ContextJack();
91
    
92

  
93
	OutputDeviceNodeRef	createOutputDeviceNode( const DeviceRef &device, const Node::Format &format = Node::Format() ) override;
94
	InputDeviceNodeRef	createInputDeviceNode( const DeviceRef &device, const Node::Format &format = Node::Format()  ) override;
95

  
96
    OutputDeviceNodeRef	mOutputDeviceNode;
97
    InputDeviceNodeRef	mInputDeviceNode;
98

  
99

  
100
  private:
101
};	
102

  
103
} } } // namespace cinder::audio::linux
JackDevice/DeviceManagerJack.cpp
1
/*
2
 Copyright (c) 2015, The Cinder Project
3

  
4
 This code is intended to be used with the Cinder C++ library, http://libcinder.org
5

  
6
 Redistribution and use in source and binary forms, with or without modification, are permitted provided that
7
 the following conditions are met:
8

  
9
    * Redistributions of source code must retain the above copyright notice, this list of conditions and
10
	
11
    the following disclaimer.
12
    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
13
	the following disclaimer in the documentation and/or other materials provided with the distribution.
14

  
15
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
16
 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
17
 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
19
 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20
 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21
 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
22
 POSSIBILITY OF SUCH DAMAGE.
23
*/
24

  
25
#include "cinder/audio/linux/DeviceManagerJack.h"
26
#include "cinder/audio/Exception.h"
27
#include <jack/jack.h>
28

  
29

  
30
namespace cinder { namespace audio { namespace linux {
31

  
32
DeviceManagerJack::DeviceManagerJack() 
33
{
34

  
35
    mDevices.push_back( addDevice("JackIn") );
36
    mDevices.push_back( addDevice("JackOut") );
37

  
38
    jack_status_t status;
39
    
40
	jack_client_t *client = jack_client_open ("device info", JackNullOption, &status, NULL);
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff