Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src The audio sub-system now supports the following features as
details: https://anonhg.NetBSD.org/src/rev/461ed45fda22
branches: trunk
changeset: 349350:461ed45fda22
user: nat <nat%NetBSD.org@localhost>
date: Thu Dec 08 10:28:44 2016 +0000
description:
The audio sub-system now supports the following features as
posted to tech-kern:
* Simultaneous playback and mixing of multiple streams
* Playback streams can be of different encoding, frequency, precision
and number of channels
* Simultaneous recording to different formats
* One audio device per process
* Sysctls to set the common format frequency, precision and channels
* Independent mixer controls for recording/playback per stream
* Utilizes little cpu time for multiple streams / good performance
* Compatible with existing programs that use OSS/NetBSD audio
* Changes to audioctl(1) to allow specifying process id for corresponding
audio device
diffstat:
sys/dev/audio.c | 3094 +++++++++++++++++++++++++++++----------
sys/dev/audiovar.h | 130 +-
sys/dev/files.audio | 4 +-
sys/miscfs/specfs/spec_vnops.c | 6 +-
sys/sys/audioio.h | 8 +-
sys/sys/conf.h | 3 +-
usr.bin/audio/ctl/audioctl.1 | 17 +-
usr.bin/audio/ctl/ctl.c | 24 +-
8 files changed, 2402 insertions(+), 884 deletions(-)
diffs (truncated from 5100 to 300 lines):
diff -r 831dbadf7ae2 -r 461ed45fda22 sys/dev/audio.c
--- a/sys/dev/audio.c Thu Dec 08 06:28:21 2016 +0000
+++ b/sys/dev/audio.c Thu Dec 08 10:28:44 2016 +0000
@@ -1,6 +1,9 @@
-/* $NetBSD: audio.c,v 1.268 2016/07/14 10:19:05 msaitoh Exp $ */
+/* $NetBSD: audio.c,v 1.269 2016/12/08 10:28:44 nat Exp $ */
/*-
+ * Copyright (c) 2016 Nathanial Sloss <nathanialsloss%yahoo.com.au@localhost>
+ * All rights reserved.
+ *
* Copyright (c) 2008 The NetBSD Foundation, Inc.
* All rights reserved.
*
@@ -109,16 +112,6 @@
* sc_intr_lock. This is to ensure that groups of hardware operations are
* made atomically. SLEEPS CANNOT OCCUR WITH THIS LOCK HELD.
*
- * - sc_dvlock, private to this module. This is a custom reader/writer lock
- * built on sc_lock and a condition variable. Some operations release
- * sc_lock in order to allocate memory, to wait for in-flight I/O to
- * complete, to copy to/from user context, etc. sc_dvlock serializes
- * changes to filters and audio device settings while a read/write to the
- * hardware is in progress. A write lock is taken only under exceptional
- * circumstances, for example when opening /dev/audio or changing audio
- * parameters. Long term sleeps and copy to/from user space may be done
- * with this lock held.
- *
* List of hardware interface methods, and which locks are held when each
* is called by this module:
*
@@ -155,11 +148,12 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.268 2016/07/14 10:19:05 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.269 2016/12/08 10:28:44 nat Exp $");
#include "audio.h"
#if NAUDIO > 0
+#include <sys/types.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/fcntl.h>
@@ -170,6 +164,7 @@
#include <sys/malloc.h>
#include <sys/proc.h>
#include <sys/systm.h>
+#include <sys/sysctl.h>
#include <sys/syslog.h>
#include <sys/kernel.h>
#include <sys/signalvar.h>
@@ -177,10 +172,16 @@
#include <sys/audioio.h>
#include <sys/device.h>
#include <sys/intr.h>
+#include <sys/kthread.h>
#include <sys/cpu.h>
#include <dev/audio_if.h>
#include <dev/audiovar.h>
+#include <dev/auconv.h>
+#include <dev/auvolconv.h>
+#ifdef VAUDIOSPEAKER
+#include <dev/spkrvar.h>
+#endif
#include <machine/endian.h>
@@ -198,6 +199,18 @@
#define SPECIFIED(x) (x != ~0)
#define SPECIFIED_CH(x) (x != (u_char)~0)
+#define VAUDIO_NFORMATS 1
+static const struct audio_format vaudio_formats[VAUDIO_NFORMATS] = {
+ { NULL, AUMODE_PLAY | AUMODE_RECORD,
+#if BYTE_ORDER == LITTLE_ENDIAN
+ AUDIO_ENCODING_SLINEAR_LE,
+#else
+ AUDIO_ENCODING_SLINEAR_BE,
+#endif
+ 16, 16, 2, AUFMT_STEREO, 1, { 44100 }
+ }
+};
+
/* #define AUDIO_PM_IDLE */
#ifdef AUDIO_PM_IDLE
int audio_idle_timeout = 30;
@@ -205,14 +218,15 @@
int audio_blk_ms = AUDIO_BLK_MS;
-int audiosetinfo(struct audio_softc *, struct audio_info *);
-int audiogetinfo(struct audio_softc *, struct audio_info *, int);
+int audiosetinfo(struct audio_softc *, struct audio_info *, bool, int);
+int audiogetinfo(struct audio_softc *, struct audio_info *, int, int);
int audio_open(dev_t, struct audio_softc *, int, int, struct lwp *);
-int audio_close(struct audio_softc *, int, int, struct lwp *);
+int audio_close(struct audio_softc *, int, int, struct lwp *, int);
int audio_read(struct audio_softc *, struct uio *, int);
int audio_write(struct audio_softc *, struct uio *, int);
-int audio_ioctl(struct audio_softc *, u_long, void *, int, struct lwp *);
+int audio_ioctl(dev_t, struct audio_softc *, u_long, void *, int,
+ struct lwp *);
int audio_poll(struct audio_softc *, int, struct lwp *);
int audio_kqfilter(struct audio_softc *, struct knote *);
paddr_t audio_mmap(struct audio_softc *, off_t, int);
@@ -223,35 +237,57 @@
static void mixer_remove(struct audio_softc *);
static void mixer_signal(struct audio_softc *);
-void audio_init_record(struct audio_softc *);
-void audio_init_play(struct audio_softc *);
-int audiostartr(struct audio_softc *);
-int audiostartp(struct audio_softc *);
+void audio_init_record(struct audio_softc *, int);
+void audio_init_play(struct audio_softc *, int);
+int audiostartr(struct audio_softc *, int);
+int audiostartp(struct audio_softc *, int);
void audio_rint(void *);
void audio_pint(void *);
+void audio_mix(void *);
+void audio_upmix(void *);
+void audio_play_thread(void *);
+void audio_rec_thread(void *);
+void recswvol_func(struct audio_softc *, struct audio_ringbuffer *, int,
+ size_t);
+void recswvol_func8(struct audio_softc *, struct audio_ringbuffer *, int,
+ size_t);
+void recswvol_func16(struct audio_softc *, struct audio_ringbuffer *, int,
+ size_t);
+void recswvol_func32(struct audio_softc *, struct audio_ringbuffer *, int,
+ size_t);
+void saturate_func(struct audio_softc *);
+void saturate_func8(struct audio_softc *);
+void saturate_func16(struct audio_softc *);
+void saturate_func32(struct audio_softc *);
+void mix_func(struct audio_softc *, struct audio_ringbuffer *, int);
+void mix_func8(struct audio_softc *, struct audio_ringbuffer *, int);
+void mix_func16(struct audio_softc *, struct audio_ringbuffer *, int);
+void mix_func32(struct audio_softc *, struct audio_ringbuffer *, int);
+void mix_write(void *);
+void mix_read(void *);
int audio_check_params(struct audio_params *);
-void audio_calc_blksize(struct audio_softc *, int);
+void audio_calc_blksize(struct audio_softc *, int, int);
void audio_fill_silence(struct audio_params *, uint8_t *, int);
int audio_silence_copyout(struct audio_softc *, int, struct uio *);
void audio_init_ringbuffer(struct audio_softc *,
struct audio_ringbuffer *, int);
-int audio_initbufs(struct audio_softc *);
-void audio_calcwater(struct audio_softc *);
-int audio_drain(struct audio_softc *);
-void audio_clear(struct audio_softc *);
-void audio_clear_intr_unlocked(struct audio_softc *sc);
-static inline void audio_pint_silence
- (struct audio_softc *, struct audio_ringbuffer *, uint8_t *, int);
-
-int audio_alloc_ring
- (struct audio_softc *, struct audio_ringbuffer *, int, size_t);
+int audio_initbufs(struct audio_softc *, int);
+void audio_calcwater(struct audio_softc *, int);
+int audio_drain(struct audio_softc *, int);
+void audio_clear(struct audio_softc *, int);
+void audio_clear_intr_unlocked(struct audio_softc *sc, int);
+static inline void
+ audio_pint_silence(struct audio_softc *, struct audio_ringbuffer *,
+ uint8_t *, int, int);
+int audio_alloc_ring(struct audio_softc *, struct audio_ringbuffer *, int,
+ size_t);
void audio_free_ring(struct audio_softc *, struct audio_ringbuffer *);
static int audio_setup_pfilters(struct audio_softc *, const audio_params_t *,
- stream_filter_list_t *);
+ stream_filter_list_t *, int);
static int audio_setup_rfilters(struct audio_softc *, const audio_params_t *,
- stream_filter_list_t *);
+ stream_filter_list_t *, int);
static void audio_stream_dtor(audio_stream_t *);
static int audio_stream_ctor(audio_stream_t *, const audio_params_t *, int);
static void stream_filter_list_append
@@ -263,7 +299,10 @@
static void stream_filter_list_set
(stream_filter_list_t *, int, stream_filter_factory_t,
const audio_params_t *);
-int audio_set_defaults(struct audio_softc *, u_int);
+int audio_set_defaults(struct audio_softc *, u_int, int);
+static int audio_sysctl_frequency(SYSCTLFN_PROTO);
+static int audio_sysctl_precision(SYSCTLFN_PROTO);
+static int audio_sysctl_channels(SYSCTLFN_PROTO);
int audioprobe(device_t, cfdata_t, void *);
void audioattach(device_t, device_t, void *);
@@ -295,6 +334,9 @@
static void audio_exit(struct audio_softc *);
static int audio_waitio(struct audio_softc *, kcondvar_t *);
+#define AUDIO_OUTPUT_CLASS 0
+#define AUDIO_INPUT_CLASS 1
+
struct portname {
const char *name;
int mask;
@@ -320,6 +362,19 @@
int au_set_port(struct audio_softc *, struct au_mixer_ports *,
u_int);
int au_get_port(struct audio_softc *, struct au_mixer_ports *);
+static int
+ audio_get_port(struct audio_softc *, mixer_ctrl_t *);
+static int
+ audio_set_port(struct audio_softc *, mixer_ctrl_t *);
+static int
+ audio_query_devinfo(struct audio_softc *, mixer_devinfo_t *);
+static int audio_set_params
+ (struct audio_softc *, int, int, audio_params_t *, audio_params_t *,
+ stream_filter_list_t *, stream_filter_list_t *, int);
+static int
+audio_query_encoding(struct audio_softc *, struct audio_encoding *);
+static int audio_set_vchan_defaults
+ (struct audio_softc *, u_int, const struct audio_format *, int);
int au_get_lr_value(struct audio_softc *, mixer_ctrl_t *, int *, int *);
int au_set_lr_value(struct audio_softc *, mixer_ctrl_t *, int, int);
int au_portof(struct audio_softc *, char *, int);
@@ -358,7 +413,20 @@
.d_mmap = audiommap,
.d_kqfilter = audiokqfilter,
.d_discard = nodiscard,
- .d_flag = D_OTHER | D_MPSAFE
+ .d_flag = D_MCLOSE | D_MPSAFE
+};
+
+/* The default vchan mode: 44.1 kHz stereo signed linear */
+struct audio_params vchan_default = {
+ .sample_rate = 44100,
+#if BYTE_ORDER == LITTLE_ENDIAN
+ .encoding = AUDIO_ENCODING_SLINEAR_LE,
+#else
+ .encoding = AUDIO_ENCODING_SLINEAR_BE,
+#endif
+ .precision = 16,
+ .validbits = 16,
+ .channels = 2,
};
/* The default audio mode: 8 kHz mono mu-law */
@@ -392,7 +460,9 @@
{
struct audio_softc *sc;
struct audio_attach_args *sa;
+ struct virtual_channel *vc;
const struct audio_hw_if *hwp;
+ const struct sysctlnode *node;
void *hdlp;
int error;
mixer_devinfo_t mi;
@@ -405,10 +475,39 @@
sa = aux;
hwp = sa->hwif;
hdlp = sa->hdl;
+ sc->sc_opens = 0;
+ sc->sc_recopens = 0;
+ sc->sc_aivalid = false;
+
+ sc->sc_trigger_started = false;
+ sc->sc_rec_started = false;
+ sc->sc_vchan[0] = kmem_zalloc(sizeof(struct virtual_channel), KM_SLEEP);
+ vc = sc->sc_vchan[0];
+ memset(sc->sc_audiopid, -1, sizeof(sc->sc_audiopid));
+ memset(sc->sc_despid, -1, sizeof(sc->sc_despid));
+ vc->sc_open = 0;
+ vc->sc_mode = 0;
+ vc->sc_npfilters = 0;
+ memset(vc->sc_pfilters, 0,
+ sizeof(vc->sc_pfilters));
+ vc->sc_lastinfovalid = false;
+ vc->sc_swvol = 255;
+ vc->sc_recswvol = 255;
+ sc->sc_iffreq = 44100;
+ sc->sc_precision = 16;
+ sc->sc_channels = 2;
+
+ if (auconv_create_encodings(vaudio_formats, VAUDIO_NFORMATS,
+ &sc->sc_encodings) != 0) {
+ aprint_error_dev(self, "couldn't create encodings\n");
+ return;
+ }
cv_init(&sc->sc_rchan, "audiord");
cv_init(&sc->sc_wchan, "audiowr");
cv_init(&sc->sc_lchan, "audiolk");
+ cv_init(&sc->sc_condvar,"play");
+ cv_init(&sc->sc_rcondvar,"record");
if (hwp == 0 || hwp->get_locks == 0) {
aprint_error(": missing method\n");
@@ -438,7 +537,6 @@
sc->hw_if = hwp;
Home |
Main Index |
Thread Index |
Old Index