forked from LeenkxTeam/LNXSDK
		
	
		
			
	
	
		
			138 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
		
		
			
		
	
	
			138 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
| 
								 | 
							
								package kha.audio2;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import kha.arrays.Float32Array;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class ResamplingAudioChannel extends AudioChannel {
							 | 
						||
| 
								 | 
							
									public var sampleRate: Int;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public function new(looping: Bool, sampleRate: Int) {
							 | 
						||
| 
								 | 
							
										super(looping);
							 | 
						||
| 
								 | 
							
										this.sampleRate = sampleRate;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public override function nextSamples(requestedSamples: Float32Array, requestedLength: Int, sampleRate: Int): Void {
							 | 
						||
| 
								 | 
							
										if (paused || stopped) {
							 | 
						||
| 
								 | 
							
											for (i in 0...requestedLength) {
							 | 
						||
| 
								 | 
							
												requestedSamples[i] = 0;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											return;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										var requestedSamplesIndex = 0;
							 | 
						||
| 
								 | 
							
										while (requestedSamplesIndex < requestedLength) {
							 | 
						||
| 
								 | 
							
											for (i in 0...min(sampleLength(sampleRate) - myPosition, requestedLength - requestedSamplesIndex)) {
							 | 
						||
| 
								 | 
							
												requestedSamples[requestedSamplesIndex++] = sample(myPosition++, sampleRate);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if (myPosition >= sampleLength(sampleRate)) {
							 | 
						||
| 
								 | 
							
												myPosition = 0;
							 | 
						||
| 
								 | 
							
												if (!looping) {
							 | 
						||
| 
								 | 
							
													stopped = true;
							 | 
						||
| 
								 | 
							
													break;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										while (requestedSamplesIndex < requestedLength) {
							 | 
						||
| 
								 | 
							
											requestedSamples[requestedSamplesIndex++] = 0;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									inline function sample(position: Int, sampleRate: Int): Float {
							 | 
						||
| 
								 | 
							
										var even = position % 2 == 0;
							 | 
						||
| 
								 | 
							
										var factor = this.sampleRate / sampleRate;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (even) {
							 | 
						||
| 
								 | 
							
											position = Std.int(position / 2);
							 | 
						||
| 
								 | 
							
											var pos = factor * position;
							 | 
						||
| 
								 | 
							
											var pos1 = Math.floor(pos);
							 | 
						||
| 
								 | 
							
											var pos2 = Math.floor(pos + 1);
							 | 
						||
| 
								 | 
							
											pos1 *= 2;
							 | 
						||
| 
								 | 
							
											pos2 *= 2;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											var minimum = 0;
							 | 
						||
| 
								 | 
							
											var maximum = data.length - 1;
							 | 
						||
| 
								 | 
							
											maximum = maximum % 2 == 0 ? maximum : maximum - 1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											var a = (pos1 < minimum || pos1 > maximum) ? 0 : data[pos1];
							 | 
						||
| 
								 | 
							
											var b = (pos2 < minimum || pos2 > maximum) ? 0 : data[pos2];
							 | 
						||
| 
								 | 
							
											return lerp(a, b, pos - Math.floor(pos));
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										else {
							 | 
						||
| 
								 | 
							
											position = Std.int(position / 2);
							 | 
						||
| 
								 | 
							
											var pos = factor * position;
							 | 
						||
| 
								 | 
							
											var pos1 = Math.floor(pos);
							 | 
						||
| 
								 | 
							
											var pos2 = Math.floor(pos + 1);
							 | 
						||
| 
								 | 
							
											pos1 = pos1 * 2 + 1;
							 | 
						||
| 
								 | 
							
											pos2 = pos2 * 2 + 1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											var minimum = 1;
							 | 
						||
| 
								 | 
							
											var maximum = data.length - 1;
							 | 
						||
| 
								 | 
							
											maximum = maximum % 2 != 0 ? maximum : maximum - 1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											var a = (pos1 < minimum || pos1 > maximum) ? 0 : data[pos1];
							 | 
						||
| 
								 | 
							
											var b = (pos2 < minimum || pos2 > maximum) ? 0 : data[pos2];
							 | 
						||
| 
								 | 
							
											return lerp(a, b, pos - Math.floor(pos));
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									inline function lerp(v0: Float, v1: Float, t: Float) {
							 | 
						||
| 
								 | 
							
										return (1 - t) * v0 + t * v1;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									inline function sampleLength(sampleRate: Int): Int {
							 | 
						||
| 
								 | 
							
										var value = Math.ceil(data.length * (sampleRate / this.sampleRate));
							 | 
						||
| 
								 | 
							
										return value % 2 == 0 ? value : value + 1;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public override function play(): Void {
							 | 
						||
| 
								 | 
							
										paused = false;
							 | 
						||
| 
								 | 
							
										stopped = false;
							 | 
						||
| 
								 | 
							
										kha.audio1.Audio._playAgain(this);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public override function pause(): Void {
							 | 
						||
| 
								 | 
							
										paused = true;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public override function stop(): Void {
							 | 
						||
| 
								 | 
							
										myPosition = 0;
							 | 
						||
| 
								 | 
							
										stopped = true;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									override function get_length(): Float {
							 | 
						||
| 
								 | 
							
										return data.length / this.sampleRate / 2; // 44.1 khz in stereo
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									override function get_position(): Float {
							 | 
						||
| 
								 | 
							
										return myPosition / kha.audio2.Audio.samplesPerSecond / 2;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									override function set_position(value: Float): Float {
							 | 
						||
| 
								 | 
							
										var pos = Math.round(value * kha.audio2.Audio.samplesPerSecond * 2.0);
							 | 
						||
| 
								 | 
							
										pos = pos % 2 == 0 ? pos : pos + 1;
							 | 
						||
| 
								 | 
							
										myPosition = max(min(pos, sampleLength(kha.audio2.Audio.samplesPerSecond)), 0);
							 | 
						||
| 
								 | 
							
										return value;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									override function get_volume(): Float {
							 | 
						||
| 
								 | 
							
										return myVolume;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									override function set_volume(value: Float): Float {
							 | 
						||
| 
								 | 
							
										return myVolume = value;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									override function get_finished(): Bool {
							 | 
						||
| 
								 | 
							
										return stopped;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									static inline function max(a: Int, b: Int) {
							 | 
						||
| 
								 | 
							
										return a > b ? a : b;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									static inline function min(a: Int, b: Int) {
							 | 
						||
| 
								 | 
							
										return a < b ? a : b;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 |