فهرست منبع

added native ogg/vorbis support for HL

Nicolas Cannasse 8 سال پیش
والد
کامیت
0c57a91451
2فایلهای تغییر یافته به همراه88 افزوده شده و 3 حذف شده
  1. 2 2
      hxd/res/Sound.hx
  2. 86 1
      hxd/snd/OggData.hx

+ 2 - 2
hxd/res/Sound.hx

@@ -23,7 +23,7 @@ class Sound extends Resource {
 			return false;
 			return false;
 			#end
 			#end
 		case OggVorbis:
 		case OggVorbis:
-			#if stb_ogg_sound
+			#if (hl || stb_ogg_sound)
 			return true;
 			return true;
 			#else
 			#else
 			return false;
 			return false;
@@ -47,7 +47,7 @@ class Sound extends Resource {
 		case 255, 'I'.code: // MP3 (or ID3)
 		case 255, 'I'.code: // MP3 (or ID3)
 			data = new hxd.snd.Mp3Data(bytes);
 			data = new hxd.snd.Mp3Data(bytes);
 		case 'O'.code: // Ogg (vorbis)
 		case 'O'.code: // Ogg (vorbis)
-			#if stb_ogg_sound
+			#if (hl || stb_ogg_sound)
 			data = new hxd.snd.OggData(bytes);
 			data = new hxd.snd.OggData(bytes);
 			#else
 			#else
 			throw "OGG format requires -lib stb_ogg_sound (for " + entry.path+")";
 			throw "OGG format requires -lib stb_ogg_sound (for " + entry.path+")";

+ 86 - 1
hxd/snd/OggData.hx

@@ -1,5 +1,88 @@
 package hxd.snd;
 package hxd.snd;
 
 
+#if hl
+
+private typedef OggFile = hl.Abstract<"fmt_ogg">;
+
+class OggData extends Data {
+
+	var bytes : haxe.io.Bytes;
+	var reader : OggFile;
+	var currentSample : Int;
+
+	public function new( bytes : haxe.io.Bytes ) {
+		this.bytes = bytes;
+		reader = ogg_open(bytes, bytes.length);
+		if( reader == null ) throw "Failed to decode OGG data";
+
+		var b = 0, f = 0, s = 0, c = 0;
+		ogg_info(reader, b, f, s, c);
+		channels = c;
+		samples = s;
+		sampleFormat = I16;
+		samplingRate = f;
+	}
+
+	override function resample(rate:Int, format:Data.SampleFormat, channels:Int):Data  {
+		switch( format ) {
+		case UI8, I16 if( channels == this.channels && rate == this.samplingRate ):
+			var g = new OggData(bytes);
+			g.sampleFormat = format;
+			return g;
+		default:
+			return super.resample(rate, format, channels);
+		}
+	}
+
+	override function decodeBuffer(out:haxe.io.Bytes, outPos:Int, sampleStart:Int, sampleCount:Int) {
+		if( currentSample != sampleStart ) {
+			currentSample = sampleStart;
+			if( !ogg_seek(reader, sampleStart) ) throw "Invalid sample start";
+		}
+		var bpp = getBytesPerSample();
+		var output : hl.Bytes = out;
+		output = output.offset(outPos);
+		var format = switch( sampleFormat ) {
+		case UI8: 1 | 256;
+		case I16: 2;
+		default:
+			throw "assert";
+		}
+		var bytesNeeded = sampleCount * bpp;
+		while( bytesNeeded > 0 ) {
+			var read = ogg_read(reader, output, bytesNeeded, format);
+			if( read < 0 ) throw "Failed to decode OGG data";
+			if( read == 0 ) {
+				// EOF
+				output.fill(0,bytesNeeded, sampleFormat == UI8 ? 0x80 : 0);
+				break;
+			}
+			bytesNeeded -= read;
+			output = output.offset(read);
+		}
+		currentSample += sampleCount;
+	}
+
+	@:hlNative("fmt", "ogg_open") static function ogg_open( bytes : hl.Bytes, size : Int ) : OggFile {
+		return null;
+	}
+
+	@:hlNative("fmt", "ogg_seek") static function ogg_seek( o : OggFile, sample : Int ) : Bool {
+		return false;
+	}
+
+	@:hlNative("fmt", "ogg_info") static function ogg_info( o : OggFile, bitrate : hl.Ref<Int>, freq : hl.Ref<Int>, samples : hl.Ref<Int>, channels : hl.Ref<Int> ) : Void {
+	}
+
+	@:hlNative("fmt", "ogg_read") static function ogg_read( o : OggFile, output : hl.Bytes, size : Int, format : Int ) : Int {
+		return 0;
+	}
+
+}
+
+
+#else
+
 private class BytesOutput extends haxe.io.Output {
 private class BytesOutput extends haxe.io.Output {
 
 
 	var bytes : haxe.io.Bytes;
 	var bytes : haxe.io.Bytes;
@@ -117,4 +200,6 @@ class OggData extends Data {
 	}
 	}
 
 
 
 
-}
+}
+
+#end