All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH alsa-plugins 0/2] Support multiple formats
@ 2021-06-17 10:03 Takashi Iwai
  2021-06-17 10:03 ` [PATCH alsa-plugins 1/2] rate-lav: " Takashi Iwai
  2021-06-17 10:03 ` [PATCH alsa-plugins 2/2] samplerate: " Takashi Iwai
  0 siblings, 2 replies; 3+ messages in thread
From: Takashi Iwai @ 2021-06-17 10:03 UTC (permalink / raw)
  To: alsa-devel

Hi,

this is a patch set to add the multi-format support for the existing
rate plugins.


Takashi

===

Takashi Iwai (2):
  rate-lav: Support multiple formats
  samplerate: Support multiple formats

 rate-lav/rate_lavrate.c | 115 ++++++++++++++++++++++++++++++++++------
 rate/rate_samplerate.c  |  99 ++++++++++++++++++++++++++++------
 2 files changed, 183 insertions(+), 31 deletions(-)

-- 
2.26.2


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH alsa-plugins 1/2] rate-lav: Support multiple formats
  2021-06-17 10:03 [PATCH alsa-plugins 0/2] Support multiple formats Takashi Iwai
@ 2021-06-17 10:03 ` Takashi Iwai
  2021-06-17 10:03 ` [PATCH alsa-plugins 2/2] samplerate: " Takashi Iwai
  1 sibling, 0 replies; 3+ messages in thread
From: Takashi Iwai @ 2021-06-17 10:03 UTC (permalink / raw)
  To: alsa-devel

Now that ALSA rate plugin core allows each rate plugin dealing with
multiple formats, this patch extends the rate-lav plugin to accept
more formats, namely, U8, S16 and S32.  The code has been carefully
modified so that it should still be compilable with old alsa-lib.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 rate-lav/rate_lavrate.c | 115 ++++++++++++++++++++++++++++++++++------
 1 file changed, 99 insertions(+), 16 deletions(-)

diff --git a/rate-lav/rate_lavrate.c b/rate-lav/rate_lavrate.c
index e9c6740ac870..2ab1d8894e63 100644
--- a/rate-lav/rate_lavrate.c
+++ b/rate-lav/rate_lavrate.c
@@ -32,6 +32,8 @@ struct rate_src {
 	unsigned int in_rate;
 	unsigned int out_rate;
 	unsigned int channels;
+
+	unsigned int version;
 };
 
 static snd_pcm_uframes_t input_frames(void *obj ATTRIBUTE_UNUSED,
@@ -52,9 +54,34 @@ static void pcm_src_free(void *obj)
 	swr_free(&rate->avr);
 }
 
