108 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
		
		
			
		
	
	
			108 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
| 
								 | 
							
								package kha.audio2;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import js.Syntax;
							 | 
						||
| 
								 | 
							
								import js.Browser;
							 | 
						||
| 
								 | 
							
								import js.html.URL;
							 | 
						||
| 
								 | 
							
								import js.html.audio.AudioContext;
							 | 
						||
| 
								 | 
							
								import js.html.audio.AudioProcessingEvent;
							 | 
						||
| 
								 | 
							
								import js.html.audio.ScriptProcessorNode;
							 | 
						||
| 
								 | 
							
								import kha.internal.IntBox;
							 | 
						||
| 
								 | 
							
								import kha.js.AEAudioChannel;
							 | 
						||
| 
								 | 
							
								import kha.Sound;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class Audio {
							 | 
						||
| 
								 | 
							
									public static var disableGcInteractions = false;
							 | 
						||
| 
								 | 
							
									static var intBox: IntBox = new IntBox(0);
							 | 
						||
| 
								 | 
							
									static var buffer: Buffer;
							 | 
						||
| 
								 | 
							
									@:noCompletion public static var _context: AudioContext;
							 | 
						||
| 
								 | 
							
									static var processingNode: ScriptProcessorNode;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									static function initContext(): Void {
							 | 
						||
| 
								 | 
							
										try {
							 | 
						||
| 
								 | 
							
											_context = new AudioContext();
							 | 
						||
| 
								 | 
							
											return;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										catch (e:Dynamic) {}
							 | 
						||
| 
								 | 
							
										try {
							 | 
						||
| 
								 | 
							
											Syntax.code("this._context = new webkitAudioContext();");
							 | 
						||
| 
								 | 
							
											return;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										catch (e:Dynamic) {}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									@:noCompletion
							 | 
						||
| 
								 | 
							
									public static function _init(): Bool {
							 | 
						||
| 
								 | 
							
										initContext();
							 | 
						||
| 
								 | 
							
										if (_context == null)
							 | 
						||
| 
								 | 
							
											return false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										Audio.samplesPerSecond = Math.round(_context.sampleRate);
							 | 
						||
| 
								 | 
							
										var bufferSize = 1024 * 2;
							 | 
						||
| 
								 | 
							
										buffer = new Buffer(bufferSize * 4, 2, Std.int(_context.sampleRate));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										processingNode = _context.createScriptProcessor(bufferSize, 0, 2);
							 | 
						||
| 
								 | 
							
										processingNode.onaudioprocess = function(e: AudioProcessingEvent) {
							 | 
						||
| 
								 | 
							
											var output1 = e.outputBuffer.getChannelData(0);
							 | 
						||
| 
								 | 
							
											var output2 = e.outputBuffer.getChannelData(1);
							 | 
						||
| 
								 | 
							
											if (audioCallback != null) {
							 | 
						||
| 
								 | 
							
												intBox.value = e.outputBuffer.length * 2;
							 | 
						||
| 
								 | 
							
												audioCallback(intBox, buffer);
							 | 
						||
| 
								 | 
							
												for (i in 0...e.outputBuffer.length) {
							 | 
						||
| 
								 | 
							
													output1[i] = buffer.data.get(buffer.readLocation);
							 | 
						||
| 
								 | 
							
													buffer.readLocation += 1;
							 | 
						||
| 
								 | 
							
													output2[i] = buffer.data.get(buffer.readLocation);
							 | 
						||
| 
								 | 
							
													buffer.readLocation += 1;
							 | 
						||
| 
								 | 
							
													if (buffer.readLocation >= buffer.size) {
							 | 
						||
| 
								 | 
							
														buffer.readLocation = 0;
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											else {
							 | 
						||
| 
								 | 
							
												for (i in 0...e.outputBuffer.length) {
							 | 
						||
| 
								 | 
							
													output1[i] = 0;
							 | 
						||
| 
								 | 
							
													output2[i] = 0;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										processingNode.connect(_context.destination);
							 | 
						||
| 
								 | 
							
										return true;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public static var samplesPerSecond: Int;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public static var audioCallback: kha.internal.IntBox->Buffer->Void;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									static var virtualChannels: Array<VirtualStreamChannel> = [];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public static function wakeChannels() {
							 | 
						||
| 
								 | 
							
										SystemImpl.mobileAudioPlaying = true;
							 | 
						||
| 
								 | 
							
										for (channel in virtualChannels) {
							 | 
						||
| 
								 | 
							
											channel.wake();
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public static function stream(sound: Sound, loop: Bool = false): kha.audio1.AudioChannel {
							 | 
						||
| 
								 | 
							
										// var source = _context.createMediaStreamSource(cast sound.compressedData.getData());
							 | 
						||
| 
								 | 
							
										// source.connect(_context.destination);
							 | 
						||
| 
								 | 
							
										var element = Browser.document.createAudioElement();
							 | 
						||
| 
								 | 
							
										#if kha_debug_html5
							 | 
						||
| 
								 | 
							
										var blob = new js.html.Blob([sound.compressedData.getData()], {type: "audio/ogg"});
							 | 
						||
| 
								 | 
							
										#else
							 | 
						||
| 
								 | 
							
										var blob = new js.html.Blob([sound.compressedData.getData()], {type: "audio/mp4"});
							 | 
						||
| 
								 | 
							
										#end
							 | 
						||
| 
								 | 
							
										element.src = URL.createObjectURL(blob);
							 | 
						||
| 
								 | 
							
										element.loop = loop;
							 | 
						||
| 
								 | 
							
										var channel = new AEAudioChannel(element, loop);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (SystemImpl.mobileAudioPlaying) {
							 | 
						||
| 
								 | 
							
											channel.play();
							 | 
						||
| 
								 | 
							
											return channel;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										else {
							 | 
						||
| 
								 | 
							
											var virtualChannel = new VirtualStreamChannel(channel, loop);
							 | 
						||
| 
								 | 
							
											virtualChannels.push(virtualChannel);
							 | 
						||
| 
								 | 
							
											return virtualChannel;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 |