2 * QEMU WAV audio output driver
4 * Copyright (c) 2004 Vassili Karpov (malc)
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 #include "audio/audio_int.h"
28 typedef struct WAVVoice
{
36 #define dolog(...) AUD_log ("wav", __VA_ARGS__)
38 #define ldebug(...) dolog (__VA_ARGS__)
46 .wav_path
= "qemu.wav"
49 static void wav_hw_run (HWVoice
*hw
)
51 WAVVoice
*wav
= (WAVVoice
*) hw
;
52 int rpos
, live
, decr
, samples
;
55 int64_t now
= qemu_get_clock (vm_clock
);
56 int64_t ticks
= now
- wav
->old_ticks
;
57 int64_t bytes
= (ticks
* hw
->bytes_per_second
) / ticks_per_sec
;
60 samples
= INT_MAX
>> hw
->shift
;
62 samples
= bytes
>> hw
->shift
;
64 live
= pcm_hw_get_live (hw
);
69 decr
= audio_MIN (live
, samples
);
73 int left_till_end_samples
= hw
->samples
- rpos
;
74 int convert_samples
= audio_MIN (samples
, left_till_end_samples
);
76 src
= advance (hw
->mix_buf
, rpos
* sizeof (st_sample_t
));
77 dst
= advance (wav
->pcm_buf
, rpos
<< hw
->shift
);
79 hw
->clip (dst
, src
, convert_samples
);
80 qemu_put_buffer (wav
->f
, dst
, convert_samples
<< hw
->shift
);
81 memset (src
, 0, convert_samples
* sizeof (st_sample_t
));
83 rpos
= (rpos
+ convert_samples
) % hw
->samples
;
84 samples
-= convert_samples
;
85 wav
->total_samples
+= convert_samples
;
88 pcm_hw_dec_live (hw
, decr
);
92 static int wav_hw_write (SWVoice
*sw
, void *buf
, int len
)
94 return pcm_hw_write (sw
, buf
, len
);
97 /* VICE code: Store number as little endian. */
98 static void le_store (uint8_t *buf
, uint32_t val
, int len
)
101 for (i
= 0; i
< len
; i
++) {
102 buf
[i
] = (uint8_t) (val
& 0xff);
107 static int wav_hw_init (HWVoice
*hw
, int freq
, int nchannels
, audfmt_e fmt
)
109 WAVVoice
*wav
= (WAVVoice
*) hw
;
110 int bits16
= 0, stereo
= audio_state
.fixed_channels
== 2;
112 0x52, 0x49, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x57, 0x41, 0x56,
113 0x45, 0x66, 0x6d, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00,
114 0x02, 0x00, 0x44, 0xac, 0x00, 0x00, 0x10, 0xb1, 0x02, 0x00, 0x04,
115 0x00, 0x10, 0x00, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00
118 switch (audio_state
.fixed_fmt
) {
129 hdr
[34] = bits16
? 0x10 : 0x08;
131 hw
->nchannels
= stereo
? 2 : 1;
132 hw
->fmt
= bits16
? AUD_FMT_S16
: AUD_FMT_U8
;
134 wav
->pcm_buf
= qemu_mallocz (hw
->bufsize
);
138 le_store (hdr
+ 22, hw
->nchannels
, 2);
139 le_store (hdr
+ 24, hw
->freq
, 4);
140 le_store (hdr
+ 28, hw
->freq
<< (bits16
+ stereo
), 4);
141 le_store (hdr
+ 32, 1 << (bits16
+ stereo
), 2);
143 wav
->f
= fopen (conf
.wav_path
, "wb");
145 dolog ("failed to open wave file `%s'\nReason: %s\n",
146 conf
.wav_path
, strerror (errno
));
147 qemu_free (wav
->pcm_buf
);
152 qemu_put_buffer (wav
->f
, hdr
, sizeof (hdr
));
156 static void wav_hw_fini (HWVoice
*hw
)
158 WAVVoice
*wav
= (WAVVoice
*) hw
;
159 int stereo
= hw
->nchannels
== 2;
162 uint32_t rifflen
= (wav
->total_samples
<< stereo
) + 36;
163 uint32_t datalen
= wav
->total_samples
<< stereo
;
165 if (!wav
->f
|| !hw
->active
)
168 le_store (rlen
, rifflen
, 4);
169 le_store (dlen
, datalen
, 4);
171 qemu_fseek (wav
->f
, 4, SEEK_SET
);
172 qemu_put_buffer (wav
->f
, rlen
, 4);
174 qemu_fseek (wav
->f
, 32, SEEK_CUR
);
175 qemu_put_buffer (wav
->f
, dlen
, 4);
180 qemu_free (wav
->pcm_buf
);
184 static int wav_hw_ctl (HWVoice
*hw
, int cmd
, ...)
191 static void *wav_audio_init (void)
196 static void wav_audio_fini (void *opaque
)
201 struct pcm_ops wav_pcm_ops
= {
209 struct audio_output_driver wav_output_driver
= {