Public
Edited
Jan 24, 2023
Insert cell
Insert cell
Insert cell
viewof mute = html`<input type='checkbox' />`
Insert cell
width=3*height
Insert cell
viewof volume = html`<input type='range' min=-24 max=0 value=-20 />`
Insert cell
viewof offset = Inputs.range([-10, 10], {label: "Amount", step: 1})
Insert cell
Insert cell
function note(i){
const min = fundamentalFrequency * 4;
const note = min * Math.pow(Math.pow(2, 1/12), i);
return note
}
Insert cell
viewof zoom = Inputs.range([1, 10], {label: "Amount"})
Insert cell
height=52
Insert cell
function row(i) {
return Math.floor(i/6);
}
Insert cell
cardDims = [24, 24 *.7]
Insert cell
margin = [2, 2];

Insert cell
function cardIndex(position) {
}
Insert cell
function column(i) {
return i % 6;
}
Insert cell
viewof range = Inputs.range([0, 100], {label: "Amount", step: 1})
Insert cell
function cardPos(i) {
return {
x: (column(i)) * (cardDims[0]+margin[0]),
y: row(i) * (cardDims[1]+margin[1]+offset)
}
}
Insert cell
function getNoteCard(x, i) {
const smolGuy = (cardDims[0]-12)/12;
const indicatorOffset = {
x: smolGuy * i+6,
y: 0
}
return htl.svg.fragment`
<rect
width=${cardDims[0]}
height=${cardDims[1]}
fill=${colors[i*12]}
rx=2
x=${cardPos(i).x}
y=${cardPos(i).y}
stroke=${
selectedCard === i ? "pink" : "none"
}
></rect>
<rect
width=${smolGuy+2}
height=${smolGuy+1}
fill="black"
x=${cardPos(i).x + indicatorOffset.x-1}
y=${cardPos(i).y}
></rect>
<rect
width=${smolGuy}
height=${smolGuy}
fill="white"
x=${cardPos(i).x + indicatorOffset.x}
y=${cardPos(i).y}
></rect>


`;
}
Insert cell
# Todo

