From: WANG <wang@wang-OptiPlex-780.(none)>
Date: Fri, 27 Sep 2013 13:14:52 +0000 (+0200)
Subject: Implement stdin, stdout and stderr to Faustine.
X-Git-Url: https://scm.cri.ensmp.fr/git/Faustine.git/commitdiff_plain/c55d1f23d06e85b0e21cdf5cbc5c8efb6ac3bc1a?hp=-c

Implement stdin, stdout and stderr to Faustine.
Tested by examples/sinwave/sin.dsp.
---

c55d1f23d06e85b0e21cdf5cbc5c8efb6ac3bc1a
diff --git a/examples/fft/Makefile b/examples/fft/Makefile
index cbe38a6..6d41558 100644
--- a/examples/fft/Makefile
+++ b/examples/fft/Makefile
@@ -8,12 +8,7 @@ SINSUM = sinsum.dsp
 WAV_BASENAME = $(SINSUM:.dsp=)
 WAV_FORMAT = wav
 WAVIN = $(WAV_BASENAME)1.$(WAV_FORMAT)
-
-INPUT1 = sin_1378Hz_0.005_ampli_128samples.wav
-INPUT2 = sin_2067Hz_0.005_ampli_128samples.wav
-INPUT3 = sin_16536Hz_0.005_ampli_128samples.wav
-INPUT4 = sin_22000Hz_0.005_ampli_128samples.wav
-
+WAV_LENGTH = 128
 
 all: $(IMGOUT)
 
@@ -23,8 +18,8 @@ $(IMGOUT): $(CSVOUT)
 $(CSVOUT): $(SRC) $(WAVIN)
 	faustine -f $(SRC) -i $(WAVIN) --oformat $(FORMAT) --obasename $(BASENAME)
 
-$(WAVIN): $(SINS) $(INPUT1) $(INPUT2) $(INPUT3) $(INPUT4)
-	faustine -f $(SINSUM) -i $(INPUT1) -i $(INPUT2) -i $(INPUT3) -i $(INPUT4) --oformat $(WAV_FORMAT) --obasename $(WAV_BASENAME)
+$(WAVIN): $(SINS)
+	faustine -f $(SINSUM) -l $(WAV_LENGTH) --oformat $(WAV_FORMAT) --obasename $(WAV_BASENAME)
 
 clean::
 	rm -f gmon.out $(CSVOUT) $(IMGOUT) $(WAVIN) *~
diff --git a/examples/fft/fft.png b/examples/fft/fft.png
index 6e8739e..eec0f4b 100644
Binary files a/examples/fft/fft.png and b/examples/fft/fft.png differ
diff --git a/examples/fft/sin_1378Hz_0.005_ampli_128samples.wav b/examples/fft/sin_1378Hz_0.005_ampli_128samples.wav
deleted file mode 100644
index 7d4c896..0000000
Binary files a/examples/fft/sin_1378Hz_0.005_ampli_128samples.wav and /dev/null differ
diff --git a/examples/fft/sin_16536Hz_0.005_ampli_128samples.wav b/examples/fft/sin_16536Hz_0.005_ampli_128samples.wav
deleted file mode 100644
index e48ffb6..0000000
Binary files a/examples/fft/sin_16536Hz_0.005_ampli_128samples.wav and /dev/null differ
diff --git a/examples/fft/sin_2067Hz_0.005_ampli_128samples.wav b/examples/fft/sin_2067Hz_0.005_ampli_128samples.wav
deleted file mode 100644
index a8524b7..0000000
Binary files a/examples/fft/sin_2067Hz_0.005_ampli_128samples.wav and /dev/null differ
diff --git a/examples/fft/sin_22000Hz_0.005_ampli_128samples.wav b/examples/fft/sin_22000Hz_0.005_ampli_128samples.wav
deleted file mode 100644
index 93556f1..0000000
Binary files a/examples/fft/sin_22000Hz_0.005_ampli_128samples.wav and /dev/null differ
diff --git a/examples/fft/sinsum.dsp b/examples/fft/sinsum.dsp
index 0ee1d5b..3299928 100644
--- a/examples/fft/sinsum.dsp
+++ b/examples/fft/sinsum.dsp
@@ -1 +1,6 @@
-process = +, + : +;
+import("math.lib");
+import("music.lib");
+samplerate = 44100;
+process = (sinwave(1378) + sinwave(2067)) , (sinwave(16536) + sinwave(22000)) : + : /(4) ;
+sinwave(f) = time*(2.0*PI)*f/samplerate : sin;
+
diff --git a/interpreter/aux.ml b/interpreter/aux.ml
index 7c21a61..5321349 100644
--- a/interpreter/aux.ml
+++ b/interpreter/aux.ml
@@ -18,7 +18,7 @@ let array_map3 = fun f -> fun a -> fun b -> fun c ->
   if n1 = n2 && n1 = n3 then Array.init n1 (fun i -> f a.(i) b.(i) c.(i))
   else raise (Invalid_argument "Array.map3 size not matched.");;
 
