buffers can now be repitched (still with aliasing)
This commit is contained in:
parent
356d4360ec
commit
55aef18851
3 changed files with 21 additions and 17 deletions
|
|
@ -10,10 +10,10 @@ class DoughProcessor extends AudioWorkletProcessor {
|
||||||
if (event.data.spawn) {
|
if (event.data.spawn) {
|
||||||
this.dough.scheduleSpawn(event.data.spawn);
|
this.dough.scheduleSpawn(event.data.spawn);
|
||||||
} else if (event.data.sample) {
|
} else if (event.data.sample) {
|
||||||
this.dough.loadSample(event.data.sample, event.data.channels);
|
this.dough.loadSample(event.data.sample, event.data.channels, event.data.sampleRate);
|
||||||
} else if (event.data.samples) {
|
} else if (event.data.samples) {
|
||||||
event.data.samples.forEach(([name, channels]) => {
|
event.data.samples.forEach(([name, channels, sampleRate]) => {
|
||||||
this.dough.loadSample(name, channels);
|
this.dough.loadSample(name, channels, sampleRate);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
console.log('unrecognized event type', event.data);
|
console.log('unrecognized event type', event.data);
|
||||||
|
|
|
||||||
|
|
@ -385,14 +385,16 @@ export class Distort {
|
||||||
|
|
||||||
export class BufferPlayer {
|
export class BufferPlayer {
|
||||||
static samples = new Map();
|
static samples = new Map();
|
||||||
channels = [];
|
buffer; // { channels: Float32Array, sampleRate: number }
|
||||||
pos = 0;
|
pos = 0;
|
||||||
|
sampleFreq = 261.626; // middle c
|
||||||
update(freq, channel = 0) {
|
update(freq, channel = 0) {
|
||||||
if (this.pos >= this.channels[channel].length) {
|
if (this.pos >= this.buffer.channels[channel].length) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
let s = this.channels[channel][this.pos];
|
const speed = ((freq / this.sampleFreq) * this.buffer.sampleRate) / SAMPLE_RATE;
|
||||||
this.pos++;
|
let s = this.buffer.channels[channel][Math.floor(this.pos)];
|
||||||
|
this.pos = this.pos + speed;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -576,7 +578,8 @@ export class DoughVoice {
|
||||||
this._sound = new SourceClass();
|
this._sound = new SourceClass();
|
||||||
} else if (BufferPlayer.samples.has(this.s)) {
|
} else if (BufferPlayer.samples.has(this.s)) {
|
||||||
this._sample = new BufferPlayer();
|
this._sample = new BufferPlayer();
|
||||||
this._sample.channels = BufferPlayer.samples.get(this.s);
|
const buffer = BufferPlayer.samples.get(this.s);
|
||||||
|
this._sample.buffer = buffer;
|
||||||
} else {
|
} else {
|
||||||
console.warn('sound not found', this.s);
|
console.warn('sound not found', this.s);
|
||||||
}
|
}
|
||||||
|
|
@ -738,7 +741,10 @@ export class DoughVoice {
|
||||||
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;
|
||||||
|
|
||||||
s = s * this.postgain * 0.2;
|
s = s * this.postgain;
|
||||||
|
if (!this._sample) {
|
||||||
|
s = s * 0.2; // turn down waveforms
|
||||||
|
}
|
||||||
|
|
||||||
if (this.pan === 0.5) {
|
if (this.pan === 0.5) {
|
||||||
this.l = this.r = s; // mono
|
this.l = this.r = s; // mono
|
||||||
|
|
@ -770,8 +776,8 @@ export class Dough {
|
||||||
this._delayL = new Delay();
|
this._delayL = new Delay();
|
||||||
this._delayR = new Delay();
|
this._delayR = new Delay();
|
||||||
}
|
}
|
||||||
loadSample(name, channels) {
|
loadSample(name, channels, sampleRate) {
|
||||||
BufferPlayer.samples.set(name, channels);
|
BufferPlayer.samples.set(name, { channels, sampleRate });
|
||||||
}
|
}
|
||||||
scheduleSpawn(value) {
|
scheduleSpawn(value) {
|
||||||
if (value._begin === undefined) {
|
if (value._begin === undefined) {
|
||||||
|
|
|
||||||
|
|
@ -118,7 +118,7 @@ let samples = {
|
||||||
'https://raw.githubusercontent.com/tidalcycles/Dirt-Samples/master/numbers/7.wav',
|
'https://raw.githubusercontent.com/tidalcycles/Dirt-Samples/master/numbers/7.wav',
|
||||||
'https://raw.githubusercontent.com/tidalcycles/Dirt-Samples/master/numbers/8.wav',
|
'https://raw.githubusercontent.com/tidalcycles/Dirt-Samples/master/numbers/8.wav',
|
||||||
],
|
],
|
||||||
piano: ['https://raw.githubusercontent.com/felixroos/dough-samples/refs/heads/main/piano/A3v8.mp3'],
|
piano: ['https://raw.githubusercontent.com/felixroos/dough-samples/refs/heads/main/piano/C3v8.mp3'],
|
||||||
flute: ['https://raw.githubusercontent.com/felixroos/samples/refs/heads/main/flute/c4.mp3'],
|
flute: ['https://raw.githubusercontent.com/felixroos/samples/refs/heads/main/flute/c4.mp3'],
|
||||||
bd: [
|
bd: [
|
||||||
'https://raw.githubusercontent.com/geikha/tidal-drum-machines/15eac73c5e878550f91d864a4863e014799403f1/machines/RolandTR909/rolandtr909-bd/Bassdrum-01.wav',
|
'https://raw.githubusercontent.com/geikha/tidal-drum-machines/15eac73c5e878550f91d864a4863e014799403f1/machines/RolandTR909/rolandtr909-bd/Bassdrum-01.wav',
|
||||||
|
|
@ -126,7 +126,7 @@ 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) {
|
async function loadSampleChannels(key, url) {
|
||||||
const buffer = await fetch(url)
|
const buffer = await fetch(url)
|
||||||
.then((res) => res.arrayBuffer())
|
.then((res) => res.arrayBuffer())
|
||||||
.then((buf) => getAudioContext().decodeAudioData(buf));
|
.then((buf) => getAudioContext().decodeAudioData(buf));
|
||||||
|
|
@ -134,7 +134,7 @@ async function loadSampleChannels(url) {
|
||||||
for (let i = 0; i < buffer.numberOfChannels; i++) {
|
for (let i = 0; i < buffer.numberOfChannels; i++) {
|
||||||
channels.push(buffer.getChannelData(i));
|
channels.push(buffer.getChannelData(i));
|
||||||
}
|
}
|
||||||
return channels;
|
return [key, channels, buffer.sampleRate];
|
||||||
}
|
}
|
||||||
|
|
||||||
let loaded = false;
|
let loaded = false;
|
||||||
|
|
@ -147,9 +147,7 @@ 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];
|
||||||
const channels = await loadSampleChannels(url);
|
return loadSampleChannels(key, url);
|
||||||
// console.log(key, 'url', url, channels);
|
|
||||||
return [key, channels];
|
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
console.log('sampleMap', sampleMap);
|
console.log('sampleMap', sampleMap);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue