sound.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. class MusicNotes {
  2. constructor() {
  3. this.isMuted = false;
  4. //https://gist.github.com/marcgg/94e97def0e8694f906443ed5262e9cbb
  5. this.frequencyLookup = {
  6. 'C0': 16.35,
  7. 'C#0': 17.32,
  8. 'Db0': 17.32,
  9. 'D0': 18.35,
  10. 'D#0': 19.45,
  11. 'Eb0': 19.45,
  12. 'E0': 20.60,
  13. 'F0': 21.83,
  14. 'F#0': 23.12,
  15. 'Gb0': 23.12,
  16. 'G0': 24.50,
  17. 'G#0': 25.96,
  18. 'Ab0': 25.96,
  19. 'A0': 27.50,
  20. 'A#0': 29.14,
  21. 'Bb0': 29.14,
  22. 'B0': 30.87,
  23. 'C1': 32.70,
  24. 'C#1': 34.65,
  25. 'Db1': 34.65,
  26. 'D1': 36.71,
  27. 'D#1': 38.89,
  28. 'Eb1': 38.89,
  29. 'E1': 41.20,
  30. 'F1': 43.65,
  31. 'F#1': 46.25,
  32. 'Gb1': 46.25,
  33. 'G1': 49.00,
  34. 'G#1': 51.91,
  35. 'Ab1': 51.91,
  36. 'A1': 55.00,
  37. 'A#1': 58.27,
  38. 'Bb1': 58.27,
  39. 'B1': 61.74,
  40. 'C2': 65.41,
  41. 'C#2': 69.30,
  42. 'Db2': 69.30,
  43. 'D2': 73.42,
  44. 'D#2': 77.78,
  45. 'Eb2': 77.78,
  46. 'E2': 82.41,
  47. 'F2': 87.31,
  48. 'F#2': 92.50,
  49. 'Gb2': 92.50,
  50. 'G2': 98.00,
  51. 'G#2': 103.83,
  52. 'Ab2': 103.83,
  53. 'A2': 110.00,
  54. 'A#2': 116.54,
  55. 'Bb2': 116.54,
  56. 'B2': 123.47,
  57. 'C3': 130.81,
  58. 'C#3': 138.59,
  59. 'Db3': 138.59,
  60. 'D3': 146.83,
  61. 'D#3': 155.56,
  62. 'Eb3': 155.56,
  63. 'E3': 164.81,
  64. 'F3': 174.61,
  65. 'F#3': 185.00,
  66. 'Gb3': 185.00,
  67. 'G3': 196.00,
  68. 'G#3': 207.65,
  69. 'Ab3': 207.65,
  70. 'A3': 220.00,
  71. 'A#3': 233.08,
  72. 'Bb3': 233.08,
  73. 'B3': 246.94,
  74. 'C4': 261.63,
  75. 'C#4': 277.18,
  76. 'Db4': 277.18,
  77. 'D4': 293.66,
  78. 'D#4': 311.13,
  79. 'Eb4': 311.13,
  80. 'E4': 329.63,
  81. 'F4': 349.23,
  82. 'F#4': 369.99,
  83. 'Gb4': 369.99,
  84. 'G4': 392.00,
  85. 'G#4': 415.30,
  86. 'Ab4': 415.30,
  87. 'A4': 440.00,
  88. 'A#4': 466.16,
  89. 'Bb4': 466.16,
  90. 'B4': 493.88,
  91. 'C5': 523.25,
  92. 'C#5': 554.37,
  93. 'Db5': 554.37,
  94. 'D5': 587.33,
  95. 'D#5': 622.25,
  96. 'Eb5': 622.25,
  97. 'E5': 659.26,
  98. 'F5': 698.46,
  99. 'F#5': 739.99,
  100. 'Gb5': 739.99,
  101. 'G5': 783.99,
  102. 'G#5': 830.61,
  103. 'Ab5': 830.61,
  104. 'A5': 880.00,
  105. 'A#5': 932.33,
  106. 'Bb5': 932.33,
  107. 'B5': 987.77,
  108. 'C6': 1046.50,
  109. 'C#6': 1108.73,
  110. 'Db6': 1108.73,
  111. 'D6': 1174.66,
  112. 'D#6': 1244.51,
  113. 'Eb6': 1244.51,
  114. 'E6': 1318.51,
  115. 'F6': 1396.91,
  116. 'F#6': 1479.98,
  117. 'Gb6': 1479.98,
  118. 'G6': 1567.98,
  119. 'G#6': 1661.22,
  120. 'Ab6': 1661.22,
  121. 'A6': 1760.00,
  122. 'A#6': 1864.66,
  123. 'Bb6': 1864.66,
  124. 'B6': 1975.53,
  125. 'C7': 2093.00,
  126. 'C#7': 2217.46,
  127. 'Db7': 2217.46,
  128. 'D7': 2349.32,
  129. 'D#7': 2489.02,
  130. 'Eb7': 2489.02,
  131. 'E7': 2637.02,
  132. 'F7': 2793.83,
  133. 'F#7': 2959.96,
  134. 'Gb7': 2959.96,
  135. 'G7': 3135.96,
  136. 'G#7': 3322.44,
  137. 'Ab7': 3322.44,
  138. 'A7': 3520.00,
  139. 'A#7': 3729.31,
  140. 'Bb7': 3729.31,
  141. 'B7': 3951.07,
  142. 'C8': 4186.01
  143. }
  144. this.audioContext = new (window.AudioContext || window.webkitAudioContext)({
  145. latencyHint: "interactive",
  146. sampleRate: 48000
  147. });
  148. this.volume = 75;
  149. }
  150. playPing(note, start = 0, notelength = 0.5) {
  151. if (this.isMuted) {
  152. return;
  153. }
  154. let buffer = this.audioContext.createBuffer(2, this.audioContext.sampleRate * 3, this.audioContext.sampleRate);
  155. let oscillatorNode = this.audioContext.createOscillator();
  156. oscillatorNode.buffer = buffer;
  157. oscillatorNode.type = "sine";
  158. oscillatorNode.frequency.value = this.frequencyLookup[note];
  159. let gainNode = this.audioContext.createGain();
  160. gainNode.gain.setValueAtTime(this.volume / 100, this.audioContext.currentTime + start);
  161. oscillatorNode.connect(gainNode);
  162. gainNode.connect(this.audioContext.destination);
  163. oscillatorNode.start(this.audioContext.currentTime + start);
  164. gainNode.gain.exponentialRampToValueAtTime(0.00001, this.audioContext.currentTime + start + notelength);
  165. oscillatorNode.stop(this.audioContext.currentTime + start + notelength);
  166. }
  167. playPingSequence(sequence, between, notelength = 0.5) {
  168. let delay = 0;
  169. for (let i = 0; i < sequence.length; i++) {
  170. this.playPing(sequence[i], delay, notelength);
  171. delay += (between / 1000);
  172. }
  173. }
  174. }