[alsa-devel] alsa-lib: Rate conversion broken for non-S16?

Takashi Iwai tiwai at suse.de
Wed Aug 11 12:21:55 CEST 2010


At Wed, 11 Aug 2010 10:59:59 +0200,
I wrote:
> 
> At Wed, 11 Aug 2010 09:04:32 +0100 (BST),
> Mark Hills wrote:
> > 
> > Hi, does anybody have any thoughts on my email below? The rate conversion 
> > code looks stable and untouched for a while.
> 
> I guess it's a missing support of 3-byte formats in 16bit conversion,
> so not specific to rate plugin.
> 
> Adding the support shouldn't be too hard, since it's already found
> in 32bit conversion.

A quick (untested) fix is below.


Takashi

---
diff --git a/src/pcm/pcm_linear.c b/src/pcm/pcm_linear.c
index 12e2e7f..01b6742 100644
--- a/src/pcm/pcm_linear.c
+++ b/src/pcm/pcm_linear.c
@@ -114,10 +114,9 @@ int snd_pcm_linear_get32_index(snd_pcm_format_t src_format, snd_pcm_format_t dst
 
 int snd_pcm_linear_put_index(snd_pcm_format_t src_format, snd_pcm_format_t dst_format)
 {
-	int sign, width, endian;
+	int sign, width, pwidth, endian;
 	sign = (snd_pcm_format_signed(src_format) != 
 		snd_pcm_format_signed(dst_format));
-	width = snd_pcm_format_width(dst_format) / 8 - 1;
 #ifdef SND_LITTLE_ENDIAN
 	endian = snd_pcm_format_big_endian(dst_format);
 #else
@@ -125,7 +124,23 @@ int snd_pcm_linear_put_index(snd_pcm_format_t src_format, snd_pcm_format_t dst_f
 #endif
 	if (endian < 0)
 		endian = 0;
-	return width * 4 + endian * 2 + sign;
+	pwidth = snd_pcm_format_physical_width(dst_format);
+	width = snd_pcm_format_width(dst_format) / 8 - 1;
+	if (pwidth == 24) {
+		switch (width) {
+		case 24:
+			width = 0; break;
+		case 20:
+			width = 1; break;
+		case 18:
+		default:
+			width = 2; break;
+		}
+		return width * 4 + endian * 2 + sign + 16;
+	} else {
+		width = width / 8 - 1;
+		return width * 4 + endian * 2 + sign;
+	}
 }
 
 int snd_pcm_linear_put32_index(snd_pcm_format_t src_format, snd_pcm_format_t dst_format)
diff --git a/src/pcm/plugin_ops.h b/src/pcm/plugin_ops.h
index 04220d6..0c63ca6 100644
--- a/src/pcm/plugin_ops.h
+++ b/src/pcm/plugin_ops.h
@@ -407,7 +407,7 @@ get16_123_B2_18: sample = (_get_triple_s(src) >> 2) ^ 0x8000; goto GET16_END;
 
 #ifdef PUT16_LABELS
 /* dst_wid dst_endswap sign_toggle */
-static void *const put16_labels[4 * 2 * 2] = {
+static void *const put16_labels[4 * 2 * 2 + 4 * 3] = {
 	&&put16_12_1,		 /* 16h ->  8h */
 	&&put16_12_9,		 /* 16h ^>  8h */
 	&&put16_12_1,		 /* 16h ->  8s */
@@ -424,6 +424,19 @@ static void *const put16_labels[4 * 2 * 2] = {
 	&&put16_12_9200,	 /* 16h ^> 32h */
 	&&put16_12_0021,	 /* 16h -> 32s */
 	&&put16_12_0029,	 /* 16h ^> 32s */
+	/* 3bytes format */
+	&&put16_12_120,	 /* 16h -> 24h */
+	&&put16_12_920,	 /* 16h ^> 24h */
+	&&put16_12_021,	 /* 16h -> 24s */
+	&&put16_12_029,	 /* 16h ^> 24h */
+	&&put16_12_120_20,	 /* 16h -> 20h */
+	&&put16_12_920_20,	 /* 16h ^> 20h */
+	&&put16_12_021_20,	 /* 16h -> 20s */
+	&&put16_12_029_20,	 /* 16h ^> 20h */
+	&&put16_12_120_18,	 /* 16h -> 18h */
+	&&put16_12_920_18,	 /* 16h ^> 18h */
+	&&put16_12_021_18,	 /* 16h -> 18s */
+	&&put16_12_029_18,	 /* 16h ^> 18h */
 };
 #endif
 
@@ -443,6 +456,18 @@ put16_12_1200: as_u32(dst) = (u_int32_t)sample << 16; goto PUT16_END;
 put16_12_9200: as_u32(dst) = (u_int32_t)(sample ^ 0x8000) << 16; goto PUT16_END;
 put16_12_0021: as_u32(dst) = (u_int32_t)bswap_16(sample); goto PUT16_END;
 put16_12_0029: as_u32(dst) = (u_int32_t)bswap_16(sample) ^ 0x80; goto PUT16_END;
+put16_12_120: _put_triple(dst, (u_int32_t)sample << 8); goto PUT16_END;
+put16_12_920: _put_triple(dst, (u_int32_t)(sample ^ 0x8000) << 8); goto PUT16_END;
+put16_12_021: _put_triple_s(dst, (u_int32_t)sample << 8); goto PUT16_END;
+put16_12_029: _put_triple_s(dst, (u_int32_t)(sample ^ 0x8000) << 8); goto PUT16_END;
+put16_12_120_20: _put_triple(dst, (u_int32_t)sample << 4); goto PUT16_END;
+put16_12_920_20: _put_triple(dst, (u_int32_t)(sample ^ 0x8000) << 4); goto PUT16_END;
+put16_12_021_20: _put_triple_s(dst, (u_int32_t)sample << 4); goto PUT16_END;
+put16_12_029_20: _put_triple_s(dst, (u_int32_t)(sample ^ 0x8000) << 4); goto PUT16_END;
+put16_12_120_18: _put_triple(dst, (u_int32_t)sample << 2); goto PUT16_END;
+put16_12_920_18: _put_triple(dst, (u_int32_t)(sample ^ 0x8000) << 2); goto PUT16_END;
+put16_12_021_18: _put_triple_s(dst, (u_int32_t)sample << 2); goto PUT16_END;
+put16_12_029_18: _put_triple_s(dst, (u_int32_t)(sample ^ 0x8000) << 2); goto PUT16_END;
 }
 #endif
 


More information about the Alsa-devel mailing list