-let decorate = fun s -> "    Faustine -> " ^ s;;
+let decorate = fun s -> "    Faustine -> " ^ s ^ "\n";;
 
 let xor : bool -> bool -> bool =
   fun a -> fun b -> (a || b) && (not (a && b));;
diff --git a/interpreter/faustio.ml b/interpreter/faustio.ml
index 7df74a6..47e07ce 100644
--- a/interpreter/faustio.ml
+++ b/interpreter/faustio.ml
@@ -12,16 +12,20 @@ open Signal;;
 open Beam;;
 open Aux;;
 
+exception Faustine_IO_Error of string;;
+
 let csv_read_buffer_length = 0xFFFF;;
 
 class virtual io = 
   object
+    val mutable _filename = ""
     val mutable _basename = ""
     val mutable _dir = ""
-    method set : string -> string -> unit = 
-      fun (dir : string) ->
-	fun (basename : string) ->
-	  _basename <- basename; _dir <- dir
+    method set : string -> string -> string -> unit = 
+      fun (filename : string) ->
+	fun (dir : string) ->
+	  fun (basename : string) ->
+	    _filename <- filename; _basename <- basename; _dir <- dir
 
     method virtual read : string array -> beam
     method virtual write : rate array -> data -> string array
@@ -70,11 +74,18 @@ class waveio : io_type =
       fun (rates : rate array) ->
 	fun (output : data) ->
 	  let n = Array.length output in	  
