File size: 5,799 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 |
<!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="stylesheet" href="examples-styles.css"/>
<link rel="icon" href="favicon.ico" type="image/x-icon"/>
<title>abcjs: Basic Synth Demo</title>
<style>
main {
max-width: 770px;
margin: 0 auto;
}
.row {
display: flex;
justify-content: space-between;
align-items: flex-start;
}
.status {
padding: 2px 10px 10px 10px;
background-color: #f0f0f0;
width:250px;
}
@media (prefers-color-scheme: dark) {
.status {
background-color: #000000;
}
}
</style>
<script src="../dist/abcjs-basic.js" type="text/javascript"></script>
<script type="text/javascript">
var abc = "T: Cooley's\n" +
"M: 4/4\n" +
"L: 1/8\n" +
"R: reel\n" +
"K: Emin\n" +
"|:D2|EB{c}BA B2 EB|~B2 AB dBAG|FDAD BDAD|FDAD dAFD|\n" +
"EBBA B2 EB|B2 AB defg|afe^c dBAF|DEFD E2:|\n" +
"|:gf|eB B2 efge|eB B2 gedB|A2 FA DAFA|A2 FA defg|\n" +
"eB B2 eBgB|eB B2 defg|afe^c dBAF|DEFD E2:|";
function load() {
// First draw the music - this supplies an object that has a lot of information about how to create the synth.
// NOTE: If you want just the sound without showing the music, use "*" instead of "paper" in the renderAbc call.
var visualObj = ABCJS.renderAbc("paper", abc, {
responsive: "resize" })[0];
// This object is the class that will contain the buffer
var midiBuffer;
var startAudioButton = document.querySelector(".activate-audio");
var stopAudioButton = document.querySelector(".stop-audio");
var explanationDiv = document.querySelector(".suspend-explanation");
var statusDiv = document.querySelector(".status");
startAudioButton.addEventListener("click", function() {
startAudioButton.setAttribute("style", "display:none;");
explanationDiv.setAttribute("style", "opacity: 0;");
statusDiv.innerHTML = "<div>Testing browser</div>";
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 () {
statusDiv.innerHTML += "<div>AudioContext resumed</div>";
// 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()
}).then(function (response) {
console.log("Notes loaded: ", response)
statusDiv.innerHTML += "<div>Audio object has been initialized</div>";
// console.log(response); // this contains the list of notes that were loaded.
// midiBuffer.prime actually builds the output buffer.
return midiBuffer.prime();
}).then(function (response) {
statusDiv.innerHTML += "<div>Audio object has been primed (" + response.duration + " seconds).</div>";
statusDiv.innerHTML += "<div>status = " + response.status + "</div>"
// At this point, everything slow has happened. midiBuffer.start will return very quickly and will start playing very quickly without lag.
midiBuffer.start();
statusDiv.innerHTML += "<div>Audio started</div>";
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() {
startAudioButton.setAttribute("style", "");
explanationDiv.setAttribute("style", "");
stopAudioButton.setAttribute("style", "display:none;");
if (midiBuffer)
midiBuffer.stop();
});
}
</script>
</head>
<body onload="load()">
<main>
<header>
<img src="https://paulrosen.github.io/abcjs/img/abcjs_comp_extended_08.svg" alt="abcjs logo">
<h1>Basic Synth</h1>
</header>
<div class="container">
<div id="paper"></div>
<p class="suspend-explanation">Browsers won't allow audio to work unless the audio is started in response to a
user action. This prevents auto-playing web sites. Therefore, the
following button is needed to do the initialization:</p>
<div class="row">
<div>
<button class="activate-audio">Activate Audio Context And Play</button>
<button class="stop-audio" style="display:none;">Stop Audio</button>
<div class='audio-error' style="display:none;">Audio is not supported in this browser.</div>
</div>
<div class="status"></div>
</div>
</div>
</main>
</body>
</html>
|