[alsa-devel] [PATCH] pcm: softvol: add support for S24_LE

Jörg Krause joerg.krause at embedded.rocks
Tue Sep 12 16:15:58 CEST 2017


On Tue, 2017-09-12 at 09:12 +0200, Takashi Iwai wrote:
> On Tue, 12 Sep 2017 09:02:47 +0200,
> Clemens Ladisch wrote:
> > 
> > Jörg Krause wrote:
> > > The i.MX6UL has a Synchronous Audio Interface (SAI), where the data in
> > > the FIFO can be aligned anywhere within the 32-bit wide register
> > > through the use of the First Bit Shifted configuration field. In the
> > > corresponding Linux SAI driver the FBS field is set the way that data
> > > alignment for 24-bit data is:
> > > 
> > > 31 30 29 28 | 27 26 25 24 | 23 22 21 20 | .. | 3 2 1 0
> > > ## ## ## ##   ## ## ## ## [           DATA[23:0]       ]
> > 
> > This indeed is S24_LE.
> > 
> > Which is an extremely uncommon format.  If possible, the driver should
> > be changed to align to the sample's MSB to the memory word's MSB, and
> > then label it as S32_LE.
> > 
> > > > S24_LE cannot be handled with the same algorithm as S32_LE.
> > 
> > To be precise: the sign in bit 23 must be preserved.
> 
> I guess the simple calculation with S24_LE using the current code
> would work as long as the upper 8 bits are ignored by hardware.
> The upper 8 bits would hold bogus bits, and clearing this would be an
> extra action we'd need in addition.

Thanks! I've copied the area convertion macro for S24_3LE and
explicitly set the upper 8 bits to 0:

"""
#define CONVERT_AREA_S24_LE() do {					\
	unsigned int ch, fr;						\
	unsigned char *src, *dst;					\
	int tmp;							\
	for (ch = 0; ch < channels; ch++) {				\
		src_area = &src_areas[ch];				\
		dst_area = &dst_areas[ch];				\
		src = snd_pcm_channel_area_addr(src_area, src_offset);	\
		dst = snd_pcm_channel_area_addr(dst_area, dst_offset);	\
		src_step = snd_pcm_channel_area_step(src_area);		\
		dst_step = snd_pcm_channel_area_step(dst_area);		\
		GET_VOL_SCALE;						\
		fr = frames;						\
		if (! vol_scale) {					\
			while (fr--) {					\
				dst[0] = dst[1] = dst[2] = dst[3] = 0;	\
				dst += dst_step;			\
			}						\
		} else if (vol_scale == 0xffff) {			\
			while (fr--) {					\
				dst[0] = src[0];			\
				dst[1] = src[1];			\
				dst[2] = src[2];			\
				dst[3] = 0;				\
				src += dst_step;			\
				dst += src_step;			\
			}						\
		} else {						\
			while (fr--) {					\
				tmp = src[0] |				\
				      (src[1] << 8) |			\
				      (((signed char *) src)[2] << 16);	\
				tmp = MULTI_DIV_24(tmp, vol_scale);	\
				dst[0] = tmp;				\
				dst[1] = tmp >> 8;			\
				dst[2] = tmp >> 16;			\
				dst[3] = 0;				\
				src += dst_step;			\
				dst += src_step;			\
			}						\
		}							\
	}								\
} while (0)
"""

Is that okay?

Jörg Krause


More information about the Alsa-devel mailing list