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

Commit d6cf92c

Browse files
authored
Merge pull request #6 from Intelligent-Instruments-Lab/ja-dev
Faust examples
2 parents de13f4a + 27890de commit d6cf92c

File tree

10 files changed

+295
-11
lines changed

10 files changed

+295
-11
lines changed

Readme.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
- examples:
88
- iipyper: basic usage for iipyper
99
- notepredictor: interactive MIDI apps with notepredictor and SuperCollider
10+
- bela: [Bela](https://bela.io) examples in C++, Pure Data and so on
11+
- faust: [Faust](https://faustdoc.grame.fr/) examples
12+
- tidalcycles [TidalCycles](https://tidalcycles.org) examples
13+
- puredata: [Pure Data](https://puredata.info) examples
1014
<!-- - clients: templates for SuperCollider, Bela (C++), Pure Data, ... -->
1115

1216
# Setup

examples/bela/cpp/cpp-osc-resonator/render.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,7 @@ void render (BelaContext *context, void *userData) {
7474
for (unsigned int n = 0; n < context->audioFrames; ++n) {
7575

7676
float in = 0.0f;
77-
if (audioInput)
78-
in = audioRead(context, n, 0); // an excitation signal
77+
if (audioInput) in = audioRead(context, n, 0); // an excitation signal
7978
else {
8079
if (++impulseCount >= impulseInterval * (1-impulseWidth))
8180
in = 1.0f * ( rand() / (float)RAND_MAX * 2.f - 1.f ); // noise
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
#include <stdlib.h>
2+
#include <Bela.h>
3+
#include <libraries/OscSender/OscSender.h>
4+
#include <libraries/OscReceiver/OscReceiver.h>
5+
#include "ResonatorBank.h" // https://github.com/jarmitage/resonators
6+
7+
OscReceiver oscReceiver;
8+
const char* remoteIp = "192.168.7.1";
9+
const int localPort = 7562;
10+
11+
ResonatorBank resBank;
12+
ResonatorBankOptions resBankOptions;
13+
std::vector<ResonatorParams> resModelParams;
14+
int resModelSize = 20;
15+
bool resModelReceived = false;
16+
17+
float impulseInterval = 44100;
18+
float impulseWidth = 0.1;
19+
float impulseCount = 0;
20+
bool audioInput = false;
21+
22+
void onReceive(oscpkt::Message* msg, const char* addr, void* arg) {
23+
24+
if(msg->match("/resonators")) {
25+
26+
printf("Model received...\n");
27+
auto argReader = msg->match("/resonators");
28+
for (int i = 0; i < resModelSize; i++) {
29+
argReader.popFloat(resModelParams[i].freq);
30+
argReader.popFloat(resModelParams[i].gain);
31+
argReader.popFloat(resModelParams[i].decay);
32+
}
33+
argReader.isOkNoMoreArgs();
34+
printf("\n");
35+
36+
resBank.setBank(resModelParams);
37+
resBank.update();
38+
resModelReceived = true;
39+
40+
} else {
41+
printf("Message address not recognised\n");
42+
}
43+
}
44+
45+
bool setup (BelaContext *context, void *userData) {
46+
47+
oscReceiver.setup(localPort, onReceive);
48+
49+
resModelParams.resize(resModelSize);
50+
resBankOptions.total = resModelSize;
51+
resBank.setup(resBankOptions, context->audioSampleRate, context->audioFrames);
52+
53+
return true;
54+
}
55+
56+
void render (BelaContext *context, void *userData) {
57+
58+
if (resModelReceived) {
59+
60+
for (unsigned int n = 0; n < context->audioFrames; ++n) {
61+
62+
float in = 0.0f;
63+
64+
if (audioInput) in = audioRead(context, n, 0); // an excitation signal
65+
else {
66+
if (++impulseCount >= impulseInterval * (1-impulseWidth))
67+
in = 1.0f * ( rand() / (float)RAND_MAX * 2.f - 1.f ); // noise
68+
if (impulseCount >= impulseInterval) impulseCount = 0;
69+
}
70+
float out = 0.0f;
71+
72+
out = resBank.render(in);
73+
74+
audioWrite(context, n, 0, out);
75+
audioWrite(context, n, 1, out);
76+
77+
}
78+
79+
}
80+
81+
}
82+
83+
void cleanup (BelaContext *context, void *userData) { }
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
"""
2+
Authors:
3+
Victor Shepardson
4+
Jack Armitage
5+
Intelligent Instruments Lab 2022
6+
"""
7+
import random
8+
import numpy as np
9+
from math import log
10+
import pandas as pd
11+
import json
12+
13+
from iipyper import OSC, run, repeat
14+
15+
def main(host="192.168.7.1", port=7563, verbose=False):
16+
17+
osc = OSC(host, port)
18+
osc.create_client("bela", host="192.168.7.2", port=7562)
19+
20+
model_size = 20
21+
22+
@repeat(1)
23+
def _():
24+
nonlocal model_size
25+
model = modelGen(model_size)
26+
osc("bela", "/resonators", *model.values.flatten())
27+
28+
def modelGen(size):
29+
res = pd.DataFrame ([], columns=['freq', 'gain', 'decay'])
30+
for i in range (0, size):
31+
res.loc[i] = [
32+
lognorm_within_range (40, 20000),
33+
np.random.uniform (0, 0.5),
34+
np.random.uniform (0, 1.0)
35+
]
36+
res = res.sort_values(by=['freq']).reset_index(drop=True)
37+
return res
38+
39+
def lognorm_within_range(vmin, vmax):
40+
vrand = random.random()
41+
logratio = log(vmax) / log(vmin)
42+
power = ((logratio-1.) * vrand)+1.
43+
return vmin**power
44+
45+
def model2osc(model):
46+
osc = {}
47+
return osc
48+
49+
def osc2model(msg):
50+
model = {}
51+
return model
52+
53+
if __name__=='__main__':
54+
run(main)

examples/bela/readme.md

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,21 @@ Unless otherwise stated, these examples assume a set up of a Bela device connect
44

55
## C++
66
- `cpp-osc-basic`: basic OSC communication with Bela
7-
- `cpp-osc-basic-gui`: basic OSC communication with Bela with a Bela GUI
8-
- `cpp-osc-basic-gui-svelte`: basic OSC communication with Bela with a Svelte GUI
9-
- `cpp-osc-recorder`: record data received from Bela
10-
- `cpp-osc-resonators`: controlling the Resonators library
11-
- `cpp-osc-scope`: controlling the Bela scope
12-
- `cpp-osc-trill`: using Trill sensors
7+
- `cpp-osc-arrays`: sending and receiving arrays
8+
- `cpp-osc-resonator`: controlling a resonant filter
9+
- `cpp-osc-resonators`: controlling a bank of resonant filters
10+
- `cpp-osc-gui-sliders`: Bela GUI with sliders controlled by `iipyper`
11+
- `cpp-osc-notepredictor-trill`: using Trill sensors to control `iipyper` `notepredictor` parameters
12+
13+
## Pure Data
14+
- `osc-receive`: receive OSC from `iipyper`
15+
- `osc-send`: send OSC to `iipyper`
16+
17+
# Todo
1318

1419
## SuperCollider
1520
- `scd-osc-basic`:
1621

17-
## Pure Data
18-
- `pd-osc-basic`:
19-
2022
## Csound
2123
- `cs-osc-basic`:
2224

examples/examples

Whitespace-only changes.
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
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(port=5511, verbose=False):
13+
14+
osc = OSC(port=port)
15+
osc.create_client("faust", port=5510)
16+
17+
connected = False
18+
19+
# Kisana parameters
20+
master = { "val": -12.0, "min": -60.0, "max": 0.0, "step": 2.0 }
21+
note = { "val": 5, "min": 0, "max": 11, "step": 1 }
22+
timbre = { "val": 0.5, "min": 0.0, "max": 1.0, "step": 0.25 }
23+
24+
@osc.args("/*")
25+
def _(address, *args):
26+
"""
27+
Handle OSC messages from Faust
28+
"""
29+
30+
if address=="/Kisana":
31+
# `osc("faust", "/*", "get")` response
32+
print(f"Kisana interface: {args}")
33+
34+
else:
35+
address = address.split("/")
36+
cmd = address[2]
37+
if cmd=="level":
38+
print(f"Level updated to: {args}")
39+
40+
@repeat(0.5)
41+
def _():
42+
nonlocal connected
43+
if connected==False:
44+
connect()
45+
connected=True
46+
update()
47+
48+
def connect():
49+
nonlocal master
50+
osc("faust", "/*", "get") # discover OSC interface
51+
osc("faust", "/xmit", 1) # turn transmission on
52+
osc("faust", "/Kisana/master", master['val']) # set master gain
53+
print("Kisana connected!")
54+
55+
def update():
56+
nonlocal note, timbre
57+
coin_flip = np.random.choice(a=[True,False], size=2)
58+
59+
if coin_flip[0]==True:
60+
note_step = np.random.randint(-note['step'], note['step']+1)
61+
note['val'] = constrain(note['val'] + note_step, note['min'], note['max'])
62+
osc("faust", "/Kisana/loop38/note", note['val'])
63+
64+
elif coin_flip[1]==True:
65+
timbre_step = np.random.random() * (timbre['step'] * 2 - timbre['step'])
66+
timbre['val'] = constrain(timbre['val'] + timbre_step, timbre['min'], timbre['max'])
67+
osc("faust", "/Kisana/timbre", timbre['val'])
68+
69+
def constrain(val, min_val, max_val):
70+
return min(max_val, max(min_val, val))
71+
72+
if __name__=='__main__':
73+
run(main)

examples/faust/hello-osc/server.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
"""
2+
Authors:
3+
Victor Shepardson
4+
Jack Armitage
5+
Intelligent Instruments Lab 2022
6+
"""
7+
8+
"""
9+
Create a file called `process.dsp` and add the following code
10+
11+
```
12+
import("stdfaust.lib");
13+
process = no.noise*hslider("level",0,0,1,0.01);
14+
```
15+
16+
Open this in FaustLive or compile it via faust2X
17+
"""
18+
19+
import random
20+
21+
from iipyper import OSC, run, repeat
22+
23+
def main(port=5511, verbose=False):
24+
25+
osc = OSC(port=port)
26+
osc.create_client("faust", port=5510)
27+
28+
connected = False
29+
30+
@osc.args("/*")
31+
def _(address, *args):
32+
"""
33+
Handle OSC messages from Faust
34+
"""
35+
36+
if address=="/FaustDSP":
37+
# `osc("faust", "/*", "get")` response
38+
print(f"Faust interface: {args}")
39+
40+
else:
41+
address = address.split("/")
42+
cmd = address[2]
43+
if cmd=="level":
44+
print(f"Level updated to: {args}")
45+
46+
@repeat(1)
47+
def _():
48+
nonlocal connected
49+
if connected==False:
50+
connected=True
51+
osc("faust", "/*", "get") # discover OSC interface
52+
osc("faust", "/xmit", 1) # turn transmission on
53+
osc("faust", "/FaustDSP/level", random.random())
54+
55+
if __name__=='__main__':
56+
run(main)

examples/faust/readme.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# `iipyper` Faust examples
2+
3+
Faust OSC documentation references:
4+
- https://faustdoc.grame.fr/manual/osc/
5+
- https://ccrma.stanford.edu/~jos/aspf/Using_FAUST_Open_Sound.html
6+
7+
## Examples
8+
- `hello-osc`: basic example demonsrating OSC send and receive
9+
- `faustlive`: examples corresponding to the [FaustLive Examples](https://github.com/grame-cncm/faustlive/tree/master/Resources/Examples)
10+
+ `harpeautomation`: autoharp with note and timbre parameters

examples/puredata/readme.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# `iipyper` Pure Data examples
2+
3+
See `/examples/bela/pd`

0 commit comments

Comments
 (0)