Annotation of qemu/audio/wavaudio.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * QEMU WAV audio output driver
                      3:  * 
                      4:  * Copyright (c) 2004 Vassili Karpov (malc)
                      5:  * 
                      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:
                     12:  *
                     13:  * The above copyright notice and this permission notice shall be included in
                     14:  * all copies or substantial portions of the Software.
                     15:  *
                     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
                     22:  * THE SOFTWARE.
                     23:  */
                     24: #include "vl.h"
                     25: 
                     26: #include "audio/audio_int.h"
                     27: 
                     28: typedef struct WAVVoice {
                     29:     HWVoice hw;
                     30:     QEMUFile *f;
                     31:     int64_t old_ticks;
                     32:     void *pcm_buf;
                     33:     int total_samples;
                     34: } WAVVoice;
                     35: 
                     36: #define dolog(...) AUD_log ("wav", __VA_ARGS__)
                     37: #ifdef DEBUG
                     38: #define ldebug(...) dolog (__VA_ARGS__)
                     39: #else
                     40: #define ldebug(...)
                     41: #endif
                     42: 
                     43: static struct {
                     44:     const char *wav_path;
                     45: } conf = {
                     46:     .wav_path = "qemu.wav"
                     47: };
                     48: 
                     49: static void wav_hw_run (HWVoice *hw)
                     50: {
                     51:     WAVVoice *wav = (WAVVoice *) hw;
                     52:     int rpos, live, decr, samples;
                     53:     uint8_t *dst;
                     54:     st_sample_t *src;
                     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;
                     58: 
                     59:     if (bytes > INT_MAX)
                     60:         samples = INT_MAX >> hw->shift;
                     61:     else
                     62:         samples = bytes >> hw->shift;
                     63: 
                     64:     live = pcm_hw_get_live (hw);
                     65:     if (live <= 0)
                     66:         return;
                     67: 
                     68:     wav->old_ticks = now;
                     69:     decr = audio_MIN (live, samples);
                     70:     samples = decr;
                     71:     rpos = hw->rpos;
                     72:     while (samples) {
                     73:         int left_till_end_samples = hw->samples - rpos;
                     74:         int convert_samples = audio_MIN (samples, left_till_end_samples);
                     75: 
                     76:         src = advance (hw->mix_buf, rpos * sizeof (st_sample_t));
                     77:         dst = advance (wav->pcm_buf, rpos << hw->shift);
                     78: 
                     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));
                     82: 
                     83:         rpos = (rpos + convert_samples) % hw->samples;
                     84:         samples -= convert_samples;
                     85:         wav->total_samples += convert_samples;
                     86:     }
                     87: 
                     88:     pcm_hw_dec_live (hw, decr);
                     89:     hw->rpos = rpos;
                     90: }
                     91: 
                     92: static int wav_hw_write (SWVoice *sw, void *buf, int len)
                     93: {
                     94:     return pcm_hw_write (sw, buf, len);
                     95: }
                     96: 
                     97: /* VICE code: Store number as little endian. */
                     98: static void le_store (uint8_t *buf, uint32_t val, int len)
                     99: {
                    100:     int i;
                    101:     for (i = 0; i < len; i++) {
                    102:         buf[i] = (uint8_t) (val & 0xff);
                    103:         val >>= 8;
                    104:     }
                    105: }
                    106: 
                    107: static int wav_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt)
                    108: {
                    109:     WAVVoice *wav = (WAVVoice *) hw;
                    110:     int bits16 = 0, stereo = audio_state.fixed_channels == 2;
                    111:     uint8_t hdr[] = {
                    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
                    116:     };
                    117: 
                    118:     switch (audio_state.fixed_fmt) {
                    119:     case AUD_FMT_S8:
                    120:     case AUD_FMT_U8:
                    121:         break;
                    122: 
                    123:     case AUD_FMT_S16:
                    124:     case AUD_FMT_U16:
                    125:         bits16 = 1;
                    126:         break;
                    127:     }
                    128: 
                    129:     hdr[34] = bits16 ? 0x10 : 0x08;
                    130:     hw->freq = 44100;
                    131:     hw->nchannels = stereo ? 2 : 1;
                    132:     hw->fmt = bits16 ? AUD_FMT_S16 : AUD_FMT_U8;
                    133:     hw->bufsize = 4096;
                    134:     wav->pcm_buf = qemu_mallocz (hw->bufsize);
                    135:     if (!wav->pcm_buf)
                    136:         return -1;
                    137: 
                    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);
                    142: 
                    143:     wav->f = fopen (conf.wav_path, "wb");
                    144:     if (!wav->f) {
                    145:         dolog ("failed to open wave file `%s'\nReason: %s\n",
                    146:                conf.wav_path, strerror (errno));
                    147:         qemu_free (wav->pcm_buf);
                    148:         wav->pcm_buf = NULL;
                    149:         return -1;
                    150:     }
                    151: 
                    152:     qemu_put_buffer (wav->f, hdr, sizeof (hdr));
                    153:     return 0;
                    154: }
                    155: 
                    156: static void wav_hw_fini (HWVoice *hw)
                    157: {
                    158:     WAVVoice *wav = (WAVVoice *) hw;
                    159:     int stereo = hw->nchannels == 2;
                    160:     uint8_t rlen[4];
                    161:     uint8_t dlen[4];
                    162:     uint32_t rifflen = (wav->total_samples << stereo) + 36;
                    163:     uint32_t datalen = wav->total_samples << stereo;
                    164: 
                    165:     if (!wav->f || !hw->active)
                    166:         return;
                    167: 
                    168:     le_store (rlen, rifflen, 4);
                    169:     le_store (dlen, datalen, 4);
                    170: 
                    171:     qemu_fseek (wav->f, 4, SEEK_SET);
                    172:     qemu_put_buffer (wav->f, rlen, 4);
                    173: 
                    174:     qemu_fseek (wav->f, 32, SEEK_CUR);
                    175:     qemu_put_buffer (wav->f, dlen, 4);
                    176: 
                    177:     fclose (wav->f);
                    178:     wav->f = NULL;
                    179: 
                    180:     qemu_free (wav->pcm_buf);
                    181:     wav->pcm_buf = NULL;
                    182: }
                    183: 
                    184: static int wav_hw_ctl (HWVoice *hw, int cmd, ...)
                    185: {
                    186:     (void) hw;
                    187:     (void) cmd;
                    188:     return 0;
                    189: }
                    190: 
                    191: static void *wav_audio_init (void)
                    192: {
                    193:     return &conf;
                    194: }
                    195: 
                    196: static void wav_audio_fini (void *opaque)
                    197: {
                    198:     ldebug ("wav_fini");
                    199: }
                    200: 
                    201: struct pcm_ops wav_pcm_ops = {
                    202:     wav_hw_init,
                    203:     wav_hw_fini,
                    204:     wav_hw_run,
                    205:     wav_hw_write,
                    206:     wav_hw_ctl
                    207: };
                    208: 
                    209: struct audio_output_driver wav_output_driver = {
                    210:     "wav",
                    211:     wav_audio_init,
                    212:     wav_audio_fini,
                    213:     &wav_pcm_ops,
                    214:     1,
                    215:     1,
                    216:     sizeof (WAVVoice)
                    217: };

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.