qemu/audio/noaudio.c
<<
>>
Prefs
   1/*
   2 * QEMU Timer based audio emulation
   3 *
   4 * Copyright (c) 2004-2005 Vassili Karpov (malc)
   5 *
   6 * Permission is hereby granted, free of charge, to any person obtaining a copy
   7 * of this software and associated documentation files (the "Software"), to deal
   8 * in the Software without restriction, including without limitation the rights
   9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 * copies of the Software, and to permit persons to whom the Software is
  11 * furnished to do so, subject to the following conditions:
  12 *
  13 * The above copyright notice and this permission notice shall be included in
  14 * all copies or substantial portions of the Software.
  15 *
  16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 * THE SOFTWARE.
  23 */
  24#include "qemu-common.h"
  25#include "audio.h"
  26#include "qemu-timer.h"
  27
  28#define AUDIO_CAP "noaudio"
  29#include "audio_int.h"
  30
  31typedef struct NoVoiceOut {
  32    HWVoiceOut hw;
  33    int64_t old_ticks;
  34} NoVoiceOut;
  35
  36typedef struct NoVoiceIn {
  37    HWVoiceIn hw;
  38    int64_t old_ticks;
  39} NoVoiceIn;
  40
  41static int no_run_out (HWVoiceOut *hw, int live)
  42{
  43    NoVoiceOut *no = (NoVoiceOut *) hw;
  44    int decr, samples;
  45    int64_t now;
  46    int64_t ticks;
  47    int64_t bytes;
  48
  49    now = qemu_get_clock_ns (vm_clock);
  50    ticks = now - no->old_ticks;
  51    bytes = muldiv64 (ticks, hw->info.bytes_per_second, get_ticks_per_sec ());
  52    bytes = audio_MIN (bytes, INT_MAX);
  53    samples = bytes >> hw->info.shift;
  54
  55    no->old_ticks = now;
  56    decr = audio_MIN (live, samples);
  57    hw->rpos = (hw->rpos + decr) % hw->samples;
  58    return decr;
  59}
  60
  61static int no_write (SWVoiceOut *sw, void *buf, int len)
  62{
  63    return audio_pcm_sw_write (sw, buf, len);
  64}
  65
  66static int no_init_out (HWVoiceOut *hw, struct audsettings *as)
  67{
  68    audio_pcm_init_info (&hw->info, as);
  69    hw->samples = 1024;
  70    return 0;
  71}
  72
  73static void no_fini_out (HWVoiceOut *hw)
  74{
  75    (void) hw;
  76}
  77
  78static int no_ctl_out (HWVoiceOut *hw, int cmd, ...)
  79{
  80    (void) hw;
  81    (void) cmd;
  82    return 0;
  83}
  84
  85static int no_init_in (HWVoiceIn *hw, struct audsettings *as)
  86{
  87    audio_pcm_init_info (&hw->info, as);
  88    hw->samples = 1024;
  89    return 0;
  90}
  91
  92static void no_fini_in (HWVoiceIn *hw)
  93{
  94    (void) hw;
  95}
  96
  97static int no_run_in (HWVoiceIn *hw)
  98{
  99    NoVoiceIn *no = (NoVoiceIn *) hw;
 100    int live = audio_pcm_hw_get_live_in (hw);
 101    int dead = hw->samples - live;
 102    int samples = 0;
 103
 104    if (dead) {
 105        int64_t now = qemu_get_clock_ns (vm_clock);
 106        int64_t ticks = now - no->old_ticks;
 107        int64_t bytes =
 108            muldiv64 (ticks, hw->info.bytes_per_second, get_ticks_per_sec ());
 109
 110        no->old_ticks = now;
 111        bytes = audio_MIN (bytes, INT_MAX);
 112        samples = bytes >> hw->info.shift;
 113        samples = audio_MIN (samples, dead);
 114    }
 115    return samples;
 116}
 117
 118static int no_read (SWVoiceIn *sw, void *buf, int size)
 119{
 120    /* use custom code here instead of audio_pcm_sw_read() to avoid
 121     * useless resampling/mixing */
 122    int samples = size >> sw->info.shift;
 123    int total = sw->hw->total_samples_captured - sw->total_hw_samples_acquired;
 124    int to_clear = audio_MIN (samples, total);
 125    sw->total_hw_samples_acquired += total;
 126    audio_pcm_info_clear_buf (&sw->info, buf, to_clear);
 127    return to_clear << sw->info.shift;
 128}
 129
 130static int no_ctl_in (HWVoiceIn *hw, int cmd, ...)
 131{
 132    (void) hw;
 133    (void) cmd;
 134    return 0;
 135}
 136
 137static void *no_audio_init (void)
 138{
 139    return &no_audio_init;
 140}
 141
 142static void no_audio_fini (void *opaque)
 143{
 144    (void) opaque;
 145}
 146
 147static struct audio_pcm_ops no_pcm_ops = {
 148    .init_out = no_init_out,
 149    .fini_out = no_fini_out,
 150    .run_out  = no_run_out,
 151    .write    = no_write,
 152    .ctl_out  = no_ctl_out,
 153
 154    .init_in  = no_init_in,
 155    .fini_in  = no_fini_in,
 156    .run_in   = no_run_in,
 157    .read     = no_read,
 158    .ctl_in   = no_ctl_in
 159};
 160
 161struct audio_driver no_audio_driver = {
 162    .name           = "none",
 163    .descr          = "Timer based audio emulation",
 164    .options        = NULL,
 165    .init           = no_audio_init,
 166    .fini           = no_audio_fini,
 167    .pcm_ops        = &no_pcm_ops,
 168    .can_be_default = 1,
 169    .max_voices_out = INT_MAX,
 170    .max_voices_in  = INT_MAX,
 171    .voice_size_out = sizeof (NoVoiceOut),
 172    .voice_size_in  = sizeof (NoVoiceIn)
 173};
 174