Skip to content

Commit

Permalink
lichen-community-systemsGH-5: Removed frame-rate model relay code to …
Browse files Browse the repository at this point in the history
…improve performance.
  • Loading branch information
duhrer committed Feb 20, 2023
1 parent b3c5e5f commit e04a161
Show file tree
Hide file tree
Showing 7 changed files with 203 additions and 136 deletions.
7 changes: 2 additions & 5 deletions demos/css/sendQuarterFrame.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,8 @@
*
* Licensed under the MIT license, see LICENSE for details.
*/
.main-panel {
display: none;
}

.start-button {
.start-button,
.stop-button {
border-radius: 0.25rem;
padding: 1rem;
}
3 changes: 1 addition & 2 deletions demos/js/receiveQuarterFrame.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@
model: {
hour: "{youme.demos.quarterFrame.receive}.model.hour",
minute: "{youme.demos.quarterFrame.receive}.model.minute",
second: "{youme.demos.quarterFrame.receive}.model.second",
frame: "{youme.demos.quarterFrame.receive}.model.frame"
second: "{youme.demos.quarterFrame.receive}.model.second"
}
}
},
Expand Down
85 changes: 61 additions & 24 deletions demos/js/sendQuarterFrame.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,17 @@
fluid.defaults("youme.demos.quarterFrame.send", {
gradeNames: ["youme.templateRenderer", "youme.messageSender"],
markup: {
container: "<div class='quarter-frame'><button class='start-button'>Start</button><div class='main-panel'><div class='timestamp'></div><div class='outputs'></div></div></div>"
container: "<div class='quarter-frame'><button class='start-button'>Start</button><button class='stop-button'>Stop</button><div class='timestamp'></div><div class='outputs'></div></div>"
},
selectors: {
mainPanel: ".main-panel",
outputs: ".outputs",
startButton: ".start-button",
stopButton: ".stop-button",
timestamp: ".timestamp"
},
model: {
isRunning: false,

timestamp: 0,
direction: 1,
piece: 0,
Expand All @@ -34,17 +36,53 @@
args: ["{that}"]
},
handleStartButtonClick: {
funcName: "youme.demos.quarterFrame.send.startScheduler",
args: ["{that}"]
funcName: "youme.demos.quarterFrame.send.handleButtonClick",
args: ["{that}", true] // newIsRunning
},
handleStopButtonClick: {
funcName: "youme.demos.quarterFrame.send.handleButtonClick",
args: ["{that}", false] // newIsRunning
}
},

modelRelay: {
startButtonToggle: {
target: "{that}.model.dom.startButton.enabled",
singleTransform: {
"type": "fluid.transforms.condition",
"condition": "{that}.model.isRunning",
"true": false,
"false": true
}
},
stopButtonToggle: {
source: "isRunning",
target: "{that}.model.dom.stopButton.enabled"
}
},

modelListeners: {
isRunning: {
funcName: "youme.demos.quarterFrame.send.toggleScheduler",
args: ["{berg.scheduler}", "{change}.value"] // scheduler, isRunning
}
},

listeners: {
"onCreate.scheduleUpdates": {
funcName: "youme.demos.quarterFrame.send.scheduleUpdates",
args: ["{berg.scheduler}", "{that}.handleQuarterFrame"] // scheduler, invoker
},
"onCreate.bindStartButton": {
this: "{that}.dom.startButton",
method: "click",
args: ["{that}.handleStartButtonClick"]
},
"onCreate.bindStopButton": {
this: "{that}.dom.stopButton",
method: "click",
args: ["{that}.handleStopButtonClick"]
},
"sendMessage.sendToOutputs": "{outputs}.events.sendMessage.fire"
},

Expand All @@ -55,11 +93,7 @@
container: "{that}.dom.timestamp",
options: {
model: {
timestamp: "{youme.demos.quarterFrame.send}.model.timestamp",
hour: "{youme.demos.quarterFrame.send}.model.hour",
minute: "{youme.demos.quarterFrame.send}.model.minute",
second: "{youme.demos.quarterFrame.send}.model.second",
frame: "{youme.demos.quarterFrame.send}.model.frame"
isRunning: "{youme.demos.quarterFrame.send}.model.isRunning"
}
}
},
Expand All @@ -72,9 +106,9 @@
options: {
components: {
clock: {
type: "berg.clock.autoAudioContext",
type: "berg.clock.raf",
options: {
freq: 120 // times per second
freq: 30 // times per second
}
}
}
Expand All @@ -83,24 +117,27 @@
}
});

