Module Name: src
Committed By: martin
Date: Tue Mar 12 12:47:41 UTC 2024
Modified Files:
src/usr.bin/audio/common [netbsd-8]: auconv.h audio.c decode.c
libaudio.h sun.c wav.c
src/usr.bin/audio/play [netbsd-8]: audioplay.1 play.c
src/usr.bin/audio/record [netbsd-8]: audiorecord.1 record.c
Log Message:
Pull up the following revisions, requested by mrg in ticket #1948:
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 playing 32-bit and 64-bit IEEE FP .wav files
- 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)
- audiorecord manual gained useful examples
To generate a diff of this commit:
cvs rdiff -u -r1.5 -r1.5.54.1 src/usr.bin/audio/common/auconv.h
cvs rdiff -u -r1.25 -r1.25.8.1 src/usr.bin/audio/common/audio.c
cvs rdiff -u -r1.1 -r1.1.8.1 src/usr.bin/audio/common/decode.c
cvs rdiff -u -r1.20 -r1.20.8.1 src/usr.bin/audio/common/libaudio.h
cvs rdiff -u -r1.9 -r1.9.8.1 src/usr.bin/audio/common/sun.c
cvs rdiff -u -r1.13.8.1 -r1.13.8.2 src/usr.bin/audio/common/wav.c
cvs rdiff -u -r1.26 -r1.26.18.1 src/usr.bin/audio/play/audioplay.1
cvs rdiff -u -r1.55 -r1.55.8.1 src/usr.bin/audio/play/play.c
cvs rdiff -u -r1.42 -r1.42.18.1 src/usr.bin/audio/record/audiorecord.1
cvs rdiff -u -r1.54 -r1.54.8.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.54.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 12:47:40 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.54.1 2024/03/12 12:47:40 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.25 src/usr.bin/audio/common/audio.c:1.25.8.1
--- src/usr.bin/audio/common/audio.c:1.25 Wed Aug 5 06:54:39 2015
+++ src/usr.bin/audio/common/audio.c Tue Mar 12 12:47:40 2024
@@ -1,7 +1,7 @@
-/* $NetBSD: audio.c,v 1.25 2015/08/05 06:54:39 mrg Exp $ */
+/* $NetBSD: audio.c,v 1.25.8.1 2024/03/12 12:47:40 martin Exp $ */
/*
- * Copyright (c) 1999 Matthew R. Green
+ * Copyright (c) 1999, 2013, 2015, 2019 Matthew R. Green
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,7 +32,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: audio.c,v 1.25 2015/08/05 06:54:39 mrg Exp $");
+__RCSID("$NetBSD: audio.c,v 1.25.8.1 2024/03/12 12:47:40 martin Exp $");
#endif
@@ -110,6 +110,8 @@ static const struct {
{ AudioEmpeg_l2_packets,AUDIO_ENCODING_MPEG_L2_PACKETS },
{ AudioEmpeg_l2_system, AUDIO_ENCODING_MPEG_L2_SYSTEM },
{ AudioEac3, AUDIO_ENCODING_AC3 },
+ { "ieee_float32", AUDIO_ENCODING_LIBAUDIO_FLOAT32 },
+ { "ieee_float64", AUDIO_ENCODING_LIBAUDIO_FLOAT64 },
{ NULL, -1 }
};
@@ -203,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.8.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 12:47:40 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.8.1 2024/03/12 12:47:40 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.8.1 2024/03/12 12:47:40 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.20 src/usr.bin/audio/common/libaudio.h:1.20.8.1
--- src/usr.bin/audio/common/libaudio.h:1.20 Wed Aug 5 06:54:39 2015
+++ src/usr.bin/audio/common/libaudio.h Tue Mar 12 12:47:40 2024
@@ -1,7 +1,7 @@
-/* $NetBSD: libaudio.h,v 1.20 2015/08/05 06:54:39 mrg Exp $ */
+/* $NetBSD: libaudio.h,v 1.20.8.1 2024/03/12 12:47:40 martin Exp $ */
/*
- * Copyright (c) 1999, 2009 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
@@ -37,6 +37,17 @@
int audio_format_from_str (char *);
/*
+ * Audio encoding formats; this is a additional to those set
+ * in sys/audioio.h, but with a large offset to avoid future
+ * conflicts (additional ones are libaudio-software only.)
+ *
+ * This is to support floating-point WAV files. These require
+ * software conversion to a supported format.
+ */
+#define AUDIO_ENCODING_LIBAUDIO_FLOAT32 1001 /* 32-bit IEEE FP. */
+#define AUDIO_ENCODING_LIBAUDIO_FLOAT64 1002 /* 64-bit IEEE FP. */
+
+/*
* We copy the Sun/NeXT on-disk audio header format and document what
* we know of it here.
*
@@ -95,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
*/
/*
@@ -107,29 +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 or mplayer */
+/* 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);
@@ -143,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;
@@ -153,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.9 src/usr.bin/audio/common/sun.c:1.9.8.1
--- src/usr.bin/audio/common/sun.c:1.9 Wed Aug 5 06:54:39 2015
+++ src/usr.bin/audio/common/sun.c Tue Mar 12 12:47:40 2024
@@ -1,7 +1,7 @@
-/* $NetBSD: sun.c,v 1.9 2015/08/05 06:54:39 mrg Exp $ */
+/* $NetBSD: sun.c,v 1.9.8.1 2024/03/12 12:47:40 martin Exp $ */
/*
- * Copyright (c) 2002 Matthew R. Green
+ * Copyright (c) 2002, 2013, 2015 Matthew R. Green
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,7 +32,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: sun.c,v 1.9 2015/08/05 06:54:39 mrg Exp $");
+__RCSID("$NetBSD: sun.c,v 1.9.8.1 2024/03/12 12:47:40 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.13.8.1 src/usr.bin/audio/common/wav.c:1.13.8.2
--- src/usr.bin/audio/common/wav.c:1.13.8.1 Mon Nov 27 12:00:37 2017
+++ src/usr.bin/audio/common/wav.c Tue Mar 12 12:47:40 2024
@@ -1,7 +1,7 @@
-/* $NetBSD: wav.c,v 1.13.8.1 2017/11/27 12:00:37 martin Exp $ */
+/* $NetBSD: wav.c,v 1.13.8.2 2024/03/12 12:47:40 martin Exp $ */
/*
- * Copyright (c) 2002, 2009 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.13.8.1 2017/11/27 12:00:37 martin Exp $");
+__RCSID("$NetBSD: wav.c,v 1.13.8.2 2024/03/12 12:47:40 martin Exp $");
#endif
@@ -49,6 +49,7 @@ __RCSID("$NetBSD: wav.c,v 1.13.8.1 2017/
#include <string.h>
#include <stdint.h>
#include <unistd.h>
+#include <stdbool.h>
#include "libaudio.h"
#include "auconv.h"
@@ -60,6 +61,7 @@ static const struct {
{ WAVE_FORMAT_UNKNOWN, "Microsoft Official Unknown" },
{ WAVE_FORMAT_PCM, "Microsoft PCM" },
{ WAVE_FORMAT_ADPCM, "Microsoft ADPCM" },
+ { WAVE_FORMAT_IEEE_FLOAT,"Microsoft IEEE Floating-Point" },
{ WAVE_FORMAT_ALAW, "Microsoft A-law" },
{ WAVE_FORMAT_MULAW, "Microsoft mu-law" },
{ WAVE_FORMAT_OKI_ADPCM,"OKI ADPCM" },
@@ -88,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
*/
@@ -95,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);
@@ -188,15 +259,27 @@ audio_wav_parse_hdr(void *hdr, size_t sz
newenc = AUDIO_ENCODING_ULAW;
newprec = 8;
break;
+ case WAVE_FORMAT_IEEE_FLOAT:
+ switch (getle16(fmt.bits_per_sample)) {
+ case 32:
+ newenc = AUDIO_ENCODING_LIBAUDIO_FLOAT32;
+ newprec = 32;
+ break;
+ case 64:
+ newenc = AUDIO_ENCODING_LIBAUDIO_FLOAT64;
+ newprec = 32;
+ break;
+ default:
+ return (AUDIO_EWAVBADPCM);
+ }
+ 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)
@@ -206,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
}
@@ -225,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
@@ -272,6 +357,8 @@ wav_prepare_header(struct track_info *ti
break;
case 16:
break;
+ case 24:
+ break;
case 32:
break;
default:
@@ -357,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.26 src/usr.bin/audio/play/audioplay.1:1.26.18.1
--- src/usr.bin/audio/play/audioplay.1:1.26 Tue Mar 18 18:20:44 2014
+++ src/usr.bin/audio/play/audioplay.1 Tue Mar 12 12:47:40 2024
@@ -1,6 +1,6 @@
-.\" $NetBSD: audioplay.1,v 1.26 2014/03/18 18:20:44 riastradh Exp $
+.\" $NetBSD: audioplay.1,v 1.26.18.1 2024/03/12 12:47:40 martin Exp $
.\"
-.\" Copyright (c) 1998, 1999, 2002, 2010 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 December 30, 2010
+.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
@@ -169,11 +171,19 @@ program can be used to show the availabl
.Nm
can be used to play Sun/NeXT audio files, and also RIFF WAVE audio files.
.Nm
-can be configured in the
-.Dq Netscape
-web browser as the program to use when playing audio files.
+can be configured in a web browser as the program to use when playing audio
+files.
+.Pp
+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).
+In this case
+.Nm
+converts the floating point data into signed linear samples before
+they are passed to the chosen audio device.
.Sh ERRORS
-If the audio device or the control device can not be opened, and error is
+If the audio device or the control device can not be opened, an error is
returned.
.Pp
If an invalid parameter is specified, an error is returned.
@@ -182,29 +192,7 @@ hardware driver.
.Sh SEE ALSO
.Xr audioctl 1 ,
.Xr audiorecord 1 ,
-.Xr aria 4 ,
-.Xr audio 4 ,
-.Xr audioamd 4 ,
-.Xr auich 4 ,
-.Xr autri 4 ,
-.Xr auvia 4 ,
-.Xr clcs 4 ,
-.Xr clct 4 ,
-.Xr cmpci 4 ,
-.Xr eap 4 ,
-.Xr emuxki 4 ,
-.Xr esm 4 ,
-.Xr eso 4 ,
-.Xr ess 4 ,
-.Xr fms 4 ,
-.Xr gus 4 ,
-.Xr guspnp 4 ,
-.Xr neo 4 ,
-.Xr sb 4 ,
-.Xr sv 4 ,
-.Xr wss 4 ,
-.Xr yds 4 ,
-.Xr ym 4
+.Xr audio 4
.Sh HISTORY
The
.Nm
@@ -214,8 +202,12 @@ The
.Nm
was first made available in
.Nx 1.4 .
+Support for RIFF WAVE recording was introduced in
+.Nx 1.6 .
+Support for RIFF WAVE IEEE floating point data was introduced in
+.Nx 10.0 .
.Sh AUTHORS
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.55 src/usr.bin/audio/play/play.c:1.55.8.1
--- src/usr.bin/audio/play/play.c:1.55 Wed Aug 5 06:54:39 2015
+++ src/usr.bin/audio/play/play.c Tue Mar 12 12:47:40 2024
@@ -1,7 +1,7 @@
-/* $NetBSD: play.c,v 1.55 2015/08/05 06:54:39 mrg Exp $ */
+/* $NetBSD: play.c,v 1.55.8.1 2024/03/12 12:47:40 martin Exp $ */
/*
- * Copyright (c) 1999, 2000, 2001, 2002, 2010 Matthew R. Green
+ * Copyright (c) 1999, 2000, 2001, 2002, 2010, 2015, 2019, 2021 Matthew R. Green
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -28,10 +28,9 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: play.c,v 1.55 2015/08/05 06:54:39 mrg Exp $");
+__RCSID("$NetBSD: play.c,v 1.55.8.1 2024/03/12 12:47:40 martin Exp $");
#endif
-
#include <sys/param.h>
#include <sys/audioio.h>
#include <sys/ioctl.h>
@@ -51,10 +50,14 @@ __RCSID("$NetBSD: play.c,v 1.55 2015/08/
#include "libaudio.h"
+typedef size_t (*convert)(void *inbuf, void *outbuf, size_t len);
+
static void usage(void) __dead;
static void play(char *);
static void play_fd(const char *, int);
-static ssize_t audioctl_write_fromhdr(void *, size_t, int, off_t *, const char *);
+static ssize_t audioctl_write_fromhdr(void *, size_t, int,
+ off_t *, const char *,
+ convert *);
static void cleanup(int) __dead;
static audio_info_t info;
@@ -62,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;
@@ -72,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
@@ -84,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);
@@ -115,6 +119,9 @@ main(int argc, char *argv[])
case 'i':
iflag++;
break;
+ case 'n':
+ nflag++;
+ break;
case 'q':
qflag++;
break;
@@ -170,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);
@@ -205,18 +212,105 @@ 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);
}
exit(exitstatus);
}
+#ifndef __vax__
+static size_t
+float32_to_linear32(void *inbuf, void *outbuf, size_t len)
+{
+ uint8_t *inbuf8 = inbuf, *end = inbuf8 + len;
+ uint8_t *outbuf8 = outbuf;
+ float f;
+ int32_t i;
+
+ while (inbuf8 + sizeof f <= end) {
+ memcpy(&f, inbuf8, sizeof f);
+
+ /* saturate */
+ if (f < -1.0)
+ f = -1.0;
+ if (f > 1.0)
+ f = 1.0;
+
+ /* Convert -1.0 to +1.0 into a 32 bit signed value */
+ i = f * (float)INT32_MAX;
+
+ memcpy(outbuf8, &i, sizeof i);
+
+ inbuf8 += sizeof f;
+ outbuf8 += sizeof i;
+ }
+
+ return len;
+}
+
+static size_t
+float64_to_linear32(void *inbuf, void *outbuf, size_t len)
+{
+ uint8_t *inbuf8 = inbuf, *end = inbuf8 + len;
+ uint8_t *outbuf8 = outbuf;
+ double f;
+ int32_t i;
+
+ while (inbuf8 + sizeof f <= end) {
+ memcpy(&f, inbuf8, sizeof f);
+
+ /* saturate */
+ if (f < -1.0)
+ f = -1.0;
+ if (f > 1.0)
+ f = 1.0;
+
+ /* Convert -1.0 to +1.0 into a 32 bit signed value */
+ i = f * ((1u << 31) - 1);
+
+ memcpy(outbuf8, &i, sizeof i);
+
+ inbuf8 += sizeof f;
+ outbuf8 += sizeof i;
+ }
+
+ return len / 2;
+}
+#endif /* __vax__ */
+
+static size_t
+audio_write(int fd, void *buf, size_t len, convert conv)
+{
+ static void *convert_buffer;
+ static size_t convert_buffer_size;
+
+ if (nflag)
+ return len;
+
+ if (conv == NULL)
+ return write(fd, buf, len);
+
+ if (convert_buffer == NULL || convert_buffer_size < len) {
+ free(convert_buffer);
+ convert_buffer = malloc(len);
+ if (convert_buffer == NULL)
+ err(1, "malloc of convert buffer failed");
+ convert_buffer_size = len;
+ }
+ len = conv(buf, convert_buffer, len);
+ return write(fd, convert_buffer, len);
+}
+
static void
play(char *file)
{
+ convert conv = NULL;
struct stat sb;
void *addr, *oaddr;
off_t filesize;
@@ -224,6 +318,7 @@ play(char *file)
off_t datasize = 0;
ssize_t hdrlen;
int fd;
+ int nw;
if (file[0] == '-' && file[1] == 0) {
play_fd("standard input", STDIN_FILENO);
@@ -232,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;
}
@@ -248,7 +342,7 @@ play(char *file)
* or if we failed to mmap the file, try to read it instead, so
* that filesystems, etc, that do not support mmap() work
*/
- if (S_ISREG(sb.st_rdev & S_IFMT) == 0 ||
+ if (!S_ISREG(sb.st_mode) ||
((off_t)sizet_filesize != filesize) ||
(oaddr = addr = mmap(0, sizet_filesize, PROT_READ,
MAP_SHARED, fd, 0)) == MAP_FAILED) {
@@ -264,15 +358,18 @@ play(char *file)
madvise(addr, sizet_filesize, MADV_SEQUENTIAL);
/*
- * get the header length and set up the audio device
+ * get the header length and set up the audio device, and
+ * determine any conversion needed.
*/
if ((hdrlen = audioctl_write_fromhdr(addr,
- sizet_filesize, audiofd, &datasize, file)) < 0) {
+ sizet_filesize, audiofd, &datasize, file, &conv)) < 0) {
if (play_errstring)
errx(1, "%s: %s", play_errstring, file);
else
errx(1, "unknown audio file: %s", file);
}
+ if (verbose)
+ printf("header length: %zd\n", hdrlen);
filesize -= hdrlen;
addr = (char *)addr + hdrlen;
@@ -283,15 +380,21 @@ play(char *file)
}
while ((uint64_t)datasize > bufsize) {
- if ((size_t)write(audiofd, addr, bufsize) != bufsize)
+ nw = audio_write(audiofd, addr, bufsize, conv);
+ if (nw == -1)
err(1, "write failed");
+ if ((size_t)nw != bufsize)
+ errx(1, "write failed");
addr = (char *)addr + bufsize;
datasize -= bufsize;
}
- if ((off_t)write(audiofd, addr, datasize) != datasize)
+ nw = audio_write(audiofd, addr, datasize, conv);
+ if (nw == -1)
err(1, "final write failed");
+ 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");
@@ -305,6 +408,7 @@ play(char *file)
static void
play_fd(const char *file, int fd)
{
+ convert conv = NULL;
char *buffer = malloc(bufsize);
ssize_t hdrlen;
int nr, nw;
@@ -324,7 +428,7 @@ play_fd(const char *file, int fd)
}
err(1, "unexpected EOF");
}
- hdrlen = audioctl_write_fromhdr(buffer, nr, audiofd, &datasize, file);
+ hdrlen = audioctl_write_fromhdr(buffer, nr, audiofd, &datasize, file, &conv);
if (hdrlen < 0) {
if (play_errstring)
errx(1, "%s: %s", play_errstring, file);
@@ -340,9 +444,11 @@ play_fd(const char *file, int fd)
while (datasize == 0 || dataout < datasize) {
if (datasize != 0 && dataout + nr > datasize)
nr = datasize - dataout;
- nw = write(audiofd, buffer, nr);
+ nw = audio_write(audiofd, buffer, nr, conv);
+ if (nw == -1)
+ err(1, "audio device write failed");
if (nw != nr)
- goto write_error;
+ errx(1, "audio device write failed");
dataout += nw;
nr = read(fd, buffer, bufsize);
if (nr == -1)
@@ -351,13 +457,11 @@ 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:
err(1, "read of standard input failed");
-write_error:
- err(1, "audio device write failed");
}
/*
@@ -367,11 +471,13 @@ write_error:
* uses the local "info" variable. blah... fix me!
*/
static ssize_t
-audioctl_write_fromhdr(void *hdr, size_t fsz, int fd, off_t *datasize, const char *file)
+audioctl_write_fromhdr(void *hdr, size_t fsz, int fd, off_t *datasize, const char *file, convert *conv)
{
sun_audioheader *sunhdr;
ssize_t hdr_len = 0;
+ *conv = NULL;
+
AUDIO_INITINFO(&info);
sunhdr = hdr;
if (ntohl(sunhdr->magic) == AUDIO_FILE_MAGIC) {
@@ -450,7 +556,33 @@ set_audio_mode:
enc ? enc : "");
}
- if (ioctl(fd, AUDIO_SETINFO, &info) < 0)
+#ifndef __vax__
+ if (info.play.encoding == AUDIO_ENCODING_LIBAUDIO_FLOAT32 ||
+ info.play.encoding == AUDIO_ENCODING_LIBAUDIO_FLOAT64) {
+ const char *msg;
+
+ if (info.play.encoding == AUDIO_ENCODING_LIBAUDIO_FLOAT32) {
+ if (sizeof(float) * CHAR_BIT != 32)
+ return -1;
+ *conv = float32_to_linear32;
+ msg = "32";
+ } else {
+ if (sizeof(double) * CHAR_BIT != 64)
+ return -1;
+ *conv = float64_to_linear32;
+ msg = "64";
+ }
+ info.play.encoding = AUDIO_ENCODING_SLINEAR_LE;
+ info.play.precision = 32;
+ if (verbose)
+ printf("%s: converting IEEE float%s to precision=%d "
+ "encoding=%s\n", file, msg,
+ info.play.precision,
+ audio_enc_from_val(info.play.encoding));
+ }
+#endif /* __vax__ */
+
+ if (!nflag && ioctl(fd, AUDIO_SETINFO, &info) < 0)
err(1, "failed to set audio info");
return (hdr_len);
@@ -460,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.42 src/usr.bin/audio/record/audiorecord.1:1.42.18.1
--- src/usr.bin/audio/record/audiorecord.1:1.42 Tue Mar 18 18:20:44 2014
+++ src/usr.bin/audio/record/audiorecord.1 Tue Mar 12 12:47:41 2024
@@ -1,4 +1,4 @@
-.\" $NetBSD: audiorecord.1,v 1.42 2014/03/18 18:20:44 riastradh Exp $
+.\" $NetBSD: audiorecord.1,v 1.42.18.1 2024/03/12 12:47:41 martin Exp $
.\"
.\" Copyright (c) 1998, 1999, 2001, 2002, 2010 Matthew R. Green
.\" All rights reserved.
@@ -24,7 +24,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd December 30, 2010
+.Dd March 25, 2021
.Dt AUDIORECORD 1
.Os
.Sh NAME
@@ -181,12 +181,14 @@ the audio control device to be used.
.It AUDIODEVICE
the audio device to be used.
.El
+.Sh EXAMPLES
+Record CD quality audio to a WAVE file:
+.Dl audiorecord -c 2 -e slinear_le -P 16 -s 44100 recording.wav
.Sh SEE ALSO
.Xr audioctl 1 ,
.Xr audioplay 1 ,
.Xr aria 4 ,
.Xr audio 4 ,
-.Xr audioamd 4 ,
.Xr auich 4 ,
.Xr autri 4 ,
.Xr auvia 4 ,
@@ -203,6 +205,7 @@ the audio device to be used.
.Xr guspnp 4 ,
.Xr neo 4 ,
.Xr sb 4 ,
+.Xr sparc/audioamd 4 ,
.Xr sv 4 ,
.Xr wss 4 ,
.Xr yds 4 ,
@@ -220,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.54 src/usr.bin/audio/record/record.c:1.54.8.1
--- src/usr.bin/audio/record/record.c:1.54 Wed Aug 5 06:54:39 2015
+++ src/usr.bin/audio/record/record.c Tue Mar 12 12:47:41 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: record.c,v 1.54 2015/08/05 06:54:39 mrg Exp $ */
+/* $NetBSD: record.c,v 1.54.8.1 2024/03/12 12:47:41 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.54 2015/08/05 06:54:39 mrg Exp $");
+__RCSID("$NetBSD: record.c,v 1.54.8.1 2024/03/12 12:47:41 martin Exp $");
#endif
@@ -68,6 +68,7 @@ static char *encoding_str;
static struct track_info ti;
static struct timeval record_time;
static struct timeval start_time;
+static int no_time_limit = 1;
static void (*conv_func) (u_char *, int);
@@ -75,13 +76,21 @@ static void usage (void) __dead;
static int timeleft (struct timeval *, struct timeval *);
static void cleanup (int) __dead;
static void rewrite_header (void);
+static void stop (int);
+
+static void stop (int sig)
+{
+ no_time_limit = 0;
+ timerclear(&record_time);
+}
int
main(int argc, char *argv[])
{
u_char *buffer;
size_t len, bufsize = 0;
- int ch, no_time_limit = 1;
+ ssize_t nread;
+ int ch;
const char *defdevice = _PATH_SOUND;
/*
@@ -283,7 +292,7 @@ main(int argc, char *argv[])
if (ioctl(audiofd, AUDIO_SETINFO, &info) < 0)
err(1, "failed to set audio info");
- signal(SIGINT, cleanup);
+ signal(SIGINT, stop);
ti.total_size = 0;
@@ -303,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);
@@ -337,13 +354,15 @@ main(int argc, char *argv[])
(void)gettimeofday(&start_time, NULL);
while (no_time_limit || timeleft(&start_time, &record_time)) {
- if ((size_t)read(audiofd, buffer, bufsize) != bufsize)
+ if ((nread = read(audiofd, buffer, bufsize)) == -1)
err(1, "read failed");
+ if (nread == 0)
+ break;
if (conv_func)
- (*conv_func)(buffer, bufsize);
- if ((size_t)write(ti.outfd, buffer, bufsize) != bufsize)
+ (*conv_func)(buffer, nread);
+ if (write(ti.outfd, buffer, nread) != nread)
err(1, "write failed");
- ti.total_size += bufsize;
+ ti.total_size += nread;
}
cleanup(0);
}
@@ -386,7 +405,6 @@ rewrite_header(void)
/* can't do this here! */
if (ti.outfd == STDOUT_FILENO)
return;
-
if (lseek(ti.outfd, (off_t)0, SEEK_SET) == (off_t)-1)
err(1, "could not seek to start of file for header rewrite");
write_header(&ti);