📄 resample.c
字号:
/* Per channel data */ st->last_sample = (spx_int32_t*)speex_alloc(nb_channels*sizeof(int)); st->magic_samples = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(int)); st->samp_frac_num = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(int)); for (i=0;i<nb_channels;i++) { st->last_sample[i] = 0; st->magic_samples[i] = 0; st->samp_frac_num[i] = 0; } speex_resampler_set_quality(st, quality); speex_resampler_set_rate_frac(st, ratio_num, ratio_den, in_rate, out_rate); update_filter(st); st->initialised = 1; if (err) *err = RESAMPLER_ERR_SUCCESS; return st;}EXPORT void speex_resampler_destroy(SpeexResamplerState *st){ speex_free(st->mem); speex_free(st->sinc_table); speex_free(st->last_sample); speex_free(st->magic_samples); speex_free(st->samp_frac_num); speex_free(st);}static int speex_resampler_process_native(SpeexResamplerState *st, spx_uint32_t channel_index, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len){ int j=0; const int N = st->filt_len; int out_sample = 0; spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size; spx_uint32_t ilen; st->started = 1; /* Call the right resampler through the function ptr */ out_sample = st->resampler_ptr(st, channel_index, mem, in_len, out, out_len); if (st->last_sample[channel_index] < (spx_int32_t)*in_len) *in_len = st->last_sample[channel_index]; *out_len = out_sample; st->last_sample[channel_index] -= *in_len; ilen = *in_len; for(j=0;j<N-1;++j) mem[j] = mem[j+ilen]; return RESAMPLER_ERR_SUCCESS;}static int speex_resampler_magic(SpeexResamplerState *st, spx_uint32_t channel_index, spx_word16_t **out, spx_uint32_t out_len) { spx_uint32_t tmp_in_len = st->magic_samples[channel_index]; spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size; const int N = st->filt_len; speex_resampler_process_native(st, channel_index, &tmp_in_len, *out, &out_len); st->magic_samples[channel_index] -= tmp_in_len; /* 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;}#ifdef FIXED_POINTEXPORT int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len)#elseEXPORT int speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)#endif{ int j; spx_uint32_t ilen = *in_len; spx_uint32_t olen = *out_len; spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size; const int filt_offs = st->filt_len - 1; const spx_uint32_t xlen = st->mem_alloc_size - filt_offs; const int istride = st->in_stride; if (st->magic_samples[channel_index]) olen -= speex_resampler_magic(st, channel_index, &out, olen); if (! st->magic_samples[channel_index]) { while (ilen && olen) { spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen; spx_uint32_t ochunk = olen; if (in) { for(j=0;j<ichunk;++j) x[j+filt_offs]=in[j*istride]; } else { for(j=0;j<ichunk;++j) x[j+filt_offs]=0; } speex_resampler_process_native(st, channel_index, &ichunk, out, &ochunk); ilen -= ichunk; olen -= ochunk; out += ochunk * st->out_stride; if (in) in += ichunk * istride; } } *in_len -= ilen; *out_len -= olen; return RESAMPLER_ERR_SUCCESS;}#ifdef FIXED_POINTEXPORT int speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)#elseEXPORT int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len)#endif{ int j; const int istride_save = st->in_stride; const int ostride_save = st->out_stride; spx_uint32_t ilen = *in_len; spx_uint32_t olen = *out_len; spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size; const spx_uint32_t xlen = st->mem_alloc_size - (st->filt_len - 1);#ifdef VAR_ARRAYS const unsigned int ylen = (olen < FIXED_STACK_ALLOC) ? olen : FIXED_STACK_ALLOC; VARDECL(spx_word16_t *ystack); ALLOC(ystack, ylen, spx_word16_t);#else const unsigned int ylen = FIXED_STACK_ALLOC; spx_word16_t ystack[FIXED_STACK_ALLOC];#endif st->out_stride = 1; while (ilen && olen) { spx_word16_t *y = ystack; spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen; spx_uint32_t ochunk = (olen > ylen) ? ylen : olen; spx_uint32_t omagic = 0; if (st->magic_samples[channel_index]) { omagic = speex_resampler_magic(st, channel_index, &y, ochunk); ochunk -= omagic; olen -= omagic; } if (! st->magic_samples[channel_index]) { if (in) { for(j=0;j<ichunk;++j)#ifdef FIXED_POINT x[j+st->filt_len-1]=WORD2INT(in[j*istride_save]);#else x[j+st->filt_len-1]=in[j*istride_save];#endif } else { for(j=0;j<ichunk;++j) x[j+st->filt_len-1]=0; } speex_resampler_process_native(st, channel_index, &ichunk, y, &ochunk); } else { ichunk = 0; ochunk = 0; } for (j=0;j<ochunk+omagic;++j)#ifdef FIXED_POINT out[j*ostride_save] = ystack[j];#else out[j*ostride_save] = WORD2INT(ystack[j]);#endif ilen -= ichunk; olen -= ochunk; out += (ochunk+omagic) * ostride_save; if (in) in += ichunk * istride_save; } st->out_stride = ostride_save; *in_len -= ilen; *out_len -= olen; return RESAMPLER_ERR_SUCCESS;}EXPORT int speex_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len){ spx_uint32_t i; int istride_save, ostride_save; spx_uint32_t bak_len = *out_len; istride_save = st->in_stride; ostride_save = st->out_stride; st->in_stride = st->out_stride = st->nb_channels; for (i=0;i<st->nb_channels;i++) { *out_len = bak_len; if (in != NULL) speex_resampler_process_float(st, i, in+i, in_len, out+i, out_len); else speex_resampler_process_float(st, i, NULL, in_len, out+i, out_len); } st->in_stride = istride_save; st->out_stride = ostride_save; return RESAMPLER_ERR_SUCCESS;} EXPORT int speex_resampler_process_interleaved_int(SpeexResamplerState *st, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len){ spx_uint32_t i; int istride_save, ostride_save; spx_uint32_t bak_len = *out_len; istride_save = st->in_stride; ostride_save = st->out_stride; st->in_stride = st->out_stride = st->nb_channels; for (i=0;i<st->nb_channels;i++) { *out_len = bak_len; if (in != NULL) speex_resampler_process_int(st, i, in+i, in_len, out+i, out_len); else speex_resampler_process_int(st, i, NULL, in_len, out+i, out_len); } st->in_stride = istride_save; st->out_stride = ostride_save; return RESAMPLER_ERR_SUCCESS;}EXPORT int speex_resampler_set_rate(SpeexResamplerState *st, spx_uint32_t in_rate, spx_uint32_t out_rate){ return speex_resampler_set_rate_frac(st, in_rate, out_rate, in_rate, out_rate);}EXPORT void speex_resampler_get_rate(SpeexResamplerState *st, spx_uint32_t *in_rate, spx_uint32_t *out_rate){ *in_rate = st->in_rate; *out_rate = st->out_rate;}EXPORT int speex_resampler_set_rate_frac(SpeexResamplerState *st, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate){ spx_uint32_t fact; spx_uint32_t old_den; spx_uint32_t i; if (st->in_rate == in_rate && st->out_rate == out_rate && st->num_rate == ratio_num && st->den_rate == ratio_den) return RESAMPLER_ERR_SUCCESS; old_den = st->den_rate; st->in_rate = in_rate; st->out_rate = out_rate; st->num_rate = ratio_num; st->den_rate = ratio_den; /* FIXME: This is terribly inefficient, but who cares (at least for now)? */ for (fact=2;fact<=IMIN(st->num_rate, st->den_rate);fact++) { while ((st->num_rate % fact == 0) && (st->den_rate % fact == 0)) { st->num_rate /= fact; st->den_rate /= fact; } } if (old_den > 0) { for (i=0;i<st->nb_channels;i++) { st->samp_frac_num[i]=st->samp_frac_num[i]*st->den_rate/old_den; /* Safety net */ if (st->samp_frac_num[i] >= st->den_rate) st->samp_frac_num[i] = st->den_rate-1; } } if (st->initialised) update_filter(st); return RESAMPLER_ERR_SUCCESS;}EXPORT void speex_resampler_get_ratio(SpeexResamplerState *st, spx_uint32_t *ratio_num, spx_uint32_t *ratio_den){ *ratio_num = st->num_rate; *ratio_den = st->den_rate;}EXPORT int speex_resampler_set_quality(SpeexResamplerState *st, int quality){ if (quality > 10 || quality < 0) return RESAMPLER_ERR_INVALID_ARG; if (st->quality == quality) return RESAMPLER_ERR_SUCCESS; st->quality = quality; if (st->initialised) update_filter(st); return RESAMPLER_ERR_SUCCESS;}EXPORT void speex_resampler_get_quality(SpeexResamplerState *st, int *quality){ *quality = st->quality;}EXPORT void speex_resampler_set_input_stride(SpeexResamplerState *st, spx_uint32_t stride){ st->in_stride = stride;}EXPORT void speex_resampler_get_input_stride(SpeexResamplerState *st, spx_uint32_t *stride){ *stride = st->in_stride;}EXPORT void speex_resampler_set_output_stride(SpeexResamplerState *st, spx_uint32_t stride){ st->out_stride = stride;}EXPORT void speex_resampler_get_output_stride(SpeexResamplerState *st, spx_uint32_t *stride){ *stride = st->out_stride;}EXPORT int speex_resampler_get_input_latency(SpeexResamplerState *st){ return st->filt_len / 2;}EXPORT int speex_resampler_get_output_latency(SpeexResamplerState *st){ return ((st->filt_len / 2) * st->den_rate + (st->num_rate >> 1)) / st->num_rate;}EXPORT int speex_resampler_skip_zeros(SpeexResamplerState *st){ spx_uint32_t i; for (i=0;i<st->nb_channels;i++) st->last_sample[i] = st->filt_len/2; return RESAMPLER_ERR_SUCCESS;}EXPORT int speex_resampler_reset_mem(SpeexResamplerState *st){ spx_uint32_t i; for (i=0;i<st->nb_channels*(st->filt_len-1);i++) st->mem[i] = 0; return RESAMPLER_ERR_SUCCESS;}EXPORT const char *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."; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -