Module Name: src
Committed By: martin
Date: Tue Mar 12 10:04:23 UTC 2024
Modified Files:
src/usr.bin/audio/common [netbsd-10]: auconv.h audio.c decode.c
libaudio.h sun.c wav.c
src/usr.bin/audio/play [netbsd-10]: audioplay.1 play.c
src/usr.bin/audio/record [netbsd-10]: audiorecord.1 record.c
Log Message:
Pull up the following revisions, requested by mrg in ticket #634:
usr.bin/audio/common/auconv.h up to 1.6
usr.bin/audio/common/audio.c up to 1.27
usr.bin/audio/common/decode.c up to 1.2
usr.bin/audio/common/libaudio.h up to 1.22
usr.bin/audio/common/sun.c up to 1.11
usr.bin/audio/common/wav.c up to 1.22
usr.bin/audio/play/audioplay.1 up to 1.34
usr.bin/audio/play/play.c up to 1.64
usr.bin/audio/record/audiorecord.1 up to 1.45
usr.bin/audio/record/record.c up to 1.58
- support for recording 24 bit .wav files
- read-overflow fixes for .wav files, and other fixes for the
wav parser
- audioplay gains -n flag (no play, like make -n)
To generate a diff of this commit:
cvs rdiff -u -r1.5 -r1.5.72.1 src/usr.bin/audio/common/auconv.h
cvs rdiff -u -r1.26 -r1.26.8.1 src/usr.bin/audio/common/audio.c
cvs rdiff -u -r1.1 -r1.1.26.1 src/usr.bin/audio/common/decode.c
cvs rdiff -u -r1.21 -r1.21.8.1 src/usr.bin/audio/common/libaudio.h
cvs rdiff -u -r1.10 -r1.10.8.1 src/usr.bin/audio/common/sun.c
cvs rdiff -u -r1.15 -r1.15.8.1 src/usr.bin/audio/common/wav.c
cvs rdiff -u -r1.30.6.1 -r1.30.6.2 src/usr.bin/audio/play/audioplay.1
cvs rdiff -u -r1.61 -r1.61.2.1 src/usr.bin/audio/play/play.c
cvs rdiff -u -r1.44 -r1.44.6.1 src/usr.bin/audio/record/audiorecord.1
cvs rdiff -u -r1.56 -r1.56.2.1 src/usr.bin/audio/record/record.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/usr.bin/audio/common/auconv.h
diff -u src/usr.bin/audio/common/auconv.h:1.5 src/usr.bin/audio/common/auconv.h:1.5.72.1
--- src/usr.bin/audio/common/auconv.h:1.5 Mon Apr 28 20:24:12 2008
+++ src/usr.bin/audio/common/auconv.h Tue Mar 12 10:04:22 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: auconv.h,v 1.5 2008/04/28 20:24:12 martin Exp $ */
+/* $NetBSD: auconv.h,v 1.5.72.1 2024/03/12 10:04:22 martin Exp $ */
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
@@ -78,6 +78,24 @@ change_sign16_be(u_char *p, int cc)
}
static inline void
+change_sign24_le(u_char *p, int cc)
+{
+ while ((cc -= 3) >= 0) {
+ p[2] ^= 0x80;
+ p += 3;
+ }
+}
+
+static inline void
+change_sign24_be(u_char *p, int cc)
+{
+ while ((cc -= 3) >= 0) {
+ p[0] ^= 0x80;
+ p += 3;
+ }
+}
+
+static inline void
change_sign32_le(u_char *p, int cc)
{
while ((cc -= 4) >= 0) {
@@ -163,6 +181,44 @@ change_sign16_swap_bytes_be(u_char *p, i
}
static inline void
+swap_bytes_change_sign24_le(u_char *p, int cc)
+{
+ u_char t;
+
+ while ((cc -= 3) >= 0) {
+ t = p[2];
+ p[2] = p[0] ^ 0x80;
+ p[0] = t;
+ p += 3;
+ }
+}
+
+static inline void
+swap_bytes_change_sign24_be(u_char *p, int cc)
+{
+ u_char t;
+
+ while ((cc -= 3) >= 0) {
+ t = p[0];
+ p[0] = p[2] ^ 0x80;
+ p[2] = t;
+ p += 3;
+ }
+}
+
+static inline void
+change_sign24_swap_bytes_le(u_char *p, int cc)
+{
+ swap_bytes_change_sign24_be(p, cc);
+}
+
+static inline void
+change_sign24_swap_bytes_be(u_char *p, int cc)
+{
+ swap_bytes_change_sign24_le(p, cc);
+}
+
+static inline void
swap_bytes_change_sign32_le(u_char *p, int cc)
{
u_char t;
Index: src/usr.bin/audio/common/audio.c
diff -u src/usr.bin/audio/common/audio.c:1.26 src/usr.bin/audio/common/audio.c:1.26.8.1
--- src/usr.bin/audio/common/audio.c:1.26 Sat Nov 9 12:46:44 2019
+++ src/usr.bin/audio/common/audio.c Tue Mar 12 10:04:22 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: audio.c,v 1.26 2019/11/09 12:46:44 mrg Exp $ */
+/* $NetBSD: audio.c,v 1.26.8.1 2024/03/12 10:04:22 martin Exp $ */
/*
* Copyright (c) 1999, 2013, 2015, 2019 Matthew R. Green
@@ -32,7 +32,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: audio.c,v 1.26 2019/11/09 12:46:44 mrg Exp $");
+__RCSID("$NetBSD: audio.c,v 1.26.8.1 2024/03/12 10:04:22 martin Exp $");
#endif
@@ -205,7 +205,7 @@ write_header(struct track_info *ti)
veclen = 0;
tlen = 0;
-
+
if (hdrlen != 0) {
iv[veclen].iov_base = hdr;
iv[veclen].iov_len = hdrlen;
Index: src/usr.bin/audio/common/decode.c
diff -u src/usr.bin/audio/common/decode.c:1.1 src/usr.bin/audio/common/decode.c:1.1.26.1
--- src/usr.bin/audio/common/decode.c:1.1 Sun Jun 21 06:06:01 2015
+++ src/usr.bin/audio/common/decode.c Tue Mar 12 10:04:22 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: decode.c,v 1.1 2015/06/21 06:06:01 mrg Exp $ */
+/* $NetBSD: decode.c,v 1.1.26.1 2024/03/12 10:04:22 martin Exp $ */
/*
* Copyright (c) 1999 Matthew R. Green
@@ -29,7 +29,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: decode.c,v 1.1 2015/06/21 06:06:01 mrg Exp $");
+__RCSID("$NetBSD: decode.c,v 1.1.26.1 2024/03/12 10:04:22 martin Exp $");
#endif
#include <sys/types.h>
@@ -85,7 +85,7 @@ decode_time(const char *arg, struct time
tvp->tv_sec = tvp->tv_usec = 0;
s = copy;
-
+
/* handle [hh:]mm:ss.dd */
if ((colon = strchr(s, ':')) != NULL) {
*colon++ = '\0';
Index: src/usr.bin/audio/common/libaudio.h
diff -u src/usr.bin/audio/common/libaudio.h:1.21 src/usr.bin/audio/common/libaudio.h:1.21.8.1
--- src/usr.bin/audio/common/libaudio.h:1.21 Sat Nov 9 12:46:44 2019
+++ src/usr.bin/audio/common/libaudio.h Tue Mar 12 10:04:22 2024
@@ -1,7 +1,7 @@
-/* $NetBSD: libaudio.h,v 1.21 2019/11/09 12:46:44 mrg Exp $ */
+/* $NetBSD: libaudio.h,v 1.21.8.1 2024/03/12 10:04:22 martin Exp $ */
/*
- * Copyright (c) 1999, 2009, 2013, 2015, 2019 Matthew R. Green
+ * Copyright (c) 1999, 2009, 2013, 2015, 2019, 2024 Matthew R. Green
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -106,7 +106,10 @@ int audio_sun_to_encoding (int, u_int *,
int audio_encoding_to_sun (int, int, int *);
/*
- * M$ WAV files, info gleamed from sox sources
+ * RIFF WAVE files. Sources: RFC 2361, and various Microsoft docs
+ * https://learn.microsoft.com/en-us/windows/win32/xaudio2/resource-interchange-file-format--riff-
+ * https://learn.microsoft.com/en-us/previous-versions/windows/hardware/design/dn653308(v=vs.85)
+ * "Multimedia Programming Interface and Data Specifications 1.0" chapter 4
*/
/*
@@ -118,30 +121,112 @@ int audio_encoding_to_sun (int, int, int
#define WAVAUDIO_FILE_MAGIC_FMT ((u_int32_t)0x666d7420)
#define WAVAUDIO_FILE_MAGIC_DATA ((u_int32_t)0x64617461)
-/* purloined from public Microsoft RIFF docs via sox, mplayer, or directly */
+/* From RFC 2361 */
#define WAVE_FORMAT_UNKNOWN (0x0000)
#define WAVE_FORMAT_PCM (0x0001)
#define WAVE_FORMAT_ADPCM (0x0002)
#define WAVE_FORMAT_IEEE_FLOAT (0x0003)
+#define WAVE_FORMAT_VSELP (0x0004)
+#define WAVE_FORMAT_IBM_CVSD (0x0005)
#define WAVE_FORMAT_ALAW (0x0006)
#define WAVE_FORMAT_MULAW (0x0007)
#define WAVE_FORMAT_OKI_ADPCM (0x0010)
#define WAVE_FORMAT_IMA_ADPCM (0x0011)
+#define WAVE_FORMAT_MEDIASPACE_ADPCM (0x0012)
+#define WAVE_FORMAT_SIERRA_ADPCM (0x0013)
+#define WAVE_FORMAT_G723_ADPCM (0x0014)
#define WAVE_FORMAT_DIGISTD (0x0015)
#define WAVE_FORMAT_DIGIFIX (0x0016)
+#define WAVE_FORMAT_DIALOGIC_OKI_ADPCM (0x0017)
+#define WAVE_FORMAT_MEDIAVISION_ADPCM (0x0018)
+#define WAVE_FORMAT_CU_CODEC (0x0019)
+#define WAVE_FORMAT_YAMAHA_ADPCM (0x0020)
+#define WAVE_FORMAT_SONARC (0x0021)
+#define WAVE_FORMAT_DSPGROUP_TRUESPEECH (0x0022)
+#define WAVE_FORMAT_ECHOSC1 (0x0023)
+#define WAVE_FORMAT_AUDIOFILE_AF36 (0x0024)
+#define WAVE_FORMAT_APTX (0x0025)
+#define WAVE_FORMAT_AUDIOFILE_AF10 (0x0026)
+#define WAVE_FORMAT_PROSODY_1612 (0x0027)
+#define WAVE_FORMAT_LRC (0x0028)
#define WAVE_FORMAT_DOLBY_AC2 (0x0030)
#define WAVE_FORMAT_GSM610 (0x0031)
+#define WAVE_FORMAT_MSNAUDIO (0x0032)
+#define WAVE_FORMAT_ANTEX_ADPCME (0x0033)
+#define WAVE_FORMAT_CONTROL_RES_VQLPC (0x0034)
+#define WAVE_FORMAT_DIGIREAL (0x0035)
+#define WAVE_FORMAT_DIGIADPCM (0x0036)
+#define WAVE_FORMAT_CONTROL_RES_CR10 (0x0037)
+#define WAVE_FORMAT_NMS_VBXADPCM (0x0038)
+#define WAVE_FORMAT_ROLAND_RDAC (0x0039)
+#define WAVE_FORMAT_ECHOSC3 (0x003a)
#define WAVE_FORMAT_ROCKWELL_ADPCM (0x003b)
#define WAVE_FORMAT_ROCKWELL_DIGITALK (0x003c)
+#define WAVE_FORMAT_XEBEC (0x003d)
#define WAVE_FORMAT_G721_ADPCM (0x0040)
#define WAVE_FORMAT_G728_CELP (0x0041)
+#define WAVE_FORMAT_MSG723 (0x0042)
#define WAVE_FORMAT_MPEG (0x0050)
+#define WAVE_FORMAT_RT24 (0x0052)
+#define WAVE_FORMAT_PAC (0x0053)
#define WAVE_FORMAT_MPEGLAYER3 (0x0055)
+#define WAVE_FORMAT_LUCENT_G723 (0x0059)
+#define WAVE_FORMAT_CIRRUS (0x0060)
+#define WAVE_FORMAT_ESPCM (0x0061)
+#define WAVE_FORMAT_VOXWARE (0x0062)
+#define WAVE_FORMAT_CANOPUS_ATRAC (0x0063)
#define WAVE_FORMAT_G726_ADPCM (0x0064)
#define WAVE_FORMAT_G722_ADPCM (0x0065)
-#define IBM_FORMAT_MULAW (0x0101)
-#define IBM_FORMAT_ALAW (0x0102)
-#define IBM_FORMAT_ADPCM (0x0103)
+#define WAVE_FORMAT_DSAT (0x0066)
+#define WAVE_FORMAT_DSAT_DISPLAY (0x0067)
+#define WAVE_FORMAT_VOXWARE_BYTE_ALIGNED (0x0069)
+#define WAVE_FORMAT_VOXWARE_AC8 (0x0070)
+#define WAVE_FORMAT_VOXWARE_AC10 (0x0071)
+#define WAVE_FORMAT_VOXWARE_AC16 (0x0072)
+#define WAVE_FORMAT_VOXWARE_AC20 (0x0073)
+#define WAVE_FORMAT_VOXWARE_RT24 (0x0074)
+#define WAVE_FORMAT_VOXWARE_RT29 (0x0075)
+#define WAVE_FORMAT_VOXWARE_RT29HW (0x0076)
+#define WAVE_FORMAT_VOXWARE_VR12 (0x0077)
+#define WAVE_FORMAT_VOXWARE_VR18 (0x0078)
+#define WAVE_FORMAT_VOXWARE_TQ40 (0x0079)
+#define WAVE_FORMAT_SOFTSOUND (0x0080)
+#define WAVE_FORMAT_VOXWARE_TQ60 (0x0081)
+#define WAVE_FORMAT_MSRT24 (0x0082)
+#define WAVE_FORMAT_G729A (0x0083)
+#define WAVE_FORMAT_MVI_MV12 (0x0084)
+#define WAVE_FORMAT_DF_G726 (0x0085)
+#define WAVE_FORMAT_DF_GSM610 (0x0086)
+#define WAVE_FORMAT_ISIAUDIO (0x0088)
+#define WAVE_FORMAT_ONLIVE (0x0089)
+#define WAVE_FORMAT_SBC24 (0x0091)
+#define WAVE_FORMAT_DOLBY_AC3_SPDIF (0x0092)
+#define WAVE_FORMAT_ZYXEL_ADPCM (0x0097)
+#define WAVE_FORMAT_PHILIPS_LPCBB (0x0098)
+#define WAVE_FORMAT_PACKED (0x0099)
+#define WAVE_FORMAT_RHETOREX_ADPCM (0x0100)
+#define WAVE_FORMAT_IRAT (0x0101)
+#define WAVE_FORMAT_VIVO_G723 (0x0111)
+#define WAVE_FORMAT_VIVO_SIREN (0x0112)
+#define WAVE_FORMAT_DIGITAL_G723 (0x0123)
+#define WAVE_FORMAT_CREATIVE_ADPCM (0x0200)
+#define WAVE_FORMAT_CREATIVE_FASTSPEECH8 (0x0202)
+#define WAVE_FORMAT_CREATIVE_FASTSPEECH10 (0x0203)
+#define WAVE_FORMAT_QUARTERDECK (0x0220)
+#define WAVE_FORMAT_FM_TOWNS_SND (0x0300)
+#define WAVE_FORMAT_BTV_DIGITAL (0x0400)
+#define WAVE_FORMAT_VME_VMPCM (0x0680)
+#define WAVE_FORMAT_OLIGSM (0x1000)
+#define WAVE_FORMAT_OLIADPCM (0x1001)
+#define WAVE_FORMAT_OLICELP (0x1002)
+#define WAVE_FORMAT_OLISBC (0x1003)
+#define WAVE_FORMAT_OLIOPR (0x1004)
+#define WAVE_FORMAT_LH_CODEC (0x1100)
+#define WAVE_FORMAT_NORRIS (0x1400)
+#define WAVE_FORMAT_ISIAUDIO2 (0x1401)
+#define WAVE_FORMAT_SOUNDSPACE_MUSICOMPRESS (0x1500)
+#define WAVE_FORMAT_DVM (0x2000)
+
#define WAVE_FORMAT_EXTENSIBLE (0xfffe)
const char *wav_enc_from_val (int);
@@ -155,7 +240,7 @@ typedef struct {
u_int16_t tag;
u_int16_t channels;
u_int32_t sample_rate;
- u_int32_t avg_bps;
+ u_int32_t avg_bytes_per_sec;
u_int16_t alignment;
u_int16_t bits_per_sample;
} __packed wav_audioheaderfmt;
@@ -165,7 +250,7 @@ typedef struct {
u_int16_t valid_bits;
u_int32_t speaker_pos_mask;
u_int16_t sub_tag;
- u_int8_t dummy[14];
+ u_int8_t guid[14];
} __packed wav_audiohdrextensible;
/* returns size of header, or -ve for failure */
Index: src/usr.bin/audio/common/sun.c
diff -u src/usr.bin/audio/common/sun.c:1.10 src/usr.bin/audio/common/sun.c:1.10.8.1
--- src/usr.bin/audio/common/sun.c:1.10 Sat Nov 9 12:46:44 2019
+++ src/usr.bin/audio/common/sun.c Tue Mar 12 10:04:22 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: sun.c,v 1.10 2019/11/09 12:46:44 mrg Exp $ */
+/* $NetBSD: sun.c,v 1.10.8.1 2024/03/12 10:04:22 martin Exp $ */
/*
* Copyright (c) 2002, 2013, 2015 Matthew R. Green
@@ -32,7 +32,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: sun.c,v 1.10 2019/11/09 12:46:44 mrg Exp $");
+__RCSID("$NetBSD: sun.c,v 1.10.8.1 2024/03/12 10:04:22 martin Exp $");
#endif
@@ -149,7 +149,7 @@ sun_prepare_header(struct track_info *ti
break;
#endif
}
-
+
/* if we can't express this as a Sun header, don't write any */
if (audio_encoding_to_sun(ti->encoding, ti->precision, &sunenc) != 0) {
if (!ti->qflag && !warned) {
Index: src/usr.bin/audio/common/wav.c
diff -u src/usr.bin/audio/common/wav.c:1.15 src/usr.bin/audio/common/wav.c:1.15.8.1
--- src/usr.bin/audio/common/wav.c:1.15 Sat Nov 9 12:46:44 2019
+++ src/usr.bin/audio/common/wav.c Tue Mar 12 10:04:23 2024
@@ -1,7 +1,7 @@
-/* $NetBSD: wav.c,v 1.15 2019/11/09 12:46:44 mrg Exp $ */
+/* $NetBSD: wav.c,v 1.15.8.1 2024/03/12 10:04:23 martin Exp $ */
/*
- * Copyright (c) 2002, 2009, 2013, 2015, 2019 Matthew R. Green
+ * Copyright (c) 2002, 2009, 2013, 2015, 2019, 2024 Matthew R. Green
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -33,7 +33,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: wav.c,v 1.15 2019/11/09 12:46:44 mrg Exp $");
+__RCSID("$NetBSD: wav.c,v 1.15.8.1 2024/03/12 10:04:23 martin Exp $");
#endif
@@ -49,6 +49,7 @@ __RCSID("$NetBSD: wav.c,v 1.15 2019/11/0
#include <string.h>
#include <stdint.h>
#include <unistd.h>
+#include <stdbool.h>
#include "libaudio.h"
#include "auconv.h"
@@ -89,6 +90,49 @@ wav_enc_from_val(int encoding)
/*
* WAV format helpers
*/
+
+static bool
+find_riff_chunk(const char search[4], size_t *remainp, char **wherep, uint32_t *partlen)
+{
+ wav_audioheaderpart part;
+
+ *partlen = 0;
+
+#define ADJUST(l) do { \
+ if (l >= *(remainp)) \
+ return false; \
+ *(wherep) += (l); \
+ *(remainp) -= (l); \
+} while (0)
+
+ while (*remainp >= sizeof part) {
+ const char *emsg = "";
+ uint32_t len;
+
+ memcpy(&part, *wherep, sizeof part);
+ ADJUST(sizeof part);
+ len = getle32(part.len);
+ if (len % 2) {
+ emsg = " (odd length, adjusted)";
+ len += 1;
+ }
+ if (strncmp(part.name, search, sizeof *search) == 0) {
+ *partlen = len;
+ if (verbose > 1)
+ fprintf(stderr, "Found part %.04s length %d%s\n",
+ part.name, len, emsg);
+ return true;
+ }
+ ADJUST(len);
+ if (verbose > 1)
+ fprintf(stderr, "Skipping part %.04s length %d%s\n",
+ part.name, len, emsg);
+ }
+#undef ADJUST
+
+ return false;
+}
+
/*
* find a .wav header, etc. returns header length on success
*/
@@ -96,61 +140,87 @@ ssize_t
audio_wav_parse_hdr(void *hdr, size_t sz, u_int *enc, u_int *prec,
u_int *sample, u_int *channels, off_t *datasize)
{
- char *where = hdr, *owhere;
- wav_audioheaderpart part;
+ char *where = hdr;
wav_audioheaderfmt fmt;
wav_audiohdrextensible ext;
- char *end = (((char *)hdr) + sz);
+ size_t remain = sz;
u_int newenc, newprec;
+ uint32_t len = 0;
u_int16_t fmttag;
static const char
strfmt[4] = "fmt ",
strRIFF[4] = "RIFF",
strWAVE[4] = "WAVE",
strdata[4] = "data";
-
+ bool found;
+
if (sz < 32)
return (AUDIO_ENOENT);
- if (strncmp(where, strRIFF, sizeof strRIFF))
+#define ADJUST(l) do { \
+ if (l >= remain) \
+ return (AUDIO_ESHORTHDR); \
+ where += (l); \
+ remain -= (l); \
+} while (0)
+
+ if (memcmp(where, strRIFF, sizeof strRIFF) != 0)
return (AUDIO_ENOENT);
- where += 8;
- if (strncmp(where, strWAVE, sizeof strWAVE))
+ ADJUST(sizeof strRIFF);
+ /* XXX we ignore the RIFF length here */
+ ADJUST(4);
+ if (memcmp(where, strWAVE, sizeof strWAVE) != 0)
return (AUDIO_ENOENT);
- where += 4;
+ ADJUST(sizeof strWAVE);
- do {
- memcpy(&part, where, sizeof part);
- owhere = where;
- where += getle32(part.len) + 8;
- } while (where < end && strncmp(part.name, strfmt, sizeof strfmt));
+ found = find_riff_chunk(strfmt, &remain, &where, &len);
/* too short ? */
- if (where + sizeof fmt > end)
+ if (!found || remain <= sizeof fmt)
return (AUDIO_ESHORTHDR);
- memcpy(&fmt, (owhere + 8), sizeof fmt);
-
+ memcpy(&fmt, where, sizeof fmt);
fmttag = getle16(fmt.tag);
if (verbose)
- printf("WAVE format tag: %x\n", fmttag);
+ printf("WAVE format tag/len: %04x/%u\n", fmttag, len);
if (fmttag == WAVE_FORMAT_EXTENSIBLE) {
- if ((uintptr_t)(where - owhere) < sizeof(fmt) + sizeof(ext))
+ if (len < sizeof(fmt) + sizeof(ext)) {
+ if (verbose)
+ fprintf(stderr, "short WAVE ext fmt\n");
return (AUDIO_ESHORTHDR);
- memcpy(&ext, owhere + sizeof fmt, sizeof ext);
- if (getle16(ext.len) < sizeof(ext) - sizeof(ext.len))
+ }
+ if (remain <= sizeof ext + sizeof fmt) {
+ if (verbose)
+ fprintf(stderr, "WAVE ext truncated\n");
return (AUDIO_ESHORTHDR);
+ }
+ memcpy(&ext, where + sizeof fmt, sizeof ext);
fmttag = getle16(ext.sub_tag);
+ uint16_t sublen = getle16(ext.len);
if (verbose)
- printf("WAVE extensible sub tag: %x\n", fmttag);
+ printf("WAVE extensible tag/len: %04x/%u\n", fmttag, sublen);
+
+ /*
+ * XXXMRG: it may be that part.len (aka sizeof fmt + sizeof ext)
+ * should equal sizeof fmt + sizeof ext.len + sublen? this block
+ * is only entered for part.len == 40, where ext.len is expected
+ * to be 22 (sizeof ext.len = 2, sizeof fmt = 16).
+ *
+ * warn about this, but don't consider it an error.
+ */
+ if (getle16(ext.len) != 22 && verbose) {
+ fprintf(stderr, "warning: WAVE ext.len %u not 22\n",
+ getle16(ext.len));
+ }
+ } else if (len < sizeof(fmt)) {
+ if (verbose)
+ fprintf(stderr, "WAVE fmt unsupported size %u\n", len);
+ return (AUDIO_EWAVUNSUPP);
}
+ ADJUST(len);
switch (fmttag) {
- case WAVE_FORMAT_UNKNOWN:
- case IBM_FORMAT_MULAW:
- case IBM_FORMAT_ALAW:
- case IBM_FORMAT_ADPCM:
default:
return (AUDIO_EWAVUNSUPP);
@@ -205,13 +275,11 @@ audio_wav_parse_hdr(void *hdr, size_t sz
break;
}
- do {
- memcpy(&part, where, sizeof part);
- owhere = where;
- where += (getle32(part.len) + 8);
- } while (where < end && strncmp(part.name, strdata, sizeof strdata));
+ found = find_riff_chunk(strdata, &remain, &where, &len);
+ if (!found)
+ return (AUDIO_EWAVNODATA);
- if ((where - getle32(part.len)) <= end) {
+ if (len) {
if (channels)
*channels = (u_int)getle16(fmt.channels);
if (sample)
@@ -221,10 +289,12 @@ audio_wav_parse_hdr(void *hdr, size_t sz
if (prec)
*prec = newprec;
if (datasize)
- *datasize = (off_t)getle32(part.len);
- return (owhere - (char *)hdr + 8);
+ *datasize = (off_t)len;
+ return (where - (char *)hdr);
}
return (AUDIO_EWAVNODATA);
+
+#undef ADJUST
}
@@ -240,7 +310,7 @@ wav_prepare_header(struct track_info *ti
*
* bytes purpose
* 0-3 "RIFF"
- * 4-7 file length (minus 8)
+ * 4-7 RIFF chunk length (file length minus 8)
* 8-15 "WAVEfmt "
* 16-19 format size
* 20-21 format tag
@@ -287,6 +357,8 @@ wav_prepare_header(struct track_info *ti
break;
case 16:
break;
+ case 24:
+ break;
case 32:
break;
default:
@@ -372,7 +444,7 @@ wav_prepare_header(struct track_info *ti
abps = (double)align*ti->sample_rate / (double)1 + 0.5;
nsample = (datalen / ti->precision) / ti->sample_rate;
-
+
/*
* now we've calculated the info, write it out!
*/
Index: src/usr.bin/audio/play/audioplay.1
diff -u src/usr.bin/audio/play/audioplay.1:1.30.6.1 src/usr.bin/audio/play/audioplay.1:1.30.6.2
--- src/usr.bin/audio/play/audioplay.1:1.30.6.1 Tue Feb 14 16:05:53 2023
+++ src/usr.bin/audio/play/audioplay.1 Tue Mar 12 10:04:23 2024
@@ -1,6 +1,6 @@
-.\" $NetBSD: audioplay.1,v 1.30.6.1 2023/02/14 16:05:53 martin Exp $
+.\" $NetBSD: audioplay.1,v 1.30.6.2 2024/03/12 10:04:23 martin Exp $
.\"
-.\" Copyright (c) 1998, 1999, 2002, 2010, 2019 Matthew R. Green
+.\" Copyright (c) 1998, 1999, 2002, 2010, 2019, 2024 Matthew R. Green
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@@ -24,7 +24,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd April 10, 2020
+.Dd March 3, 2024
.Dt AUDIOPLAY 1
.Os
.Sh NAME
@@ -32,7 +32,7 @@
.Nd play audio files
.Sh SYNOPSIS
.Nm
-.Op Fl hiqV
+.Op Fl hinqV
.Op Fl B Ar buffersize
.Op Fl b Ar balance
.Op Fl d Ar device
@@ -118,6 +118,8 @@ sample rate.
Print a help message.
.It Fl i
If the audio device cannot be opened, exit now rather than wait for it.
+.It Fl n
+Do not write audio data, only parse files for sanity.
.It Fl P
When combined with the
.Fl f
@@ -175,7 +177,7 @@ files.
In addition to the audio driver encodings list in the EXAMPLES section,
.Nm
supports playing IEEE floating point data in RIFF WAVE audio files
-(with one caveat that the floating point size must be native.)
+(with one caveat that the floating point size must be native).
In this case
.Nm
converts the floating point data into signed linear samples before
@@ -208,4 +210,4 @@ Support for RIFF WAVE IEEE floating poin
The
.Nm
program was written by
-.An Matthew R. Green Aq Mt [email protected] .
+.An Matthew R. Green Aq Mt [email protected] .
Index: src/usr.bin/audio/play/play.c
diff -u src/usr.bin/audio/play/play.c:1.61 src/usr.bin/audio/play/play.c:1.61.2.1
--- src/usr.bin/audio/play/play.c:1.61 Sun May 15 02:16:06 2022
+++ src/usr.bin/audio/play/play.c Tue Mar 12 10:04:23 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: play.c,v 1.61 2022/05/15 02:16:06 mrg Exp $ */
+/* $NetBSD: play.c,v 1.61.2.1 2024/03/12 10:04:23 martin Exp $ */
/*
* Copyright (c) 1999, 2000, 2001, 2002, 2010, 2015, 2019, 2021 Matthew R. Green
@@ -28,7 +28,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: play.c,v 1.61 2022/05/15 02:16:06 mrg Exp $");
+__RCSID("$NetBSD: play.c,v 1.61.2.1 2024/03/12 10:04:23 martin Exp $");
#endif
#include <sys/param.h>
@@ -65,6 +65,7 @@ static int volume;
static int balance;
static int port;
static int fflag;
+static int nflag;
static int qflag;
int verbose;
static int sample_rate;
@@ -75,7 +76,7 @@ static int channels;
static char const *play_errstring = NULL;
static size_t bufsize;
-static int audiofd;
+static int audiofd = -1;
static int exitstatus = EXIT_SUCCESS;
int
@@ -87,7 +88,7 @@ main(int argc, char *argv[])
const char *defdevice = _PATH_SOUND;
const char *device = NULL;
- while ((ch = getopt(argc, argv, "b:B:C:c:d:e:fhip:P:qs:Vv:")) != -1) {
+ while ((ch = getopt(argc, argv, "b:B:C:c:d:e:fhinp:P:qs:Vv:")) != -1) {
switch (ch) {
case 'b':
decode_int(optarg, &balance);
@@ -118,6 +119,9 @@ main(int argc, char *argv[])
case 'i':
iflag++;
break;
+ case 'n':
+ nflag++;
+ break;
case 'q':
qflag++;
break;
@@ -173,22 +177,22 @@ main(int argc, char *argv[])
(device = getenv("AUDIODEV")) == NULL) /* Sun compatibility */
device = defdevice;
- audiofd = open(device, O_WRONLY);
- if (audiofd < 0 && device == defdevice) {
- device = _PATH_SOUND0;
+ if (!nflag) {
audiofd = open(device, O_WRONLY);
- }
-
- if (audiofd < 0)
- err(1, "failed to open %s", device);
+ if (audiofd < 0 && device == defdevice) {
+ device = _PATH_SOUND0;
+ audiofd = open(device, O_WRONLY);
+ }
+ if (audiofd < 0)
+ err(1, "failed to open %s", device);
- if (ioctl(audiofd, AUDIO_GETINFO, &info) < 0)
- err(1, "failed to get audio info");
- if (bufsize == 0) {
- bufsize = info.play.buffer_size;
- if (bufsize < 32 * 1024)
- bufsize = 32 * 1024;
+ if (ioctl(audiofd, AUDIO_GETINFO, &info) < 0)
+ err(1, "failed to get audio info");
+ if (bufsize == 0)
+ bufsize = info.play.buffer_size;
}
+ if (bufsize == 0)
+ bufsize = 32 * 1024;
signal(SIGINT, cleanup);
signal(SIGTERM, cleanup);
@@ -208,9 +212,12 @@ static void
cleanup(int signo)
{
- (void)ioctl(audiofd, AUDIO_FLUSH, NULL);
- (void)ioctl(audiofd, AUDIO_SETINFO, &info);
- close(audiofd);
+ if (audiofd != -1) {
+ (void)ioctl(audiofd, AUDIO_FLUSH, NULL);
+ (void)ioctl(audiofd, AUDIO_SETINFO, &info);
+ close(audiofd);
+ audiofd = -1;
+ }
if (signo != 0) {
(void)raise_default_signal(signo);
}
@@ -283,6 +290,9 @@ audio_write(int fd, void *buf, size_t le
static void *convert_buffer;
static size_t convert_buffer_size;
+ if (nflag)
+ return len;
+
if (conv == NULL)
return write(fd, buf, len);
@@ -317,8 +327,7 @@ play(char *file)
fd = open(file, O_RDONLY);
if (fd < 0) {
- if (!qflag)
- warn("could not open %s", file);
+ warn("could not open %s", file);
exitstatus = EXIT_FAILURE;
return;
}
@@ -359,6 +368,8 @@ play(char *file)
else
errx(1, "unknown audio file: %s", file);
}
+ if (verbose)
+ printf("header length: %zd\n", hdrlen);
filesize -= hdrlen;
addr = (char *)addr + hdrlen;
@@ -383,7 +394,7 @@ play(char *file)
if ((off_t)nw != datasize)
errx(1, "final write failed");
- if (ioctl(audiofd, AUDIO_DRAIN) < 0 && !qflag)
+ if (!nflag && ioctl(audiofd, AUDIO_DRAIN) < 0 && !qflag)
warn("audio drain ioctl failed");
if (munmap(oaddr, sizet_filesize) < 0)
err(1, "munmap failed");
@@ -446,7 +457,7 @@ play_fd(const char *file, int fd)
break;
}
/* something to think about: no message given for dataout < datasize */
- if (ioctl(audiofd, AUDIO_DRAIN) < 0 && !qflag)
+ if (!nflag && ioctl(audiofd, AUDIO_DRAIN) < 0 && !qflag)
warn("audio drain ioctl failed");
return;
read_error:
@@ -571,7 +582,7 @@ set_audio_mode:
}
#endif /* __vax__ */
- if (ioctl(fd, AUDIO_SETINFO, &info) < 0)
+ if (!nflag && ioctl(fd, AUDIO_SETINFO, &info) < 0)
err(1, "failed to set audio info");
return (hdr_len);
@@ -581,7 +592,7 @@ static void
usage(void)
{
- fprintf(stderr, "Usage: %s [-hiqV] [options] files\n", getprogname());
+ fprintf(stderr, "Usage: %s [-hinqV] [options] files\n", getprogname());
fprintf(stderr, "Options:\n\t"
"-B buffer size\n\t"
"-b balance (0-63)\n\t"
Index: src/usr.bin/audio/record/audiorecord.1
diff -u src/usr.bin/audio/record/audiorecord.1:1.44 src/usr.bin/audio/record/audiorecord.1:1.44.6.1
--- src/usr.bin/audio/record/audiorecord.1:1.44 Thu Mar 25 10:03:26 2021
+++ src/usr.bin/audio/record/audiorecord.1 Tue Mar 12 10:04:23 2024
@@ -1,4 +1,4 @@
-.\" $NetBSD: audiorecord.1,v 1.44 2021/03/25 10:03:26 nia Exp $
+.\" $NetBSD: audiorecord.1,v 1.44.6.1 2024/03/12 10:04:23 martin Exp $
.\"
.\" Copyright (c) 1998, 1999, 2001, 2002, 2010 Matthew R. Green
.\" All rights reserved.
@@ -223,7 +223,7 @@ big/little-endian samples was first made
The
.Nm
program was written by
-.An Matthew R. Green Aq Mt [email protected] .
+.An Matthew R. Green Aq Mt [email protected] .
.Sh BUGS
WAV big-endian samples are converted to little-endian, rather than
a RIFX header being written.
Index: src/usr.bin/audio/record/record.c
diff -u src/usr.bin/audio/record/record.c:1.56 src/usr.bin/audio/record/record.c:1.56.2.1
--- src/usr.bin/audio/record/record.c:1.56 Sun Jan 9 06:33:13 2022
+++ src/usr.bin/audio/record/record.c Tue Mar 12 10:04:23 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: record.c,v 1.56 2022/01/09 06:33:13 mlelstv Exp $ */
+/* $NetBSD: record.c,v 1.56.2.1 2024/03/12 10:04:23 martin Exp $ */
/*
* Copyright (c) 1999, 2002, 2003, 2005, 2010 Matthew R. Green
@@ -32,7 +32,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: record.c,v 1.56 2022/01/09 06:33:13 mlelstv Exp $");
+__RCSID("$NetBSD: record.c,v 1.56.2.1 2024/03/12 10:04:23 martin Exp $");
#endif
@@ -312,19 +312,27 @@ main(int argc, char *argv[])
s = "change sign (big-endian, 16 bit)";
else if (conv_func == change_sign16_le)
s = "change sign (little-endian, 16 bit)";
+ else if (conv_func == change_sign24_be)
+ s = "change sign (big-endian, 24 bit)";
+ else if (conv_func == change_sign24_le)
+ s = "change sign (little-endian, 24 bit)";
else if (conv_func == change_sign32_be)
s = "change sign (big-endian, 32 bit)";
else if (conv_func == change_sign32_le)
s = "change sign (little-endian, 32 bit)";
else if (conv_func == change_sign16_swap_bytes_be)
s = "change sign & swap bytes (big-endian, 16 bit)";
- else if (conv_func == change_sign16_swap_bytes_le)
+ else if (conv_func == change_sign24_swap_bytes_le)
s = "change sign & swap bytes (little-endian, 16 bit)";
+ else if (conv_func == change_sign16_swap_bytes_be)
+ s = "change sign & swap bytes (big-endian, 24 bit)";
+ else if (conv_func == change_sign24_swap_bytes_le)
+ s = "change sign & swap bytes (little-endian, 24 bit)";
else if (conv_func == change_sign32_swap_bytes_be)
s = "change sign (big-endian, 32 bit)";
else if (conv_func == change_sign32_swap_bytes_le)
s = "change sign & swap bytes (little-endian, 32 bit)";
-
+
if (s)
fprintf(stderr, "%s: converting, using function: %s\n",
getprogname(), s);