All of lore.kernel.org
 help / color / mirror / Atom feed
* Bug in aplay?
@ 2012-12-12 11:01 Damien Zammit
  2012-12-12 11:38 ` Takashi Iwai
  0 siblings, 1 reply; 7+ messages in thread
From: Damien Zammit @ 2012-12-12 11:01 UTC (permalink / raw)
  To: alsa-devel

Hi,
I think i found a small bug in alsa utility "aplay".

If you have a sound device that supports the S24_3BE format natively,
and you have a wav file of the same format, aplay will not play it
because it detects the wrong format and assumes it is default format.
(ie 8000Hz Mono 1 channel).
I compiled my own version of aplay and it works because I hacked the
default format to match this format, but it is not the ideal solution.

pi@raspberrypi ~ $ aplay --version
aplay: version 1.0.25 by Jaroslav Kysela <perex@perex.cz>

pi@raspberrypi ~ $ aplay -D hw:1 48000-S24_3BE.wav
Playing raw data '48000-S24_3BE.wav' : Unsigned 8 bit, Rate 8000 Hz, Mono
aplay: set_params:1081: Sample format non available
Available formats:
- S24_3BE

My version:
pi@raspberrypi ~ $ ./aplay -D hw:1 48000-S24_3BE.wav
Playing raw data '48000-S24_3BE.wav' : Signed 24 bit Big Endian in
3bytes, Rate 48000 Hz, Stereo
aplay: set_params:1145: Unable to install hw params:
ACCESS:  RW_INTERLEAVED
FORMAT:  S24_3BE
SUBFORMAT:  STD
SAMPLE_BITS: 24
FRAME_BITS: 48
CHANNELS: 2
RATE: 48000
PERIOD_TIME: 125000
PERIOD_SIZE: 6000
PERIOD_BYTES: 36000
PERIODS: 4
BUFFER_TIME: 500000
BUFFER_SIZE: 24000
BUFFER_BYTES: 144000
TICK_TIME: 0
pi@raspberrypi ~ $

This is making it tricky for me to use my sound card.  For some reason
it works better with jackd.  The error above is also a mystery to me,
but it seems to be detecting the format better.

Regards,
Damien

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

* Re: Bug in aplay?
  2012-12-12 11:01 Bug in aplay? Damien Zammit
@ 2012-12-12 11:38 ` Takashi Iwai
  2012-12-12 11:54   ` Damien Zammit
  0 siblings, 1 reply; 7+ messages in thread
From: Takashi Iwai @ 2012-12-12 11:38 UTC (permalink / raw)
  To: Damien Zammit; +Cc: alsa-devel

At Wed, 12 Dec 2012 22:01:38 +1100,
Damien Zammit wrote:
> 
> Hi,
> I think i found a small bug in alsa utility "aplay".
> 
> If you have a sound device that supports the S24_3BE format natively,
> and you have a wav file of the same format, aplay will not play it
> because it detects the wrong format and assumes it is default format.
> (ie 8000Hz Mono 1 channel).
> I compiled my own version of aplay and it works because I hacked the
> default format to match this format, but it is not the ideal solution.
> 
> pi@raspberrypi ~ $ aplay --version
> aplay: version 1.0.25 by Jaroslav Kysela <perex@perex.cz>
> 
> pi@raspberrypi ~ $ aplay -D hw:1 48000-S24_3BE.wav
> Playing raw data '48000-S24_3BE.wav' : Unsigned 8 bit, Rate 8000 Hz, Mono
> aplay: set_params:1081: Sample format non available
> Available formats:
> - S24_3BE

Does your WAV file have a valid WAV_FMT_* chunk indicating the 24bit
format?  aplay checks bit_p_spl and byte_p_spl fields of WaveFmtBody
defined in formats.h.


Takashi

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

* Re: Bug in aplay?
  2012-12-12 11:38 ` Takashi Iwai
@ 2012-12-12 11:54   ` Damien Zammit
  2012-12-12 11:59     ` Clemens Ladisch
  0 siblings, 1 reply; 7+ messages in thread
From: Damien Zammit @ 2012-12-12 11:54 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel

