summaryrefslogtreecommitdiff
path: root/apps/plugins
diff options
context:
space:
mode:
authorRobert Keevil <rkeevil+rockbox@gmail.com>2007-07-31 17:23:49 +0000
committerRobert Keevil <rkeevil+rockbox@gmail.com>2007-07-31 17:23:49 +0000
commit98e607390673a2e81eed132724d83f430a0ea66e (patch)
tree1a9ec519c852f7614e416d44161c755ee1fbc115 /apps/plugins
parentaea433c3e30a7ab2f836bd516b0104a236612bbf (diff)
downloadrockbox-98e607390673a2e81eed132724d83f430a0ea66e.tar.gz
rockbox-98e607390673a2e81eed132724d83f430a0ea66e.zip
vu_meter: Use the fixedpoint lib (moving flog there)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@14103 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins')
-rw-r--r--apps/plugins/lib/fixedpoint.c30
-rw-r--r--apps/plugins/lib/fixedpoint.h1
-rw-r--r--apps/plugins/vu_meter.c89
3 files changed, 42 insertions, 78 deletions
diff --git a/apps/plugins/lib/fixedpoint.c b/apps/plugins/lib/fixedpoint.c
index cf69d9c31b..88c2f6ea54 100644
--- a/apps/plugins/lib/fixedpoint.c
+++ b/apps/plugins/lib/fixedpoint.c
@@ -202,3 +202,33 @@ long cos_int(int val)
202 } 202 }
203 return 0; 203 return 0;
204} 204}
205
206/**
207 * Fixed-point natural log
208 * taken from http://www.quinapalus.com/efunc.html
209 * "The code assumes integers are at least 32 bits long. The (positive)
210 * argument and the result of the function are both expressed as fixed-point
211 * values with 16 fractional bits, although intermediates are kept with 28
212 * bits of precision to avoid loss of accuracy during shifts."
213 */
214
215long flog(int x) {
216 long t,y;
217
218 y=0xa65af;
219 if(x<0x00008000) x<<=16, y-=0xb1721;
220 if(x<0x00800000) x<<= 8, y-=0x58b91;
221 if(x<0x08000000) x<<= 4, y-=0x2c5c8;
222 if(x<0x20000000) x<<= 2, y-=0x162e4;
223 if(x<0x40000000) x<<= 1, y-=0x0b172;
224 t=x+(x>>1); if((t&0x80000000)==0) x=t,y-=0x067cd;
225 t=x+(x>>2); if((t&0x80000000)==0) x=t,y-=0x03920;
226 t=x+(x>>3); if((t&0x80000000)==0) x=t,y-=0x01e27;
227 t=x+(x>>4); if((t&0x80000000)==0) x=t,y-=0x00f85;
228 t=x+(x>>5); if((t&0x80000000)==0) x=t,y-=0x007e1;
229 t=x+(x>>6); if((t&0x80000000)==0) x=t,y-=0x003f8;
230 t=x+(x>>7); if((t&0x80000000)==0) x=t,y-=0x001fe;
231 x=0x80000000-x;
232 y-=x>>15;
233 return y;
234}
diff --git a/apps/plugins/lib/fixedpoint.h b/apps/plugins/lib/fixedpoint.h
index c58798930a..719915709a 100644
--- a/apps/plugins/lib/fixedpoint.h
+++ b/apps/plugins/lib/fixedpoint.h
@@ -23,3 +23,4 @@ long fsincos(unsigned long phase, long *cos);
23long fsqrt(long a, unsigned int fracbits); 23long fsqrt(long a, unsigned int fracbits);
24long cos_int(int val); 24long cos_int(int val);
25long sin_int(int val); 25long sin_int(int val);
26long flog(int x);
diff --git a/apps/plugins/vu_meter.c b/apps/plugins/vu_meter.c
index ba64932d84..a03f38fe54 100644
--- a/apps/plugins/vu_meter.c
+++ b/apps/plugins/vu_meter.c
@@ -16,6 +16,7 @@
16 * 16 *
17 **************************************************************************/ 17 **************************************************************************/
18#include "plugin.h" 18#include "plugin.h"
19#include "fixedpoint.h"
19 20
20#if defined(HAVE_LCD_BITMAP) 21#if defined(HAVE_LCD_BITMAP)
21 22
@@ -200,78 +201,20 @@ void reset_settings(void) {
200 vumeter_settings.digital_decay=0; 201 vumeter_settings.digital_decay=0;
201} 202}
202 203
203/* taken from http://www.quinapalus.com/efunc.html */
204int fxlog(int x) {
205 int t,y;
206
207 y=0xa65af;
208 if(x<0x00008000) x<<=16, y-=0xb1721;
209 if(x<0x00800000) x<<= 8, y-=0x58b91;
210 if(x<0x08000000) x<<= 4, y-=0x2c5c8;
211 if(x<0x20000000) x<<= 2, y-=0x162e4;
212 if(x<0x40000000) x<<= 1, y-=0x0b172;
213 t=x+(x>>1); if((t&0x80000000)==0) x=t,y-=0x067cd;
214 t=x+(x>>2); if((t&0x80000000)==0) x=t,y-=0x03920;
215 t=x+(x>>3); if((t&0x80000000)==0) x=t,y-=0x01e27;
216 t=x+(x>>4); if((t&0x80000000)==0) x=t,y-=0x00f85;
217 t=x+(x>>5); if((t&0x80000000)==0) x=t,y-=0x007e1;
218 t=x+(x>>6); if((t&0x80000000)==0) x=t,y-=0x003f8;
219 t=x+(x>>7); if((t&0x80000000)==0) x=t,y-=0x001fe;
220 x=0x80000000-x;
221 y-=x>>15;
222 return y;
223}
224
225/*
226 * Integer square root routine, good for up to 32-bit values.
227 * Note that the largest square root (that of 0xffffffff) is
228 * 0xffff, so the result fits in a regular unsigned and need
229 * not be `long'.
230 *
231 * Original code from Tomas Rokicki (using a well known algorithm).
232 * This version by Chris Torek, University of Maryland.
233 *
234 * This code is in the public domain.
235 */
236unsigned int root(unsigned long v)
237{
238 register unsigned long t = 1L << 30, r = 0, s; /* 30 = 15*2 */
239
240#define STEP(k) \
241 s = t + r; \
242 r >>= 1; \
243 if (s <= v) { \
244 v -= s; \
245 r |= t; \
246 }
247 STEP(15); t >>= 2;
248 STEP(14); t >>= 2;
249 STEP(13); t >>= 2;
250 STEP(12); t >>= 2;
251 STEP(11); t >>= 2;
252 STEP(10); t >>= 2;
253 STEP(9); t >>= 2;
254 STEP(8); t >>= 2;
255 STEP(7); t >>= 2;
256 STEP(6); t >>= 2;
257 STEP(5); t >>= 2;
258 STEP(4); t >>= 2;
259 STEP(3); t >>= 2;
260 STEP(2); t >>= 2;
261 STEP(1); t >>= 2;
262 STEP(0);
263 return r;
264
265}
266
267void calc_scales(void) 204void calc_scales(void)
268{ 205{
269 unsigned int fx_log_factor = E_POW_5/half_width; 206 unsigned int fx_log_factor = E_POW_5/half_width;
270 unsigned int y,z; 207 unsigned int y,z;
271 208
209 long j;
210 long k;
211 int nh = LCD_HEIGHT - NEEDLE_TOP;
212 long nh2 = nh*nh;
213
272 for (i=1; i <= half_width; i++) 214 for (i=1; i <= half_width; i++)
273 { 215 {
274 y = (half_width/5)*fxlog(i*fx_log_factor); 216 /* analog scale */
217 y = (half_width/5)*flog(i*fx_log_factor);
275 218
276 /* better way of checking for negative values? */ 219 /* better way of checking for negative values? */
277 z = y>>16; 220 z = y>>16;
@@ -281,25 +224,15 @@ void calc_scales(void)
281 analog_db_scale[i-1] = z; 224 analog_db_scale[i-1] = z;
282 /* play nice */ 225 /* play nice */
283 rb->yield(); 226 rb->yield();
284 }
285 227
286 long j; 228 /* y values (analog needle co-ords) */
287 long k;
288 unsigned int l;
289 int nh = LCD_HEIGHT - NEEDLE_TOP;
290 long nh2 = nh*nh;
291 for (i=1; i<=half_width; i++)
292 {
293 j = i - (int)(half_width/2); 229 j = i - (int)(half_width/2);
294 k = nh2 - ( j * j ); 230 k = nh2 - ( j * j );
295 /* +1 seems to give a closer approximation */
296 l = root(k) + 1;
297 l = LCD_HEIGHT - l;
298 231
299 y_values[i-1] = l; 232 /* fsqrt+1 seems to give a closer approximation */
233 y_values[i-1] = LCD_HEIGHT - (fsqrt(k, 16)>>8) - 1;
300 rb->yield(); 234 rb->yield();
301 } 235 }
302
303} 236}
304 237
305void load_settings(void) { 238void load_settings(void) {