Newer
Older
2024-TakizawaSoetsu / system / kenban / kenban.html
@Soetsu Takizawa Soetsu Takizawa on 16 Jul 2024 7 KB add
<!DOCTYPE html>
<html lang="jp">
<head>
<meta charset="UTF-8">
<title>作曲ページ</title>
<link rel="stylesheet" href="./kenban.css">
<style>
        .hidden {
          display: none;
        }
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tone/14.8.49/Tone.js"></script>
<script>
let synth = new Tone.Synth().toDestination();
const instruments = {
	"synth": new Tone.Synth().toDestination(),
    	"piano": new Tone.Sampler({
	"C3": "https://nbrosowsky.github.io/tonejs-instruments/samples/piano/C3.mp3", 
	"C4": "https://nbrosowsky.github.io/tonejs-instruments/samples/piano/C4.mp3",
	"C5": "https://nbrosowsky.github.io/tonejs-instruments/samples/piano/C5.mp3",
	"C6": "https://nbrosowsky.github.io/tonejs-instruments/samples/piano/C6.mp3",
	"C7": "https://nbrosowsky.github.io/tonejs-instruments/samples/piano/C7.mp3"
	}).toDestination(),
	"violin": new Tone.Sampler({
	"G3": "https://nbrosowsky.github.io/tonejs-instruments/samples/violin/G3.mp3",
	"C4": "https://nbrosowsky.github.io/tonejs-instruments/samples/violin/C4.mp3",
	"C5": "https://nbrosowsky.github.io/tonejs-instruments/samples/violin/C5.mp3",
	"C6": "https://nbrosowsky.github.io/tonejs-instruments/samples/violin/C6.mp3",
	"C7": "https://nbrosowsky.github.io/tonejs-instruments/samples/violin/C7.mp3"
          }).toDestination(),
          "trumpet": new Tone.Sampler({
    	  "F3": "https://nbrosowsky.github.io/tonejs-instruments/samples/trumpet/F3.mp3",
    	  "C4": "https://nbrosowsky.github.io/tonejs-instruments/samples/trumpet/C4.mp3",
    	  "A5": "https://nbrosowsky.github.io/tonejs-instruments/samples/trumpet/A5.mp3",
          "G4": "https://nbrosowsky.github.io/tonejs-instruments/samples/trumpet/G4.mp3",
    	  "C6": "https://nbrosowsky.github.io/tonejs-instruments/samples/trumpet/C6.mp3",
          }).toDestination()
        };
        let recordedNotes = [];
        let noteLengths = [];
        let pianoRoll = [];
        let currentOctave = 4; // 初期オクターブ
     
        window.onload = () => {
          drawKeyboard();
        };
     
    const drawKeyboard = () => {
          const musicalScaleArray = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"];
          let baseKey;
          for (let i = 0; i < 25; i++) {
            const key = document.createElement("button");
            key.id = `key_${musicalScaleArray[i % musicalScaleArray.length]}${Math.floor(i / 12) + 3}`;
            key.onmousedown = recordNote;
            key.onmouseup = stop;
            key.onmouseleave = stop;
     
            if (musicalScaleArray[i % 12].indexOf("#") > -1) {
              key.classList.add("black");
            } else {
              key.classList.add("white");
              baseKey = document.createElement("div");
            }
            baseKey.appendChild(key);
            document.getElementById("keyboard").appendChild(baseKey);
          }
        };
     
        const recordNote = (e) => {
          const scale = e.target.id.split("_")[1];
          const noteLength = document.getElementById("noteLength").value;
          const octaveAdjustedScale = adjustOctave(scale);
          recordedNotes.push(octaveAdjustedScale);
          noteLengths.push(noteLength);
          synth.triggerAttack(octaveAdjustedScale);
          addToPianoRoll(octaveAdjustedScale, noteLength);
          updatePianoRoll();
        };
     
        const adjustOctave = (scale) => {
          const note = scale.slice(0, -1);
          const octave = parseInt(scale.slice(-1));
          const newOctave = octave + currentOctave - 4; // 初期オクターブからの差分を計算
          return `${note}${newOctave}`;
        };
     
        const addToPianoRoll = (scale, length) => {
          pianoRoll.push({ scale, length });
        };
     
        const updatePianoRoll = () => {
          const pianoRollTable = document.getElementById("pianoRoll");
          pianoRollTable.innerHTML = "<tr><th>音高</th><th>長さ</th></tr>";
          pianoRoll.forEach((note, index) => {
            const newRow = document.createElement("tr");
            newRow.innerHTML = `<td>${note.scale}</td><td>${note.length}</td>`;
            pianoRollTable.appendChild(newRow);
          });
        };
        
        const play = async () => {
    	await Tone.start();
    	Tone.Transport.bpm.value = document.getElementById("tempo").value;
     
    	let currentTime = Tone.now();
     
    	recordedNotes.forEach((scale, index) => {
    	    const duration = Tone.Time(noteLengths[index]).toSeconds();
    	    const endTime = currentTime + duration;
    	    if (scale !== "rest") {
    		synth.triggerAttackRelease(scale, noteLengths[index], currentTime);
    	    }
    	    currentTime = endTime;
    	});
        };
     
        const stop = async () => {
          synth.triggerRelease();
        };
     
        const reset = () => {
          recordedNotes = [];
          noteLengths = [];
          pianoRoll = [];
          updatePianoRoll();
        };
     
        const toggleKeyboard = () => {
          const keyboard = document.getElementById("keyboard");
          if (keyboard.classList.contains("hidden")) {
            keyboard.classList.remove("hidden");
          } else {
            keyboard.classList.add("hidden");
          }
        };
     
        const setInstrument = (instrumentName) => {
          synth = instruments[instrumentName];
        };
     
        const increaseOctave = () => {
          if (currentOctave < 7) {
            currentOctave++;
            document.getElementById("currentOctave").textContent = currentOctave;
          }
        };
     
        const decreaseOctave = () => {
          if (currentOctave > 1) {
            currentOctave--;
            document.getElementById("currentOctave").textContent = currentOctave;
          }
        };
        const recordRest = () => {
    	const noteLength = document.getElementById("noteLength").value;
    	recordedNotes.push("rest");
    	noteLengths.push(noteLength);
    	addToPianoRoll("休符", noteLength);
    	updatePianoRoll();
        };
