]> git.proxmox.com Git - mirror_qemu.git/blobdiff - audio/noaudio.c
spapr: fix memory hot-unplugging
[mirror_qemu.git] / audio / noaudio.c
index aa3581168d8dd07aabd961e1da87bf90bb2e3afb..9ca9eaf01fcb36a5f1b6f924c96da811fd857e3e 100644 (file)
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "vl.h"
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "qemu/host-utils.h"
+#include "audio.h"
+#include "qemu/timer.h"
 
 #define AUDIO_CAP "noaudio"
 #include "audio_int.h"
@@ -36,25 +40,19 @@ typedef struct NoVoiceIn {
     int64_t old_ticks;
 } NoVoiceIn;
 
-static int no_run_out (HWVoiceOut *hw)
+static int no_run_out (HWVoiceOut *hw, int live)
 {
     NoVoiceOut *no = (NoVoiceOut *) hw;
-    int live, decr, samples;
-    int64_t now = qemu_get_clock (vm_clock);
-    int64_t ticks = now - no->old_ticks;
-    int64_t bytes = (ticks * hw->info.bytes_per_second) / ticks_per_sec;
-
-    if (bytes > INT_MAX) {
-        samples = INT_MAX >> hw->info.shift;
-    }
-    else {
-        samples = bytes >> hw->info.shift;
-    }
-
-    live = audio_pcm_hw_get_live_out (&no->hw);
-    if (!live) {
-        return 0;
-    }
+    int decr, samples;
+    int64_t now;
+    int64_t ticks;
+    int64_t bytes;
+
+    now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+    ticks = now - no->old_ticks;
+    bytes = muldiv64(ticks, hw->info.bytes_per_second, NANOSECONDS_PER_SECOND);
+    bytes = audio_MIN(bytes, INT_MAX);
+    samples = bytes >> hw->info.shift;
 
     no->old_ticks = now;
     decr = audio_MIN (live, samples);
@@ -64,12 +62,12 @@ static int no_run_out (HWVoiceOut *hw)
 
 static int no_write (SWVoiceOut *sw, void *buf, int len)
 {
-    return audio_pcm_sw_write (sw, buf, len);
+    return audio_pcm_sw_write(sw, buf, len);
 }
 
-static int no_init_out (HWVoiceOut *hw, audsettings_t *as)
+static int no_init_out(HWVoiceOut *hw, struct audsettings *as, void *drv_opaque)
 {
-    audio_pcm_init_info (&hw->info, as, 0);
+    audio_pcm_init_info (&hw->info, as);
     hw->samples = 1024;
     return 0;
 }
@@ -86,9 +84,9 @@ static int no_ctl_out (HWVoiceOut *hw, int cmd, ...)
     return 0;
 }
 
-static int no_init_in (HWVoiceIn *hw, audsettings_t *as)
+static int no_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
 {
-    audio_pcm_init_info (&hw->info, as, 0);
+    audio_pcm_init_info (&hw->info, as);
     hw->samples = 1024;
     return 0;
 }
@@ -101,27 +99,34 @@ static void no_fini_in (HWVoiceIn *hw)
 static int no_run_in (HWVoiceIn *hw)
 {
     NoVoiceIn *no = (NoVoiceIn *) hw;
-    int64_t now = qemu_get_clock (vm_clock);
-    int64_t ticks = now - no->old_ticks;
-    int64_t bytes = (ticks * hw->info.bytes_per_second) / ticks_per_sec;
     int live = audio_pcm_hw_get_live_in (hw);
     int dead = hw->samples - live;
-    int samples;
+    int samples = 0;
 
-    bytes = audio_MIN (bytes, INT_MAX);
-    samples = bytes >> hw->info.shift;
-    samples = audio_MIN (samples, dead);
+    if (dead) {
+        int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+        int64_t ticks = now - no->old_ticks;
+        int64_t bytes =
+            muldiv64(ticks, hw->info.bytes_per_second, NANOSECONDS_PER_SECOND);
 
+        no->old_ticks = now;
+        bytes = audio_MIN (bytes, INT_MAX);
+        samples = bytes >> hw->info.shift;
+        samples = audio_MIN (samples, dead);
+    }
     return samples;
 }
 
 static int no_read (SWVoiceIn *sw, void *buf, int size)
 {
+    /* use custom code here instead of audio_pcm_sw_read() to avoid
+     * useless resampling/mixing */
     int samples = size >> sw->info.shift;
     int total = sw->hw->total_samples_captured - sw->total_hw_samples_acquired;
     int to_clear = audio_MIN (samples, total);
+    sw->total_hw_samples_acquired += total;
     audio_pcm_info_clear_buf (&sw->info, buf, to_clear);
-    return to_clear;
+    return to_clear << sw->info.shift;
 }
 
 static int no_ctl_in (HWVoiceIn *hw, int cmd, ...)
@@ -142,29 +147,29 @@ static void no_audio_fini (void *opaque)
 }
 
 static struct audio_pcm_ops no_pcm_ops = {
-    no_init_out,
-    no_fini_out,
-    no_run_out,
-    no_write,
-    no_ctl_out,
-
-    no_init_in,
-    no_fini_in,
-    no_run_in,
-    no_read,
-    no_ctl_in
+    .init_out = no_init_out,
+    .fini_out = no_fini_out,
+    .run_out  = no_run_out,
+    .write    = no_write,
+    .ctl_out  = no_ctl_out,
+
+    .init_in  = no_init_in,
+    .fini_in  = no_fini_in,
+    .run_in   = no_run_in,
+    .read     = no_read,
+    .ctl_in   = no_ctl_in
 };
 
 struct audio_driver no_audio_driver = {
-    INIT_FIELD (name           = ) "none",
-    INIT_FIELD (descr          = ) "Timer based audio emulation",
-    INIT_FIELD (options        = ) NULL,
-    INIT_FIELD (init           = ) no_audio_init,
-    INIT_FIELD (fini           = ) no_audio_fini,
-    INIT_FIELD (pcm_ops        = ) &no_pcm_ops,
-    INIT_FIELD (can_be_default = ) 1,
-    INIT_FIELD (max_voices_out = ) INT_MAX,
-    INIT_FIELD (max_voices_in  = ) INT_MAX,
-    INIT_FIELD (voice_size_out = ) sizeof (NoVoiceOut),
-    INIT_FIELD (voice_size_in  = ) sizeof (NoVoiceIn)
+    .name           = "none",
+    .descr          = "Timer based audio emulation",
+    .options        = NULL,
+    .init           = no_audio_init,
+    .fini           = no_audio_fini,
+    .pcm_ops        = &no_pcm_ops,
+    .can_be_default = 1,
+    .max_voices_out = INT_MAX,
+    .max_voices_in  = INT_MAX,
+    .voice_size_out = sizeof (NoVoiceOut),
+    .voice_size_in  = sizeof (NoVoiceIn)
 };