From: WANG Date: Fri, 6 Sep 2013 15:25:47 +0000 (+0200) Subject: Refactoring of Signal class by adding a rate class. X-Git-Url: https://scm.cri.ensmp.fr/git/Faustine.git/commitdiff_plain/d204fe8a60e0556b0294e17c5c6948cb6cee7d91 Refactoring of Signal class by adding a rate class. --- diff --git a/examples/sinwave/output1.wav b/examples/sinwave/output1.wav index 37a80e3..f019696 100644 Binary files a/examples/sinwave/output1.wav and b/examples/sinwave/output1.wav differ diff --git a/interpretor/beam.ml b/interpretor/beam.ml index b66ac2b..6e56170 100644 --- a/interpretor/beam.ml +++ b/interpretor/beam.ml @@ -96,12 +96,12 @@ class beam : signal_type array -> beam_type = transpose (Array.sub container 0 !index) | _ -> raise x - method frequency : int array = - let each_rate : signal -> int = + method frequency : rate_type array = + let each_rate : signal -> rate = fun (s : signal) -> let rate = s#frequency in - if rate > 0 then rate - else if rate = 0 then 44100 + if rate#num > 0 then rate + else if rate#num = 0 then new rate 44100 1 else raise (Beam_matching "frequency error.") in Array.map each_rate self#get diff --git a/interpretor/faustio.ml b/interpretor/faustio.ml index 3094ce9..8518b5b 100644 --- a/interpretor/faustio.ml +++ b/interpretor/faustio.ml @@ -24,7 +24,7 @@ class virtual io = _basename <- basename; _dir <- dir method virtual read : string array -> beam - method virtual write : int array -> float array array array -> string array + method virtual write : rate array -> float array array array -> string array method private concat : float array array array -> float array array = fun (origin : float array array array) -> @@ -51,7 +51,12 @@ class waveio : io_type = let files = Array.map Sndfile.openfile paths in let frames = Array.map Int64.to_int (Array.map Sndfile.frames files) in - let rates = Array.map Sndfile.samplerate files in + let make_rate = + fun (denom : int) -> + fun (num : int) -> + new rate num denom in + let nums = Array.map Sndfile.samplerate files in + let rates = Array.map (make_rate 1) nums in let create_container = fun l -> Array.create l 1. in let containers = Array.map create_container frames in let _ = array_map2 Sndfile.read files containers in @@ -61,20 +66,22 @@ class waveio : io_type = array_map2 (new signal) rates (Array.map stream2func containers) in new beam signals - method write : int array -> float array array array -> string array = - fun (rates : int array) -> + method write : rate array -> float array array array -> string array = + fun (rates : rate array) -> fun (output : float array array array) -> let n = Array.length output in let paths = Array.init n (fun i -> _dir ^ _basename ^ (string_of_int (i + 1)) ^ ".wav") 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 Sndfile.MAJOR_WAV Sndfile.MINOR_PCM_16 in - let openwr = fun path -> fun channel -> fun rate -> - Sndfile.openfile ~info:(Sndfile.RDWR, file_format, channel, rate) path in - array_map3 openwr paths channels rates in + let openwr = fun path -> fun channel -> fun freq -> + Sndfile.openfile ~info:(Sndfile.RDWR, file_format, channel, freq) path in + array_map3 openwr paths channels freqs in let data = self#concat output in let _ = array_map2 Sndfile.write files data in @@ -106,7 +113,7 @@ class csvio : io_type = let values = let convertor = new value Zero in Array.map (convertor#of_float_array) data in - new signal 0 (Array.get values) + new signal (new rate 0 1) (Array.get values) method read : string array -> beam = fun (paths : string array) -> @@ -114,8 +121,8 @@ class csvio : io_type = let signals = Array.map self#csvread files in new beam signals - method write : int array -> float array array array -> string array = - fun (rates : int array) -> + method write : rate array -> float array array array -> string array = + fun (rates : rate array) -> fun (data : float array array array) -> let paths = let n = Array.length data in @@ -178,8 +185,8 @@ class iomanager = wave#set _dir _basename; csv#set _dir _basename - method write : int array -> float array array array -> string array = - fun (rates : int array) -> + method write : rate array -> float array array array -> string array = + fun (rates : rate array) -> fun (data : float array array array) -> if _format = "" then raise (Invalid_argument "output format unset.") diff --git a/interpretor/process.ml b/interpretor/process.ml index e7568df..f094b7b 100644 --- a/interpretor/process.ml +++ b/interpretor/process.ml @@ -89,7 +89,8 @@ class proc_const : faust_exp -> process_type = method eval : beam_type -> beam_type = fun (input : beam_type) -> if input#get = [||] then - new beam [| new signal 0 (fun t -> new value self#const)|] + new beam [| new signal (new rate 0 1) + (fun t -> new value self#const)|] else raise (Process_error "proc_const accepts no input.") end;; @@ -265,7 +266,7 @@ and proc_rec : faust_exp -> process_type = method eval : beam_type -> beam_type = fun (input : beam_type) -> let memory = Hashtbl.create self#delay in - let rates = ref (Array.make self#dim#output 0) in + let rates = ref (Array.make self#dim#output (new rate 0 1)) in let split : (time -> value_type array) -> (time -> value_type) array = fun beam_at -> diff --git a/interpretor/signal.ml b/interpretor/signal.ml index a32923e..00a1709 100644 --- a/interpretor/signal.ml +++ b/interpretor/signal.ml @@ -13,8 +13,45 @@ exception Signal_operation of string;; let delay_memory_length = 10000;; -class signal : int -> (time -> value_type) -> signal_type = - fun (freq_init : int) -> +class rate : int -> int -> rate_type = + fun (num_init : int) -> + fun (denom_init : int) -> + let rec pgcd : int -> int -> int = + 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 + object (self) + val _num = num_corrected + val _denom = denom_corrected + method num = _num + method denom = _denom + method to_int = + self#num / self#denom + method to_float = + (float_of_int self#num) /. (float_of_int self#denom) + method to_string = + (string_of_int self#num) ^ "/" ^ (string_of_int self#denom) + method equal : rate_type -> bool = + fun (r : rate_type) -> (self#num = r#num) && (self#denom = r#denom) + method mul : int -> rate_type = + fun (i : int) -> new rate (self#num * i) self#denom + method div : int -> rate_type = + fun (i : int) -> new rate self#num (self#denom * i) + end + + +class signal : rate_type -> (time -> value_type) -> signal_type = + fun (freq_init : rate_type) -> fun (func_init : time -> value_type) -> object (self) val mutable signal_func = func_init @@ -22,13 +59,13 @@ class signal : int -> (time -> value_type) -> signal_type = method frequency = freq_init method at = signal_func - method private check_freq : signal_type list -> int = + method private check_freq : signal_type list -> rate_type = fun (sl : signal_type list) -> - let check : int -> signal_type -> int = - fun (f : int) -> + let check : rate_type -> signal_type -> rate_type = + fun (f : rate_type) -> fun (s : signal_type) -> - if f = s#frequency || s#frequency = 0 then f - else if f = 0 then s#frequency + if f#equal s#frequency || s#frequency#num = 0 then f + else if f#num = 0 then s#frequency else raise (Signal_operation "frequency not matched.") in List.fold_left check self#frequency sl @@ -158,7 +195,7 @@ class signal : int -> (time -> value_type) -> signal_type = if size <= 0 then raise (Signal_operation "Vectorize: size <= 0.") else - let freq = self#frequency / size in + let freq = self#frequency#div size in let func : time -> value_type = fun t -> let vec = fun i -> (self#at (size * t + i))#get in @@ -171,7 +208,7 @@ class signal : int -> (time -> value_type) -> signal_type = match (self#at 0)#get with | Vec vec -> vec#size | _ -> raise (Signal_operation "Serialize: scalar input.") in - let freq = self#frequency * size in + let freq = self#frequency#mul size in let func : time -> value_type = fun t -> match (self#at (t/size))#get with diff --git a/interpretor/types.ml b/interpretor/types.ml index f8aeeb8..620cde5 100644 --- a/interpretor/types.ml +++ b/interpretor/types.ml @@ -91,6 +91,9 @@ class type rate_type = object method to_int : int method to_float : float + method to_string : string + method num : int + method denom : int method equal : rate_type -> bool method mul : int -> rate_type method div : int -> rate_type @@ -98,7 +101,7 @@ class type rate_type = class type signal_type = object - method frequency : int + method frequency : rate_type method at : time -> value_type method add_memory : int -> unit method add : signal_type -> signal_type @@ -141,7 +144,7 @@ class type beam_type = method matching : int -> beam_type method at : time -> value_type array method output : int -> float array array array - method frequency : int array + method frequency : rate_type array end;; @@ -170,5 +173,5 @@ class type io_type = object method set : string -> string -> unit method read : string array -> beam_type - method write : int array -> float array array array -> string array + method write : rate_type array -> float array array array -> string array end;;