fix looping fonts

This commit is contained in:
Felix Roos 2022-06-20 20:55:20 +02:00
parent 82d6103907
commit d5938a016c
5 changed files with 97 additions and 34 deletions

View file

@ -15,11 +15,35 @@ async function loadFont(name) {
return loadCache[name];
}
let bufferCache = {};
export async function getFontBufferSource(name, pitch, ac) {
const { buffer, zone } = await getFontPitch(name, pitch, ac);
const src = ac.createBufferSource();
src.buffer = buffer;
const baseDetune = zone.originalPitch - 100.0 * zone.coarseTune - zone.fineTune;
const playbackRate = 1.0 * Math.pow(2, (100.0 * pitch - baseDetune) / 1200.0);
// src detune?
src.playbackRate.value = playbackRate;
const loop = zone.loopStart > 1 && zone.loopStart < zone.loopEnd;
if (!loop) {
/* const waveDuration = duration + this.afterTime;
if (waveDuration > zone.buffer.duration / playbackRate) {
waveDuration = zone.buffer.duration / playbackRate;
// TODO: do sth with waveduration
} */
} else {
src.loop = true;
src.loopStart = zone.loopStart / zone.sampleRate;
src.loopEnd = zone.loopEnd / zone.sampleRate;
//+ (zone.delay ? zone.delay : 0);
}
return src;
}
let bufferCache = {};
export async function getFontPitch(name, pitch, ac) {
const key = `${name}:::${pitch}`;
if (bufferCache[key]) {
return (await bufferCache[key])();
return bufferCache[key];
}
// console.log('load buffer', key);
const load = async () => {
@ -35,31 +59,10 @@ export async function getFontBufferSource(name, pitch, ac) {
if (!buffer) {
throw new Error(`no soundfont buffer found for preset ${name}, pitch: ${pitch}`);
}
return () => {
const src = ac.createBufferSource();
src.buffer = buffer;
const baseDetune = zone.originalPitch - 100.0 * zone.coarseTune - zone.fineTune;
const playbackRate = 1.0 * Math.pow(2, (100.0 * pitch - baseDetune) / 1200.0);
// src detune?
src.playbackRate.value = playbackRate;
const loop = zone.loopStart > 1 && zone.loopStart < zone.loopEnd;
if (!loop) {
/* const waveDuration = duration + this.afterTime;
if (waveDuration > zone.buffer.duration / playbackRate) {
waveDuration = zone.buffer.duration / playbackRate;
// TODO: do sth with waveduration
} */
} else {
src.loop = true;
/* src.loopStart = zone.loopStart / zone.sampleRate + (zone.delay ? zone.delay : 0);
src.loopEnd = zone.loopEnd / zone.sampleRate + (zone.delay ? zone.delay : 0); */
}
return src;
};
return { buffer, zone };
};
bufferCache[key] = load(); // dont await here to cache promise immediately!
return (await bufferCache[key])();
return bufferCache[key];
}
function findZone(preset, pitch) {

View file

@ -3,9 +3,6 @@
"version": "0.1.0",
"description": "Soundsfont support for strudel",
"main": "index.mjs",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"type": "module",
"repository": {
"type": "git",

View file

@ -63,10 +63,9 @@ const getSoundfontKey = (s) => {
const name = nameIndex < 10 ? `00${nameIndex}` : nameIndex < 100 ? `0${nameIndex}` : nameIndex;
if (nameIndex !== -1) {
// TODO: indices of instrumentNames do not seem to match instruments
s = globalThis.soundfontList.instruments.find((instrument) => instrument.startsWith(name));
// console.log('match', nameIndex, s);
return globalThis.soundfontList.instruments.find((instrument) => instrument.startsWith(name));
}
return globalThis.soundfontList?.instruments?.[nameIndex];
return;
};
const getSampleBufferSource = async (s, n) => {
@ -169,15 +168,17 @@ Pattern.prototype.out = function () {
console.warn('no buffer source');
return;
}
// bufferSource.playbackRate.value = Math.abs(speed) * playbackRate;
bufferSource.playbackRate.value = Math.abs(speed) * bufferSource.playbackRate.value;
// TODO: nudge, unit, cut, loop
let duration = soundfont ? hap.duration : bufferSource.buffer.duration;
// let duration = bufferSource.buffer.duration;
const offset = begin * duration;
duration = ((end - begin) * duration) / Math.abs(speed);
bufferSource.start(t, offset, duration);
if (soundfont) {
bufferSource.start(t, offset); // duration does not work here for some reason
} else {
bufferSource.start(t, offset, duration);
}
bufferSource.stop(t + duration);
chain.push(bufferSource);
if (soundfont) {