babylon.audioEngine.ts 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. module BABYLON {
  2. export class AudioEngine {
  3. private _audioContext: AudioContext = null;
  4. private _audioContextInitialized = false;
  5. public canUseWebAudio: boolean = false;
  6. public masterGain: GainNode;
  7. private _connectedAnalyser: Analyser;
  8. public WarnedWebAudioUnsupported: boolean = false;
  9. public unlocked: boolean = false;
  10. public onAudioUnlocked: () => any;
  11. public isMP3supported: boolean = false;
  12. public isOGGsupported: boolean = false;
  13. public get audioContext(): AudioContext {
  14. if (!this._audioContextInitialized) {
  15. this._initializeAudioContext();
  16. }
  17. return this._audioContext;
  18. }
  19. constructor() {
  20. if (typeof window.AudioContext !== 'undefined' || typeof window.webkitAudioContext !== 'undefined') {
  21. window.AudioContext = window.AudioContext || window.webkitAudioContext;
  22. this.canUseWebAudio = true;
  23. }
  24. var audioElem = document.createElement('audio');
  25. if (audioElem && !!audioElem.canPlayType && audioElem.canPlayType('audio/mpeg; codecs="mp3"').replace(/^no$/, '')) {
  26. this.isMP3supported = true;
  27. }
  28. if (audioElem && !!audioElem.canPlayType && audioElem.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/, '')) {
  29. this.isOGGsupported = true;
  30. }
  31. if (/iPad|iPhone|iPod/.test(navigator.platform)) {
  32. this._unlockiOSaudio();
  33. }
  34. else {
  35. this.unlocked = true;
  36. }
  37. }
  38. private _unlockiOSaudio() {
  39. var unlockaudio = () => {
  40. var buffer = this.audioContext.createBuffer(1, 1, 22050);
  41. var source = this.audioContext.createBufferSource();
  42. source.buffer = buffer;
  43. source.connect(this.audioContext.destination);
  44. source.start(0);
  45. setTimeout(() => {
  46. if (((<any>source).playbackState === (<any>source).PLAYING_STATE || (<any>source).playbackState === (<any>source).FINISHED_STATE)) {
  47. this.unlocked = true;
  48. window.removeEventListener('touchend', unlockaudio, false);
  49. if (this.onAudioUnlocked) {
  50. this.onAudioUnlocked();
  51. }
  52. }
  53. }, 0);
  54. };
  55. window.addEventListener('touchend', unlockaudio, false);
  56. }
  57. private _initializeAudioContext() {
  58. try {
  59. if (this.canUseWebAudio) {
  60. this._audioContext = new AudioContext();
  61. // create a global volume gain node
  62. this.masterGain = this._audioContext.createGain();
  63. this.masterGain.gain.value = 1;
  64. this.masterGain.connect(this._audioContext.destination);
  65. this._audioContextInitialized = true;
  66. }
  67. }
  68. catch (e) {
  69. this.canUseWebAudio = false;
  70. Tools.Error("Web Audio: " + e.message);
  71. }
  72. }
  73. public dispose() {
  74. if (this.canUseWebAudio && this._audioContextInitialized) {
  75. if (this._connectedAnalyser) {
  76. this._connectedAnalyser.stopDebugCanvas();
  77. this._connectedAnalyser.dispose();
  78. this.masterGain.disconnect();
  79. this.masterGain.connect(this._audioContext.destination);
  80. this._connectedAnalyser = null;
  81. }
  82. this.masterGain.gain.value = 1;
  83. }
  84. this.WarnedWebAudioUnsupported = false;
  85. }
  86. public getGlobalVolume(): number {
  87. if (this.canUseWebAudio && this._audioContextInitialized) {
  88. return this.masterGain.gain.value;
  89. }
  90. else {
  91. return -1;
  92. }
  93. }
  94. public setGlobalVolume(newVolume: number) {
  95. if (this.canUseWebAudio && this._audioContextInitialized) {
  96. this.masterGain.gain.value = newVolume;
  97. }
  98. }
  99. public connectToAnalyser(analyser: Analyser) {
  100. if (this._connectedAnalyser) {
  101. this._connectedAnalyser.stopDebugCanvas();
  102. }
  103. if (this.canUseWebAudio && this._audioContextInitialized) {
  104. this._connectedAnalyser = analyser;
  105. this.masterGain.disconnect();
  106. this._connectedAnalyser.connectAudioNodes(this.masterGain, this._audioContext.destination);
  107. }
  108. }
  109. }
  110. }