diff --git a/apps/action.h b/apps/action.h
index c096abf880..d3da152e35 100644
--- a/apps/action.h
+++ b/apps/action.h
@@ -187,6 +187,7 @@ enum {
ACTION_PS_NUDGE_RIGHT,
ACTION_PS_NUDGE_LEFTOFF,
ACTION_PS_NUDGE_RIGHTOFF,
+ ACTION_PS_TOGGLE_MODE,
ACTION_PS_RESET,
ACTION_PS_EXIT, /* _STD_* isnt going to work here */
diff --git a/apps/keymaps/keymap-gigabeat.c b/apps/keymaps/keymap-gigabeat.c
index 9822049214..e248e2c4db 100644
--- a/apps/keymaps/keymap-gigabeat.c
+++ b/apps/keymaps/keymap-gigabeat.c
@@ -216,8 +216,9 @@ const struct button_mapping button_context_pitchscreen[] = {
{ ACTION_PS_NUDGE_LEFTOFF, BUTTON_LEFT|BUTTON_REL, BUTTON_NONE },
{ ACTION_PS_NUDGE_RIGHT, BUTTON_RIGHT, BUTTON_NONE },
{ ACTION_PS_NUDGE_RIGHTOFF, BUTTON_RIGHT|BUTTON_REL, BUTTON_NONE },
- { ACTION_PS_RESET, BUTTON_POWER, BUTTON_NONE },
- { ACTION_PS_EXIT, BUTTON_A, BUTTON_NONE },
+ { ACTION_PS_TOGGLE_MODE, BUTTON_MENU, BUTTON_NONE },
+ { ACTION_PS_RESET, BUTTON_POWER, BUTTON_NONE },
+ { ACTION_PS_EXIT, BUTTON_A, BUTTON_NONE },
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
}; /* button_context_pitchcreen */
diff --git a/apps/keymaps/keymap-h10.c b/apps/keymaps/keymap-h10.c
index 45dde38844..b1355568ec 100644
--- a/apps/keymaps/keymap-h10.c
+++ b/apps/keymaps/keymap-h10.c
@@ -254,6 +254,7 @@ const struct button_mapping button_context_pitchscreen[] = {
{ ACTION_PS_NUDGE_LEFTOFF, BUTTON_REW|BUTTON_REL, BUTTON_NONE },
{ ACTION_PS_NUDGE_RIGHT, BUTTON_FF, BUTTON_NONE },
{ ACTION_PS_NUDGE_RIGHTOFF, BUTTON_FF|BUTTON_REL, BUTTON_NONE },
+ { ACTION_PS_TOGGLE_MODE, BUTTON_POWER, BUTTON_NONE },
{ ACTION_PS_RESET, BUTTON_PLAY, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_LEFT, BUTTON_NONE },
diff --git a/apps/keymaps/keymap-h1x0_h3x0.c b/apps/keymaps/keymap-h1x0_h3x0.c
index 7eaccc96a7..7793669d33 100644
--- a/apps/keymaps/keymap-h1x0_h3x0.c
+++ b/apps/keymaps/keymap-h1x0_h3x0.c
@@ -226,6 +226,7 @@ const struct button_mapping button_context_pitchscreen[] = {
{ ACTION_PS_NUDGE_LEFTOFF, BUTTON_LEFT|BUTTON_REL, BUTTON_NONE },
{ ACTION_PS_NUDGE_RIGHT, BUTTON_RIGHT, BUTTON_NONE },
{ ACTION_PS_NUDGE_RIGHTOFF, BUTTON_RIGHT|BUTTON_REL, BUTTON_NONE },
+ { ACTION_PS_TOGGLE_MODE, BUTTON_MODE, BUTTON_NONE },
{ ACTION_PS_RESET, BUTTON_ON, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_OFF, BUTTON_NONE },
diff --git a/apps/keymaps/keymap-ipod.c b/apps/keymaps/keymap-ipod.c
index be5429d65b..e0268e29ca 100644
--- a/apps/keymaps/keymap-ipod.c
+++ b/apps/keymaps/keymap-ipod.c
@@ -143,6 +143,7 @@ const struct button_mapping button_context_pitchscreen[] = {
{ ACTION_PS_NUDGE_LEFTOFF, BUTTON_LEFT|BUTTON_REL, BUTTON_NONE },
{ ACTION_PS_NUDGE_RIGHT, BUTTON_RIGHT, BUTTON_NONE },
{ ACTION_PS_NUDGE_RIGHTOFF, BUTTON_RIGHT|BUTTON_REL, BUTTON_NONE },
+ { ACTION_PS_TOGGLE_MODE, BUTTON_SELECT, BUTTON_NONE },
{ ACTION_PS_RESET, BUTTON_MENU, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_SELECT, BUTTON_NONE },
diff --git a/apps/keymaps/keymap-ondio.c b/apps/keymaps/keymap-ondio.c
index defc4e3762..bc92fc47ba 100644
--- a/apps/keymaps/keymap-ondio.c
+++ b/apps/keymaps/keymap-ondio.c
@@ -125,6 +125,7 @@ const struct button_mapping button_context_pitchscreen[] = {
{ ACTION_PS_NUDGE_LEFTOFF, BUTTON_LEFT|BUTTON_REL, BUTTON_NONE },
{ ACTION_PS_NUDGE_RIGHT, BUTTON_RIGHT, BUTTON_NONE },
{ ACTION_PS_NUDGE_RIGHTOFF, BUTTON_RIGHT|BUTTON_REL, BUTTON_NONE },
+ { ACTION_PS_TOGGLE_MODE, BUTTON_MENU|BUTTON_REPEAT, BUTTON_MENU },
{ ACTION_PS_RESET, BUTTON_MENU, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_OFF, BUTTON_NONE },
diff --git a/apps/keymaps/keymap-recorder.c b/apps/keymaps/keymap-recorder.c
index 718fddf888..cc09b90bfd 100644
--- a/apps/keymaps/keymap-recorder.c
+++ b/apps/keymaps/keymap-recorder.c
@@ -150,6 +150,7 @@ static const struct button_mapping button_context_pitchscreen[] = {
{ ACTION_PS_NUDGE_LEFTOFF, BUTTON_LEFT|BUTTON_REL, BUTTON_NONE },
{ ACTION_PS_NUDGE_RIGHT, BUTTON_RIGHT, BUTTON_NONE },
{ ACTION_PS_NUDGE_RIGHTOFF, BUTTON_RIGHT|BUTTON_REL, BUTTON_NONE },
+ { ACTION_PS_TOGGLE_MODE, BUTTON_F1, BUTTON_NONE },
{ ACTION_PS_RESET, BUTTON_ON, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_OFF, BUTTON_NONE },
diff --git a/apps/keymaps/keymap-x5.c b/apps/keymaps/keymap-x5.c
index 2bfa48c517..4b5b74dced 100644
--- a/apps/keymaps/keymap-x5.c
+++ b/apps/keymaps/keymap-x5.c
@@ -138,6 +138,7 @@ const struct button_mapping button_context_pitchscreen[] = {
{ ACTION_PS_NUDGE_LEFTOFF, BUTTON_LEFT|BUTTON_REL, BUTTON_NONE },
{ ACTION_PS_NUDGE_RIGHT, BUTTON_RIGHT, BUTTON_NONE },
{ ACTION_PS_NUDGE_RIGHTOFF, BUTTON_RIGHT|BUTTON_REL, BUTTON_NONE },
+ { ACTION_PS_TOGGLE_MODE, BUTTON_SELECT, BUTTON_NONE },
{ ACTION_PS_RESET, BUTTON_POWER, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_PLAY, BUTTON_NONE },
diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index 0b463f58c0..8d050a72bf 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -9374,6 +9374,34 @@
*: ""
+
+ id: LANG_SYSFONT_PITCH_UP_SEMITONE
+ desc: in wps
+ user:
+
+
+ *: "Semitone Up"
+
+
+ *: ""
+
+
+
+ id: LANG_SYSFONT_PITCH_DOWN_SEMITONE
+ desc: in wps
+ user:
+
+
+ *: "Semitone Down"
+
+
+ *: ""
+
+
id: LANG_SYSFONT_F2_MODE
desc: in wps F2 pressed
diff --git a/apps/screens.c b/apps/screens.c
index b81932b941..50f1055f90 100644
--- a/apps/screens.c
+++ b/apps/screens.c
@@ -362,11 +362,23 @@ int charging_screen(void)
#endif /* CONFIG_CHARGING && !HAVE_POWEROFF_WHILE_CHARGING */
#ifdef HAVE_PITCHSCREEN
+
+#define PITCH_MAX 2000
+#define PITCH_MIN 500
+#define PITCH_SMALL_DELTA 1
+#define PITCH_BIG_DELTA 10
+#define PITCH_NUDGE_DELTA 20
+
+#define PITCH_MODE_ABSOLUTE 1
+#define PITCH_MODE_SEMITONE -PITCH_MODE_ABSOLUTE
+
+static int pitch_mode = PITCH_MODE_ABSOLUTE; /* 1 - absolute, -1 - semitone */
+
/* returns:
0 if no key was pressed
1 if USB was connected */
-void pitch_screen_draw(struct screen *display, int pitch)
+void pitch_screen_draw(struct screen *display, int pitch, int pitch_mode)
{
unsigned char* ptr;
unsigned char buf[32];
@@ -385,14 +397,22 @@ void pitch_screen_draw(struct screen *display, int pitch)
{
/* UP: Pitch Up */
- ptr = str(LANG_SYSFONT_PITCH_UP);
+ if (pitch_mode == PITCH_MODE_ABSOLUTE) {
+ ptr = str(LANG_SYSFONT_PITCH_UP);
+ } else {
+ ptr = str(LANG_SYSFONT_PITCH_UP_SEMITONE);
+ }
display->getstringsize(ptr,&w,&h);
display->putsxy((display->width-w)/2, 0, ptr);
display->mono_bitmap(bitmap_icons_7x8[Icon_UpArrow],
display->width/2 - 3, h, 7, 8);
/* DOWN: Pitch Down */
- ptr = str(LANG_SYSFONT_PITCH_DOWN);
+ if (pitch_mode == PITCH_MODE_ABSOLUTE) {
+ ptr = str(LANG_SYSFONT_PITCH_DOWN);
+ } else {
+ ptr = str(LANG_SYSFONT_PITCH_DOWN_SEMITONE);
+ }
display->getstringsize(ptr,&w,&h);
display->putsxy((display->width-w)/2, display->height - h, ptr);
display->mono_bitmap(bitmap_icons_7x8[Icon_DownArrow],
@@ -426,10 +446,83 @@ void pitch_screen_draw(struct screen *display, int pitch)
display->update();
}
+static int pitch_increase(int pitch, int delta,
+ bool allow_cutoff, bool redraw_screens) {
+ int new_pitch;
+ int i;
+
+ if (delta < 0) {
+ if (pitch + delta >= PITCH_MIN) {
+ new_pitch = pitch + delta;
+ } else {
+ if (!allow_cutoff) {
+ return pitch;
+ }
+ new_pitch = PITCH_MIN;
+ }
+ } else if (delta > 0) {
+ if (pitch + delta <= PITCH_MAX) {
+ new_pitch = pitch + delta;
+ } else {
+ if (!allow_cutoff) {
+ return pitch;
+ }
+ new_pitch = PITCH_MAX;
+ }
+ } else {
+ /* delta == 0 -> no real change */
+ return pitch;
+ }
+ sound_set_pitch(new_pitch);
+
+ if (redraw_screens) {
+ FOR_NB_SCREENS(i)
+ pitch_screen_draw(&screens[i], pitch, pitch_mode);
+ }
+
+ return new_pitch;
+}
+
+/* Factor for changing the pitch one half tone up.
+ The exact value is 2^(1/12) = 1.05946309436
+ But we use only integer arithmetics, so take
+ rounded factor multiplied by 10^5=100,000. This is
+ enough to get the same promille values as if we
+ had used floating point (checked with a spread
+ sheet).
+ */
+#define PITCH_SEMITONE_FACTOR 105946L
+
+/* Some helpful constants. K is the scaling factor for SEMITONE.
+ N is for more accurate rounding
+ KN is K * N
+ */
+#define PITCH_K_FCT 100000UL
+#define PITCH_N_FCT 10
+#define PITCH_KN_FCT 1000000UL
+
+static int pitch_increase_semitone(int pitch, bool up) {
+ uint32_t tmp;
+ uint32_t round_fct; /* How much to scale down at the end */
+ tmp = pitch;
+ if (up) {
+ tmp = tmp * PITCH_SEMITONE_FACTOR;
+ round_fct = PITCH_K_FCT;
+ } else {
+ tmp = (tmp * PITCH_KN_FCT) / PITCH_SEMITONE_FACTOR;
+ round_fct = PITCH_N_FCT;
+ }
+ /* Scaling down with rounding */
+ tmp = (tmp + round_fct / 2) / round_fct;
+ return pitch_increase(pitch, tmp - pitch, false, false);
+}
+
bool pitch_screen(void)
{
int button;
int pitch = sound_get_pitch();
+ int new_pitch;
+ bool nudged = false;
bool exit = false;
int i;
@@ -441,64 +534,61 @@ bool pitch_screen(void)
while (!exit)
{
FOR_NB_SCREENS(i)
- pitch_screen_draw(&screens[i],pitch);
+ pitch_screen_draw(&screens[i], pitch, pitch_mode);
button = get_action(CONTEXT_PITCHSCREEN,TIMEOUT_BLOCK);
switch (button) {
case ACTION_PS_INC_SMALL:
- if ( pitch < 2000 )
- pitch++;
- sound_set_pitch(pitch);
+ if (pitch_mode == PITCH_MODE_ABSOLUTE) {
+ pitch = pitch_increase(pitch, PITCH_SMALL_DELTA, true, false);
+ } else {
+ pitch = pitch_increase_semitone(pitch, true);
+ }
break;
case ACTION_PS_INC_BIG:
- if ( pitch < 1990 )
- pitch += 10;
- else
- pitch = 2000;
- sound_set_pitch(pitch);
+ if (pitch_mode == PITCH_MODE_ABSOLUTE) {
+ pitch = pitch_increase(pitch, PITCH_BIG_DELTA, true, false);
+ }
break;
case ACTION_PS_DEC_SMALL:
- if ( pitch > 500 )
- pitch--;
- sound_set_pitch(pitch);
+ if (pitch_mode == PITCH_MODE_ABSOLUTE) {
+ pitch = pitch_increase(pitch, -PITCH_SMALL_DELTA, true, false);
+ } else {
+ pitch = pitch_increase_semitone(pitch, false);
+ }
break;
case ACTION_PS_DEC_BIG:
- if ( pitch > 510 )
- pitch -= 10;
- else
- pitch = 500;
- sound_set_pitch(pitch);
+ if (pitch_mode == PITCH_MODE_ABSOLUTE) {
+ pitch = pitch_increase(pitch, -PITCH_BIG_DELTA, true, false);
+ }
break;
case ACTION_PS_NUDGE_RIGHT:
- if ( pitch < 1980 )
- {
- pitch += 20;
- sound_set_pitch(pitch);
- FOR_NB_SCREENS(i)
- pitch_screen_draw(&screens[i],pitch);
- }
+ new_pitch = pitch_increase(pitch, PITCH_NUDGE_DELTA, false, true);
+ nudged = (new_pitch != pitch);
+ pitch = new_pitch;
break;
case ACTION_PS_NUDGE_RIGHTOFF:
- pitch -= 20;
- sound_set_pitch(pitch);
+ if (nudged) {
+ pitch = pitch_increase(pitch, -PITCH_NUDGE_DELTA, false, false);
+ }
+ nudged = false;
break;
case ACTION_PS_NUDGE_LEFT:
- if ( pitch > 520 )
- {
- pitch -= 20;
- sound_set_pitch(pitch);
- FOR_NB_SCREENS(i)
- pitch_screen_draw(&screens[i],pitch);
- }
+ new_pitch = pitch_increase(pitch, -PITCH_NUDGE_DELTA, false, true);
+ nudged = (new_pitch != pitch);
+ pitch = new_pitch;
break;
+
case ACTION_PS_NUDGE_LEFTOFF:
- pitch += 20;
- sound_set_pitch(pitch);
+ if (nudged) {
+ pitch = pitch_increase(pitch, PITCH_NUDGE_DELTA, false, false);
+ }
+ nudged = false;
break;
case ACTION_PS_RESET:
@@ -506,6 +596,10 @@ bool pitch_screen(void)
sound_set_pitch( pitch );
break;
+ case ACTION_PS_TOGGLE_MODE:
+ pitch_mode = -pitch_mode;
+ break;
+
case ACTION_PS_EXIT:
exit = true;
break;