forked from len0rd/rockbox
Something horrible happened with binsize, so revert FS#8894 completely (for now).
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@18449 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
1adf5f27af
commit
4bb8fd286b
11 changed files with 5 additions and 432 deletions
|
@ -201,4 +201,3 @@ keymaps/keymap-hdd1630.c
|
||||||
#elif CONFIG_KEYPAD == IAUDIO67_PAD
|
#elif CONFIG_KEYPAD == IAUDIO67_PAD
|
||||||
keymaps/keymap-iaudio67.c
|
keymaps/keymap-iaudio67.c
|
||||||
#endif
|
#endif
|
||||||
tdspeed.c
|
|
||||||
|
|
68
apps/dsp.c
68
apps/dsp.c
|
@ -32,7 +32,6 @@
|
||||||
#include "replaygain.h"
|
#include "replaygain.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "tdspeed.h"
|
|
||||||
|
|
||||||
/* 16-bit samples are scaled based on these constants. The shift should be
|
/* 16-bit samples are scaled based on these constants. The shift should be
|
||||||
* no more than 15.
|
* no more than 15.
|
||||||
|
@ -42,14 +41,8 @@
|
||||||
|
|
||||||
#define NATIVE_DEPTH 16
|
#define NATIVE_DEPTH 16
|
||||||
/* If the buffer sizes change, check the assembly code! */
|
/* If the buffer sizes change, check the assembly code! */
|
||||||
#define SMALL_SAMPLE_BUF_COUNT 256
|
#define SAMPLE_BUF_COUNT 256
|
||||||
#define SMALL_RESAMPLE_BUF_COUNT (256 * 4) /* Enough for 11,025 Hz -> 44,100 Hz*/
|
#define RESAMPLE_BUF_COUNT (256 * 4) /* Enough for 11,025 Hz -> 44,100 Hz*/
|
||||||
#define BIG_SAMPLE_BUF_COUNT 4096
|
|
||||||
#define BIG_RESAMPLE_BUF_COUNT (4096 * 4) /* Enough for 11,025 Hz -> 44,100 Hz*/
|
|
||||||
int sample_buf_count;
|
|
||||||
int resample_buf_count;
|
|
||||||
#define SAMPLE_BUF_COUNT sample_buf_count
|
|
||||||
#define RESAMPLE_BUF_COUNT resample_buf_count
|
|
||||||
#define DEFAULT_GAIN 0x01000000
|
#define DEFAULT_GAIN 0x01000000
|
||||||
#define SAMPLE_BUF_LEFT_CHANNEL 0
|
#define SAMPLE_BUF_LEFT_CHANNEL 0
|
||||||
#define SAMPLE_BUF_RIGHT_CHANNEL (SAMPLE_BUF_COUNT/2)
|
#define SAMPLE_BUF_RIGHT_CHANNEL (SAMPLE_BUF_COUNT/2)
|
||||||
|
@ -170,8 +163,6 @@ struct dsp_config
|
||||||
int sample_depth;
|
int sample_depth;
|
||||||
int sample_bytes;
|
int sample_bytes;
|
||||||
int stereo_mode;
|
int stereo_mode;
|
||||||
bool tdspeed_active;
|
|
||||||
int tdspeed_factor; /* % */
|
|
||||||
int frac_bits;
|
int frac_bits;
|
||||||
#ifdef HAVE_SW_TONE_CONTROLS
|
#ifdef HAVE_SW_TONE_CONTROLS
|
||||||
/* Filter struct for software bass/treble controls */
|
/* Filter struct for software bass/treble controls */
|
||||||
|
@ -235,12 +226,8 @@ static bool crossfeed_enabled;
|
||||||
* of copying needed is minimized for that case.
|
* of copying needed is minimized for that case.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int32_t small_sample_buf[SMALL_SAMPLE_BUF_COUNT] IBSS_ATTR;
|
int32_t sample_buf[SAMPLE_BUF_COUNT] IBSS_ATTR;
|
||||||
static int32_t small_resample_buf[SMALL_RESAMPLE_BUF_COUNT] IBSS_ATTR;
|
static int32_t resample_buf[RESAMPLE_BUF_COUNT] IBSS_ATTR;
|
||||||
int32_t big_sample_buf[BIG_SAMPLE_BUF_COUNT];
|
|
||||||
static int32_t big_resample_buf[BIG_RESAMPLE_BUF_COUNT];
|
|
||||||
int32_t *sample_buf;
|
|
||||||
static int32_t *resample_buf;
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* Clip sample to arbitrary limits where range > 0 and min + range = max */
|
/* Clip sample to arbitrary limits where range > 0 and min + range = max */
|
||||||
|
@ -277,30 +264,6 @@ void sound_set_pitch(int permille)
|
||||||
audio_dsp.codec_frequency);
|
audio_dsp.codec_frequency);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tdspeed_setup(struct dsp_config *dspc)
|
|
||||||
{
|
|
||||||
if(dspc == &dsp_conf[CODEC_IDX_AUDIO]) {
|
|
||||||
#if 0
|
|
||||||
mylog("tdspeed_setup: CODEC_IDX_AUDIO, factor %d, %d, %d\n",
|
|
||||||
dspc->tdspeed_factor, dspc->codec_frequency,
|
|
||||||
dspc->stereo_mode != STEREO_MONO);
|
|
||||||
#endif
|
|
||||||
if(dspc->tdspeed_factor == 0 || dspc->tdspeed_factor == 100)
|
|
||||||
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_factor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void dsp_set_speed(int percent)
|
|
||||||
{
|
|
||||||
dsp_conf[CODEC_IDX_AUDIO].tdspeed_factor = percent;
|
|
||||||
tdspeed_setup(&dsp_conf[CODEC_IDX_AUDIO]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Convert count samples to the internal format, if needed. Updates src
|
/* 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
|
* 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
|
* samples to consume. Note that for mono, dst[0] equals dst[1], as there
|
||||||
|
@ -1174,9 +1137,6 @@ int dsp_process(struct dsp_config *dsp, char *dst, const char *src[], int count)
|
||||||
|
|
||||||
dsp->input_samples(samples, src, tmp);
|
dsp->input_samples(samples, src, tmp);
|
||||||
|
|
||||||
if(dsp->tdspeed_active)
|
|
||||||
samples = tdspeed_doit(tmp, samples);
|
|
||||||
|
|
||||||
if (dsp->apply_gain)
|
if (dsp->apply_gain)
|
||||||
dsp->apply_gain(samples, &dsp->data, tmp);
|
dsp->apply_gain(samples, &dsp->data, tmp);
|
||||||
|
|
||||||
|
@ -1228,19 +1188,6 @@ int dsp_process(struct dsp_config *dsp, char *dst, const char *src[], int count)
|
||||||
/* dsp_input_size MUST be called afterwards */
|
/* dsp_input_size MUST be called afterwards */
|
||||||
int dsp_output_count(struct dsp_config *dsp, int count)
|
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;
|
|
||||||
resample_buf_count = SMALL_RESAMPLE_BUF_COUNT;
|
|
||||||
} else {
|
|
||||||
sample_buf = big_sample_buf;
|
|
||||||
resample_buf = big_resample_buf;
|
|
||||||
sample_buf_count = BIG_SAMPLE_BUF_COUNT;
|
|
||||||
resample_buf_count = BIG_RESAMPLE_BUF_COUNT;
|
|
||||||
}
|
|
||||||
if(dsp->tdspeed_active)
|
|
||||||
count = tdspeed_est_output_size(count);
|
|
||||||
if (dsp->resample)
|
if (dsp->resample)
|
||||||
{
|
{
|
||||||
count = (int)(((unsigned long)count * NATIVE_FREQUENCY
|
count = (int)(((unsigned long)count * NATIVE_FREQUENCY
|
||||||
|
@ -1274,9 +1221,6 @@ int dsp_input_count(struct dsp_config *dsp, int count)
|
||||||
dsp->data.resample_data.delta) >> 16);
|
dsp->data.resample_data.delta) >> 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dsp->tdspeed_active)
|
|
||||||
count = tdspeed_est_input_size(count);
|
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1324,7 +1268,6 @@ intptr_t dsp_configure(struct dsp_config *dsp, int setting, intptr_t value)
|
||||||
dsp->frequency = dsp->codec_frequency;
|
dsp->frequency = dsp->codec_frequency;
|
||||||
|
|
||||||
resampler_new_delta(dsp);
|
resampler_new_delta(dsp);
|
||||||
tdspeed_setup(dsp);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DSP_SET_SAMPLE_DEPTH:
|
case DSP_SET_SAMPLE_DEPTH:
|
||||||
|
@ -1354,7 +1297,6 @@ intptr_t dsp_configure(struct dsp_config *dsp, int setting, intptr_t value)
|
||||||
dsp->stereo_mode = value;
|
dsp->stereo_mode = value;
|
||||||
dsp->data.num_channels = value == STEREO_MONO ? 1 : 2;
|
dsp->data.num_channels = value == STEREO_MONO ? 1 : 2;
|
||||||
dsp_update_functions(dsp);
|
dsp_update_functions(dsp);
|
||||||
tdspeed_setup(dsp);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DSP_RESET:
|
case DSP_RESET:
|
||||||
|
@ -1379,7 +1321,6 @@ intptr_t dsp_configure(struct dsp_config *dsp, int setting, intptr_t value)
|
||||||
|
|
||||||
dsp_update_functions(dsp);
|
dsp_update_functions(dsp);
|
||||||
resampler_new_delta(dsp);
|
resampler_new_delta(dsp);
|
||||||
tdspeed_setup(dsp);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DSP_FLUSH:
|
case DSP_FLUSH:
|
||||||
|
@ -1387,7 +1328,6 @@ intptr_t dsp_configure(struct dsp_config *dsp, int setting, intptr_t value)
|
||||||
sizeof (dsp->data.resample_data));
|
sizeof (dsp->data.resample_data));
|
||||||
resampler_new_delta(dsp);
|
resampler_new_delta(dsp);
|
||||||
dither_init(dsp);
|
dither_init(dsp);
|
||||||
tdspeed_setup(dsp);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DSP_SET_TRACK_GAIN:
|
case DSP_SET_TRACK_GAIN:
|
||||||
|
|
|
@ -165,6 +165,5 @@ void sound_set_pitch(int r);
|
||||||
int sound_get_pitch(void);
|
int sound_get_pitch(void);
|
||||||
int dsp_callback(int msg, intptr_t param);
|
int dsp_callback(int msg, intptr_t param);
|
||||||
void dsp_dither_enable(bool enable);
|
void dsp_dither_enable(bool enable);
|
||||||
void dsp_set_speed(int speed);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -12037,17 +12037,3 @@
|
||||||
recording: ""
|
recording: ""
|
||||||
</voice>
|
</voice>
|
||||||
</phrase>
|
</phrase>
|
||||||
<phrase>
|
|
||||||
id: LANG_SPEED
|
|
||||||
desc: time-domain speed compress/stretch
|
|
||||||
user:
|
|
||||||
<source>
|
|
||||||
*: "Speed"
|
|
||||||
</source>
|
|
||||||
<dest>
|
|
||||||
*: "Speed"
|
|
||||||
</dest>
|
|
||||||
<voice>
|
|
||||||
*: "Speed"
|
|
||||||
</voice>
|
|
||||||
</phrase>
|
|
||||||
|
|
|
@ -89,8 +89,6 @@ MENUITEM_SETTING(stereo_width, &global_settings.stereo_width,
|
||||||
|
|
||||||
MENUITEM_SETTING(dithering_enabled,
|
MENUITEM_SETTING(dithering_enabled,
|
||||||
&global_settings.dithering_enabled, lowlatency_callback);
|
&global_settings.dithering_enabled, lowlatency_callback);
|
||||||
MENUITEM_SETTING(sound_speed, &global_settings.sound_speed,
|
|
||||||
lowlatency_callback);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
|
#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
|
||||||
|
@ -118,7 +116,7 @@ MAKE_MENU(sound_settings, ID2P(LANG_SOUND_SETTINGS), NULL, Icon_Audio,
|
||||||
#endif
|
#endif
|
||||||
&balance,&channel_config,&stereo_width
|
&balance,&channel_config,&stereo_width
|
||||||
#if CONFIG_CODEC == SWCODEC
|
#if CONFIG_CODEC == SWCODEC
|
||||||
,&crossfeed_menu, &equalizer_menu, &dithering_enabled, &sound_speed
|
,&crossfeed_menu, &equalizer_menu, &dithering_enabled
|
||||||
#endif
|
#endif
|
||||||
#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
|
#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
|
||||||
,&loudness,&avc,&superbass,&mdb_enable,&mdb_strength
|
,&loudness,&avc,&superbass,&mdb_enable,&mdb_strength
|
||||||
|
|
|
@ -913,7 +913,6 @@ void settings_apply(bool read_disk)
|
||||||
}
|
}
|
||||||
|
|
||||||
dsp_dither_enable(global_settings.dithering_enabled);
|
dsp_dither_enable(global_settings.dithering_enabled);
|
||||||
dsp_set_speed(global_settings.sound_speed);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_SPDIF_POWER
|
#ifdef HAVE_SPDIF_POWER
|
||||||
|
|
|
@ -633,7 +633,6 @@ struct user_settings
|
||||||
int eq_band4_gain; /* +/- dB */
|
int eq_band4_gain; /* +/- dB */
|
||||||
|
|
||||||
bool dithering_enabled;
|
bool dithering_enabled;
|
||||||
int sound_speed;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1106,9 +1106,6 @@ const struct settings_list settings[] = {
|
||||||
/* dithering */
|
/* dithering */
|
||||||
OFFON_SETTING(F_SOUNDSETTING, dithering_enabled, LANG_DITHERING, false,
|
OFFON_SETTING(F_SOUNDSETTING, dithering_enabled, LANG_DITHERING, false,
|
||||||
"dithering enabled", dsp_dither_enable),
|
"dithering enabled", dsp_dither_enable),
|
||||||
INT_SETTING(0, sound_speed, LANG_SPEED, 100, "speed",
|
|
||||||
UNIT_INT, 35, 250, 5,
|
|
||||||
NULL, NULL, dsp_set_speed),
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_WM8758
|
#ifdef HAVE_WM8758
|
||||||
SOUND_SETTING(F_NO_WRAP, bass_cutoff, LANG_BASS_CUTOFF,
|
SOUND_SETTING(F_NO_WRAP, bass_cutoff, LANG_BASS_CUTOFF,
|
||||||
|
|
334
apps/tdspeed.c
334
apps/tdspeed.c
|
@ -1,334 +0,0 @@
|
||||||
/*
|
|
||||||
* Audio time domain speed scaling / time compression/stretch.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2006 by Nicolas Pitre <nico@cam.org>
|
|
||||||
*
|
|
||||||
* Modified by Stéphane Doyon to adapt to Rockbox
|
|
||||||
* Copyright (C) 2006-2007 by Stéphane Doyon <s.doyon@videotron.ca>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License version 2 as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "system.h"
|
|
||||||
#include "tdspeed.h"
|
|
||||||
|
|
||||||
#define mylog(...)
|
|
||||||
#define assert(...)
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
#define assert(cond) \
|
|
||||||
if(!(cond)) { \
|
|
||||||
badlog("Assertion failed in %s at line %d: %s\n", \
|
|
||||||
__FUNCTION__, __LINE__, #cond); \
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define MIN_RATE 8000
|
|
||||||
#define MAX_RATE 48000 /* double buffer for double rate */
|
|
||||||
#define MIN_FACTOR 35
|
|
||||||
#define MAX_FACTOR 250
|
|
||||||
|
|
||||||
//#define FIXED_BUFSIZE 3072 /* 48KHz factor 3.0 */
|
|
||||||
#define FIXED_BUFSIZE 3524 /* worse seen, not sure how to calc */
|
|
||||||
|
|
||||||
struct tdspeed_state_s {
|
|
||||||
bool stereo;
|
|
||||||
int shift_max; /* maximum displacement on a frame */
|
|
||||||
int src_step; /* source window pace */
|
|
||||||
int dst_step; /* destination window pace */
|
|
||||||
int dst_order; /* power of two for dst_step */
|
|
||||||
int ovl_shift; /* overlap buffer frame shift */
|
|
||||||
int ovl_size; /* overlap buffer used size */
|
|
||||||
int ovl_space; /* overlap buffer size */
|
|
||||||
int32_t *ovl_buff[2]; /* overlap buffer */
|
|
||||||
};
|
|
||||||
static struct tdspeed_state_s tdspeed_state;
|
|
||||||
|
|
||||||
static int32_t overlap_buffer[2][FIXED_BUFSIZE];
|
|
||||||
static int32_t outbuf[2][TDSPEED_OUTBUFSIZE];
|
|
||||||
|
|
||||||
bool tdspeed_init(int samplerate, bool stereo, int factor)
|
|
||||||
{
|
|
||||||
struct tdspeed_state_s *st = &tdspeed_state;
|
|
||||||
int src_frame_sz;
|
|
||||||
|
|
||||||
if(factor == 100)
|
|
||||||
return false;
|
|
||||||
if (samplerate < MIN_RATE || samplerate > MAX_RATE)
|
|
||||||
return false;
|
|
||||||
if(factor <MIN_FACTOR || factor > MAX_FACTOR)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
st->stereo = !!stereo;
|
|
||||||
|
|
||||||
#define MINFREQ 100
|
|
||||||
st->dst_step = samplerate / MINFREQ;
|
|
||||||
|
|
||||||
if (factor > 100)
|
|
||||||
st->dst_step = st->dst_step *100 /factor;
|
|
||||||
st->dst_order = 1;
|
|
||||||
|
|
||||||
while (st->dst_step >>= 1)
|
|
||||||
st->dst_order++;
|
|
||||||
st->dst_step = (1 << st->dst_order);
|
|
||||||
st->src_step = st->dst_step * factor /100;
|
|
||||||
st->shift_max = (st->dst_step > st->src_step) ? st->dst_step : st->src_step;
|
|
||||||
|
|
||||||
src_frame_sz = st->shift_max + st->dst_step;
|
|
||||||
if (st->dst_step > st->src_step)
|
|
||||||
src_frame_sz += st->dst_step - st->src_step;
|
|
||||||
st->ovl_space = ((src_frame_sz - 2)/st->src_step) * st->src_step
|
|
||||||
+ src_frame_sz;
|
|
||||||
if (st->src_step > st->dst_step)
|
|
||||||
st->ovl_space += 2*st->src_step - st->dst_step;
|
|
||||||
|
|
||||||
mylog(
|
|
||||||
"shift_max %d, src_step %d, dst_step %d, dst_order %d, src_frame_sz %d, ovl_space %d\n",
|
|
||||||
st->shift_max, st->src_step, st->dst_step, st->dst_order, src_frame_sz, st->ovl_space);
|
|
||||||
|
|
||||||
assert(st->ovl_space <= FIXED_BUFSIZE);
|
|
||||||
|
|
||||||
st->ovl_size = 0;
|
|
||||||
st->ovl_shift = 0;
|
|
||||||
|
|
||||||
st->ovl_buff[0] = overlap_buffer[0];
|
|
||||||
if(stereo)
|
|
||||||
st->ovl_buff[1] = overlap_buffer[1];
|
|
||||||
else st->ovl_buff[1] = st->ovl_buff[0];
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tdspeed_apply(int32_t *buf_out[2], int32_t *buf_in[2], int data_len,
|
|
||||||
int last, int out_size)
|
|
||||||
/* data_len in samples */
|
|
||||||
{
|
|
||||||
struct tdspeed_state_s *st = &tdspeed_state;
|
|
||||||
int32_t *curr, *prev, *dest[2], *d;
|
|
||||||
int i, j, next_frame, prev_frame, shift, src_frame_sz;
|
|
||||||
bool stereo = buf_in[0] != buf_in[1];
|
|
||||||
assert(stereo == st->stereo);
|
|
||||||
|
|
||||||
src_frame_sz = st->shift_max + st->dst_step;
|
|
||||||
if (st->dst_step > st->src_step)
|
|
||||||
src_frame_sz += st->dst_step - st->src_step;
|
|
||||||
|
|
||||||
/* deal with overlap data first, if any */
|
|
||||||
if (st->ovl_size) {
|
|
||||||
int have, copy, steps;
|
|
||||||
have = st->ovl_size;
|
|
||||||
if (st->ovl_shift > 0)
|
|
||||||
have -= st->ovl_shift;
|
|
||||||
/* append just enough data to have all of the overlap buffer consumed*/
|
|
||||||
steps = (have - 1) / st->src_step;
|
|
||||||
copy = steps * st->src_step + src_frame_sz - have;
|
|
||||||
if (copy < src_frame_sz - st->dst_step)
|
|
||||||
copy += st->src_step; /* one more step to allow for pregap data */
|
|
||||||
if (copy > data_len) copy = data_len;
|
|
||||||
assert(st->ovl_size +copy <= FIXED_BUFSIZE);
|
|
||||||
memcpy(st->ovl_buff[0] + st->ovl_size, buf_in[0],
|
|
||||||
copy * sizeof(int32_t));
|
|
||||||
if(stereo)
|
|
||||||
memcpy(st->ovl_buff[1] + st->ovl_size, buf_in[1],
|
|
||||||
copy * sizeof(int32_t));
|
|
||||||
if (!last && have + copy < src_frame_sz) {
|
|
||||||
/* still not enough to process at least one frame */
|
|
||||||
st->ovl_size += copy;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/* recursively call ourselves to process the overlap buffer */
|
|
||||||
have = st->ovl_size;
|
|
||||||
st->ovl_size = 0;
|
|
||||||
if (copy == data_len) {
|
|
||||||
assert( (have+copy) <= FIXED_BUFSIZE);
|
|
||||||
return tdspeed_apply(buf_out, st->ovl_buff, have+copy, last,
|
|
||||||
out_size);
|
|
||||||
}
|
|
||||||
assert( (have+copy) <= FIXED_BUFSIZE);
|
|
||||||
i = tdspeed_apply(buf_out, st->ovl_buff, have+copy, -1, out_size);
|
|
||||||
dest[0] = buf_out[0] + i;
|
|
||||||
dest[1] = buf_out[1] + i;
|
|
||||||
/* readjust pointers to account for data already consumed */
|
|
||||||
next_frame = copy - src_frame_sz + st->src_step;
|
|
||||||
prev_frame = next_frame - st->ovl_shift;
|
|
||||||
} else {
|
|
||||||
dest[0] = buf_out[0];
|
|
||||||
dest[1] = buf_out[1];
|
|
||||||
next_frame = prev_frame = 0;
|
|
||||||
if (st->ovl_shift > 0)
|
|
||||||
next_frame += st->ovl_shift;
|
|
||||||
else
|
|
||||||
prev_frame += -st->ovl_shift;
|
|
||||||
}
|
|
||||||
st->ovl_shift = 0;
|
|
||||||
|
|
||||||
/* process all complete frames */
|
|
||||||
while (data_len -next_frame >= src_frame_sz) {
|
|
||||||
/* find frame overlap by autocorelation */
|
|
||||||
long long min_delta = ~(1ll << 63); /* most positive */
|
|
||||||
shift = 0;
|
|
||||||
#define INC1 8
|
|
||||||
#define INC2 32
|
|
||||||
/* Power of 2 of a 28bit number requires 56bits, can accumulate
|
|
||||||
256times in a 64bit variable. */
|
|
||||||
assert(st->dst_step /INC2 <= 256);
|
|
||||||
assert(next_frame+st->shift_max-1 +st->dst_step-1 < data_len);
|
|
||||||
assert(prev_frame +st->dst_step-1 < data_len);
|
|
||||||
for (i = 0; i < st->shift_max; i += INC1) {
|
|
||||||
long long delta = 0;
|
|
||||||
curr = buf_in[0] +next_frame + i;
|
|
||||||
prev = buf_in[0] +prev_frame;
|
|
||||||
for (j = 0; j < st->dst_step;
|
|
||||||
j += INC2, curr += INC2, prev += INC2) {
|
|
||||||
int32_t diff = *curr - *prev;
|
|
||||||
delta += (long long)diff * diff;
|
|
||||||
if (delta >= min_delta)
|
|
||||||
goto skip;
|
|
||||||
}
|
|
||||||
if(stereo) {
|
|
||||||
curr = buf_in[1] +next_frame + i;
|
|
||||||
prev = buf_in[1] +prev_frame;
|
|
||||||
for (j = 0; j < st->dst_step;
|
|
||||||
j += INC2, curr += INC2, prev += INC2) {
|
|
||||||
int32_t diff = *curr - *prev;
|
|
||||||
delta += (long long)diff * diff;
|
|
||||||
if (delta >= min_delta)
|
|
||||||
goto skip;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
min_delta = delta;
|
|
||||||
shift = i;
|
|
||||||
skip:;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* overlap fading-out previous frame with fading-in current frame */
|
|
||||||
curr = buf_in[0] +next_frame + shift;
|
|
||||||
prev = buf_in[0] +prev_frame;
|
|
||||||
d = dest[0];
|
|
||||||
assert(next_frame+shift +st->dst_step-1 < data_len);
|
|
||||||
assert(prev_frame +st->dst_step-1 < data_len);
|
|
||||||
assert(dest[0]-buf_out[0] +st->dst_step-1 < out_size);
|
|
||||||
for (i = 0, j = st->dst_step; j; i++, j--) {
|
|
||||||
*d++ = (*curr++ * (long long)i
|
|
||||||
+ *prev++ * (long long)j) >> st->dst_order;
|
|
||||||
}
|
|
||||||
dest[0] = d;
|
|
||||||
if(stereo) {
|
|
||||||
curr = buf_in[1] +next_frame + shift;
|
|
||||||
prev = buf_in[1] +prev_frame;
|
|
||||||
d = dest[1];
|
|
||||||
for (i = 0, j = st->dst_step; j; i++, j--) {
|
|
||||||
assert(d < buf_out[1] +out_size);
|
|
||||||
*d++ = (*curr++ * (long long)i
|
|
||||||
+ *prev++ * (long long)j) >> st->dst_order;
|
|
||||||
}
|
|
||||||
dest[1] = d;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* adjust pointers for next frame */
|
|
||||||
prev_frame = next_frame + shift + st->dst_step;
|
|
||||||
//assert(prev_frame == curr[0] -buf_in[0]);
|
|
||||||
next_frame += st->src_step;
|
|
||||||
/* here next_frame - prev_frame = src_step - dst_step - shift */
|
|
||||||
assert(next_frame - prev_frame == st->src_step - st->dst_step - shift);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* now deal with remaining partial frames */
|
|
||||||
if (last == -1) {
|
|
||||||
/* special overlap buffer processing: remember frame shift only */
|
|
||||||
st->ovl_shift = next_frame - prev_frame;
|
|
||||||
} else if (last != 0) {
|
|
||||||
/* last call: purge all remaining data to output buffer */
|
|
||||||
i = data_len -prev_frame;
|
|
||||||
assert(dest[0] +i <= buf_out[0] +out_size);
|
|
||||||
memcpy(dest[0], buf_in[0] +prev_frame, i * sizeof(int32_t));
|
|
||||||
dest[0] += i;
|
|
||||||
if(stereo) {
|
|
||||||
assert(dest[1] +i <= buf_out[1] +out_size);
|
|
||||||
memcpy(dest[1], buf_in[1] +prev_frame, i * sizeof(int32_t));
|
|
||||||
dest[1] += i;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* preserve remaining data + needed overlap data for next call */
|
|
||||||
st->ovl_shift = next_frame - prev_frame;
|
|
||||||
i = (st->ovl_shift < 0) ? next_frame : prev_frame;
|
|
||||||
st->ovl_size = data_len - i;
|
|
||||||
assert(st->ovl_size <= FIXED_BUFSIZE);
|
|
||||||
memcpy(st->ovl_buff[0], buf_in[0]+i, st->ovl_size * sizeof(int32_t));
|
|
||||||
if(stereo)
|
|
||||||
memcpy(st->ovl_buff[1], buf_in[1]+i, st->ovl_size * sizeof(int32_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
return dest[0] - buf_out[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
static int tdspeed_next_required_space(int data_len, int last)
|
|
||||||
{
|
|
||||||
struct tdspeed_state_s *st = &tdspeed_state;
|
|
||||||
int src_frame_sz, src_size, nb_frames, dst_space;
|
|
||||||
|
|
||||||
src_frame_sz = st->shift_max + st->dst_step;
|
|
||||||
if (st->dst_step > st->src_step)
|
|
||||||
src_frame_sz += st->dst_step - st->src_step;
|
|
||||||
src_size = data_len + st->ovl_size;
|
|
||||||
if (st->ovl_shift > 0)
|
|
||||||
src_size -= st->ovl_shift;
|
|
||||||
if (src_size < src_frame_sz) {
|
|
||||||
if (!last)
|
|
||||||
return 0;
|
|
||||||
dst_space = data_len + st->ovl_size;
|
|
||||||
if (st->ovl_shift < 0)
|
|
||||||
dst_space += st->ovl_shift;
|
|
||||||
} else {
|
|
||||||
nb_frames = (src_size - src_frame_sz) / st->src_step + 1;
|
|
||||||
dst_space = nb_frames * st->dst_step;
|
|
||||||
if (last) {
|
|
||||||
dst_space += src_size - nb_frames * st->src_step;
|
|
||||||
dst_space += st->src_step - st->dst_step;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return dst_space;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
long tdspeed_est_output_size(long size)
|
|
||||||
{
|
|
||||||
//int _size = size;
|
|
||||||
#if 0
|
|
||||||
size = tdspeed_next_required_space(size, false);
|
|
||||||
if(size > TDSPEED_OUTBUFSIZE)
|
|
||||||
size = TDSPEED_OUTBUFSIZE;
|
|
||||||
#else
|
|
||||||
size = TDSPEED_OUTBUFSIZE;
|
|
||||||
#endif
|
|
||||||
mylog("tdspeed_est_output_size of %d -> %d\n", _size, size);
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
long tdspeed_est_input_size(long size)
|
|
||||||
{
|
|
||||||
struct tdspeed_state_s *st = &tdspeed_state;
|
|
||||||
//int _size = size;
|
|
||||||
size = (size -st->ovl_size) *st->src_step /st->dst_step;
|
|
||||||
if(size <0)
|
|
||||||
size = 0;
|
|
||||||
else size = size;
|
|
||||||
mylog("tdspeed_est_input_size of %d -> %d\n", _size, size);
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tdspeed_doit(int32_t *src[], int count)
|
|
||||||
{
|
|
||||||
mylog("tdspeed_doit %d\n", count);
|
|
||||||
count = tdspeed_apply( (int32_t *[2]) { outbuf[0], outbuf[1] },
|
|
||||||
src, count, 0, TDSPEED_OUTBUFSIZE);
|
|
||||||
src[0] = outbuf[0];
|
|
||||||
src[1] = outbuf[1];
|
|
||||||
return count;
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
#define TDSPEED_OUTBUFSIZE 4096
|
|
||||||
|
|
||||||
bool tdspeed_init(int samplerate, bool stereo, int factor);
|
|
||||||
int tdspeed_apply(int32_t *buf_out[2], int32_t *buf_in[2], int data_len,
|
|
||||||
int last, int out_size);
|
|
||||||
|
|
||||||
long tdspeed_est_output_size(long size);
|
|
||||||
long tdspeed_est_input_size(long size);
|
|
||||||
int tdspeed_doit(int32_t *src[], int count);
|
|
|
@ -418,7 +418,6 @@ Florin Popescu
|
||||||
Volker Mische
|
Volker Mische
|
||||||
Vitja Makarov
|
Vitja Makarov
|
||||||
Francisco Vila
|
Francisco Vila
|
||||||
Nicolas Pitre
|
|
||||||
|
|
||||||
The libmad team
|
The libmad team
|
||||||
The wavpack team
|
The wavpack team
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue