1
0
Fork 0
forked from len0rd/rockbox
foxbox/apps/gui/pitchscreen.c
Daniel Stenberg 2acc0ac542 Updated our source code header to explicitly mention that we are GPL v2 or
later. We still need to hunt down snippets used that are not. 1324 modified
files...
http://www.rockbox.org/mail/archive/rockbox-dev-archive-2008-06/0060.shtml


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@17847 a1c6a512-1295-4272-9138-f99709370657
2008-06-28 18:10:04 +00:00

287 lines
8.4 KiB
C

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2002 Björn Stenberg
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* 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;
}