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 m...@eterna.com.au . +.An Matthew R. Green Aq Mt m...@eterna23.net . 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 m...@eterna.com.au . +.An Matthew R. Green Aq Mt m...@eterna23.net . .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);