Audio.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. /**
  2. * @author mrdoob / http://mrdoob.com/
  3. * @author Reece Aaron Lecrivain / http://reecenotes.com/
  4. */
  5. import { Object3D } from '../core/Object3D.js';
  6. function Audio( listener ) {
  7. Object3D.call( this );
  8. this.type = 'Audio';
  9. this.context = listener.context;
  10. this.gain = this.context.createGain();
  11. this.gain.connect( listener.getInput() );
  12. this.autoplay = false;
  13. this.buffer = null;
  14. this.loop = false;
  15. this.startTime = 0;
  16. this.offset = 0;
  17. this.playbackRate = 1;
  18. this.isPlaying = false;
  19. this.hasPlaybackControl = true;
  20. this.sourceType = 'empty';
  21. this.filters = [];
  22. }
  23. Audio.prototype = Object.assign( Object.create( Object3D.prototype ), {
  24. constructor: Audio,
  25. getOutput: function () {
  26. return this.gain;
  27. },
  28. setNodeSource: function ( audioNode ) {
  29. this.hasPlaybackControl = false;
  30. this.sourceType = 'audioNode';
  31. this.source = audioNode;
  32. this.connect();
  33. return this;
  34. },
  35. setBuffer: function ( audioBuffer ) {
  36. this.buffer = audioBuffer;
  37. this.sourceType = 'buffer';
  38. if ( this.autoplay ) this.play();
  39. return this;
  40. },
  41. play: function () {
  42. if ( this.isPlaying === true ) {
  43. console.warn( 'THREE.Audio: Audio is already playing.' );
  44. return;
  45. }
  46. if ( this.hasPlaybackControl === false ) {
  47. console.warn( 'THREE.Audio: this Audio has no playback control.' );
  48. return;
  49. }
  50. var source = this.context.createBufferSource();
  51. source.buffer = this.buffer;
  52. source.loop = this.loop;
  53. source.onended = this.onEnded.bind( this );
  54. source.playbackRate.setValueAtTime( this.playbackRate, this.startTime );
  55. this.startTime = this.context.currentTime;
  56. source.start( this.startTime, this.offset );
  57. this.isPlaying = true;
  58. this.source = source;
  59. return this.connect();
  60. },
  61. pause: function () {
  62. if ( this.hasPlaybackControl === false ) {
  63. console.warn( 'THREE.Audio: this Audio has no playback control.' );
  64. return;
  65. }
  66. if ( this.isPlaying === true ) {
  67. this.source.stop();
  68. this.offset += ( this.context.currentTime - this.startTime ) * this.playbackRate;
  69. this.isPlaying = false;
  70. }
  71. return this;
  72. },
  73. stop: function () {
  74. if ( this.hasPlaybackControl === false ) {
  75. console.warn( 'THREE.Audio: this Audio has no playback control.' );
  76. return;
  77. }
  78. this.source.stop();
  79. this.offset = 0;
  80. this.isPlaying = false;
  81. return this;
  82. },
  83. connect: function () {
  84. if ( this.filters.length > 0 ) {
  85. this.source.connect( this.filters[ 0 ] );
  86. for ( var i = 1, l = this.filters.length; i < l; i ++ ) {
  87. this.filters[ i - 1 ].connect( this.filters[ i ] );
  88. }
  89. this.filters[ this.filters.length - 1 ].connect( this.getOutput() );
  90. } else {
  91. this.source.connect( this.getOutput() );
  92. }
  93. return this;
  94. },
  95. disconnect: function () {
  96. if ( this.filters.length > 0 ) {
  97. this.source.disconnect( this.filters[ 0 ] );
  98. for ( var i = 1, l = this.filters.length; i < l; i ++ ) {
  99. this.filters[ i - 1 ].disconnect( this.filters[ i ] );
  100. }
  101. this.filters[ this.filters.length - 1 ].disconnect( this.getOutput() );
  102. } else {
  103. this.source.disconnect( this.getOutput() );
  104. }
  105. return this;
  106. },
  107. getFilters: function () {
  108. return this.filters;
  109. },
  110. setFilters: function ( value ) {
  111. if ( ! value ) value = [];
  112. if ( this.isPlaying === true ) {
  113. this.disconnect();
  114. this.filters = value;
  115. this.connect();
  116. } else {
  117. this.filters = value;
  118. }
  119. return this;
  120. },
  121. getFilter: function () {
  122. return this.getFilters()[ 0 ];
  123. },
  124. setFilter: function ( filter ) {
  125. return this.setFilters( filter ? [ filter ] : [] );
  126. },
  127. setPlaybackRate: function ( value ) {
  128. if ( this.hasPlaybackControl === false ) {
  129. console.warn( 'THREE.Audio: this Audio has no playback control.' );
  130. return;
  131. }
  132. this.playbackRate = value;
  133. if ( this.isPlaying === true ) {
  134. this.source.playbackRate.setValueAtTime( this.playbackRate, this.context.currentTime );
  135. }
  136. return this;
  137. },
  138. getPlaybackRate: function () {
  139. return this.playbackRate;
  140. },
  141. onEnded: function () {
  142. this.isPlaying = false;
  143. },
  144. getLoop: function () {
  145. if ( this.hasPlaybackControl === false ) {
  146. console.warn( 'THREE.Audio: this Audio has no playback control.' );
  147. return false;
  148. }
  149. return this.loop;
  150. },
  151. setLoop: function ( value ) {
  152. if ( this.hasPlaybackControl === false ) {
  153. console.warn( 'THREE.Audio: this Audio has no playback control.' );
  154. return;
  155. }
  156. this.loop = value;
  157. if ( this.isPlaying === true ) {
  158. this.source.loop = this.loop;
  159. }
  160. return this;
  161. },
  162. getVolume: function () {
  163. return this.gain.gain.value;
  164. },
  165. setVolume: function ( value ) {
  166. this.gain.gain.value = value;
  167. return this;
  168. }
  169. } );
  170. export { Audio };