Statistics
| Branch: | Revision:

root / audio / wavcapture.c @ e6bb7d7e

History | View | Annotate | Download (3.9 kB)

1 87ecb68b pbrook
#include "hw/hw.h"
2 87ecb68b pbrook
#include "console.h"
3 87ecb68b pbrook
#include "audio.h"
4 8ead62cf bellard
5 8ead62cf bellard
typedef struct {
6 8ead62cf bellard
    QEMUFile *f;
7 8ead62cf bellard
    int bytes;
8 ec36b695 bellard
    char *path;
9 ec36b695 bellard
    int freq;
10 ec36b695 bellard
    int bits;
11 ec36b695 bellard
    int nchannels;
12 ec36b695 bellard
    CaptureVoiceOut *cap;
13 8ead62cf bellard
} WAVState;
14 8ead62cf bellard
15 8ead62cf bellard
/* VICE code: Store number as little endian. */
16 8ead62cf bellard
static void le_store (uint8_t *buf, uint32_t val, int len)
17 8ead62cf bellard
{
18 8ead62cf bellard
    int i;
19 8ead62cf bellard
    for (i = 0; i < len; i++) {
20 8ead62cf bellard
        buf[i] = (uint8_t) (val & 0xff);
21 8ead62cf bellard
        val >>= 8;
22 8ead62cf bellard
    }
23 8ead62cf bellard
}
24 8ead62cf bellard
25 ec36b695 bellard
static void wav_notify (void *opaque, audcnotification_e cmd)
26 8ead62cf bellard
{
27 ec36b695 bellard
    (void) opaque;
28 ec36b695 bellard
    (void) cmd;
29 ec36b695 bellard
}
30 8ead62cf bellard
31 ec36b695 bellard
static void wav_destroy (void *opaque)
32 ec36b695 bellard
{
33 ec36b695 bellard
    WAVState *wav = opaque;
34 ec36b695 bellard
    uint8_t rlen[4];
35 ec36b695 bellard
    uint8_t dlen[4];
36 ec36b695 bellard
    uint32_t datalen = wav->bytes;
37 ec36b695 bellard
    uint32_t rifflen = datalen + 36;
38 8ead62cf bellard
39 e84a4fed bellard
    if (wav->f) {
40 e84a4fed bellard
        le_store (rlen, rifflen, 4);
41 e84a4fed bellard
        le_store (dlen, datalen, 4);
42 f941aa25 ths
43 e84a4fed bellard
        qemu_fseek (wav->f, 4, SEEK_SET);
44 e84a4fed bellard
        qemu_put_buffer (wav->f, rlen, 4);
45 f941aa25 ths
46 e84a4fed bellard
        qemu_fseek (wav->f, 32, SEEK_CUR);
47 e84a4fed bellard
        qemu_put_buffer (wav->f, dlen, 4);
48 e84a4fed bellard
        qemu_fclose (wav->f);
49 8ead62cf bellard
    }
50 f941aa25 ths
51 e84a4fed bellard
    qemu_free (wav->path);
52 8ead62cf bellard
}
53 8ead62cf bellard
54 ec36b695 bellard
static void wav_capture (void *opaque, void *buf, int size)
55 8ead62cf bellard
{
56 8ead62cf bellard
    WAVState *wav = opaque;
57 8ead62cf bellard
58 8ead62cf bellard
    qemu_put_buffer (wav->f, buf, size);
59 8ead62cf bellard
    wav->bytes += size;
60 8ead62cf bellard
}
61 8ead62cf bellard
62 ec36b695 bellard
static void wav_capture_destroy (void *opaque)
63 ec36b695 bellard
{
64 ec36b695 bellard
    WAVState *wav = opaque;
65 ec36b695 bellard
66 ec36b695 bellard
    AUD_del_capture (wav->cap, wav);
67 ec36b695 bellard
}
68 ec36b695 bellard
69 ec36b695 bellard
static void wav_capture_info (void *opaque)
70 ec36b695 bellard
{
71 ec36b695 bellard
    WAVState *wav = opaque;
72 ec36b695 bellard
    char *path = wav->path;
73 ec36b695 bellard
74 ec36b695 bellard
    term_printf ("Capturing audio(%d,%d,%d) to %s: %d bytes\n",
75 ec36b695 bellard
                 wav->freq, wav->bits, wav->nchannels,
76 ec36b695 bellard
                 path ? path : "<not available>", wav->bytes);
77 ec36b695 bellard
}
78 ec36b695 bellard
79 ec36b695 bellard
static struct capture_ops wav_capture_ops = {
80 ec36b695 bellard
    .destroy = wav_capture_destroy,
81 ec36b695 bellard
    .info = wav_capture_info
82 ec36b695 bellard
};
83 ec36b695 bellard
84 ec36b695 bellard
int wav_start_capture (CaptureState *s, const char *path, int freq,
85 ec36b695 bellard
                       int bits, int nchannels)
