File size: 6,107 Bytes
af6912c |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="favicon.ico" type="image/x-icon"/>
<link rel="stylesheet" href="examples-styles.css"/>
<title>Karaoke Synth</title>
<style>
main {
max-width: 770px;
margin: 0 auto;
}
.buttons {
text-align: center;
}
</style>
<script src="../dist/abcjs-basic.js" type="text/javascript"></script>
<script type="text/javascript">
var abc =
'T:Cindy\n' +
'M:4/4\n' +
'K:G\n' +
'%%score (harmony melody)\n' +
'L:1/4\n' +
'[V: harmony]' +
'g||"G"gggg|dB2g|gggd|g3g|\n' +
'"G"gggd|dcB2|dccA|Bzz2|\n' +
'"C"G2cc|ccd/c/B|"G"G4-|Gzz2|\n' +
'"C"G2cc|cc2c|"D7"dddc|"G"B2z2|]\n' +
'[V: melody]' +
'd||"G"eddB|AG2d|eddB|d3d|\n' +
'"G"eddB|BAG2|"D7"BGGE|"G"GzB/A/G|\n' +
'"C"E2GG|AGB/A/G|"G"D4-|DzB/A/G|\n' +
'"C"E2GG|AG2A|"D7"BBBA|"G"G2z2|]\n';
function load() {
// First draw the music - this supplies an object that has a lot of information about how to create the synth.
var visualObj = ABCJS.renderAbc("paper", abc, {
responsive: "resize" })[0];
// This object is the class that will contain the buffer
var midiBuffer;
var startChordsButton = document.querySelector(".play-chords");
var startMelodiesButton = document.querySelector(".play-melodies");
var startHarmonyButton = document.querySelector(".play-harmony");
var startMelodyButton = document.querySelector(".play-melody");
var startAllButton = document.querySelector(".play-all");
var stopAudioButton = document.querySelector(".stop-audio");
startChordsButton.addEventListener("click", function() {
var options = {voicesOff: true};
play(options);
});
startMelodiesButton.addEventListener("click", function() {
var options = {chordsOff: true};
play(options);
});
startHarmonyButton.addEventListener("click", function() {
var options = {chordsOff: true, voicesOff: [1]};
play(options);
});
startMelodyButton.addEventListener("click", function() {
var options = {chordsOff: true, voicesOff: [0]};
play(options);
});
startAllButton.addEventListener("click", function() {
var options = {};
play(options);
});
function play(options) {
startChordsButton.setAttribute("style", "display:none;");
startMelodiesButton.setAttribute("style", "display:none;");
startHarmonyButton.setAttribute("style", "display:none;");
startMelodyButton.setAttribute("style", "display:none;");
startAllButton.setAttribute("style", "display:none;");
if (ABCJS.synth.supportsAudio()) {
stopAudioButton.setAttribute("style", "");
// An audio context is needed - this can be passed in for two reasons:
// 1) So that you can share this audio context with other elements on your page.
// 2) So that you can create it during a user interaction so that the browser doesn't block the sound.
// Setting this is optional - if you don't set an audioContext, then abcjs will create one.
window.AudioContext = window.AudioContext ||
window.webkitAudioContext ||
navigator.mozAudioContext ||
navigator.msAudioContext;
var audioContext = new window.AudioContext();
audioContext.resume().then(function () {
// In theory the AC shouldn't start suspended because it is being initialized in a click handler, but iOS seems to anyway.
// This does a bare minimum so this object could be created in advance, or whenever convenient.
midiBuffer = new ABCJS.synth.CreateSynth();
// midiBuffer.init preloads and caches all the notes needed. There may be significant network traffic here.
return midiBuffer.init({
visualObj: visualObj,
audioContext: audioContext,
millisecondsPerMeasure: visualObj.millisecondsPerMeasure(),
options: options
}).then(function (response) {
// console.log(response); // this contains the list of notes that were loaded.
// midiBuffer.prime actually builds the output buffer.
return midiBuffer.prime();
}).then(function () {
// At this point, everything slow has happened. midiBuffer.start will return very quickly and will start playing very quickly without lag.
midiBuffer.start();
return Promise.resolve();
}).catch(function (error) {
if (error.status === "NotSupported") {
stopAudioButton.setAttribute("style", "display:none;");
var audioError = document.querySelector(".audio-error");
audioError.setAttribute("style", "");
} else
console.warn("synth error", error);
});
});
} else {
var audioError = document.querySelector(".audio-error");
audioError.setAttribute("style", "");
}
}
stopAudioButton.addEventListener("click", function() {
startChordsButton.setAttribute("style", "");
startMelodiesButton.setAttribute("style", "");
startHarmonyButton.setAttribute("style", "");
startMelodyButton.setAttribute("style", "");
startAllButton.setAttribute("style", "");
stopAudioButton.setAttribute("style", "display:none;");
if (midiBuffer)
midiBuffer.stop();
});
}
</script>
</head>
<body onload="load()">
<header>
<img src="https://paulrosen.github.io/abcjs/img/abcjs_comp_extended_08.svg" alt="abcjs logo">
<h1>abcjs karaoke synth</h1>
</header>
<div class="container">
<main>
<div id="paper"></div>
<div class="buttons">
<button class="play-chords">Play Chords</button>
<button class="play-melodies">Play Melodies</button>
<button class="play-harmony">Play Harmony</button>
<button class="play-melody">Play Melody</button>
<button class="play-all">Play All</button>
<button class="stop-audio" style="display:none;">Stop Audio</button>
</div>
<div class='audio-error' style="display:none;">Audio is not supported in this browser.</div>
</main>
</div>
</body>
</html>
|