Index: docs/CREDITS
===================================================================
--- docs/CREDITS (revision 21112)
+++ docs/CREDITS (working copy)
@@ -466,6 +466,7 @@
Nick Sant
Michael Carr
Eric Clayton
+Nicolas Pitre
The libmad team
The wavpack team
Index: apps/action.h
===================================================================
--- apps/action.h (revision 21112)
+++ apps/action.h (working copy)
@@ -210,6 +210,8 @@
ACTION_PS_TOGGLE_MODE,
ACTION_PS_RESET,
ACTION_PS_EXIT, /* _STD_* isnt going to work here */
+ ACTION_PS_SLOWER,
+ ACTION_PS_FASTER,
/* yesno screen */
ACTION_YESNO_ACCEPT,
Index: apps/settings.c
===================================================================
--- apps/settings.c (revision 21112)
+++ apps/settings.c (working copy)
@@ -936,6 +936,7 @@
}
dsp_dither_enable(global_settings.dithering_enabled);
+ dsp_timestretch_enable(global_settings.timestretch_enabled);
#endif
#ifdef HAVE_SPDIF_POWER
Index: apps/lang/english.lang
===================================================================
--- apps/lang/english.lang (revision 21112)
+++ apps/lang/english.lang (working copy)
@@ -12468,3 +12468,37 @@
*: "Prevent Track Skipping"
+
+ id: LANG_TIMESTRETCH
+ desc: timestretch enable
+ user: core
+
+ *: none
+ swcodec: "Timestretch"
+
+
+ *: none
+ swcodec: "Timestretch"
+
+
+ *: none
+ swcodec: "Timestretch"
+
+
+
+ id: LANG_SPEED
+ desc: timestretch speed
+ user: core
+
+ *: none
+ swcodec: "Speed"
+
+
+ *: none
+ swcodec: "Speed"
+
+
+ *: none
+ swcodec: "Speed"
+
+
Index: apps/gui/pitchscreen.c
===================================================================
--- apps/gui/pitchscreen.c (revision 21112)
+++ apps/gui/pitchscreen.c (working copy)
@@ -36,12 +36,13 @@
#include "system.h"
#include "misc.h"
#include "pitchscreen.h"
+#if CONFIG_CODEC == SWCODEC
+#include "tdspeed.h"
+#endif
-#define PITCH_MODE_ABSOLUTE 1
-#define PITCH_MODE_SEMITONE -PITCH_MODE_ABSOLUTE
+
#define ICON_BORDER 12 /* icons are currently 7x8, so add ~2 pixels */
/* on both sides when drawing */
-
#define PITCH_MAX 2000
#define PITCH_MIN 500
@@ -49,9 +50,15 @@
#define PITCH_BIG_DELTA 10
#define PITCH_NUDGE_DELTA 20
+static enum
+{
+ PITCH_MODE_ABSOLUTE,
+ PITCH_MODE_SEMITONE,
+#if CONFIG_CODEC == SWCODEC
+ PITCH_MODE_TIMESTRETCH,
+#endif
+} pitch_mode = PITCH_MODE_ABSOLUTE;
-static int pitch_mode = PITCH_MODE_ABSOLUTE; /* 1 - absolute, -1 - semitone */
-
enum
{
PITCH_TOP = 0,
@@ -83,8 +90,8 @@
/* must be called before pitchscreen_draw, or within
* since it neither clears nor updates the display */
-static void pitchscreen_draw_icons (struct screen *display,
- struct viewport *parent)
+static void pitchscreen_draw_icons(struct screen *display,
+ struct viewport *parent)
{
display->set_viewport(parent);
display->mono_bitmap(bitmap_icons_7x8[Icon_UpArrow],
@@ -102,25 +109,29 @@
display->update_viewport();
}
-static void pitchscreen_draw (struct screen *display, int max_lines,
- struct viewport pitch_viewports[PITCH_ITEM_COUNT], int pitch)
+static void pitchscreen_draw(struct screen *display, int max_lines,
+ struct viewport pitch_viewports[PITCH_ITEM_COUNT],
+ int pitch
+#if CONFIG_CODEC == SWCODEC
+ ,int speed
+#endif
+ )
{
unsigned char* ptr;
- unsigned char buf[32];
- int width_val, w, h;
+ char buf[32];
+ int w, h;
bool show_lang_pitch;
- /* Hide "Pitch up/Pitch down" for a small screen */
+ /* "Pitch up/Pitch down" - hide for a small screen */
if (max_lines >= 5)
{
/* UP: Pitch Up */
display->set_viewport(&pitch_viewports[PITCH_TOP]);
- if (pitch_mode == PITCH_MODE_ABSOLUTE) {
+ if (pitch_mode == PITCH_MODE_SEMITONE)
+ ptr = str(LANG_PITCH_UP_SEMITONE);
+ else
ptr = str(LANG_PITCH_UP);
- } else {
- ptr = str(LANG_PITCH_UP_SEMITONE);
- }
- display->getstringsize(ptr,&w,&h);
+ display->getstringsize(ptr, &w, &h);
display->clear_viewport();
/* draw text */
display->putsxy((pitch_viewports[PITCH_TOP].width / 2) -
@@ -129,81 +140,125 @@
/* DOWN: Pitch Down */
display->set_viewport(&pitch_viewports[PITCH_BOTTOM]);
- if (pitch_mode == PITCH_MODE_ABSOLUTE) {
+ if (pitch_mode == PITCH_MODE_SEMITONE)
+ ptr = str(LANG_PITCH_DOWN_SEMITONE);
+ else
ptr = str(LANG_PITCH_DOWN);
- } else {
- ptr = str(LANG_PITCH_DOWN_SEMITONE);
- }
- display->getstringsize(ptr,&w,&h);
+ display->getstringsize(ptr, &w, &h);
display->clear_viewport();
/* draw text */
display->putsxy((pitch_viewports[PITCH_BOTTOM].width / 2) -
(w / 2), 0, ptr);
display->update_viewport();
}
+
+ /* Middle section */
display->set_viewport(&pitch_viewports[PITCH_MID]);
+ display->clear_viewport();
+ int width_used = 0;
- snprintf((char *)buf, sizeof(buf), "%s", str(LANG_PITCH));
- display->getstringsize(buf,&w,&h);
- /* lets hide LANG_PITCH for smaller screens */
- display->clear_viewport();
+ /* Middle section upper line - hide for a small screen */
if ((show_lang_pitch = (max_lines >= 3)))
+ {
+#if CONFIG_CODEC == SWCODEC
+ if (pitch_mode != PITCH_MODE_TIMESTRETCH)
+ {
+#endif
+ /* LANG_PITCH */
+ snprintf(buf, sizeof(buf), "%s", str(LANG_PITCH));
+#if CONFIG_CODEC == SWCODEC
+ }
+ else
+ {
+ /* Pitch:XXX.X% */
+ snprintf(buf, sizeof(buf), "%s:%d.%d%%", str(LANG_PITCH),
+ pitch / 10, pitch % 10);
+ }
+#endif
+ display->getstringsize(buf, &w, &h);
display->putsxy((pitch_viewports[PITCH_MID].width / 2) - (w / 2),
- 0, buf);
+ 0, buf);
+ if (w > width_used)
+ width_used = w;
+ }
- /* "XXX.X%" */
- snprintf((char *)buf, sizeof(buf), "%d.%d%%",
- pitch / 10, pitch % 10 );
- display->getstringsize(buf,&width_val,&h);
- display->putsxy((pitch_viewports[PITCH_MID].width / 2) - (width_val / 2),
- (show_lang_pitch? h : h/2), buf);
+ /* Middle section lower line */
+#if CONFIG_CODEC == SWCODEC
+ if (pitch_mode != PITCH_MODE_TIMESTRETCH)
+ {
+#endif
+ /* "XXX.X%" */
+ snprintf(buf, sizeof(buf), "%d.%d%%",
+ pitch / 10, pitch % 10);
+#if CONFIG_CODEC == SWCODEC
+ }
+ else
+ {
+ /* "Speed:XXX%" */
+ snprintf(buf, sizeof(buf), "%s:%d%%", str(LANG_SPEED), speed);
+ }
+#endif
+ display->getstringsize(buf, &w, &h);
+ display->putsxy((pitch_viewports[PITCH_MID].width / 2) - (w / 2),
+ (show_lang_pitch ? h : h/2), buf);
+ if (w > width_used)
+ width_used = w;
- /* What's wider? LANG_PITCH or the value?
- * Only interesting if LANG_PITCH is actually drawn */
- if (show_lang_pitch && width_val > w)
- w = width_val;
+ /* Middle section left/right labels */
+ const char *leftlabel = "-2%";
+ const char *rightlabel = "+2%";
+#if CONFIG_CODEC == SWCODEC
+ if (pitch_mode == PITCH_MODE_TIMESTRETCH)
+ {
+ leftlabel = "<<";
+ rightlabel = ">>";
+ }
+#endif
- /* Let's treat '+' and '-' as equally wide
- * This saves a getstringsize call
- * Also, it wouldn't look nice if -2% shows up, but +2% not */
- display->getstringsize("+2%",&width_val,&h);
- w += width_val*2;
- /* hide +2%/-2% for a narrow screens */
- if (w <= pitch_viewports[PITCH_MID].width)
+ /* Only display if they fit */
+ display->getstringsize(leftlabel, &w, &h);
+ width_used += w;
+ display->getstringsize(rightlabel, &w, &h);
+ width_used += w;
+
+ if (width_used <= pitch_viewports[PITCH_MID].width)
{
- /* RIGHT: +2% */
- display->putsxy(pitch_viewports[PITCH_MID].width - width_val, h /2, "+2%");
- /* LEFT: -2% */
- display->putsxy(0, h / 2, "-2%");
+ display->putsxy(0, h / 2, leftlabel);
+ display->putsxy(pitch_viewports[PITCH_MID].width - w, h /2, rightlabel);
}
display->update_viewport();
display->set_viewport(NULL);
}
-static int pitch_increase(int pitch, int delta, bool allow_cutoff)
+static int pitch_increase(int pitch, int pitch_delta, bool allow_cutoff)
{
int new_pitch;
- if (delta < 0) {
- if (pitch + delta >= PITCH_MIN) {
- new_pitch = pitch + delta;
- } else {
- if (!allow_cutoff) {
+ if (pitch_delta < 0)
+ {
+ if (pitch + pitch_delta >= PITCH_MIN)
+ new_pitch = 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) {
+ }
+ else if (pitch_delta > 0)
+ {
+ if (pitch + pitch_delta <= PITCH_MAX)
+ new_pitch = pitch + pitch_delta;
+ else
+ {
+ if (!allow_cutoff)
return pitch;
- }
new_pitch = PITCH_MAX;
}
- } else {
- /* delta == 0 -> no real change */
+ }
+ else
+ {
+ /* pitch_delta == 0 -> no real change */
return pitch;
}
sound_set_pitch(new_pitch);
@@ -234,10 +289,13 @@
uint32_t tmp;
uint32_t round_fct; /* How much to scale down at the end */
tmp = pitch;
- if (up) {
+ if (up)
+ {
tmp = tmp * PITCH_SEMITONE_FACTOR;
round_fct = PITCH_K_FCT;
- } else {
+ }
+ else
+ {
tmp = (tmp * PITCH_KN_FCT) / PITCH_SEMITONE_FACTOR;
round_fct = PITCH_N_FCT;
}
@@ -256,7 +314,12 @@
{
int button, i;
int pitch = sound_get_pitch();
- int new_pitch, delta = 0;
+#if CONFIG_CODEC == SWCODEC
+ int speed = dsp_get_timestretch();
+ int maintain_speed_pitch = speed * pitch; /* speed * pitch to maintain */
+#endif
+ int new_pitch;
+ int pitch_delta = 0;
bool nudged = false;
bool exit = false;
/* should maybe be passed per parameter later, not needed for now */
@@ -283,58 +346,118 @@
{
FOR_NB_SCREENS(i)
pitchscreen_draw(&screens[i], max_lines[i],
- pitch_viewports[i], pitch);
- button = get_action(CONTEXT_PITCHSCREEN,HZ);
- switch (button) {
+ pitch_viewports[i], pitch
+#if CONFIG_CODEC == SWCODEC
+ , speed
+#endif
+ );
+ button = get_action(CONTEXT_PITCHSCREEN, HZ);
+ switch (button)
+ {
case ACTION_PS_INC_SMALL:
- delta = PITCH_SMALL_DELTA;
+ pitch_delta = PITCH_SMALL_DELTA;
break;
case ACTION_PS_INC_BIG:
- delta = PITCH_BIG_DELTA;
+ pitch_delta = PITCH_BIG_DELTA;
break;
case ACTION_PS_DEC_SMALL:
- delta = -PITCH_SMALL_DELTA;
+ pitch_delta = -PITCH_SMALL_DELTA;
break;
case ACTION_PS_DEC_BIG:
- delta = -PITCH_BIG_DELTA;
+ pitch_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;
+#if CONFIG_CODEC == SWCODEC
+ if (pitch_mode != PITCH_MODE_TIMESTRETCH)
+ {
+#endif
+ new_pitch = pitch_increase(pitch, PITCH_NUDGE_DELTA, false);
+ nudged = (new_pitch != pitch);
+ pitch = new_pitch;
+ break;
+#if CONFIG_CODEC == SWCODEC
+ }
+
+ case ACTION_PS_FASTER:
+ if (pitch_mode == PITCH_MODE_TIMESTRETCH)
+ {
+ if (speed < SPEED_MAX)
+ {
+ speed++;
+ dsp_set_timestretch(speed);
+ maintain_speed_pitch = speed * pitch;
+ }
+ }
break;
+#endif
case ACTION_PS_NUDGE_RIGHTOFF:
- if (nudged) {
+ if (nudged)
+ {
pitch = pitch_increase(pitch, -PITCH_NUDGE_DELTA, false);
+ nudged = 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;
+#if CONFIG_CODEC == SWCODEC
+ if (pitch_mode != PITCH_MODE_TIMESTRETCH)
+ {
+#endif
+ new_pitch = pitch_increase(pitch, -PITCH_NUDGE_DELTA, false);
+ nudged = (new_pitch != pitch);
+ pitch = new_pitch;
+ break;
+#if CONFIG_CODEC == SWCODEC
+ }
+
+ case ACTION_PS_SLOWER:
+ if (pitch_mode == PITCH_MODE_TIMESTRETCH)
+ {
+ if (speed > SPEED_MIN)
+ {
+ speed--;
+ dsp_set_timestretch(speed);
+ maintain_speed_pitch = speed * pitch;
+ }
+ }
break;
+#endif
case ACTION_PS_NUDGE_LEFTOFF:
- if (nudged) {
+ if (nudged)
+ {
pitch = pitch_increase(pitch, PITCH_NUDGE_DELTA, false);
+ nudged = false;
}
- nudged = false;
break;
case ACTION_PS_RESET:
pitch = 1000;
- sound_set_pitch( pitch );
+ sound_set_pitch(pitch);
+#if CONFIG_CODEC == SWCODEC
+ speed = 100;
+ dsp_set_timestretch(speed);
+ maintain_speed_pitch = speed * pitch;
+#endif
break;
case ACTION_PS_TOGGLE_MODE:
- pitch_mode = -pitch_mode;
+ ++pitch_mode;
+#if CONFIG_CODEC == SWCODEC
+ if (dsp_timestretch_enabled())
+ {
+ if (pitch_mode > PITCH_MODE_TIMESTRETCH)
+ pitch_mode = PITCH_MODE_ABSOLUTE;
+ break;
+ }
+#endif
+ if (pitch_mode > PITCH_MODE_SEMITONE)
+ pitch_mode = PITCH_MODE_ABSOLUTE;
break;
case ACTION_PS_EXIT:
@@ -342,19 +465,32 @@
break;
default:
- if(default_event_handler(button) == SYS_USB_CONNECTED)
+ if (default_event_handler(button) == SYS_USB_CONNECTED)
return 1;
break;
}
- if(delta)
+ if (pitch_delta)
{
- if (pitch_mode == PITCH_MODE_ABSOLUTE) {
- pitch = pitch_increase(pitch, delta, true);
- } else {
- pitch = pitch_increase_semitone(pitch, delta > 0);
+ if (pitch_mode == PITCH_MODE_SEMITONE)
+ pitch = pitch_increase_semitone(pitch, pitch_delta > 0);
+ else
+ pitch = pitch_increase(pitch, pitch_delta, true);
+#if CONFIG_CODEC == SWCODEC
+ if (pitch_mode == PITCH_MODE_TIMESTRETCH)
+ {
+ /* Set speed to maintain time dimension */
+ /* i.e. increase pitch, slow down speed */
+ int new_speed = maintain_speed_pitch / pitch;
+ if (new_speed >= SPEED_MIN && new_speed <= SPEED_MAX)
+ {
+ speed = new_speed;
+ dsp_set_timestretch(speed);
+ }
}
-
- delta = 0;
+ else
+ maintain_speed_pitch = speed * pitch;
+#endif
+ pitch_delta = 0;
}
}
#if CONFIG_CODEC == SWCODEC
Index: apps/settings.h
===================================================================
--- apps/settings.h (revision 21112)
+++ apps/settings.h (working copy)
@@ -374,6 +374,7 @@
int keyclick; /* keyclick volume */
int keyclick_repeats; /* keyclick on repeats */
bool dithering_enabled;
+ bool timestretch_enabled;
#endif /* CONFIG_CODEC == SWCODEC */
#ifdef HAVE_RECORDING
Index: apps/menus/sound_menu.c
===================================================================
--- apps/menus/sound_menu.c (revision 21112)
+++ apps/menus/sound_menu.c (working copy)
@@ -1,4 +1,3 @@
-
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
@@ -32,6 +31,9 @@
#include "eq_menu.h"
#include "exported_menus.h"
#include "menu_common.h"
+#include "splash.h"
+#include "kernel.h"
+#include "dsp.h"
/***********************************/
/* SOUND MENU */
@@ -57,14 +59,14 @@
MENUITEM_SETTING(treble_cutoff, &global_settings.treble_cutoff, NULL);
#endif
MENUITEM_SETTING(balance, &global_settings.balance, NULL);
-MENUITEM_SETTING(channel_config, &global_settings.channel_config,
+MENUITEM_SETTING(channel_config, &global_settings.channel_config,
#if CONFIG_CODEC == SWCODEC
lowlatency_callback
#else
NULL
#endif
);
-MENUITEM_SETTING(stereo_width, &global_settings.stereo_width,
+MENUITEM_SETTING(stereo_width, &global_settings.stereo_width,
#if CONFIG_CODEC == SWCODEC
lowlatency_callback
#else
@@ -86,7 +88,21 @@
MAKE_MENU(crossfeed_menu,ID2P(LANG_CROSSFEED), NULL, Icon_NOICON,
&crossfeed, &crossfeed_direct_gain, &crossfeed_cross_gain,
&crossfeed_hf_attenuation, &crossfeed_hf_cutoff);
-
+
+static int timestretch_callback(int action,const struct menu_item_ex *this_item)
+{
+ switch (action)
+ {
+ case ACTION_EXIT_MENUITEM: /* on exit */
+ if (global_settings.timestretch_enabled && !dsp_timestretch_enabled())
+ splash(HZ*2, ID2P(LANG_PLEASE_REBOOT));
+ break;
+ }
+ lowlatency_callback(action, this_item);
+ return action;
+}
+ MENUITEM_SETTING(timestretch_enabled,
+ &global_settings.timestretch_enabled, timestretch_callback);
MENUITEM_SETTING(dithering_enabled,
&global_settings.dithering_enabled, lowlatency_callback);
#endif
@@ -120,7 +136,8 @@
#endif
&balance,&channel_config,&stereo_width
#if CONFIG_CODEC == SWCODEC
- ,&crossfeed_menu, &equalizer_menu, &dithering_enabled
+ ,&crossfeed_menu, &equalizer_menu, &dithering_enabled
+ ,×tretch_enabled
#endif
#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
,&loudness,&avc,&superbass,&mdb_enable,&mdb_strength
Index: apps/dsp.c
===================================================================
--- apps/dsp.c (revision 21112)
+++ apps/dsp.c (working copy)
@@ -32,22 +32,19 @@
#include "replaygain.h"
#include "misc.h"
#include "debug.h"
+#include "tdspeed.h"
+#include "buffer.h"
/* 16-bit samples are scaled based on these constants. The shift should be
* no more than 15.
*/
-#define WORD_SHIFT 12
-#define WORD_FRACBITS 27
+#define WORD_SHIFT 12
+#define WORD_FRACBITS 27
-#define NATIVE_DEPTH 16
-/* If the buffer sizes change, check the assembly code! */
-#define SAMPLE_BUF_COUNT 256
-#define RESAMPLE_BUF_COUNT (256 * 4) /* Enough for 11,025 Hz -> 44,100 Hz*/
-#define DEFAULT_GAIN 0x01000000
-#define SAMPLE_BUF_LEFT_CHANNEL 0
-#define SAMPLE_BUF_RIGHT_CHANNEL (SAMPLE_BUF_COUNT/2)
-#define RESAMPLE_BUF_LEFT_CHANNEL 0
-#define RESAMPLE_BUF_RIGHT_CHANNEL (RESAMPLE_BUF_COUNT/2)
+#define NATIVE_DEPTH 16
+/* If the small buffer size changes, check the assembly code! */
+#define SMALL_SAMPLE_BUF_COUNT 256
+#define DEFAULT_GAIN 0x01000000
/* enums to index conversion properly with stereo mode and other settings */
enum
@@ -101,7 +98,7 @@
struct resample_data resample_data; /* 08h */
int32_t clip_min; /* 18h */
int32_t clip_max; /* 1ch */
- int32_t gain; /* 20h - Note that this is in S8.23 format. */
+ int32_t gain; /* 20h - Note that this is in S8.23 format. */
/* 24h */
};
@@ -140,7 +137,7 @@
/* Typedefs keep things much neater in this case */
typedef void (*sample_input_fn_type)(int count, const char *src[],
- int32_t *dst[]);
+ int32_t *dst[]);
typedef int (*resample_fn_type)(int count, struct dsp_data *data,
int32_t *src[], int32_t *dst[]);
typedef void (*sample_output_fn_type)(int count, struct dsp_data *data,
@@ -163,6 +160,9 @@
int sample_depth;
int sample_bytes;
int stereo_mode;
+ bool tdspeed_enabled; /* User has enabled timestretch */
+ int tdspeed_percent; /* Speed % */
+ bool tdspeed_active; /* Timestretch is in use */
int frac_bits;
#ifdef HAVE_SW_TONE_CONTROLS
/* Filter struct for software bass/treble controls */
@@ -218,17 +218,32 @@
static long replaygain;
static bool crossfeed_enabled;
-#define audio_dsp (dsp_conf[CODEC_IDX_AUDIO])
-#define voice_dsp (dsp_conf[CODEC_IDX_VOICE])
+#define AUDIO_DSP (dsp_conf[CODEC_IDX_AUDIO])
+#define VOICE_DSP (dsp_conf[CODEC_IDX_VOICE])
/* The internal format is 32-bit samples, non-interleaved, stereo. This
* format is similar to the raw output from several codecs, so the amount
* of copying needed is minimized for that case.
*/
-int32_t sample_buf[SAMPLE_BUF_COUNT] IBSS_ATTR;
-static int32_t resample_buf[RESAMPLE_BUF_COUNT] IBSS_ATTR;
+#define RESAMPLE_RATIO 4 /* Enough for 11,025 Hz -> 44,100 Hz */
+static int32_t small_sample_buf[SMALL_SAMPLE_BUF_COUNT] IBSS_ATTR;
+static int32_t small_resample_buf[SMALL_SAMPLE_BUF_COUNT * RESAMPLE_RATIO] IBSS_ATTR;
+
+static int32_t *big_sample_buf = NULL;
+static int32_t *big_resample_buf = NULL;
+static int big_sample_buf_count = -1; /* -1=unknown, 0=not available */
+
+static int sample_buf_count;
+static int32_t *sample_buf;
+static int32_t *resample_buf;
+
+#define SAMPLE_BUF_LEFT_CHANNEL 0
+#define SAMPLE_BUF_RIGHT_CHANNEL (sample_buf_count/2)
+#define RESAMPLE_BUF_LEFT_CHANNEL 0
+#define RESAMPLE_BUF_RIGHT_CHANNEL (sample_buf_count/2 * RESAMPLE_RATIO)
+
#if 0
/* Clip sample to arbitrary limits where range > 0 and min + range = max */
static inline long clip_sample(int32_t sample, int32_t min, int32_t range)
@@ -260,10 +275,66 @@
void sound_set_pitch(int permille)
{
pitch_ratio = permille;
- dsp_configure(&audio_dsp, DSP_SWITCH_FREQUENCY,
- audio_dsp.codec_frequency);
+ dsp_configure(&AUDIO_DSP, DSP_SWITCH_FREQUENCY,
+ AUDIO_DSP.codec_frequency);
}
+void tdspeed_setup(struct dsp_config *dspc)
+{
+ if(dspc == &AUDIO_DSP)
+ {
+ if (dspc->tdspeed_percent == 0)
+ dspc->tdspeed_percent = 100;
+ if (!dspc->tdspeed_enabled ||
+ dspc->tdspeed_percent == 100 ||
+ big_sample_buf_count <= 0)
+ dspc->tdspeed_active = false;
+ else dspc->tdspeed_active
+ = tdspeed_init(dspc->codec_frequency == 0 ? NATIVE_FREQUENCY
+ : dspc->codec_frequency,
+ dspc->stereo_mode != STEREO_MONO,
+ dspc->tdspeed_percent);
+ }
+}
+
+void dsp_timestretch_enable(bool enable)
+{
+ if (enable)
+ {
+ /* Set up timestretch buffers on first enable */
+ if (big_sample_buf_count < 0)
+ {
+ big_sample_buf_count = SMALL_SAMPLE_BUF_COUNT * RESAMPLE_RATIO;
+ big_sample_buf = small_resample_buf;
+ big_resample_buf = (int32_t *) buffer_alloc(big_sample_buf_count * RESAMPLE_RATIO * sizeof(int32_t));
+ }
+ }
+ else
+ {
+ /* If not enabled at startup, buffers will never be available */
+ if (big_sample_buf_count < 0)
+ big_sample_buf_count = 0;
+ }
+ AUDIO_DSP.tdspeed_enabled = enable;
+ tdspeed_setup(&AUDIO_DSP);
+}
+
+void dsp_set_timestretch(int percent)
+{
+ AUDIO_DSP.tdspeed_percent = percent;
+ tdspeed_setup(&AUDIO_DSP);
+}
+
+int dsp_get_timestretch()
+{
+ return AUDIO_DSP.tdspeed_percent;
+}
+
+bool dsp_timestretch_enabled()
+{
+ return (AUDIO_DSP.tdspeed_enabled && big_sample_buf_count > 0);
+}
+
/* Convert count samples to the internal format, if needed. Updates src
* to point past the samples "consumed" and dst is set to point to the
* samples to consume. Note that for mono, dst[0] equals dst[1], as there
@@ -403,6 +474,7 @@
dsp->input_samples = sample_input_functions[convert];
}
+
#ifndef DSP_HAVE_ASM_SAMPLE_OUTPUT_MONO
/* write mono internal format to output format */
static void sample_output_mono(int count, struct dsp_data *data,
@@ -462,7 +534,7 @@
for (ch = 0; ch < data->num_channels; ch++)
{
struct dither_data * const dither = &dither_data[ch];
- int32_t *s = src[ch];
+ const int32_t *s = src[ch];
int i;
for (i = 0, d = &dst[ch]; i < count; i++, s++, d += 2)
@@ -540,7 +612,7 @@
int out = dsp->data.num_channels - 1;
- if (dsp == &audio_dsp && dither_enabled)
+ if (dsp == &AUDIO_DSP && dither_enabled)
out += 2;
dsp->output_samples = sample_output_functions[out];
@@ -565,9 +637,9 @@
/* Just initialize things and not worry too much about the relatively
* uncommon case of not being able to spit out a sample for the frame.
*/
- int32_t *s = src[ch];
+ const int32_t *s = src[ch];
int32_t last = data->resample_data.last_sample[ch];
-
+
data->resample_data.last_sample[ch] = s[count - 1];
d = dst[ch];
phase = data->resample_data.phase;
@@ -603,11 +675,10 @@
/* Rolled channel loop actually showed slightly faster. */
do
{
- /* Should always be able to output a sample for a ratio up to
- RESAMPLE_BUF_COUNT / SAMPLE_BUF_COUNT. */
- int32_t *s = src[ch];
+ /* Should always be able to output a sample for a ratio up to RESAMPLE_RATIO */
+ const int32_t *s = src[ch];
int32_t last = data->resample_data.last_sample[ch];
-
+
data->resample_data.last_sample[ch] = s[count - 1];
d = dst[ch];
phase = data->resample_data.phase;
@@ -638,7 +709,7 @@
static void resampler_new_delta(struct dsp_config *dsp)
{
- dsp->data.resample_data.delta = (unsigned long)
+ dsp->data.resample_data.delta = (unsigned long)
dsp->frequency * 65536LL / NATIVE_FREQUENCY;
if (dsp->frequency == NATIVE_FREQUENCY)
@@ -686,7 +757,7 @@
void dsp_dither_enable(bool enable)
{
- struct dsp_config *dsp = &audio_dsp;
+ struct dsp_config *dsp = &AUDIO_DSP;
dither_enabled = enable;
sample_output_new_format(dsp);
}
@@ -705,7 +776,7 @@
int32_t *coefs = &crossfeed_data.coefs[0];
int32_t gain = crossfeed_data.gain;
int32_t *di = crossfeed_data.index;
-
+
int32_t acc;
int32_t left, right;
int i;
@@ -734,7 +805,7 @@
/* Now add the attenuated direct sound and write to outputs */
buf[0][i] = FRACMUL(left, gain) + hist_r[1];
buf[1][i] = FRACMUL(right, gain) + hist_l[1];
-
+
/* Wrap delay line index if bigger than delay line size */
if (di >= delay + 13*2)
di = delay;
@@ -754,7 +825,7 @@
void dsp_set_crossfeed(bool enable)
{
crossfeed_enabled = enable;
- audio_dsp.apply_crossfeed = (enable && audio_dsp.data.num_channels > 1)
+ AUDIO_DSP.apply_crossfeed = (enable && AUDIO_DSP.data.num_channels > 1)
? apply_crossfeed : NULL;
}
@@ -815,17 +886,17 @@
dsp->data.gain = DEFAULT_GAIN;
/* Replay gain not relevant to voice */
- if (dsp == &audio_dsp && replaygain)
+ if (dsp == &AUDIO_DSP && replaygain)
{
dsp->data.gain = replaygain;
}
-
+
if (dsp->eq_process && eq_precut)
{
dsp->data.gain =
(long) (((int64_t) dsp->data.gain * eq_precut) >> 24);
}
-
+
if (dsp->data.gain == DEFAULT_GAIN)
{
dsp->data.gain = 0;
@@ -846,7 +917,7 @@
void dsp_set_eq_precut(int precut)
{
eq_precut = get_replaygain_int(precut * -10);
- set_gain(&audio_dsp);
+ set_gain(&AUDIO_DSP);
}
/**
@@ -867,10 +938,10 @@
cutoff = 0xffffffff / NATIVE_FREQUENCY * (*setting++);
q = *setting++;
gain = *setting++;
-
+
if (q == 0)
q = 1;
-
+
/* NOTE: The coef functions assume the EMAC unit is in fractional mode,
which it should be, since we're executed from the main thread. */
@@ -903,7 +974,7 @@
EQ_PEAK_SHIFT, /* peaking */
EQ_SHELF_SHIFT, /* high shelf */
};
- unsigned int channels = audio_dsp.data.num_channels;
+ unsigned int channels = AUDIO_DSP.data.num_channels;
int i;
/* filter configuration currently is 1 low shelf filter, 3 band peaking
@@ -925,14 +996,14 @@
*/
void dsp_set_eq(bool enable)
{
- audio_dsp.eq_process = enable ? eq_process : NULL;
- set_gain(&audio_dsp);
+ AUDIO_DSP.eq_process = enable ? eq_process : NULL;
+ set_gain(&AUDIO_DSP);
}
static void dsp_set_stereo_width(int value)
{
long width, straight, cross;
-
+
width = value * 0x7fffff / 100;
if (value <= 100)
@@ -1039,14 +1110,14 @@
};
if ((unsigned)value >= ARRAYLEN(channels_process_functions) ||
- audio_dsp.stereo_mode == STEREO_MONO)
+ AUDIO_DSP.stereo_mode == STEREO_MONO)
{
value = SOUND_CHAN_STEREO;
}
/* This doesn't apply to voice */
channels_mode = value;
- audio_dsp.channels_process = channels_process_functions[value];
+ AUDIO_DSP.channels_process = channels_process_functions[value];
}
#if CONFIG_CODEC == SWCODEC
@@ -1057,10 +1128,10 @@
filter_bishelf_coefs(0xffffffff/NATIVE_FREQUENCY*200,
0xffffffff/NATIVE_FREQUENCY*3500,
bass, treble, -prescale,
- audio_dsp.tone_filter.coefs);
+ AUDIO_DSP.tone_filter.coefs);
/* Sync the voice dsp coefficients */
- memcpy(&voice_dsp.tone_filter.coefs, audio_dsp.tone_filter.coefs,
- sizeof (voice_dsp.tone_filter.coefs));
+ memcpy(&VOICE_DSP.tone_filter.coefs, AUDIO_DSP.tone_filter.coefs,
+ sizeof (VOICE_DSP.tone_filter.coefs));
}
#endif
@@ -1069,7 +1140,8 @@
*/
int dsp_callback(int msg, intptr_t param)
{
- switch (msg) {
+ switch (msg)
+ {
#ifdef HAVE_SW_TONE_CONTROLS
case DSP_CALLBACK_SET_PRESCALE:
prescale = param;
@@ -1112,7 +1184,6 @@
static long last_yield;
long tick;
int written = 0;
- int samples;
#if defined(CPU_COLDFIRE)
/* set emac unit for dsp processing, and save old macsr, we're running in
@@ -1132,43 +1203,58 @@
will be preloaded to be used for the call if not. */
while (count > 0)
{
- samples = MIN(SAMPLE_BUF_COUNT/2, count);
+ int samples = MIN(sample_buf_count/2, count);
count -= samples;
dsp->input_samples(samples, src, tmp);
- if (dsp->apply_gain)
- dsp->apply_gain(samples, &dsp->data, tmp);
+ if (dsp->tdspeed_active)
+ samples = tdspeed_doit(tmp, samples);
- if (dsp->resample && (samples = resample(dsp, samples, tmp)) <= 0)
- break; /* I'm pretty sure we're downsampling here */
+ int chunk_offset = 0;
+ while (samples > 0)
+ {
+ int32_t *t2[2];
+ t2[0] = tmp[0]+chunk_offset;
+ t2[1] = tmp[1]+chunk_offset;
- if (dsp->apply_crossfeed)
- dsp->apply_crossfeed(samples, tmp);
+ int chunk = MIN(sample_buf_count/2, samples);
+ chunk_offset += chunk;
+ samples -= chunk;
- if (dsp->eq_process)
- dsp->eq_process(samples, tmp);
+ if (dsp->apply_gain)
+ dsp->apply_gain(chunk, &dsp->data, t2);
+ if (dsp->resample && (chunk = resample(dsp, chunk, t2)) <= 0)
+ break; /* I'm pretty sure we're downsampling here */
+
+ if (dsp->apply_crossfeed)
+ dsp->apply_crossfeed(chunk, t2);
+
+ if (dsp->eq_process)
+ dsp->eq_process(chunk, t2);
+
#ifdef HAVE_SW_TONE_CONTROLS
- if ((bass | treble) != 0)
- eq_filter(tmp, &dsp->tone_filter, samples,
+ if ((bass | treble) != 0)
+ eq_filter(t2, &dsp->tone_filter, chunk,
dsp->data.num_channels, FILTER_BISHELF_SHIFT);
#endif
- if (dsp->channels_process)
- dsp->channels_process(samples, tmp);
+ if (dsp->channels_process)
+ dsp->channels_process(chunk, t2);
- dsp->output_samples(samples, &dsp->data, tmp, (int16_t *)dst);
+ dsp->output_samples(chunk, &dsp->data, t2, (int16_t *)dst);
- written += samples;
- dst += samples * sizeof (int16_t) * 2;
-
- /* yield at least once each tick */
- tick = current_tick;
- if (TIME_AFTER(tick, last_yield))
- {
- last_yield = tick;
- yield();
+ written += chunk;
+ dst += chunk * sizeof (int16_t) * 2;
+
+ /* yield at least once each tick */
+ tick = current_tick;
+ if (TIME_AFTER(tick, last_yield))
+ {
+ last_yield = tick;
+ yield();
+ }
}
}
@@ -1188,6 +1274,20 @@
/* dsp_input_size MUST be called afterwards */
int dsp_output_count(struct dsp_config *dsp, int count)
{
+ if(!dsp->tdspeed_active)
+ {
+ sample_buf = small_sample_buf;
+ resample_buf = small_resample_buf;
+ sample_buf_count = SMALL_SAMPLE_BUF_COUNT;
+ }
+ else
+ {
+ sample_buf = big_sample_buf;
+ sample_buf_count = big_sample_buf_count;
+ resample_buf = big_resample_buf;
+ }
+ if(dsp->tdspeed_active)
+ count = tdspeed_est_output_size();
if (dsp->resample)
{
count = (int)(((unsigned long)count * NATIVE_FREQUENCY
@@ -1195,12 +1295,12 @@
}
/* Now we have the resampled sample count which must not exceed
- * RESAMPLE_BUF_COUNT/2 to avoid resample buffer overflow. One
+ * RESAMPLE_BUF_RIGHT_CHANNEL to avoid resample buffer overflow. One
* must call dsp_input_count() to get the correct input sample
* count.
*/
- if (count > RESAMPLE_BUF_COUNT/2)
- count = RESAMPLE_BUF_COUNT/2;
+ if (count > RESAMPLE_BUF_RIGHT_CHANNEL)
+ count = RESAMPLE_BUF_RIGHT_CHANNEL;
return count;
}
@@ -1221,6 +1321,9 @@
dsp->data.resample_data.delta) >> 16);
}
+ if(dsp->tdspeed_active)
+ count = tdspeed_est_input_size(count);
+
return count;
}
@@ -1234,7 +1337,7 @@
{
sample_input_new_format(dsp);
sample_output_new_format(dsp);
- if (dsp == &audio_dsp)
+ if (dsp == &AUDIO_DSP)
dsp_set_crossfeed(crossfeed_enabled);
}
@@ -1246,9 +1349,9 @@
switch (value)
{
case CODEC_IDX_AUDIO:
- return (intptr_t)&audio_dsp;
+ return (intptr_t)&AUDIO_DSP;
case CODEC_IDX_VOICE:
- return (intptr_t)&voice_dsp;
+ return (intptr_t)&VOICE_DSP;
default:
return (intptr_t)NULL;
}
@@ -1262,12 +1365,13 @@
if we're called from the main audio thread. Voice UI thread should
not need this feature.
*/
- if (dsp == &audio_dsp)
+ if (dsp == &AUDIO_DSP)
dsp->frequency = pitch_ratio * dsp->codec_frequency / 1000;
else
dsp->frequency = dsp->codec_frequency;
resampler_new_delta(dsp);
+ tdspeed_setup(dsp);
break;
case DSP_SET_SAMPLE_DEPTH:
@@ -1290,13 +1394,14 @@
dsp->data.output_scale = dsp->frac_bits + 1 - NATIVE_DEPTH;
sample_input_new_format(dsp);
- dither_init(dsp);
+ dither_init(dsp);
break;
case DSP_SET_STEREO_MODE:
dsp->stereo_mode = value;
dsp->data.num_channels = value == STEREO_MONO ? 1 : 2;
dsp_update_functions(dsp);
+ tdspeed_setup(dsp);
break;
case DSP_RESET:
@@ -1310,7 +1415,7 @@
dsp->data.clip_min = -((1 << WORD_FRACBITS));
dsp->codec_frequency = dsp->frequency = NATIVE_FREQUENCY;
- if (dsp == &audio_dsp)
+ if (dsp == &AUDIO_DSP)
{
track_gain = 0;
album_gain = 0;
@@ -1321,6 +1426,7 @@
dsp_update_functions(dsp);
resampler_new_delta(dsp);
+ tdspeed_setup(dsp);
break;
case DSP_FLUSH:
@@ -1328,25 +1434,26 @@
sizeof (dsp->data.resample_data));
resampler_new_delta(dsp);
dither_init(dsp);
+ tdspeed_setup(dsp);
break;
case DSP_SET_TRACK_GAIN:
- if (dsp == &audio_dsp)
+ if (dsp == &AUDIO_DSP)
dsp_set_gain_var(&track_gain, value);
break;
case DSP_SET_ALBUM_GAIN:
- if (dsp == &audio_dsp)
+ if (dsp == &AUDIO_DSP)
dsp_set_gain_var(&album_gain, value);
break;
case DSP_SET_TRACK_PEAK:
- if (dsp == &audio_dsp)
+ if (dsp == &AUDIO_DSP)
dsp_set_gain_var(&track_peak, value);
break;
case DSP_SET_ALBUM_PEAK:
- if (dsp == &audio_dsp)
+ if (dsp == &AUDIO_DSP)
dsp_set_gain_var(&album_peak, value);
break;
@@ -1403,5 +1510,5 @@
/* Store in S8.23 format to simplify calculations. */
replaygain = gain;
- set_gain(&audio_dsp);
+ set_gain(&AUDIO_DSP);
}
Index: apps/dsp.h
===================================================================
--- apps/dsp.h (revision 21112)
+++ apps/dsp.h (working copy)
@@ -164,5 +164,9 @@
int sound_get_pitch(void);
int dsp_callback(int msg, intptr_t param);
void dsp_dither_enable(bool enable);
+void dsp_timestretch_enable(bool enable);
+void dsp_set_timestretch(int percent);
+bool dsp_timestretch_enabled(void);
+int dsp_get_timestretch(void);
#endif
Index: apps/settings_list.c
===================================================================
--- apps/settings_list.c (revision 21112)
+++ apps/settings_list.c (working copy)
@@ -1181,6 +1181,10 @@
/* dithering */
OFFON_SETTING(F_SOUNDSETTING, dithering_enabled, LANG_DITHERING, false,
"dithering enabled", dsp_dither_enable),
+
+ /* timestretch */
+ OFFON_SETTING(F_SOUNDSETTING, timestretch_enabled, LANG_TIMESTRETCH, false,
+ "timestretch enabled", dsp_timestretch_enable),
#endif
#ifdef HAVE_WM8758
SOUND_SETTING(F_NO_WRAP, bass_cutoff, LANG_BASS_CUTOFF,
Index: apps/SOURCES
===================================================================
--- apps/SOURCES (revision 21112)
+++ apps/SOURCES (working copy)
@@ -233,3 +233,4 @@
#elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
keymaps/keymap-yh8xx_yh9xx.c
#endif
+tdspeed.c
Index: apps/keymaps/keymap-m3.c
===================================================================
--- apps/keymaps/keymap-m3.c (revision 21112)
+++ apps/keymaps/keymap-m3.c (working copy)
@@ -162,6 +162,8 @@
{ ACTION_PS_TOGGLE_MODE, BUTTON_MODE, BUTTON_NONE },
{ ACTION_PS_RESET, BUTTON_REC, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_PLAY, BUTTON_NONE },
+ { ACTION_PS_SLOWER, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_PS_FASTER, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE },
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
}; /* button_context_pitchscreen */
@@ -178,6 +180,8 @@
{ ACTION_PS_TOGGLE_MODE, BUTTON_RC_MODE, BUTTON_NONE },
{ ACTION_PS_RESET, BUTTON_RC_REC, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_RC_PLAY, BUTTON_NONE },
+ { ACTION_PS_SLOWER, BUTTON_RC_REW|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_PS_FASTER, BUTTON_RC_FF|BUTTON_REPEAT, BUTTON_NONE },
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
}; /* remote_button_context_pitchscreen */
Index: apps/keymaps/keymap-h1x0_h3x0.c
===================================================================
--- apps/keymaps/keymap-h1x0_h3x0.c (revision 21112)
+++ apps/keymaps/keymap-h1x0_h3x0.c (working copy)
@@ -230,6 +230,8 @@
{ ACTION_PS_RESET, BUTTON_SELECT, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_ON, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_OFF, BUTTON_NONE },
+ { ACTION_PS_SLOWER, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_PS_FASTER, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE },
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
}; /* button_context_pitchcreen */
@@ -561,6 +563,8 @@
{ ACTION_PS_RESET, BUTTON_RC_MENU, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_RC_ON, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_RC_STOP, BUTTON_NONE },
+ { ACTION_PS_SLOWER, BUTTON_RC_REW|BUTTON_REPEAT,BUTTON_NONE },
+ { ACTION_PS_FASTER, BUTTON_RC_FF|BUTTON_REPEAT, BUTTON_NONE },
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
}; /* button_context_pitchcreen */
@@ -577,6 +581,8 @@
{ ACTION_PS_RESET, BUTTON_RC_MENU, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_RC_ON, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_RC_STOP, BUTTON_NONE },
+ { ACTION_PS_SLOWER, BUTTON_RC_SOURCE|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_PS_FASTER, BUTTON_RC_BITRATE|BUTTON_REPEAT, BUTTON_NONE },
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
};
@@ -593,6 +599,8 @@
{ ACTION_PS_RESET, BUTTON_RC_MENU, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_RC_ON, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_RC_STOP, BUTTON_NONE },
+ { ACTION_PS_SLOWER, BUTTON_RC_REW|BUTTON_REPEAT,BUTTON_NONE },
+ { ACTION_PS_FASTER, BUTTON_RC_FF|BUTTON_REPEAT, BUTTON_NONE },
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
};
Index: apps/keymaps/keymap-ifp7xx.c
===================================================================
--- apps/keymaps/keymap-ifp7xx.c (revision 21112)
+++ apps/keymaps/keymap-ifp7xx.c (working copy)
@@ -132,6 +132,8 @@
{ ACTION_PS_NUDGE_RIGHTOFF, BUTTON_RIGHT|BUTTON_REL, BUTTON_NONE },
{ ACTION_PS_RESET, BUTTON_MODE, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_PLAY, BUTTON_NONE },
+ { ACTION_PS_SLOWER, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_PS_FASTER, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE },
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
}; /* button_context_pitchcreen */
Index: apps/keymaps/keymap-iaudio67.c
===================================================================
--- apps/keymaps/keymap-iaudio67.c (revision 21112)
+++ apps/keymaps/keymap-iaudio67.c (working copy)
@@ -197,6 +197,10 @@
{ ACTION_PS_RESET, BUTTON_PLAY, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_MENU, BUTTON_NONE },
+
+ { ACTION_PS_SLOWER, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_PS_FASTER, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE },
+
#endif
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD),
}; /* button_context_pitchscreen */
Index: apps/keymaps/keymap-c100.c
===================================================================
--- apps/keymaps/keymap-c100.c (revision 21112)
+++ apps/keymaps/keymap-c100.c (working copy)
@@ -173,6 +173,8 @@
{ ACTION_PS_NUDGE_RIGHTOFF, BUTTON_RIGHT|BUTTON_REL, BUTTON_NONE },
{ ACTION_PS_RESET, BUTTON_SELECT, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_POWER, BUTTON_NONE },
+ { ACTION_PS_SLOWER, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_PS_FASTER, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE },
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD),
}; /* button_context_pitchscreen */
Index: apps/keymaps/keymap-gigabeat-s.c
===================================================================
--- apps/keymaps/keymap-gigabeat-s.c (revision 21112)
+++ apps/keymaps/keymap-gigabeat-s.c (working copy)
@@ -252,6 +252,8 @@
{ ACTION_PS_TOGGLE_MODE, BUTTON_MENU, BUTTON_NONE },
{ ACTION_PS_RESET, BUTTON_PLAY, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_BACK, BUTTON_NONE },
+ { ACTION_PS_SLOWER, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_PS_FASTER, BUTTON_RIGHT|BUTTON_REPEAT,BUTTON_NONE },
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
}; /* button_context_pitchcreen */
@@ -445,6 +447,8 @@
{ ACTION_PS_RESET, BUTTON_RC_PLAY|BUTTON_REL, BUTTON_RC_PLAY },
{ ACTION_PS_TOGGLE_MODE, BUTTON_RC_PLAY|BUTTON_REPEAT, BUTTON_RC_PLAY },
{ ACTION_PS_EXIT, BUTTON_RC_DSP|BUTTON_REL, BUTTON_RC_DSP },
+ { ACTION_PS_SLOWER, BUTTON_RC_RW|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_PS_FASTER, BUTTON_RC_FF|BUTTON_REPEAT, BUTTON_NONE },
LAST_ITEM_IN_LIST
}; /* remote_button_context_pitchscreen */
Index: apps/keymaps/keymap-gigabeat.c
===================================================================
--- apps/keymaps/keymap-gigabeat.c (revision 21112)
+++ apps/keymaps/keymap-gigabeat.c (working copy)
@@ -240,6 +240,8 @@
{ ACTION_PS_TOGGLE_MODE, BUTTON_MENU, BUTTON_NONE },
{ ACTION_PS_RESET, BUTTON_A, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_POWER, BUTTON_NONE },
+ { ACTION_PS_SLOWER, BUTTON_RC_RW|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_PS_FASTER, BUTTON_RC_FF|BUTTON_REPEAT, BUTTON_NONE },
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
}; /* button_context_pitchcreen */
Index: apps/keymaps/keymap-c200.c
===================================================================
--- apps/keymaps/keymap-c200.c (revision 21112)
+++ apps/keymaps/keymap-c200.c (working copy)
@@ -207,6 +207,9 @@
{ ACTION_PS_RESET, BUTTON_SELECT, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_POWER, BUTTON_NONE },
+ { ACTION_PS_SLOWER, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_PS_FASTER, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE },
+
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD),
}; /* button_context_pitchscreen */
Index: apps/keymaps/keymap-e200.c
===================================================================
--- apps/keymaps/keymap-e200.c (revision 21112)
+++ apps/keymaps/keymap-e200.c (working copy)
@@ -203,6 +203,8 @@
{ ACTION_PS_RESET, BUTTON_SELECT, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_POWER, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_UP, BUTTON_NONE },
+ { ACTION_PS_SLOWER, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_PS_FASTER, BUTTON_RIGHT|BUTTON_REPEAT,BUTTON_NONE },
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD),
}; /* button_context_pitchscreen */
Index: apps/keymaps/keymap-m200.c
===================================================================
--- apps/keymaps/keymap-m200.c (revision 21112)
+++ apps/keymaps/keymap-m200.c (working copy)
@@ -207,6 +207,8 @@
{ ACTION_PS_RESET, BUTTON_SELECT, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_POWER, BUTTON_NONE },
+ { ACTION_PS_SLOWER, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_PS_FASTER, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE },
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD),
}; /* button_context_pitchscreen */
Index: apps/keymaps/keymap-sa9200.c
===================================================================
--- apps/keymaps/keymap-sa9200.c (revision 21112)
+++ apps/keymaps/keymap-sa9200.c (working copy)
@@ -240,6 +240,8 @@
{ ACTION_PS_TOGGLE_MODE, BUTTON_MENU, BUTTON_NONE },
{ ACTION_PS_RESET, BUTTON_RIGHT, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_POWER, BUTTON_NONE },
+ { ACTION_PS_SLOWER, BUTTON_REW|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_PS_FASTER, BUTTON_FFWD|BUTTON_REPEAT, BUTTON_NONE },
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
}; /* button_context_pitchcreen */
Index: apps/keymaps/keymap-touchscreen.c
===================================================================
--- apps/keymaps/keymap-touchscreen.c (revision 21112)
+++ apps/keymaps/keymap-touchscreen.c (working copy)
@@ -206,6 +206,8 @@
{ ACTION_PS_TOGGLE_MODE, BUTTON_BOTTOMRIGHT, BUTTON_NONE },
{ ACTION_PS_RESET, BUTTON_CENTER, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_TOPLEFT, BUTTON_NONE },
+ { ACTION_PS_SLOWER, BUTTON_MIDLEFT|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_PS_FASTER, BUTTON_MIDRIGHT|BUTTON_REPEAT, BUTTON_NONE },
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_CUSTOM2|CONTEXT_PITCHSCREEN)
}; /* button_context_pitchcreen */
Index: apps/keymaps/keymap-clip.c
===================================================================
--- apps/keymaps/keymap-clip.c (revision 21112)
+++ apps/keymaps/keymap-clip.c (working copy)
@@ -194,6 +194,8 @@
{ ACTION_PS_RESET, BUTTON_SELECT, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_POWER, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_UP, BUTTON_NONE },
+ /* { ACTION_PS_SLOWER, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, */
+ /* { ACTION_PS_FASTER, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, */
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD),
}; /* button_context_pitchscreen */
Index: apps/keymaps/keymap-h10.c
===================================================================
--- apps/keymaps/keymap-h10.c (revision 21112)
+++ apps/keymaps/keymap-h10.c (working copy)
@@ -260,6 +260,8 @@
{ ACTION_PS_TOGGLE_MODE, BUTTON_POWER, BUTTON_NONE },
{ ACTION_PS_RESET, BUTTON_PLAY, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_LEFT, BUTTON_NONE },
+ { ACTION_PS_SLOWER, BUTTON_REW|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_PS_FASTER, BUTTON_FF|BUTTON_REPEAT, BUTTON_NONE },
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD),
}; /* button_context_pitchscreen */
@@ -274,6 +276,8 @@
{ ACTION_PS_NUDGE_RIGHT, BUTTON_RC_FF, BUTTON_NONE },
{ ACTION_PS_NUDGE_RIGHTOFF, BUTTON_RC_FF|BUTTON_REL, BUTTON_NONE },
{ ACTION_PS_RESET, BUTTON_RC_PLAY, BUTTON_NONE },
+ { ACTION_PS_SLOWER, BUTTON_RC_REW|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_PS_FASTER, BUTTON_RC_FF|BUTTON_REPEAT, BUTTON_NONE },
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD),
}; /* button_context_pitchscreen */
Index: apps/keymaps/keymap-av300.c
===================================================================
--- apps/keymaps/keymap-av300.c (revision 21112)
+++ apps/keymaps/keymap-av300.c (working copy)
@@ -159,6 +159,8 @@
{ ACTION_PS_TOGGLE_MODE, BUTTON_F1, BUTTON_NONE },
{ ACTION_PS_RESET, BUTTON_ON, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_OFF, BUTTON_NONE },
+ { ACTION_PS_SLOWER, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_PS_FASTER, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE },
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
}; /* button_context_pitchcreen */
Index: apps/keymaps/keymap-ipod.c
===================================================================
--- apps/keymaps/keymap-ipod.c (revision 21112)
+++ apps/keymaps/keymap-ipod.c (working copy)
@@ -146,6 +146,8 @@
{ ACTION_PS_TOGGLE_MODE, BUTTON_PLAY, BUTTON_NONE },
{ ACTION_PS_RESET, BUTTON_MENU, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_SELECT, BUTTON_NONE },
+ { ACTION_PS_SLOWER, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_PS_FASTER, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE },
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
}; /* button_context_pitchscreen */
Index: apps/keymaps/keymap-x5.c
===================================================================
--- apps/keymaps/keymap-x5.c (revision 21112)
+++ apps/keymaps/keymap-x5.c (working copy)
@@ -151,6 +151,8 @@
{ ACTION_PS_TOGGLE_MODE, BUTTON_SELECT, BUTTON_NONE },
{ ACTION_PS_RESET, BUTTON_POWER, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_PLAY, BUTTON_NONE },
+ { ACTION_PS_SLOWER, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_PS_FASTER, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE },
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
}; /* button_context_pitchscreen */
@@ -166,6 +168,8 @@
{ ACTION_PS_NUDGE_RIGHTOFF, BUTTON_RC_FF|BUTTON_REL, BUTTON_NONE },
{ ACTION_PS_RESET, BUTTON_RC_MODE, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_RC_PLAY, BUTTON_NONE },
+ { ACTION_PS_SLOWER, BUTTON_RC_REW|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_PS_FASTER, BUTTON_RC_FF|BUTTON_REPEAT, BUTTON_NONE },
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
}; /* remote_button_context_pitchscreen */
Index: apps/keymaps/keymap-mr100.c
===================================================================
--- apps/keymaps/keymap-mr100.c (revision 21112)
+++ apps/keymaps/keymap-mr100.c (working copy)
@@ -237,6 +237,8 @@
{ ACTION_PS_TOGGLE_MODE, BUTTON_MENU, BUTTON_NONE },
{ ACTION_PS_RESET, BUTTON_DISPLAY, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_PLAY, BUTTON_NONE },
+ { ACTION_PS_SLOWER, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_PS_FASTER, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE },
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
}; /* button_context_pitchcreen */
Index: apps/keymaps/keymap-logikdax.c
===================================================================
--- apps/keymaps/keymap-logikdax.c (revision 21112)
+++ apps/keymaps/keymap-logikdax.c (working copy)
@@ -190,6 +190,9 @@
{ ACTION_PS_RESET, BUTTON_SELECT, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_MODE, BUTTON_NONE },
+ { ACTION_PS_SLOWER, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_PS_FASTER, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE },
+
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD),
}; /* button_context_pitchscreen */
Index: apps/keymaps/keymap-meizu-m6sl.c
===================================================================
--- apps/keymaps/keymap-meizu-m6sl.c (revision 21112)
+++ apps/keymaps/keymap-meizu-m6sl.c (working copy)
@@ -227,6 +227,8 @@
{ ACTION_PS_TOGGLE_MODE, BUTTON_MENU, BUTTON_NONE },
{ ACTION_PS_RESET, BUTTON_PLAY, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_PS_SLOWER, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_PS_FASTER, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE },
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
}; /* button_context_pitchcreen */
Index: apps/keymaps/keymap-fuze.c
===================================================================
--- apps/keymaps/keymap-fuze.c (revision 21112)
+++ apps/keymaps/keymap-fuze.c (working copy)
@@ -203,6 +203,8 @@
{ ACTION_PS_RESET, BUTTON_SELECT, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_HOME|BUTTON_REPEAT, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_UP, BUTTON_NONE },
+ { ACTION_PS_SLOWER, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_PS_FASTER, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE },
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD),
}; /* button_context_pitchscreen */
Index: apps/keymaps/keymap-hdd1630.c
===================================================================
--- apps/keymaps/keymap-hdd1630.c (revision 21112)
+++ apps/keymaps/keymap-hdd1630.c (working copy)
@@ -238,8 +238,10 @@
{ 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_NONE },
- { ACTION_PS_RESET, BUTTON_VIEW, BUTTON_NONE },
- { ACTION_PS_EXIT, BUTTON_POWER, BUTTON_NONE },
+ { ACTION_PS_RESET, BUTTON_VIEW, BUTTON_NONE },
+ { ACTION_PS_EXIT, BUTTON_POWER, BUTTON_NONE },
+ { ACTION_PS_SLOWER, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_PS_FASTER, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE },
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
}; /* button_context_pitchcreen */