Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/usr.bin/audio move most of the header writing code from reco...
details: https://anonhg.NetBSD.org/src/rev/a4d039906bd8
branches: trunk
changeset: 789662:a4d039906bd8
user: mrg <mrg%NetBSD.org@localhost>
date: Fri Aug 30 20:57:26 2013 +0000
description:
move most of the header writing code from record.c into wav.c and sun.c.
introduce a struct write_info for communication between front ends and
backends.
libaudio API is still pretty ugly, and needs to stay local here for now,
but it is a little more usable for other tools now.
diffstat:
usr.bin/audio/common/audio.c | 76 ++++++-
usr.bin/audio/common/libaudio.h | 34 ++-
usr.bin/audio/common/sun.c | 130 ++++++++++-
usr.bin/audio/common/wav.c | 271 ++++++++++++++++++++++-
usr.bin/audio/ctl/ctl.c | 6 +-
usr.bin/audio/record/record.c | 474 ++++-----------------------------------
6 files changed, 561 insertions(+), 430 deletions(-)
diffs (truncated from 1269 to 300 lines):
diff -r 70e85494823f -r a4d039906bd8 usr.bin/audio/common/audio.c
--- a/usr.bin/audio/common/audio.c Fri Aug 30 16:43:33 2013 +0000
+++ b/usr.bin/audio/common/audio.c Fri Aug 30 20:57:26 2013 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: audio.c,v 1.21 2011/09/06 22:41:53 jmcneill Exp $ */
+/* $NetBSD: audio.c,v 1.22 2013/08/30 20:57:26 mrg Exp $ */
/*
* Copyright (c) 1999 Matthew R. Green
@@ -32,7 +32,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: audio.c,v 1.21 2011/09/06 22:41:53 jmcneill Exp $");
+__RCSID("$NetBSD: audio.c,v 1.22 2013/08/30 20:57:26 mrg Exp $");
#endif
@@ -40,7 +40,9 @@
#include <sys/audioio.h>
#include <sys/ioctl.h>
#include <sys/time.h>
+#include <sys/uio.h>
+#include <unistd.h>
#include <ctype.h>
#include <err.h>
#include <stdio.h>
@@ -48,6 +50,7 @@
#include <string.h>
#include "libaudio.h"
+#include "auconv.h"
/* what format am i? */
@@ -66,6 +69,8 @@
{ NULL, -1 }
};
+char audio_default_info[8] = { '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' };
+
int
audio_format_from_str(char *str)
{
@@ -233,3 +238,70 @@
return "Invalid error";
return audio_errlist[errval];
}
+
+void
+write_header(struct write_info *wi)
+{
+ struct iovec iv[3];
+ int veclen, left, tlen;
+ void *hdr;
+ size_t hdrlen;
+
+ switch (wi->format) {
+ case AUDIO_FORMAT_DEFAULT:
+ case AUDIO_FORMAT_SUN:
+ if (sun_prepare_header(wi, &hdr, &hdrlen, &left) != 0)
+ return;
+ break;
+ case AUDIO_FORMAT_WAV:
+ if (wav_prepare_header(wi, &hdr, &hdrlen, &left) != 0)
+ return;
+ break;
+ case AUDIO_FORMAT_NONE:
+ return;
+ default:
+ errx(1, "unknown audio format");
+ }
+
+ veclen = 0;
+ tlen = 0;
+
+ if (hdrlen != 0) {
+ iv[veclen].iov_base = hdr;
+ iv[veclen].iov_len = hdrlen;
+ tlen += iv[veclen++].iov_len;
+ }
+ if (wi->header_info) {
+ iv[veclen].iov_base = wi->header_info;
+ iv[veclen].iov_len = (int)strlen(wi->header_info) + 1;
+ tlen += iv[veclen++].iov_len;
+ }
+ if (left) {
+ iv[veclen].iov_base = audio_default_info;
+ iv[veclen].iov_len = left;
+ tlen += iv[veclen++].iov_len;
+ }
+
+ if (tlen == 0)
+ return;
+
+ if (writev(wi->outfd, iv, veclen) != tlen)
+ err(1, "could not write audio header");
+}
+
+write_conv_func
+write_get_conv_func(struct write_info *wi)
+{
+
+ switch (wi->format) {
+ case AUDIO_FORMAT_DEFAULT:
+ case AUDIO_FORMAT_SUN:
+ return sun_write_get_conv_func(wi);
+ case AUDIO_FORMAT_WAV:
+ return wav_write_get_conv_func(wi);
+ case AUDIO_FORMAT_NONE:
+ return NULL;
+ default:
+ errx(1, "unknown audio format");
+ }
+}
diff -r 70e85494823f -r a4d039906bd8 usr.bin/audio/common/libaudio.h
--- a/usr.bin/audio/common/libaudio.h Fri Aug 30 16:43:33 2013 +0000
+++ b/usr.bin/audio/common/libaudio.h Fri Aug 30 20:57:26 2013 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: libaudio.h,v 1.17 2011/08/28 01:17:47 joerg Exp $ */
+/* $NetBSD: libaudio.h,v 1.18 2013/08/30 20:57:26 mrg Exp $ */
/*
* Copyright (c) 1999, 2009 Matthew R. Green
@@ -184,6 +184,38 @@
void decode_encoding (const char *, int *);
/*
+ * Write a sun/wav header, shared between record and merge.
+ *
+ * Note that write_header() may change the values of format,
+ * encoding.
+ */
+
+struct write_info {
+ int outfd;
+ char *header_info;
+ int format;
+ int encoding;
+ int precision;
+ int qflag;
+ ssize_t total_size;
+ int sample_rate;
+ int channels;
+};
+
+typedef void (*write_conv_func) (u_char *, int);
+
+void write_header (struct write_info *);
+write_conv_func write_get_conv_func(struct write_info *);
+
+/* backends for the above */
+int sun_prepare_header(struct write_info *wi, void **hdrp, size_t *lenp, int *leftp);
+int wav_prepare_header(struct write_info *wi, void **hdrp, size_t *lenp, int *leftp);
+write_conv_func sun_write_get_conv_func(struct write_info *wi);
+write_conv_func wav_write_get_conv_func(struct write_info *wi);
+
+extern char audio_default_info[8];
+
+/*
* get/put 16/32 bits of big/little endian data
*/
#include <sys/types.h>
diff -r 70e85494823f -r a4d039906bd8 usr.bin/audio/common/sun.c
--- a/usr.bin/audio/common/sun.c Fri Aug 30 16:43:33 2013 +0000
+++ b/usr.bin/audio/common/sun.c Fri Aug 30 20:57:26 2013 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sun.c,v 1.7 2011/08/28 01:17:47 joerg Exp $ */
+/* $NetBSD: sun.c,v 1.8 2013/08/30 20:57:26 mrg Exp $ */
/*
* Copyright (c) 2002 Matthew R. Green
@@ -32,7 +32,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: sun.c,v 1.7 2011/08/28 01:17:47 joerg Exp $");
+__RCSID("$NetBSD: sun.c,v 1.8 2013/08/30 20:57:26 mrg Exp $");
#endif
@@ -46,8 +46,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include "libaudio.h"
+#include "auconv.h"
/*
* SunOS/NeXT .au format helpers
@@ -106,3 +108,127 @@
}
return (1);
}
+
+int
+sun_prepare_header(struct write_info *wi, void **hdrp, size_t *lenp, int *leftp)
+{
+ static int warned = 0;
+ static sun_audioheader auh;
+ int sunenc, oencoding = wi->encoding;
+
+ /* only perform conversions if we don't specify the encoding */
+ switch (wi->encoding) {
+
+ case AUDIO_ENCODING_ULINEAR_LE:
+#if BYTE_ORDER == LITTLE_ENDIAN
+ case AUDIO_ENCODING_ULINEAR:
+#endif
+ if (wi->precision == 16 || wi->precision == 32)
+ wi->encoding = AUDIO_ENCODING_SLINEAR_BE;
+ break;
+
+ case AUDIO_ENCODING_ULINEAR_BE:
+#if BYTE_ORDER == BIG_ENDIAN
+ case AUDIO_ENCODING_ULINEAR:
+#endif
+ if (wi->precision == 16 || wi->precision == 32)
+ wi->encoding = AUDIO_ENCODING_SLINEAR_BE;
+ break;
+
+ case AUDIO_ENCODING_SLINEAR_LE:
+#if BYTE_ORDER == LITTLE_ENDIAN
+ case AUDIO_ENCODING_SLINEAR:
+#endif
+ if (wi->precision == 16 || wi->precision == 32)
+ wi->encoding = AUDIO_ENCODING_SLINEAR_BE;
+ break;
+
+#if BYTE_ORDER == BIG_ENDIAN
+ case AUDIO_ENCODING_SLINEAR:
+ wi->encoding = AUDIO_ENCODING_SLINEAR_BE;
+ break;
+#endif
+ }
+
+ /* if we can't express this as a Sun header, don't write any */
+ if (audio_encoding_to_sun(wi->encoding, wi->precision, &sunenc) != 0) {
+ if (!wi->qflag && !warned) {
+ const char *s = audio_enc_from_val(oencoding);
+
+ if (s == NULL)
+ s = "(unknown)";
+ warnx("failed to convert to sun encoding from %s "
+ "(precision %d);\nSun audio header not written",
+ s, wi->precision);
+ }
+ wi->format = AUDIO_FORMAT_NONE;
+ warned = 1;
+ return -1;
+ }
+
+ auh.magic = htonl(AUDIO_FILE_MAGIC);
+ if (wi->outfd == STDOUT_FILENO)
+ auh.data_size = htonl(AUDIO_UNKNOWN_SIZE);
+ else if (wi->total_size != -1)
+ auh.data_size = htonl(wi->total_size);
+ else
+ auh.data_size = 0;
+ auh.encoding = htonl(sunenc);
+ auh.sample_rate = htonl(wi->sample_rate);
+ auh.channels = htonl(wi->channels);
+ if (wi->header_info) {
+ int len, infolen;
+
+ infolen = ((len = strlen(wi->header_info)) + 7) & 0xfffffff8;
+ *leftp = infolen - len;
+ auh.hdr_size = htonl(sizeof(auh) + infolen);
+ } else {
+ *leftp = sizeof(audio_default_info);
+ auh.hdr_size = htonl(sizeof(auh) + *leftp);
+ }
+ *(sun_audioheader **)hdrp = &auh;
+ *lenp = sizeof auh;
+ return 0;
+}
+
+write_conv_func
+sun_write_get_conv_func(struct write_info *wi)
+{
+ write_conv_func conv_func = NULL;
+
+ /* only perform conversions if we don't specify the encoding */
+ switch (wi->encoding) {
+
+ case AUDIO_ENCODING_ULINEAR_LE:
+#if BYTE_ORDER == LITTLE_ENDIAN
+ case AUDIO_ENCODING_ULINEAR:
+#endif
+ if (wi->precision == 16)
+ conv_func = change_sign16_swap_bytes_le;
+ else if (wi->precision == 32)
+ conv_func = change_sign32_swap_bytes_le;
+ break;
+
+ case AUDIO_ENCODING_ULINEAR_BE:
+#if BYTE_ORDER == BIG_ENDIAN
Home |
Main Index |
Thread Index |
Old Index