Sun Jun 11 13:02:44 2017 UTC ()
Initialize and set all required parameters for the audiobell.


(nat)
diff -r1.20 -r1.21 src/sys/dev/audiobell.c

cvs diff -r1.20 -r1.21 src/sys/dev/Attic/audiobell.c (switch to unified diff)

--- src/sys/dev/Attic/audiobell.c 2017/06/04 05:37:56 1.20
+++ src/sys/dev/Attic/audiobell.c 2017/06/11 13:02:44 1.21
@@ -1,173 +1,176 @@ @@ -1,173 +1,176 @@
1/* $NetBSD: audiobell.c,v 1.20 2017/06/04 05:37:56 nat Exp $ */ 1/* $NetBSD: audiobell.c,v 1.21 2017/06/11 13:02:44 nat Exp $ */
2 2
3 3
4/* 4/*
5 * Copyright (c) 1999 Richard Earnshaw 5 * Copyright (c) 1999 Richard Earnshaw
6 * Copyright (c) 2004 Ben Harris 6 * Copyright (c) 2004 Ben Harris
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
10 * are met: 10 * are met:
11 * 1. Redistributions of source code must retain the above copyright 11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer. 12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright 13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the 14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution. 15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software 16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement: 17 * must display the following acknowledgement:
18 * This product includes software developed by the RiscBSD team. 18 * This product includes software developed by the RiscBSD team.
19 * 4. The name of the author may not be used to endorse or promote products 19 * 4. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission. 20 * derived from this software without specific prior written permission.
21 * 21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */ 32 */
33 33
34#include <sys/types.h> 34#include <sys/types.h>
35__KERNEL_RCSID(0, "$NetBSD: audiobell.c,v 1.20 2017/06/04 05:37:56 nat Exp $"); 35__KERNEL_RCSID(0, "$NetBSD: audiobell.c,v 1.21 2017/06/11 13:02:44 nat Exp $");
36 36
37#include <sys/audioio.h> 37#include <sys/audioio.h>
38#include <sys/conf.h> 38#include <sys/conf.h>
39#include <sys/device.h> 39#include <sys/device.h>
40#include <sys/fcntl.h> 40#include <sys/fcntl.h>
41#include <sys/file.h> 41#include <sys/file.h>
42#include <sys/filedesc.h> 42#include <sys/filedesc.h>
43#include <sys/ioctl.h> 43#include <sys/ioctl.h>
44#include <sys/malloc.h> 44#include <sys/malloc.h>
45#include <sys/null.h> 45#include <sys/null.h>
46#include <sys/systm.h> 46#include <sys/systm.h>
47#include <sys/uio.h> 47#include <sys/uio.h>
48#include <sys/unistd.h> 48#include <sys/unistd.h>
49 49
50#include <dev/audio_if.h> 50#include <dev/audio_if.h>
51#include <dev/audiovar.h> 51#include <dev/audiovar.h>
52#include <dev/audiobellvar.h> 52#include <dev/audiobellvar.h>
53#include <dev/audiobelldata.h> 53#include <dev/audiobelldata.h>
54 54
55/* 44.1 kHz should reduce hum at higher pitches. */ 55/* 44.1 kHz should reduce hum at higher pitches. */
56#define BELL_SAMPLE_RATE 44100 56#define BELL_SAMPLE_RATE 44100
57#define BELL_SHIFT 19 57#define BELL_SHIFT 19
58 58
59static inline void 59static inline void
60audiobell_expandwave(int16_t *buf) 60audiobell_expandwave(int16_t *buf)
61{ 61{
62 u_int i; 62 u_int i;
63 63
64 for (i = 0; i < __arraycount(sinewave); i++) 64 for (i = 0; i < __arraycount(sinewave); i++)
65 buf[i] = sinewave[i]; 65 buf[i] = sinewave[i];
66 for (i = __arraycount(sinewave); i < __arraycount(sinewave) * 2; i++) 66 for (i = __arraycount(sinewave); i < __arraycount(sinewave) * 2; i++)
67 buf[i] = buf[__arraycount(sinewave) * 2 - i - 1]; 67 buf[i] = buf[__arraycount(sinewave) * 2 - i - 1];
68 for (i = __arraycount(sinewave) * 2; i < __arraycount(sinewave) * 4; i++) 68 for (i = __arraycount(sinewave) * 2; i < __arraycount(sinewave) * 4; i++)
69 buf[i] = -buf[__arraycount(sinewave) * 4 - i - 1]; 69 buf[i] = -buf[__arraycount(sinewave) * 4 - i - 1];
70} 70}
71 71
72/* 72/*
73 * The algorithm here is based on that described in the RISC OS Programmer's 73 * The algorithm here is based on that described in the RISC OS Programmer's
74 * Reference Manual (pp1624--1628). 74 * Reference Manual (pp1624--1628).
75 */ 75 */
76static inline int 76static inline int
77audiobell_synthesize(int16_t *buf, u_int pitch, u_int period, u_int volume, 77audiobell_synthesize(int16_t *buf, u_int pitch, u_int period, u_int volume,
78 uint32_t *phase) 78 uint32_t *phase)
79{ 79{
80 int16_t *wave; 80 int16_t *wave;
81 81
82 wave = malloc(sizeof(sinewave) * 4, M_TEMP, M_WAITOK); 82 wave = malloc(sizeof(sinewave) * 4, M_TEMP, M_WAITOK);
83 if (wave == NULL) return -1; 83 if (wave == NULL) return -1;
84 audiobell_expandwave(wave); 84 audiobell_expandwave(wave);
85 pitch = pitch * ((sizeof(sinewave) * 4) << BELL_SHIFT) / 85 pitch = pitch * ((sizeof(sinewave) * 4) << BELL_SHIFT) /
86 BELL_SAMPLE_RATE / 2; 86 BELL_SAMPLE_RATE / 2;
87 period = period * BELL_SAMPLE_RATE / 1000 / 2; 87 period = period * BELL_SAMPLE_RATE / 1000 / 2;
88 88
89 for (; period != 0; period--) { 89 for (; period != 0; period--) {
90 *buf++ = wave[*phase >> BELL_SHIFT]; 90 *buf++ = wave[*phase >> BELL_SHIFT];
91 *phase += pitch; 91 *phase += pitch;
92 } 92 }
93 93
94 free(wave, M_TEMP); 94 free(wave, M_TEMP);
95 return 0; 95 return 0;
96} 96}
97 97
98void 98void
99audiobell(void *v, u_int pitch, u_int period, u_int volume, int poll) 99audiobell(void *v, u_int pitch, u_int period, u_int volume, int poll)
100{ 100{
101 int16_t *buf; 101 int16_t *buf;
102 uint32_t phase; 102 uint32_t phase;
103 struct audio_info ai; 103 struct audio_info ai;
104 struct uio auio; 104 struct uio auio;
105 struct iovec aiov; 105 struct iovec aiov;
106 struct file *fp; 106 struct file *fp;
107 int size, len; 107 int size, len;
108 108
109 KASSERT(volume <= 100); 109 KASSERT(volume <= 100);
110 110
111 fp = NULL; 111 fp = NULL;
112 dev_t audio = AUDIO_DEVICE | device_unit((device_t)v); 112 dev_t audio = AUDIO_DEVICE | device_unit((device_t)v);
113 113
114 /* The audio system isn't built for polling. */ 114 /* The audio system isn't built for polling. */
115 if (poll) return; 115 if (poll) return;
116 116
117 /* If not configured, we can't beep. */ 117 /* If not configured, we can't beep. */
118 if (audiobellopen(audio, FWRITE, 0, NULL, &fp) != EMOVEFD || fp == NULL) 118 if (audiobellopen(audio, FWRITE, 0, NULL, &fp) != EMOVEFD || fp == NULL)
119 return; 119 return;
120 120
121 if (audiobellioctl(fp, AUDIO_GETINFO, &ai) != 0) { 121 if (audiobellioctl(fp, AUDIO_GETINFO, &ai) != 0) {
122 audiobellclose(fp); 122 audiobellclose(fp);
123 return; 123 return;
124 } 124 }
125 125
 126 AUDIO_INITINFO(&ai);
 127 ai.mode = AUMODE_PLAY;
126 ai.play.sample_rate = BELL_SAMPLE_RATE; 128 ai.play.sample_rate = BELL_SAMPLE_RATE;
127 ai.play.precision = 16; 129 ai.play.precision = 16;
 130 ai.play.channels = 1;
128 ai.play.gain = 255 * volume / 100; 131 ai.play.gain = 255 * volume / 100;
129 132
130#if BYTE_ORDER == LITTLE_ENDIAN 133#if BYTE_ORDER == LITTLE_ENDIAN
131 ai.play.encoding = AUDIO_ENCODING_SLINEAR_LE; 134 ai.play.encoding = AUDIO_ENCODING_SLINEAR_LE;
132#else 135#else
133 ai.play.encoding = AUDIO_ENCODING_SLINEAR_BE; 136 ai.play.encoding = AUDIO_ENCODING_SLINEAR_BE;
134#endif 137#endif
135 138
136 if (audiobellioctl(fp, AUDIO_SETINFO, &ai) != 0) { 139 if (audiobellioctl(fp, AUDIO_SETINFO, &ai) != 0) {
137 audiobellclose(fp); 140 audiobellclose(fp);
138 return; 141 return;
139 } 142 }
140 buf = NULL; 143 buf = NULL;
141 144
142 if (ai.blocksize < BELL_SAMPLE_RATE) 145 if (ai.blocksize < BELL_SAMPLE_RATE)
143 ai.blocksize = BELL_SAMPLE_RATE; 146 ai.blocksize = BELL_SAMPLE_RATE;
144 147
145 len = period * BELL_SAMPLE_RATE / 1000 * 2; 148 len = period * BELL_SAMPLE_RATE / 1000 * 2;
146 size = min(len, ai.blocksize); 149 size = min(len, ai.blocksize);
147 if (size == 0) goto out; 150 if (size == 0) goto out;
148 151
149 buf = malloc(size, M_TEMP, M_WAITOK); 152 buf = malloc(size, M_TEMP, M_WAITOK);
150 if (buf == NULL) goto out; 153 if (buf == NULL) goto out;
151  154
152 phase = 0; 155 phase = 0;
153 while (len > 0) { 156 while (len > 0) {
154 size = min(len, ai.blocksize); 157 size = min(len, ai.blocksize);
155 if (audiobell_synthesize(buf, pitch, size * 158 if (audiobell_synthesize(buf, pitch, size *
156 1000 / BELL_SAMPLE_RATE, volume, &phase) != 0) 159 1000 / BELL_SAMPLE_RATE, volume, &phase) != 0)
157 goto out; 160 goto out;
158 aiov.iov_base = (void *)buf; 161 aiov.iov_base = (void *)buf;
159 aiov.iov_len = size; 162 aiov.iov_len = size;
160 auio.uio_iov = &aiov; 163 auio.uio_iov = &aiov;
161 auio.uio_iovcnt = 1; 164 auio.uio_iovcnt = 1;
162 auio.uio_offset = 0; 165 auio.uio_offset = 0;
163 auio.uio_resid = size; 166 auio.uio_resid = size;
164 auio.uio_rw = UIO_WRITE; 167 auio.uio_rw = UIO_WRITE;
165 UIO_SETUP_SYSSPACE(&auio); 168 UIO_SETUP_SYSSPACE(&auio);
166 169
167 audiobellwrite(fp, NULL, &auio, NULL, 0); 170 audiobellwrite(fp, NULL, &auio, NULL, 0);
168 len -= size; 171 len -= size;
169 } 172 }
170out: 173out:
171 if (buf != NULL) free(buf, M_TEMP); 174 if (buf != NULL) free(buf, M_TEMP);
172 audiobellclose(fp); 175 audiobellclose(fp);
173} 176}