Statistics
| Branch: | Revision:

root / audio / wavcapture.c @ 34b5d2c6

History | View | Annotate | Download (5 kB)

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