-	  let paths = Array.init n (fun i -> 
-	    _dir ^ _basename ^ (string_of_int (i + 1)) ^ ".wav") in
+	  let paths = 
+	    if _filename = "" then 
+	      Array.init n (fun i -> 
+		_dir ^ _basename ^ (string_of_int (i + 1)) ^ ".wav") 
+	    else if n = 1 then 
+	      let () = Unix.unlink "_filename" in [|(_filename ^ ".wav")|]
+	    else raise (Faustine_IO_Error ("The process has several output signals, 
+			however stdout supports only one output signal. Please remove 
+			the '> " ^ _filename ^ "'.")) in
 	  let get_freq = fun (r : rate) -> r#to_int in
 	  let freqs = Array.map get_freq rates in
-
+	  
 	  let files = 
 	    let channels = self#channels output in 
 	    let file_format = Sndfile.format 
@@ -124,12 +135,16 @@ class csvio : io_type =
     method write : rate array -> data -> string array = 
       fun (rates : rate array) ->
 	fun (data : data) ->
+	  let n = Array.length data in
 	  let paths = 
-	    let n = Array.length data in
-	    let path_pattern = fun i -> 
-	      _dir ^ _basename ^ (string_of_int (i + 1)) ^ ".csv" in
-	    Array.init n path_pattern in	  
-
+	    if _filename = "" then 
+	      Array.init n (fun i -> 
+		_dir ^ _basename ^ (string_of_int (i + 1)) ^ ".csv") 
+	    else if n = 1 then 
+	      let () = Unix.unlink _filename in [|(_filename ^ ".csv")|]
+	    else raise (Faustine_IO_Error ("The process has several output signals, 
+			however stdout supports only one output signal. Please remove 
+			the '> " ^ _filename ^ "'.")) in
 	  let files = Array.map open_out paths in
 	  let strings = 
 	    let value2string : float array -> string =
@@ -151,6 +166,7 @@ class iomanager =
   object (self)
     val wave = new waveio
     val csv = new csvio
+    val mutable _output_filename = ""
     val mutable _dir = ""
     val mutable _format = ""
     val mutable _basename = ""
@@ -175,15 +191,17 @@ class iomanager =
 	  fun b1 -> fun b2 -> b1#append b2 in
 	List.fold_left concat (new beam [||]) beams
 	      
-    method set : string -> string -> string -> unit = 
-      fun (dir : string) ->
-	fun (format : string) ->
-	  fun (basename : string) ->
-	    _dir <- dir; 
-	    _format <- format; 
-	    _basename <- basename;
-	    wave#set _dir _basename;
-	    csv#set _dir _basename
+    method set : string -> string -> string -> string -> unit = 
+      fun (filename : string) ->
+	fun (dir : string) ->
+	  fun (format : string) ->
+	    fun (basename : string) ->
+	      _output_filename <- filename;
+	      _dir <- dir; 
+	      _format <- format; 
+	      _basename <- basename;
+	      wave#set _output_filename _dir _basename;
+	      csv#set _output_filename _dir _basename
 
     method write : rate array -> data -> string array = 
       fun (rates : rate array) ->
diff --git a/interpreter/main.ml b/interpreter/main.ml
index 54c7f1a..2f102f3 100644
--- a/interpreter/main.ml
+++ b/interpreter/main.ml
@@ -6,6 +6,7 @@
 *)
 
 open Aux;;
+open Beam;;
 open Process;;
 open Faustio;;
 
@@ -33,8 +34,9 @@ let size_input = ref 0;;
 let inputs = ref [];;
 let time_max = ref 0xFFFF;;
 let dir_output = ref "";;
-let format_output = ref "wav";;
+let format_output = ref "csv";;
 let basename_output = ref "output";;
+let output = ref "";;
 
 let option_usage = "usage: " ^ Sys.argv.(0) 
   ^ " [-f dsp_src] [-i input] [-l length] [--odir dir] [--oformat wav/csv] [--obasename name]";;
@@ -51,65 +53,87 @@ let speclist = [
   ("--obasename", Arg.String (fun s -> basename_output := s), ": set output basename");
   ];;
  
+let file_of_path : string -> string = 
+  fun (path : string) ->
+    let fragments = Str.split (Str.regexp "/") path in
+    let n = List.length fragments in
+    List.nth fragments (n - 1);;  
+
+let stdinput = fun (x : unit) ->
+  let path = Unix.readlink "/proc/self/fd/0" in
+  if path <> "/dev/pts/4" then
+    ( incr size_input;
+      inputs := !inputs @ [path] )
+  else ();;
+
+let stdoutput = fun (x : unit) ->
+  let path = Unix.readlink "/proc/self/fd/1" in
+  if path <> "/dev/pts/4" then output := path
+  else ();;
+
+let stdio = fun (x : unit) -> 
+  stdinput ();
+  stdoutput ();;
 
 let main () = 
+
 (*
-        let () = print_endline (Scanf.Scanning.name_of_input (Scanf.Scanning.stdin)) in
 	let () = print_endline (Unix.readlink "/proc/self/fd/0") in
 	let () = print_endline (Unix.readlink "/proc/self/fd/1") in
 	let () = print_endline (Unix.readlink "/proc/self/fd/2") in
 *)
+        let () = stdio () in 
 	let () = Arg.parse speclist option_unknown option_usage in
         let _ = Sys.signal Sys.sigalrm Sys.Signal_ignore in
 	let _ = set_GC () in
 	let io = new iomanager in
-	let () = io#set !dir_output !format_output !basename_output in
+	let () = io#set !output !dir_output !format_output !basename_output in
 
 
-	let () = print_string("    Faustine -> Reading input ...") in
+	let () = output_string stderr ("    Faustine -> Reading input ...") in
 	let tic0 = Unix.time () in
-	let input = io#read !inputs in
+	let input : beam = io#read !inputs in
 	let toc0 = Unix.time () in
-	let () = print_endline(" Done. (duration: " ^ (string_of_float (toc0 -. tic0)) ^ "s.)") in
+	let () = output_string stderr (" Done. (duration: " ^ (string_of_float (toc0 -. tic0)) ^ "s.)\n") in
 
 
-	let () = print_string("    Faustine -> Preprocessing...") in
+	let () = output_string stderr ("    Faustine -> Preprocessing...") in
 	let tic1 = Unix.time () in
 	let faust_core = Preprocess.preprocess !path_dsp in
 	let toc1 = Unix.time () in
-	let () = print_endline(" Done. (duration: " ^ (string_of_float (toc1 -. tic1)) ^ "s.)") in
+	let () = output_string stderr (" Done. (duration: " ^ (string_of_float (toc1 -. tic1)) ^ "s.)\n") in
 
 
-	let () = print_string("    Faustine -> Constructing process...") in
+	let () = output_string stderr ("    Faustine -> Constructing process...") in
 	let tic2 = Unix.time () in
 	let faust_exp = exp_of_string faust_core in
 	let proc = (new proc_factory)#make faust_exp in
 	let toc2 = Unix.time () in
-	let () = print_endline(" Done. (duration: " ^ (string_of_float (toc2 -. tic2)) ^ "s.)") in
+	let () = output_string stderr (" Done. (duration: " ^ (string_of_float (toc2 -. tic2)) ^ "s.)\n") in
 
 
-	let () = print_string("    Faustine -> Constructing signals...") in
+	let () = output_string stderr ("    Faustine -> Constructing signals...") in
 	let tic3 = Unix.time () in
-	let output = proc#eval input in
+	let output : beam = proc#eval input in
 	let toc3 = Unix.time () in
-	let () = print_endline(" Done. (duration: " ^ (string_of_float (toc3 -. tic3)) ^ "s.)") in
+	let () = output_string stderr (" Done. (duration: " ^ (string_of_float (toc3 -. tic3)) ^ "s.)\n") in
 
 
-	let () = print_string("    Faustine -> Evaluating...") in
+	let () = output_string stderr ("    Faustine -> Evaluating...") in
 	let tic4 = Unix.time () in
 	let data = output#output !time_max in
 	let rates = output#frequency in
 	let toc4 = Unix.time () in
-	let () = print_endline(" Done. (duration: " ^ (string_of_float (toc4 -. tic4)) ^ "s.)") in
+	let () = output_string stderr (" Done. (duration: " ^ (string_of_float (toc4 -. tic4)) ^ "s.)\n") in
 
 
-	let () = print_string("    Faustine -> Writing output...") in
+	let () = output_string stderr ("    Faustine -> Writing output...") in
 	let tic5 = Unix.time () in
 	let output_paths = io#write rates data in
 	let toc5 = Unix.time () in
-	let () = print_endline(" Done. (duration: " ^ (string_of_float (toc5 -. tic5)) ^ "s.)") in
+	let () = output_string stderr (" Done. (duration: " ^ (string_of_float (toc5 -. tic5)) ^ "s.)\n") in
 
-	let _ = Array.map print_endline 
+	let _ = Array.map (output_string stderr)  
 	    (Array.map decorate output_paths) in
 	();;
 
diff --git a/interpreter/signal.ml b/interpreter/signal.ml
index 66089e9..0701ffc 100644
--- a/interpreter/signal.ml
+++ b/interpreter/signal.ml
@@ -20,19 +20,14 @@ class rate : int -> int -> rate_type =
 	fun i1 -> fun i2 ->
 	  let r = i1 mod i2 in 
 	  if r = 0 then i2 else pgcd i2 r in
-      let num_positive = 
-	if num_init >= 0 then num_init 
-	else (-num_init) in
-      let denom_positive = 
-	if denom_init > 0 then denom_init 
-	else if denom_init < 0 then -denom_init
-	else raise (Signal_operation "sample rate denominater = 0.") in
-      let factor = pgcd num_positive denom_positive in
-      let num_corrected = num_init / factor in
-      let denom_corrected = denom_init / factor in
+      let factor = 
+	if denom_init = 0 then 
+	  raise (Signal_operation "sample rate denominater = 0.")
+	else 
+	  pgcd (abs num_init) (abs denom_init) in
       object (self)
-	val _num = num_corrected
-	val _denom = denom_corrected
+	val _num = num_init / factor
+	val _denom = denom_init / factor
 	method num = _num
 	method denom = _denom
 	method to_int = 
@@ -243,7 +238,6 @@ class signal : rate_type -> (time -> value_type) -> signal_type =
 		  new value (Vec (new vector size vec)) in
 	      new signal freq func
 
-
 	method serialize : signal_type = 
 	  let size = 
 	    match (self#at 0)#get with
diff --git a/interpreter/types.ml b/interpreter/types.ml
index 7024eeb..da486f2 100644
--- a/interpreter/types.ml
+++ b/interpreter/types.ml
@@ -253,7 +253,7 @@ class type process_type =
 
 class type io_type = 
     object
-      method set : string -> string -> unit
+      method set : string -> string -> string -> unit
       method read : string array -> beam_type
       method write : rate_type array -> data -> string array
     end;;