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>