youme.demos.quarterFrame.send.handleButtonClick = function (that, newIsRunning) {
that.applier.change("isRunning", newIsRunning);
};

// I am choosing not to properly deal with drop frame, and pretend it's just 30 FPS.
youme.demos.quarterFrame.send.rates = [24, 25, 30, 30];

youme.demos.quarterFrame.send.startScheduler = function (that) {
var startButtonElement = that.locate("startButton");
startButtonElement.hide();

var mainPanelElement = that.locate("mainPanel");
mainPanelElement.show();

that.scheduler.start();
youme.demos.quarterFrame.send.toggleScheduler = function (scheduler, isRunning) {
if (isRunning) {
scheduler.start();
}
else {
scheduler.stop();
}
};

// May need a setTimeout or other delay depending on whether this bug hits us:
// https://github.com/colinbdclark/bergson/blob/master/examples/audiocontext-clock/audio-context-clock-example.js
that.scheduler.schedule({
youme.demos.quarterFrame.send.scheduleUpdates = function (scheduler, callback) {
scheduler.schedule({
type: "repeat",
freq: 120,
callback: that.handleQuarterFrame
freq: 30,
callback: callback
});
};

Expand Down
65 changes: 60 additions & 5 deletions demos/js/smfMetadata.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@
var metaDataPropertiesToTrack = ["name", "copyright", "text"];
fluid.each(midiObject.tracks, function (singleTrack, trackNumber) {
var trackObject = {
noteCount: 0
messagesByType: {},
metaEventsByType: {}
};

if (midiObject.header.format === 1) {
Expand All @@ -67,9 +68,12 @@
var metaEvent = fluid.get(singleEvent, "metaEvent");

if (message) {
if (message.type === "noteOn" && message.velocity > 0) {
trackObject.noteCount++;
}
var currentMessageTypeCount = fluid.get(trackObject, ["messagesByType", message.type]) || 0;
fluid.set(trackObject, ["messagesByType", message.type], currentMessageTypeCount + 1);
}
else if (metaEvent) {
var currentMetaEventTypeCount = fluid.get(trackObject, ["eventsByType", metaEvent.type]) || 0;
fluid.set(trackObject, ["metaEventsByType", metaEvent.type], currentMetaEventTypeCount + 1);
}

if (metaEvent) {
Expand All @@ -82,9 +86,60 @@
}
}
}
});
}, singleTrack.events);
smfMetadata.tracks.push(trackObject);
});

if (midiObject.header) {
var timingObject = youme.demos.smf.metadata.extractTiming(midiObject);
smfMetadata.timing = timingObject;
}

return smfMetadata;
};

// Calculate duration of song.
youme.demos.smf.metadata.extractTiming = function (midiObject) {
var timingObject = {
duration: 0
};

var allEvents = [];
fluid.each(midiObject.tracks, function (singleTrack) {
allEvents.push(...singleTrack.events);
});
if (midiObject.header.format !== 2) {
allEvents.sort(youme.demos.smf.metadata.sortByTicksElapsed);
}

var secondsPerTick = 0.5 / midiObject.header.division.resolution;
fluid.each(allEvents, function (singleEvent) {
if (singleEvent.tickDelta && (singleEvent.message || (singleEvent.metaEvent && midiObject.header.format !== 1))) {
var secondsDelta = singleEvent.tickDelta * secondsPerTick;

// Track the smallest non-zero pause so that we can understand how fast a clock we need.
timingObject.smallestPauseSeconds = timingObject.smallestPauseSeconds ? Math.min(timingObject.smallestPauseSeconds, secondsDelta) : secondsDelta;

timingObject.duration += secondsDelta;
}

// Update the timing if needed.
if (singleEvent.metaEvent && singleEvent.metaEvent.type === "tempo") {
var secondsPerQuarterNote = singleEvent.metaEvent.value / 1000000;
secondsPerTick = secondsPerQuarterNote / midiObject.header.division.resolution;
}
});

return timingObject;
};

// Sort in numerical order by "elapsed ticks".
youme.demos.smf.metadata.sortByTicksElapsed = function (a, b) {
if (a.ticksElapsed !== undefined && b.ticksElapsed !== undefined) {
return a.ticksElapsed - b.ticksElapsed;
}
else {
fluid.fail("There should be no events without elapsed ticks.");
}
};
})(fluid);
Loading

0 comments on commit e04a161

Please sign in to comment.