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