This commit is contained in:
2023-12-01 11:16:16 +01:00
parent 31adc17a36
commit a34f1a33eb
7 changed files with 117 additions and 172 deletions

View File

@ -1581,7 +1581,9 @@ export class UserAPI {
// Low Frequency Oscillators
// =============================================================
line = (start: number, end: number, step: number = 1): number[] => {
public range = (v: number, a: number, b: number): number => v * (b - a) + a;
public line = (start: number, end: number, step: number = 1): number[] => {
/**
* Returns an array of values between start and end, with a given step.
*
@ -1603,7 +1605,11 @@ export class UserAPI {
return result;
};
sine = (freq: number = 1, times: number = 1, offset: number = 0): number => {
public sine = (
freq: number = 1,
times: number = 1,
offset: number = 0,
): number => {
/**
* Returns a sine wave between -1 and 1.
*
@ -1617,7 +1623,11 @@ export class UserAPI {
);
};
usine = (freq: number = 1, times: number = 1, offset: number = 0): number => {
public usine = (
freq: number = 1,
times: number = 1,
offset: number = 0,
): number => {
/**
* Returns a sine wave between 0 and 1.
*

View File

@ -4,7 +4,8 @@ import { tryEvaluate } from "./Evaluator";
import { getAudioContext } from "superdough";
// @ts-ignore
import "zyklus";
const zeroPad = (num: number, places: number) => String(num).padStart(places, "0");
const zeroPad = (num: number, places: number) =>
String(num).padStart(places, "0");
export interface TimePosition {
/**
@ -61,7 +62,10 @@ export class Clock {
this.running = true;
this.deadline = 0;
this.timeviewer = document.getElementById("timeviewer")!;
this.clock = getAudioContext().createClock(this.clockCallback, this.pulse_duration)
this.clock = getAudioContext().createClock(
this.clockCallback,
this.pulse_duration,
);
}
clockCallback = (time: number, duration: number, tick: number) => {
@ -89,7 +93,6 @@ export class Clock {
}
// Implement TransportNode clock callback and update clock info with it
};
convertTicksToTimeposition(ticks: number): TimePosition {
@ -183,13 +186,13 @@ export class Clock {
this.app.audioContext.resume();
this.running = true;
this.app.api.MidiConnection.sendStartMessage();
this.clock.start()
this.clock.start();
}
public pause(): void {
this.running = false;
this.app.api.MidiConnection.sendStopMessage();
this.clock.pause()
this.clock.pause();
}
public stop(): void {

View File

@ -1,68 +0,0 @@
import { tryEvaluate } from "./Evaluator";
const zeroPad = (num, places) => String(num).padStart(places, "0");
export class TransportNode extends AudioWorkletNode {
constructor(context, options, application) {
super(context, "transport", options);
this.app = application;
this.port.addEventListener("message", this.handleMessage);
this.port.start();
this.timeviewer = document.getElementById("timeviewer");
}
/** @type {(this: MessagePort, ev: MessageEvent<any>) => any} */
handleMessage = (message) => {
if (message.data) {
if (message.data.type === "bang") {
if (this.app.clock.running) {
if (this.app.settings.send_clock) {
this.app.api.MidiConnection.sendMidiClock();
}
const futureTimeStamp = this.app.clock.convertTicksToTimeposition(
this.app.clock.tick,
);
this.app.clock.time_position = futureTimeStamp;
if (futureTimeStamp.pulse % this.app.clock.ppqn == 0) {
this.timeviewer.innerHTML = `${zeroPad(futureTimeStamp.bar, 2)}:${
futureTimeStamp.beat + 1
} / ${this.app.clock.bpm}`;
}
if (this.app.exampleIsPlaying) {
tryEvaluate(this.app, this.app.example_buffer);
} else {
tryEvaluate(this.app, this.app.global_buffer);
}
this.app.clock.incrementTick(message.data.bpm);
}
}
}
};
start() {
this.port.postMessage({ type: "start" });
}
pause() {
this.port.postMessage({ type: "pause" });
}
resume() {
this.port.postMessage({ type: "resume" });
}
setBPM(bpm) {
this.port.postMessage({ type: "bpm", value: bpm });
}
setPPQN(ppqn) {
this.port.postMessage({ type: "ppqn", value: ppqn });
}
setNudge(nudge) {
this.port.postMessage({ type: "nudge", value: nudge });
}
stop() {
this.port.postMessage({ type: "stop" });
}
}

View File

@ -1,5 +1,11 @@
import { type Editor } from "../main";
import { freqToMidi, chord as parseChord, noteNameToMidi, resolvePitchBend, safeScale } from "zifferjs";
import {
freqToMidi,
chord as parseChord,
noteNameToMidi,
resolvePitchBend,
safeScale,
} from "zifferjs";
import { SkipEvent } from "./SkipEvent";
export type EventOperation<T> = (instance: T, ...args: any[]) => void;
@ -311,16 +317,16 @@ export abstract class AudibleEvent extends AbstractEvent {
return this;
};
protected updateValue<T>(
key: string,
value: T | T[] | null
): this {
protected updateValue<T>(key: string, value: T | T[] | null): this {
if (value == null) return this;
this.values[key] = value;
return this;
}
public note = (value: number | string | null, ...kwargs: number[]|string[]) => {
public note = (
value: number | string | null,
...kwargs: number[] | string[]
) => {
if (typeof value === "string") {
const parsedNote = noteNameToMidi(value);
return this.updateValue("note", [parsedNote, ...kwargs].flat(Infinity));

View File

@ -5,10 +5,7 @@ import {
arrayOfObjectsToObjectWithArrays,
objectWithArraysToArrayOfObjects,
} from "../Utils/Generic";
import {
midiToFreq,
noteFromPc,
} from "zifferjs";
import { midiToFreq, noteFromPc } from "zifferjs";
import {
superdough,
@ -111,13 +108,13 @@ export class SoundEvent extends AudibleEvent {
return self;
},
scope: function (self: SoundEvent) {
self.updateValue("analyze", true)
return self
self.updateValue("analyze", true);
return self;
},
debug: function (self: SoundEvent, callback?: Function) {
self.updateValue("debug", true)
self.updateValue("debug", true);
if (callback) {
self.updateValue("debugFunction", callback)
self.updateValue("debugFunction", callback);
}
return self;
},
@ -467,16 +464,12 @@ export class SoundEvent extends AudibleEvent {
}
if (this.values["debug"]) {
if (this.values["debugFunction"]) {
this.values["debugFunction"](filteredEvent)
this.values["debugFunction"](filteredEvent);
} else {
console.log(filteredEvent)
console.log(filteredEvent);
}
}
superdough(
filteredEvent,
this.app.clock.deadline,
filteredEvent.dur,
);
superdough(filteredEvent, this.app.clock.deadline, filteredEvent.dur);
}
};
}

View File

@ -13,7 +13,8 @@ ${makeExample(
"Feeding a sine to the oscilloscope",
`
beat(1)::sound('sine').freq(200).ad(0, .2).scope().out()
`, true
`,
true,
)}
Here is a layout of the scope configuration options: