]>
Commit | Line | Data |
---|---|---|
8ead62cf FB |
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 | ||
74 | ops.state = wav_state_cb; | |
75 | ops.capture = wav_capture_cb; | |
76 | ||
77 | wav = qemu_mallocz (sizeof (*wav)); | |
78 | if (!wav) { | |
79 | AUD_log ("wav", "Could not allocate memory (%zu bytes)", sizeof (*wav)); | |
80 | return; | |
81 | } | |
82 | ||
83 | shift = bits16 + stereo; | |
84 | hdr[34] = bits16 ? 0x10 : 0x08; | |
85 | ||
86 | le_store (hdr + 22, as.nchannels, 2); | |
87 | le_store (hdr + 24, freq, 4); | |
88 | le_store (hdr + 28, freq << shift, 4); | |
89 | le_store (hdr + 32, 1 << shift, 2); | |
90 | ||
91 | wav->f = fopen (path, "wb"); | |
92 | if (!wav->f) { | |
93 | AUD_log ("wav", "Failed to open wave file `%s'\nReason: %s\n", | |
94 | path, strerror (errno)); | |
95 | qemu_free (wav); | |
96 | return; | |
97 | } | |
98 | ||
99 | qemu_put_buffer (wav->f, hdr, sizeof (hdr)); | |
100 | AUD_add_capture (NULL, &as, 0, &ops, wav); | |
101 | } |