### 6Examples

#### 6.1Frequency analysis and C code generation

A typical use case is to define a filter, plot its transfer function, and when satisfied, generate some C code.

The filter can be defined in a separate module file or a submodule form exporting an identifier referring to the abstract program. This program can then be passed to an analysis or code generation function such as ai-spectrum or ai-array-c below. The former can be used in conjunction with Racket’s plot facility. The latter produces a C syntax file containing a C function, structure definitions for input, output and state, and preprocessor macros that abstract meta data to facilitate integration in a C host framework.

 > (module test rai/stream (provide svf integrator) (define (integrator (s) (x)) (let ((s (+ s x))) (values s s))) (define (svf (s1 s2) (in)) (let* ((f 0.1) (q 0.3) (s2 (+ s2 (* f s1))) (s1 (- s1 (* f (+ (* q s1) s2 in))))) (values s1 s2 s2))))
> (require 'test)
> (require rai/ai-freq)
> (require plot)
 > (define (plot-filter f) (parameterize ((plot-x-transform log-transform) (plot-y-transform log-transform) (plot-x-ticks (log-ticks)) (plot-y-ticks (log-ticks))) (plot (function (compose magnitude (ai-spectrum f)) 0.0001 0.5))))
> (plot-filter integrator)

> (plot-filter svf)

> (require rai/ai-array-c)
> (display (ai-array-c svf #:nsi 1))
 struct proc_si { int r5; float r7; float r8; }; #define proc_si_r5 0 #define proc_si_r7 0 #define proc_si_r8 0 #define proc_for_si(m) \ m(r5, 0, 1) \ m(r7, 0, 1) \ m(r8, 0, 1) \ struct proc_so { int r6; float r15; float r10; }; #define proc_so_r6 0 #define proc_so_r15 0 #define proc_so_r10 0 #define proc_for_so(m) \ m(r6, 0, 1) \ m(r15, 0, 1) \ m(r10, 0, 1) \ struct proc_in { float * restrict in; }; #define proc_in_in 0 #define proc_for_in(m) \ m(in, 0, 1) \ struct proc_param { }; #define proc_for_param(m) \ struct proc_out { float * restrict r16; }; #define proc_out_r16 0 #define proc_for_out(m) \ m(r16, 0, 1) \ struct proc_store { float r2[1]; }; #define proc_store_r2 1 #define proc_for_store(m) \ m(r2, 1, 1, 1) \ #define proc_for_control(m) \ void proc_loop ( struct proc_si * restrict state, struct proc_in * restrict in, struct proc_param * restrict param, struct proc_out * restrict out, struct proc_store * restrict store, int t_endx) { struct proc_si * restrict si = (struct proc_si *)(&state[(0)&1]); struct proc_so * restrict so = (struct proc_so *)(&state[(1)&1]); for (int t = 0; t < t_endx; t ++) { struct proc_si * restrict si = (struct proc_si *)(&state[(t^0)&1]); struct proc_so * restrict so = (struct proc_so *)(&state[(t^1)&1]); /*?*/ float r0 = p_copy(t); /*?*/ float r1 = p_copy(t_endx); /*?*/ float r3 = p_copy(1.0); /*?*/ float r4 = p_sub(r3, 1.0); so->r6 = p_sub(si->r5, 1.0); float r9 = p_mul(0.1, si->r7); so->r10 = p_add(si->r8, r9); float r11 = p_mul(0.3, si->r7); float r12 = p_add(so->r10, in->in[t]); float r13 = p_add(r11, r12); float r14 = p_mul(0.1, r13); so->r15 = p_sub(si->r7, r14); out->r16[t] = p_copy(so->r10); } }