a munch adventure
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 

199 行
3.9 KiB

  1. let playing = [];
  2. let looping = {};
  3. const audioBaseUrl = "https://chemicalcrux.org/satiate/media/audio/";
  4. let audioDict = {};
  5. // play some sound
  6. function playSfx(name) {
  7. if (audioDict[name] == undefined) {
  8. console.log(name + " is not loaded yet, dingus");
  9. return;
  10. }
  11. let src = audioContext.createBufferSource();
  12. src.buffer = audioDict[name];
  13. src.connect(audioContext.destination);
  14. playing.push(src);
  15. src.name = name;
  16. src.onended = (event) => src.done = true;
  17. src.start(0);
  18. }
  19. function playLoop(name) {
  20. if (audioDict[name] == undefined) {
  21. console.log(name + " is not loaded yet, dingus");
  22. return;
  23. }
  24. // if already playing, just keep going
  25. if (looping[name] && !looping[name].done) {
  26. console.log(name + " is already looping");
  27. return;
  28. }
  29. let src = audioContext.createBufferSource();
  30. src.buffer = audioDict[name];
  31. src.connect(audioContext.destination);
  32. looping[name] = src;
  33. src.name = name;
  34. src.onended = (event) => src.done = true;
  35. src.loop = true;
  36. src.start(0);
  37. }
  38. function stopSfx(name) {
  39. playing.map(item => {
  40. if (item.name == name)
  41. item.stop();
  42. } );
  43. cleanPlaying();
  44. }
  45. function stopLoop(name) {
  46. if (looping[name]) {
  47. looping[name].stop();
  48. delete looping[name];
  49. }
  50. }
  51. function cleanPlaying() {
  52. playing = playing.filter(item => !item.done);
  53. }
  54. // asynchronously load an audio file
  55. function loadAudio(name, flush=false) {
  56. // do we already have the audio?
  57. if (audioDict[name] && !flush) {
  58. return;
  59. }
  60. // is the audio already stored locally?
  61. if (!flush) {
  62. checkCache(
  63. "audio",
  64. name,
  65. (data) => parseAudioData(name, data),
  66. () => loadRemoteAudio(name)
  67. );
  68. } else {
  69. loadRemoteAudio(name);
  70. }
  71. }
  72. function cacheAndParse(name, data) {
  73. storeCache("audio", name, data.slice(0));
  74. parseAudioData(name, data);
  75. }
  76. function parseAudioData(name, data) {
  77. console.log(data);
  78. audioContext.decodeAudioData(data, function(buffer) {
  79. audioDict[name] = buffer;
  80. }, function(e){ console.log("Error with decoding audio data" + e.err);});
  81. }
  82. function loadRemoteAudio(name) {
  83. let xhr = new XMLHttpRequest();
  84. xhr.open("GET", audioBaseUrl + name, true);
  85. xhr.responseType = "arraybuffer";
  86. xhr.onload = (res) => {
  87. if (xhr.status == 200)
  88. cacheAndParse(name, xhr.response);
  89. else
  90. console.log("Couldn't load " + name);
  91. }
  92. xhr.onerror = (xhr) => console.log("Couldn't load " + name);
  93. xhr.send();
  94. }
  95. // check if the content is cached
  96. function checkCache(type, name, hit, miss) {
  97. const req = window.indexedDB.open("cache", 1);
  98. req.onsuccess = () => {
  99. const db = req.result;
  100. const tx = db.transaction([type], "readonly");
  101. const audio = tx.objectStore(type);
  102. const read = audio.get(name);
  103. read.onsuccess = (event) => {
  104. const res = event.target.result;
  105. if (res) {
  106. console.log("cache hit on " + name);
  107. hit(res.content);
  108. } else {
  109. console.log("cache miss on " + name);
  110. miss();
  111. }
  112. }
  113. tx.oncomplete = () => {
  114. db.close();
  115. }
  116. }
  117. }
  118. function initAudio() {
  119. audioContext = new (window.AudioContext || window.webkitAudioContext)();
  120. console.log("Initialized audio context");
  121. console.log(audioContext);
  122. }
  123. // caching stuff here
  124. function storeCache(type, name, blob) {
  125. const req = window.indexedDB.open("cache", 1);
  126. req.onsuccess = () => {
  127. const db = req.result;
  128. const tx = db.transaction([type], "readwrite");
  129. const audio = tx.objectStore(type);
  130. const update = audio.put({
  131. name: name,
  132. content: blob
  133. });
  134. tx.oncomplete = () => {
  135. db.close();
  136. }
  137. }
  138. }
  139. // if the indexedDB table doesn't exist at all, make it
  140. function createCache() {
  141. let idb = window.indexedDB;
  142. let req = idb.open("cache", 1);
  143. req.onupgradeneeded = event => {
  144. const db = event.target.result;
  145. const audio = db.createObjectStore("audio", { keyPath: "name" });
  146. }
  147. req.onerror = event => {
  148. alert("Couldn't open the database?");
  149. }
  150. }