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