pi@raspberrypi ~ $ hexdump -C 48000-S24_3BE.wav |head
00000000  52 49 46 58 01 c3 20 48  57 41 56 45 66 6d 74 20  |RIFX.. HWAVEfmt |
00000010  00 00 00 28 ff fe 00 02  00 00 bb 80 00 04 65 00  |...(..........e.|
00000020  00 06 00 18 00 16 00 18  00 00 00 03 00 01 00 00  |................|
00000030  00 00 10 00 80 00 00 aa  00 38 9b 71 66 61 63 74  |.........8.qfact|
00000040  00 00 00 04 00 4b 30 00  64 61 74 61 01 c3 20 00  |.....K0.data.. .|
00000050  ff f6 00 00 14 00 00 3f  00 00 26 00 00 25 00 00  |.......?..&..%..|
00000060  2c 00 ff cf 00 00 2b 00  00 0b 00 00 25 00 00 44  |,.....+.....%..D|
00000070  00 00 1d 00 00 1b 00 00  13 00 00 19 00 00 06 00  |................|
00000080  ff f8 00 00 00 00 ff ab  00 00 04 00 ff f1 00 00  |................|
00000090  0a 00 00 5a 00 00 0d 00  00 38 00 00 0a 00 00 08  |...Z.....8......|

On 12 December 2012 22:38, Takashi Iwai <tiwai@suse.de> wrote:
> At Wed, 12 Dec 2012 22:01:38 +1100,
> Damien Zammit wrote:
>>
>> Hi,
>> I think i found a small bug in alsa utility "aplay".
>>
>> If you have a sound device that supports the S24_3BE format natively,
>> and you have a wav file of the same format, aplay will not play it
>> because it detects the wrong format and assumes it is default format.
>> (ie 8000Hz Mono 1 channel).
>> I compiled my own version of aplay and it works because I hacked the
>> default format to match this format, but it is not the ideal solution.
>>
>> pi@raspberrypi ~ $ aplay --version
>> aplay: version 1.0.25 by Jaroslav Kysela <perex@perex.cz>
>>
>> pi@raspberrypi ~ $ aplay -D hw:1 48000-S24_3BE.wav
>> Playing raw data '48000-S24_3BE.wav' : Unsigned 8 bit, Rate 8000 Hz, Mono
>> aplay: set_params:1081: Sample format non available
>> Available formats:
>> - S24_3BE
>
> Does your WAV file have a valid WAV_FMT_* chunk indicating the 24bit
> format?  aplay checks bit_p_spl and byte_p_spl fields of WaveFmtBody
> defined in formats.h.
>
>
> Takashi

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

* Re: Bug in aplay?
  2012-12-12 11:54   ` Damien Zammit
@ 2012-12-12 11:59     ` Clemens Ladisch
  2012-12-12 12:08       ` Damien Zammit
  2012-12-12 14:23       ` Takashi Iwai
  0 siblings, 2 replies; 7+ messages in thread
From: Clemens Ladisch @ 2012-12-12 11:59 UTC (permalink / raw)
  To: Damien Zammit; +Cc: Takashi Iwai, alsa-devel

Damien Zammit wrote:
> pi@raspberrypi ~ $ hexdump -C 48000-S24_3BE.wav |head
> 00000000  52 49 46 58 01 c3 20 48  57 41 56 45 66 6d 74 20  |RIFX.. HWAVEfmt |

aplay does not support big-endian .wav files.


Regards,
Clemens

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

* Re: Bug in aplay?
  2012-12-12 11:59     ` Clemens Ladisch
@ 2012-12-12 12:08       ` Damien Zammit
  2012-12-12 13:01         ` Clemens Ladisch
  2012-12-12 14:23       ` Takashi Iwai
  1 sibling, 1 reply; 7+ messages in thread
From: Damien Zammit @ 2012-12-12 12:08 UTC (permalink / raw)
  To: Clemens Ladisch; +Cc: Takashi Iwai, alsa-devel

I wish to record and playback streams from my sound card which uses 24
bit big endian format, but I do not wish to resample it.  Is it
possible to reorder the endianess on the fly so that I can play and
record using alsa tools without losing any quality?

On 12 December 2012 22:59, Clemens Ladisch <clemens@ladisch.de> wrote:
> Damien Zammit wrote:
>> pi@raspberrypi ~ $ hexdump -C 48000-S24_3BE.wav |head
>> 00000000  52 49 46 58 01 c3 20 48  57 41 56 45 66 6d 74 20  |RIFX.. HWAVEfmt |
>
> aplay does not support big-endian .wav files.
>
>
> Regards,
> Clemens

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

* Re: Bug in aplay?
  2012-12-12 12:08       ` Damien Zammit
@ 2012-12-12 13:01         ` Clemens Ladisch
  0 siblings, 0 replies; 7+ messages in thread
From: Clemens Ladisch @ 2012-12-12 13:01 UTC (permalink / raw)
  To: Damien Zammit; +Cc: Takashi Iwai, alsa-devel

Damien Zammit wrote:
> I wish to record and playback streams from my sound card which uses 24
> bit big endian format, but I do not wish to resample it.

You get resampling only if the sample rates do not match.


Regards,
Clemens

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

* Re: Bug in aplay?
  2012-12-12 11:59     ` Clemens Ladisch
  2012-12-12 12:08       ` Damien Zammit
@ 2012-12-12 14:23       ` Takashi Iwai
  1 sibling, 0 replies; 7+ messages in thread
From: Takashi Iwai @ 2012-12-12 14:23 UTC (permalink / raw)
  To: Clemens Ladisch; +Cc: alsa-devel, Damien Zammit

At Wed, 12 Dec 2012 12:59:01 +0100,
Clemens Ladisch wrote:
> 
> Damien Zammit wrote:
> > pi@raspberrypi ~ $ hexdump -C 48000-S24_3BE.wav |head
> > 00000000  52 49 46 58 01 c3 20 48  57 41 56 45 66 6d 74 20  |RIFX.. HWAVEfmt |
> 
> aplay does not support big-endian .wav files.

Indeed.

The (untested) patch below should add the support for BE format.
Give it a try.


Takashi

---
diff --git a/aplay/aplay.c b/aplay/aplay.c
index f35f603..4852b20 100644
--- a/aplay/aplay.c
+++ b/aplay/aplay.c
@@ -892,11 +892,20 @@ static ssize_t test_wavefile(int fd, u_char *_buffer, size_t size)
 	WaveFmtBody *f;
 	WaveChunkHeader *c;
 	u_int type, len;
+	unsigned short format, channels;
+	int big_endian, native_format;
 
 	if (size < sizeof(WaveHeader))
 		return -1;
-	if (h->magic != WAV_RIFF || h->type != WAV_WAVE)
+	if (h->magic == WAV_RIFF)
+		big_endian = 0;
+	else if (h->magic == WAV_RIFX)
+		big_endian = 1;
+	else
+		return -1;
+	if (h->type != WAV_WAVE)
 		return -1;
+
 	if (size > sizeof(WaveHeader)) {
 		check_wavefile_space(buffer, size - sizeof(WaveHeader), blimit);
 		memcpy(buffer, _buffer + sizeof(WaveHeader), size - sizeof(WaveHeader));
@@ -907,7 +916,7 @@ static ssize_t test_wavefile(int fd, u_char *_buffer, size_t size)
 		test_wavefile_read(fd, buffer, &size, sizeof(WaveChunkHeader), __LINE__);
 		c = (WaveChunkHeader*)buffer;
 		type = c->type;
-		len = LE_INT(c->length);
+		len = TO_CPU_INT(c->length, big_endian);
 		len += len % 2;
 		if (size > sizeof(WaveChunkHeader))
 			memmove(buffer, buffer + sizeof(WaveChunkHeader), size - sizeof(WaveChunkHeader));
@@ -929,7 +938,8 @@ static ssize_t test_wavefile(int fd, u_char *_buffer, size_t size)
 	check_wavefile_space(buffer, len, blimit);
 	test_wavefile_read(fd, buffer, &size, len, __LINE__);
 	f = (WaveFmtBody*) buffer;
-	if (LE_SHORT(f->format) == WAV_FMT_EXTENSIBLE) {
+	format = TO_CPU_SHORT(f->format, big_endian);
+	if (format == WAV_FMT_EXTENSIBLE) {
 		WaveFmtExtensibleBody *fe = (WaveFmtExtensibleBody*)buffer;
 		if (len < sizeof(WaveFmtExtensibleBody)) {
 			error(_("unknown length of extensible 'fmt ' chunk (read %u, should be %u at least)"),
@@ -940,19 +950,20 @@ static ssize_t test_wavefile(int fd, u_char *_buffer, size_t size)
 			error(_("wrong format tag in extensible 'fmt ' chunk"));
 			prg_exit(EXIT_FAILURE);
 		}
-		f->format = fe->guid_format;
+		format = TO_CPU_SHORT(fe->guid_format, big_endian);
 	}
-        if (LE_SHORT(f->format) != WAV_FMT_PCM &&
-            LE_SHORT(f->format) != WAV_FMT_IEEE_FLOAT) {
-                error(_("can't play WAVE-file format 0x%04x which is not PCM or FLOAT encoded"), LE_SHORT(f->format));
+	if (format != WAV_FMT_PCM &&
+	    format != WAV_FMT_IEEE_FLOAT) {
+                error(_("can't play WAVE-file format 0x%04x which is not PCM or FLOAT encoded"), format);
 		prg_exit(EXIT_FAILURE);
 	}
-	if (LE_SHORT(f->channels) < 1) {
-		error(_("can't play WAVE-files with %d tracks"), LE_SHORT(f->channels));
+	channels = TO_CPU_SHORT(f->channels, big_endian);
+	if (channels < 1) {
+		error(_("can't play WAVE-files with %d tracks"), channels);
 		prg_exit(EXIT_FAILURE);
 	}
-	hwparams.channels = LE_SHORT(f->channels);
-	switch (LE_SHORT(f->bit_p_spl)) {
+	hwparams.channels = channels;
+	switch (TO_CPU_SHORT(f->bit_p_spl, big_endian)) {
 	case 8:
 		if (hwparams.format != DEFAULT_FORMAT &&
 		    hwparams.format != SND_PCM_FORMAT_U8)
@@ -960,43 +971,69 @@ static ssize_t test_wavefile(int fd, u_char *_buffer, size_t size)
 		hwparams.format = SND_PCM_FORMAT_U8;
 		break;
 	case 16:
+		if (big_endian)
+			native_format = SND_PCM_FORMAT_S16_BE;
+		else
+			native_format = SND_PCM_FORMAT_S16_LE;
 		if (hwparams.format != DEFAULT_FORMAT &&
-		    hwparams.format != SND_PCM_FORMAT_S16_LE)
-			fprintf(stderr, _("Warning: format is changed to S16_LE\n"));
-		hwparams.format = SND_PCM_FORMAT_S16_LE;
+		    hwparams.format != native_format)
+			fprintf(stderr, _("Warning: format is changed to %s\n"),
+				snd_pcm_format_name(native_format));
+		hwparams.format = native_format;
 		break;
 	case 24:
-		switch (LE_SHORT(f->byte_p_spl) / hwparams.channels) {
+		switch (TO_CPU_SHORT(f->byte_p_spl, big_endian) / hwparams.channels) {
 		case 3:
+			if (big_endian)
+				native_format = SND_PCM_FORMAT_S24_3BE;
+			else
+				native_format = SND_PCM_FORMAT_S24_3LE;
 			if (hwparams.format != DEFAULT_FORMAT &&
-			    hwparams.format != SND_PCM_FORMAT_S24_3LE)
-				fprintf(stderr, _("Warning: format is changed to S24_3LE\n"));
-			hwparams.format = SND_PCM_FORMAT_S24_3LE;
+			    hwparams.format != native_format)
+				fprintf(stderr, _("Warning: format is changed to %s\n"),
+					snd_pcm_format_name(native_format));
+			hwparams.format = native_format;
 			break;
 		case 4:
+			if (big_endian)
+				native_format = SND_PCM_FORMAT_S24_BE;
+			else
+				native_format = SND_PCM_FORMAT_S24_LE;
 			if (hwparams.format != DEFAULT_FORMAT &&
-			    hwparams.format != SND_PCM_FORMAT_S24_LE)
-				fprintf(stderr, _("Warning: format is changed to S24_LE\n"));
-			hwparams.format = SND_PCM_FORMAT_S24_LE;
+			    hwparams.format != native_format)
+				fprintf(stderr, _("Warning: format is changed to %s\n"),
+					snd_pcm_format_name(native_format));
+			hwparams.format = native_format;
 			break;
 		default:
 			error(_(" can't play WAVE-files with sample %d bits in %d bytes wide (%d channels)"),
-			      LE_SHORT(f->bit_p_spl), LE_SHORT(f->byte_p_spl), hwparams.channels);
+			      TO_CPU_SHORT(f->bit_p_spl, big_endian),
+			      TO_CPU_SHORT(f->byte_p_spl, big_endian),
+			      hwparams.channels);
 			prg_exit(EXIT_FAILURE);
 		}
 		break;
 	case 32:
-                if (LE_SHORT(f->format) == WAV_FMT_PCM)
-                        hwparams.format = SND_PCM_FORMAT_S32_LE;
-                else if (LE_SHORT(f->format) == WAV_FMT_IEEE_FLOAT)
-                        hwparams.format = SND_PCM_FORMAT_FLOAT_LE;
+		if (format == WAV_FMT_PCM) {
+			if (big_endian)
+				native_format = SND_PCM_FORMAT_S32_BE;
+			else
+				native_format = SND_PCM_FORMAT_S32_LE;
+                        hwparams.format = native_format;
+		} else if (format == WAV_FMT_IEEE_FLOAT) {
+			if (big_endian)
+				native_format = SND_PCM_FORMAT_FLOAT_BE;
+			else
+				native_format = SND_PCM_FORMAT_FLOAT_LE;
+			hwparams.format = native_format;
+		}
 		break;
 	default:
 		error(_(" can't play WAVE-files with sample %d bits wide"),
-		      LE_SHORT(f->bit_p_spl));
+		      TO_CPU_SHORT(f->bit_p_spl, big_endian));
 		prg_exit(EXIT_FAILURE);
 	}
-	hwparams.rate = LE_INT(f->sample_fq);
+	hwparams.rate = TO_CPU_INT(f->sample_fq, big_endian);
 	
 	if (size > len)
 		memmove(buffer, buffer + len, size - len);
@@ -1009,7 +1046,7 @@ static ssize_t test_wavefile(int fd, u_char *_buffer, size_t size)
 		test_wavefile_read(fd, buffer, &size, sizeof(WaveChunkHeader), __LINE__);
 		c = (WaveChunkHeader*)buffer;
 		type = c->type;
-		len = LE_INT(c->length);
+		len = TO_CPU_INT(c->length, big_endian);
 		if (size > sizeof(WaveChunkHeader))
 			memmove(buffer, buffer + sizeof(WaveChunkHeader), size - sizeof(WaveChunkHeader));
 		size -= sizeof(WaveChunkHeader);
diff --git a/aplay/formats.h b/aplay/formats.h
index b5314f9..ac0a2b0 100644
--- a/aplay/formats.h
+++ b/aplay/formats.h
@@ -60,7 +60,14 @@ typedef struct voc_ext_block {
 #error "Wrong endian"
 #endif
 
+/* Note: the following macros evaluate the parameter v twice */
+#define TO_CPU_SHORT(v, be) \
+	((be) ? BE_SHORT(v) : LE_SHORT(v))
+#define TO_CPU_INT(v, be) \
+	((be) ? BE_INT(v) : LE_INT(v))
+
 #define WAV_RIFF		COMPOSE_ID('R','I','F','F')
+#define WAV_RIFX		COMPOSE_ID('R','I','F','X')
 #define WAV_WAVE		COMPOSE_ID('W','A','V','E')
 #define WAV_FMT			COMPOSE_ID('f','m','t',' ')
 #define WAV_DATA		COMPOSE_ID('d','a','t','a')

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

end of thread, other threads:[~2012-12-12 14:23 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-12-12 11:01 Bug in aplay? Damien Zammit
2012-12-12 11:38 ` Takashi Iwai
2012-12-12 11:54   ` Damien Zammit
2012-12-12 11:59     ` Clemens Ladisch
2012-12-12 12:08       ` Damien Zammit
2012-12-12 13:01         ` Clemens Ladisch
2012-12-12 14:23       ` 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.