Skip to content
This repository was archived by the owner on Nov 23, 2023. It is now read-only.

Commit de13f4a

Browse files
authored
Merge pull request #4 from Intelligent-Instruments-Lab/ja-dev
New examples: Bela C++, Bela Pure Data, TidalCycles WIP
2 parents 5abe0c2 + efb11b4 commit de13f4a

File tree

15 files changed

+621
-0
lines changed

15 files changed

+621
-0
lines changed
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
#include <Bela.h>
2+
#include <libraries/OscSender/OscSender.h>
3+
#include <libraries/OscReceiver/OscReceiver.h>
4+
#include <cmath>
5+
6+
OscSender oscSender;
7+
OscReceiver oscReceiver;
8+
9+
const char* remoteIp = "192.168.7.1";
10+
const int remotePort = 7563;
11+
const int localPort = 7562;
12+
13+
const int OSC_PACKET_LEN = 300;
14+
const int OUT_CHANNELS = 2;
15+
16+
std::vector<float> oscInBuffer;
17+
std::vector<float> oscOutBuffer;
18+
19+
float gIn1, gIn2;
20+
21+
int writePointer = 0;
22+
int packetsSent = 0;
23+
int gAudioFramesPerAnalogFrame = 0;
24+
25+
void onReceive(oscpkt::Message* msg, const char* addr, void* arg) {
26+
if(msg->match("/bela")) {
27+
auto argReader = msg->match("/bela");
28+
for (int i=0; i<OUT_CHANNELS * OSC_PACKET_LEN; i++)
29+
argReader.popFloat(oscInBuffer[i]);
30+
argReader.isOkNoMoreArgs();
31+
}
32+
printf("Printing oscInBuffer: ");
33+
for(auto f : oscInBuffer)
34+
printf("%f ", f);
35+
printf("\n");
36+
}
37+
38+
bool setup(BelaContext *context, void *userData) {
39+
oscSender.setup(remotePort, remoteIp);
40+
oscReceiver.setup(localPort, on_receive);
41+
42+
oscInBuffer.resize(OUT_CHANNELS * OSC_PACKET_LEN);
43+
oscOutBuffer.resize(OUT_CHANNELS * OSC_PACKET_LEN);
44+
45+
if (context->analogFrames)
46+
gAudioFramesPerAnalogFrame = context->audioFrames / context->analogFrames;
47+
48+
return true;
49+
}
50+
51+
void render(BelaContext *context, void *userData) {
52+
for (unsigned int n = 0; n < context->audioFrames; ++n) {
53+
if (gAudioFramesPerAnalogFrame && !(n % gAudioFramesPerAnalogFrame)) {
54+
gIn1 = analogRead(context, n / gAudioFramesPerAnalogFrame, 0);
55+
gIn2 = analogRead(context, n / gAudioFramesPerAnalogFrame, 1);
56+
}
57+
58+
oscOutBuffer[writePointer] = gIn1;
59+
oscOutBuffer[OSC_PACKET_LEN+writePointer] = gIn2;
60+
61+
if (writePointer + 1 == OSC_PACKET_LEN) {
62+
oscSender.newMessage("/bela");
63+
oscSender.add(packetsSent);
64+
for (auto v : oscOutBuffer)
65+
oscSender.add(v);
66+
oscSender.send();
67+
packetsSent += 1;
68+
}
69+
writePointer = (writePointer+1)%OSC_PACKET_LEN;
70+
}
71+
}
72+
73+
void cleanup(BelaContext*context, void *userData){}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
"""
2+
Authors:
3+
Victor Shepardson
4+
Jack Armitage
5+
Intelligent Instruments Lab 2022
6+
"""
7+
8+
import numpy as np
9+
from iipyper import OSC, run, repeat
10+
11+
OSC_PACKET_LEN = 300
12+
OUT_CHANNELS = 2
13+
14+
def main(host="192.168.7.1", port=7563):
15+
16+
osc = OSC(host, port, verbose=False)
17+
osc.create_client("bela", host="192.168.7.2", port=7562)
18+
19+
@osc.args("/*")
20+
def _(address, *args):
21+
print(f"{address} {args}")
22+
23+
@repeat(1)
24+
def _():
25+
arr = np.random.rand(OSC_PACKET_LEN * OUT_CHANNELS)
26+
osc("bela", "/bela", *arr)
27+
28+
if __name__=='__main__':
29+
run(main)
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
"""
2+
Authors:
3+
Victor Shepardson
4+
Jack Armitage
5+
Intelligent Instruments Lab 2022
6+
"""
7+
8+
"""
9+
To run this example, open the Bela OSC example at:
10+
https://github.com/BelaPlatform/Bela/blob/master/examples/Communication/OSC/render.cpp
11+
12+
And change the IP address to the following:
13+
```
14+
const char* remoteIp = "192.168.7.1";
15+
```
16+
"""
17+
18+
from iipyper import OSC, run, repeat
19+
20+
def main(host="192.168.7.1", port=7563):
21+
22+
osc = OSC(host, port)
23+
osc.create_client("bela", host="192.168.7.2", port=7562)
24+
25+
connected = False
26+
count = 0
27+
28+
@osc.args("/*")
29+
def _(address, *args):
30+
"""
31+
Handle OSC messages from Bela
32+
"""
33+
print(f"{address} {args}")
34+
35+
if address=="/osc-setup":
36+
nonlocal connected
37+
connected = True
38+
print("Bela connected!")
39+
osc("bela", "/osc-setup-reply")
40+
41+
elif address=="/osc-acknowledge":
42+
print(f"Bela acknowledged osc-test: {args}")
43+
44+
else:
45+
print(f"Unrecognised OSC {address} with {args}")
46+
47+
@repeat(1)
48+
def _():
49+
nonlocal connected
50+
nonlocal count
51+
if connected==True:
52+
osc("bela", "/osc-test", count, 3.14)
53+
count=count+1
54+
else:
55+
print("Waiting for Bela to connect...")
56+
57+
if __name__=='__main__':
58+
run(main)
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*
2+
Based on \example Gui/sliders/render.cpp
3+
*/
4+
5+
#include <Bela.h>
6+
#include <libraries/Oscillator/Oscillator.h>
7+
#include <libraries/Gui/Gui.h>
8+
#include <libraries/GuiController/GuiController.h>
9+
#include <libraries/OscSender/OscSender.h>
10+
#include <libraries/OscReceiver/OscReceiver.h>
11+
#include <cmath>
12+
13+
Gui gui;
14+
GuiController controller;
15+
Oscillator oscillator;
16+
17+
OscSender oscSender;
18+
OscReceiver oscReceiver;
19+
const char* remoteIp = "192.168.7.1";
20+
const int localPort = 7562;
21+
const int remotePort = 7563;
22+
23+
unsigned int gPitchSliderIdx;
24+
unsigned int gAmplitudeSliderIdx;
25+
float gPitch = 60.0;
26+
float gAmplitude = 0.1;
27+
28+
void onReceive(oscpkt::Message* msg, const char* addr, void* arg) {
29+
30+
if (msg->match("/pitch")) {
31+
32+
float pitch;
33+
msg->match("/pitch").popFloat(pitch).isOkNoMoreArgs();
34+
if (gPitch != pitch) {
35+
gPitch = pitch;
36+
controller.setSliderValue(gPitchSliderIdx, gPitch);
37+
printf("Pitch %f\n", gPitch);
38+
}
39+
40+
} else if (msg->match("/amplitude")) {
41+
42+
float amplitude;
43+
msg->match("/amplitude").popFloat(amplitude).isOkNoMoreArgs();
44+
if (gAmplitude != amplitude) {
45+
gAmplitude = amplitude;
46+
controller.setSliderValue(gAmplitudeSliderIdx, gAmplitude);
47+
printf("Amplitude %f\n", gAmplitude);
48+
}
49+
50+
} else {
51+
printf("Address not recognised\n");
52+
}
53+
54+
}
55+
56+
bool setup(BelaContext *context, void *userData)
57+
{
58+
oscReceiver.setup(localPort, onReceive);
59+
oscSender.setup(remotePort, remoteIp);
60+
61+
oscillator.setup(context->audioSampleRate);
62+
63+
// Set up the GUI
64+
gui.setup(context->projectName);
65+
// and attach to it
66+
controller.setup(&gui, "Controls");
67+
68+
// Arguments: name, default value, minimum, maximum, increment
69+
// store the return value to read from the slider later on
70+
gPitchSliderIdx = controller.addSlider("Pitch (MIDI note)", gPitch, 48, 84, 1); // step is 1: quantized semitones
71+
gAmplitudeSliderIdx = controller.addSlider("Amplitude", gAmplitude, 0, 0.5, 0.0001);
72+
return true;
73+
}
74+
75+
void render(BelaContext *context, void *userData)
76+
{
77+
// Access the sliders specifying the index we obtained when creating then
78+
float pitch = controller.getSliderValue(gPitchSliderIdx);
79+
float amplitude = controller.getSliderValue(gAmplitudeSliderIdx);
80+
if (gPitch != pitch) {
81+
gPitch = pitch;
82+
oscSender.newMessage("/pitch").add(gPitch).send();
83+
}
84+
if (gAmplitude != amplitude) {
85+
gAmplitude = amplitude;
86+
oscSender.newMessage("/amplitude").add(gAmplitude).send();
87+
}
88+
89+
float frequency = 440 * powf(2, (gPitch-69)/12); // compute the frequency based on the MIDI pitch
90+
oscillator.setFrequency(frequency);
91+
// notice: no smoothing for amplitude and frequency, you will get clicks when the values change
92+
93+
for(unsigned int n = 0; n < context->audioFrames; n++) {
94+
float out = oscillator.process() * gAmplitude;
95+
for(unsigned int channel = 0; channel < context->audioOutChannels; channel++) {
96+
// Write the sample to every audio output channel
97+
audioWrite(context, n, channel, out);
98+
}
99+
}
100+
}
101+
102+
void cleanup(BelaContext *context, void *userData)
103+
{}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
"""
2+
Authors:
3+
Victor Shepardson
4+
Jack Armitage
5+
Intelligent Instruments Lab 2022
6+
"""
7+
8+
import numpy as np
9+
10+
from iipyper import OSC, run, repeat
11+
12+
def main(host="192.168.7.1", port=7563, verbose=False):
13+
14+
osc = OSC(host, port)
15+
osc.create_client("bela", host="192.168.7.2", port=7562)
16+
17+
pitch = { "val": 60.0, "min": 48, "max": 84, "step": 4 }
18+
amplitude = { "val": 0.1, "min": 0.0, "max": 0.5, "step": 0.01 }
19+
20+
@osc.args("/pitch")
21+
def _(address, *args):
22+
print(f"Received pitch", args)
23+
pitch['val'] = args[0]
24+
25+
@osc.args("/amplitude")
26+
def _(address, *args):
27+
print(f"Received amplitude", args)
28+
amplitude['val'] = args[0]
29+
30+
@repeat(0.125)
31+
def _():
32+
nonlocal pitch, amplitude
33+
coin_flip = np.random.choice(a=[True,False], size=2)
34+
35+
if coin_flip[0]==True:
36+
step = np.random.randint(-pitch['step'], pitch['step']+1)
37+
pitch['val'] = constrain(pitch['val'] + step, pitch['min'], pitch['max'])
38+
osc("bela", "/pitch", pitch['val'])
39+
40+
elif coin_flip[1]==True:
41+
step = np.random.random() * (amplitude['step']*2) - amplitude['step']
42+
amplitude['val'] = constrain(amplitude['val'] + step, amplitude['min'], amplitude['max'])
43+
osc("bela", "/amplitude", amplitude['val'])
44+
45+
def constrain(val, min_val, max_val):
46+
return min(max_val, max(min_val, val))
47+
48+
if __name__=='__main__':
49+
run(main)

0 commit comments

Comments
 (0)