swr: handle initial negative sample index outside DSP function.

Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
Ronald S. Bultje 2014-06-13 19:06:30 -04:00 committed by Michael Niedermayer
parent d77815eeaa
commit b785c62681
5 changed files with 66 additions and 50 deletions

View File

@ -407,6 +407,51 @@ static int resample_flush(struct SwrContext *s) {
return 0;
}
// in fact the whole handle multiple ridiculously small buffers might need more thinking...
static int invert_initial_buffer(ResampleContext *c, AudioData *dst, const AudioData *src,
int in_count, int *out_idx, int *out_sz)
{
int n, ch, num = FFMIN(in_count + *out_sz, c->filter_length + 1), res;
if (c->index >= 0)
return 0;
if ((res = swri_realloc_audio(dst, c->filter_length * 2 + 1)) < 0)
return res;
// copy
for (n = *out_sz; n < num; n++) {
for (ch = 0; ch < src->ch_count; ch++) {
memcpy(dst->ch[ch] + ((c->filter_length + n) * c->felem_size),
src->ch[ch] + ((n - *out_sz) * c->felem_size), c->felem_size);
}
}
// if not enough data is in, return and wait for more
if (num < c->filter_length + 1) {
*out_sz = num;
*out_idx = c->filter_length;
return INT_MAX;
}
// else invert
for (n = 1; n <= c->filter_length; n++) {
for (ch = 0; ch < src->ch_count; ch++) {
memcpy(dst->ch[ch] + ((c->filter_length - n) * c->felem_size),
dst->ch[ch] + ((c->filter_length + n) * c->felem_size),
c->felem_size);
}
}
res = num - *out_sz;
*out_idx = c->filter_length + (c->index >> c->phase_shift);
*out_sz = 1 + c->filter_length * 2 - *out_idx;
c->index &= c->phase_mask;
assert(res > 0);
return res;
}
struct Resampler const swri_resampler={
resample_init,
resample_free,
@ -414,4 +459,5 @@ struct Resampler const swri_resampler={
resample_flush,
set_compensation,
get_delay,
invert_initial_buffer,
};

View File

@ -107,7 +107,10 @@
#endif
int RENAME(swri_resample)(ResampleContext *c, DELEM *dst, const DELEM *src, int *consumed, int src_size, int dst_size, int update_ctx){
int dst_index, i;
int dst_index;
#if !defined(COMMON_CORE) || !defined(LINEAR_CORE)
int i;
#endif
int index= c->index;
int frac= c->frac;
int dst_incr_frac= c->dst_incr % c->src_incr;
@ -133,7 +136,7 @@ int RENAME(swri_resample)(ResampleContext *c, DELEM *dst, const DELEM *src, int
av_assert2(index >= 0);
*consumed= index;
index = 0;
} else if (index >= 0) {
} else {
int64_t end_index = (1LL + src_size - c->filter_length) << c->phase_shift;
int64_t delta_frac = (end_index - index) * c->src_incr - c->frac;
int delta_n = (delta_frac + c->dst_incr - 1) / c->dst_incr;
@ -195,54 +198,6 @@ int RENAME(swri_resample)(ResampleContext *c, DELEM *dst, const DELEM *src, int
}
*consumed = sample_index;
} else {
int sample_index = 0;
for(dst_index=0; dst_index < dst_size; dst_index++){
FELEM *filter;
FELEM2 val=0;
sample_index += index >> c->phase_shift;
index &= c->phase_mask;
filter = ((FELEM*)c->filter_bank) + c->filter_alloc*index;
if(sample_index + c->filter_length > src_size || -sample_index >= src_size){
break;
}else if(sample_index < 0){
for(i=0; i<c->filter_length; i++)
val += src[FFABS(sample_index + i)] * (FELEM2)filter[i];
OUT(dst[dst_index], val);
}else if(c->linear){
FELEM2 v2=0;
#ifdef LINEAR_CORE
LINEAR_CORE
#else
for(i=0; i<c->filter_length; i++){
val += src[sample_index + i] * (FELEM2)filter[i];
v2 += src[sample_index + i] * (FELEM2)filter[i + c->filter_alloc];
}
#endif
val+=(v2-val)*(FELEML)frac / c->src_incr;
OUT(dst[dst_index], val);
}else{
#ifdef COMMON_CORE
COMMON_CORE
#else
for(i=0; i<c->filter_length; i++){
val += src[sample_index + i] * (FELEM2)filter[i];
}
OUT(dst[dst_index], val);
#endif
}
frac += dst_incr_frac;
index += dst_incr;
if(frac >= c->src_incr){
frac -= c->src_incr;
index++;
}
}
*consumed= FFMAX(sample_index, 0);
index += FFMIN(sample_index, 0) << c->phase_shift;
}
if(update_ctx){

View File

@ -87,7 +87,14 @@ static int64_t get_delay(struct SwrContext *s, int64_t base){
return (int64_t)(delay_s * base + .5);
}
static int invert_initial_buffer(struct ResampleContext *c, AudioData *dst, const AudioData *src,
int in_count, int *out_idx, int *out_sz)
{
return 0;
}
struct Resampler const soxr_resampler={
create, destroy, process, flush, NULL /* set_compensation */, get_delay,
invert_initial_buffer,
};

View File

@ -541,6 +541,12 @@ static int resample(SwrContext *s, AudioData *out_param, int out_count,
tmp=out=*out_param;
in = *in_param;
border = s->resampler->invert_initial_buffer(s->resample, &s->in_buffer,
&in, in_count, &s->in_buffer_index, &s->in_buffer_count);
if (border == INT_MAX) return 0;
else if (border < 0) return border;
else if (border) { buf_set(&in, &in, border); in_count -= border; s->resample_in_constraint = 0; }
do{
int ret, size, consumed;
if(!s->resample_in_constraint && s->in_buffer_count){

View File

@ -157,6 +157,7 @@ typedef int (* multiple_resample_func)(struct ResampleContext *c, AudioData
typedef int (* resample_flush_func)(struct SwrContext *c);
typedef int (* set_compensation_func)(struct ResampleContext *c, int sample_delta, int compensation_distance);
typedef int64_t (* get_delay_func)(struct SwrContext *s, int64_t base);
typedef int (* invert_initial_buffer_func)(struct ResampleContext *c, AudioData *dst, const AudioData *src, int src_size, int *dst_idx, int *dst_count);
struct Resampler {
resample_init_func init;
@ -165,6 +166,7 @@ struct Resampler {
resample_flush_func flush;
set_compensation_func set_compensation;
get_delay_func get_delay;
invert_initial_buffer_func invert_initial_buffer;
};
extern struct Resampler const swri_resampler;