root / audio / wavcapture.c @ d929eba5
History | View | Annotate | Download (2.4 kB)
1 |
#include "vl.h" |
---|---|
2 |
|
3 |
typedef struct { |
4 |
QEMUFile *f; |
5 |
int bytes;
|
6 |
} WAVState; |
7 |
|
8 |
/* VICE code: Store number as little endian. */
|
9 |
static void le_store (uint8_t *buf, uint32_t val, int len) |
10 |
{ |
11 |
int i;
|
12 |
for (i = 0; i < len; i++) { |
13 |
buf[i] = (uint8_t) (val & 0xff);
|
14 |
val >>= 8;
|
15 |
} |
16 |
} |
17 |
|
18 |
static void wav_state_cb (void *opaque, int enabled) |
19 |
{ |
20 |
WAVState *wav = opaque; |
21 |
|
22 |
if (!enabled) {
|
23 |
uint8_t rlen[4];
|
24 |
uint8_t dlen[4];
|
25 |
uint32_t datalen = wav->bytes; |
26 |
uint32_t rifflen = datalen + 36;
|
27 |
|
28 |
if (!wav->f) {
|
29 |
return;
|
30 |
} |
31 |
|
32 |
le_store (rlen, rifflen, 4);
|
33 |
le_store (dlen, datalen, 4);
|
34 |
|
35 |
qemu_fseek (wav->f, 4, SEEK_SET);
|
36 |
qemu_put_buffer (wav->f, rlen, 4);
|
37 |
|
38 |
qemu_fseek (wav->f, 32, SEEK_CUR);
|
39 |
qemu_put_buffer (wav->f, dlen, 4);
|
40 |
} |
41 |
else {
|
42 |
qemu_fseek (wav->f, 0, SEEK_END);
|
43 |
} |
44 |
} |
45 |
|
46 |
static void wav_capture_cb (void *opaque, void *buf, int size) |
47 |
{ |
48 |
WAVState *wav = opaque; |
49 |
|
50 |
qemu_put_buffer (wav->f, buf, size); |
51 |
wav->bytes += size; |
52 |
} |
53 |
|
54 |
void wav_capture (const char *path, int freq, int bits16, int stereo) |
55 |
{ |
56 |
WAVState *wav; |
57 |
uint8_t hdr[] = { |
58 |
0x52, 0x49, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x57, 0x41, 0x56, |
59 |
0x45, 0x66, 0x6d, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, |
60 |
0x02, 0x00, 0x44, 0xac, 0x00, 0x00, 0x10, 0xb1, 0x02, 0x00, 0x04, |
61 |
0x00, 0x10, 0x00, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00 |
62 |
}; |
63 |
audsettings_t as; |
64 |
struct audio_capture_ops ops;
|
65 |
int shift;
|
66 |
|
67 |
stereo = !!stereo; |
68 |
bits16 = !!bits16; |
69 |
|
70 |
as.freq = freq; |
71 |
as.nchannels = 1 << stereo;
|
72 |
as.fmt = bits16 ? AUD_FMT_S16 : AUD_FMT_U8; |
73 |
as.endianness = 0;
|
74 |
|
75 |
ops.state = wav_state_cb; |
76 |
ops.capture = wav_capture_cb; |
77 |
|
78 |
wav = qemu_mallocz (sizeof (*wav));
|
79 |
if (!wav) {
|
80 |
AUD_log ("wav", "Could not allocate memory (%zu bytes)", sizeof (*wav)); |
81 |
return;
|
82 |
} |
83 |
|
84 |
shift = bits16 + stereo; |
85 |
hdr[34] = bits16 ? 0x10 : 0x08; |
86 |
|
87 |
le_store (hdr + 22, as.nchannels, 2); |
88 |
le_store (hdr + 24, freq, 4); |
89 |
le_store (hdr + 28, freq << shift, 4); |
90 |
le_store (hdr + 32, 1 << shift, 2); |
91 |
|
92 |
wav->f = fopen (path, "wb");
|
93 |
if (!wav->f) {
|
94 |
AUD_log ("wav", "Failed to open wave file `%s'\nReason: %s\n", |
95 |
path, strerror (errno)); |
96 |
qemu_free (wav); |
97 |
return;
|
98 |
} |
99 |
|
100 |
qemu_put_buffer (wav->f, hdr, sizeof (hdr));
|
101 |
AUD_add_capture (NULL, &as, &ops, wav);
|
102 |
} |