+static int to_av_format(snd_pcm_format_t f)
+{
+	switch (f) {
+	case SND_PCM_FORMAT_FLOAT:
+		return AV_SAMPLE_FMT_FLT;
+	case SND_PCM_FORMAT_U8:
+		return AV_SAMPLE_FMT_U8;
+	case SND_PCM_FORMAT_S16:
+		return AV_SAMPLE_FMT_S16;
+	case SND_PCM_FORMAT_S32:
+	default:
+		return AV_SAMPLE_FMT_S32;
+	}
+}
+
+static int support_multi_format(struct rate_src *rate)
+{
+#if SND_PCM_RATE_PLUGIN_VERSION >= 0x010003
+	return rate->version >= 0x010003;
+#else
+	return 0;
+#endif
+}
+
 static int pcm_src_init(void *obj, snd_pcm_rate_info_t *info)
 {
 	struct rate_src *rate = obj;
+	int fmt;
 
 	if (!rate->avr || rate->channels != info->channels) {
 		int ret;
@@ -74,8 +101,12 @@ static int pcm_src_init(void *obj, snd_pcm_rate_info_t *info)
 					  av_get_default_channel_layout(rate->channels), 0);
 		av_opt_set_int(rate->avr, "in_sample_rate", rate->in_rate, 0);
 		av_opt_set_int(rate->avr, "out_sample_rate", rate->out_rate, 0);
-		av_opt_set_sample_fmt(rate->avr, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
-		av_opt_set_sample_fmt(rate->avr, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
+		fmt = support_multi_format(rate) ? info->in.format : SND_PCM_FORMAT_S16;
+		av_opt_set_sample_fmt(rate->avr, "in_sample_fmt",
+				      to_av_format(fmt), 0);
+		fmt = support_multi_format(rate) ? info->out.format : SND_PCM_FORMAT_S16;
+		av_opt_set_sample_fmt(rate->avr, "out_sample_fmt",
+				      to_av_format(fmt), 0);
 
 		ret = swr_init(rate->avr);
 		if (ret < 0) {
@@ -109,12 +140,10 @@ static void pcm_src_reset(void *obj)
 	}
 }
 
-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 do_convert(struct rate_src *rate,
+		       void *dst, unsigned int dst_frames,
+		       const void *src, unsigned int src_frames)
 {
-	struct rate_src *rate = obj;
 	unsigned int total_in = swr_get_delay(rate->avr, rate->in_rate) + src_frames;
 
 	swr_convert(rate->avr, (uint8_t **)&dst, dst_frames,
@@ -125,6 +154,38 @@ static void pcm_src_convert_s16(void *obj, int16_t *dst,
 			     src_frames);
 }
 
+#if SND_PCM_RATE_PLUGIN_VERSION >= 0x010003
+static inline void *get_addr(const snd_pcm_channel_area_t *area, snd_pcm_uframes_t offset)
+{
+	return (char *)area->addr + (area->first + area->step * offset) / 8;
+}
+
+static void pcm_src_convert(void *obj,
+			    const snd_pcm_channel_area_t *dst_areas,
+			    snd_pcm_uframes_t dst_offset,
+			    unsigned int dst_frames,
+			    const snd_pcm_channel_area_t *src_areas,
+			    snd_pcm_uframes_t src_offset,
+			    unsigned int src_frames)
+{
+	struct rate_src *rate = obj;
+	const void *src = get_addr(src_areas, src_offset);
+	void *dst = get_addr(dst_areas, dst_offset);
+
+	do_convert(rate, dst, dst_frames, src, src_frames);
+}
+#endif
+
+static void pcm_src_convert_s16(void *obj, int16_t *dst,
+				unsigned int dst_frames,
+				const int16_t *src,
+				unsigned int src_frames)
+{
+	struct rate_src *rate = obj;
+
+	do_convert(rate, dst, dst_frames, src, src_frames);
+}
+
 static void pcm_src_close(void *obj)
 {
 	pcm_src_free(obj);
@@ -145,12 +206,29 @@ static void dump(void *obj ATTRIBUTE_UNUSED, snd_output_t *out)
 }
 #endif
 
+#if SND_PCM_RATE_PLUGIN_VERSION >= 0x010003
+static int get_supported_formats(void *obj, uint64_t *in_formats,
+				 uint64_t *out_formats,
+				 unsigned int *flags)
+{
+	*in_formats = *out_formats =
+		(1ULL << SND_PCM_FORMAT_U8) |
+		(1ULL << SND_PCM_FORMAT_S16) |
+		(1ULL << SND_PCM_FORMAT_S32);
+	*flags = SND_PCM_RATE_FLAG_INTERLEAVED;
+	return 0;
+}
+#endif
+
 static snd_pcm_rate_ops_t pcm_src_ops = {
 	.close = pcm_src_close,
 	.init = pcm_src_init,
 	.free = pcm_src_free,
 	.reset = pcm_src_reset,
 	.adjust_pitch = pcm_src_adjust_pitch,
+#if SND_PCM_RATE_PLUGIN_VERSION >= 0x010003
+	.convert = pcm_src_convert,
+#endif
 	.convert_s16 = pcm_src_convert_s16,
 	.input_frames = input_frames,
 	.output_frames = output_frames,
@@ -159,30 +237,35 @@ static snd_pcm_rate_ops_t pcm_src_ops = {
 	.get_supported_rates = get_supported_rates,
 	.dump = dump,
 #endif
+#if SND_PCM_RATE_PLUGIN_VERSION >= 0x010003
+	.get_supported_formats = get_supported_formats,
+#endif
 };
 
 int pcm_src_open(unsigned int version, void **objp, snd_pcm_rate_ops_t *ops)
 {
 	struct rate_src *rate;
 
-#if SND_PCM_RATE_PLUGIN_VERSION < 0x010002
-	if (version != SND_PCM_RATE_PLUGIN_VERSION) {
-		fprintf(stderr, "Invalid rate plugin version %x\n", version);
-		return -EINVAL;
-	}
-#endif
 	rate = calloc(1, sizeof(*rate));
 	if (!rate)
 		return -ENOMEM;
 
 	*objp = rate;
 	rate->avr = NULL;
+	rate->version = version;
 #if SND_PCM_RATE_PLUGIN_VERSION >= 0x010002
-	if (version == 0x010001)
+	if (version == 0x010001) {
 		memcpy(ops, &pcm_src_ops, sizeof(snd_pcm_rate_old_ops_t));
-	else
+		return 0;
+	}
+#endif
+#if SND_PCM_RATE_PLUGIN_VERSION >= 0x010003
+	if (version == 0x010002) {
+		memcpy(ops, &pcm_src_ops, sizeof(snd_pcm_rate_v2_ops_t));
+		return 0;
+	}
 #endif
-		*ops = pcm_src_ops;
+	*ops = pcm_src_ops;
 	return 0;
 }
 
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH alsa-plugins 2/2] samplerate: Support multiple formats
  2021-06-17 10:03 [PATCH alsa-plugins 0/2] Support multiple formats Takashi Iwai
  2021-06-17 10:03 ` [PATCH alsa-plugins 1/2] rate-lav: " Takashi Iwai
@ 2021-06-17 10:03 ` Takashi Iwai
  1 sibling, 0 replies; 3+ messages in thread
From: Takashi Iwai @ 2021-06-17 10:03 UTC (permalink / raw)
  To: alsa-devel

Now that ALSA rate plugin core allows each rate plugin dealing with
multiple formats, this patch extends the libsamplerate plugin to
accept more formats, namely, S16 and S32.  The code has been carefully
modified so that it should still be compilable with old alsa-lib.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 rate/rate_samplerate.c | 99 +++++++++++++++++++++++++++++++++++-------
 1 file changed, 84 insertions(+), 15 deletions(-)

diff --git a/rate/rate_samplerate.c b/rate/rate_samplerate.c
index 100d6f2b110e..af0bf98cb4e9 100644
--- a/rate/rate_samplerate.c
+++ b/rate/rate_samplerate.c
@@ -40,9 +40,12 @@
 #include <alsa/pcm_rate.h>
 
 struct rate_src {
+	unsigned int version;
 	double ratio;
 	int converter;
 	unsigned int channels;
+	int in_int;
+	int out_int;
 	float *src_buf;
 	float *dst_buf;
 	SRC_STATE *state;
@@ -109,6 +112,13 @@ static int pcm_src_init(void *obj, snd_pcm_rate_info_t *info)
 	rate->data.src_ratio = rate->ratio;
 	rate->data.end_of_input = 0;
 
+#if SND_PCM_RATE_PLUGIN_VERSION >= 0x010003
+	if (rate->version >= 0x010003) {
+		rate->in_int = info->in.format == SND_PCM_FORMAT_S32;
+		rate->out_int = info->out.format == SND_PCM_FORMAT_S32;
+	}
+#endif
+
 	return 0;
 }
 
@@ -128,24 +138,61 @@ 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 do_convert(struct rate_src *rate,
+		       void *dst, unsigned int dst_frames,
+		       const void *src, unsigned int src_frames)
 {
-	struct rate_src *rate = obj;
 	unsigned int ofs;
 
 	rate->data.input_frames = src_frames;
 	rate->data.output_frames = dst_frames;
 	rate->data.end_of_input = 0;
 	
-	src_short_to_float_array(src, rate->src_buf, src_frames * rate->channels);
+	if (rate->in_int)
+		src_int_to_float_array(src, rate->src_buf, src_frames * rate->channels);
+	else
+		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);
+	if (rate->out_int)
+		src_float_to_int_array(rate->dst_buf, dst + ofs * rate->channels * 4,
+				       rate->data.output_frames_gen * rate->channels);
+	else
+		src_float_to_short_array(rate->dst_buf, dst + ofs * rate->channels * 2,
+					 rate->data.output_frames_gen * rate->channels);
+}
+
+#if SND_PCM_RATE_PLUGIN_VERSION >= 0x010003
+static inline void *get_addr(const snd_pcm_channel_area_t *area, snd_pcm_uframes_t offset)
+{
+	return (char *)area->addr + (area->first + area->step * offset) / 8;
+}
+
+static void pcm_src_convert(void *obj,
+			    const snd_pcm_channel_area_t *dst_areas,
+			    snd_pcm_uframes_t dst_offset,
+			    unsigned int dst_frames,
+			    const snd_pcm_channel_area_t *src_areas,
+			    snd_pcm_uframes_t src_offset,
+			    unsigned int src_frames)
+{
+	struct rate_src *rate = obj;
+	const void *src = get_addr(src_areas, src_offset);
+	void *dst = get_addr(dst_areas, dst_offset);
+
+	do_convert(rate, dst, dst_frames, src, src_frames);
+}
+#endif
+
+static void pcm_src_convert_s16(void *obj, int16_t *dst, unsigned int dst_frames,
+				const int16_t *src, unsigned int src_frames)
+{
+	struct rate_src *rate = obj;
+
+	do_convert(rate, dst, dst_frames, src, src_frames);
 }
 
 static void pcm_src_close(void *obj)
@@ -167,12 +214,28 @@ static void dump(void *obj ATTRIBUTE_UNUSED, snd_output_t *out)
 }
 #endif
 
+#if SND_PCM_RATE_PLUGIN_VERSION >= 0x010003
+static int get_supported_formats(void *obj, uint64_t *in_formats,
+				 uint64_t *out_formats,
+				 unsigned int *flags)
+{
+	*in_formats = *out_formats =
+		(1ULL << SND_PCM_FORMAT_S16) |
+		(1ULL << SND_PCM_FORMAT_S32);
+	*flags = SND_PCM_RATE_FLAG_INTERLEAVED;
+	return 0;
+}
+#endif
+
 static snd_pcm_rate_ops_t pcm_src_ops = {
 	.close = pcm_src_close,
 	.init = pcm_src_init,
 	.free = pcm_src_free,
 	.reset = pcm_src_reset,
 	.adjust_pitch = pcm_src_adjust_pitch,
+#if SND_PCM_RATE_PLUGIN_VERSION >= 0x010003
+	.convert = pcm_src_convert,
+#endif
 	.convert_s16 = pcm_src_convert_s16,
 	.input_frames = input_frames,
 	.output_frames = output_frames,
@@ -181,6 +244,9 @@ static snd_pcm_rate_ops_t pcm_src_ops = {
 	.get_supported_rates = get_supported_rates,
 	.dump = dump,
 #endif
+#if SND_PCM_RATE_PLUGIN_VERSION >= 0x010003
+	.get_supported_formats = get_supported_formats,
+#endif
 };
 
 static int pcm_src_open(unsigned int version, void **objp,
@@ -188,24 +254,27 @@ static int pcm_src_open(unsigned int version, void **objp,
 {
 	struct rate_src *rate;
 
-#if SND_PCM_RATE_PLUGIN_VERSION < 0x010002
-	if (version != SND_PCM_RATE_PLUGIN_VERSION) {
-		fprintf(stderr, "Invalid rate plugin version %x\n", version);
-		return -EINVAL;
-	}
-#endif
 	rate = calloc(1, sizeof(*rate));
 	if (! rate)
 		return -ENOMEM;
+
+	rate->version = version;
 	rate->converter = type;
 
 	*objp = rate;
 #if SND_PCM_RATE_PLUGIN_VERSION >= 0x010002
-	if (version == 0x010001)
+	if (version == 0x010001) {
 		memcpy(ops, &pcm_src_ops, sizeof(snd_pcm_rate_old_ops_t));
-	else
+		return 0;
+	}
+#endif
+#if SND_PCM_RATE_PLUGIN_VERSION >= 0x010003
+	if (version == 0x010002) {
+		memcpy(ops, &pcm_src_ops, sizeof(snd_pcm_rate_v2_ops_t));
+		return 0;
+	}
 #endif
-		*ops = pcm_src_ops;
+	*ops = pcm_src_ops;
 	return 0;
 }
 
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2021-06-17 10:05 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-17 10:03 [PATCH alsa-plugins 0/2] Support multiple formats Takashi Iwai
2021-06-17 10:03 ` [PATCH alsa-plugins 1/2] rate-lav: " Takashi Iwai
2021-06-17 10:03 ` [PATCH alsa-plugins 2/2] samplerate: " Takashi Iwai

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.