static void Close( vlc_object_t *p_obj ) { filter_t *p_filter = (filter_t *)p_obj; filter_sys_t *p_sys = p_filter->p_sys; soxr_delete( p_sys->soxr ); if( p_sys->vr_soxr ) soxr_delete( p_sys->vr_soxr ); free( p_sys ); }
static struct ResampleContext *create(struct ResampleContext *c, int out_rate, int in_rate, int filter_size, int phase_shift, int linear, double cutoff, enum AVSampleFormat format, enum SwrFilterType filter_type, int kaiser_beta, double precision, int cheby){ soxr_error_t error; soxr_datatype_t type = format == AV_SAMPLE_FMT_S16P? SOXR_INT16_S : format == AV_SAMPLE_FMT_S16 ? SOXR_INT16_I : format == AV_SAMPLE_FMT_S32P? SOXR_INT32_S : format == AV_SAMPLE_FMT_S32 ? SOXR_INT32_I : format == AV_SAMPLE_FMT_FLTP? SOXR_FLOAT32_S : format == AV_SAMPLE_FMT_FLT ? SOXR_FLOAT32_I : format == AV_SAMPLE_FMT_DBLP? SOXR_FLOAT64_S : format == AV_SAMPLE_FMT_DBL ? SOXR_FLOAT64_I : (soxr_datatype_t)-1; soxr_io_spec_t io_spec = soxr_io_spec(type, type); soxr_quality_spec_t q_spec = soxr_quality_spec((int)((precision-2)/4), (SOXR_HI_PREC_CLOCK|SOXR_ROLLOFF_NONE)*!!cheby); q_spec.precision = linear? 0 : precision; #if !defined SOXR_VERSION /* Deprecated @ March 2013: */ q_spec.bw_pc = cutoff? FFMAX(FFMIN(cutoff,.995),.8)*100 : q_spec.bw_pc; #else q_spec.passband_end = cutoff? FFMAX(FFMIN(cutoff,.995),.8) : q_spec.passband_end; #endif soxr_delete((soxr_t)c); c = (struct ResampleContext *) soxr_create(in_rate, out_rate, 0, &error, &io_spec, &q_spec, 0); if (!c) av_log(NULL, AV_LOG_ERROR, "soxr_create: %s\n", error); return c; }
int resample_close(struct resample_handle *h) { if(h == NULL) return 0; /* Close libsoxr */ if(h->soxr != NULL) soxr_delete(h->soxr); /* Free specs for down/up-mixing */ if(h->out_specs != NULL) { int i; for(i = 0; i < h->out_nb_channel; i++) if(h->out_specs[i].in_specs != NULL) free(h->out_specs[i].in_specs); free(h->out_specs); } /* Free buffer */ if(h->buffer != NULL) free(h->buffer); if(h->buffer_out != NULL) free(h->buffer_out); /* Free structure */ free(h); return 0; }
void DSD2PCM::Open(long DSDsamplesPerSec, int desiredSampleRate, int ch, int desiredWordSize) { dsd_samples_per_sec = DSDsamplesPerSec; channels = ch; wordSize = desiredWordSize; desired_sample_rate = desiredSampleRate; ds.clear(); ns.clear(); buffer.clear(); buffer_stored = 0; flush_phase = false; for (int i = 0; i < ch; ++i) { ds.push_back(Downsampler(ds_pc)); ns.push_back(Noiseshaper()); } if (soxr != NULL) { soxr_delete(soxr); } { soxr_error_t e = NULL; soxr_runtime_spec_t spec = soxr_runtime_spec(0); soxr = soxr_create(DSDsamplesPerSec / 8, desiredSampleRate, ch, &e, NULL, NULL, &spec); if (e != NULL) { OutputDebugStringA((char*)e); DebugBreak(); } } }
void DSD2PCM::Close() { dsd_samples_per_sec = channels = 0; ds.clear(); ns.clear(); buffer.clear(); buffer_stored = 0; if (soxr != NULL) { soxr_delete(soxr); soxr = NULL; } }
void BE_ST_ShutdownAudio(void) { if (g_sdlAudioSubsystemUp) { if ((g_sdlAudioSpec.callback == BEL_ST_Resampling_EmuCallBack) || (g_sdlAudioSpec.callback == BEL_ST_Resampling_DigiCallBack)) { #ifndef REFKEEN_RESAMPLER_NONE if (g_refKeenCfg.useResampler) { #if (defined REFKEEN_RESAMPLER_LIBSWRESAMPLE) swr_free(&g_sdlSwrContext); #elif (defined REFKEEN_RESAMPLER_LIBAVRESAMPLE) avresample_free(&g_sdlAvAudioResampleContext); #elif (defined REFKEEN_RESAMPLER_LIBAVCODEC) av_resample_close(g_sdlAvResampleContext); #elif (defined REFKEEN_RESAMPLER_LIBRESAMPLE) resample_close(g_sdlResampleHandle); #elif (defined REFKEEN_RESAMPLER_LIBSOXR) soxr_delete(g_sdlSoxr); #elif (defined REFKEEN_RESAMPLER_LIBSPEEXDSP) speex_resampler_destroy(g_sdlSpeexResamplerState); #elif (defined REFKEEN_RESAMPLER_LIBSAMPLERATE) src_delete(g_sdlSrcResampler); #endif } else #endif // REFKEEN_RESAMPLER_NONE { free(g_sdlSampleRateConvTable); } } #ifdef REFKEEN_CONFIG_THREADS SDL_DestroyMutex(g_sdlCallbackMutex); g_sdlCallbackMutex = NULL; #endif SDL_CloseAudio(); SDL_QuitSubSystem(SDL_INIT_AUDIO); g_sdlAudioSubsystemUp = false; } g_sdlCallbackSDFuncPtr = 0; // Just in case this may be called after the audio subsystem was never really started (manual calls to callback) }
VarRateResample::~VarRateResample() { soxr_delete((soxr_t)mHandle); mHandle = NULL; }
static void destroy(struct ResampleContext * *c){ soxr_delete((soxr_t)*c); *c = NULL; }
static int Open( vlc_object_t *p_obj, bool b_change_ratio ) { filter_t *p_filter = (filter_t *)p_obj; /* Cannot remix */ if( p_filter->fmt_in.audio.i_channels != p_filter->fmt_out.audio.i_channels ) return VLC_EGENERIC; /* Get SoXR input/output format */ soxr_datatype_t i_itype, i_otype; if( !SoXR_GetFormat( p_filter->fmt_in.audio.i_format, &i_itype ) || !SoXR_GetFormat( p_filter->fmt_out.audio.i_format, &i_otype ) ) return VLC_EGENERIC; filter_sys_t *p_sys = calloc( 1, sizeof( filter_sys_t ) ); if( unlikely( p_sys == NULL ) ) return VLC_ENOMEM; /* Setup SoXR */ int64_t i_vlc_q = var_InheritInteger( p_obj, "soxr-resampler-quality" ); if( i_vlc_q < 0 ) i_vlc_q = 0; else if( i_vlc_q > MAX_SOXR_QUALITY ) i_vlc_q = MAX_SOXR_QUALITY; const unsigned long i_recipe = soxr_resampler_quality_list[i_vlc_q]; const unsigned i_channels = p_filter->fmt_in.audio.i_channels; const double f_ratio = p_filter->fmt_out.audio.i_rate / (double) p_filter->fmt_in.audio.i_rate; p_sys->f_fixed_ratio = f_ratio; soxr_error_t error; /* IO spec */ soxr_io_spec_t io_spec = soxr_io_spec( i_itype, i_otype ); /* Quality spec */ soxr_quality_spec_t q_spec = soxr_quality_spec( i_recipe, 0 ); /* Create SoXR */ p_sys->soxr = soxr_create( 1, f_ratio, i_channels, &error, &io_spec, &q_spec, NULL ); if( error ) { msg_Err( p_filter, "soxr_create failed: %s", soxr_strerror( error ) ); free( p_sys ); return VLC_EGENERIC; } /* Create a 'variable-rate' SoXR if needed: it is slower than the fixed * one, but it will be only used when the input rate is changing (to catch * up a delay). */ if( b_change_ratio ) { q_spec = soxr_quality_spec( SOXR_LQ, SOXR_VR ); p_sys->vr_soxr = soxr_create( 1, f_ratio, i_channels, &error, &io_spec, &q_spec, NULL ); if( error ) { msg_Err( p_filter, "soxr_create failed: %s", soxr_strerror( error ) ); soxr_delete( p_sys->soxr ); free( p_sys ); return VLC_EGENERIC; } soxr_set_io_ratio( p_sys->vr_soxr, 1 / f_ratio, 0 ); } msg_Dbg( p_filter, "Using SoX Resampler with '%s' engine and '%s' quality " "to convert %4.4s/%dHz to %4.4s/%dHz.", soxr_engine( p_sys->soxr ), soxr_resampler_quality_vlctext[i_vlc_q], (const char *)&p_filter->fmt_in.audio.i_format, p_filter->fmt_in.audio.i_rate, (const char *)&p_filter->fmt_out.audio.i_format, p_filter->fmt_out.audio.i_rate ); p_filter->p_sys = p_sys; p_filter->pf_audio_filter = Resample; p_filter->pf_flush = Flush; p_filter->pf_audio_drain = Drain; return VLC_SUCCESS; }
void Resampler::Resample(unsigned int in_channels, unsigned int in_sample_rate, AVSampleFormat in_format, unsigned int in_sample_count, const uint8_t* in_data, unsigned int out_channels, unsigned int out_sample_rate, AVSampleFormat out_format, unsigned int* out_sample_count, const uint8_t** out_data) { Q_ASSERT(in_channels > 0 && out_channels > 0); Q_ASSERT(in_sample_rate > 0 && out_sample_rate > 0); Q_ASSERT(in_channels == out_channels); Q_ASSERT(out_format == AV_SAMPLE_FMT_FLT); if(m_started) { Q_ASSERT(m_out_channels == out_channels); Q_ASSERT(m_out_sample_rate == out_sample_rate); } else { m_started = true; m_in_sample_rate = 0; // trigger creation of new resampler m_out_channels = out_channels; m_out_sample_rate = out_sample_rate; } // prepare output samples unsigned int out_pos = 0; m_out_data.alloc(16 * 1024); // do we need a new resampler? if(in_sample_rate != m_in_sample_rate) { // delete old resampler if(m_soxr != NULL) { // flush resampler for( ; ; ) { size_t out_done; soxr_error_t error = soxr_process(m_soxr, NULL, 0, NULL, m_out_data.data() + out_pos * out_channels * sizeof(float), m_out_data.size() / (out_channels * sizeof(float)) - out_pos, &out_done); if(error != NULL) { Logger::LogError("[Resampler::Resample] " + QObject::tr("Error: Flushing resampler failed! Reason: %s").arg(soxr_strerror(error))); throw SoxrException(); } out_pos += out_done; if(out_pos < m_out_data.size() / (out_channels * sizeof(float))) break; m_out_data.realloc(m_out_data.size() * 2); } soxr_delete(m_soxr); m_soxr = NULL; } m_in_sample_rate = in_sample_rate; // do we really need a resampler? if(m_in_sample_rate != m_out_sample_rate) { Logger::LogInfo("[Resampler::Resampler] " + QObject::tr("Resampling from %1 to %2.").arg(m_in_sample_rate).arg(m_out_sample_rate)); soxr_error_t error; soxr_quality_spec_t quality = soxr_quality_spec(SOXR_MQ, 0); m_soxr = soxr_create((double) m_in_sample_rate, (double) m_out_sample_rate, out_channels, &error, NULL, &quality, NULL); if(m_soxr == NULL || error != NULL) { m_in_sample_rate = 0; Logger::LogError("[Resampler::Resampler] " + QObject::tr("Error: Can't create resampler! Reason: %s").arg(soxr_strerror(error))); throw SoxrException(); } } else { Logger::LogInfo("[Resampler::Resampler] " + QObject::tr("Resampling not needed.")); } } // prepare input samples uint8_t *in_data_float; unsigned int in_pos = 0; if(in_format == AV_SAMPLE_FMT_FLT) { in_data_float = (uint8_t*) in_data; } else if(in_format == AV_SAMPLE_FMT_S16) { m_in_data.alloc(in_sample_count * out_channels * sizeof(float)); SampleCopy(in_sample_count * out_channels, (const int16_t*) in_data, 1, (float*) m_in_data.data(), 1); in_data_float = (uint8_t*) m_in_data.data(); } else { Q_ASSERT(false); // unsupported input format return; } // no resampling needed? if(m_in_sample_rate == m_out_sample_rate) { if(out_pos == 0) { *out_sample_count = in_sample_count; *out_data = in_data_float; } else { m_out_data.realloc((out_pos + in_sample_count) * out_channels * sizeof(float)); memcpy(m_out_data.data() + out_pos * out_channels * sizeof(float), in_data_float, in_sample_count * out_channels * sizeof(float)); *out_sample_count = out_pos + in_sample_count; *out_data = m_out_data.data(); } return; } // resample for( ; ; ) { size_t in_done, out_done; soxr_error_t error = soxr_process(m_soxr, in_data_float + in_pos * out_channels * sizeof(float), in_sample_count - in_pos, &in_done, m_out_data.data() + out_pos * out_channels * sizeof(float), m_out_data.size() / (out_channels * sizeof(float)) - out_pos, &out_done); if(error != NULL) { Logger::LogError("[Resampler::Resample] " + QObject::tr("Error: Resampling failed!")); throw SoxrException(); } in_pos += in_done; out_pos += out_done; if(in_pos == in_sample_count) break; m_out_data.realloc(m_out_data.size() * 2); } *out_sample_count = out_pos; *out_data = m_out_data.data(); }
Resampler::~Resampler() { if(m_soxr != NULL) { soxr_delete(m_soxr); m_soxr = NULL; } }
int main(int n, char const * arg[]) { char const * const arg0 = n? --n, *arg++ : "", * engine = ""; double const irate = n? --n, atof(*arg++) : 96000.; double const orate = n? --n, atof(*arg++) : 44100.; unsigned const chans = n? --n, (unsigned)atoi(*arg++) : 1; soxr_datatype_t const itype = n? --n, (soxr_datatype_t)atoi(*arg++) : 0; unsigned const ospec = n? --n, (soxr_datatype_t)atoi(*arg++) : 0; unsigned long const q_recipe= n? --n, strtoul(*arg++, 0, 16) : SOXR_HQ; unsigned long const q_flags = n? --n, strtoul(*arg++, 0, 16) : 0; double const passband_end = n? --n, atof(*arg++) : 0; double const stopband_begin = n? --n, atof(*arg++) : 0; double const phase_response = n? --n, atof(*arg++) : -1; int const use_threads = n? --n, atoi(*arg++) : 1; soxr_datatype_t const otype = ospec & 3; soxr_quality_spec_t q_spec = soxr_quality_spec(q_recipe, q_flags); soxr_io_spec_t io_spec = soxr_io_spec(itype, otype); soxr_runtime_spec_t const runtime_spec = soxr_runtime_spec(!use_threads); /* Allocate resampling input and output buffers in proportion to the input * and output rates: */ #define buf_total_len 15000 /* In samples per channel. */ size_t const osize = soxr_datatype_size(otype) * chans; size_t const isize = soxr_datatype_size(itype) * chans; size_t const olen0= (size_t)(orate * buf_total_len / (irate + orate) + .5); size_t const olen = min(max(olen0, 1), buf_total_len - 1); size_t const ilen = buf_total_len - olen; void * const obuf = malloc(osize * olen); void * const ibuf = malloc(isize * ilen); size_t odone = 0, clips = 0, omax = 0, i; soxr_error_t error; soxr_t soxr; int32_t seed = 0; char const * e = getenv("SOXR_THROUGHPUT_GAIN"); double gain = e? atof(e) : .5; /* Overrides (if given): */ if (passband_end > 0) q_spec.passband_end = passband_end / 100; if (stopband_begin > 0) q_spec.stopband_begin = stopband_begin / 100; if (phase_response >=0) q_spec.phase_response = phase_response; io_spec.flags = ospec & ~7u; /* Create a stream resampler: */ soxr = soxr_create( irate, orate, chans, /* Input rate, output rate, # of channels. */ &error, /* To report any error during creation. */ &io_spec, &q_spec, &runtime_spec); #define ranqd1(x) ((x) = 1664525 * (x) + 1013904223) /* int32_t x */ #define dranqd1(x) (ranqd1(x) * (1. / (65536. * 32768.))) /* [-1,1) */ #define RAND (dranqd1(seed) * gain) #define DURATION_MSECS 125 #define NUM_ATTEMPTS 8 if (!error) { /* If all is well, run the resampler: */ engine = soxr_engine(soxr); switch (itype & 3) { case 0: for (i=0;i<ilen*chans; ((float *)ibuf)[i]=(float )RAND, ++i); break; case 1: for (i=0;i<ilen*chans; ((double *)ibuf)[i]=(double )RAND, ++i); break; case 2: for (i=0;i<ilen*chans; ((int32_t *)ibuf)[i]=rint32(65536.*32768*RAND), ++i); break; case 3: for (i=0;i<ilen*chans; ((int16_t *)ibuf)[i]=rint16( 1.*32768*RAND), ++i); break; } /* Resample in blocks: */ for (i=0; i<NUM_ATTEMPTS; ++i) { size_t itotal = 0, ototal = 0; timerStart(DURATION_MSECS); do { size_t const ilen1 = odone < olen? ilen : 0; error = soxr_process(soxr, ibuf, ilen1, NULL, obuf, olen, &odone); itotal += ilen1; ototal += odone; } while (!error && timerRunning()); omax = max(omax, ototal); } } /* Tidy up: */ clips = *soxr_num_clips(soxr); /* Can occur only with integer output. */ soxr_delete(soxr); free(obuf), free(ibuf); /* Diagnostics: */ fprintf(stderr, "%-26s %s; %lu clips; I/O: %s (%-5s) %.2f Ms/s\n", arg0, soxr_strerror(error), (long unsigned)clips, ferror(stdin) || ferror(stdout)? strerror(errno) : "no error", engine, 1e-6 * k / DURATION_MSECS * chans * (double)omax); return !!error; }