</script>
</head>
<body>
<p>キーボード</p>
<button onclick="toggleKeyboard()">show/hide</button>
<div id="keyboard" class="keyboard hidden"></div>
      <p>
        <label for="tempo">BPM:</label>
        <input type="number" id="tempo" value="120" min="1">
      </p>
      <p>
        <label for="noteLength">length of notes</label>
        <select id="noteLength">
          <option value="1n">1</option>
          <option value="2n">2</option>
          <option value="4n.">4.</option>
          <option value="4n">4</option>
          <option value="8n.">8.</option>
          <option value="8n">8</option>
          <option value="16n">16</option>
        </select>
      </p>
      <p>
        <label for="instrumentSelect">Instrument:</label>
        <select id="instrumentSelect" onchange="setInstrument(this.value)">
         <option value="synth">シンセサイザー</option>
         <option value="piano">ピアノ</option>
         <option value="violin">ヴァイオリン</option>
         <option value="trumpet">トランペット</option>
        </select>
      </p>
      <p>
        <button onclick="recordRest()">休符を入力</button>
      </p>
     
      <p>
        <button onclick="decreaseOctave()">-</button>
        <span>Octave: <span id="currentOctave">4</span></span>
        <button onclick="increaseOctave()">+</button>
      </p>
      <button onclick="play()">start</button>
      <button onclick="reset()">reset</button>
      <table id="pianoRoll"></table>
</body>
</html>