int quality;
spx_uint32_t nb_channels;
spx_uint32_t filt_len;
spx_uint32_t mem_alloc_size;
spx_uint32_t buffer_size; int int_advance; int frac_advance; float cutoff;
spx_uint32_t oversample; int initialised; int started;
/* These are per-channel */
spx_int32_t *last_sample;
spx_uint32_t *samp_frac_num;
spx_uint32_t *magic_samples;
#if0 #include <stdio.h> int main(int argc, char **argv)
{ int i; for (i=0;i<256;i++)
{
printf ("%f\n", compute_func(i/256., KAISER12));
} return0;
} #endif
#ifdef FIXED_POINT /* The slow way of computing a sinc for the table. Should improve that some day */ static spx_word16_t sinc(float cutoff, float x, int N, conststruct FuncDef *window_func)
{ /*fprintf (stderr, "%f ", x);*/ float xx = x * cutoff; if (fabs(x)<1e-6f) return WORD2INT(32768.*cutoff); elseif (fabs(x) > .5f*N) return0; /*FIXME: Can it really be any slower than this? */ return WORD2INT(32768.*cutoff*sin(M_PI*xx)/(M_PI*xx) * compute_func(fabs(2.*x/N), window_func));
} #else /* The slow way of computing a sinc for the table. Should improve that some day */ static spx_word16_t sinc(float cutoff, float x, int N, conststruct FuncDef *window_func)
{ /*fprintf (stderr, "%f ", x);*/ float xx = x * cutoff; if (fabs(x)<1e-6) return cutoff; elseif (fabs(x) > .5*N) return0; /*FIXME: Can it really be any slower than this? */ return cutoff*sin(M_PI*xx)/(M_PI*xx) * compute_func(fabs(2.*x/N), window_func);
} #endif
#ifdef FIXED_POINT staticvoid cubic_coef(spx_word16_t x, spx_word16_t interp[4])
{ /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation
but I know it's MMSE-optimal on a sinc */
spx_word16_t x2, x3;
x2 = MULT16_16_P15(x, x);
x3 = MULT16_16_P15(x, x2);
interp[0] = PSHR32(MULT16_16(QCONST16(-0.16667f, 15),x) + MULT16_16(QCONST16(0.16667f, 15),x3),15);
interp[1] = EXTRACT16(EXTEND32(x) + SHR32(SUB32(EXTEND32(x2),EXTEND32(x3)),1));
interp[3] = PSHR32(MULT16_16(QCONST16(-0.33333f, 15),x) + MULT16_16(QCONST16(.5f,15),x2) - MULT16_16(QCONST16(0.16667f, 15),x3),15); /* Just to make sure we don't have rounding problems */
interp[2] = Q15_ONE-interp[0]-interp[1]-interp[3]; if (interp[2]<32767)
interp[2]+=1;
} #else staticvoid cubic_coef(spx_word16_t frac, spx_word16_t interp[4])
{ /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation
but I know it's MMSE-optimal on a sinc */
interp[0] = -0.16667f*frac + 0.16667f*frac*frac*frac;
interp[1] = frac + 0.5f*frac*frac - 0.5f*frac*frac*frac; /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac;*/
interp[3] = -0.33333f*frac + 0.5f*frac*frac - 0.16667f*frac*frac*frac; /* Just to make sure we don't have rounding problems */
interp[2] = 1.-interp[0]-interp[1]-interp[3];
} #endif
#ifdef OVERRIDE_INNER_PRODUCT_SINGLE if (!moz_speex_have_single_simd()) { #endif int j;
sum = 0; for(j=0;j<N;j++) sum += MULT16_16(sinct[j], iptr[j]);
/* This code is slower on most DSPs which have only 2 accumulators. Plusthisthisforcestruncationto32bitsandyoulosetheHWguardbits. Ithinkwecantrustthecompilerandletitvectorizeand/orunrollitself. spx_word32_taccum[4]={0,0,0,0}; for(j=0;j<N;j+=4){ accum[0]+=MULT16_16(sinct[j],iptr[j]); accum[1]+=MULT16_16(sinct[j+1],iptr[j+1]); accum[2]+=MULT16_16(sinct[j+2],iptr[j+2]); accum[3]+=MULT16_16(sinct[j+3],iptr[j+3]); } sum=accum[0]+accum[1]+accum[2]+accum[3];
*/
sum = SATURATE32PSHR(sum, 15, 32767); #ifdef OVERRIDE_INNER_PRODUCT_SINGLE
} else {
sum = inner_product_single(sinct, iptr, N);
} #endif
staticint multiply_frac(spx_uint32_t *result, spx_uint32_t value, spx_uint32_t num, spx_uint32_t den)
{
spx_uint32_t major = value / den;
spx_uint32_t remain = value % den; /* TODO: Could use 64 bits operation to check for overflow. But only guaranteed in C99+ */ if (remain > UINT32_MAX / num || major > UINT32_MAX / num
|| major * num > UINT32_MAX - remain * num / den) return RESAMPLER_ERR_OVERFLOW;
*result = remain * num / den + major * num; return RESAMPLER_ERR_SUCCESS;
}
if (st->num_rate > st->den_rate)
{ /* down-sampling */
st->cutoff = quality_map[st->quality].downsample_bandwidth * st->den_rate / st->num_rate; if (multiply_frac(&st->filt_len,st->filt_len,st->num_rate,st->den_rate) != RESAMPLER_ERR_SUCCESS) goto fail; /* Round up to make sure we have a multiple of 8 for SSE */
st->filt_len = ((st->filt_len-1)&(~0x7))+8; if (2*st->den_rate < st->num_rate)
st->oversample >>= 1; if (4*st->den_rate < st->num_rate)
st->oversample >>= 1; if (8*st->den_rate < st->num_rate)
st->oversample >>= 1; if (16*st->den_rate < st->num_rate)
st->oversample >>= 1; if (st->oversample < 1)
st->oversample = 1;
} else { /* up-sampling */
st->cutoff = quality_map[st->quality].upsample_bandwidth;
}
use_direct = #ifdef RESAMPLE_HUGEMEM /* Choose the direct resampler, even with higher initialization costs,
when resampling any multiple of 100 to 44100. */
st->den_rate <= 441 #else /* Choose the resampling type that requires the least amount of memory */
st->filt_len*st->den_rate <= st->filt_len*st->oversample+8 #endif
&& INT_MAX/sizeof(spx_word16_t)/st->den_rate >= st->filt_len; if (use_direct)
{
min_sinc_table_length = st->filt_len*st->den_rate;
} else { if ((INT_MAX/sizeof(spx_word16_t)-8)/st->oversample < st->filt_len) goto fail;
min_sinc_table_length = st->filt_len*st->oversample+8;
} if (st->sinc_table_length < min_sinc_table_length)
{
spx_word16_t *sinc_table = (spx_word16_t *)speex_realloc(st->sinc_table,min_sinc_table_length*sizeof(spx_word16_t)); if (!sinc_table) goto fail;
/* Here's the place where we update the filter memory to take into account thechangeinfilterlength.It'sprobablythemessiestpartofthecode
due to handling of lots of corner cases. */
/* Adding buffer_size to filt_len won't overflow here because filt_len
could be multiplied by sizeof(spx_word16_t) above. */
min_alloc_size = st->filt_len-1 + st->buffer_size; if (min_alloc_size > st->mem_alloc_size)
{
spx_word16_t *mem; if (INT_MAX/sizeof(spx_word16_t)/st->nb_channels < min_alloc_size) goto fail; elseif (!(mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*min_alloc_size * sizeof(*mem)))) goto fail;
st->mem = mem;
st->mem_alloc_size = min_alloc_size;
} if (!st->started)
{
spx_uint32_t i; for (i=0;i<st->nb_channels*st->mem_alloc_size;i++)
st->mem[i] = 0; /*speex_warning("reinit filter");*/
} elseif (st->filt_len > old_length)
{
spx_uint32_t i; /* Increase the filter length */ /*speex_warning("increase filter size");*/ for (i=st->nb_channels;i--;)
{
spx_uint32_t j;
spx_uint32_t olen = old_length;
spx_uint32_t start = i*st->mem_alloc_size;
spx_uint32_t magic_samples = st->magic_samples[i]; /*if (st->magic_samples[i])*/
{ /* Try and remove the magic samples as if nothing had happened */
/* FIXME: This is wrong but for now we need it to avoid going over the array bounds */
olen = old_length + 2*magic_samples; for (j=old_length-1+magic_samples;j--;)
st->mem[start+j+magic_samples] = st->mem[i*old_alloc_size+j]; for (j=0;j<magic_samples;j++)
st->mem[start+j] = 0;
st->magic_samples[i] = 0;
} if (st->filt_len > olen)
{ /* If the new filter length is still bigger than the "augmented" length */ /* Copy data going backward */ for (j=0;j<olen-1;j++)
st->mem[start+(st->filt_len-2-j)] = st->mem[start+(olen-2-j)]; /* Then put zeros for lack of anything better */ for (;j<st->filt_len-1;j++)
st->mem[start+(st->filt_len-2-j)] = 0; /* Adjust last_sample */
st->last_sample[i] += (st->filt_len - olen)/2;
} else { /* Put back some of the magic! */
magic_samples = (olen - st->filt_len)/2; for (j=0;j<st->filt_len-1+magic_samples;j++)
st->mem[start+j] = st->mem[start+j+magic_samples];
st->magic_samples[i] = magic_samples;
}
}
} elseif (st->filt_len < old_length)
{
spx_uint32_t i; /* Reduce filter length, this a bit tricky. We need to store some of the memory as "magic"
samples so they can be used directly as input the next time(s) */ for (i=0;i<st->nb_channels;i++)
{
spx_uint32_t j;
spx_uint32_t old_magic = st->magic_samples[i];
st->magic_samples[i] = (old_length - st->filt_len)/2; /* We must copy some of the memory that's no longer used */ /* Copy data going backward */ for (j=0;j<st->filt_len-1+st->magic_samples[i]+old_magic;j++)
st->mem[i*st->mem_alloc_size+j] = st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]];
st->magic_samples[i] += old_magic;
}
} return RESAMPLER_ERR_SUCCESS;
fail:
st->resampler_ptr = resampler_basic_zero; /* st->mem may still contain consumed input samples for the filter. Restorefilt_lensothatfilt_len-1stillpointstothepositionafter
the last of these samples. */
st->filt_len = old_length; return RESAMPLER_ERR_ALLOC_FAILED;
}
/* Per channel data */ if (!(st->last_sample = (spx_int32_t*)speex_alloc(nb_channels*sizeof(spx_int32_t)))) goto fail; if (!(st->magic_samples = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(spx_uint32_t)))) goto fail; if (!(st->samp_frac_num = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(spx_uint32_t)))) goto fail;
/* If we couldn't process all "magic" input samples, save the rest for next time */ if (st->magic_samples[channel_index])
{
spx_uint32_t i; for (i=0;i<st->magic_samples[channel_index];i++)
mem[N-1+i]=mem[N-1+i+tmp_in_len];
}
*out += out_len*st->out_stride; return out_len;
}
EXPORT int speex_resampler_reset_mem(SpeexResamplerState *st)
{
spx_uint32_t i; for (i=0;i<st->nb_channels;i++)
{
st->last_sample[i] = 0;
st->magic_samples[i] = 0;
st->samp_frac_num[i] = 0;
} for (i=0;i<st->nb_channels*(st->filt_len-1);i++)
st->mem[i] = 0; return RESAMPLER_ERR_SUCCESS;
}
EXPORT constchar *speex_resampler_strerror(int err)
{ switch (err)
{ case RESAMPLER_ERR_SUCCESS: return"Success."; case RESAMPLER_ERR_ALLOC_FAILED: return"Memory allocation failed."; case RESAMPLER_ERR_BAD_STATE: return"Bad resampler state."; case RESAMPLER_ERR_INVALID_ARG: return"Invalid argument."; case RESAMPLER_ERR_PTR_OVERLAP: return"Input and output buffers overlap."; default: return"Unknown error. Bad error code or strange version mismatch.";
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.