7025309c5fe8f97459520fa8c7f8a9057d12fe6f
[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 struct eval_state *eval;
45 static int eval_ready;
46
47 static struct rpipe_frame frame1 __attribute__((aligned(8)));
48 static struct rpipe_frame frame2 __attribute__((aligned(8)));
49 static int frame1_free;
50 static int frame2_free;
51
52 static unsigned int all_frames;
53
54 static struct rpipe_frame *alloc_rpipe_frame()
55 {
56         if(frame1_free) return &frame1;
57         if(frame2_free) return &frame2;
58         return NULL;
59 }
60
61 static void refill_rpipe_frame(struct rpipe_frame *rpipe_frame)
62 {
63         if(rpipe_frame == &frame1) frame1_free = 1;
64         else if(rpipe_frame == &frame2) frame2_free = 1;
65         else printf("API: trying to refill unknown rpipe frame\n");
66 }
67
68 static void free_rpipe_frame(struct rpipe_frame *rpipe_frame)
69 {
70         snd_record_refill(rpipe_frame->samples);
71         refill_rpipe_frame(rpipe_frame);
72 }
73
74 void apipe_init()
75 {
76         run_analyzer_bottom_half = 0;
77         peak_bass = 1740164;
78         peak_mid = 1062625;
79         peak_treb = 928140;
80         bass_att = 0.0;
81         mid_att = 0.0;
82         treb_att = 0.0;
83         eval_ready = 1;
84         frame1_free = 1;
85         frame2_free = 1;
86         all_frames = 0;
87         printf("API: analysis pipeline ready\n");
88 }
89
90 static void apipe_snd_callback(short *buffer, void *user)
91 {
92         if(run_analyzer_bottom_half) {
93                 /* Skip this buffer */
94                 snd_record_refill(buffer);
95                 return;
96         }
97         analyzer_buffer = buffer;
98         run_analyzer_bottom_half = 1;
99 }
100
101 void apipe_start(struct eval_state *e)
102 {
103         snd_record_empty();
104         snd_record_refill(audiobuffer1);
105         snd_record_refill(audiobuffer2);
106         snd_record_refill(audiobuffer3);
107         eval = e;
108         snd_record_start(apipe_snd_callback, NSAMPLES, NULL);
109 }
110
111 void apipe_stop()
112 {
113         snd_record_stop();
114 }
115
116 static struct pfpu_td pfpu_td;
117
118 //#define DUMP_MESH
119
120 static void pvv_callback(struct pfpu_td *td)
121 {
122         struct rpipe_frame *rpipe_frame;
123         #ifdef DUMP_MESH
124         int x, y;
125         #endif
126
127         rpipe_frame = (struct rpipe_frame *)td->user;
128
129         #ifdef DUMP_MESH
130         for(y=10;y<13;y++) {
131                 for(x=10;x<13;x++)
132                         printf("(%02d %02d) ", rpipe_frame->vertices[y][x].y, rpipe_frame->vertices[y][x].x);
133                 printf("\n");
134         }
135         printf("\n");
136         #endif
137
138         if(!rpipe_input(rpipe_frame)) free_rpipe_frame(rpipe_frame);
139         eval_ready = 1;
140 }
141
142 static void pfv_callback(struct pfpu_td *td)
143 {
144         struct rpipe_frame *rpipe_frame;
145         int brightness256, brightness64, frame_mod;
146         float decay;
147
148         rpipe_frame = (struct rpipe_frame *)td->user;
149
150         decay = eval_read_pfv(eval, pfv_decay);
151         brightness256 = 255.0*decay+3.5;
152         brightness64 = (brightness256 >> 2)-1;
153         brightness256 &= 3;
154         frame_mod = rpipe_frame->framenr & 3;
155         if((brightness256 == 1) && (frame_mod == 0))
156                 brightness64++;
157         if((brightness256 == 2) && ((frame_mod == 0)||(frame_mod == 2)))
158                 brightness64++;
159         if((brightness256 == 3) && (frame_mod != 3))
160                 brightness64++;
161         if(brightness64 < 0) brightness64 = 0;
162         if(brightness64 > 63) brightness64 = 63;
163         rpipe_frame->brightness = brightness64;
164
165         rpipe_frame->wave_mode = eval_read_pfv(eval, pfv_wave_mode);
166         rpipe_frame->wave_scale = eval_read_pfv(eval, pfv_wave_scale);
167         rpipe_frame->wave_additive = eval_read_pfv(eval, pfv_wave_additive) != 0.0;
168         rpipe_frame->wave_usedots = eval_read_pfv(eval, pfv_wave_usedots) != 0.0;
169         rpipe_frame->wave_maximize_color = eval_read_pfv(eval, pfv_wave_maximize_color) != 0.0;
170         rpipe_frame->wave_thick = eval_read_pfv(eval, pfv_wave_thick) != 0.0;
171         
172         rpipe_frame->wave_x = eval_read_pfv(eval, pfv_wave_x);
173         rpipe_frame->wave_y = eval_read_pfv(eval, pfv_wave_y);
174         rpipe_frame->wave_r = eval_read_pfv(eval, pfv_wave_r);
175         rpipe_frame->wave_g = eval_read_pfv(eval, pfv_wave_g);
176         rpipe_frame->wave_b = eval_read_pfv(eval, pfv_wave_b);
177         rpipe_frame->wave_a = eval_read_pfv(eval, pfv_wave_a);
178
179         rpipe_frame->ob_size = eval_read_pfv(eval, pfv_ob_size);
180         rpipe_frame->ob_r = eval_read_pfv(eval, pfv_ob_r);
181         rpipe_frame->ob_g = eval_read_pfv(eval, pfv_ob_g);
182         rpipe_frame->ob_b = eval_read_pfv(eval, pfv_ob_b);
183         rpipe_frame->ob_a = eval_read_pfv(eval, pfv_ob_a);
184
185         rpipe_frame->ib_size = eval_read_pfv(eval, pfv_ib_size);
186         rpipe_frame->ib_r = eval_read_pfv(eval, pfv_ib_r);
187         rpipe_frame->ib_g = eval_read_pfv(eval, pfv_ib_g);
188         rpipe_frame->ib_b = eval_read_pfv(eval, pfv_ib_b);
189         rpipe_frame->ib_a = eval_read_pfv(eval, pfv_ib_a);
190
191         rpipe_frame->mv_x = eval_read_pfv(eval, pfv_mv_x);
192         rpipe_frame->mv_y = eval_read_pfv(eval, pfv_mv_y);
193         rpipe_frame->mv_dx = eval_read_pfv(eval, pfv_mv_dx);
194         rpipe_frame->mv_dy = eval_read_pfv(eval, pfv_mv_dy);
195         rpipe_frame->mv_l = eval_read_pfv(eval, pfv_mv_l);
196         rpipe_frame->mv_r = eval_read_pfv(eval, pfv_mv_r);
197         rpipe_frame->mv_g = eval_read_pfv(eval, pfv_mv_g);
198         rpipe_frame->mv_b = eval_read_pfv(eval, pfv_mv_b);
199         rpipe_frame->mv_a = eval_read_pfv(eval, pfv_mv_a);
200
201         rpipe_frame->tex_wrap = eval_read_pfv(eval, pfv_tex_wrap) != 0.0;
202
203         eval_pfv_to_pvv(eval);
204         eval_pvv_fill_td(eval, &pfpu_td, &rpipe_frame->vertices[0][0], pvv_callback, rpipe_frame);
205         pfpu_submit_task(&pfpu_td);
206 }
207
208 static void analyzer_bottom_half()
209 {
210         struct analyzer_state analyzer;
211         int bass, mid, treb;
212         float fbass, fmid, ftreb;
213         float time;
214         int i;
215         struct rpipe_frame *rpipe_frame;
216         struct timestamp ts;
217
218         rpipe_frame = alloc_rpipe_frame();
219         if(rpipe_frame == NULL) {
220                 snd_record_refill(analyzer_buffer);
221                 return; /* drop this buffer */
222         }
223
224         rpipe_frame->nsamples = NSAMPLES;
225         rpipe_frame->samples = analyzer_buffer;
226         rpipe_frame->callback = free_rpipe_frame;
227
228         analyzer_init(&analyzer);
229         for(i=0;i<NSAMPLES;i++)
230                 analyzer_put_sample(&analyzer, analyzer_buffer[2*i], analyzer_buffer[2*i+1]);
231
232         bass = analyzer_get_bass(&analyzer);
233         mid = analyzer_get_mid(&analyzer);
234         treb = analyzer_get_treb(&analyzer);
235         // TODO: appropriate scaling
236         if(bass > peak_bass) peak_bass = bass;
237         if(mid > peak_mid) peak_mid = mid;
238         if(treb > peak_treb) peak_treb = treb;
239         fbass = 5.0f*(float)bass/(float)peak_bass;
240         fmid = 5.0f*(float)mid/(float)peak_mid;
241         ftreb = 5.0f*(float)treb/(float)peak_treb;
242
243         treb_att = 0.6f*treb_att + 0.4f*ftreb;
244         mid_att = 0.6f*mid_att + 0.4f*fmid;
245         bass_att = 0.6f*bass_att + 0.4f*fbass;
246
247         time_get(&ts);
248         time = (float)ts.sec + (float)ts.usec/1000000.0f;
249
250         eval_reinit_all_pfv(eval);
251         
252         eval_write_pfv(eval, pfv_time, time);
253         eval_write_pfv(eval, pfv_bass, fbass);
254         eval_write_pfv(eval, pfv_mid, fmid);
255         eval_write_pfv(eval, pfv_treb, ftreb);
256         eval_write_pfv(eval, pfv_bass_att, bass_att);
257         eval_write_pfv(eval, pfv_mid_att, mid_att);
258         eval_write_pfv(eval, pfv_treb_att, treb_att);
259
260         rpipe_frame->time = time;
261         rpipe_frame->treb = ftreb;
262         rpipe_frame->framenr = all_frames++;
263
264         eval_pfv_fill_td(eval, &pfpu_td, pfv_callback, rpipe_frame);
265         pfpu_submit_task(&pfpu_td);
266 }
267
268 void apipe_service()
269 {
270         if(run_analyzer_bottom_half && eval_ready) {
271                 cpustats_enter();
272                 analyzer_bottom_half();
273                 eval_ready = 0;
274                 run_analyzer_bottom_half = 0;
275                 cpustats_leave();
276         }
277 }