std::pair<size_t, size_t> Resample::Process(double factor, float *inBuffer, size_t inBufferLen, bool lastFlag, float *outBuffer, size_t outBufferLen) { size_t idone, odone; if (mbWantConstRateResampling) { soxr_process(mHandle.get(), inBuffer , (lastFlag? ~inBufferLen : inBufferLen), &idone, outBuffer, outBufferLen, &odone); } else { soxr_set_io_ratio(mHandle.get(), 1/factor, 0); inBufferLen = lastFlag? ~inBufferLen : inBufferLen; soxr_process(mHandle.get(), inBuffer , inBufferLen , &idone, outBuffer, outBufferLen, &odone); } return { idone, odone }; }
int Resample::Process(double factor, float *inBuffer, int inBufferLen, bool lastFlag, int *inBufferUsed, float *outBuffer, int outBufferLen) { size_t idone, odone; if (mbWantConstRateResampling) { soxr_process((soxr_t)mHandle, inBuffer , (size_t)(lastFlag? ~inBufferLen : inBufferLen), &idone, outBuffer, (size_t) outBufferLen, &odone); } else { soxr_set_io_ratio((soxr_t)mHandle, 1/factor, 0); inBufferLen = lastFlag? ~inBufferLen : inBufferLen; soxr_process((soxr_t)mHandle, inBuffer , (size_t)inBufferLen , &idone, outBuffer, (size_t)outBufferLen, &odone); } *inBufferUsed = (int)idone; return (int)odone; }
static int flush(struct SwrContext *s){ s->delayed_samples_fixup = soxr_delay((soxr_t)s->resample); soxr_process((soxr_t)s->resample, NULL, 0, NULL, NULL, 0, NULL); { float f; size_t idone, odone; soxr_process((soxr_t)s->resample, &f, 0, &idone, &f, 0, &odone); s->delayed_samples_fixup -= soxr_delay((soxr_t)s->resample); } return 0; }
// convert channels, src is interlaced as LRLRLR... // return: # of samples rendered size_t DSD2PCM::Render(uint8_t* src, size_t src_size, size_t block_size, int lsbf, uint8_t* dst, size_t samplesToRender) { std::vector<float> float_data(src_size, 0), resample_data(src_size, 0); size_t idone = 0, odone = 0; if (flush_phase) { return 0; // RenderFlush(dst, samplesToRender); } for (int ch = 0; ch < channels; ++ch) { ds[ch].translate(src_size / channels, src + ch * block_size, (block_size > 1) ? 1 : channels, lsbf, float_data.data() + ch, channels); } soxr_process(soxr, float_data.data(), src_size / channels, &idone, resample_data.data(), src_size / channels, &odone); if (odone > 0) { buffer.insert(buffer.end(), resample_data.begin(), resample_data.begin() + odone * channels); buffer_stored += odone; } if (buffer_stored >= samplesToRender) { size_t samplesWritten = writeFinal(buffer, samplesToRender, dst); if (samplesWritten > 0) { buffer.erase(buffer.begin(), buffer.begin() + samplesToRender * channels); buffer_stored -= samplesWritten; return samplesWritten; } } return 0; }
DspChunk DspRate::ProcessEosChunk(soxr_t soxr, DspChunk& chunk) { assert(soxr); DspChunk output; if (!chunk.IsEmpty()) output = ProcessChunk(soxr, chunk); for (;;) { DspChunk tailChunk(DspFormat::Float, m_channels, m_outputRate, m_outputRate); size_t inputDone = 0; size_t outputDo = tailChunk.GetFrameCount(); size_t outputDone = 0; soxr_process(soxr, nullptr, 0, &inputDone, tailChunk.GetData(), outputDo, &outputDone); tailChunk.ShrinkTail(outputDone); DspChunk::MergeChunks(output, tailChunk); if (outputDone < outputDo) break; } return output; }
static int process( struct ResampleContext * c, AudioData *dst, int dst_size, AudioData *src, int src_size, int *consumed){ size_t idone, odone; soxr_error_t error = soxr_set_error((soxr_t)c, soxr_set_num_channels((soxr_t)c, src->ch_count)); error = soxr_process((soxr_t)c, src->ch, (size_t)src_size, &idone, dst->ch, (size_t)dst_size, &odone); *consumed = (int)idone; return error? -1 : odone; }
int ConstRateResample::Process(double factor, float *inBuffer, int inBufferLen, bool lastFlag, int *inBufferUsed, float *outBuffer, int outBufferLen) { size_t idone , odone; soxr_process((soxr_t)mHandle, inBuffer , (size_t)(lastFlag? ~inBufferLen : inBufferLen), &idone, outBuffer, (size_t) outBufferLen, &odone); *inBufferUsed = (int)idone; return (int)odone; }
static block_t * SoXR_Resample( filter_t *p_filter, soxr_t soxr, block_t *p_in, size_t i_olen ) { filter_sys_t *p_sys = p_filter->p_sys; size_t i_idone, i_odone; const size_t i_oframesize = p_filter->fmt_out.audio.i_bytes_per_frame; const size_t i_ilen = p_in ? p_in->i_nb_samples : 0; block_t *p_out = i_ilen >= i_olen ? p_in : block_Alloc( i_olen * i_oframesize ); soxr_error_t error = soxr_process( soxr, p_in ? p_in->p_buffer : NULL, i_ilen, &i_idone, p_out->p_buffer, i_olen, &i_odone ); if( error ) { msg_Err( p_filter, "soxr_process failed: %s", soxr_strerror( error ) ); block_Release( p_out ); goto error; } if( unlikely( i_idone < i_ilen ) ) msg_Err( p_filter, "lost %zd of %zd input frames", i_ilen - i_idone, i_idone); p_out->i_buffer = i_odone * i_oframesize; p_out->i_nb_samples = i_odone; p_out->i_length = vlc_tick_from_samples(i_odone, p_filter->fmt_out.audio.i_rate); if( p_in ) { p_sys->i_last_olen = i_olen; p_sys->last_soxr = soxr; } else { soxr_clear( soxr ); p_sys->i_last_olen = 0; p_sys->last_soxr = NULL; } error: if( p_in && p_out != p_in ) block_Release( p_in ); return p_out; }
size_t DSD2PCM::RenderLast() { const int src_size = 4096; std::vector<float> resample_data(src_size, 0); if (flush_phase) return buffer_stored; size_t idone = 0, odone = 0; do { soxr_process(soxr, NULL, 0, &idone, resample_data.data(), src_size / channels, &odone); if (odone > 0) { buffer.insert(buffer.end(), resample_data.begin(), resample_data.begin() + odone * channels); buffer_stored += odone; } } while (odone > 0); flush_phase = true; return buffer_stored; }
DspChunk DspRate::ProcessChunk(soxr_t soxr, DspChunk& chunk) { assert(soxr); assert(!chunk.IsEmpty()); assert(chunk.GetRate() == m_inputRate); assert(chunk.GetChannelCount() == m_channels); DspChunk::ToFloat(chunk); size_t outputFrames = (size_t)(2 * (uint64_t)chunk.GetFrameCount() * m_outputRate / m_inputRate); DspChunk output(DspFormat::Float, chunk.GetChannelCount(), outputFrames, m_outputRate); size_t inputDone = 0; size_t outputDone = 0; soxr_process(soxr, chunk.GetData(), chunk.GetFrameCount(), &inputDone, output.GetData(), output.GetFrameCount(), &outputDone); assert(inputDone == chunk.GetFrameCount()); output.ShrinkTail(outputDone); return output; }
static int flush(struct SwrContext *s){ soxr_process((soxr_t)s->resample, NULL, 0, NULL, NULL, 0, NULL); return 0; }
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(); }
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; }