Use FPVM in demo firmware (unfinished, broken)
[mw/milkymist.git] / software / demo / apipe.c
1 /*
2  * Milkymist VJ SoC (Software)
3  * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, version 3 of the License.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #include <stdio.h>
19 #include <board.h>
20
21 #include <hal/brd.h>
22 #include <hal/snd.h>
23 #include <hal/pfpu.h>
24 #include <hal/time.h>
25
26 #include "analyzer.h"
27 #include "eval.h"
28 #include "cpustats.h"
29 #include "rpipe.h"
30 #include "apipe.h"
31
32 /* Also used as frame rate limiter */
33 #define NSAMPLES (48000/30)
34
35 static short audiobuffer1[NSAMPLES*2];
36 static short audiobuffer2[NSAMPLES*2];
37 static short audiobuffer3[NSAMPLES*2];
38
39 static int run_analyzer_bottom_half;
40 static short *analyzer_buffer;
41 static int peak_bass, peak_mid, peak_treb;
42 static float bass_att, mid_att, treb_att;
43
44 static int eval_ready;
45
46 static struct rpipe_frame frame1 __attribute__((aligned(8)));
47 static struct rpipe_frame frame2 __attribute__((aligned(8)));
48 static int frame1_free;
49 static int frame2_free;
50
51 static unsigned int all_frames;
52
53 static struct rpipe_frame *alloc_rpipe_frame()
54 {
55         if(frame1_free) return &frame1;
56         if(frame2_free) return &frame2;
57         return NULL;
58 }
59
60 static void refill_rpipe_frame(struct rpipe_frame *rpipe_frame)
61 {
62         if(rpipe_frame == &frame1) frame1_free = 1;
63         else if(rpipe_frame == &frame2) frame2_free = 1;
64         else printf("API: trying to refill unknown rpipe frame\n");
65 }
66
67 static void free_rpipe_frame(struct rpipe_frame *rpipe_frame)
68 {
69         snd_record_refill(rpipe_frame->samples);
70         refill_rpipe_frame(rpipe_frame);
71 }
72
73 void apipe_init()
74 {
75         run_analyzer_bottom_half = 0;
76         peak_bass = 1740164;
77         peak_mid = 1062625;
78         peak_treb = 928140;
79         bass_att = 0.0;
80         mid_att = 0.0;
81         treb_att = 0.0;
82         eval_ready = 1;
83         frame1_free = 1;
84         frame2_free = 1;
85         all_frames = 0;
86         printf("API: analysis pipeline ready\n");
87 }
88
89 static void apipe_snd_callback(short *buffer, void *user)
90 {
91         if(run_analyzer_bottom_half) {
92                 /* Skip this buffer */
93                 snd_record_refill(buffer);
94                 return;
95         }
96         analyzer_buffer = buffer;
97         run_analyzer_bottom_half = 1;
98 }
99
100 void apipe_start()
101 {
102         snd_record_empty();
103         snd_record_refill(audiobuffer1);
104         snd_record_refill(audiobuffer2);
105         snd_record_refill(audiobuffer3);
106         snd_record_start(apipe_snd_callback, NSAMPLES, NULL);
107 }
108
109 void apipe_stop()
110 {
111         snd_record_stop();
112 }
113
114 static struct pfpu_td pfpu_td;
115
116 //#define DUMP_MESH
117
118 static void pvv_callback(struct pfpu_td *td)
119 {
120         struct rpipe_frame *rpipe_frame;
121         #ifdef DUMP_MESH
122         int x, y;
123         #endif
124
125         rpipe_frame = (struct rpipe_frame *)td->user;
126
127         #ifdef DUMP_MESH
128         for(y=10;y<13;y++) {
129                 for(x=10;x<13;x++)
130                         printf("(%02d %02d) ", rpipe_frame->vertices[y][x].y, rpipe_frame->vertices[y][x].x);
131                 printf("\n");
132         }
133         printf("\n");
134         #endif
135
136         if(!rpipe_input(rpipe_frame)) free_rpipe_frame(rpipe_frame);
137         eval_ready = 1;
138 }
139
140 static void pfv_callback(struct pfpu_td *td)
141 {
142         struct rpipe_frame *rpipe_frame;
143         int brightness256, brightness64, frame_mod;
144         float decay;
145
146         rpipe_frame = (struct rpipe_frame *)td->user;
147
148         decay = eval_read_pfv(pfv_decay);
149         brightness256 = 255.0*decay+3.5;
150         brightness64 = (brightness256 >> 2)-1;
151         brightness256 &= 3;
152         frame_mod = rpipe_frame->framenr & 3;
153         if((brightness256 == 1) && (frame_mod == 0))
154                 brightness64++;
155         if((brightness256 == 2) && ((frame_mod == 0)||(frame_mod == 2)))
156                 brightness64++;
157         if((brightness256 == 3) && (frame_mod != 3))
158                 brightness64++;
159         if(brightness64 < 0) brightness64 = 0;
160         if(brightness64 > 63) brightness64 = 63;
161         rpipe_frame->brightness = brightness64;
162
163         rpipe_frame->wave_mode = eval_read_pfv(pfv_wave_mode);
164         rpipe_frame->wave_scale = eval_read_pfv(pfv_wave_scale);
165         rpipe_frame->wave_additive = eval_read_pfv(pfv_wave_additive) != 0.0;
166         rpipe_frame->wave_usedots = eval_read_pfv(pfv_wave_usedots) != 0.0;
167         rpipe_frame->wave_maximize_color = eval_read_pfv(pfv_wave_maximize_color) != 0.0;
168         rpipe_frame->wave_thick = eval_read_pfv(pfv_wave_thick) != 0.0;
169         
170         rpipe_frame->wave_x = eval_read_pfv(pfv_wave_x);
171         rpipe_frame->wave_y = eval_read_pfv(pfv_wave_y);
172         rpipe_frame->wave_r = eval_read_pfv(pfv_wave_r);
173         rpipe_frame->wave_g = eval_read_pfv(pfv_wave_g);
174         rpipe_frame->wave_b = eval_read_pfv(pfv_wave_b);
175         rpipe_frame->wave_a = eval_read_pfv(pfv_wave_a);
176
177         rpipe_frame->ob_size = eval_read_pfv(pfv_ob_size);
178         rpipe_frame->ob_r = eval_read_pfv(pfv_ob_r);
179         rpipe_frame->ob_g = eval_read_pfv(pfv_ob_g);
180         rpipe_frame->ob_b = eval_read_pfv(pfv_ob_b);
181         rpipe_frame->ob_a = eval_read_pfv(pfv_ob_a);
182
183         rpipe_frame->ib_size = eval_read_pfv(pfv_ib_size);
184         rpipe_frame->ib_r = eval_read_pfv(pfv_ib_r);
185         rpipe_frame->ib_g = eval_read_pfv(pfv_ib_g);
186         rpipe_frame->ib_b = eval_read_pfv(pfv_ib_b);
187         rpipe_frame->ib_a = eval_read_pfv(pfv_ib_a);
188
189         rpipe_frame->mv_x = eval_read_pfv(pfv_mv_x);
190         rpipe_frame->mv_y = eval_read_pfv(pfv_mv_y);
191         rpipe_frame->mv_dx = eval_read_pfv(pfv_mv_dx);
192         rpipe_frame->mv_dy = eval_read_pfv(pfv_mv_dy);
193         rpipe_frame->mv_l = eval_read_pfv(pfv_mv_l);
194         rpipe_frame->mv_r = eval_read_pfv(pfv_mv_r);
195         rpipe_frame->mv_g = eval_read_pfv(pfv_mv_g);
196         rpipe_frame->mv_b = eval_read_pfv(pfv_mv_b);
197         rpipe_frame->mv_a = eval_read_pfv(pfv_mv_a);
198
199         rpipe_frame->tex_wrap = eval_read_pfv(pfv_tex_wrap) != 0.0;
200
201         eval_pfv_to_pvv();
202         eval_pvv_fill_td(&pfpu_td, &rpipe_frame->vertices[0][0], pvv_callback, rpipe_frame);
203         pfpu_submit_task(&pfpu_td);
204 }
205
206 static void analyzer_bottom_half()
207 {
208         struct analyzer_state analyzer;
209         int bass, mid, treb;
210         float fbass, fmid, ftreb;
211         float time;
212         int i;
213         struct rpipe_frame *rpipe_frame;
214         struct timestamp ts;
215
216         rpipe_frame = alloc_rpipe_frame();
217         if(rpipe_frame == NULL) {
218                 snd_record_refill(analyzer_buffer);
219                 return; /* drop this buffer */
220         }
221
222         rpipe_frame->nsamples = NSAMPLES;
223         rpipe_frame->samples = analyzer_buffer;
224         rpipe_frame->callback = free_rpipe_frame;
225
226         analyzer_init(&analyzer);
227         for(i=0;i<NSAMPLES;i++)
228                 analyzer_put_sample(&analyzer, analyzer_buffer[2*i], analyzer_buffer[2*i+1]);
229
230         bass = analyzer_get_bass(&analyzer);
231         mid = analyzer_get_mid(&analyzer);
232         treb = analyzer_get_treb(&analyzer);
233         // TODO: appropriate scaling
234         if(bass > peak_bass) peak_bass = bass;
235         if(mid > peak_mid) peak_mid = mid;
236         if(treb > peak_treb) peak_treb = treb;
237         fbass = 5.0f*(float)bass/(float)peak_bass;
238         fmid = 5.0f*(float)mid/(float)peak_mid;
239         ftreb = 5.0f*(float)treb/(float)peak_treb;
240
241         treb_att = 0.6f*treb_att + 0.4f*ftreb;
242         mid_att = 0.6f*mid_att + 0.4f*fmid;
243         bass_att = 0.6f*bass_att + 0.4f*fbass;
244
245         time_get(&ts);
246         time = (float)ts.sec + (float)ts.usec/1000000.0f;
247
248         eval_reinit_all_pfv();
249         
250         eval_write_pfv(pfv_time, time);
251         eval_write_pfv(pfv_bass, fbass);
252         eval_write_pfv(pfv_mid, fmid);
253         eval_write_pfv(pfv_treb, ftreb);
254         eval_write_pfv(pfv_bass_att, bass_att);
255         eval_write_pfv(pfv_mid_att, mid_att);
256         eval_write_pfv(pfv_treb_att, treb_att);
257
258         rpipe_frame->time = time;
259         rpipe_frame->treb = ftreb;
260         rpipe_frame->framenr = all_frames++;
261
262         eval_pfv_fill_td(&pfpu_td, pfv_callback, rpipe_frame);
263         pfpu_submit_task(&pfpu_td);
264 }
265
266 void apipe_service()
267 {
268         if(run_analyzer_bottom_half && eval_ready) {
269                 cpustats_enter();
270                 analyzer_bottom_half();
271                 eval_ready = 0;
272                 run_analyzer_bottom_half = 0;
273                 cpustats_leave();
274         }
275 }