xref: /qemu/audio/audio_int.h (revision 69a80279)
1fb065187Sbellard /*
2fb065187Sbellard  * QEMU Audio subsystem header
3fb065187Sbellard  *
41d14ffa9Sbellard  * Copyright (c) 2003-2005 Vassili Karpov (malc)
5fb065187Sbellard  *
6fb065187Sbellard  * Permission is hereby granted, free of charge, to any person obtaining a copy
7fb065187Sbellard  * of this software and associated documentation files (the "Software"), to deal
8fb065187Sbellard  * in the Software without restriction, including without limitation the rights
9fb065187Sbellard  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10fb065187Sbellard  * copies of the Software, and to permit persons to whom the Software is
11fb065187Sbellard  * furnished to do so, subject to the following conditions:
12fb065187Sbellard  *
13fb065187Sbellard  * The above copyright notice and this permission notice shall be included in
14fb065187Sbellard  * all copies or substantial portions of the Software.
15fb065187Sbellard  *
16fb065187Sbellard  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17fb065187Sbellard  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18fb065187Sbellard  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19fb065187Sbellard  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20fb065187Sbellard  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21fb065187Sbellard  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22fb065187Sbellard  * THE SOFTWARE.
23fb065187Sbellard  */
24175de524SMarkus Armbruster 
25fb065187Sbellard #ifndef QEMU_AUDIO_INT_H
26fb065187Sbellard #define QEMU_AUDIO_INT_H
27fb065187Sbellard 
281ef1ec2aSGerd Hoffmann #ifdef CONFIG_AUDIO_COREAUDIO
291d14ffa9Sbellard #define FLOAT_MIXENG
301d14ffa9Sbellard /* #define RECIPROCAL */
311d14ffa9Sbellard #endif
321d14ffa9Sbellard #include "mixeng.h"
33fb065187Sbellard 
34739362d4SMarc-André Lureau #ifdef CONFIG_GIO
35739362d4SMarc-André Lureau #include <gio/gio.h>
36739362d4SMarc-André Lureau #endif
37739362d4SMarc-André Lureau 
381d14ffa9Sbellard struct audio_pcm_ops;
391d14ffa9Sbellard 
401d14ffa9Sbellard struct audio_callback {
411d14ffa9Sbellard     void *opaque;
42cb4f03e8Smalc     audio_callback_fn fn;
431d14ffa9Sbellard };
441d14ffa9Sbellard 
451d14ffa9Sbellard struct audio_pcm_info {
461d14ffa9Sbellard     int bits;
47ed2a4a79SKővágó, Zoltán     bool is_signed;
48ed2a4a79SKővágó, Zoltán     bool is_float;
491d14ffa9Sbellard     int freq;
501d14ffa9Sbellard     int nchannels;
512b9cce8cSKővágó, Zoltán     int bytes_per_frame;
521d14ffa9Sbellard     int bytes_per_second;
53d929eba5Sbellard     int swap_endianness;
541d14ffa9Sbellard };
551d14ffa9Sbellard 
56526fb058SKővágó, Zoltán typedef struct AudioState AudioState;
57ec36b695Sbellard typedef struct SWVoiceCap SWVoiceCap;
58ec36b695Sbellard 
59dc88e38fSKővágó, Zoltán typedef struct STSampleBuffer {
60dc88e38fSKővágó, Zoltán     size_t pos, size;
618dbd3d17SVolker Rümelin     st_sample *buffer;
62dc88e38fSKővágó, Zoltán } STSampleBuffer;
63dc88e38fSKővágó, Zoltán 
641d14ffa9Sbellard typedef struct HWVoiceOut {
65526fb058SKővágó, Zoltán     AudioState *s;
66fb065187Sbellard     int enabled;
67713a98f8Smalc     int poll_mode;
68fb065187Sbellard     int pending_disable;
691d14ffa9Sbellard     struct audio_pcm_info info;
70fb065187Sbellard 
71fb065187Sbellard     f_sample *clip;
721d14ffa9Sbellard     uint64_t ts_helper;
73fb065187Sbellard 
748dbd3d17SVolker Rümelin     STSampleBuffer mix_buf;
75ff095e52SKővágó, Zoltán     void *buf_emul;
76ff095e52SKővágó, Zoltán     size_t pos_emul, pending_emul, size_emul;
77fb065187Sbellard 
787520462bSKővágó, Zoltán     size_t samples;
7972cf2d4fSBlue Swirl     QLIST_HEAD (sw_out_listhead, SWVoiceOut) sw_head;
8072cf2d4fSBlue Swirl     QLIST_HEAD (sw_cap_listhead, SWVoiceCap) cap_head;
8135f4b58cSblueswir1     struct audio_pcm_ops *pcm_ops;
8272cf2d4fSBlue Swirl     QLIST_ENTRY (HWVoiceOut) entries;
831d14ffa9Sbellard } HWVoiceOut;
84fb065187Sbellard 
851d14ffa9Sbellard typedef struct HWVoiceIn {
86526fb058SKővágó, Zoltán     AudioState *s;
871d14ffa9Sbellard     int enabled;
88713a98f8Smalc     int poll_mode;
891d14ffa9Sbellard     struct audio_pcm_info info;
90fb065187Sbellard 
91fb065187Sbellard     t_sample *conv;
92fb065187Sbellard 
937520462bSKővágó, Zoltán     size_t total_samples_captured;
941d14ffa9Sbellard     uint64_t ts_helper;
951d14ffa9Sbellard 
968dbd3d17SVolker Rümelin     STSampleBuffer conv_buf;
97ff095e52SKővágó, Zoltán     void *buf_emul;
98ff095e52SKővágó, Zoltán     size_t pos_emul, pending_emul, size_emul;
991d14ffa9Sbellard 
1007520462bSKővágó, Zoltán     size_t samples;
10172cf2d4fSBlue Swirl     QLIST_HEAD (sw_in_listhead, SWVoiceIn) sw_head;
10235f4b58cSblueswir1     struct audio_pcm_ops *pcm_ops;
10372cf2d4fSBlue Swirl     QLIST_ENTRY (HWVoiceIn) entries;
1041d14ffa9Sbellard } HWVoiceIn;
1051d14ffa9Sbellard 
1061d14ffa9Sbellard struct SWVoiceOut {
1071a7dafceSmalc     QEMUSoundCard *card;
108526fb058SKővágó, Zoltán     AudioState *s;
1091d14ffa9Sbellard     struct audio_pcm_info info;
1101d14ffa9Sbellard     t_sample *conv;
1112c3f9a0aSVolker Rümelin     STSampleBuffer resample_buf;
112fb065187Sbellard     void *rate;
1137520462bSKővágó, Zoltán     size_t total_hw_samples_mixed;
114fb065187Sbellard     int active;
1151d14ffa9Sbellard     int empty;
1161d14ffa9Sbellard     HWVoiceOut *hw;
117fb065187Sbellard     char *name;
1181ea879e5Smalc     struct mixeng_volume vol;
1191d14ffa9Sbellard     struct audio_callback callback;
12072cf2d4fSBlue Swirl     QLIST_ENTRY (SWVoiceOut) entries;
121fb065187Sbellard };
122fb065187Sbellard 
1231d14ffa9Sbellard struct SWVoiceIn {
1241a7dafceSmalc     QEMUSoundCard *card;
125526fb058SKővágó, Zoltán     AudioState *s;
1261d14ffa9Sbellard     int active;
1271d14ffa9Sbellard     struct audio_pcm_info info;
1281d14ffa9Sbellard     void *rate;
1297520462bSKővágó, Zoltán     size_t total_hw_samples_acquired;
1302c3f9a0aSVolker Rümelin     STSampleBuffer resample_buf;
1311d14ffa9Sbellard     f_sample *clip;
1321d14ffa9Sbellard     HWVoiceIn *hw;
1331d14ffa9Sbellard     char *name;
1341ea879e5Smalc     struct mixeng_volume vol;
1351d14ffa9Sbellard     struct audio_callback callback;
13672cf2d4fSBlue Swirl     QLIST_ENTRY (SWVoiceIn) entries;
137fb065187Sbellard };
138fb065187Sbellard 
139d3893a39SGerd Hoffmann typedef struct audio_driver audio_driver;
140c0fe3827Sbellard struct audio_driver {
141c0fe3827Sbellard     const char *name;
142c0fe3827Sbellard     const char *descr;
143f6061733SPaolo Bonzini     void *(*init) (Audiodev *, Error **);
144c0fe3827Sbellard     void (*fini) (void *);
145739362d4SMarc-André Lureau #ifdef CONFIG_GIO
146e74fec9aSMarc-André Lureau     void (*set_dbus_server) (AudioState *s, GDBusObjectManagerServer *manager, bool p2p);
147739362d4SMarc-André Lureau #endif
14835f4b58cSblueswir1     struct audio_pcm_ops *pcm_ops;
149c0fe3827Sbellard     int max_voices_out;
150c0fe3827Sbellard     int max_voices_in;
1513724ab3bSVolker Rümelin     size_t voice_size_out;
1523724ab3bSVolker Rümelin     size_t voice_size_in;
153d3893a39SGerd Hoffmann     QLIST_ENTRY(audio_driver) next;
154c0fe3827Sbellard };
155c0fe3827Sbellard 
1561d14ffa9Sbellard struct audio_pcm_ops {
157ff095e52SKővágó, Zoltán     int    (*init_out)(HWVoiceOut *hw, audsettings *as, void *drv_opaque);
1581d14ffa9Sbellard     void   (*fini_out)(HWVoiceOut *hw);
159ff095e52SKővágó, Zoltán     size_t (*write)   (HWVoiceOut *hw, void *buf, size_t size);
160fdc8c5f4SVolker Rümelin     void   (*run_buffer_out)(HWVoiceOut *hw);
161ff095e52SKővágó, Zoltán     /*
1629833438eSVolker Rümelin      * Get the free output buffer size. This is an upper limit. The size
1639833438eSVolker Rümelin      * returned by function get_buffer_out may be smaller.
1649833438eSVolker Rümelin      */
1659833438eSVolker Rümelin     size_t (*buffer_get_free)(HWVoiceOut *hw);
1669833438eSVolker Rümelin     /*
167ff095e52SKővágó, Zoltán      * get a buffer that after later can be passed to put_buffer_out; optional
168ff095e52SKővágó, Zoltán      * returns the buffer, and writes it's size to size (in bytes)
169ff095e52SKővágó, Zoltán      */
170ff095e52SKővágó, Zoltán     void  *(*get_buffer_out)(HWVoiceOut *hw, size_t *size);
171ff095e52SKővágó, Zoltán     /*
172ff095e52SKővágó, Zoltán      * put back the buffer returned by get_buffer_out; optional
173ff095e52SKővágó, Zoltán      * buf must be equal the pointer returned by get_buffer_out,
174ff095e52SKővágó, Zoltán      * size may be smaller
175ff095e52SKővágó, Zoltán      */
176ff095e52SKővágó, Zoltán     size_t (*put_buffer_out)(HWVoiceOut *hw, void *buf, size_t size);
177571a8c52SKővágó, Zoltán     void   (*enable_out)(HWVoiceOut *hw, bool enable);
178cecc1e79SKővágó, Zoltán     void   (*volume_out)(HWVoiceOut *hw, Volume *vol);
179fb065187Sbellard 
180ff095e52SKővágó, Zoltán     int    (*init_in) (HWVoiceIn *hw, audsettings *as, void *drv_opaque);
1811d14ffa9Sbellard     void   (*fini_in) (HWVoiceIn *hw);
182ff095e52SKővágó, Zoltán     size_t (*read)    (HWVoiceIn *hw, void *buf, size_t size);
183a2893c83SVolker Rümelin     void   (*run_buffer_in)(HWVoiceIn *hw);
184ff095e52SKővágó, Zoltán     void  *(*get_buffer_in)(HWVoiceIn *hw, size_t *size);
185ff095e52SKővágó, Zoltán     void   (*put_buffer_in)(HWVoiceIn *hw, void *buf, size_t size);
186571a8c52SKővágó, Zoltán     void   (*enable_in)(HWVoiceIn *hw, bool enable);
187cecc1e79SKővágó, Zoltán     void   (*volume_in)(HWVoiceIn *hw, Volume *vol);
1881d14ffa9Sbellard };
189fb065187Sbellard 
190a2893c83SVolker Rümelin void audio_generic_run_buffer_in(HWVoiceIn *hw);
191ff095e52SKővágó, Zoltán void *audio_generic_get_buffer_in(HWVoiceIn *hw, size_t *size);
192ff095e52SKővágó, Zoltán void audio_generic_put_buffer_in(HWVoiceIn *hw, void *buf, size_t size);
193fdc8c5f4SVolker Rümelin void audio_generic_run_buffer_out(HWVoiceOut *hw);
1949833438eSVolker Rümelin size_t audio_generic_buffer_get_free(HWVoiceOut *hw);
195ff095e52SKővágó, Zoltán void *audio_generic_get_buffer_out(HWVoiceOut *hw, size_t *size);
196ff095e52SKővágó, Zoltán size_t audio_generic_put_buffer_out(HWVoiceOut *hw, void *buf, size_t size);
197ff095e52SKővágó, Zoltán size_t audio_generic_write(HWVoiceOut *hw, void *buf, size_t size);
198ff095e52SKővágó, Zoltán size_t audio_generic_read(HWVoiceIn *hw, void *buf, size_t size);
199ff095e52SKővágó, Zoltán 
2008ead62cfSbellard struct capture_callback {
2018ead62cfSbellard     struct audio_capture_ops ops;
2028ead62cfSbellard     void *opaque;
20372cf2d4fSBlue Swirl     QLIST_ENTRY (capture_callback) entries;
2048ead62cfSbellard };
2058ead62cfSbellard 
206ec36b695Sbellard struct CaptureVoiceOut {
2078ead62cfSbellard     HWVoiceOut hw;
2088ead62cfSbellard     void *buf;
20972cf2d4fSBlue Swirl     QLIST_HEAD (cb_listhead, capture_callback) cb_head;
21072cf2d4fSBlue Swirl     QLIST_ENTRY (CaptureVoiceOut) entries;
211ec36b695Sbellard };
212ec36b695Sbellard 
213ec36b695Sbellard struct SWVoiceCap {
214ec36b695Sbellard     SWVoiceOut sw;
215ec36b695Sbellard     CaptureVoiceOut *cap;
21672cf2d4fSBlue Swirl     QLIST_ENTRY (SWVoiceCap) entries;
217ec36b695Sbellard };
2188ead62cfSbellard 
219fd5283fbSPhilippe Mathieu-Daudé typedef struct AudioState {
220c0fe3827Sbellard     struct audio_driver *drv;
22171830221SKővágó, Zoltán     Audiodev *dev;
222c0fe3827Sbellard     void *drv_opaque;
223c0fe3827Sbellard 
224c0fe3827Sbellard     QEMUTimer *ts;
22572cf2d4fSBlue Swirl     QLIST_HEAD (card_listhead, QEMUSoundCard) card_head;
22672cf2d4fSBlue Swirl     QLIST_HEAD (hw_in_listhead, HWVoiceIn) hw_head_in;
22772cf2d4fSBlue Swirl     QLIST_HEAD (hw_out_listhead, HWVoiceOut) hw_head_out;
22872cf2d4fSBlue Swirl     QLIST_HEAD (cap_listhead, CaptureVoiceOut) cap_head;
229c0fe3827Sbellard     int nb_hw_voices_out;
230c0fe3827Sbellard     int nb_hw_voices_in;
231978dd635Smalc     int vm_running;
23271830221SKővágó, Zoltán     int64_t period_ticks;
233526fb058SKővágó, Zoltán 
234526fb058SKővágó, Zoltán     bool timer_running;
235526fb058SKővágó, Zoltán     uint64_t timer_last;
236ecd97e95SKővágó, Zoltán 
237ecd97e95SKővágó, Zoltán     QTAILQ_ENTRY(AudioState) list;
238fd5283fbSPhilippe Mathieu-Daudé } AudioState;
239c0fe3827Sbellard 
24000e07679SMichael Walle extern const struct mixeng_volume nominal_volume;
241c0fe3827Sbellard 
24271830221SKővágó, Zoltán extern const char *audio_prio_list[];
24371830221SKővágó, Zoltán 
244d3893a39SGerd Hoffmann void audio_driver_register(audio_driver *drv);
245d3893a39SGerd Hoffmann 
2461ea879e5Smalc void audio_pcm_init_info (struct audio_pcm_info *info, struct audsettings *as);
2471d14ffa9Sbellard void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len);
248fb065187Sbellard 
249c0fe3827Sbellard int audio_bug (const char *funcname, int cond);
250c0fe3827Sbellard 
25118e2c177SKővágó, Zoltán void audio_run(AudioState *s, const char *msg);
252713a98f8Smalc 
25337a54d05SVolker Rümelin const char *audio_application_name(void);
25437a54d05SVolker Rümelin 
255857271a2SKővágó, Zoltán typedef struct RateCtl {
256857271a2SKővágó, Zoltán     int64_t start_ticks;
257857271a2SKővágó, Zoltán     int64_t bytes_sent;
258857271a2SKővágó, Zoltán } RateCtl;
259857271a2SKővágó, Zoltán 
260857271a2SKővágó, Zoltán void audio_rate_start(RateCtl *rate);
26102732641SVolker Rümelin size_t audio_rate_peek_bytes(RateCtl *rate, struct audio_pcm_info *info);
26202732641SVolker Rümelin void audio_rate_add_bytes(RateCtl *rate, size_t bytes_used);
263613fe02bSVolker Rümelin size_t audio_rate_get_bytes(RateCtl *rate, struct audio_pcm_info *info,
264857271a2SKővágó, Zoltán                             size_t bytes_avail);
265857271a2SKővágó, Zoltán 
audio_ring_dist(size_t dst,size_t src,size_t len)2667520462bSKővágó, Zoltán static inline size_t audio_ring_dist(size_t dst, size_t src, size_t len)
2671d14ffa9Sbellard {
2681d14ffa9Sbellard     return (dst >= src) ? (dst - src) : (len - src + dst);
2691d14ffa9Sbellard }
2701d14ffa9Sbellard 
27118404ff1SVolker Rümelin /**
27218404ff1SVolker Rümelin  * audio_ring_posb() - returns new position in ringbuffer in backward
27318404ff1SVolker Rümelin  * direction at given distance
27418404ff1SVolker Rümelin  *
27518404ff1SVolker Rümelin  * @pos: current position in ringbuffer
27618404ff1SVolker Rümelin  * @dist: distance in ringbuffer to walk in reverse direction
27718404ff1SVolker Rümelin  * @len: size of ringbuffer
27818404ff1SVolker Rümelin  */
audio_ring_posb(size_t pos,size_t dist,size_t len)27918404ff1SVolker Rümelin static inline size_t audio_ring_posb(size_t pos, size_t dist, size_t len)
28018404ff1SVolker Rümelin {
28118404ff1SVolker Rümelin     return pos >= dist ? pos - dist : len - dist + pos;
28218404ff1SVolker Rümelin }
28318404ff1SVolker Rümelin 
28487e613eaSStefan Weil #define dolog(fmt, ...) AUD_log(AUDIO_CAP, fmt, ## __VA_ARGS__)
2851d14ffa9Sbellard 
2861d14ffa9Sbellard #ifdef DEBUG
28787e613eaSStefan Weil #define ldebug(fmt, ...) AUD_log(AUDIO_CAP, fmt, ## __VA_ARGS__)
2881d14ffa9Sbellard #else
28987e613eaSStefan Weil #define ldebug(fmt, ...) (void)0
2901d14ffa9Sbellard #endif
2911d14ffa9Sbellard 
29271830221SKővágó, Zoltán typedef struct AudiodevListEntry {
29371830221SKővágó, Zoltán     Audiodev *dev;
29471830221SKővágó, Zoltán     QSIMPLEQ_ENTRY(AudiodevListEntry) next;
29571830221SKővágó, Zoltán } AudiodevListEntry;
29671830221SKővágó, Zoltán 
29771830221SKővágó, Zoltán typedef QSIMPLEQ_HEAD(, AudiodevListEntry) AudiodevListHead;
29871830221SKővágó, Zoltán 
29971830221SKővágó, Zoltán void audio_create_pdos(Audiodev *dev);
30071830221SKővágó, Zoltán AudiodevPerDirectionOptions *audio_get_pdo_in(Audiodev *dev);
30171830221SKővágó, Zoltán AudiodevPerDirectionOptions *audio_get_pdo_out(Audiodev *dev);
30271830221SKővágó, Zoltán 
303175de524SMarkus Armbruster #endif /* QEMU_AUDIO_INT_H */
304