Browse Source

Hmm

master
Pete Shadbolt 2 years ago
parent
commit
951bdd9b8b
2 changed files with 93 additions and 27 deletions
  1. +7
    -27
      audio.scd
  2. +86
    -0
      radio.py

+ 7
- 27
audio.scd View File

@@ -18,25 +18,23 @@ s.waitForBoot {
lagtime = 100 / (2**octave);

// Oscillator/filter frequency
// frequency = notefreq * (1 + (hue*0.1));
frequency = notefreq * (1 + (hue*5)) * (2**(octave-2));
frequency = (notefreq * (1 + (hue*0.1))) * (2**(octave));
//frequency = (130 + (hue * 130)) * (2 ** octave);
//frequency = 130 * Scale.major.ratios[(hue * 12).asInteger];
//frequency = (130 * frequency) * (2**octave);
frequency = Lag.kr(frequency, lagtime/10);
// Filtered saw oscillator
// oscillator = Mix.ar([SawDPW.ar(frequency), SawDPW.ar(frequency/2+0.5)]);
oscillator = Mix.ar([DPW3Tri.ar(frequency), DPW3Tri.ar(frequency/2+0.5)]);
oscillator = Mix.ar([SawDPW.ar(frequency), SawDPW.ar(frequency/2+value*(1-saturation)*50)]);
filter = DFM1.ar(oscillator, frequency, saturation/2, 1.0, 0.0, 0.0006);

// Noise
qfactor = Lag.kr((1 - saturation)**2, lagtime);
noise = Crackle.ar(1.9, 1.0);
qfactor = Lag.kr((1 - saturation)**4, lagtime);
noise = Crackle.ar(1.99, 1.0);
noise = BPF.ar(noise, frequency, qfactor);

// Mix noise and saw
mixer = Mix.ar([filter * saturation.sqrt(), 3* noise*(1-saturation)]);
mixer = Mix.ar([filter * saturation.sqrt(), 1 * noise*(1-saturation)]);

// Apply pan
panner = LinPan2.ar(mixer, pan);
@@ -48,11 +46,8 @@ s.waitForBoot {
// Compress
output = Compander.ar(output, output, 0.5, 0.3, 0.3, 0.1, lagtime);

// Fade in on boot
output = output * Lag.kr(gain, lagtime);

// Crank everything down
output = output * 0.3;
output = output * 0.9;

Out.ar(0, output);
});
@@ -68,26 +63,11 @@ s.waitForBoot {
octave = (2 - (index / 4).floor);
"Module %: Pan %, octave %\n".postf(index, pan.round(1e-1), octave.round(1e-1));
Synth.new(\module,
[\hue, 0.5, \saturation, 0.1, \value, 0.5, \pan, pan, \gain, 0.0, \octave, octave, \notefreq, Scale.major.degreeToFreq(index, 48.midicps, octave)]
[\hue, 0.5, \saturation, 0.1, \value, 0.5, \pan, pan, \gain, 0.9, \octave, octave, \notefreq, Scale.major.degreeToFreq(index, 48.midicps, octave)]
)
}
);

// Turn up gain after some time
SystemClock.schedAbs(8, {modules[0].set(\gain, 1)});
SystemClock.schedAbs(8, {modules[1].set(\gain, 1)});
SystemClock.schedAbs(8, {modules[2].set(\gain, 1)});
SystemClock.schedAbs(8, {modules[3].set(\gain, 1)});
SystemClock.schedAbs(16, {modules[4].set(\gain, 1)});
SystemClock.schedAbs(16, {modules[5].set(\gain, 1)});
SystemClock.schedAbs(16, {modules[6].set(\gain, 1)});
SystemClock.schedAbs(16, {modules[7].set(\gain, 1)});
SystemClock.schedAbs(32, {modules[8].set(\gain, 1)});
SystemClock.schedAbs(32, {modules[9].set(\gain, 1)});
SystemClock.schedAbs(32, {modules[10].set(\gain, 1)});
SystemClock.schedAbs(32, {modules[11].set(\gain, 1)});
SystemClock.schedAbs(32, {modules[12].set(\gain, 1)});

// Hook up OSC
f = { |msg, time, addr|
if(msg[0] == '/radio') {


+ 86
- 0
radio.py View File

@@ -0,0 +1,86 @@
import math
import time
import itertools as it
import cv2
import colorsys
from pythonosc import udp_client
import numpy as np

DENSITY = 4
RED = [0, 0, 255]
N_COLORS = 3
LAST_MESSAGE_TIME = 0


def draw_rectangle(frame, sp, ep):
""" Draw a rectangle on the frame """
return cv2.rectangle(frame, sp, ep, RED, 1)


def analyze_block(frame, osc, index, sp, ep, send=False):
""" Analyze a block """
block = frame[sp[1]:ep[1], sp[0]:ep[0], 0:3]
average_color = np.average(block, (0, 1)) / 255
h, s, v = colorsys.rgb_to_hsv(*average_color)

# Configure the oscillator
if send:
print("Sending message", h, s, v)
osc.send_message(
"/radio",
[int(index), float(h),
float(s), float(v), .5])

# Draw a blob of the average color
sp2 = tuple(int(x) for x in (2 * np.array(sp) + np.array(ep)) / 3)
ep2 = tuple(int(x) for x in (np.array(sp) + 2 * np.array(ep)) / 3)
frame = cv2.rectangle(frame, sp2, ep2,
[int(x * 255) for x in average_color], -1)

# Draw the image
for thickness, color in ((3, (0, 0, 0)), (1, (255, 255, 255))):
frame = cv2.putText(frame,
text=f"{h:.2f} {s:.2f} {v:.2f}",
org=(sp[0] + 10, sp[1] + 20),
fontScale=.5,
color=color,
fontFace=2,
thickness=thickness)
return frame


def analyze(frame, osc):
""" Analyze the full frame """
global LAST_MESSAGE_TIME
height, width, d = frame.shape
n = DENSITY
m = math.ceil(n * (height / width))
dx = width / n
dy = height / m
send = False
if time.time() - LAST_MESSAGE_TIME > 0.1:
LAST_MESSAGE_TIME = time.time()
for index, (y, x) in enumerate(it.product(range(m), range(n))):
sp = (int(x * dx), int(y * dy))
ep = (int(x * dx + dx), int(y * dy + dy))
frame = draw_rectangle(frame, sp, ep)
frame = analyze_block(frame, osc, index, sp, ep, True)
return frame


if __name__ == '__main__':
camera = cv2.VideoCapture("/dev/video2")
# camera = cv2.VideoCapture(0)
osc = udp_client.SimpleUDPClient("0.0.0.0", 5005)

while True:
ret, frame = camera.read()
frame = analyze(frame, osc)
cv2.imshow('Input', frame)

c = cv2.waitKey(1)
if c == 27:
break

camera.release()
cv2.destroyAllWindows()

Loading…
Cancel
Save