diff src/fftw-3.3.3/genfft/gen_mdct.ml @ 10:37bf6b4a2645

Add FFTW3
author Chris Cannam
date Wed, 20 Mar 2013 15:35:50 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/fftw-3.3.3/genfft/gen_mdct.ml	Wed Mar 20 15:35:50 2013 +0000
@@ -0,0 +1,257 @@
+(*
+ * Copyright (c) 1997-1999 Massachusetts Institute of Technology
+ * Copyright (c) 2003, 2007-11 Matteo Frigo
+ * Copyright (c) 2003, 2007-11 Massachusetts Institute of Technology
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *)
+
+(* generation of trigonometric transforms *)
+
+open Util
+open Genutil
+open C
+
+
+let usage = "Usage: " ^ Sys.argv.(0) ^ " -n <number>"
+
+let uistride = ref Stride_variable
+let uostride = ref Stride_variable
+let uivstride = ref Stride_variable
+let uovstride = ref Stride_variable
+let normalization = ref 1
+
+type mode =
+  | MDCT
+  | MDCT_MP3
+  | MDCT_VORBIS
+  | MDCT_WINDOW
+  | MDCT_WINDOW_SYM
+  | IMDCT
+  | IMDCT_MP3
+  | IMDCT_VORBIS
+  | IMDCT_WINDOW
+  | IMDCT_WINDOW_SYM
+  | NONE
+
+let mode = ref NONE
+
+let speclist = [
+  "-with-istride",
+  Arg.String(fun x -> uistride := arg_to_stride x),
+  " specialize for given input stride";
+
+  "-with-ostride",
+  Arg.String(fun x -> uostride := arg_to_stride x),
+  " specialize for given output stride";
+
+  "-with-ivstride",
+  Arg.String(fun x -> uivstride := arg_to_stride x),
+  " specialize for given input vector stride";
+
+  "-with-ovstride",
+  Arg.String(fun x -> uovstride := arg_to_stride x),
+  " specialize for given output vector stride";
+
+  "-normalization",
+  Arg.String(fun x -> normalization := int_of_string x),
+  " normalization integer to divide by";
+
+  "-mdct",
+  Arg.Unit(fun () -> mode := MDCT),
+  " generate an MDCT codelet";
+
+  "-mdct-mp3",
+  Arg.Unit(fun () -> mode := MDCT_MP3),
+  " generate an MDCT codelet with MP3 windowing";
+
+  "-mdct-window",
+  Arg.Unit(fun () -> mode := MDCT_WINDOW),
+  " generate an MDCT codelet with window array";
+
+  "-mdct-window-sym",
+  Arg.Unit(fun () -> mode := MDCT_WINDOW_SYM),
+  " generate an MDCT codelet with symmetric window array";
+
+  "-imdct",
+  Arg.Unit(fun () -> mode := IMDCT),
+  " generate an IMDCT codelet";
+
+  "-imdct-mp3",
+  Arg.Unit(fun () -> mode := IMDCT_MP3),
+  " generate an IMDCT codelet with MP3 windowing";
+
+  "-imdct-window",
+  Arg.Unit(fun () -> mode := IMDCT_WINDOW),
+  " generate an IMDCT codelet with window array";
+
+  "-imdct-window-sym",
+  Arg.Unit(fun () -> mode := IMDCT_WINDOW_SYM),
+  " generate an IMDCT codelet with symmetric window array";
+]
+
+let unity_window n i = Complex.one
+
+(* MP3 window(k) = sin(pi/(2n) * (k + 1/2)) *)
+let mp3_window n k = 
+  Complex.imag (Complex.exp (8 * n) (2*k + 1))
+
+(* Vorbis window(k) = sin(pi/2 * (mp3_window(k))^2)
+    ... this is transcendental, though, so we can't do it with our
+        current Complex.exp function *)
+
+let window_array n w =
+    array n (fun i ->
+      let stride = C.SInteger 1
+      and klass = Unique.make () in
+      let refr = C.array_subscript w stride i in
+      let kr = Variable.make_constant klass refr in
+      load_r (kr, kr))
+
+let load_window w n i = w i
+let load_window_sym w n i = w (if (i < n) then i else (2*n - 1 - i))
+
+(* fixme: use same locations for input and output so that it works in-place? *)
+
+(* Note: only correct for even n! *)
+let load_array_mdct window n rarr iarr locations =
+  let twon = 2 * n in
+  let arr = load_array_c twon 
+      (locative_array_c twon rarr iarr locations "BUG") in
+  let arrw = fun i -> Complex.times (window n i) (arr i) in
+  array n
+    ((Complex.times Complex.half) @@
+     (fun i ->
+       if (i < n/2) then
+	 Complex.uminus (Complex.plus [arrw (i + n + n/2); 
+				       arrw (n + n/2 - 1 - i)])
+       else
+	 Complex.plus [arrw (i - n/2); 
+		       Complex.uminus (arrw (n + n/2 - 1 - i))]))
+
+let store_array_mdct window n rarr iarr locations arr =
+  store_array_r n (locative_array_c n rarr iarr locations "BUG") arr
+
+let load_array_imdct window n rarr iarr locations =
+  load_array_c n (locative_array_c n rarr iarr locations "BUG")
+
+let store_array_imdct window n rarr iarr locations arr =
+  let n2 = n/2 in
+  let threen2 = 3*n2 in
+  let arr2 = fun i ->
+    if (i < n2) then
+      arr (i + n2)
+    else if (i < threen2) then
+      Complex.uminus (arr (threen2 - 1 - i))
+    else
+      Complex.uminus (arr (i - threen2))
+  in
+  let arr2w = fun i -> Complex.times (window n i) (arr2 i) in
+  let twon = 2 * n in
+  store_array_r twon (locative_array_c twon rarr iarr locations "BUG") arr2w
+
+let window_param = function
+    MDCT_WINDOW -> true
+  | MDCT_WINDOW_SYM -> true
+  | IMDCT_WINDOW -> true
+  | IMDCT_WINDOW_SYM -> true
+  | _ -> false
+
+let generate n mode =
+  let iarray = "I"
+  and oarray = "O"
+  and istride = "istride"
+  and ostride = "ostride" 
+  and window = "W" 
+  and name = !Magic.codelet_name in
+
+  let vistride = either_stride (!uistride) (C.SVar istride)
+  and vostride = either_stride (!uostride) (C.SVar ostride)
+  in
+
+  let sivs = stride_to_string "ovs" !uovstride in
+  let sovs = stride_to_string "ivs" !uivstride in
+
+  let (transform, load_input, store_output) = match mode with
+  | MDCT -> Trig.dctIV, load_array_mdct unity_window,
+      store_array_mdct unity_window
+  | MDCT_MP3 -> Trig.dctIV, load_array_mdct mp3_window,
+      store_array_mdct unity_window
+  | MDCT_WINDOW -> Trig.dctIV, load_array_mdct
+	(load_window (window_array (2 * n) window)),
+      store_array_mdct unity_window
+  | MDCT_WINDOW_SYM -> Trig.dctIV, load_array_mdct
+	(load_window_sym (window_array n window)),
+      store_array_mdct unity_window
+  | IMDCT -> Trig.dctIV, load_array_imdct unity_window,
+      store_array_imdct unity_window
+  | IMDCT_MP3 -> Trig.dctIV, load_array_imdct unity_window,
+      store_array_imdct mp3_window
+  | IMDCT_WINDOW -> Trig.dctIV, load_array_imdct unity_window,
+      store_array_imdct (load_window (window_array (2 * n) window))
+  | IMDCT_WINDOW_SYM -> Trig.dctIV, load_array_imdct unity_window,
+      store_array_imdct (load_window_sym (window_array n window))
+  | _ -> failwith "must specify transform kind"
+  in
+    
+  let locations = unique_array_c (2*n) in
+  let input = 
+    load_input n
+      (C.array_subscript iarray vistride)
+      (C.array_subscript "BUG" vistride)
+      locations
+  in
+  let output = (Complex.times (Complex.inverse_int !normalization)) 
+    @@ (transform n input) in
+  let odag =
+    store_output n
+      (C.array_subscript oarray vostride)
+      (C.array_subscript "BUG" vostride)
+      locations 
+      output
+  in
+  let annot = standard_optimizer odag in
+
+  let tree =
+    Fcn ("void", name,
+	 ([Decl (C.constrealtypep, iarray);
+	   Decl (C.realtypep, oarray)]
+	  @ (if stride_fixed !uistride then [] 
+               else [Decl (C.stridetype, istride)])
+	  @ (if stride_fixed !uostride then [] 
+	       else [Decl (C.stridetype, ostride)])
+	  @ (choose_simd []
+	       (if stride_fixed !uivstride then [] else 
+	       [Decl ("int", sivs)]))
+	  @ (choose_simd []
+	       (if stride_fixed !uovstride then [] else 
+	       [Decl ("int", sovs)]))
+	  @ (if (not (window_param mode)) then [] 
+	       else [Decl (C.constrealtypep, window)])
+	 ),
+	 finalize_fcn (Asch annot))
+
+  in
+  (unparse tree) ^ "\n"
+
+
+let main () =
+  begin
+    parse speclist usage;
+    print_string (generate (check_size ()) !mode);
+  end
+
+let _ = main()