7835a20347
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@17424 a1c6a512-1295-4272-9138-f99709370657
285 lines
8.3 KiB
C
285 lines
8.3 KiB
C
/***************************************************************************
|
|
* __________ __ ___.
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
* \/ \/ \/ \/ \/
|
|
* $Id$
|
|
*
|
|
* Copyright (C) 2002 Björn Stenberg
|
|
*
|
|
* All files in this archive are subject to the GNU General Public License.
|
|
* See the file COPYING in the source tree root for full license agreement.
|
|
*
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
* KIND, either express or implied.
|
|
*
|
|
****************************************************************************/
|
|
|
|
#include <stdbool.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include "config.h"
|
|
#include "sprintf.h"
|
|
#include "settings.h"
|
|
#include "action.h"
|
|
#include "system.h"
|
|
#include "font.h"
|
|
#include "misc.h"
|
|
#include "dsp.h"
|
|
#include "sound.h"
|
|
#include "pcmbuf.h"
|
|
#include "lang.h"
|
|
#include "icons.h"
|
|
#include "screen_access.h"
|
|
#include "screens.h"
|
|
|
|
#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 */
|
|
|
|
static void pitch_screen_draw(struct screen *display, int pitch, int pitch_mode)
|
|
{
|
|
unsigned char* ptr;
|
|
unsigned char buf[32];
|
|
int w, h;
|
|
|
|
display->clear_display();
|
|
|
|
if (display->nb_lines < 4) /* very small screen, just show the pitch value */
|
|
{
|
|
w = snprintf((char *)buf, sizeof(buf), "%s: %d.%d%%",str(LANG_PITCH),
|
|
pitch / 10, pitch % 10 );
|
|
display->putsxy((display->width-(w*display->char_width))/2,
|
|
display->nb_lines/2,buf);
|
|
}
|
|
else /* bigger screen, show everything... */
|
|
{
|
|
|
|
/* UP: Pitch Up */
|
|
if (pitch_mode == PITCH_MODE_ABSOLUTE) {
|
|
ptr = str(LANG_PITCH_UP);
|
|
} else {
|
|
ptr = str(LANG_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 */
|
|
if (pitch_mode == PITCH_MODE_ABSOLUTE) {
|
|
ptr = str(LANG_PITCH_DOWN);
|
|
} else {
|
|
ptr = str(LANG_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],
|
|
display->width/2 - 3, display->height - h*2, 7, 8);
|
|
|
|
/* RIGHT: +2% */
|
|
ptr = "+2%";
|
|
display->getstringsize(ptr,&w,&h);
|
|
display->putsxy(display->width-w, (display->height-h)/2, ptr);
|
|
display->mono_bitmap(bitmap_icons_7x8[Icon_FastForward],
|
|
display->width-w-8, (display->height-h)/2, 7, 8);
|
|
|
|
/* LEFT: -2% */
|
|
ptr = "-2%";
|
|
display->getstringsize(ptr,&w,&h);
|
|
display->putsxy(0, (display->height-h)/2, ptr);
|
|
display->mono_bitmap(bitmap_icons_7x8[Icon_FastBackward],
|
|
w+1, (display->height-h)/2, 7, 8);
|
|
|
|
/* "Pitch" */
|
|
snprintf((char *)buf, sizeof(buf), str(LANG_PITCH));
|
|
display->getstringsize(buf,&w,&h);
|
|
display->putsxy((display->width-w)/2, (display->height/2)-h, buf);
|
|
/* "XX.X%" */
|
|
snprintf((char *)buf, sizeof(buf), "%d.%d%%",
|
|
pitch / 10, pitch % 10 );
|
|
display->getstringsize(buf,&w,&h);
|
|
display->putsxy((display->width-w)/2, display->height/2, buf);
|
|
}
|
|
|
|
display->update();
|
|
}
|
|
|
|
static int pitch_increase(int pitch, int delta, bool allow_cutoff)
|
|
{
|
|
int new_pitch;
|
|
|
|
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);
|
|
|
|
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);
|
|
}
|
|
|
|
bool pitch_screen(void)
|
|
{
|
|
int button;
|
|
int pitch = sound_get_pitch();
|
|
int new_pitch, delta = 0;
|
|
bool nudged = false;
|
|
bool exit = false;
|
|
int i;
|
|
|
|
#if CONFIG_CODEC == SWCODEC
|
|
pcmbuf_set_low_latency(true);
|
|
#endif
|
|
|
|
while (!exit)
|
|
{
|
|
FOR_NB_SCREENS(i)
|
|
pitch_screen_draw(&screens[i], pitch, pitch_mode);
|
|
|
|
button = get_action(CONTEXT_PITCHSCREEN,TIMEOUT_BLOCK);
|
|
switch (button) {
|
|
case ACTION_PS_INC_SMALL:
|
|
delta = PITCH_SMALL_DELTA;
|
|
break;
|
|
|
|
case ACTION_PS_INC_BIG:
|
|
delta = PITCH_BIG_DELTA;
|
|
break;
|
|
|
|
case ACTION_PS_DEC_SMALL:
|
|
delta = -PITCH_SMALL_DELTA;
|
|
break;
|
|
|
|
case ACTION_PS_DEC_BIG:
|
|
delta = -PITCH_BIG_DELTA;
|
|
break;
|
|
|
|
case ACTION_PS_NUDGE_RIGHT:
|
|
new_pitch = pitch_increase(pitch, PITCH_NUDGE_DELTA, false);
|
|
nudged = (new_pitch != pitch);
|
|
pitch = new_pitch;
|
|
break;
|
|
|
|
case ACTION_PS_NUDGE_RIGHTOFF:
|
|
if (nudged) {
|
|
pitch = pitch_increase(pitch, -PITCH_NUDGE_DELTA, false);
|
|
}
|
|
nudged = false;
|
|
break;
|
|
|
|
case ACTION_PS_NUDGE_LEFT:
|
|
new_pitch = pitch_increase(pitch, -PITCH_NUDGE_DELTA, false);
|
|
nudged = (new_pitch != pitch);
|
|
pitch = new_pitch;
|
|
break;
|
|
|
|
case ACTION_PS_NUDGE_LEFTOFF:
|
|
if (nudged) {
|
|
pitch = pitch_increase(pitch, PITCH_NUDGE_DELTA, false);
|
|
}
|
|
nudged = false;
|
|
break;
|
|
|
|
case ACTION_PS_RESET:
|
|
pitch = 1000;
|
|
sound_set_pitch( pitch );
|
|
break;
|
|
|
|
case ACTION_PS_TOGGLE_MODE:
|
|
pitch_mode = -pitch_mode;
|
|
break;
|
|
|
|
case ACTION_PS_EXIT:
|
|
exit = true;
|
|
break;
|
|
|
|
default:
|
|
if(default_event_handler(button) == SYS_USB_CONNECTED)
|
|
return 1;
|
|
break;
|
|
}
|
|
|
|
if(delta)
|
|
{
|
|
if (pitch_mode == PITCH_MODE_ABSOLUTE) {
|
|
pitch = pitch_increase(pitch, delta, true);
|
|
} else {
|
|
pitch = pitch_increase_semitone(pitch, delta > 0 ? true:false);
|
|
}
|
|
|
|
delta = 0;
|
|
}
|
|
|
|
}
|
|
#if CONFIG_CODEC == SWCODEC
|
|
pcmbuf_set_low_latency(false);
|
|
#endif
|
|
lcd_setfont(FONT_UI);
|
|
return 0;
|
|
}
|