fix: scheduling + sample playback

This commit is contained in:
Felix Roos 2025-06-08 09:05:14 +02:00
parent 0f2aa9569b
commit 356d4360ec
No known key found for this signature in database
2 changed files with 20 additions and 22 deletions

View file

@ -384,6 +384,7 @@ export class Distort {
// distortion could be expressed as a function, because it's stateless // distortion could be expressed as a function, because it's stateless
export class BufferPlayer { export class BufferPlayer {
static samples = new Map();
channels = []; channels = [];
pos = 0; pos = 0;
update(freq, channel = 0) { update(freq, channel = 0) {
@ -573,10 +574,9 @@ export class DoughVoice {
if (shapes[this.s]) { if (shapes[this.s]) {
const SourceClass = shapes[this.s]; const SourceClass = shapes[this.s];
this._sound = new SourceClass(); this._sound = new SourceClass();
} else if (value.samples.has(this.s)) { } else if (BufferPlayer.samples.has(this.s)) {
this._sample = new BufferPlayer(); this._sample = new BufferPlayer();
this._sample.channels = value.samples.get(this.s); this._sample.channels = BufferPlayer.samples.get(this.s);
this._sample.pos = 0;
} else { } else {
console.warn('sound not found', this.s); console.warn('sound not found', this.s);
} }
@ -735,7 +735,6 @@ export class DoughVoice {
this._crush && (s = this._crush.update(s, this.crush)); this._crush && (s = this._crush.update(s, this.crush));
this._distort && (s = this._distort.update(s, this.distort, this.distortvol)); this._distort && (s = this._distort.update(s, this.distort, this.distortvol));
/* Math.random() > 0.99 && console.log('gate', gate); */
const env = this._adsr.update(t, gate, this.attack, this.decay, this.sustain, this.release); const env = this._adsr.update(t, gate, this.attack, this.decay, this.sustain, this.release);
s = s * env; s = s * env;
@ -762,7 +761,6 @@ export class Dough {
delaysend = [0, 0]; delaysend = [0, 0];
delaytime = getDefaultValue('delaytime'); delaytime = getDefaultValue('delaytime');
delayfeedback = getDefaultValue('delayfeedback'); delayfeedback = getDefaultValue('delayfeedback');
samples = new Map();
t = 0; t = 0;
// sampleRate: number, currentTime: number (seconds) // sampleRate: number, currentTime: number (seconds)
constructor(sampleRate = 48000, currentTime = 0) { constructor(sampleRate = 48000, currentTime = 0) {
@ -773,7 +771,7 @@ export class Dough {
this._delayR = new Delay(); this._delayR = new Delay();
} }
loadSample(name, channels) { loadSample(name, channels) {
this.samples.set(name, channels); BufferPlayer.samples.set(name, channels);
} }
scheduleSpawn(value) { scheduleSpawn(value) {
if (value._begin === undefined) { if (value._begin === undefined) {
@ -783,12 +781,12 @@ export class Dough {
throw new Error('[dough]: scheduleSpawn expected _duration to be set'); throw new Error('[dough]: scheduleSpawn expected _duration to be set');
} }
value.sampleRate = this.sampleRate; value.sampleRate = this.sampleRate;
const time = value._begin; // set from supradough.mjs // convert seconds to samples
const time = Math.floor(value._begin * this.sampleRate); // set from supradough.mjs
this.schedule({ time, type: 'spawn', arg: value }); this.schedule({ time, type: 'spawn', arg: value });
} }
spawn(value) { spawn(value) {
value.id = this.vid++; value.id = this.vid++;
value.samples = this.samples;
const voice = new DoughVoice(value); const voice = new DoughVoice(value);
this.voices.push(voice); this.voices.push(voice);
// console.log('spawn', voice.id, 'voices:', this.voices.length); // console.log('spawn', voice.id, 'voices:', this.voices.length);

View file

@ -25,18 +25,6 @@ Pattern.prototype.supradough = function () {
}, 1); }, 1);
}; };
async function loadSampleChannels(url) {
const buffer = await fetch(url)
.then((res) => res.arrayBuffer())
.then((buf) => getAudioContext().decodeAudioData(buf));
// console.log('buffer', buffer, buffer.numberOfChannels);
let channels = [];
for (let i = 0; i < buffer.numberOfChannels; i++) {
channels.push(buffer.getChannelData(i));
}
return channels;
}
let samples = { let samples = {
casio: [ casio: [
'https://raw.githubusercontent.com/tidalcycles/Dirt-Samples/master/casio/high.wav', 'https://raw.githubusercontent.com/tidalcycles/Dirt-Samples/master/casio/high.wav',
@ -138,6 +126,17 @@ let samples = {
}; };
// for some reason, only piano and flute work.. is it because mp3?? // for some reason, only piano and flute work.. is it because mp3??
async function loadSampleChannels(url) {
const buffer = await fetch(url)
.then((res) => res.arrayBuffer())
.then((buf) => getAudioContext().decodeAudioData(buf));
let channels = [];
for (let i = 0; i < buffer.numberOfChannels; i++) {
channels.push(buffer.getChannelData(i));
}
return channels;
}
let loaded = false; let loaded = false;
export async function doughsample() { export async function doughsample() {
!doughWorklet && initDoughWorklet(); !doughWorklet && initDoughWorklet();
@ -148,8 +147,9 @@ export async function doughsample() {
const sampleMap = await Promise.all( const sampleMap = await Promise.all(
Object.entries(samples).map(async ([key, url]) => { Object.entries(samples).map(async ([key, url]) => {
url = url[0]; url = url[0];
console.log(key, 'url', url); const channels = await loadSampleChannels(url);
return [key, await loadSampleChannels(url)]; // console.log(key, 'url', url, channels);
return [key, channels];
}), }),
); );
console.log('sampleMap', sampleMap); console.log('sampleMap', sampleMap);