coninuted work on tracker

main
mwinter 1 year ago
parent 3622475cbe
commit 620b912d13

@ -6,9 +6,11 @@ module.exports = {
oscInFilter:function(data) {
//console.log(data)
var {host, port, address, args} = data
if (address === '/playing') {
if (address === '/playing') {
receive("/measure", args[0].value)
receive("/beat", args[1].value)
receive("/visual_click", 1)
@ -22,6 +24,8 @@ module.exports = {
var {host, port, address, args} = data
console.log(data)
if (address.substring(1, 6) == 'mixer') {
tokens = address.split('/')
ins = tokens[2]

@ -0,0 +1,158 @@
// Latency compensation for osc clients
// use receiveSync() instead of receive()
// to send synchronized messages to all clients
// keep track of connected clients
// use global object to keep the list
// from resetting when hot-reloading the custom module
global.clients = global.clients || {}
var clients = global.clients
app.on('open', (data, client)=>{
if (!clients[client.id]) clients[client.id] = {
latencies: [],
latency: 0,
}
})
app.on('close', (data, client)=>{
delete clients[client.id]
})
function pingClients(){
// ping clients and make them include their id and ping date in the reply
var date = Date.now()
for (let id in clients) {
receive('/SCRIPT', `send('custom-module:null', '/pong', "${id}", ${date})`)
}
}
function handleClientPong(id, date) {
// client's ping response to measure their latency
// estimated as half of the roundtrip latency
if (clients[id]) {
// accumulate latency measures
// keep 5 latest values
if (clients[id].latencies.unshift((Date.now() - date) / 2) > 5) clients[id].latencies.pop()
if (clients[id].latencies.length < 2)
clients[id].latency = clients[id].latencies[0]
else
clients[id].latency = filterLatencies(clients[id].latencies)
}
}
function filterLatencies(arr) {
// As described at https://web.archive.org/web/20160310125700/http://mine-control.com/zack/timesync/timesync.html
// with bith from https://github.com/enmasseio/timesync/blob/master/src/stat.js
// compute median
var sorted = arr.slice().sort((a,b)=> a > b ? 1 : a < b ? -1 : 0)
var median
if (sorted.length % 2 === 0)
// even
median = (sorted[arr.length / 2 - 1] + sorted[arr.length / 2]) / 2
else
// odd
median = sorted[(arr.length - 1) / 2]
// compute variance (average of the squared differences from the mean)
// in the end divide by (arr.length - 1) because we are working on
// a sample and not on a full dataset (https://www.mathsisfun.com/data/standard-deviation.html)
var mean = arr.reduce((a,b)=>a + b) / arr.length;
var variance = arr.map(x => Math.pow(x - mean, 2))
.reduce((a,b)=>a + b) / (arr.length - 1)
// compute standard deviation
var stdDeviation = Math.sqrt(variance)
// discard values above 1 standard-deviation from the median
var filtered = arr.filter(x=>x < median + stdDeviation)
// return arithmetic mean of remaining values
return filtered.reduce((a,b)=>a + b) / filtered.length;
}
function receiveSync(address, ...args) {
// Send a message to all clients with dalys based on their measured latency
// get worst client latency
var maxLatency = 0
for (let id in clients) {
if (clients[id].latency > maxLatency) maxLatency = clients[id].latency
}
// delay message by the latency delta with the worst client
for (let id in clients) {
setTimeout(()=>{
//send(host, port, address, ...args, {clientId: id})
receive(address, ...args, {clientId: id})
}, maxLatency - clients[id].latency)
}
}
// Measure clients latencies every 2 seconds
setInterval(pingClients, 50)
module.exports = {
oscInFilter:function(data) {
//console.log(data)
var {host, port, address, args} = data
if (address === '/playing') {
receive("/measure", args[0].value)
receive("/beat", args[1].value)
receive("/visual_click", 1)
//receiveSync("/measure", args[0].value)
//receiveSync("/beat", args[1].value)
//receiveSync("/visual_click", 1)
}
return
},
oscOutFilter:function(data){
var {address, args, host, port} = data
if (host === 'custom-module') {
// handle client's ping response
if (address === '/pong') handleClientPong(args[0].value, args[1].value)
return // bypass original message
}
if (address.substring(1, 6) == 'mixer') {
tokens = address.split('/')
ins = tokens[2]
type = tokens[3]
index = tokens[4]
val = args[0].value
args = [{'type': 's', 'value': ins}, {'type': 's', 'value': type}, {'type': 's', 'value': index}, {'type': 'f', 'value': val}]
//console.log(data)
address = '/mixer'
return {host, port, address, args}
}
if (address === '/transport') {
return {host, port, address, args}
}
return
}
}

@ -0,0 +1,53 @@
import cv2
import numpy as np
drawing = False
point1 = ()
point2 = ()
def mouse_drawing(event, x, y, flags, params):
global point1, point2, drawing
if event == cv2.EVENT_LBUTTONDOWN:
if drawing is False:
drawing = True
point1 = (x, y)
else:
drawing = False
elif event == cv2.EVENT_MOUSEMOVE:
if drawing is True:
point2 = (x, y)
cap = cv2.VideoCapture("/home/mwinter/Portfolio/a_history_of_the_domino_problem/a_history_of_the_domino_problem_source/recs/a_history_of_the_domino_problem_final_documentation_hq.mp4")
# Exit if video not opened.
if not cap.isOpened():
print("Could not open video")
sys.exit()
# Read first frame.
cap.set(cv2.CAP_PROP_POS_FRAMES, 5000)
ok, initFrame = cap.read()
if not ok:
print('Cannot read video file')
sys.exit()
cv2.namedWindow("Frame")
#cv2.setMouseCallback("Frame", mouse_drawing)
while cap.isOpened():
ok, frame = cap.read()
if ok == True:
#if point1 and point2:
# cv2.rectangle(frame, point1, point2, (0, 255, 0))
cv2.imshow("Frame", frame)
else:
break
cap.release()
cv2.destroyAllWindows()

@ -0,0 +1,113 @@
# importing libraries
import cv2
import numpy as np
drawing = False
point1 = ()
point2 = ()
def mouse_drawing(event, x, y, flags, params):
global point1, point2, drawing
if event == cv2.EVENT_LBUTTONDOWN:
if drawing is False:
drawing = True
point1 = (x, y)
else:
drawing = False
elif event == cv2.EVENT_MOUSEMOVE:
if drawing is True:
point2 = (x, y)
#xFine = (848, 187, 225, 21.0)
#yFine = (604, 402, 20.5, 276)
xFine = (848, 187, 848 + 225, 187 + 21.0)
yFine = (604, 402, 604 + 20.5, 402 + 276)
frameCountMod = 0
centroidX = [0, 0]
centroidY = [0, 0]
def track(frame, ROI, centroid, update):
if(update):
crop = frame[int(ROI[1]):int(ROI[3]), int(ROI[0]):int(ROI[2])]
crop = cv2.cvtColor(crop, cv2.COLOR_RGB2GRAY)
crop = cv2.GaussianBlur(crop,(7,7),cv2.BORDER_DEFAULT)
ret,thresh = cv2.threshold(crop, 50, 255, 0)
contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
for c in contours:
# calculate moments for each contour
M = cv2.moments(c)
# calculate x,y coordinate of center
if M["m00"] != 0:
centroid[0] = int(M["m10"] / M["m00"])
centroid[1] = int(M["m01"] / M["m00"])
else:
centroid[0], centroid[1] = 0, 0
#cv2.circle(img, (cX, cY), 5, (255, 255, 255), -1)
cv2.circle(frame, (int(ROI[0]) + centroid[0], int(ROI[1]) + centroid[1]), 3, (0, 255, 0), -1)
cv2.namedWindow("Frame")
cv2.setMouseCallback("Frame", mouse_drawing)
# Create a VideoCapture object and read from input file
cap = cv2.VideoCapture("/home/mwinter/Portfolio/a_history_of_the_domino_problem/a_history_of_the_domino_problem_source/recs/a_history_of_the_domino_problem_final_documentation_hq.mp4")
cap.set(cv2.CAP_PROP_POS_FRAMES, 10000)
# Check if camera opened successfully
if (cap.isOpened()== False):
print("Error opening video file")
frameCountMod = 0
centroidX = [0, 0]
centroidY = [0, 0]
# Read until video is completed
while(cap.isOpened()):
# Capture frame-by-frame
ret, frame = cap.read()
if ret == True:
# Display the resulting frame
if(frameCountMod == 0):
track(frame, xFine, centroidX, True)
track(frame, yFine, centroidY, True)
xPos = (centroidX[0] / xFine[2]) * 2 - 1
yPos = (centroidY[1] / yFine[3]) * 2 - 1
else:
track(frame, xFine, centroidX, False)
track(frame, yFine, centroidY, False)
frameCountMod = (frameCountMod + 1) % 10
cv2.rectangle(frame, (int(xFine[0]), int(xFine[1])), (int(xFine[2]),int(xFine[3])), (0, 255, 0))
cv2.rectangle(frame, (int(yFine[0]), int(yFine[1])), (int(yFine[2]),int(yFine[3])), (0, 255, 0))
if point1 and point2:
#cv2.rectangle(frame, point1, point2, (0, 255, 0))
xFine = (point1[0], point1[1], point2[0], point2[1])
cv2.imshow("Frame", frame)
# Press Q on keyboard to exit
if cv2.waitKey(25) & 0xFF == ord('q'):
break
# Break the loop
else:
break
# When everything done, release
# the video capture object
cap.release()
# Closes all the frames
cv2.destroyAllWindows()

@ -0,0 +1,110 @@
# importing libraries
import cv2
import numpy as np
drawing = False
point1 = ()
point2 = ()
def mouse_drawing(event, x, y, flags, params):
global point1, point2, drawing
if event == cv2.EVENT_LBUTTONDOWN:
if drawing is False:
drawing = True
point1 = (x, y)
else:
drawing = False
elif event == cv2.EVENT_MOUSEMOVE:
if drawing is True:
point2 = (x, y)
#xFine = (848, 187, 225, 21.0)
#yFine = (604, 402, 20.5, 276)
xFine = (848, 187, 848 + 225, 187 + 21.0)
yFine = (604, 402, 604 + 20.5, 402 + 276)
frameCountMod = 0
centroidX = [0, 0]
centroidY = [0, 0]
def track(frame, ROI, centroid, update):
if(update):
crop = frame[int(ROI[1]):int(ROI[3]), int(ROI[0]):int(ROI[2])]
crop = cv2.cvtColor(crop, cv2.COLOR_RGB2GRAY)
crop = cv2.GaussianBlur(crop,(7,7),cv2.BORDER_DEFAULT)
#ret, thresh = cv2.threshold(crop, 100, 255, cv2.THRESH_OTSU + cv2.THRESH_BINARY)
ret,thresh = cv2.threshold(crop, 50, 255, 0)
M = cv2.moments(thresh)
# calculate x,y coordinate of center
if M["m00"] != 0:
centroid[0] = int(M["m10"] / M["m00"])
centroid[1] = int(M["m01"] / M["m00"])
#else:
# cX, cY = 0, 0
#print(cY)
cv2.circle(frame, (int(ROI[0]) + centroid[0], int(ROI[1]) + centroid[1]), 3, (0, 255, 0), -1)
cv2.namedWindow("Frame")
cv2.setMouseCallback("Frame", mouse_drawing)
# Create a VideoCapture object and read from input file
cap = cv2.VideoCapture("/home/mwinter/Portfolio/a_history_of_the_domino_problem/a_history_of_the_domino_problem_source/recs/a_history_of_the_domino_problem_final_documentation_hq.mp4")
cap.set(cv2.CAP_PROP_POS_FRAMES, 10000)
# Check if camera opened successfully
if (cap.isOpened()== False):
print("Error opening video file")
frameCountMod = 0
centroidX = [0, 0]
centroidY = [0, 0]
# Read until video is completed
while(cap.isOpened()):
# Capture frame-by-frame
ret, frame = cap.read()
if ret == True:
# Display the resulting frame
if(frameCountMod == 0):
track(frame, xFine, centroidX, True)
track(frame, yFine, centroidY, True)
xPos = (centroidX[0] / xFine[2]) * 2 - 1
yPos = (centroidY[1] / yFine[3]) * 2 - 1
else:
track(frame, xFine, centroidX, False)
track(frame, yFine, centroidY, False)
frameCountMod = (frameCountMod + 1) % 3
cv2.rectangle(frame, (int(xFine[0]), int(xFine[1])), (int(xFine[2]),int(xFine[3])), (0, 255, 0))
cv2.rectangle(frame, (int(yFine[0]), int(yFine[1])), (int(yFine[2]),int(yFine[3])), (0, 255, 0))
if point1 and point2:
#cv2.rectangle(frame, point1, point2, (0, 255, 0))
xFine = (point1[0], point1[1], point2[0], point2[1])
cv2.imshow("Frame", frame)
# Press Q on keyboard to exit
if cv2.waitKey(25) & 0xFF == ord('q'):
break
# Break the loop
else:
break
# When everything done, release
# the video capture object
cap.release()
# Closes all the frames
cv2.destroyAllWindows()

@ -0,0 +1,60 @@
# importing libraries
import cv2
import numpy as np
drawing = False
point1 = ()
point2 = ()
def mouse_drawing(event, x, y, flags, params):
global point1, point2, drawing
if event == cv2.EVENT_LBUTTONDOWN:
if drawing is False:
drawing = True
point1 = (x, y)
else:
drawing = False
elif event == cv2.EVENT_MOUSEMOVE:
if drawing is True:
point2 = (x, y)
cv2.namedWindow("Frame")
cv2.setMouseCallback("Frame", mouse_drawing)
# Create a VideoCapture object and read from input file
cap = cv2.VideoCapture("/home/mwinter/Portfolio/a_history_of_the_domino_problem/a_history_of_the_domino_problem_source/recs/a_history_of_the_domino_problem_final_documentation_hq.mp4")
# Check if camera opened successfully
if (cap.isOpened()== False):
print("Error opening video file")
# Read until video is completed
while(cap.isOpened()):
# Capture frame-by-frame
ret, frame = cap.read()
if ret == True:
# Display the resulting frame
if point1 and point2:
cv2.rectangle(frame, point1, point2, (0, 255, 0))
cv2.imshow("Frame", frame)
# Press Q on keyboard to exit
if cv2.waitKey(25) & 0xFF == ord('q'):
break
# Break the loop
else:
break
# When everything done, release
# the video capture object
cap.release()
# Closes all the frames
cv2.destroyAllWindows()

@ -0,0 +1,208 @@
\version "2.24.1"
genStaff =
#(define-music-function (parser location part)
(string?)
(let * ((file (string-append "includes/ammann_part_" part ".ly")))
#{
\new Staff \with {
instrumentName = #part
shortInstrumentName = #part
}
<<
\include #file
>>
#}))
\paper {
#(set-paper-size "a4" 'portrait)
top-margin = 1 \cm
bottom-margin = 1 \cm
left-margin = 1.75 \cm
top-system-spacing =
#'((basic-distance . 15 )
(minimum-distance . 15 )
(padding . 0 )
(stretchability . 0))
last-bottom-spacing =
#'((basic-distance . 15 )
(minimum-distance . 15 )
(padding . 0 )
(stretchability . 0))
systems-per-page = 2
print-page-number = ##t
oddHeaderMarkup = \markup { \unless \on-first-page { "(ammann)" }}
oddHeaderMarkup = \markup { \unless \on-first-page { "(ammann)" }}
oddFooterMarkup = \markup { \fill-line {
\concat {
"-"
\fontsize #1.5
\fromproperty #'page:page-number-string
"-"}}}
evenFooterMarkup = \markup { \fill-line {
\concat {
"-"
\fontsize #1.5
\fromproperty #'page:page-number-string
"-"}}}
}
\header {
title = \markup { \italic {ammann}}
subtitle = \markup { \normal-text { from \italic{a history of the domino the problem}}}
composer = \markup \right-column {"michael winter" "(schloss solitude, stuttgart and calle monclova 62, mexico city; 2018-19)"}
tagline = ""
}
#(set-global-staff-size 11)
\layout {
indent = 0.0\cm
line-width = 17\cm
%ragged-last = ##t
\context {
\Score
\override BarNumber.extra-offset = #'(0 . 4)
\override BarNumber.stencil = #(make-stencil-circler 0.1 0.25 ly:text-interface::print)
\override RehearsalMark.direction = #DOWN
}
\context {
\Staff
\override VerticalAxisGroup.staff-staff-spacing =
#'((basic-distance . 15 )
(minimum-distance . 15 )
(padding . 0 )
(stretchability . 0))
\override TimeSignature.font-size = #2
\override TimeSignature.break-align-symbol = #'clef
\override TimeSignature.X-offset =
#ly:self-alignment-interface::x-aligned-on-self
\override TimeSignature.self-alignment-X = #LEFT
%\override TimeSignature.after-line-breaking =
% #shift-right-at-line-begin
\override TimeSignature.Y-offset = #9
\override TimeSignature.extra-offset = #'(2 . 0)
}
\context {
\StaffGroup
\name "SemiStaffGroup"
\consists "Span_bar_engraver"
\override SpanBar.stencil =
#(lambda (grob)
(if (string=? (ly:grob-property grob 'glyph-name) "|")
(set! (ly:grob-property grob 'glyph-name) ""))
(ly:span-bar::print grob))
}
\context {
\Score
\accepts SemiStaffGroup
}
}
\score {
%showLastLength = R1*128
\new Score
%\with{ proportionalNotationDuration = #(ly:make-moment 1 16) }
<<
\new SemiStaffGroup {
<<
\new Staff \with {
instrumentName = #"8"
shortInstrumentName = #"8"
midiInstrument = #"clarinet"
}
<<
\include "includes/ammann_part_0.ly"
>>
\new Staff \with {
instrumentName = #"7"
shortInstrumentName = #"7"
midiInstrument = #"clarinet"
\remove "Time_signature_engraver"
}
<<
\include "includes/ammann_part_1.ly"
>>
\new Staff \with {
instrumentName = #"6"
shortInstrumentName = #"6"
midiInstrument = #"clarinet"
\remove "Time_signature_engraver"
}
<<
\include "includes/ammann_part_2.ly"
>>
\new Staff \with {
instrumentName = #"5"
shortInstrumentName = #"5"
midiInstrument = #"clarinet"
\remove "Time_signature_engraver"
}
<<
\include "includes/ammann_part_3.ly"
>>
\new Staff \with {
instrumentName = #"4"
shortInstrumentName = #"4"
midiInstrument = #"clarinet"
\remove "Time_signature_engraver"
}
<<
\include "includes/ammann_part_4.ly"
>>
\new Staff \with {
instrumentName = #"3"
shortInstrumentName = #"3"
midiInstrument = #"clarinet"
\remove "Time_signature_engraver"
}
<<
\include "includes/ammann_part_5.ly"
>>
\new Staff \with {
instrumentName = #"2"
shortInstrumentName = #"2"
midiInstrument = #"clarinet"
\remove "Time_signature_engraver"
}
<<
\include "includes/ammann_part_6.ly"
>>
\new Staff \with {
instrumentName = #"1"
shortInstrumentName = #"1"
midiInstrument = #"clarinet"
\remove "Time_signature_engraver"
}
<<
\include "includes/ammann_part_7.ly"
>>
%\genStaff #"0"
%\genStaff #"1"
%\genStaff #"2"
%\genStaff #"3"
%\genStaff #"4"
%\genStaff #"5"
>>
}
>>
\layout { }
\midi { }
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -6,7 +6,8 @@ var createTransportPattern;
Event.addEventType(\osc, {
if (~addr.postln.notNil) {
~msg.postln;
~addr.sendMsg(~path, *~msg);
//~addr.sendMsg(~path, *~msg);
~addr.sendBundle(1, [~path] ++ ~msg);
};
});
@ -169,7 +170,7 @@ Event.addEventType(\osc, {
),
//\sustain, Pseq(r.slice(nil, 1).flat ),
\amp, Pseq(r.slice(nil, 3).flat * 0.5)
\amp, Pseq(r.slice(nil, 3).flat /** 0.5*/)
)
});
@ -313,7 +314,6 @@ measureLengths = seqs[1].sum.collect({4});
playbackData.add(\penrose -> [~penroseCreatePatternsForLive.value(seqs, group), createTransportData.value(measureLengths), measureLengths]);
seqs = File.readAllString((~dir +/+ "music_data" +/+ "ammann.txt").standardizePath).interpret;
~seqs = seqs;
measureLengths = seqs[0].collect({arg item; item[0].sum});
playbackData.add(\ammann -> [~ammannCreatePatternsForLive.value(seqs, group), createTransportData.value(measureLengths), measureLengths]);
@ -328,12 +328,12 @@ playbackData.add(\jaendel -> [~jaendelCreatePatternsForLive.value(seqs, 0, 1, 55
OSCdef(\mixer, {arg msg, time, addr, port;
msg.postln;
[msg, time, addr, port].postln;
mixer.set((msg[1] ++ '_' ++ msg[2] ++ '_' ++ msg[3]), msg[4])
}, \mixer);
OSCdef(\transport, {arg msg, time, addr, port;
msg.postln;
[msg, time, addr, port].postln;
if(msg[1] == 0, {
//need some work here to make sure all synths are getting cutoff correctly
group.set(\release, 2);
@ -353,6 +353,7 @@ OSCdef(\transport, {arg msg, time, addr, port;
player = EventStreamPlayer(offsetStream ++ stream ++ terminationStream);
tempoClock = TempoClock(msg[5]/60.0);
player.play(tempoClock);
//player.play(tempoClock, quant: Quant.new(0, 0, -2));
});
}, \transport);

Loading…
Cancel
Save