15f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/*
25f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * QEMU Timer based audio emulation
35f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer *
45f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * Copyright (c) 2004-2005 Vassili Karpov (malc)
50bc735ffcfb223c0186419547abaa5c84482663eChris Lattner *
60bc735ffcfb223c0186419547abaa5c84482663eChris Lattner * Permission is hereby granted, free of charge, to any person obtaining a copy
75f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * of this software and associated documentation files (the "Software"), to deal
85f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * in the Software without restriction, including without limitation the rights
95f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * copies of the Software, and to permit persons to whom the Software is
115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * furnished to do so, subject to the following conditions:
125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer *
135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * The above copyright notice and this permission notice shall be included in
145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * all copies or substantial portions of the Software.
155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer *
165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18136f93a2b660fc780fc2dba82a6f42ca4dc9164aChris Lattner * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19136f93a2b660fc780fc2dba82a6f42ca4dc9164aChris Lattner * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * THE SOFTWARE.
235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer */
245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "qemu-common.h"
255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "audio.h"
265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "qemu-timer.h"
275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#define AUDIO_CAP "noaudio"
295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "audio_int.h"
305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencertypedef struct NoVoiceOut {
325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    HWVoiceOut hw;
335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    int64_t old_ticks;
345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} NoVoiceOut;
355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencertypedef struct NoVoiceIn {
375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    HWVoiceIn hw;
385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    int64_t old_ticks;
395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} NoVoiceIn;
405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic int no_run_out (HWVoiceOut *hw, int live)
425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{
435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    NoVoiceOut *no = (NoVoiceOut *) hw;
445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    int decr, samples;
455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    int64_t now;
465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    int64_t ticks;
475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    int64_t bytes;
485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    now = qemu_get_clock (vm_clock);
505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    ticks = now - no->old_ticks;
515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    bytes = muldiv64 (ticks, hw->info.bytes_per_second, get_ticks_per_sec ());
525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    bytes = audio_MIN (bytes, INT_MAX);
535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    samples = bytes >> hw->info.shift;
545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    no->old_ticks = now;
565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    decr = audio_MIN (live, samples);
575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    hw->rpos = (hw->rpos + decr) % hw->samples;
585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return decr;
595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic int no_write (SWVoiceOut *sw, void *buf, int len)
625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{
635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return audio_pcm_sw_write (sw, buf, len);
645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic int no_init_out (HWVoiceOut *hw, struct audsettings *as)
675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{
685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    audio_pcm_init_info (&hw->info, as);
695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    hw->samples = 1024;
705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return 0;
715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic void no_fini_out (HWVoiceOut *hw)
745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{
755f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    (void) hw;
765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic int no_ctl_out (HWVoiceOut *hw, int cmd, ...)
795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{
805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    (void) hw;
815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    (void) cmd;
825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return 0;
835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic int no_init_in (HWVoiceIn *hw, struct audsettings *as)
865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{
875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    audio_pcm_init_info (&hw->info, as);
885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    hw->samples = 1024;
895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return 0;
90b8128140956c6f8f0ab143818775a81f4b4aa477Chris Lattner}
915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic void no_fini_in (HWVoiceIn *hw)
935f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{
945f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    (void) hw;
955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
9698be4943e8dc4f3905629a7102668960873cf863Chris Lattner
979c728dc4d8da89c73fcae74c9e72d7a83ffd7b6dTed Kremenekstatic int no_run_in (HWVoiceIn *hw)
985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{
995f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    NoVoiceIn *no = (NoVoiceIn *) hw;
1005f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    int live = audio_pcm_hw_get_live_in (hw);
1015f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    int dead = hw->samples - live;
1025f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    int samples = 0;
1035f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1045f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    if (dead) {
1055f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        int64_t now = qemu_get_clock (vm_clock);
1065f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        int64_t ticks = now - no->old_ticks;
1075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        int64_t bytes =
1085f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer            muldiv64 (ticks, hw->info.bytes_per_second, get_ticks_per_sec ());
1095f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        no->old_ticks = now;
1115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        bytes = audio_MIN (bytes, INT_MAX);
1125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        samples = bytes >> hw->info.shift;
1135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        samples = audio_MIN (samples, dead);
1145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    }
1155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return samples;
1165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
1175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic int no_read (SWVoiceIn *sw, void *buf, int size)
1195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{
1205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    int samples = size >> sw->info.shift;
1215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    int total = sw->hw->total_samples_captured - sw->total_hw_samples_acquired;
1225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    int to_clear = audio_MIN (samples, total);
1235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    audio_pcm_info_clear_buf (&sw->info, buf, to_clear);
1245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return to_clear;
12598be4943e8dc4f3905629a7102668960873cf863Chris Lattner}
1269c728dc4d8da89c73fcae74c9e72d7a83ffd7b6dTed Kremenek
1275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic int no_ctl_in (HWVoiceIn *hw, int cmd, ...)
1285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{
1295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    (void) hw;
1305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    (void) cmd;
1315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return 0;
1325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
1335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic void *no_audio_init (void)
1355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{
1365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return &no_audio_init;
1375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
1385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic void no_audio_fini (void *opaque)
1405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{
1415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    (void) opaque;
1425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
1435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic struct audio_pcm_ops no_pcm_ops = {
1455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    .init_out = no_init_out,
1465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    .fini_out = no_fini_out,
1475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    .run_out  = no_run_out,
1485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    .write    = no_write,
1495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    .ctl_out  = no_ctl_out,
1505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    .init_in  = no_init_in,
1525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    .fini_in  = no_fini_in,
1535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    .run_in   = no_run_in,
1545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    .read     = no_read,
1555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    .ctl_in   = no_ctl_in
1565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer};
1575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstruct audio_driver no_audio_driver = {
1595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    .name           = "none",
1605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    .descr          = "Timer based audio emulation",
1615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    .options        = NULL,
1625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    .init           = no_audio_init,
1635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    .fini           = no_audio_fini,
1645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    .pcm_ops        = &no_pcm_ops,
1655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    .can_be_default = 1,
1665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    .max_voices_out = INT_MAX,
1675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    .max_voices_in  = INT_MAX,
1685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    .voice_size_out = sizeof (NoVoiceOut),
1695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    .voice_size_in  = sizeof (NoVoiceIn)
1705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer};
1715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer