2
0
Эх сурвалжийг харах

factorized sound convert, enable ogg convert, fixed bug when converting sound

Nicolas Cannasse 10 жил өмнө
parent
commit
f1bce36e3f

+ 6 - 4
hxd/fmt/pak/Build.hx

@@ -22,7 +22,7 @@ class Build {
 			case "fbx":
 				dir = getTemp(dir,path,"hmd");
 			case "wav":
-				dir = getTemp(dir,path,"mp3");
+				dir = getTemp(dir,path,#if stb_ogg_sound "ogg" #else "mp3" #end);
 			default:
 			}
 			var data = sys.io.File.getBytes(dir);
@@ -40,10 +40,12 @@ class Build {
 		var name = "R_" + invalidChars.replace(path, "_");
 		var f = dir.substr(0, dir.length - path.length)+".tmp/"+name+"."+ext;
 		if( !sys.FileSystem.exists(f) ) {
-			if( ext == "mp3" )
-				Sys.command("lame",["--resample","44100","--silent","-h",dir,f]);
-			else
+			switch( ext ) {
+			case "mp3":
+				hxd.snd.Convert.toMP3(dir, f);
+			default:
 				throw 'Missing \'$f\' required by \'$dir\'';
+			}
 		}
 		return f;
 	}

+ 32 - 22
hxd/fs/LocalFileSystem.hx

@@ -11,6 +11,7 @@ private class LocalEntry extends FileEntry {
 	#if air3
 	var file : flash.filesystem.File;
 	var fread : flash.filesystem.FileStream;
+	var checkExists : Bool;
 	#else
 	var file : String;
 	var fread : sys.io.FileInput;
@@ -25,6 +26,8 @@ private class LocalEntry extends FileEntry {
 			convertToHMD();
 		if( fs.createMP3 && extension == "wav" )
 			convertToMP3();
+		if( fs.createOGG && extension == "wav" )
+			convertToOGG();
 	}
 
 	static var INVALID_CHARS = ~/[^A-Za-z0-9_]/g;
@@ -50,8 +53,8 @@ private class LocalEntry extends FileEntry {
 			out.open(target, flash.filesystem.FileMode.WRITE);
 			out.writeBytes(hmd.getData());
 			out.close();
+			checkExists = true;
 		}
-		file = target;
 		#else
 		var ttime = try sys.FileSystem.stat(target) catch( e : Dynamic ) null;
 		if( ttime == null || ttime.mtime.getTime() < sys.FileSystem.stat(file).mtime.getTime() ) {
@@ -59,6 +62,7 @@ private class LocalEntry extends FileEntry {
 			sys.io.File.saveBytes(target, hmd);
 		}
 		#end
+		file = target;
 	}
 
 	function convertToMP3() {
@@ -66,28 +70,31 @@ private class LocalEntry extends FileEntry {
 		#if air3
 		var target = new flash.filesystem.File(target);
 		if( !target.exists || target.modificationDate.getTime() < file.modificationDate.getTime() ) {
-			var p = new flash.desktop.NativeProcess();
-			var i = new flash.desktop.NativeProcessStartupInfo();
-			i.arguments = flash.Vector.ofArray(["--resample", "44100", "-h",file.nativePath,target.nativePath]);
-			var f = flash.filesystem.File.applicationDirectory.resolvePath("lame.exe");
-			if( !f.exists ) {
-				f = new flash.filesystem.File("d:/projects/shiroTools/tools/lame.exe");
-				if( !f.exists ) throw "lame.exe not found : cannot convert wav to mp3";
-			}
-			i.executable = f;
-			i.workingDirectory = f.parent;
-			p.addEventListener("exit", function(e:Dynamic) {
-				var code : Int = Reflect.field(e, "exitCode");
-				if( code == 0 )
-					file = target;
-			});
-			p.addEventListener(flash.events.IOErrorEvent.IO_ERROR, function(e) {
-				trace(e);
-			});
-			p.start(i);
-		} else
-			file = target;
+			hxd.snd.Convert.toMP3(file.nativePath, target.nativePath);
+			checkExists = true;
+		}
+		#else
+		var ttime = try sys.FileSystem.stat(target) catch( e : Dynamic ) null;
+		if( ttime == null || ttime.mtime.getTime() < sys.FileSystem.stat(file).mtime.getTime() )
+			hxd.snd.Convert.toMP3(file, target);
 		#end
+		file = target;
+	}
+
+	function convertToOGG() {
+		var target = fs.tmpDir + "R_" + INVALID_CHARS.replace(relPath,"_") + ".ogg";
+		#if air3
+		var target = new flash.filesystem.File(target);
+		if( !target.exists || target.modificationDate.getTime() < file.modificationDate.getTime() ) {
+			hxd.snd.Convert.toOGG(file.nativePath, target.nativePath);
+			checkExists = true;
+		}
+		#else
+		var ttime = try sys.FileSystem.stat(target) catch( e : Dynamic ) null;
+		if( ttime == null || ttime.mtime.getTime() < sys.FileSystem.stat(file).mtime.getTime() )
+			hxd.snd.Convert.toOGG(file, target);
+		#end
+		file = target;
 	}
 
 	override function getSign() : Int {
@@ -109,6 +116,8 @@ private class LocalEntry extends FileEntry {
 
 	override function getBytes() : haxe.io.Bytes {
 		#if air3
+		if( checkExists && !file.exists )
+			return haxe.io.Bytes.alloc(0);
 		var fs = new flash.filesystem.FileStream();
 		fs.open(file, flash.filesystem.FileMode.READ);
 		var bytes = haxe.io.Bytes.alloc(fs.bytesAvailable);
@@ -320,6 +329,7 @@ class LocalFileSystem implements FileSystem {
 	public var baseDir(default,null) : String;
 	var createHMD : Bool = true;
 	public var createMP3 : Bool;
+	public var createOGG : Bool;
 	public var tmpDir : String;
 
 	public function new( dir : String ) {

+ 1 - 0
hxd/res/EmbedOptions.hx

@@ -2,6 +2,7 @@ package hxd.res;
 
 typedef EmbedOptions = {
 	?compressSounds : Bool,
+	?compressAsMp3 : Bool,
 	?tmpDir : String,
 	?fontsChars : String,
 }

+ 25 - 7
hxd/res/FileTree.hx

@@ -55,6 +55,8 @@ class FileTree {
 		if( options == null ) options = { };
 		var needTmp = options.compressSounds;
 		if( options.tmpDir == null ) options.tmpDir = path + "/.tmp/";
+		// if the OGG library is detected, compress as OGG by default, unless compressAsMp3 is set
+		if( options.compressAsMp3 == null ) options.compressAsMp3 = options.compressSounds && !Context.defined("stb_ogg_sound");
 		if( needTmp && !sys.FileSystem.exists(options.tmpDir) )
 			sys.FileSystem.createDirectory(options.tmpDir);
 		this.options = options;
@@ -105,16 +107,32 @@ class FileTree {
 
 		switch( ext.toLowerCase() ) {
 		case "wav" if( options.compressSounds ):
-			var tmp = options.tmpDir + name + ".mp3";
-			if( getTime(tmp) < getTime(fullPath) ) {
-				Sys.println("Converting " + relPath);
-				if( Sys.command("lame", ["--resample","44100","--silent","-h",fullPath,tmp]) != 0 )
-					Context.warning("Failed to run lame on " + path, pos);
-				else {
+			if( options.compressAsMp3 || !Context.defined("stb_ogg_sound") ) {
+				var tmp = options.tmpDir + name + ".mp3";
+				if( getTime(tmp) < getTime(fullPath) ) {
+					Sys.println("Converting " + relPath);
+					try {
+						hxd.snd.Convert.toMP3(fullPath, tmp);
+						fullPath = tmp;
+					} catch( e : Dynamic ) {
+						Context.warning(e, pos);
+					}
+				} else {
 					fullPath = tmp;
 				}
 			} else {
-				fullPath = tmp;
+				var tmp = options.tmpDir + name + ".ogg";
+				if( getTime(tmp) < getTime(fullPath) ) {
+					Sys.println("Converting " + relPath);
+					try {
+						hxd.snd.Convert.toOGG(fullPath, tmp);
+						fullPath = tmp;
+					} catch( e : Dynamic ) {
+						Context.warning(e, pos);
+					}
+				} else {
+					fullPath = tmp;
+				}
 			}
 			Context.registerModuleDependency(currentModule, fullPath);
 		case "fbx":

+ 6 - 0
hxd/res/Sound.hx

@@ -10,6 +10,12 @@ class Sound extends Resource {
 		if( data != null )
 			return data;
 		var bytes = entry.getBytes();
+
+		#if flash
+		if( bytes.length == 0 )
+			return new hxd.snd.LoadingData(this);
+		#end
+
 		switch( bytes.get(0) ) {
 		case 'R'.code: // RIFF (wav)
 			data = new hxd.snd.WavData(bytes);

+ 43 - 0
hxd/snd/Convert.hx

@@ -0,0 +1,43 @@
+package hxd.snd;
+
+
+class Convert {
+
+	static function command(name, args) {
+		#if (flash && air3)
+		var p = new flash.desktop.NativeProcess();
+		var i = new flash.desktop.NativeProcessStartupInfo();
+		i.arguments = flash.Vector.ofArray(args);
+		var f = flash.filesystem.File.applicationDirectory.resolvePath(name+".exe");
+		if( !f.exists ) {
+			// TODO : replace with a proper $PATH lookup
+			f = new flash.filesystem.File("d:/projects/shiroTools/tools/"+name+".exe");
+			if( !f.exists ) throw name+".exe not found : cannot convert wav";
+		}
+		i.executable = f;
+		i.workingDirectory = f.parent;
+		p.addEventListener("exit", function(e:Dynamic) {
+			var r : Int = Reflect.field(e, "exitCode");
+			if( r != 0 ) throw "Failed to run " + name+" " + args.join(" ") + " (Error " + r + ")";
+		});
+		p.addEventListener(flash.events.IOErrorEvent.IO_ERROR, function(e) {
+		});
+		p.start(i);
+		#elseif sys
+		var r = Sys.command(name, args);
+		if( r != 0 )
+			throw "Failed to run " + name+" " + args.join(" ") + " (Error " + r + ")";
+		#else
+		throw "Can't run command on this platform";
+		#end
+	}
+
+	public static function toMP3( srcFile : String, dstFile : String ) {
+		command("lame", ["--resample", "44100", "--silent", "-h", srcFile, dstFile]);
+	}
+
+	public static function toOGG( srcFile : String, dstFile : String ) {
+		command("oggenc2", ["--resample", "44100", "-Q", srcFile, "-o", dstFile]);
+	}
+
+}

+ 31 - 0
hxd/snd/LoadingData.hx

@@ -0,0 +1,31 @@
+package hxd.snd;
+
+class LoadingData extends Data {
+
+	var snd : hxd.res.Sound;
+	var waitCount = 0;
+
+	public function new(snd) {
+		this.snd = snd;
+	}
+
+	override public function decode(out:haxe.io.Bytes, outPos:Int, sampleStart:Int, sampleCount:Int):Void {
+		var d = snd.getData();
+		if( Std.is(d, LoadingData) )
+			throw "Sound data is not yet available, use load() first";
+		d.decode(out, outPos, sampleStart, sampleCount);
+	}
+
+	override public function load(onEnd:Void->Void) {
+		if( waitCount > 10 )
+			throw "Failed to load data";
+		var d = snd.getData();
+		if( Std.is(d, LoadingData) ) {
+			waitCount++;
+			haxe.Timer.delay(load.bind(onEnd), 100);
+			return;
+		}
+		d.load(onEnd);
+	}
+
+}

+ 10 - 6
samples/sound/Sound.hx

@@ -22,11 +22,15 @@ class Sound extends hxd.App {
 	override function init() {
 		//var c = new NoiseChannel();
 		//haxe.Timer.delay(c.stop, 1000);
-
-		#if !cpp
+/*
+		#if (cpp || stb_ogg_sound || true)
+		var c = hxd.Res.music_loop_ogg.play(true);
+		#else
 		var c = hxd.Res.music_loop.play(true);
-		c.onEnd = function() trace("LOOP");
 		#end
+		c.onEnd = function() trace("LOOP");*/
+
+		hxd.Res.haunted_intro_ogg.play().queueNext(hxd.Res.haunted_loop_ogg);
 	}
 
 	override function update(dt:Float) {
@@ -40,9 +44,9 @@ class Sound extends hxd.App {
 	}
 
 	static function main() {
-		hxd.Res.initEmbed();
-		if( hxd.res.Sound.startWorker() )
-			return;
+		hxd.Res.initEmbed({compressSounds:true});
+//		if( hxd.res.Sound.startWorker() )
+//			return;
 		new Sound();
 	}
 

+ 2 - 5
samples/sound/sound.hxml

@@ -1,13 +1,10 @@
 -js main.js
 -main Sound
 -lib heaps
+-lib stb_ogg_sound
 --next
 -swf main.swf
 -swf-version 11.8
 -main Sound
 -lib heaps
---next
--cpp bin
--main Sound
--lib heaps
--lib hxsdl
+-lib stb_ogg_sound

+ 1 - 1
samples/sound/sound.hxproj

@@ -24,7 +24,7 @@
     <option noInlineOnDebug="False" />
     <option mainClass="Sound" />
     <option enabledebug="False" />
-    <option additional="-lib heaps&#xA;&#xA;--next&#xA;-swf main.swf&#xA;-swf-version 11.8&#xA;-main Sound&#xA;-lib heaps&#xA;&#xA;--next&#xA;-cpp bin&#xA;-main Sound&#xA;-lib heaps&#xA;-lib hxsdl" />
+    <option additional="-lib heaps&#xA;-lib stb_ogg_sound&#xA;&#xA;--next&#xA;-swf main.swf&#xA;-swf-version 11.8&#xA;-main Sound&#xA;-lib heaps&#xA;-lib stb_ogg_sound&#xA;&#xA;#--next&#xA;#-cpp bin&#xA;#-main Sound&#xA;#-lib heaps&#xA;#-lib hxsdl" />
   </build>
   <!-- haxelib libraries -->
   <haxelib>