Annotation of qemu/audio/wavaudio.c, revision 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.