Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Patches #41

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,18 @@
<span class="value"><span id="cutoffSustainLabel"></span><span class="gray">x</span></span>
<input id="cutoffSustainSlider" type="range" min="0" max="5" step=".01" oninput="cutoff.setSustain(this.value)"/>
</div>
<!-- Expanding Etc into Cut to make room for patches -->
<div id="auxEtc" class="sliderPanel">
<div>
<span class="name gray">patch</span>
<br>
<div id="patches">
<span class="arrow prev" onclick="prevPatch()">►</span>
<span class="value"><span id="patchLabel">patch</span></span>
<span class="arrow" onclick="nextPatch()">►</span>
</div>
</div>
</div>
</div>
<div id="etcSliders" class="sliderPanel">
<div>
Expand Down
131 changes: 110 additions & 21 deletions script.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
let polysynth;
let settings;
let patchIndex = 0;

// toggles
let invertMode = false;
let invertChord = false;
let specialChord = false;

const debounce = (func, timeout = 300) => {
let timer;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => func.apply(this, args), timeout);
};
};

const scale = (num, inMin, inMax, outMin, outMax) =>
(num - inMin) * (outMax - outMin) / (inMax - inMin) + outMin;

Expand Down Expand Up @@ -123,12 +132,11 @@ const toggleSettings = () => {
$('.settings').toggleClass('on');
};

const saveSettings = (newSettings) => {
// TODO: since this is called on input, debounce to limit number of times we access storage
const saveSettings = debounce((newSettings) => {
const settings = JSON.parse(localStorage.getItem('settings'));
Object.assign(settings, newSettings);
localStorage.setItem('settings', JSON.stringify(settings));
};
});

const setVolume = (newVolume) => {
newVolume = Number(newVolume);
Expand Down Expand Up @@ -270,6 +278,98 @@ const setWaveform = (newWaveform) => {
saveSettings({waveform: newWaveform});
};

const patches = [
{
name: 'warm',
octave: -1,
bendRange: 2, // In semitones
waveform: 'sawtooth',
numVoices: 5,
stereoWidth: 1,
attack: 0.28,
decay: 0.28,
sustain: 1,
release: 0.28,
cutoff: {
maxFrequency: 1800,
attack: 0.1,
decay: 2.5,
sustain: 0.2
},
},
{
name: 'buzzy',
octave: -1,
bendRange: 2, // In semitones
waveform: 'sawtooth',
numVoices: 5,
stereoWidth: 1,
attack: 0.28,
decay: 0.28,
sustain: 1,
release: 0.28,
cutoff: {
maxFrequency: 7500,
attack: 0.1,
decay: 2.5,
sustain: 0.2
},
},
{
name: 'hollow',
octave: -1,
bendRange: 2, // In semitones
waveform: 'triangle',
numVoices: 5,
stereoWidth: 1,
attack: 0.28,
decay: 0.28,
sustain: 0.3,
release: 2.5,
cutoff: {
maxFrequency: 7500,
attack: 0.1,
decay: 2.5,
sustain: 0.2
},
},
];

const loadPatch = () => {
const patch = patches[patchIndex];

setOctave(patch.octave);
setWidth(patch.stereoWidth);
setBendRange(patch.bendRange);
setAttack(patch.attack);
setDecay(patch.decay);
setSustain(patch.sustain);
setRelease(patch.release);
cutoff.setMaxFrequency(patch.cutoff.maxFrequency);
cutoff.setAttack(patch.cutoff.attack);
cutoff.setDecay(patch.cutoff.decay);
cutoff.setSustain(patch.cutoff.sustain);
setWaveform(patch.waveform);

$('#patchLabel').text(patch.name);
};

const prevPatch = () => {
patchIndex--;
if (patchIndex < 0) {
patchIndex = patches.length - 1;
}
loadPatch();
};

const nextPatch = () => {
patchIndex++;
if (patchIndex > patches.length - 1) {
patchIndex = 0;
}
loadPatch();
};

// reload page w/o POST
const panic = () => {
window.location = window.location;
Expand Down Expand Up @@ -337,7 +437,7 @@ const panic = () => {
ctrl() {
// controllers such as mod wheel, aftertouch, breath add vibrato
const [, , strength] = msg.data;
polysynth.lfo.depth(normalize(strength) * 10);
polysynth.lfo.depth(normalize(strength) * 20);
},
unknown() {}
};
Expand Down Expand Up @@ -386,32 +486,21 @@ const panic = () => {
let settings = JSON.parse(localStorage.getItem('settings'));
if (!settings) {
// load and save defaults
// a little torn on this, but for now key & volume are not saved to patch
settings = {
key: 40, // C
octave: -1,
bendRange: 2, // In semitones
waveform: 'sawtooth',
patch: patchIndex,
key: 40, // C,
volume: 0.9,
numVoices: 5,
stereoWidth: 1,
attack: 0.28,
decay: 0.28,
sustain: 1,
release: 0.28,
cutoff: {
maxFrequency: 1800,
attack: 0.1,
decay: 2.5,
sustain: 0.2
}
};
localStorage.setItem('settings', JSON.stringify(settings));
}
return settings;
};

settings = getSettings();
polysynth = new Polysynth(audioCtx, settings);
polysynth = new Polysynth(audioCtx, Object.assign({}, patches[settings.patch], settings));

loadPatch();

// update controls to display initial synth values
$('#keySlider').val(settings.key); // not a subpoly or submono property
Expand Down
28 changes: 27 additions & 1 deletion styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -184,12 +184,38 @@ button:active {
border-radius: 1.5vw 1.5vw 0 0;
}

#auxEtc {
background-color: hsl(340, 86%, 50%);
width: 27.6667vw;
margin: -.5vw -3vw;
border-radius: 1.5vw 0 0 0;
}

#etcSliders {
background-color: hsl(340, 86%, 50%);
border-bottom-left-radius: 0;
float: right;
}

#patches {
display: flex;
justify-content: center;
line-height: 2vw;
}

#patches span {
margin: .5vw;
}

.arrow {
font-size: 2vw;
height: 1.76vw;
}

.prev {
transform: rotate(180deg);
}

.sliderPanel {
width: 27.6667vw;
height: 54.25vw;
Expand Down Expand Up @@ -272,6 +298,6 @@ button.settings {
position: relative;
transform: translate(-50%, -50%);
left: 50%;
top: 50%;
top: 45%;
padding: 1vw;
}