Madewithwebsim / 7BGbbW7K0gEtscV9M.html
allknowingroger's picture
Upload 17 files
36a60d4 verified
raw
history blame contribute delete
No virus
9.63 kB
<html><head><base href="https://piano.midi/webmidi@latest/flex-horizontal/use-event.note.name+event.note.octave__not.value/in_getKeys_just_do_straight_comparison/whiteKeys_and_blackKeys_are_nodeLists_not_arrays/position_fix_keyboard_above_text/playable-with-mouse-too/hide%3Ccomments%3Eand%3Clinks%3E/drop_piano_2_octaves/abnormify_sound/push_audio_creativity/explore_tonejs_instruments/drop_piano_decibels_by_10/add_higher_octave/hush_comments"><title>Sonic Artistry</title>
<style>
body {
margin: 0;
padding: 0;
background: radial-gradient(circle at center, #111, #333);
color: #fff;
font-family: monospace;
overflow: hidden;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
}
#instrumentSelector {
position: absolute;
top: 10px;
left: 10px;
background-color: rgba(255, 255, 255, 0.1);
padding: 10px;
border-radius: 5px;
z-index: 1;
}
#keyboardContainer {
display: flex;
flex-direction: row;
align-items: flex-end;
margin-bottom: 20px;
}
.key {
width: 50px;
height: 200px;
background: linear-gradient(to bottom, #eee, #ccc);
border: 1px solid #000;
box-sizing: border-box;
cursor: pointer;
transition: background-color 0.2s, transform 0.2s;
position: relative;
transform-style: preserve-3d;
display: flex;
justify-content: center;
align-items: flex-end;
padding-bottom: 10px;
font-size: 12px;
}
.key::after {
content: attr(data-note);
}
.key.black {
width: 30px;
height: 120px;
background: linear-gradient(to bottom, #555, #222);
margin-right: -15px;
margin-left: -15px;
z-index: 1;
}
.key:hover {
background: linear-gradient(to bottom, #ddd, #bbb);
}
.key.black:hover {
background: linear-gradient(to bottom, #777, #444);
}
.key.pressed {
background: linear-gradient(to bottom, #ccc, #aaa);
transform: translateZ(20px);
}
.key.black.pressed {
background: linear-gradient(to bottom, #666, #333);
transform: translateZ(20px);
}
.key::before {
content: "";
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 0;
height: 0;
background-color: rgba(255, 255, 255, 0.5);
border-radius: 50%;
opacity: 0;
transition: width 0.2s, height 0.2s, opacity 0.2s;
}
.key.pressed::before {
width: 100px;
height: 100px;
opacity: 1;
}
.key.black::before {
background-color: rgba(0, 0, 0, 0.5);
}
</style>
</head>
<body>
<div id="instrumentSelector">
<label for="instrumentSelect">Select Instrument:</label>
<select id="instrumentSelect">
<option value="AMSynth">AM Synth</option>
<option value="FMSynth">FM Synth</option>
<option value="DuoSynth">Duo Synth</option>
<option value="MonoSynth">Mono Synth</option>
<option value="PluckSynth">Pluck Synth</option>
<option value="Membrane">Membrane Synth</option>
<option value="MetalSynth">Metal Synth</option>
<option value="NoiseSynth">Noise Synth</option>
</select>
</div>
<div id="keyboardContainer">
<div class="key white" data-note="C2" data-midi="36"></div>
<div class="key black" data-note="C#2" data-midi="37"></div>
<div class="key white" data-note="D2" data-midi="38"></div>
<div class="key black" data-note="D#2" data-midi="39"></div>
<div class="key white" data-note="E2" data-midi="40"></div>
<div class="key white" data-note="F2" data-midi="41"></div>
<div class="key black" data-note="F#2" data-midi="42"></div>
<div class="key white" data-note="G2" data-midi="43"></div>
<div class="key black" data-note="G#2" data-midi="44"></div>
<div class="key white" data-note="A2" data-midi="45"></div>
<div class="key black" data-note="A#2" data-midi="46"></div>
<div class="key white" data-note="B2" data-midi="47"></div>
<div class="key white" data-note="C3" data-midi="48"></div>
<div class="key black" data-note="C#3" data-midi="49"></div>
<div class="key white" data-note="D3" data-midi="50"></div>
<div class="key black" data-note="D#3" data-midi="51"></div>
<div class="key white" data-note="E3" data-midi="52"></div>
<div class="key white" data-note="F3" data-midi="53"></div>
<div class="key black" data-note="F#3" data-midi="54"></div>
<div class="key white" data-note="G3" data-midi="55"></div>
<div class="key black" data-note="G#3" data-midi="56"></div>
<div class="key white" data-note="A3" data-midi="57"></div>
<div class="key black" data-note="A#3" data-midi="58"></div>
<div class="key white" data-note="B3" data-midi="59"></div>
<div class="key white" data-note="C4" data-midi="60"></div>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/Tone.js"></script>
<script src="https://cdn.jsdelivr.net/npm/webmidi@latest/dist/iife/webmidi.iife.min.js"></script>
<script>
const whiteKeys = document.querySelectorAll('.key.white');
const blackKeys = document.querySelectorAll('.key.black');
const instrumentSelect = document.getElementById('instrumentSelect');
let synth;
const reverb = new Tone.Reverb({ decay: 5, wet: 0.5 }).toDestination();
const delay = new Tone.FeedbackDelay({ delayTime: 0.5, feedback: 0.25, wet: 0.25 }).toDestination();
function initSynth(instrumentType) {
if (synth) {
synth.disconnect();
}
switch (instrumentType) {
case 'AMSynth':
synth = new Tone.PolySynth(Tone.AMSynth, { polyphony: 32, volume: -10 }).toDestination();
break;
case 'FMSynth':
synth = new Tone.PolySynth(Tone.FMSynth, { polyphony: 32, volume: -10 }).toDestination();
break;
case 'DuoSynth':
synth = new Tone.PolySynth(Tone.DuoSynth, { polyphony: 32, volume: -10 }).toDestination();
break;
case 'MonoSynth':
synth = new Tone.MonoSynth({ volume: -10 }).toDestination();
break;
case 'PluckSynth':
synth = new Tone.PluckSynth({ volume: -10 }).toDestination();
break;
case 'Membrane':
synth = new Tone.PolySynth(Tone.MembraneSynth, { polyphony: 32, volume: -10 }).toDestination();
break;
case 'MetalSynth':
synth = new Tone.PolySynth(Tone.MetalSynth, { polyphony: 32, volume: -10 }).toDestination();
break;
case 'NoiseSynth':
synth = new Tone.NoiseSynth({ volume: -10 }).toDestination();
break;
default:
synth = new Tone.PolySynth(Tone.AMSynth, { polyphony: 32, volume: -10 }).toDestination();
}
synth.connect(reverb);
synth.connect(delay);
}
initSynth(instrumentSelect.value);
instrumentSelect.addEventListener('change', (event) => {
initSynth(event.target.value);
});
let midiAccess, midiInput;
WebMidi.enable(err => {
if (err) {
console.error('Failed to enable WebMIDI:', err);
return;
}
console.log('WebMIDI enabled!');
midiInput = WebMidi.inputs[0];
if (!midiInput) {
console.warn('No MIDI input device detected.');
return;
}
console.log(`Connected to MIDI input device: ${midiInput.name}`);
midiInput.addListener('noteon', 'all', event => {
const midiNoteValue = `${event.note.name}${event.note.octave}`;
handleNoteOn(midiNoteValue, event.velocity / 127);
});
midiInput.addListener('noteoff', 'all', event => {
const midiNoteValue = `${event.note.name}${event.note.octave}`;
handleNoteOff(midiNoteValue);
});
});
function handleNoteOn(midiNoteValue, velocity) {
const whiteKey = Array.from(whiteKeys).find(key => key.dataset.note === midiNoteValue);
const blackKey = Array.from(blackKeys).find(key => key.dataset.note === midiNoteValue);
if (whiteKey) {
whiteKey.classList.add('pressed');
synth.triggerAttack(noteToFrequency(whiteKey.dataset.midi), velocity);
} else if (blackKey) {
blackKey.classList.add('pressed');
synth.triggerAttack(noteToFrequency(blackKey.dataset.midi), velocity);
}
}
function handleNoteOff(midiNoteValue) {
const whiteKey = Array.from(whiteKeys).find(key => key.dataset.note === midiNoteValue);
const blackKey = Array.from(blackKeys).find(key => key.dataset.note === midiNoteValue);
if (whiteKey) {
whiteKey.classList.remove('pressed');
synth.triggerRelease(noteToFrequency(whiteKey.dataset.midi));
} else if (blackKey) {
blackKey.classList.remove('pressed');
synth.triggerRelease(noteToFrequency(blackKey.dataset.midi));
}
}
function whiteKeyMouseDown(event) {
const key = event.target;
key.classList.add('pressed');
synth.triggerAttack(noteToFrequency(key.dataset.midi), 0.5);
}
function whiteKeyMouseUp(event) {
const key = event.target;
key.classList.remove('pressed');
synth.triggerRelease(noteToFrequency(key.dataset.midi));
}
function blackKeyMouseDown(event) {
const key = event.target;
key.classList.add('pressed');
synth.triggerAttack(noteToFrequency(key.dataset.midi), 0.5);
}
function blackKeyMouseUp(event) {
const key = event.target;
key.classList.remove('pressed');
synth.triggerRelease(noteToFrequency(key.dataset.midi));
}
whiteKeys.forEach(key => {
key.addEventListener('mousedown', whiteKeyMouseDown);
key.addEventListener('mouseup', whiteKeyMouseUp);
key.addEventListener('mouseleave', whiteKeyMouseUp);
});
blackKeys.forEach(key => {
key.addEventListener('mousedown', blackKeyMouseDown);
key.addEventListener('mouseup', blackKeyMouseUp);
key.addEventListener('mouseleave', blackKeyMouseUp);
});
function noteToFrequency(note) {
const baseFrequency = 440;
return baseFrequency * Math.pow(2, (note - 69) / 12);
}
</script>
</body>
</html>