]> git.proxmox.com Git - mirror_qemu.git/blame - audio/wavcapture.c
spapr: Move RMA memory region registration code
[mirror_qemu.git] / audio / wavcapture.c
CommitLineData
87ecb68b 1#include "hw/hw.h"
83c9089e 2#include "monitor/monitor.h"
87ecb68b 3#include "audio.h"
8ead62cf
FB
4
5typedef struct {
b04df2a4 6 FILE *f;
8ead62cf 7 int bytes;
ec36b695
FB
8 char *path;
9 int freq;
10 int bits;
11 int nchannels;
12 CaptureVoiceOut *cap;
8ead62cf
FB
13} WAVState;
14
15/* VICE code: Store number as little endian. */
16static void le_store (uint8_t *buf, uint32_t val, int len)
17{
18 int i;
19 for (i = 0; i < len; i++) {
20 buf[i] = (uint8_t) (val & 0xff);
21 val >>= 8;
22 }
23}
24
ec36b695 25static void wav_notify (void *opaque, audcnotification_e cmd)
8ead62cf 26{
ec36b695
FB
27 (void) opaque;
28 (void) cmd;
29}
8ead62cf 30
ec36b695
FB
31static void wav_destroy (void *opaque)
32{
33 WAVState *wav = opaque;
34 uint8_t rlen[4];
35 uint8_t dlen[4];
36 uint32_t datalen = wav->bytes;
37 uint32_t rifflen = datalen + 36;
b04df2a4 38 Monitor *mon = cur_mon;
8ead62cf 39
e84a4fed
FB
40 if (wav->f) {
41 le_store (rlen, rifflen, 4);
42 le_store (dlen, datalen, 4);
f941aa25 43
b04df2a4
JQ
44 if (fseek (wav->f, 4, SEEK_SET)) {
45 monitor_printf (mon, "wav_destroy: rlen fseek failed\nReason: %s\n",
46 strerror (errno));
47 goto doclose;
48 }
49 if (fwrite (rlen, 4, 1, wav->f) != 1) {
50 monitor_printf (mon, "wav_destroy: rlen fwrite failed\nReason %s\n",
51 strerror (errno));
52 goto doclose;
53 }
54 if (fseek (wav->f, 32, SEEK_CUR)) {
55 monitor_printf (mon, "wav_destroy: dlen fseek failed\nReason %s\n",
56 strerror (errno));
57 goto doclose;
58 }
59 if (fwrite (dlen, 1, 4, wav->f) != 4) {
60 monitor_printf (mon, "wav_destroy: dlen fwrite failed\nReason %s\n",
61 strerror (errno));
62 goto doclose;
63 }
64 doclose:
65 if (fclose (wav->f)) {
69e99504 66 error_report("wav_destroy: fclose failed: %s", strerror(errno));
b04df2a4 67 }
8ead62cf 68 }
f941aa25 69
7267c094 70 g_free (wav->path);
8ead62cf
FB
71}
72
ec36b695 73static void wav_capture (void *opaque, void *buf, int size)
8ead62cf
FB
74{
75 WAVState *wav = opaque;
76
b04df2a4
JQ
77 if (fwrite (buf, size, 1, wav->f) != 1) {
78 monitor_printf (cur_mon, "wav_capture: fwrite error\nReason: %s",
79 strerror (errno));
80 }
8ead62cf
FB
81 wav->bytes += size;
82}
83
ec36b695
FB
84static void wav_capture_destroy (void *opaque)
85{
86 WAVState *wav = opaque;
87
88 AUD_del_capture (wav->cap, wav);
89}
90
91static void wav_capture_info (void *opaque)
92{
93 WAVState *wav = opaque;
94 char *path = wav->path;
95
b04df2a4
JQ
96 monitor_printf (cur_mon, "Capturing audio(%d,%d,%d) to %s: %d bytes\n",
97 wav->freq, wav->bits, wav->nchannels,
98 path ? path : "<not available>", wav->bytes);
ec36b695
FB
99}
100
101static struct capture_ops wav_capture_ops = {
102 .destroy = wav_capture_destroy,
103 .info = wav_capture_info
104};
105
106int wav_start_capture (CaptureState *s, const char *path, int freq,
107 int bits, int nchannels)
8ead62cf 108{
376253ec 109 Monitor *mon = cur_mon;
8ead62cf
FB
110 WAVState *wav;
111 uint8_t hdr[] = {
112 0x52, 0x49, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x57, 0x41, 0x56,
113 0x45, 0x66, 0x6d, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00,
114 0x02, 0x00, 0x44, 0xac, 0x00, 0x00, 0x10, 0xb1, 0x02, 0x00, 0x04,
115 0x00, 0x10, 0x00, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00
116 };
1ea879e5 117 struct audsettings as;
8ead62cf 118 struct audio_capture_ops ops;
ec36b695
FB
119 int stereo, bits16, shift;
120 CaptureVoiceOut *cap;
121
122 if (bits != 8 && bits != 16) {
b04df2a4 123 monitor_printf (mon, "incorrect bit count %d, must be 8 or 16\n", bits);
ec36b695
FB
124 return -1;
125 }
126
127 if (nchannels != 1 && nchannels != 2) {
b04df2a4
JQ
128 monitor_printf (mon, "incorrect channel count %d, must be 1 or 2\n",
129 nchannels);
ec36b695
FB
130 return -1;
131 }
8ead62cf 132
ec36b695
FB
133 stereo = nchannels == 2;
134 bits16 = bits == 16;
8ead62cf
FB
135
136 as.freq = freq;
137 as.nchannels = 1 << stereo;
138 as.fmt = bits16 ? AUD_FMT_S16 : AUD_FMT_U8;
d929eba5 139 as.endianness = 0;
8ead62cf 140
ec36b695
FB
141 ops.notify = wav_notify;
142 ops.capture = wav_capture;
143 ops.destroy = wav_destroy;
8ead62cf 144
7267c094 145 wav = g_malloc0 (sizeof (*wav));
8ead62cf
FB
146
147 shift = bits16 + stereo;
148 hdr[34] = bits16 ? 0x10 : 0x08;
149
150 le_store (hdr + 22, as.nchannels, 2);
151 le_store (hdr + 24, freq, 4);
152 le_store (hdr + 28, freq << shift, 4);
153 le_store (hdr + 32, 1 << shift, 2);
154
b04df2a4 155 wav->f = fopen (path, "wb");
8ead62cf 156 if (!wav->f) {
b04df2a4
JQ
157 monitor_printf (mon, "Failed to open wave file `%s'\nReason: %s\n",
158 path, strerror (errno));
7267c094 159 g_free (wav);
ec36b695 160 return -1;
8ead62cf
FB
161 }
162
7267c094 163 wav->path = g_strdup (path);
ec36b695
FB
164 wav->bits = bits;
165 wav->nchannels = nchannels;
166 wav->freq = freq;
167
b04df2a4
JQ
168 if (fwrite (hdr, sizeof (hdr), 1, wav->f) != 1) {
169 monitor_printf (mon, "Failed to write header\nReason: %s\n",
170 strerror (errno));
171 goto error_free;
172 }
ec36b695 173
1a7dafce 174 cap = AUD_add_capture (&as, &ops, wav);
ec36b695 175 if (!cap) {
b04df2a4
JQ
176 monitor_printf (mon, "Failed to add audio capture\n");
177 goto error_free;
ec36b695
FB
178 }
179
180 wav->cap = cap;
181 s->opaque = wav;
182 s->ops = wav_capture_ops;
183 return 0;
b04df2a4
JQ
184
185error_free:
186 g_free (wav->path);
187 if (fclose (wav->f)) {
188 monitor_printf (mon, "Failed to close wave file\nReason: %s\n",
189 strerror (errno));
190 }
191 g_free (wav);
192 return -1;
8ead62cf 193}