Message ID | 3a7d4f82-07af-cffb-a757-a258242b0199@ivitera.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Hi Pavel, Thanks for the reference to your previous discussion and the patches. They were super helpful. As you can see from my reply to Takashi, I'm proposing adding a convert_s32 method that doesn't impose dependency on a HW FPU on alsa-lib. The convert_s32 method would operate on an array of int32's. From the point of view of the plugin developer, the change from convert_s16 to convert_s32 is pretty trivial. The plugins that I personally care about operate internally with floats. The plugin would remain responsible for converting between int32 and float. I agree that a libsoxr plugin would be great. Getting higher quality real-time resampling is my ultimate goal :) Thanks, Flavio -----Original Message----- From: Pavel Hofman <pavel.hofman@ivitera.com> Sent: Wednesday, April 4, 2018 11:17 PM To: Flavio Protasio Ribeiro <flaviopr@microsoft.com>; alsa-devel@alsa-project.org Subject: Re: [alsa-devel] Conversion to int16_t and resolution loss with rate converter plugins Dne 5.4.2018 v 05:05 Flavio Protasio Ribeiro napsal(a): > Hi Folks, > > > > The libsamplerate and speex rate converter plugins only implement the > convert_s16 callback from snd_pcm_rate_ops_t. This has ALSA convert > the buffer to int16_t before handing it over to the plugin for > resampling. On devices with more than 16 effective bits, this implies > words gets truncated and bits are lost. > > > > Specifically for libsamplerate, the resampling is internally > implemented with floats, so truncating to 16 bits does not offer a > computational benefit. > > > > I get why only convert_s16 is implemented for plugins that aren't part > of the main alsa-lib package. The more generic convert callback comes > with the burden having the plugin support conversion from/to any of > the ALSA data types (or alternatively, having the plugin source > include plugin_ops.h and its dependencies). So here's what I > propose: replace convert_s16 with a convert_s32 callback which uses > int32_t instead of int16_t. This would preserve all bits from the > device and keep the plugin interface simple. Of course this means > plugins have to be updated to use convert_s32 and rebuilt. > > Hi, Many years ago I tried to extend the rate API to float, the native formats of libsamplerate and speex. I go stuck on float support of all platforms, perhaps you can get something from the discussion and patches. https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fmailman.alsa-project.org%2Fpipermail%2Falsa-devel%2F2011-June%2F041059.html&data=02%7C01%7Cflaviopr%40microsoft.com%7C1a39272ef41948b9e0e508d59abce88d%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C1%7C636585058520946316&sdata=y3iBvFGetAKtrkVO%2FUlHUUHSKpXSyko8pJme6NSlpQA%3D&reserved=0 https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fmailman.alsa-project.org%2Fpipermail%2Falsa-devel%2F2011-July%2F041503.html&data=02%7C01%7Cflaviopr%40microsoft.com%7C1a39272ef41948b9e0e508d59abce88d%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C1%7C636585058520946316&sdata=4%2F%2BIryERoT4btWN%2FGzYQmLH2Q86IPGr7odNuSAxJIVM%3D&reserved=0 If we succeed in adding >16 bit API to the rate plugin, perhaps supporting libsoxr would be the next step which would bring great value (performance vs. CPU load) to alsa-lib. Unfortunately that is not just about conversion, there are other quirks to iron out... Anyway, thanks a lot and good luck to your very useful endeavour. Best regards, Pavel.
Dne 5.4.2018 v 23:21 Flavio Protasio Ribeiro napsal(a): > Hi Pavel, > > Thanks for the reference to your previous discussion and the patches. > They were super helpful. As you can see from my reply to Takashi, I'm > proposing adding a convert_s32 method that doesn't impose dependency > on a HW FPU on alsa-lib. The convert_s32 method would operate on an > array of int32's. > > From the point of view of the plugin developer, the change from > convert_s16 to convert_s32 is pretty trivial. The plugins that I > personally care about operate internally with floats. The plugin > would remain responsible for converting between int32 and float. Sounds much better than my attempt at float API. > > I agree that a libsoxr plugin would be great. Getting higher quality > real-time resampling is my ultimate goal :) If you make it work, you will be praised by countless users :-) But the existing rate API will have to be modified since libsoxr behaves a bit different to speex or libresample - see the library author discussing the issues http://mailman.alsa-project.org/pipermail/alsa-devel/2013-September/066764.html Thanks, Pavel.
From 34fb26dc0a95f7d1950abe2582cf79219d1876a9 Mon Sep 17 00:00:00 2001 From: Pavel Hofman <pavel.hofman@ivitera.com> Date: Tue, 28 Jun 2011 08:55:08 +0200 Subject: [PATCH - resample 1/1] Using float instead of s16 for libsamplerate Natively libsamplerate operates in floats. Using the new convert_float API instead of dropping resoluton in convert_s16. Signed-off-by: Pavel Hofman <pavel.hofman@ivitera.com> diff --git a/rate/rate_samplerate.c b/rate/rate_samplerate.c index 53a0627..c612983 100644 --- a/rate/rate_samplerate.c +++ b/rate/rate_samplerate.c @@ -23,12 +23,12 @@ #include <alsa/asoundlib.h> #include <alsa/pcm_rate.h> +typedef float float_t; + struct rate_src { double ratio; int converter; unsigned int channels; - float *src_buf; - float *dst_buf; SRC_STATE *state; SRC_DATA data; }; @@ -53,9 +53,6 @@ static void pcm_src_free(void *obj) { struct rate_src *rate = obj; - free(rate->src_buf); - free(rate->dst_buf); - rate->src_buf = rate->dst_buf = NULL; if (rate->state) { src_delete(rate->state); @@ -79,17 +76,6 @@ static int pcm_src_init(void *obj, snd_pcm_rate_info_t *info) rate->ratio = (double)info->out.rate / (double)info->in.rate; - free(rate->src_buf); - rate->src_buf = malloc(sizeof(float) * rate->channels * info->in.period_size); - free(rate->dst_buf); - rate->dst_buf = malloc(sizeof(float) * rate->channels * info->out.period_size); - if (! rate->src_buf || ! rate->dst_buf) { - pcm_src_free(rate); - return -ENOMEM; - } - - rate->data.data_in = rate->src_buf; - rate->data.data_out = rate->dst_buf; rate->data.src_ratio = rate->ratio; rate->data.end_of_input = 0; @@ -112,8 +98,8 @@ static void pcm_src_reset(void *obj) src_reset(rate->state); } -static void pcm_src_convert_s16(void *obj, int16_t *dst, unsigned int dst_frames, - const int16_t *src, unsigned int src_frames) +static void pcm_src_convert_float(void *obj, float_t *dst, unsigned int dst_frames, + const float_t *src, unsigned int src_frames) { struct rate_src *rate = obj; unsigned int ofs; @@ -121,15 +107,17 @@ static void pcm_src_convert_s16(void *obj, int16_t *dst, unsigned int dst_frames rate->data.input_frames = src_frames; rate->data.output_frames = dst_frames; rate->data.end_of_input = 0; + rate->data.data_in = src; + rate->data.data_out = dst; + - src_short_to_float_array(src, rate->src_buf, src_frames * rate->channels); src_process(rate->state, &rate->data); if (rate->data.output_frames_gen < dst_frames) ofs = dst_frames - rate->data.output_frames_gen; else ofs = 0; - src_float_to_short_array(rate->dst_buf, dst + ofs * rate->channels, - rate->data.output_frames_gen * rate->channels); + /*src_float_to_short_array(rate->dst_buf, dst + ofs * rate->channels, + rate->data.output_frames_gen * rate->channels); */ } static void pcm_src_close(void *obj) @@ -157,7 +145,7 @@ static snd_pcm_rate_ops_t pcm_src_ops = { .free = pcm_src_free, .reset = pcm_src_reset, .adjust_pitch = pcm_src_adjust_pitch, - .convert_s16 = pcm_src_convert_s16, + .convert_float = pcm_src_convert_float, .input_frames = input_frames, .output_frames = output_frames, #if SND_PCM_RATE_PLUGIN_VERSION >= 0x010002 -- 1.7.0.4