18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * QEMU WAV audio driver
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (c) 2007 The Android Open Source Project
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (c) 2004-2005 Vassili Karpov (malc)
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Permission is hereby granted, free of charge, to any person obtaining a copy
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * of this software and associated documentation files (the "Software"), to deal
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * in the Software without restriction, including without limitation the rights
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * copies of the Software, and to permit persons to whom the Software is
128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * furnished to do so, subject to the following conditions:
138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * The above copyright notice and this permission notice shall be included in
158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * all copies or substantial portions of the Software.
168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE SOFTWARE.
248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "hw/hw.h"
267a78db75ad42aea283f5073f51891464104a9fc3David 'Digit' Turner#include "qemu/timer.h"
275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "audio.h"
285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define AUDIO_CAP "wav"
308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "audio_int.h"
318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  WAV_AUDIO_IN  1
338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/** VOICE OUT  (Saving to a .WAV file)
358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project **/
368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct WAVVoiceOut {
378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    HWVoiceOut hw;
380e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner    FILE *f;
398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int64_t old_ticks;
408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    void *pcm_buf;
418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int total_samples;
428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} WAVVoiceOut;
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic struct {
455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct audsettings settings;
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *wav_path;
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} conf_out = {
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        44100,
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        2,
518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        AUD_FMT_S16,
528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        0
538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    },
548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "qemu.wav"
558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
575d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turnerstatic int wav_out_run (HWVoiceOut *hw, int live)
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    WAVVoiceOut *wav = (WAVVoiceOut *) hw;
605d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    int rpos, decr, samples;
618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint8_t *dst;
625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct st_sample *src;
63dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int64_t ticks = now - wav->old_ticks;
65a7fb77d6eca56e61e94f62e7deb4120b60b1e919David 'Digit' Turner    int64_t bytes =
66a7fb77d6eca56e61e94f62e7deb4120b60b1e919David 'Digit' Turner        muldiv64 (ticks, hw->info.bytes_per_second, get_ticks_per_sec ());
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (bytes > INT_MAX) {
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        samples = INT_MAX >> hw->info.shift;
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else {
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        samples = bytes >> hw->info.shift;
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    wav->old_ticks = now;
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    decr = audio_MIN (live, samples);
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    samples = decr;
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    rpos = hw->rpos;
798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (samples) {
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int left_till_end_samples = hw->samples - rpos;
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int convert_samples = audio_MIN (samples, left_till_end_samples);
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        src = hw->mix_buf + rpos;
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dst = advance (wav->pcm_buf, rpos << hw->info.shift);
858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hw->clip (dst, src, convert_samples);
870e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner        if (fwrite (dst, convert_samples << hw->info.shift, 1, wav->f) != 1) {
880e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner            dolog ("wav_run_out: fwrite of %d bytes failed\nReaons: %s\n",
890e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner                   convert_samples << hw->info.shift, strerror (errno));
900e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner        }
918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rpos = (rpos + convert_samples) % hw->samples;
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        samples -= convert_samples;
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wav->total_samples += convert_samples;
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hw->rpos = rpos;
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return decr;
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int wav_out_write (SWVoiceOut *sw, void *buf, int len)
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return audio_pcm_sw_write (sw, buf, len);
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* VICE code: Store number as little endian. */
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void le_store (uint8_t *buf, uint32_t val, int len)
1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int i;
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (i = 0; i < len; i++) {
1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf[i] = (uint8_t) (val & 0xff);
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        val >>= 8;
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int wav_out_init (HWVoiceOut *hw, struct audsettings *as)
1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    WAVVoiceOut *wav = (WAVVoiceOut *) hw;
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int bits16 = 0, stereo = 0;
1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint8_t hdr[] = {
1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        0x52, 0x49, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x57, 0x41, 0x56,
1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        0x45, 0x66, 0x6d, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00,
1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        0x02, 0x00, 0x44, 0xac, 0x00, 0x00, 0x10, 0xb1, 0x02, 0x00, 0x04,
1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        0x00, 0x10, 0x00, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00
1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    };
1265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct audsettings wav_as = conf_out.settings;
1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    (void) as;
1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    stereo = wav_as.nchannels == 2;
1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (wav_as.fmt) {
1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case AUD_FMT_S8:
1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case AUD_FMT_U8:
1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bits16 = 0;
1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case AUD_FMT_S16:
1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case AUD_FMT_U16:
1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bits16 = 1;
1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case AUD_FMT_S32:
1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case AUD_FMT_U32:
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dolog ("WAVE files can not handle 32bit formats\n");
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hdr[34] = bits16 ? 0x10 : 0x08;
1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    wav_as.endianness = 0;
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    audio_pcm_init_info (&hw->info, &wav_as);
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hw->samples = 1024;
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    wav->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!wav->pcm_buf) {
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dolog ("Could not allocate buffer (%d bytes)\n",
1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               hw->samples << hw->info.shift);
1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    le_store (hdr + 22, hw->info.nchannels, 2);
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    le_store (hdr + 24, hw->info.freq, 4);
1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    le_store (hdr + 28, hw->info.freq << (bits16 + stereo), 4);
1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    le_store (hdr + 32, 1 << (bits16 + stereo), 2);
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1660e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner    wav->f = fopen (conf_out.wav_path, "wb");
1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!wav->f) {
1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dolog ("Failed to open wave file `%s'\nReason: %s\n",
1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               conf_out.wav_path, strerror (errno));
170aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner        g_free (wav->pcm_buf);
1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wav->pcm_buf = NULL;
1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1750e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner    if (fwrite (hdr, sizeof (hdr), 1, wav->f) != 1) {
1760e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner        dolog ("wav_init_out: failed to write header\nReason: %s\n",
1770e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner               strerror(errno));
1780e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner        return -1;
1790e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner    }
1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void wav_out_fini (HWVoiceOut *hw)
1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    WAVVoiceOut *wav = (WAVVoiceOut *) hw;
1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint8_t rlen[4];
1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint8_t dlen[4];
1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t datalen = wav->total_samples << hw->info.shift;
1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t rifflen = datalen + 36;
1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!wav->f) {
1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    le_store (rlen, rifflen, 4);
1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    le_store (dlen, datalen, 4);
1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1980e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner    fseek (wav->f, 4, SEEK_SET);
1990e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner    fwrite(rlen, 4, 1, wav->f);
2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2010e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner    fseek (wav->f, 32, SEEK_CUR);
2020e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner    fwrite(dlen, 4, 1, wav->f);
2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2040e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner    fclose (wav->f);
2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    wav->f = NULL;
2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
207aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    g_free (wav->pcm_buf);
2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    wav->pcm_buf = NULL;
2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int wav_out_ctl (HWVoiceOut *hw, int cmd, ...)
2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    (void) hw;
2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    (void) cmd;
2158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
2168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if WAV_AUDIO_IN
2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/** WAV IN (Reading from a .WAV file)
2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project **/
2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project static struct {
2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *wav_path;
2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} conf_in = {
2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "qemu.wav"
2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
2298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct WAVVoiceIn {
2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    HWVoiceIn  hw;
2320e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner    FILE*      f;
2338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int64_t    old_ticks;
2348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    void*      pcm_buf;
2358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int        total_samples;
2368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int        total_size;
2378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} WAVVoiceIn;
2388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
2418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectle_read( const uint8_t*  p, int  size ) {
2428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  shift  = 0;
2438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  result = 0;
2448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for ( ; size > 0; size-- ) {
2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        result = result | (p[0] << shift);
2468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p     += 1;
2478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        shift += 8;
2488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return  result;
2508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
2535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerwav_in_init (HWVoiceIn *hw, struct audsettings *as)
2548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    WAVVoiceIn*  wav = (WAVVoiceIn *) hw;
2568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char*  path = conf_in.wav_path;
2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint8_t      hdr[44];
2585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct audsettings wav_as = *as;
2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int           nchannels, freq, format, bits;
2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2610e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner    wav->f = fopen (path, "rb");
2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (wav->f == NULL) {
2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dolog("Failed to open wave file '%s'\nReason: %s\n", path,
2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project              strerror(errno));
2658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2680e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner    if (fread(hdr, sizeof(hdr), 1, wav->f) != 1) {
2690e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner        dolog("File '%s' doesn't seem to be a .wav file\n", path);
2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto Fail;
2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* check that this is a wave file */
2748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( hdr[0] != 'R' || hdr[1] != 'I' || hdr[2] != 'F' || hdr[3] != 'F' ||
2758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         hdr[8] != 'W' || hdr[9] != 'A' || hdr[10]!= 'V' || hdr[11]!= 'E' ||
2768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         hdr[12]!= 'f' || hdr[13]!= 'm' || hdr[14]!= 't' || hdr[15]!= ' ' ||
2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         hdr[40]!= 'd' || hdr[41]!= 'a' || hdr[42]!= 't' || hdr[43]!= 'a') {
2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         dolog("File '%s' is not a valid .wav file\n", path);
2798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         goto Fail;
2808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    nchannels   = le_read( hdr+22, 2 );
2838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    freq        = le_read( hdr+24, 4 );
2848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    format      = le_read( hdr+32, 2 );
2858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bits        = le_read( hdr+34, 2 );
2868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    wav->total_size = le_read( hdr+40, 4 );
2888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* perform some sainty checks */
2908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (nchannels) {
2918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
2928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2: break;
2938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
2948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dolog("unsupported number of channels (%d) in '%s'\n",
2958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  nchannels, path);
2968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto Fail;
2978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (format) {
3008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
3018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
3028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 4: break;
3038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
3048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dolog("unsupported bytes per sample (%d) in '%s'\n",
3058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  format, path);
3068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto Fail;
3078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (format*8/nchannels != bits) {
3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dolog("invalid bits per sample (%d, expected %d) in '%s'\n",
3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project              bits, format*8/nchannels, path);
3128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto Fail;
3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    wav_as.nchannels  = nchannels;
3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    wav_as.fmt        = (bits == 8) ? AUD_FMT_U8 : AUD_FMT_S16;
3178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    wav_as.freq       = freq;
3188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    wav_as.endianness = 0;  /* always little endian */
3198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    audio_pcm_init_info (&hw->info, &wav_as);
3218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hw->samples  = 1024;
3238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    wav->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
3248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!wav->pcm_buf) {
3258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto Fail;
3268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
3288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectFail:
3300e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner    fclose (wav->f);
3318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    wav->f = NULL;
3328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
3338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void wav_in_fini (HWVoiceIn *hw)
3378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    WAVVoiceIn *wav = (WAVVoiceIn *) hw;
3398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!wav->f) {
3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
3428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3440e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner    fclose (wav->f);
3458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    wav->f = NULL;
3468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
347aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    g_free (wav->pcm_buf);
3488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    wav->pcm_buf = NULL;
3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int wav_in_run (HWVoiceIn *hw)
3528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    WAVVoiceIn*   wav = (WAVVoiceIn *) hw;
3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int           wpos, live, decr, samples;
3558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint8_t*      src;
3565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct st_sample*  dst;
3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
358dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    int64_t  now   = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int64_t  ticks = now - wav->old_ticks;
360a7fb77d6eca56e61e94f62e7deb4120b60b1e919David 'Digit' Turner    int64_t  bytes = muldiv64(ticks, hw->info.bytes_per_second, get_ticks_per_sec());
3618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (bytes > INT_MAX) {
3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        samples = INT_MAX >> hw->info.shift;
3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else {
3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        samples = bytes >> hw->info.shift;
3678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    live = audio_pcm_hw_get_live_in (hw);
3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!live) {
3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
3728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    wav->old_ticks = now;
3758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    decr    = audio_MIN (live, samples);
3778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    samples = decr;
3788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    wpos    = hw->wpos;
3798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (samples) {
3808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int left_till_end_samples = hw->samples - wpos;
3818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int convert_samples       = audio_MIN (samples, left_till_end_samples);
3828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dst = hw->conv_buf + wpos;
3848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        src = advance (wav->pcm_buf, wpos << hw->info.shift);
3858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3860e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner        clearerr(wav->f);
3870e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner        size_t read_bytes = fread(src, 1, convert_samples << hw->info.shift, wav->f);
3880e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner        if (read_bytes == 0 && ferror(wav->f) != EINTR)
3890e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner            return 0;
3908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3910e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner        size_t read_samples = read_bytes >> hw->info.shift;
3920e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner        memcpy (dst, src, read_bytes);
3930e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner
3940e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner        wpos                = (wpos + read_samples) % hw->samples;
3950e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner        samples            -= read_samples;
3960e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner        wav->total_samples += read_samples;
3978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hw->wpos = wpos;
4008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return decr;
4018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int wav_in_read (SWVoiceIn *sw, void *buf, int len)
4048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return audio_pcm_sw_read (sw, buf, len);
4068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int wav_in_ctl (HWVoiceIn *hw, int cmd, ...)
4098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    (void) hw;
4118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    (void) cmd;
4128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
4138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif  /* WAV_AUDIO_IN */
4168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/** COMMON CODE
4188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project **/
4198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void *wav_audio_init (void)
4208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return &conf_out;
4228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void wav_audio_fini (void *opaque)
4258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    (void) opaque;
4278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ldebug ("wav_fini");
4288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic struct audio_option wav_options[] = {
4318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {"FREQUENCY", AUD_OPT_INT, &conf_out.settings.freq,
4328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     "Frequency", NULL, 0},
4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {"FORMAT", AUD_OPT_FMT, &conf_out.settings.fmt,
4358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     "Format", NULL, 0},
4368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {"DAC_FIXED_CHANNELS", AUD_OPT_INT, &conf_out.settings.nchannels,
4388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     "Number of channels (1 - mono, 2 - stereo)", NULL, 0},
4398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {"PATH", AUD_OPT_STR, &conf_out.wav_path,
4418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     "Path to output .wav file", NULL, 0},
4428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if WAV_AUDIO_IN
4448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {"IN_PATH", AUD_OPT_STR, &conf_in.wav_path,
4458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     "Path to input .wav file", NULL, 0},
4468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
4478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {NULL, 0, NULL, NULL, NULL, 0}
4488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
4498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct audio_pcm_ops wav_pcm_ops = {
4518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    wav_out_init,
4528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    wav_out_fini,
4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    wav_out_run,
4548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    wav_out_write,
4558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    wav_out_ctl,
4568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if WAV_AUDIO_IN
4588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    wav_in_init,
4598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    wav_in_fini,
4608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    wav_in_run,
4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    wav_in_read,
4628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    wav_in_ctl
4638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
4648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL,
4658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL,
4668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL,
4678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL,
4688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL
4698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
4708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
4718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct audio_driver wav_audio_driver = {
4738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    INIT_FIELD (name           = ) "wav",
4748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    INIT_FIELD (descr          = )
4758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "WAV file read/write (www.wikipedia.org/wiki/WAV)",
4768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    INIT_FIELD (options        = ) wav_options,
4778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    INIT_FIELD (init           = ) wav_audio_init,
4788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    INIT_FIELD (fini           = ) wav_audio_fini,
4798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    INIT_FIELD (pcm_ops        = ) &wav_pcm_ops,
4808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    INIT_FIELD (can_be_default = ) 0,
4818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if WAV_AUDIO_IN
4828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    INIT_FIELD (max_voices_in  = ) 1,
4838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    INIT_FIELD (max_voices_out = ) 1,
4848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    INIT_FIELD (voice_size_out = ) sizeof (WAVVoiceOut),
4858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    INIT_FIELD (voice_size_in  = ) sizeof (WAVVoiceIn)
4868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
4878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    INIT_FIELD (max_voices_out = ) 1,
4888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    INIT_FIELD (max_voices_in  = ) 0,
4898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    INIT_FIELD (voice_size_out = ) sizeof (WAVVoiceOut),
4908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    INIT_FIELD (voice_size_in  = ) 0
4918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
4928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
493