- Play notes when u click on a card
- integrate card interactions
- 1st click: highlight card
- 2nd click
- if other card, stack highlighted card on top
- if elsewhere, return highlighted card to default position
Insert cell
colors =["#a50026","#a70226","#a90426","#ab0626","#ad0826","#af0926","#b10b26","#b30d26","#b50f26","#b61127","#b81327","#ba1527","#bc1727","#be1927","#c01b27","#c21d28","#c41f28","#c52128","#c72328","#c92529","#cb2729","#cc2929","#ce2b2a","#d02d2a","#d12f2b","#d3312b","#d4332c","#d6352c","#d7382d","#d93a2e","#da3c2e","#dc3e2f","#dd4030","#de4331","#e04532","#e14733","#e24a33","#e34c34","#e44e35","#e55136","#e75337","#e85538","#e95839","#ea5a3a","#eb5d3c","#ec5f3d","#ed613e","#ed643f","#ee6640","#ef6941","#f06b42","#f16e43","#f17044","#f27346","#f37547","#f37848","#f47a49","#f57d4a","#f57f4b","#f6824d","#f6844e","#f7864f","#f78950","#f88b51","#f88e53","#f89054","#f99355","#f99556","#f99858","#fa9a59","#fa9c5a","#fa9f5b","#fba15d","#fba35e","#fba660","#fba861","#fcaa62","#fcad64","#fcaf65","#fcb167","#fcb368","#fcb56a","#fdb86b","#fdba6d","#fdbc6e","#fdbe70","#fdc071","#fdc273","#fdc474","#fdc676","#fdc878","#fdca79","#fecc7b","#fecd7d","#fecf7e","#fed180","#fed382","#fed584","#fed685","#fed887","#feda89","#fedb8b","#fedd8d","#fede8f","#fee090","#fee192","#fee394","#fee496","#fee698","#fee79a","#fee89b","#feea9d","#feeb9f","#feeca0","#feeda2","#feeea3","#fdefa5","#fdf0a6","#fdf1a7","#fdf2a9","#fcf3aa","#fcf4ab","#fcf5ab","#fbf5ac","#fbf6ad","#faf6ad","#faf7ad","#f9f7ae","#f8f7ae","#f7f8ad","#f7f8ad","#f6f8ad","#f5f8ac","#f4f8ab","#f3f8ab","#f1f8aa","#f0f7a9","#eff7a8","#eef7a6","#edf6a5","#ebf6a4","#eaf6a2","#e8f5a1","#e7f59f","#e6f49d","#e4f39c","#e2f39a","#e1f298","#dff297","#def195","#dcf093","#daef92","#d9ef90","#d7ee8e","#d5ed8d","#d3ec8b","#d2ec89","#d0eb88","#ceea86","#cce985","#cae983","#c8e882","#c6e780","#c4e67f","#c2e57e","#c0e47c","#bee47b","#bce37a","#bae279","#b8e178","#b6e076","#b4df75","#b2de74","#b0dd73","#aedc72","#acdb71","#a9da70","#a7d970","#a5d86f","#a3d86e","#a0d76d","#9ed66c","#9cd56c","#99d36b","#97d26b","#95d16a","#92d069","#90cf69","#8ece68","#8bcd68","#89cc67","#86cb67","#84ca66","#81c966","#7fc866","#7cc665","#79c565","#77c464","#74c364","#71c263","#6fc063","#6cbf62","#69be62","#67bd62","#64bc61","#61ba60","#5eb960","#5cb85f","#59b65f","#56b55e","#53b45e","#51b25d","#4eb15c","#4baf5c","#48ae5b","#46ad5a","#43ab5a","#40aa59","#3da858","#3ba757","#38a557","#36a456","#33a255","#31a154","#2e9f54","#2c9d53","#2a9c52","#289a51","#259950","#23974f","#21954f","#1f944e","#1e924d","#1c904c","#1a8f4b","#188d4a","#178b49","#158948","#148747","#128646","#118446","#108245","#0e8044","#0d7e43","#0c7d42","#0b7b41","#0a7940","#08773f","#07753e","#06733d","#05713c","#04703b","#036e3a","#026c39","#016a38","#006837"]
Insert cell
Insert cell
synths = {
//create a synth and connect it to the master output (your speakers)
var synth = new Tone.PolySynth({
maxPolyphony: 12,
voice: Tone.FMSynth
}).chain(Volume, Tone.Master);
synth.set({
oscillator: {
type: "sine"
},
envelope: {
decay: 1,
release: 1
}
});

var synth2 = new Tone.PolySynth({
maxPolyphony: 12,
voice: Tone.FMSynth
}).chain(Volume, Tone.Master);
synth2.set({
oscillator: {
type: "sine"
},
envelope: {
decay: .1,
release: .1
}
});

try {
yield {synth, synth2};
yield invalidation;
} finally {
//synth.dispose();
}
}
Insert cell
Insert cell
fundamentalFrequency = 40.45;
Insert cell
{

synths.synth.triggerAttackRelease(note(selectedCard), .5)
}
Insert cell
Volume = new Tone.Volume(volume)
Insert cell
{ Volume.mute = mute }
Insert cell
Tone = require('tone')
Insert cell
# Appendix

We used the known values of some notes from here as a test case
https://pages.mtu.edu/~suits/notefreq432.html

ended up reading from here to get the math that gave something that sounded right
https://en.wikipedia.org/wiki/Equal_temperament

A prior attempt added 1/12 of the difference between the min frequency & 2*min frequency
Insert cell
[...Array(12).keys()].map(note).map((x,i) => ({val: x, diff: x - known_values[i]}))
Insert cell
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more