Files
Linus Torvalds d62c7a8afe Allow re-ordering effects
This is one of the things I wanted to do but was just too painful to do
with a screen and rotary encoder model: re-order the effects in the
effect chain.

It's trivial to do from an _audio_ standpoint - it's just an array of
effect indexes that says what order to run the effects in.

But from an UI angle, it was just too painful to do.

Until I bit the bullet and decided that the WebMIDI thing is the only
real configuration tool, and you configure things into scenes.  Now it's
pretty straightforward.

The rule is simple: you always have to start with the noise gate.  It
doesn't have to be *enabled*, but it has to be there in the effect
chain.  Then we just use one of the reserved bytes in the effect save
state to say what the next effect is.  Voilà, an almost arbitrary effect
chain.

This reorganizes the effect chain in another way too: not only can you
re-order the effects, but the effect chain now deals with the 'mix' for
you, which means that every single effect now automatically has a mix
setting, and the ones that did it explicitly have been removed.

Note that the vibrato effect did an interesting equal-power mix thing,
and that also was removed, but I'm making a note of it here because I
wonder if that thing should be how we do the generic mixing.  But I
wanted to keep the changes _fairly_ minimal.

As always, the WebMIDI code is all antigravity.  And let's be honest, in
this case that's the complex case.  But it would have been a nightmare
to do in the embedded context on the pedal, and with this whole "UI
through WebMIDI" the effect chain changes are fairly simple.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2026-07-23 21:40:48 -07:00

55 lines
1.3 KiB
JavaScript

const CACHE_NAME = 'rp2350-pedal-cache-v8';
const urlsToCache = [
'./',
'./index.html',
'./style.css',
'./app.js',
'./effects.js',
'./manifest.json',
'./icon-192.png',
'./icon-512.png'
];
self.addEventListener('install', event => {
self.skipWaiting();
event.waitUntil(
caches.open(CACHE_NAME)
.then(cache => {
return cache.addAll(urlsToCache);
})
);
});
self.addEventListener('fetch', event => {
event.respondWith(
fetch(event.request).then(response => {
// Network success - update cache and return response
if (response && response.status === 200) {
const responseClone = response.clone();
caches.open(CACHE_NAME).then(cache => {
cache.put(event.request, responseClone);
});
}
return response;
}).catch(() => {
// Network failed - fallback to cache
return caches.match(event.request);
})
);
});
self.addEventListener('activate', event => {
const cacheWhitelist = [CACHE_NAME];
event.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames.map(cacheName => {
if (cacheWhitelist.indexOf(cacheName) === -1) {
return caches.delete(cacheName);
}
})
);
})
);
});