18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * QEMU FMOD audio driver
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (c) 2004-2005 Vassili Karpov (malc)
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Permission is hereby granted, free of charge, to any person obtaining a copy
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * of this software and associated documentation files (the "Software"), to deal
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * in the Software without restriction, including without limitation the rights
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * copies of the Software, and to permit persons to whom the Software is
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * furnished to do so, subject to the following conditions:
128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * The above copyright notice and this permission notice shall be included in
148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * all copies or substantial portions of the Software.
158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE SOFTWARE.
238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <fmod.h>
258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <fmod_errors.h>
265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "qemu-common.h"
278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "audio.h"
288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define AUDIO_CAP "fmod"
308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "audio_int.h"
318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct FMODVoiceOut {
338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    HWVoiceOut hw;
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned int old_pos;
358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    FSOUND_SAMPLE *fmod_sample;
368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int channel;
378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} FMODVoiceOut;
388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct FMODVoiceIn {
408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    HWVoiceIn hw;
418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    FSOUND_SAMPLE *fmod_sample;
428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} FMODVoiceIn;
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic struct {
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *drvname;
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int nb_samples;
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int freq;
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int nb_channels;
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int bufsize;
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int broken_adc;
518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} conf = {
525d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .nb_samples  = 2048 * 2,
535d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .freq        = 44100,
545d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .nb_channels = 2,
558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void GCC_FMT_ATTR (1, 2) fmod_logerr (const char *fmt, ...)
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_list ap;
608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_start (ap, fmt);
628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    AUD_vlog (AUDIO_CAP, fmt, ap);
638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_end (ap);
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    AUD_log (AUDIO_CAP, "Reason: %s\n",
668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             FMOD_ErrorString (FSOUND_GetError ()));
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void GCC_FMT_ATTR (2, 3) fmod_logerr2 (
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *typ,
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *fmt,
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ...
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    )
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_list ap;
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    AUD_log (AUDIO_CAP, "Could not initialize %s\n", typ);
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_start (ap, fmt);
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    AUD_vlog (AUDIO_CAP, fmt, ap);
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_end (ap);
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    AUD_log (AUDIO_CAP, "Reason: %s\n",
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             FMOD_ErrorString (FSOUND_GetError ()));
858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int fmod_write (SWVoiceOut *sw, void *buf, int len)
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return audio_pcm_sw_write (sw, buf, len);
908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void fmod_clear_sample (FMODVoiceOut *fmd)
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    HWVoiceOut *hw = &fmd->hw;
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int status;
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    void *p1 = 0, *p2 = 0;
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned int len1 = 0, len2 = 0;
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    status = FSOUND_Sample_Lock (
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        fmd->fmod_sample,
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        0,
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hw->samples << hw->info.shift,
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        &p1,
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        &p2,
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        &len1,
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        &len2
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        );
1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!status) {
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        fmod_logerr ("Failed to lock sample\n");
1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((len1 & hw->info.align) || (len2 & hw->info.align)) {
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dolog ("Lock returned misaligned length %d, %d, alignment %d\n",
1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               len1, len2, hw->info.align + 1);
1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto fail;
1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((len1 + len2) - (hw->samples << hw->info.shift)) {
1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dolog ("Lock returned incomplete length %d, %d\n",
1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               len1 + len2, hw->samples << hw->info.shift);
1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto fail;
1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    audio_pcm_info_clear_buf (&hw->info, p1, hw->samples);
1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project fail:
1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    status = FSOUND_Sample_Unlock (fmd->fmod_sample, p1, p2, len1, len2);
1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!status) {
1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        fmod_logerr ("Failed to unlock sample\n");
1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void fmod_write_sample (HWVoiceOut *hw, uint8_t *dst, int dst_len)
1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int src_len1 = dst_len;
1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int src_len2 = 0;
1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int pos = hw->rpos + dst_len;
1405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct st_sample *src1 = hw->mix_buf + hw->rpos;
1415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct st_sample *src2 = NULL;
1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (pos > hw->samples) {
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        src_len1 = hw->samples - hw->rpos;
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        src2 = hw->mix_buf;
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        src_len2 = dst_len - src_len1;
1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pos = src_len2;
1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (src_len1) {
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hw->clip (dst, src1, src_len1);
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (src_len2) {
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dst = advance (dst, src_len1 << hw->info.shift);
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hw->clip (dst, src2, src_len2);
1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hw->rpos = pos % hw->samples;
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int fmod_unlock_sample (FSOUND_SAMPLE *sample, void *p1, void *p2,
1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                               unsigned int blen1, unsigned int blen2)
1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int status = FSOUND_Sample_Unlock (sample, p1, p2, blen1, blen2);
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!status) {
1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        fmod_logerr ("Failed to unlock sample\n");
1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int fmod_lock_sample (
1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    FSOUND_SAMPLE *sample,
1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct audio_pcm_info *info,
1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int pos,
1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int len,
1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    void **p1,
1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    void **p2,
1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned int *blen1,
1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned int *blen2
1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    )
1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int status;
1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    status = FSOUND_Sample_Lock (
1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sample,
1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pos << info->shift,
1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len << info->shift,
1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p1,
1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p2,
1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        blen1,
1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        blen2
1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        );
1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!status) {
1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        fmod_logerr ("Failed to lock sample\n");
1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((*blen1 & info->align) || (*blen2 & info->align)) {
2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dolog ("Lock returned misaligned length %d, %d, alignment %d\n",
2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               *blen1, *blen2, info->align + 1);
2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        fmod_unlock_sample (sample, *p1, *p2, *blen1, *blen2);
2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *p1 = NULL - 1;
2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *p2 = NULL - 1;
2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *blen1 = ~0U;
2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *blen2 = ~0U;
2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!*p1 && *blen1) {
2158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dolog ("warning: !p1 && blen1=%d\n", *blen1);
2168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *blen1 = 0;
2178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!p2 && *blen2) {
2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dolog ("warning: !p2 && blen2=%d\n", *blen2);
2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *blen2 = 0;
2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2275d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turnerstatic int fmod_run_out (HWVoiceOut *hw, int live)
2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    FMODVoiceOut *fmd = (FMODVoiceOut *) hw;
2305d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    int decr;
2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    void *p1 = 0, *p2 = 0;
2328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned int blen1 = 0, blen2 = 0;
2338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned int len1 = 0, len2 = 0;
2348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2355d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    if (!hw->pending_disable) {
2368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
2378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    decr = live;
2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (fmd->channel >= 0) {
2428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int len = decr;
2438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int old_pos = fmd->old_pos;
2448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int ppos = FSOUND_GetCurrentPosition (fmd->channel);
2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (ppos == old_pos || !ppos) {
2478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
2488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
2498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ((old_pos < ppos) && ((old_pos + len) > ppos)) {
2518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            len = ppos - old_pos;
2528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
2538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else {
2548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ((old_pos > ppos) && ((old_pos + len) > (ppos + hw->samples))) {
2558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                len = hw->samples - old_pos + ppos;
2568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        decr = len;
2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (audio_bug (AUDIO_FUNC, decr < 0)) {
2618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dolog ("decr=%d live=%d ppos=%d old_pos=%d len=%d\n",
2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   decr, live, ppos, old_pos, len);
2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
2658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!decr) {
2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (fmod_lock_sample (fmd->fmod_sample, &fmd->hw.info,
2738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          fmd->old_pos, decr,
2748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          &p1, &p2,
2758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          &blen1, &blen2)) {
2768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len1 = blen1 >> hw->info.shift;
2808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len2 = blen2 >> hw->info.shift;
2818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ldebug ("%p %p %d %d %d %d\n", p1, p2, len1, len2, blen1, blen2);
2828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    decr = len1 + len2;
2838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (p1 && len1) {
2858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        fmod_write_sample (hw, p1, len1);
2868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (p2 && len2) {
2898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        fmod_write_sample (hw, p2, len2);
2908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    fmod_unlock_sample (fmd->fmod_sample, p1, p2, blen1, blen2);
2938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    fmd->old_pos = (fmd->old_pos + decr) % hw->samples;
2958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return decr;
2968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int aud_to_fmodfmt (audfmt_e fmt, int stereo)
2998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int mode = FSOUND_LOOP_NORMAL;
3018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (fmt) {
3038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case AUD_FMT_S8:
3048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        mode |= FSOUND_SIGNED | FSOUND_8BITS;
3058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
3068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case AUD_FMT_U8:
3088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        mode |= FSOUND_UNSIGNED | FSOUND_8BITS;
3098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case AUD_FMT_S16:
3128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        mode |= FSOUND_SIGNED | FSOUND_16BITS;
3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
3148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case AUD_FMT_U16:
3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        mode |= FSOUND_UNSIGNED | FSOUND_16BITS;
3178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
3188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
3208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dolog ("Internal logic error: Bad audio format %d\n", fmt);
3218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG_FMOD
3228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        abort ();
3238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
3248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        mode |= FSOUND_8BITS;
3258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    mode |= stereo ? FSOUND_STEREO : FSOUND_MONO;
3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return mode;
3288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void fmod_fini_out (HWVoiceOut *hw)
3318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    FMODVoiceOut *fmd = (FMODVoiceOut *) hw;
3338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (fmd->fmod_sample) {
3358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        FSOUND_Sample_Free (fmd->fmod_sample);
3368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        fmd->fmod_sample = 0;
3378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (fmd->channel >= 0) {
3398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            FSOUND_StopSound (fmd->channel);
3408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int fmod_init_out (HWVoiceOut *hw, struct audsettings *as)
3458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int bits16, mode, channel;
3478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    FMODVoiceOut *fmd = (FMODVoiceOut *) hw;
3485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct audsettings obt_as = *as;
3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    mode = aud_to_fmodfmt (as->fmt, as->nchannels == 2 ? 1 : 0);
3518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    fmd->fmod_sample = FSOUND_Sample_Alloc (
3528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        FSOUND_FREE,            /* index */
3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        conf.nb_samples,        /* length */
3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        mode,                   /* mode */
3558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        as->freq,               /* freq */
3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        255,                    /* volume */
3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        128,                    /* pan */
3588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        255                     /* priority */
3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        );
3608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!fmd->fmod_sample) {
3628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        fmod_logerr2 ("DAC", "Failed to allocate FMOD sample\n");
3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    channel = FSOUND_PlaySoundEx (FSOUND_FREE, fmd->fmod_sample, 0, 1);
3678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (channel < 0) {
3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        fmod_logerr2 ("DAC", "Failed to start playing sound\n");
3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        FSOUND_Sample_Free (fmd->fmod_sample);
3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    fmd->channel = channel;
3738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* FMOD always operates on little endian frames? */
3758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    obt_as.endianness = 0;
3768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    audio_pcm_init_info (&hw->info, &obt_as);
3778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bits16 = (mode & FSOUND_16BITS) != 0;
3788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hw->samples = conf.nb_samples;
3798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
3808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int fmod_ctl_out (HWVoiceOut *hw, int cmd, ...)
3838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int status;
3858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    FMODVoiceOut *fmd = (FMODVoiceOut *) hw;
3868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (cmd) {
3888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case VOICE_ENABLE:
3898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        fmod_clear_sample (fmd);
3908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        status = FSOUND_SetPaused (fmd->channel, 0);
3918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!status) {
3928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            fmod_logerr ("Failed to resume channel %d\n", fmd->channel);
3938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
3948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
3958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case VOICE_DISABLE:
3978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        status = FSOUND_SetPaused (fmd->channel, 1);
3988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!status) {
3998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            fmod_logerr ("Failed to pause channel %d\n", fmd->channel);
4008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
4028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
4048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int fmod_init_in (HWVoiceIn *hw, struct audsettings *as)
4078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int bits16, mode;
4098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    FMODVoiceIn *fmd = (FMODVoiceIn *) hw;
4105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct audsettings obt_as = *as;
4118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (conf.broken_adc) {
4138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
4148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    mode = aud_to_fmodfmt (as->fmt, as->nchannels == 2 ? 1 : 0);
4178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    fmd->fmod_sample = FSOUND_Sample_Alloc (
4188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        FSOUND_FREE,            /* index */
4198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        conf.nb_samples,        /* length */
4208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        mode,                   /* mode */
4218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        as->freq,               /* freq */
4228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        255,                    /* volume */
4238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        128,                    /* pan */
4248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        255                     /* priority */
4258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        );
4268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!fmd->fmod_sample) {
4288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        fmod_logerr2 ("ADC", "Failed to allocate FMOD sample\n");
4298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
4308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* FMOD always operates on little endian frames? */
4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    obt_as.endianness = 0;
4348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    audio_pcm_init_info (&hw->info, &obt_as);
4358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bits16 = (mode & FSOUND_16BITS) != 0;
4368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hw->samples = conf.nb_samples;
4378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
4388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void fmod_fini_in (HWVoiceIn *hw)
4418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    FMODVoiceIn *fmd = (FMODVoiceIn *) hw;
4438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (fmd->fmod_sample) {
4458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        FSOUND_Record_Stop ();
4468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        FSOUND_Sample_Free (fmd->fmod_sample);
4478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        fmd->fmod_sample = 0;
4488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int fmod_run_in (HWVoiceIn *hw)
4528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    FMODVoiceIn *fmd = (FMODVoiceIn *) hw;
4548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int hwshift = hw->info.shift;
4558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int live, dead, new_pos, len;
4568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned int blen1 = 0, blen2 = 0;
4578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned int len1, len2;
4588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned int decr;
4598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    void *p1, *p2;
4608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    live = audio_pcm_hw_get_live_in (hw);
4628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dead = hw->samples - live;
4638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!dead) {
4648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
4658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    new_pos = FSOUND_Record_GetPosition ();
4688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (new_pos < 0) {
4698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        fmod_logerr ("Could not get recording position\n");
4708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
4718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len = audio_ring_dist (new_pos,  hw->wpos, hw->samples);
4748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!len) {
4758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
4768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len = audio_MIN (len, dead);
4788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (fmod_lock_sample (fmd->fmod_sample, &fmd->hw.info,
4808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          hw->wpos, len,
4818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          &p1, &p2,
4828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          &blen1, &blen2)) {
4838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
4848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len1 = blen1 >> hwshift;
4878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len2 = blen2 >> hwshift;
4888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    decr = len1 + len2;
4898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (p1 && blen1) {
4918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hw->conv (hw->conv_buf + hw->wpos, p1, len1, &nominal_volume);
4928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (p2 && len2) {
4948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hw->conv (hw->conv_buf, p2, len2, &nominal_volume);
4958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    fmod_unlock_sample (fmd->fmod_sample, p1, p2, blen1, blen2);
4988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hw->wpos = (hw->wpos + decr) % hw->samples;
4998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return decr;
5008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic struct {
5038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *name;
5048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int type;
5058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} drvtab[] = {
5065d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    { .name = "none",   .type = FSOUND_OUTPUT_NOSOUND },
5078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
5085d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    { .name = "winmm",  .type = FSOUND_OUTPUT_WINMM   },
5095d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    { .name = "dsound", .type = FSOUND_OUTPUT_DSOUND  },
5105d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    { .name = "a3d",    .type = FSOUND_OUTPUT_A3D     },
5115d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    { .name = "asio",   .type = FSOUND_OUTPUT_ASIO    },
5128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
5138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef __linux__
5145d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    { .name = "oss",    .type = FSOUND_OUTPUT_OSS     },
5155d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    { .name = "alsa",   .type = FSOUND_OUTPUT_ALSA    },
5165d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    { .name = "esd",    .type = FSOUND_OUTPUT_ESD     },
5178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef __APPLE__
5195d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    { .name = "mac",    .type = FSOUND_OUTPUT_MAC     },
5208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if 0
5225d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    { .name = "xbox",   .type = FSOUND_OUTPUT_XBOX    },
5235d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    { .name = "ps2",    .type = FSOUND_OUTPUT_PS2     },
5245d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    { .name = "gcube",  .type = FSOUND_OUTPUT_GC      },
5258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
5265d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    { .name = "none-realtime", .type = FSOUND_OUTPUT_NOSOUND_NONREALTIME }
5278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
5288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void *fmod_audio_init (void)
5308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    size_t i;
5328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    double ver;
5338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int status;
5348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int output_type = -1;
5358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *drv = conf.drvname;
5368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ver = FSOUND_GetVersion ();
5388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ver < FMOD_VERSION) {
5398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dolog ("Wrong FMOD version %f, need at least %f\n", ver, FMOD_VERSION);
5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return NULL;
5418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef __linux__
5448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ver < 3.75) {
5458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dolog ("FMOD before 3.75 has bug preventing ADC from working\n"
5468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               "ADC will be disabled.\n");
5478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        conf.broken_adc = 1;
5488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
5508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (drv) {
5528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int found = 0;
5535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        for (i = 0; i < ARRAY_SIZE (drvtab); i++) {
5548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!strcmp (drv, drvtab[i].name)) {
5558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                output_type = drvtab[i].type;
5568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                found = 1;
5578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
5588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
5598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!found) {
5618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dolog ("Unknown FMOD driver `%s'\n", drv);
5628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dolog ("Valid drivers:\n");
5635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            for (i = 0; i < ARRAY_SIZE (drvtab); i++) {
5648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                dolog ("  %s\n", drvtab[i].name);
5658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
5668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (output_type != -1) {
5708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        status = FSOUND_SetOutput (output_type);
5718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!status) {
5728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            fmod_logerr ("FSOUND_SetOutput(%d) failed\n", output_type);
5738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return NULL;
5748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (conf.bufsize) {
5788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        status = FSOUND_SetBufferSize (conf.bufsize);
5798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!status) {
5808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            fmod_logerr ("FSOUND_SetBufferSize (%d) failed\n", conf.bufsize);
5818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    status = FSOUND_Init (conf.freq, conf.nb_channels, 0);
5858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!status) {
5868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        fmod_logerr ("FSOUND_Init failed\n");
5878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return NULL;
5888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return &conf;
5918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int fmod_read (SWVoiceIn *sw, void *buf, int size)
5948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return audio_pcm_sw_read (sw, buf, size);
5968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int fmod_ctl_in (HWVoiceIn *hw, int cmd, ...)
5998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int status;
6018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    FMODVoiceIn *fmd = (FMODVoiceIn *) hw;
6028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (cmd) {
6048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case VOICE_ENABLE:
6058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        status = FSOUND_Record_StartSample (fmd->fmod_sample, 1);
6068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!status) {
6078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            fmod_logerr ("Failed to start recording\n");
6088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
6098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
6108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case VOICE_DISABLE:
6128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        status = FSOUND_Record_Stop ();
6138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!status) {
6148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            fmod_logerr ("Failed to stop recording\n");
6158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
6168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
6178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
6198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void fmod_audio_fini (void *opaque)
6228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    (void) opaque;
6248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    FSOUND_Close ();
6258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic struct audio_option fmod_options[] = {
6285d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    {
6295d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .name  = "DRV",
6305d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .tag   = AUD_OPT_STR,
6315d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .valp  = &conf.drvname,
6325d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .descr = "FMOD driver"
6335d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    },
6345d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    {
6355d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .name  = "FREQ",
6365d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .tag   = AUD_OPT_INT,
6375d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .valp  = &conf.freq,
6385d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .descr = "Default frequency"
6395d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    },
6405d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    {
6415d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .name  = "SAMPLES",
6425d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .tag   = AUD_OPT_INT,
6435d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .valp  = &conf.nb_samples,
6445d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .descr = "Buffer size in samples"
6455d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    },
6465d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    {
6475d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .name  = "CHANNELS",
6485d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .tag   = AUD_OPT_INT,
6495d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .valp  = &conf.nb_channels,
6505d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .descr = "Number of default channels (1 - mono, 2 - stereo)"
6515d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    },
6525d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    {
6535d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .name  = "BUFSIZE",
6545d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .tag   = AUD_OPT_INT,
6555d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .valp  = &conf.bufsize,
6565d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .descr = "(undocumented)"
6575d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    },
6585d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    { /* End of list */ }
6598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
6608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic struct audio_pcm_ops fmod_pcm_ops = {
6625d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .init_out = fmod_init_out,
6635d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .fini_out = fmod_fini_out,
6645d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .run_out  = fmod_run_out,
6655d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .write    = fmod_write,
6665d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .ctl_out  = fmod_ctl_out,
6675d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner
6685d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .init_in  = fmod_init_in,
6695d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .fini_in  = fmod_fini_in,
6705d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .run_in   = fmod_run_in,
6715d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .read     = fmod_read,
6725d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .ctl_in   = fmod_ctl_in
6738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
6748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct audio_driver fmod_audio_driver = {
6765d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .name           = "fmod",
6775d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .descr          = "FMOD 3.xx http://www.fmod.org",
6785d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .options        = fmod_options,
6795d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .init           = fmod_audio_init,
6805d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .fini           = fmod_audio_fini,
6815d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .pcm_ops        = &fmod_pcm_ops,
6825d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .can_be_default = 1,
6835d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .max_voices_out = INT_MAX,
6845d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .max_voices_in  = INT_MAX,
6855d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .voice_size_out = sizeof (FMODVoiceOut),
6865d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .voice_size_in  = sizeof (FMODVoiceIn)
6878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
688