86 8ead62cf bellard
{
87 8ead62cf bellard
    WAVState *wav;
88 8ead62cf bellard
    uint8_t hdr[] = {
89 8ead62cf bellard
        0x52, 0x49, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x57, 0x41, 0x56,
90 8ead62cf bellard
        0x45, 0x66, 0x6d, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00,
91 8ead62cf bellard
        0x02, 0x00, 0x44, 0xac, 0x00, 0x00, 0x10, 0xb1, 0x02, 0x00, 0x04,
92 8ead62cf bellard
        0x00, 0x10, 0x00, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00
93 8ead62cf bellard
    };
94 8ead62cf bellard
    audsettings_t as;
95 8ead62cf bellard
    struct audio_capture_ops ops;
96 ec36b695 bellard
    int stereo, bits16, shift;
97 ec36b695 bellard
    CaptureVoiceOut *cap;
98 ec36b695 bellard
99 ec36b695 bellard
    if (bits != 8 && bits != 16) {
100 ec36b695 bellard
        term_printf ("incorrect bit count %d, must be 8 or 16\n", bits);
101 ec36b695 bellard
        return -1;
102 ec36b695 bellard
    }
103 ec36b695 bellard
104 ec36b695 bellard
    if (nchannels != 1 && nchannels != 2) {
105 47dbd1f3 bellard
        term_printf ("incorrect channel count %d, must be 1 or 2\n",
106 47dbd1f3 bellard
                     nchannels);
107 ec36b695 bellard
        return -1;
108 ec36b695 bellard
    }
109 8ead62cf bellard
110 ec36b695 bellard
    stereo = nchannels == 2;
111 ec36b695 bellard
    bits16 = bits == 16;
112 8ead62cf bellard
113 8ead62cf bellard
    as.freq = freq;
114 8ead62cf bellard
    as.nchannels = 1 << stereo;
115 8ead62cf bellard
    as.fmt = bits16 ? AUD_FMT_S16 : AUD_FMT_U8;
116 d929eba5 bellard
    as.endianness = 0;
117 8ead62cf bellard
118 ec36b695 bellard
    ops.notify = wav_notify;
119 ec36b695 bellard
    ops.capture = wav_capture;
120 ec36b695 bellard
    ops.destroy = wav_destroy;
121 8ead62cf bellard
122 8ead62cf bellard
    wav = qemu_mallocz (sizeof (*wav));
123 8ead62cf bellard
    if (!wav) {
124 a3c25997 bellard
        term_printf ("Could not allocate memory for wav capture (%zu bytes)",
125 a3c25997 bellard
                     sizeof (*wav));
126 ec36b695 bellard
        return -1;
127 8ead62cf bellard
    }
128 8ead62cf bellard
129 8ead62cf bellard
    shift = bits16 + stereo;
130 8ead62cf bellard
    hdr[34] = bits16 ? 0x10 : 0x08;
131 8ead62cf bellard
132 8ead62cf bellard
    le_store (hdr + 22, as.nchannels, 2);
133 8ead62cf bellard
    le_store (hdr + 24, freq, 4);
134 8ead62cf bellard
    le_store (hdr + 28, freq << shift, 4);
135 8ead62cf bellard
    le_store (hdr + 32, 1 << shift, 2);
136 8ead62cf bellard
137 e70332b3 bellard
    wav->f = qemu_fopen (path, "wb");
138 8ead62cf bellard
    if (!wav->f) {
139 ec36b695 bellard
        term_printf ("Failed to open wave file `%s'\nReason: %s\n",
140 ec36b695 bellard
                     path, strerror (errno));
141 8ead62cf bellard
        qemu_free (wav);
142 ec36b695 bellard
        return -1;
143 8ead62cf bellard
    }
144 8ead62cf bellard
145 ec36b695 bellard
    wav->path = qemu_strdup (path);
146 ec36b695 bellard
    wav->bits = bits;
147 ec36b695 bellard
    wav->nchannels = nchannels;
148 ec36b695 bellard
    wav->freq = freq;
149 ec36b695 bellard
150 8ead62cf bellard
    qemu_put_buffer (wav->f, hdr, sizeof (hdr));
151 ec36b695 bellard
152 ec36b695 bellard
    cap = AUD_add_capture (NULL, &as, &ops, wav);
153 ec36b695 bellard
    if (!cap) {
154 ec36b695 bellard
        term_printf ("Failed to add audio capture\n");
155 e84a4fed bellard
        qemu_free (wav->path);
156 e84a4fed bellard
        qemu_fclose (wav->f);
157 ec36b695 bellard
        qemu_free (wav);
158 ec36b695 bellard
        return -1;
159 ec36b695 bellard
    }
160 ec36b695 bellard
161 ec36b695 bellard
    wav->cap = cap;
162 ec36b695 bellard
    s->opaque = wav;
163 ec36b695 bellard
    s->ops = wav_capture_ops;
164 ec36b695 bellard
    return 0;
165 8ead62cf bellard
}