Home | History | Annotate | Download | only in audio
      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 
     31 typedef struct NoVoiceOut {
     32     HWVoiceOut hw;
     33     int64_t old_ticks;
     34 } NoVoiceOut;
     35 
     36 typedef struct NoVoiceIn {
     37     HWVoiceIn hw;
     38     int64_t old_ticks;
     39 } NoVoiceIn;
     40 
     41 static int no_run_out (HWVoiceOut *hw)
     42 {
     43     NoVoiceOut *no = (NoVoiceOut *) hw;
     44     int live, decr, samples;
     45     int64_t now;
     46     int64_t ticks;
     47     int64_t bytes;
     48 
     49     live = audio_pcm_hw_get_live_out (&no->hw);
     50     if (!live) {
     51         return 0;
     52     }
     53 
     54     now = qemu_get_clock (vm_clock);
     55     ticks = now - no->old_ticks;
     56     bytes = muldiv64 (ticks, hw->info.bytes_per_second, get_ticks_per_sec ());
     57     bytes = audio_MIN (bytes, INT_MAX);
     58     samples = bytes >> hw->info.shift;
     59 
     60     no->old_ticks = now;
     61     decr = audio_MIN (live, samples);
     62     hw->rpos = (hw->rpos + decr) % hw->samples;
     63     return decr;
     64 }
     65 
     66 static int no_write (SWVoiceOut *sw, void *buf, int len)
     67 {
     68     return audio_pcm_sw_write (sw, buf, len);
     69 }
     70 
     71 static int no_init_out (HWVoiceOut *hw, struct audsettings *as)
     72 {
     73     audio_pcm_init_info (&hw->info, as);
     74     hw->samples = 1024;
     75     return 0;
     76 }
     77 
     78 static void no_fini_out (HWVoiceOut *hw)
     79 {
     80     (void) hw;
     81 }
     82 
     83 static int no_ctl_out (HWVoiceOut *hw, int cmd, ...)
     84 {
     85     (void) hw;
     86     (void) cmd;
     87     return 0;
     88 }
     89 
     90 static int no_init_in (HWVoiceIn *hw, struct audsettings *as)
     91 {
     92     audio_pcm_init_info (&hw->info, as);
     93     hw->samples = 1024;
     94     return 0;
     95 }
     96 
     97 static void no_fini_in (HWVoiceIn *hw)
     98 {
     99     (void) hw;
    100 }
    101 
    102 static int no_run_in (HWVoiceIn *hw)
    103 {
    104     NoVoiceIn *no = (NoVoiceIn *) hw;
    105     int live = audio_pcm_hw_get_live_in (hw);
    106     int dead = hw->samples - live;
    107     int samples = 0;
    108 
    109     if (dead) {
    110         int64_t now = qemu_get_clock (vm_clock);
    111         int64_t ticks = now - no->old_ticks;
    112         int64_t bytes =
    113             muldiv64 (ticks, hw->info.bytes_per_second, get_ticks_per_sec ());
    114 
    115         no->old_ticks = now;
    116         bytes = audio_MIN (bytes, INT_MAX);
    117         samples = bytes >> hw->info.shift;
    118         samples = audio_MIN (samples, dead);
    119     }
    120     return samples;
    121 }
    122 
    123 static int no_read (SWVoiceIn *sw, void *buf, int size)
    124 {
    125     int samples = size >> sw->info.shift;
    126     int total = sw->hw->total_samples_captured - sw->total_hw_samples_acquired;
    127     int to_clear = audio_MIN (samples, total);
    128     audio_pcm_info_clear_buf (&sw->info, buf, to_clear);
    129     return to_clear;
    130 }
    131 
    132 static int no_ctl_in (HWVoiceIn *hw, int cmd, ...)
    133 {
    134     (void) hw;
    135     (void) cmd;
    136     return 0;
    137 }
    138 
    139 static void *no_audio_init (void)
    140 {
    141     return &no_audio_init;
    142 }
    143 
    144 static void no_audio_fini (void *opaque)
    145 {
    146     (void) opaque;
    147 }
    148 
    149 static struct audio_pcm_ops no_pcm_ops = {
    150     no_init_out,
    151     no_fini_out,
    152     no_run_out,
    153     no_write,
    154     no_ctl_out,
    155 
    156     no_init_in,
    157     no_fini_in,
    158     no_run_in,
    159     no_read,
    160     no_ctl_in
    161 };
    162 
    163 struct audio_driver no_audio_driver = {
    164     INIT_FIELD (name           = ) "none",
    165     INIT_FIELD (descr          = ) "disabled audio",
    166     INIT_FIELD (options        = ) NULL,
    167     INIT_FIELD (init           = ) no_audio_init,
    168     INIT_FIELD (fini           = ) no_audio_fini,
    169     INIT_FIELD (pcm_ops        = ) &no_pcm_ops,
    170     INIT_FIELD (can_be_default = ) 1,
    171     INIT_FIELD (max_voices_out = ) INT_MAX,
    172     INIT_FIELD (max_voices_in  = ) INT_MAX,
    173     INIT_FIELD (voice_size_out = ) sizeof (NoVoiceOut),
    174     INIT_FIELD (voice_size_in  = ) sizeof (NoVoiceIn)
    175 };
    176