mirror of
https://codeberg.org/uzu/strudel
synced 2026-07-23 21:47:16 -04:00
basic offline cache
This commit is contained in:
@@ -34,7 +34,8 @@
|
||||
},
|
||||
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
||||
"dependencies": {
|
||||
"@strudel.cycles/core": "workspace:*"
|
||||
"@strudel.cycles/core": "workspace:*",
|
||||
"idb-keyval": "^6.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vite": "^3.2.2"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { logger, toMidi, valueToMidi } from '@strudel.cycles/core';
|
||||
import { getAudioContext } from './index.mjs';
|
||||
import { get, set } from 'idb-keyval';
|
||||
|
||||
const bufferCache = {}; // string: Promise<ArrayBuffer>
|
||||
const loadCache = {}; // string: Promise<ArrayBuffer>
|
||||
@@ -74,22 +75,37 @@ export const getSampleBufferSource = async (s, n, note, speed, freq) => {
|
||||
return bufferSource;
|
||||
};
|
||||
|
||||
export const loadBuffer = (url, ac, s, n = 0) => {
|
||||
const useOfflineCache = true;
|
||||
|
||||
export const loadBuffer = async (url, ac, s, n = 0) => {
|
||||
const label = s ? `sound "${s}:${n}"` : 'sample';
|
||||
// only load if not already requested (loadCache = cache promises loading buffers by url)
|
||||
if (!loadCache[url]) {
|
||||
logger(`[sampler] load ${label}..`, 'load-sample', { url });
|
||||
const timestamp = Date.now();
|
||||
loadCache[url] = fetch(url)
|
||||
.then((res) => res.arrayBuffer())
|
||||
.then(async (res) => {
|
||||
const took = Date.now() - timestamp;
|
||||
const size = humanFileSize(res.byteLength);
|
||||
// const downSpeed = humanFileSize(res.byteLength / took);
|
||||
logger(`[sampler] load ${label}... done! loaded ${size} in ${took}ms`, 'loaded-sample', { url });
|
||||
const decoded = await ac.decodeAudioData(res);
|
||||
bufferCache[url] = decoded;
|
||||
return decoded;
|
||||
});
|
||||
loadCache[url] = (async () => {
|
||||
logger(`[sampler] load ${label}..`, 'load-sample', { url });
|
||||
const timestamp = Date.now();
|
||||
if (useOfflineCache) {
|
||||
const cachedDataUrl = await get(url);
|
||||
if (cachedDataUrl) {
|
||||
// buffer has been loaded into offline cache in a previous session
|
||||
logger(`[sampler] load ${label}... done! found in offline cache!`, 'loaded-sample', { url });
|
||||
return dataUrlToAudioBuffer(ac, cachedDataUrl);
|
||||
}
|
||||
}
|
||||
// buffer not cached offline => fetch from url =>
|
||||
const res = await fetch(url);
|
||||
const buf = await res.arrayBuffer();
|
||||
if (useOfflineCache) {
|
||||
// we don't need to wait for the offline cache to finish here
|
||||
bufferToDataUrl(buf).then((dataUrl) => set(url, dataUrl));
|
||||
}
|
||||
const audioBuffer = await ac.decodeAudioData(buf);
|
||||
const took = Date.now() - timestamp;
|
||||
const size = humanFileSize(buf.byteLength);
|
||||
logger(`[sampler] load ${label}... done! loaded ${size} in ${took}ms`, 'loaded-sample', { url });
|
||||
bufferCache[url] = audioBuffer;
|
||||
return audioBuffer;
|
||||
})();
|
||||
}
|
||||
return loadCache[url];
|
||||
};
|
||||
@@ -179,3 +195,20 @@ export const resetLoadedSamples = () => {
|
||||
};
|
||||
|
||||
export const getLoadedSamples = () => sampleCache.current;
|
||||
|
||||
async function bufferToDataUrl(buf) {
|
||||
return new Promise((resolve) => {
|
||||
var blob = new Blob([buf], { type: 'application/octet-binary' });
|
||||
var reader = new FileReader();
|
||||
reader.onload = function (event) {
|
||||
resolve(event.target.result);
|
||||
};
|
||||
reader.readAsDataURL(blob);
|
||||
});
|
||||
}
|
||||
|
||||
function dataUrlToAudioBuffer(ctx, dataUrl) {
|
||||
return fetch(dataUrl)
|
||||
.then((res) => res.arrayBuffer())
|
||||
.then((res) => ctx.decodeAudioData(res));
|
||||
}
|
||||
|
||||
Generated
+12
@@ -313,9 +313,11 @@ importers:
|
||||
packages/webaudio:
|
||||
specifiers:
|
||||
'@strudel.cycles/core': workspace:*
|
||||
idb-keyval: ^6.2.0
|
||||
vite: ^3.2.2
|
||||
dependencies:
|
||||
'@strudel.cycles/core': link:../core
|
||||
idb-keyval: 6.2.0
|
||||
devDependencies:
|
||||
vite: 3.2.5
|
||||
|
||||
@@ -6296,6 +6298,12 @@ packages:
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/idb-keyval/6.2.0:
|
||||
resolution: {integrity: sha512-uw+MIyQn2jl3+hroD7hF8J7PUviBU7BPKWw4f/ISf32D4LoGu98yHjrzWWJDASu9QNrX10tCJqk9YY0ClWm8Ng==}
|
||||
dependencies:
|
||||
safari-14-idb-fix: 3.0.0
|
||||
dev: false
|
||||
|
||||
/ieee754/1.2.1:
|
||||
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
|
||||
|
||||
@@ -9968,6 +9976,10 @@ packages:
|
||||
mri: 1.2.0
|
||||
dev: false
|
||||
|
||||
/safari-14-idb-fix/3.0.0:
|
||||
resolution: {integrity: sha512-eBNFLob4PMq8JA1dGyFn6G97q3/WzNtFK4RnzT1fnLq+9RyrGknzYiM/9B12MnKAxuj1IXr7UKYtTNtjyKMBog==}
|
||||
dev: false
|
||||
|
||||
/safe-buffer/5.1.2:
|
||||
resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user