Statistics
| Branch: | Revision:

root / audio / wavcapture.c @ 8b7968f7

History | View | Annotate | Download (3.8 kB)

1 87ecb68b pbrook
#include "hw/hw.h"
2 376253ec aliguori
#include "monitor.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 376253ec aliguori
    monitor_printf(cur_mon, "Capturing audio(%d,%d,%d) to %s: %d bytes\n",
75 376253ec aliguori
                   wav->freq, wav->bits, wav->nchannels,
76 376253ec aliguori
                   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 376253ec aliguori
    Monitor *mon = cur_mon;
88 8ead62cf bellard
    WAVState *wav;
89 8ead62cf bellard
    uint8_t hdr[] = {
90 8ead62cf bellard
        0x52, 0x49, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x57, 0x41, 0x56,
91 8ead62cf bellard
        0x45, 0x66, 0x6d, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00,
92 8ead62cf bellard
        0x02, 0x00, 0x44, 0xac, 0x00, 0x00, 0x10, 0xb1, 0x02, 0x00, 0x04,
93 8ead62cf bellard
        0x00, 0x10, 0x00, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00
94 8ead62cf bellard
    };
95 1ea879e5 malc
    struct audsettings as;
96 8ead62cf bellard
    struct audio_capture_ops ops;
97 ec36b695 bellard
    int stereo, bits16, shift;
98 ec36b695 bellard
    CaptureVoiceOut *cap;
99 ec36b695 bellard
100 ec36b695 bellard
    if (bits != 8 && bits != 16) {
101 376253ec aliguori
        monitor_printf(mon, "incorrect bit count %d, must be 8 or 16\n", bits);
102 ec36b695 bellard
        return -1;
103 ec36b695 bellard
    }
104 ec36b695 bellard
105 ec36b695 bellard
    if (nchannels != 1 && nchannels != 2) {
106 376253ec aliguori
        monitor_printf(mon, "incorrect channel count %d, must be 1 or 2\n",
107 376253ec aliguori
                       nchannels);
108 ec36b695 bellard
        return -1;
109 ec36b695 bellard
    }
110 8ead62cf bellard
111 ec36b695 bellard
    stereo = nchannels == 2;
112 ec36b695 bellard
    bits16 = bits == 16;
113 8ead62cf bellard
114 8ead62cf bellard
    as.freq = freq;
115 8ead62cf bellard
    as.nchannels = 1 << stereo;
116 8ead62cf bellard
    as.fmt = bits16 ? AUD_FMT_S16 : AUD_FMT_U8;
117 d929eba5 bellard
    as.endianness = 0;
118 8ead62cf bellard
119 ec36b695 bellard
    ops.notify = wav_notify;
120 ec36b695 bellard
    ops.capture = wav_capture;
121 ec36b695 bellard
    ops.destroy = wav_destroy;
122 8ead62cf bellard
123 8ead62cf bellard
    wav = qemu_mallocz (sizeof (*wav));
124 8ead62cf bellard
125 8ead62cf bellard
    shift = bits16 + stereo;
126 8ead62cf bellard
    hdr[34] = bits16 ? 0x10 : 0x08;
127 8ead62cf bellard
128 8ead62cf bellard
    le_store (hdr + 22, as.nchannels, 2);
129 8ead62cf bellard
    le_store (hdr + 24, freq, 4);
130 8ead62cf bellard
    le_store (hdr + 28, freq << shift, 4);
131 8ead62cf bellard
    le_store (hdr + 32, 1 << shift, 2);
132 8ead62cf bellard
133 e70332b3 bellard
    wav->f = qemu_fopen (path, "wb");
134 8ead62cf bellard
    if (!wav->f) {
135 376253ec aliguori
        monitor_printf(mon, "Failed to open wave file `%s'\nReason: %s\n",
136 376253ec aliguori
                       path, strerror (errno));
137 8ead62cf bellard
        qemu_free (wav);
138 ec36b695 bellard
        return -1;
139 8ead62cf bellard
    }
140 8ead62cf bellard
141 ec36b695 bellard
    wav->path = qemu_strdup (path);
142 ec36b695 bellard
    wav->bits = bits;
143 ec36b695 bellard
    wav->nchannels = nchannels;
144 ec36b695 bellard
    wav->freq = freq;
145 ec36b695 bellard
146 8ead62cf bellard
    qemu_put_buffer (wav->f, hdr, sizeof (hdr));
147 ec36b695 bellard
148 1a7dafce malc
    cap = AUD_add_capture (&as, &ops, wav);
149 ec36b695 bellard
    if (!cap) {
150 376253ec aliguori
        monitor_printf(mon, "Failed to add audio capture\n");
151 e84a4fed bellard
        qemu_free (wav->path);
152 e84a4fed bellard
        qemu_fclose (wav->f);
153 ec36b695 bellard
        qemu_free (wav);
154 ec36b695 bellard
        return -1;
155 ec36b695 bellard
    }
156 ec36b695 bellard
157 ec36b695 bellard
    wav->cap = cap;
158 ec36b695 bellard
    s->opaque = wav;
159 ec36b695 bellard
    s->ops = wav_capture_ops;
160 ec36b695 bellard
    return 0;
161 8ead62cf bellard
}