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