summaryrefslogtreecommitdiff
path: root/apps/recorder/peakmeter.c
diff options
context:
space:
mode:
authorDan Everton <dan@iocaine.org>2006-03-25 13:35:31 +0000
committerDan Everton <dan@iocaine.org>2006-03-25 13:35:31 +0000
commitb66477adccfd08987e409182e15bb17e70283fae (patch)
tree46861838424afed2c2d7a6e41d429064d08f0e45 /apps/recorder/peakmeter.c
parent2b71fa855d57c1dcd19411882d545002603a9dc3 (diff)
downloadrockbox-b66477adccfd08987e409182e15bb17e70283fae.tar.gz
rockbox-b66477adccfd08987e409182e15bb17e70283fae.zip
Support the recording screen on the LCD remote. Also adds support for the peakmeter in the rremote WPS. Patch from Martin Scarratt (task 4818).
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9246 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/recorder/peakmeter.c')
-rw-r--r--apps/recorder/peakmeter.c163
1 files changed, 85 insertions, 78 deletions
diff --git a/apps/recorder/peakmeter.c b/apps/recorder/peakmeter.c
index 8bcc0688a6..ec80622367 100644
--- a/apps/recorder/peakmeter.c
+++ b/apps/recorder/peakmeter.c
@@ -33,6 +33,7 @@
33#include "lang.h" 33#include "lang.h"
34#include "peakmeter.h" 34#include "peakmeter.h"
35#include "audio.h" 35#include "audio.h"
36#include "screen_access.h"
36#ifdef CONFIG_BACKLIGHT 37#ifdef CONFIG_BACKLIGHT
37#include "backlight.h" 38#include "backlight.h"
38#endif 39#endif
@@ -48,6 +49,8 @@ static bool pm_playback = true; /* selects between playback and recording peaks
48 49
49#endif 50#endif
50 51
52struct meter_scales scales[NB_SCREENS];
53
51#if !defined(SIMULATOR) && CONFIG_CODEC != SWCODEC 54#if !defined(SIMULATOR) && CONFIG_CODEC != SWCODEC
52/* Data source */ 55/* Data source */
53static int pm_src_left = MAS_REG_DQPEAK_L; 56static int pm_src_left = MAS_REG_DQPEAK_L;
@@ -60,12 +63,6 @@ static int pm_cur_right;
60static int pm_max_left; /* maximum values between peak meter draws */ 63static int pm_max_left; /* maximum values between peak meter draws */
61static int pm_max_right; 64static int pm_max_right;
62 65
63/* Peak hold */
64static int pm_peak_left; /* buffered peak values */
65static int pm_peak_right;
66static long pm_peak_timeout_l; /* peak hold timeouts */
67static long pm_peak_timeout_r;
68
69/* Clip hold */ 66/* Clip hold */
70static bool pm_clip_left = false; /* when true a clip has occurred */ 67static bool pm_clip_left = false; /* when true a clip has occurred */
71static bool pm_clip_right = false; 68static bool pm_clip_right = false;
@@ -82,6 +79,7 @@ unsigned short peak_meter_range_min; /* minimum of range in samples */
82unsigned short peak_meter_range_max; /* maximum of range in samples */ 79unsigned short peak_meter_range_max; /* maximum of range in samples */
83static unsigned short pm_range; /* range width in samples */ 80static unsigned short pm_range; /* range width in samples */
84static bool pm_use_dbfs = true; /* true if peakmeter displays dBfs */ 81static bool pm_use_dbfs = true; /* true if peakmeter displays dBfs */
82bool level_check; /* true if peeked at peakmeter before drawing */
85static unsigned short pm_db_min = 0; /* minimum of range in 1/100 dB */ 83static unsigned short pm_db_min = 0; /* minimum of range in 1/100 dB */
86static unsigned short pm_db_max = 9000; /* maximum of range in 1/100 dB */ 84static unsigned short pm_db_max = 9000; /* maximum of range in 1/100 dB */
87static unsigned short pm_db_range = 9000; /* range width in 1/100 dB */ 85static unsigned short pm_db_range = 9000; /* range width in 1/100 dB */
@@ -140,7 +138,6 @@ static const long clip_time_out[] = {
140 138
141/* precalculated peak values that represent magical 139/* precalculated peak values that represent magical
142 dBfs values. Used to draw the scale */ 140 dBfs values. Used to draw the scale */
143#define DB_SCALE_SRC_VALUES_SIZE 12
144static const int db_scale_src_values[DB_SCALE_SRC_VALUES_SIZE] = { 141static const int db_scale_src_values[DB_SCALE_SRC_VALUES_SIZE] = {
145 32752, /* 0 db */ 142 32752, /* 0 db */
146 22784, /* - 3 db */ 143 22784, /* - 3 db */
@@ -158,15 +155,6 @@ static const int db_scale_src_values[DB_SCALE_SRC_VALUES_SIZE] = {
158 155
159static int db_scale_count = DB_SCALE_SRC_VALUES_SIZE; 156static int db_scale_count = DB_SCALE_SRC_VALUES_SIZE;
160 157
161/* if db_scale_valid is false the content of
162 db_scale_lcd_coord needs recalculation */
163static bool db_scale_valid = false;
164
165/* contains the lcd x coordinates of the magical
166 scale values in db_scale_src_values */
167static int db_scale_lcd_coord[sizeof db_scale_src_values / sizeof (int)];
168
169
170/** 158/**
171 * Calculates dB Value for the peak meter, uses peak value as input 159 * Calculates dB Value for the peak meter, uses peak value as input
172 * @param int sample - The input value 160 * @param int sample - The input value
@@ -368,7 +356,9 @@ void peak_meter_set_min(int newmin)
368 356
369 pm_db_min = calc_db(peak_meter_range_min); 357 pm_db_min = calc_db(peak_meter_range_min);
370 pm_db_range = pm_db_max - pm_db_min; 358 pm_db_range = pm_db_max - pm_db_min;
371 db_scale_valid = false; 359 int i;
360 FOR_NB_SCREENS(i)
361 scales[i].db_scale_valid = false;
372} 362}
373 363
374/** 364/**
@@ -410,7 +400,9 @@ void peak_meter_set_max(int newmax)
410 400
411 pm_db_max = calc_db(peak_meter_range_max); 401 pm_db_max = calc_db(peak_meter_range_max);
412 pm_db_range = pm_db_max - pm_db_min; 402 pm_db_range = pm_db_max - pm_db_min;
413 db_scale_valid = false; 403 int i;
404 FOR_NB_SCREENS(i)
405 scales[i].db_scale_valid = false;
414} 406}
415 407
416/** 408/**
@@ -449,8 +441,10 @@ bool peak_meter_get_use_dbfs(void)
449 */ 441 */
450void peak_meter_set_use_dbfs(bool use) 442void peak_meter_set_use_dbfs(bool use)
451{ 443{
444 int i;
452 pm_use_dbfs = use; 445 pm_use_dbfs = use;
453 db_scale_valid = false; 446 FOR_NB_SCREENS(i)
447 scales[i].db_scale_valid = false;
454} 448}
455 449
456/** 450/**
@@ -713,7 +707,8 @@ void peak_meter_peek(void)
713 break; 707 break;
714 } 708 }
715#endif 709#endif
716 710 /* check levels next time peakmeter drawn */
711 level_check = true;
717#ifdef PM_DEBUG 712#ifdef PM_DEBUG
718 peek_calls++; 713 peek_calls++;
719#endif 714#endif
@@ -816,23 +811,27 @@ unsigned short peak_meter_scale_value(unsigned short val, int meterwidth)
816 } 811 }
817 return retval; 812 return retval;
818} 813}
819 814void peak_meter_screen(struct screen *display, int x, int y, int height)
820 815{
816 peak_meter_draw(display, &scales[display->screen_type], x, y,
817 display->width, height);
818}
821/** 819/**
822 * Draws a peak meter in the specified size at the specified position. 820 * Draws a peak meter in the specified size at the specified position.
823 * @param int x - The x coordinate. 821 * @param int x - The x coordinate.
824 * Make sure that 0 <= x and x + width < LCD_WIDTH 822 * Make sure that 0 <= x and x + width < display->width
825 * @param int y - The y coordinate. 823 * @param int y - The y coordinate.
826 * Make sure that 0 <= y and y + height < LCD_HEIGHT 824 * Make sure that 0 <= y and y + height < display->height
827 * @param int width - The width of the peak meter. Note that for display 825 * @param int width - The width of the peak meter. Note that for display
828 * of clips a 3 pixel wide area is used -> 826 * of clips a 3 pixel wide area is used ->
829 * width > 3 827 * width > 3
830 * @param int height - The height of the peak meter. height > 3 828 * @param int height - The height of the peak meter. height > 3
831 */ 829 */
832void peak_meter_draw(int x, int y, int width, int height) 830void peak_meter_draw(struct screen *display, struct meter_scales *scales,
831 int x, int y, int width, int height)
833{ 832{
833 static int left_level = 0, right_level = 0;
834 int left = 0, right = 0; 834 int left = 0, right = 0;
835 static int last_left = 0, last_right = 0;
836 int meterwidth = width - 3; 835 int meterwidth = width - 3;
837 int i; 836 int i;
838 837
@@ -844,17 +843,21 @@ void peak_meter_draw(int x, int y, int width, int height)
844 /* if disabled only draw the peak meter */ 843 /* if disabled only draw the peak meter */
845 if (peak_meter_enabled) { 844 if (peak_meter_enabled) {
846 845
847 /* read the volume info from MAS */
848 left = peak_meter_read_l();
849 right = peak_meter_read_r();
850 846
851 /* scale the samples dBfs */ 847 if (level_check){
852 left = peak_meter_scale_value(left, meterwidth); 848 /* only read the volume info from MAS if peek since last read*/
853 right = peak_meter_scale_value(right, meterwidth); 849 left_level = peak_meter_read_l();
854 850 right_level = peak_meter_read_r();
855 /* if the scale has changed -> recalculate the scale 851 level_check = false;
852 }
853
854 /* scale the samples dBfs */
855 left = peak_meter_scale_value(left_level, meterwidth);
856 right = peak_meter_scale_value(right_level, meterwidth);
857
858 /*if the scale has changed -> recalculate the scale
856 (The scale becomes invalid when the range changed.) */ 859 (The scale becomes invalid when the range changed.) */
857 if (!db_scale_valid){ 860 if (!scales->db_scale_valid){
858 861
859 if (pm_use_dbfs) { 862 if (pm_use_dbfs) {
860 db_scale_count = DB_SCALE_SRC_VALUES_SIZE; 863 db_scale_count = DB_SCALE_SRC_VALUES_SIZE;
@@ -862,7 +865,7 @@ void peak_meter_draw(int x, int y, int width, int height)
862 /* find the real x-coords for predefined interesting 865 /* find the real x-coords for predefined interesting
863 dBfs values. These only are recalculated when the 866 dBfs values. These only are recalculated when the
864 scaling of the meter changed. */ 867 scaling of the meter changed. */
865 db_scale_lcd_coord[i] = 868 scales->db_scale_lcd_coord[i] =
866 peak_meter_scale_value( 869 peak_meter_scale_value(
867 db_scale_src_values[i], 870 db_scale_src_values[i],
868 meterwidth - 1); 871 meterwidth - 1);
@@ -873,7 +876,7 @@ void peak_meter_draw(int x, int y, int width, int height)
873 else { 876 else {
874 db_scale_count = 10; 877 db_scale_count = 10;
875 for (i = 0; i < db_scale_count; i++) { 878 for (i = 0; i < db_scale_count; i++) {
876 db_scale_lcd_coord[i] = 879 scales->db_scale_lcd_coord[i] =
877 (i * (MAX_PEAK / 10) - peak_meter_range_min) * 880 (i * (MAX_PEAK / 10) - peak_meter_range_min) *
878 meterwidth / pm_range; 881 meterwidth / pm_range;
879 } 882 }
@@ -881,20 +884,20 @@ void peak_meter_draw(int x, int y, int width, int height)
881 884
882 /* mark scale valid to avoid recalculating dBfs values 885 /* mark scale valid to avoid recalculating dBfs values
883 of the scale. */ 886 of the scale. */
884 db_scale_valid = true; 887 scales->db_scale_valid = true;
885 } 888 }
886 889
887 /* apply release */ 890 /* apply release */
888 left = MAX(left , last_left - pm_peak_release); 891 left = MAX(left , scales->last_left - pm_peak_release);
889 right = MAX(right, last_right - pm_peak_release); 892 right = MAX(right, scales->last_right - pm_peak_release);
890 893
891 /* reset max values after timeout */ 894 /* reset max values after timeout */
892 if (TIME_AFTER(current_tick, pm_peak_timeout_l)){ 895 if (TIME_AFTER(current_tick, scales->pm_peak_timeout_l)){
893 pm_peak_left = 0; 896 scales->pm_peak_left = 0;
894 } 897 }
895 898
896 if (TIME_AFTER(current_tick, pm_peak_timeout_r)){ 899 if (TIME_AFTER(current_tick, scales->pm_peak_timeout_r)){
897 pm_peak_right = 0; 900 scales->pm_peak_right = 0;
898 } 901 }
899 902
900 if (!pm_clip_eternal) { 903 if (!pm_clip_eternal) {
@@ -910,51 +913,51 @@ void peak_meter_draw(int x, int y, int width, int height)
910 } 913 }
911 914
912 /* check for new max values */ 915 /* check for new max values */
913 if (left > pm_peak_left) { 916 if (left > scales->pm_peak_left) {
914 pm_peak_left = left - 1; 917 scales->pm_peak_left = left - 1;
915 pm_peak_timeout_l = 918 scales->pm_peak_timeout_l =
916 current_tick + peak_time_out[pm_peak_hold]; 919 current_tick + peak_time_out[pm_peak_hold];
917 } 920 }
918 921
919 if (right > pm_peak_right) { 922 if (right > scales->pm_peak_right) {
920 pm_peak_right = right - 1; 923 scales->pm_peak_right = right - 1;
921 pm_peak_timeout_r = 924 scales->pm_peak_timeout_r =
922 current_tick + peak_time_out[pm_peak_hold]; 925 current_tick + peak_time_out[pm_peak_hold];
923 } 926 }
924 } 927 }
925 928
926 /* draw the peak meter */ 929 /* draw the peak meter */
927 lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); 930 display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
928 lcd_fillrect(x, y, width, height); 931 display->fillrect(x, y, width, height);
929 lcd_set_drawmode(DRMODE_SOLID); 932 display->set_drawmode(DRMODE_SOLID);
930 933
931 /* draw left */ 934 /* draw left */
932 lcd_fillrect (x, y, left, height / 2 - 2 ); 935 display->fillrect (x, y, left, height / 2 - 2 );
933 if (pm_peak_left > 0) { 936 if (scales->pm_peak_left > 0) {
934 lcd_vline(x + pm_peak_left, y, y + height / 2 - 2 ); 937 display->vline(x + scales->pm_peak_left, y, y + height / 2 - 2 );
935 } 938 }
936 if (pm_clip_left) { 939 if (pm_clip_left) {
937 lcd_fillrect(x + meterwidth, y, 3, height / 2 - 1); 940 display->fillrect(x + meterwidth, y, 3, height / 2 - 1);
938 } 941 }
939 942
940 /* draw right */ 943 /* draw right */
941 lcd_fillrect(x, y + height / 2 + 1, right, height / 2 - 2); 944 display->fillrect(x, y + height / 2 + 1, right, height / 2 - 2);
942 if (pm_peak_right > 0) { 945 if (scales->pm_peak_right > 0) {
943 lcd_vline( x + pm_peak_right, y + height / 2, y + height - 2); 946 display->vline( x + scales->pm_peak_right, y + height / 2, y + height - 2);
944 } 947 }
945 if (pm_clip_right) { 948 if (pm_clip_right) {
946 lcd_fillrect(x + meterwidth, y + height / 2, 3, height / 2 - 1); 949 display->fillrect(x + meterwidth, y + height / 2, 3, height / 2 - 1);
947 } 950 }
948 951
949 /* draw scale end */ 952 /* draw scale end */
950 lcd_vline(x + meterwidth, y, y + height - 2); 953 display->vline(x + meterwidth, y, y + height - 2);
951 954
952 lcd_set_drawmode(DRMODE_COMPLEMENT); 955 display->set_drawmode(DRMODE_COMPLEMENT);
953 /* draw dots for scale marks */ 956 /* draw dots for scale marks */
954 for (i = 0; i < db_scale_count; i++) { 957 for (i = 0; i < db_scale_count; i++) {
955 /* The x-coordinates of interesting scale mark points 958 /* The x-coordinates of interesting scale mark points
956 have been calculated before */ 959 have been calculated before */
957 lcd_drawpixel(db_scale_lcd_coord[i], y + height / 2 - 1); 960 display->drawpixel(scales->db_scale_lcd_coord[i], y + height / 2 - 1);
958 } 961 }
959 962
960#ifdef HAVE_RECORDING 963#ifdef HAVE_RECORDING
@@ -988,25 +991,25 @@ void peak_meter_draw(int x, int y, int width, int height)
988 if (trig_status != TRIG_OFF) { 991 if (trig_status != TRIG_OFF) {
989 int start_trigx, stop_trigx, ycenter; 992 int start_trigx, stop_trigx, ycenter;
990 993
991 lcd_set_drawmode(DRMODE_SOLID); 994 display->set_drawmode(DRMODE_SOLID);
992 ycenter = y + height / 2; 995 ycenter = y + height / 2;
993 /* display threshold value */ 996 /* display threshold value */
994 start_trigx = x+peak_meter_scale_value(trig_strt_threshold,meterwidth); 997 start_trigx = x+peak_meter_scale_value(trig_strt_threshold,meterwidth);
995 lcd_vline(start_trigx, ycenter - 2, ycenter); 998 display->vline(start_trigx, ycenter - 2, ycenter);
996 start_trigx ++; 999 start_trigx ++;
997 if (start_trigx < LCD_WIDTH) lcd_drawpixel(start_trigx, ycenter - 1); 1000 if (start_trigx < display->width ) display->drawpixel(start_trigx, ycenter - 1);
998 1001
999 stop_trigx = x + peak_meter_scale_value(trig_stp_threshold,meterwidth); 1002 stop_trigx = x + peak_meter_scale_value(trig_stp_threshold,meterwidth);
1000 lcd_vline(stop_trigx, ycenter - 2, ycenter); 1003 display->vline(stop_trigx, ycenter - 2, ycenter);
1001 if (stop_trigx > 0) lcd_drawpixel(stop_trigx - 1, ycenter - 1); 1004 if (stop_trigx > 0) display->drawpixel(stop_trigx - 1, ycenter - 1);
1002 } 1005 }
1003#endif /*HAVE_RECORDING*/ 1006#endif /*HAVE_RECORDING*/
1004 1007
1005#ifdef PM_DEBUG 1008#ifdef PM_DEBUG
1006 /* display a bar to show how many calls to peak_meter_peek 1009 /* display a bar to show how many calls to peak_meter_peek
1007 have ocurred since the last display */ 1010 have ocurred since the last display */
1008 lcd_set_drawmode(DRMODE_COMPLEMENT); 1011 display->set_drawmode(DRMODE_COMPLEMENT);
1009 lcd_fillrect(x, y, tmp, 3); 1012 display->fillrect(x, y, tmp, 3);
1010 1013
1011 if (tmp < PEEKS_PER_DRAW_SIZE) { 1014 if (tmp < PEEKS_PER_DRAW_SIZE) {
1012 peeks_per_redraw[tmp]++; 1015 peeks_per_redraw[tmp]++;
@@ -1019,14 +1022,14 @@ void peak_meter_draw(int x, int y, int width, int height)
1019 1022
1020 /* display a bar to show how many ticks have passed since 1023 /* display a bar to show how many ticks have passed since
1021 the last redraw */ 1024 the last redraw */
1022 lcd_fillrect(x, y + height / 2, current_tick - pm_tick, 2); 1025 display->fillrect(x, y + height / 2, current_tick - pm_tick, 2);
1023 pm_tick = current_tick; 1026 pm_tick = current_tick;
1024#endif 1027#endif
1025 1028
1026 last_left = left; 1029 scales->last_left = left;
1027 last_right = right; 1030 scales->last_right = right;
1028 1031
1029 lcd_set_drawmode(DRMODE_SOLID); 1032 display->set_drawmode(DRMODE_SOLID);
1030} 1033}
1031 1034
1032#ifdef HAVE_RECORDING 1035#ifdef HAVE_RECORDING
@@ -1171,11 +1174,12 @@ void peak_meter_draw_trig(int xpos, int ypos)
1171} 1174}
1172#endif 1175#endif
1173 1176
1174int peak_meter_draw_get_btn(int x, int y, int width, int height) 1177int peak_meter_draw_get_btn(int x, int y, int height)
1175{ 1178{
1176 int button = BUTTON_NONE; 1179 int button = BUTTON_NONE;
1177 long next_refresh = current_tick; 1180 long next_refresh = current_tick;
1178 long next_big_refresh = current_tick + HZ / 10; 1181 long next_big_refresh = current_tick + HZ / 10;
1182 int i;
1179#ifndef SIMULATOR 1183#ifndef SIMULATOR
1180 bool highperf = !ata_disk_is_active(); 1184 bool highperf = !ata_disk_is_active();
1181#else 1185#else
@@ -1196,8 +1200,11 @@ int peak_meter_draw_get_btn(int x, int y, int width, int height)
1196 sleep(0); /* Sleep until end of current tick. */ 1200 sleep(0); /* Sleep until end of current tick. */
1197 } 1201 }
1198 if (TIME_AFTER(current_tick, next_refresh)) { 1202 if (TIME_AFTER(current_tick, next_refresh)) {
1199 peak_meter_draw(x, y, width, height); 1203 FOR_NB_SCREENS(i)
1200 lcd_update_rect(x, y, width, height); 1204 {
1205 peak_meter_screen(&screens[i], x, y, height);
1206 screens[i].update_rect(x, y, screens[i].width, height);
1207 }
1201 next_refresh += HZ / PEAK_METER_FPS; 1208 next_refresh += HZ / PEAK_METER_FPS;
1202 dopeek = true; 1209 dopeek = true;
1203 } 1210 }