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; | ||
|  | 		} | ||
|  | 	} | ||
|  | } |