Beispiel #1
0
void resample_samples(struct processstate *process) {
	size_t idone, odone;
	size_t clip_cnt;
	
	soxr_error_t error =
		SOXR(r, process, r->resampler, process->inbuf, process->in_frames, &idone, process->outbuf, process->max_out_frames, &odone);
	if (error) {
		LOG_INFO("soxr_process error: %s", soxr_strerror(error));
		return;
	}
	
	if (idone != process->in_frames) {
		// should not get here if buffers are big enough...
		LOG_ERROR("should not get here - partial sox process: %u of %u processed %u of %u out",
				  (unsigned)idone, process->in_frames, (unsigned)odone, process->max_out_frames);
	}
	
	process->out_frames = odone;
	process->total_in  += idone;
	process->total_out += odone;
	
	clip_cnt = *(SOXR(r, num_clips, r->resampler));
	if (clip_cnt - r->old_clips) {
		LOG_SDEBUG("resampling clips: %u", (unsigned)(clip_cnt - r->old_clips));
		r->old_clips = clip_cnt;
	}
}
Beispiel #2
0
bool resample_drain(struct processstate *process) {
	size_t odone;
	size_t clip_cnt;
		
	soxr_error_t error = SOXR(r, process, r->resampler, NULL, 0, NULL, process->outbuf, process->max_out_frames, &odone);
	if (error) {
		LOG_INFO("soxr_process error: %s", soxr_strerror(error));
		return true;
	}
	
	process->out_frames = odone;
	process->total_out += odone;
	
	clip_cnt = *(SOXR(r, num_clips, r->resampler));
	if (clip_cnt - r->old_clips) {
		LOG_DEBUG("resampling clips: %u", (unsigned)(clip_cnt - r->old_clips));
		r->old_clips = clip_cnt;
	}
	
	if (odone == 0) {

		LOG_INFO("resample track complete - total track clips: %u", r->old_clips);

		SOXR(r, delete, r->resampler);
		r->resampler = NULL;

		return true;

	} else {
Beispiel #3
0
void resample_samples(struct thread_ctx_s *ctx) {
	struct soxr *r = ctx->decode.process_handle;
	size_t idone, odone;
	size_t clip_cnt;

	soxr_error_t error =
		SOXR(&gr, process, r->resampler, ctx->process.inbuf, ctx->process.in_frames, &idone, ctx->process.outbuf, ctx->process.max_out_frames, &odone);
	if (error) {
		LOG_INFO("[%p]: soxr_process error: %s", ctx, soxr_strerror(error));
		return;
	}

	if (idone != ctx->process.in_frames) {
		// should not get here if buffers are big enough...
		LOG_ERROR("[%p]: should not get here - partial sox process: %u of %u processed %u of %u out",
				  ctx, (unsigned)idone, ctx->process.in_frames, (unsigned)odone, ctx->process.max_out_frames);
	}
	
	ctx->process.out_frames = odone;
	ctx->process.total_in  += idone;
	ctx->process.total_out += odone;

	clip_cnt = *(SOXR(&gr, num_clips, r->resampler));
	if (clip_cnt - r->old_clips) {
		LOG_SDEBUG("[%p]: resampling clips: %u", ctx, (unsigned)(clip_cnt - r->old_clips));
		r->old_clips = clip_cnt;
	}
}
Beispiel #4
0
bool resample_drain(struct thread_ctx_s *ctx) {
	struct soxr *r = ctx->decode.process_handle;
	size_t odone;
	size_t clip_cnt;
		
	soxr_error_t error = SOXR(&gr, process, r->resampler, NULL, 0, NULL, ctx->process.outbuf, ctx->process.max_out_frames, &odone);
	if (error) {
		LOG_INFO("[%p]: soxr_process error: %s", ctx, soxr_strerror(error));
		return true;
	}
	
	ctx->process.out_frames = odone;
	ctx->process.total_out += odone;

	clip_cnt = *(SOXR(&gr, num_clips, r->resampler));
	if (clip_cnt - r->old_clips) {
		LOG_DEBUG("[%p]: resampling clips: %u", ctx, (unsigned)(clip_cnt - r->old_clips));
		r->old_clips = clip_cnt;
	}
	
	if (odone == 0) {

		LOG_INFO("[%]: resample track complete - total track clips: %u", ctx, r->old_clips);

		SOXR(&gr, delete, r->resampler);
		r->resampler = NULL;

		return true;

	} else {
Beispiel #5
0
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;
}
Beispiel #6
0
SoxrResampler::SoxrResampler(const SOXRModule &module,
                             const std::shared_ptr<ISource> &src,
                             unsigned rate)
    : FilterBase(src), m_module(module), m_position(0)
{
    const AudioStreamBasicDescription &asbd = src->getSampleFormat();
    unsigned bits = 32;
    if (asbd.mBitsPerChannel > 32
        || (asbd.mFormatFlags & kAudioFormatFlagIsSignedInteger) &&
           asbd.mBitsPerChannel > 24)
        bits = 64;
    m_asbd = cautil::buildASBDForPCM(rate, asbd.mChannelsPerFrame,
                                     bits, kAudioFormatFlagIsFloat);

    soxr_quality_spec_t qspec;
    soxr_io_spec_t iospec;
    if (bits == 32) {
        qspec = m_module.quality_spec(SOXR_HQ, 0);
        iospec = m_module.io_spec(SOXR_FLOAT32_I, SOXR_FLOAT32_I);
    } else {
        qspec = m_module.quality_spec(SOXR_VHQ, 0);
        iospec = m_module.io_spec(SOXR_FLOAT64_I, SOXR_FLOAT64_I);
    }
    soxr_error_t error = 0;
    soxr_t resampler = m_module.create(asbd.mSampleRate, rate,
                                       asbd.mChannelsPerFrame,
                                       &error, &iospec, &qspec, 0);
    if (!resampler)
        throw std::runtime_error(strutil::format("soxr: %s",
                                                 soxr_strerror(error)));
    m_resampler = std::shared_ptr<soxr>(resampler, m_module.delete_);
    m_module.set_input_fn(resampler, staticInputProc, this, 0x10000);
    double factor = rate / asbd.mSampleRate;
    m_length = source()->length();
    if (m_length != ~0ULL)
        m_length = m_length * factor + .5;
}
Beispiel #7
0
void BE_ST_InitAudio(void)
{
	g_sdlAudioSubsystemUp = false;
	g_sdlEmulatedOPLChipReady = false;
	int inSampleRate = BE_Cross_GetSelectedGameVerSampleRate();
	bool doDigitized = (inSampleRate != 0);
	if (!doDigitized)
		inSampleRate = OPL_SAMPLE_RATE;

	if (g_refKeenCfg.sndSubSystem)
	{
		if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
		{
			BE_Cross_LogMessage(BE_LOG_MSG_WARNING, "SDL audio system initialization failed,\n%s\n", SDL_GetError());
		}
		else
		{
			g_sdlAudioSpec.freq = g_refKeenCfg.sndSampleRate;
#ifdef MIXER_SAMPLE_FORMAT_FLOAT
			g_sdlAudioSpec.format = AUDIO_F32SYS;
#elif (defined MIXER_SAMPLE_FORMAT_SINT16)
			g_sdlAudioSpec.format = AUDIO_S16SYS;
#endif
			g_sdlAudioSpec.channels = 1;
			// Should be some power-of-two roughly proportional to the sample rate; Using 1024 for 48000Hz.
			for (g_sdlAudioSpec.samples = 1; g_sdlAudioSpec.samples < g_refKeenCfg.sndSampleRate/64; g_sdlAudioSpec.samples *= 2)
			{
			}

			if (doDigitized)
				g_sdlAudioSpec.callback = (g_refKeenCfg.sndSampleRate == inSampleRate) ? BEL_ST_Simple_DigiCallBack : BEL_ST_Resampling_DigiCallBack;
			else
				g_sdlAudioSpec.callback = ((g_refKeenCfg.sndSampleRate == inSampleRate) || !g_refKeenCfg.oplEmulation) ? BEL_ST_Simple_EmuCallBack : BEL_ST_Resampling_EmuCallBack;

			g_sdlAudioSpec.userdata = NULL;
			if (SDL_OpenAudio(&g_sdlAudioSpec, NULL))
			{
				BE_Cross_LogMessage(BE_LOG_MSG_WARNING, "Cannot open SDL audio device,\n%s\n", SDL_GetError());
				SDL_QuitSubSystem(SDL_INIT_AUDIO);
			}
			else
			{
#ifdef REFKEEN_CONFIG_THREADS
				g_sdlCallbackMutex = SDL_CreateMutex();
				if (!g_sdlCallbackMutex)
				{
					BE_Cross_LogMessage(BE_LOG_MSG_ERROR, "Cannot create recursive mutex for SDL audio callback,\n%s\nClosing SDL audio subsystem\n", SDL_GetError());
					SDL_CloseAudio();
					SDL_QuitSubSystem(SDL_INIT_AUDIO);
				}
				else
#endif
				{
					BE_Cross_LogMessage(BE_LOG_MSG_NORMAL, "Audio subsystem initialized, requested spec: freq %d, format %u, channels %d, samples %u\n", (int)g_sdlAudioSpec.freq, (unsigned int)g_sdlAudioSpec.format, (int)g_sdlAudioSpec.channels, (unsigned int)g_sdlAudioSpec.samples);
					g_sdlAudioSubsystemUp = true;
				}
			}
		}
	}
	// If the audio subsystem is off, let us simulate a byte rate
	// of 1000Hz (same as SDL_GetTicks() time units)
	if (!g_sdlAudioSubsystemUp)
	{
		g_sdlAudioSpec.freq = doDigitized ? inSampleRate : (NUM_OF_BYTES_FOR_SOUND_CALLBACK_WITH_DISABLED_SUBSYSTEM / sizeof(BE_ST_SndSample_T));
		g_sdlAudioSpec.callback = doDigitized ? BEL_ST_Resampling_DigiCallBack : BEL_ST_Resampling_EmuCallBack;
		return;
	}

	if (g_refKeenCfg.oplEmulation)
	{
		YM3812Init(1, 3579545, OPL_SAMPLE_RATE);
		g_sdlEmulatedOPLChipReady = true;
	}

	if ((doDigitized || g_sdlEmulatedOPLChipReady) && (g_sdlAudioSpec.freq != inSampleRate))
	{
		// Should allocate this first, for g_sdlSrcData.data_in
		g_sdlMiscOutNumOfSamples = 2*g_sdlAudioSpec.samples;
		g_sdlMiscOutSamples = (BE_ST_SndSample_T *)malloc(sizeof(BE_ST_SndSample_T) * g_sdlMiscOutNumOfSamples); 
		if (g_sdlMiscOutSamples == NULL)
			BE_ST_ExitWithErrorMsg("BE_ST_InitAudio: Out of memory! (Failed to allocate g_sdlMiscOutSamples.)");

#ifndef REFKEEN_RESAMPLER_NONE
		if (g_refKeenCfg.useResampler)
		{
#if (!defined REFKEEN_RESAMPLER_LIBRESAMPLE) && (!defined REFKEEN_RESAMPLER_LIBAVCODEC)
			char errMsg[160];
#endif

#if (defined REFKEEN_RESAMPLER_LIBSWRESAMPLE)
			g_sdlSwrContext = swr_alloc_set_opts(
				NULL,                // allocating a new context
				AV_CH_LAYOUT_MONO,   // out channels layout
				AV_SAMPLE_FMT_S16,   // out format
				g_sdlAudioSpec.freq, // out rate
				AV_CH_LAYOUT_MONO,   // in channels layout
				AV_SAMPLE_FMT_S16,   // in format
				inSampleRate,        // in rate
				0,
				NULL
			);
			if (g_sdlSwrContext == NULL)
				BE_ST_ExitWithErrorMsg("BE_ST_InitAudio: swr_alloc_set_opts failed!");
			int error = swr_init(g_sdlSwrContext);
			if (error != 0)
			{
				// av_err2str requires libavutil/libavutil-ffmpeg, so don't convert code to string
				snprintf(errMsg, sizeof(errMsg), "BE_ST_InitAudio: swr_init failed! Error code: %d", error);
				BE_ST_ExitWithErrorMsg(errMsg);
			}
#elif (defined REFKEEN_RESAMPLER_LIBAVRESAMPLE)
			g_sdlAvAudioResampleContext = avresample_alloc_context();
			if (g_sdlAvAudioResampleContext == NULL)
				BE_ST_ExitWithErrorMsg("BE_ST_InitAudio: avresample_alloc_context failed!");
			av_opt_set_int(g_sdlAvAudioResampleContext, "in_channel_layout",  AV_CH_LAYOUT_MONO,   0);
			av_opt_set_int(g_sdlAvAudioResampleContext, "out_channel_layout", AV_CH_LAYOUT_MONO,   0);
			av_opt_set_int(g_sdlAvAudioResampleContext, "in_sample_rate",     inSampleRate,        0);
			av_opt_set_int(g_sdlAvAudioResampleContext, "out_sample_rate",    g_sdlAudioSpec.freq, 0);
			av_opt_set_int(g_sdlAvAudioResampleContext, "in_sample_fmt",      AV_SAMPLE_FMT_S16,   0);
			av_opt_set_int(g_sdlAvAudioResampleContext, "out_sample_fmt",     AV_SAMPLE_FMT_S16,   0);
			int error = avresample_open(g_sdlAvAudioResampleContext);
			if (error != 0)
			{
				// av_err2str requires libavutil/libavutil-ffmpeg, so don't convert code to string
				snprintf(errMsg, sizeof(errMsg), "BE_ST_InitAudio: swr_init failed! Error code: %d", error);
				BE_ST_ExitWithErrorMsg(errMsg);
			}
#elif (defined REFKEEN_RESAMPLER_LIBAVCODEC)
			avcodec_register_all();
			g_sdlAvResampleContext = av_resample_init(
				g_sdlAudioSpec.freq,	// out rate
				inSampleRate,	// in rate
				16,	// filter length
				10,	// phase count
				0,	// linear FIR filter
				1.0	// cutoff frequency
			);
			if (g_sdlAvResampleContext == NULL)
				BE_ST_ExitWithErrorMsg("BE_ST_InitAudio: av_resample_init failed!");
#elif (defined REFKEEN_RESAMPLER_LIBRESAMPLE)
			g_sdlResampleFactor = (double)g_sdlAudioSpec.freq/inSampleRate;
			g_sdlResampleHandle = resample_open(0, g_sdlResampleFactor, g_sdlResampleFactor);
			if (g_sdlResampleHandle == NULL)
				BE_ST_ExitWithErrorMsg("BE_ST_InitAudio: resample_open failed!");
#elif (defined REFKEEN_RESAMPLER_LIBSOXR)
			soxr_io_spec_t io_spec = soxr_io_spec(SOXR_INT16, SOXR_INT16);
			soxr_quality_spec_t q_spec = soxr_quality_spec(SOXR_LQ, 0); // Default quality spec adds an audible latency for resampling to 8000Hz
			soxr_error_t error;
			g_sdlSoxr = soxr_create(
				inSampleRate, // in rate
				g_sdlAudioSpec.freq, // out rate
				1, // channels
				&error,
				&io_spec,
				&q_spec,
				NULL // runtime spec
			);
			if (g_sdlSoxr == NULL)
			{
				snprintf(errMsg, sizeof(errMsg), "BE_ST_InitAudio: soxr_create failed!\nError: %s", soxr_strerror(error));
				BE_ST_ExitWithErrorMsg(errMsg);
			}
#elif (defined REFKEEN_RESAMPLER_LIBSPEEXDSP)
			int error;
			g_sdlSpeexResamplerState = speex_resampler_init(
				1, // channels
				inSampleRate, // in rate
				g_sdlAudioSpec.freq, // out rate
				0, // quality in the range 0-10 (10 is higher)
				&error
			);
			if (g_sdlSpeexResamplerState == NULL)
			{
				snprintf(errMsg, sizeof(errMsg), "BE_ST_InitAudio: speex_resampler_init failed! Error code: %d\nError: %s", error, speex_resampler_strerror(error));
				BE_ST_ExitWithErrorMsg(errMsg);
			}
#elif (defined REFKEEN_RESAMPLER_LIBSAMPLERATE)
			int error;
			g_sdlSrcResampler = src_new(SRC_SINC_FASTEST, 1, &error);
			if (g_sdlSrcResampler == NULL)
			{
				snprintf(errMsg, sizeof(errMsg), "BE_ST_InitAudio: src_new failed!\nError code: %d", error);
				BE_ST_ExitWithErrorMsg(errMsg);
			}
			g_sdlSrcData.data_in = doDigitized ? g_sdlMiscOutSamples : g_sdlALOutSamples;
			g_sdlSrcData.src_ratio = (double)g_sdlAudioSpec.freq / inSampleRate;
#endif
		}
		else
#endif // REFKEEN_RESAMPLER_NONE
		{
			// The sum of all entries should be g_sdlAudioSpec.freq,
			// "uniformly" distributed over g_sdlALSampleRateConvTable
			g_sdlSampleRateConvTable = (int *)malloc(sizeof(int) * inSampleRate);
			if (g_sdlSampleRateConvTable == NULL)
				BE_ST_ExitWithErrorMsg("BE_ST_InitAudio: Failed to allocate memory for sample rate conversion!");
			g_sdlSampleRateConvTableSize = inSampleRate;
			for (int i = 0; i < inSampleRate; ++i)
			{
				// Using uint64_t cause an overflow is possible
				g_sdlSampleRateConvTable[i] = ((uint64_t)(i+1)*(uint64_t)g_sdlAudioSpec.freq/inSampleRate)-(uint64_t)i*(uint64_t)g_sdlAudioSpec.freq/inSampleRate;
			}
			g_sdlSampleRateConvCurrIndex = 0;
			g_sdlSampleRateConvCounter = 0;
		}
	}
}
Beispiel #8
0
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;
}
Beispiel #9
0
bool resample_newstream(struct processstate *process, unsigned raw_sample_rate, unsigned max_sample_rate) {
	unsigned outrate;

	if (r->max_rate) {
		outrate = max_sample_rate;
	} else {
		outrate = raw_sample_rate;
		while (outrate <= max_sample_rate) outrate <<= 1;
		outrate >>= 1;
	}

	process->in_sample_rate = raw_sample_rate;
	process->out_sample_rate = outrate;

	if (r->resampler) {
		r->soxr_delete(r->resampler);
		r->resampler = NULL;
	}

	if (raw_sample_rate != outrate) {

		soxr_io_spec_t io_spec;
		soxr_quality_spec_t q_spec;
		soxr_error_t error;

		LOG_INFO("resampling from %u -> %u", raw_sample_rate, outrate);

		io_spec = r->soxr_io_spec(SOXR_INT32_I, SOXR_INT32_I);
		io_spec.scale = r->scale;

		q_spec = r->soxr_quality_spec(r->q_recipe, r->q_flags);
		if (r->q_precision > 0) {
			q_spec.precision = r->q_precision;
		}
		if (r->q_passband_end > 0) {
			q_spec.passband_end = r->q_passband_end;
		}
		if (r->q_stopband_begin > 0) {
			q_spec.stopband_begin = r->q_stopband_begin;
		}
		if (r->q_phase_response > -1) {
			q_spec.phase_response = r->q_phase_response;
		}

		LOG_DEBUG("resampling with soxr_quality_spec_t[precision: %03.1f, passband_end: %03.6f, stopband_begin: %03.6f, "
				  "phase_response: %03.1f, flags: 0x%02x], soxr_io_spec_t[scale: %03.2f]", q_spec.precision,
				  q_spec.passband_end, q_spec.stopband_begin, q_spec.phase_response, q_spec.flags, io_spec.scale);

		r->resampler = r->soxr_create(raw_sample_rate, outrate, 2, &error, &io_spec, &q_spec, NULL);
		if (error) {
			LOG_INFO("soxr_create error: %s", soxr_strerror(error));
			return false;
		}

		r->old_clips = 0;
		return true;

	} else {

		LOG_INFO("disable resampling - rates match");
		return false;
	}
}
Beispiel #10
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();

}
Beispiel #11
0
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;
}