Commit fb065187e4ee9e0d1709b344ec01bb426ff1e43b
1 parent
bf71c9d9
audio clean up (initial patch by malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1131 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
17 changed files
with
337 additions
and
333 deletions
Makefile.target
| 1 | 1 | include config.mak |
| 2 | 2 | |
| 3 | -#After enabling Adlib and/or FMOD rebuild QEMU from scratch | |
| 4 | -#Uncomment following for adlib support | |
| 5 | -#USE_ADLIB=1 | |
| 6 | - | |
| 7 | 3 | #Uncomment following and specify proper paths/names for FMOD support |
| 8 | 4 | #USE_FMOD=1 |
| 9 | 5 | #FMOD_INCLUDE=/net/include/fmod |
| ... | ... | @@ -278,11 +274,18 @@ VL_OBJS=vl.o osdep.o block.o readline.o monitor.o pci.o console.o |
| 278 | 274 | VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o |
| 279 | 275 | |
| 280 | 276 | SOUND_HW = sb16.o |
| 281 | -AUDIODRV = audio.o ossaudio.o sdlaudio.o wavaudio.o | |
| 277 | +AUDIODRV = audio.o wavaudio.o | |
| 278 | +ifdef CONFIG_SDL | |
| 279 | +AUDIODRV += sdlaudio.o | |
| 280 | +endif | |
| 281 | +ifdef CONFIG_OSS | |
| 282 | +AUDIODRV += ossaudio.o | |
| 283 | +endif | |
| 284 | + | |
| 285 | +pc.o: DEFINES := -DUSE_SB16 $(DEFINES) | |
| 282 | 286 | |
| 283 | -ifeq ($(USE_ADLIB),1) | |
| 287 | +ifdef CONFIG_ADLIB | |
| 284 | 288 | SOUND_HW += fmopl.o adlib.o |
| 285 | -audio.o: DEFINES := -DUSE_ADLIB $(DEFINES) | |
| 286 | 289 | endif |
| 287 | 290 | |
| 288 | 291 | ifeq ($(USE_FMOD),1) | ... | ... |
audio/audio.c
| ... | ... | @@ -22,62 +22,26 @@ |
| 22 | 22 | * THE SOFTWARE. |
| 23 | 23 | */ |
| 24 | 24 | #include <assert.h> |
| 25 | -#include <limits.h> | |
| 26 | 25 | #include "vl.h" |
| 27 | 26 | |
| 28 | -#define AUDIO_CAP "audio" | |
| 29 | -#include "audio/audio.h" | |
| 30 | - | |
| 31 | 27 | #define USE_SDL_AUDIO |
| 32 | 28 | #define USE_WAV_AUDIO |
| 33 | 29 | |
| 34 | -#if defined __linux__ || (defined _BSD && !defined __APPLE__) | |
| 35 | -#define USE_OSS_AUDIO | |
| 36 | -#endif | |
| 37 | - | |
| 38 | -#ifdef USE_OSS_AUDIO | |
| 39 | -#include "audio/ossaudio.h" | |
| 40 | -#endif | |
| 41 | - | |
| 42 | -#ifdef USE_SDL_AUDIO | |
| 43 | -#include "audio/sdlaudio.h" | |
| 44 | -#endif | |
| 45 | - | |
| 46 | -#ifdef USE_WAV_AUDIO | |
| 47 | -#include "audio/wavaudio.h" | |
| 48 | -#endif | |
| 30 | +#include "audio/audio_int.h" | |
| 49 | 31 | |
| 50 | -#ifdef USE_FMOD_AUDIO | |
| 51 | -#include "audio/fmodaudio.h" | |
| 32 | +#define dolog(...) AUD_log ("audio", __VA_ARGS__) | |
| 33 | +#ifdef DEBUG | |
| 34 | +#define ldebug(...) dolog (__VA_ARGS__) | |
| 35 | +#else | |
| 36 | +#define ldebug(...) | |
| 52 | 37 | #endif |
| 53 | 38 | |
| 54 | 39 | #define QC_AUDIO_DRV "QEMU_AUDIO_DRV" |
| 55 | -#define QC_VOICES "QEMU_VOICES" | |
| 40 | +#define QC_VOICES "QEMU_VOICES" | |
| 56 | 41 | #define QC_FIXED_FORMAT "QEMU_FIXED_FORMAT" |
| 57 | 42 | #define QC_FIXED_FREQ "QEMU_FIXED_FREQ" |
| 58 | 43 | |
| 59 | -extern void SB16_init (void); | |
| 60 | - | |
| 61 | -#ifdef USE_ADLIB | |
| 62 | -extern void Adlib_init (void); | |
| 63 | -#endif | |
| 64 | - | |
| 65 | -#ifdef USE_GUS | |
| 66 | -extern void GUS_init (void); | |
| 67 | -#endif | |
| 68 | - | |
| 69 | -static void (*hw_ctors[]) (void) = { | |
| 70 | - SB16_init, | |
| 71 | -#ifdef USE_ADLIB | |
| 72 | - Adlib_init, | |
| 73 | -#endif | |
| 74 | -#ifdef USE_GUS | |
| 75 | - GUS_init, | |
| 76 | -#endif | |
| 77 | - NULL | |
| 78 | -}; | |
| 79 | - | |
| 80 | -static HWVoice *hw_voice; | |
| 44 | +static HWVoice *hw_voices; | |
| 81 | 45 | |
| 82 | 46 | AudioState audio_state = { |
| 83 | 47 | 1, /* use fixed settings */ |
| ... | ... | @@ -127,9 +91,10 @@ const char *audio_get_conf_str (const char *key, const char *defval) |
| 127 | 91 | return val; |
| 128 | 92 | } |
| 129 | 93 | |
| 130 | -void audio_log (const char *fmt, ...) | |
| 94 | +void AUD_log (const char *cap, const char *fmt, ...) | |
| 131 | 95 | { |
| 132 | 96 | va_list ap; |
| 97 | + fprintf (stderr, "%s: ", cap); | |
| 133 | 98 | va_start (ap, fmt); |
| 134 | 99 | vfprintf (stderr, fmt, ap); |
| 135 | 100 | va_end (ap); |
| ... | ... | @@ -403,7 +368,7 @@ int pcm_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt) |
| 403 | 368 | static int dist (void *hw) |
| 404 | 369 | { |
| 405 | 370 | if (hw) { |
| 406 | - return (((uint8_t *) hw - (uint8_t *) hw_voice) | |
| 371 | + return (((uint8_t *) hw - (uint8_t *) hw_voices) | |
| 407 | 372 | / audio_state.voice_size) + 1; |
| 408 | 373 | } |
| 409 | 374 | else { |
| ... | ... | @@ -411,7 +376,7 @@ static int dist (void *hw) |
| 411 | 376 | } |
| 412 | 377 | } |
| 413 | 378 | |
| 414 | -#define ADVANCE(hw) hw ? advance (hw, audio_state.voice_size) : hw_voice | |
| 379 | +#define ADVANCE(hw) hw ? advance (hw, audio_state.voice_size) : hw_voices | |
| 415 | 380 | |
| 416 | 381 | HWVoice *pcm_hw_find_any (HWVoice *hw) |
| 417 | 382 | { |
| ... | ... | @@ -648,6 +613,21 @@ SWVoice *AUD_open (SWVoice *sw, const char *name, |
| 648 | 613 | return sw; |
| 649 | 614 | } |
| 650 | 615 | |
| 616 | +void AUD_close (SWVoice *sw) | |
| 617 | +{ | |
| 618 | + if (!sw) | |
| 619 | + return; | |
| 620 | + | |
| 621 | + pcm_sw_fini (sw); | |
| 622 | + pcm_hw_del_sw (sw->hw, sw); | |
| 623 | + pcm_hw_gc (sw->hw); | |
| 624 | + if (sw->name) { | |
| 625 | + qemu_free (sw->name); | |
| 626 | + sw->name = NULL; | |
| 627 | + } | |
| 628 | + qemu_free (sw); | |
| 629 | +} | |
| 630 | + | |
| 651 | 631 | int AUD_write (SWVoice *sw, void *buf, int size) |
| 652 | 632 | { |
| 653 | 633 | int bytes; |
| ... | ... | @@ -797,13 +777,13 @@ void AUD_enable (SWVoice *sw, int on) |
| 797 | 777 | } |
| 798 | 778 | |
| 799 | 779 | static struct audio_output_driver *drvtab[] = { |
| 800 | -#ifdef USE_OSS_AUDIO | |
| 780 | +#ifdef CONFIG_OSS | |
| 801 | 781 | &oss_output_driver, |
| 802 | 782 | #endif |
| 803 | 783 | #ifdef USE_FMOD_AUDIO |
| 804 | 784 | &fmod_output_driver, |
| 805 | 785 | #endif |
| 806 | -#ifdef USE_SDL_AUDIO | |
| 786 | +#ifdef CONFIG_SDL | |
| 807 | 787 | &sdl_output_driver, |
| 808 | 788 | #endif |
| 809 | 789 | #ifdef USE_WAV_AUDIO |
| ... | ... | @@ -821,8 +801,8 @@ static int voice_init (struct audio_output_driver *drv) |
| 821 | 801 | drv->name, audio_state.nb_hw_voices, drv->max_voices); |
| 822 | 802 | audio_state.nb_hw_voices = drv->max_voices; |
| 823 | 803 | } |
| 824 | - hw_voice = qemu_mallocz (audio_state.nb_hw_voices * drv->voice_size); | |
| 825 | - if (hw_voice) { | |
| 804 | + hw_voices = qemu_mallocz (audio_state.nb_hw_voices * drv->voice_size); | |
| 805 | + if (hw_voices) { | |
| 826 | 806 | audio_state.drv = drv; |
| 827 | 807 | return 1; |
| 828 | 808 | } |
| ... | ... | @@ -928,8 +908,4 @@ void AUD_init (void) |
| 928 | 908 | dolog ("Can not initialize audio subsystem\n"); |
| 929 | 909 | return; |
| 930 | 910 | } |
| 931 | - | |
| 932 | - for (i = 0; hw_ctors[i]; i++) { | |
| 933 | - hw_ctors[i] (); | |
| 934 | - } | |
| 935 | 911 | } | ... | ... |
audio/audio.h
| ... | ... | @@ -26,13 +26,6 @@ |
| 26 | 26 | |
| 27 | 27 | #include "mixeng.h" |
| 28 | 28 | |
| 29 | -#define dolog(...) fprintf (stderr, AUDIO_CAP ": " __VA_ARGS__) | |
| 30 | -#ifdef DEBUG | |
| 31 | -#define ldebug(...) dolog (__VA_ARGS__) | |
| 32 | -#else | |
| 33 | -#define ldebug(...) | |
| 34 | -#endif | |
| 35 | - | |
| 36 | 29 | typedef enum { |
| 37 | 30 | AUD_FMT_U8, |
| 38 | 31 | AUD_FMT_S8, |
| ... | ... | @@ -40,130 +33,14 @@ typedef enum { |
| 40 | 33 | AUD_FMT_S16 |
| 41 | 34 | } audfmt_e; |
| 42 | 35 | |
| 43 | -typedef struct HWVoice HWVoice; | |
| 44 | -struct audio_output_driver; | |
| 45 | - | |
| 46 | -typedef struct AudioState { | |
| 47 | - int fixed_format; | |
| 48 | - int fixed_freq; | |
| 49 | - int fixed_channels; | |
| 50 | - int fixed_fmt; | |
| 51 | - int nb_hw_voices; | |
| 52 | - int voice_size; | |
| 53 | - int64_t ticks_threshold; | |
| 54 | - int freq_threshold; | |
| 55 | - void *opaque; | |
| 56 | - struct audio_output_driver *drv; | |
| 57 | -} AudioState; | |
| 58 | - | |
| 59 | -extern AudioState audio_state; | |
| 60 | - | |
| 61 | -typedef struct SWVoice { | |
| 62 | - int freq; | |
| 63 | - audfmt_e fmt; | |
| 64 | - int nchannels; | |
| 65 | - | |
| 66 | - int shift; | |
| 67 | - int align; | |
| 68 | - | |
| 69 | - t_sample *conv; | |
| 70 | - | |
| 71 | - int left; | |
| 72 | - int pos; | |
| 73 | - int bytes_per_second; | |
| 74 | - int64_t ratio; | |
| 75 | - st_sample_t *buf; | |
| 76 | - void *rate; | |
| 77 | - | |
| 78 | - int wpos; | |
| 79 | - int live; | |
| 80 | - int active; | |
| 81 | - int64_t old_ticks; | |
| 82 | - HWVoice *hw; | |
| 83 | - char *name; | |
| 84 | -} SWVoice; | |
| 85 | - | |
| 86 | -#define VOICE_ENABLE 1 | |
| 87 | -#define VOICE_DISABLE 2 | |
| 88 | - | |
| 89 | -struct pcm_ops { | |
| 90 | - int (*init) (HWVoice *hw, int freq, int nchannels, audfmt_e fmt); | |
| 91 | - void (*fini) (HWVoice *hw); | |
| 92 | - void (*run) (HWVoice *hw); | |
| 93 | - int (*write) (SWVoice *sw, void *buf, int size); | |
| 94 | - int (*ctl) (HWVoice *hw, int cmd, ...); | |
| 95 | -}; | |
| 96 | - | |
| 97 | -struct audio_output_driver { | |
| 98 | - const char *name; | |
| 99 | - void *(*init) (void); | |
| 100 | - void (*fini) (void *); | |
| 101 | - struct pcm_ops *pcm_ops; | |
| 102 | - int can_be_default; | |
| 103 | - int max_voices; | |
| 104 | - int voice_size; | |
| 105 | -}; | |
| 106 | - | |
| 107 | -struct HWVoice { | |
| 108 | - int active; | |
| 109 | - int enabled; | |
| 110 | - int pending_disable; | |
| 111 | - int valid; | |
| 112 | - int freq; | |
| 113 | - | |
| 114 | - f_sample *clip; | |
| 115 | - audfmt_e fmt; | |
| 116 | - int nchannels; | |
| 117 | - | |
| 118 | - int align; | |
| 119 | - int shift; | |
| 120 | - | |
| 121 | - int rpos; | |
| 122 | - int bufsize; | |
| 123 | - | |
| 124 | - int bytes_per_second; | |
| 125 | - st_sample_t *mix_buf; | |
| 126 | - | |
| 127 | - int samples; | |
| 128 | - int64_t old_ticks; | |
| 129 | - int nb_voices; | |
| 130 | - struct SWVoice **pvoice; | |
| 131 | - struct pcm_ops *pcm_ops; | |
| 132 | -}; | |
| 133 | - | |
| 134 | -void audio_log (const char *fmt, ...); | |
| 135 | -void pcm_sw_free_resources (SWVoice *sw); | |
| 136 | -int pcm_sw_alloc_resources (SWVoice *sw); | |
| 137 | -void pcm_sw_fini (SWVoice *sw); | |
| 138 | -int pcm_sw_init (SWVoice *sw, HWVoice *hw, int freq, | |
| 139 | - int nchannels, audfmt_e fmt); | |
| 140 | - | |
| 141 | -void pcm_hw_clear (HWVoice *hw, void *buf, int len); | |
| 142 | -HWVoice * pcm_hw_find_any (HWVoice *hw); | |
| 143 | -HWVoice * pcm_hw_find_any_active (HWVoice *hw); | |
| 144 | -HWVoice * pcm_hw_find_any_passive (HWVoice *hw); | |
| 145 | -HWVoice * pcm_hw_find_specific (HWVoice *hw, int freq, | |
| 146 | - int nchannels, audfmt_e fmt); | |
| 147 | -HWVoice * pcm_hw_add (int freq, int nchannels, audfmt_e fmt); | |
| 148 | -int pcm_hw_add_sw (HWVoice *hw, SWVoice *sw); | |
| 149 | -int pcm_hw_del_sw (HWVoice *hw, SWVoice *sw); | |
| 150 | -SWVoice * pcm_create_voice_pair (int freq, int nchannels, audfmt_e fmt); | |
| 151 | - | |
| 152 | -void pcm_hw_free_resources (HWVoice *hw); | |
| 153 | -int pcm_hw_alloc_resources (HWVoice *hw); | |
| 154 | -void pcm_hw_fini (HWVoice *hw); | |
| 155 | -void pcm_hw_gc (HWVoice *hw); | |
| 156 | -int pcm_hw_get_live (HWVoice *hw); | |
| 157 | -int pcm_hw_get_live2 (HWVoice *hw, int *nb_active); | |
| 158 | -void pcm_hw_dec_live (HWVoice *hw, int decr); | |
| 159 | -int pcm_hw_write (SWVoice *sw, void *buf, int len); | |
| 160 | - | |
| 161 | -int audio_get_conf_int (const char *key, int defval); | |
| 162 | -const char *audio_get_conf_str (const char *key, const char *defval); | |
| 36 | +typedef struct SWVoice SWVoice; | |
| 163 | 37 | |
| 164 | -/* Public API */ | |
| 165 | 38 | SWVoice * AUD_open (SWVoice *sw, const char *name, int freq, |
| 166 | 39 | int nchannels, audfmt_e fmt); |
| 40 | +void AUD_init (void); | |
| 41 | +void AUD_log (const char *cap, const char *fmt, ...) | |
| 42 | + __attribute__ ((__format__ (__printf__, 2, 3)));; | |
| 43 | +void AUD_close (SWVoice *sw); | |
| 167 | 44 | int AUD_write (SWVoice *sw, void *pcm_buf, int size); |
| 168 | 45 | void AUD_adjust (SWVoice *sw, int leftover); |
| 169 | 46 | void AUD_reset (SWVoice *sw); | ... | ... |
audio/audio_int.h
0 โ 100644
| 1 | +/* | |
| 2 | + * QEMU Audio subsystem header | |
| 3 | + * | |
| 4 | + * Copyright (c) 2003-2004 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 | +#ifndef QEMU_AUDIO_INT_H | |
| 25 | +#define QEMU_AUDIO_INT_H | |
| 26 | + | |
| 27 | +#include "vl.h" | |
| 28 | + | |
| 29 | +struct pcm_ops; | |
| 30 | + | |
| 31 | +typedef struct HWVoice { | |
| 32 | + int active; | |
| 33 | + int enabled; | |
| 34 | + int pending_disable; | |
| 35 | + int valid; | |
| 36 | + int freq; | |
| 37 | + | |
| 38 | + f_sample *clip; | |
| 39 | + audfmt_e fmt; | |
| 40 | + int nchannels; | |
| 41 | + | |
| 42 | + int align; | |
| 43 | + int shift; | |
| 44 | + | |
| 45 | + int rpos; | |
| 46 | + int bufsize; | |
| 47 | + | |
| 48 | + int bytes_per_second; | |
| 49 | + st_sample_t *mix_buf; | |
| 50 | + | |
| 51 | + int samples; | |
| 52 | + int64_t old_ticks; | |
| 53 | + int nb_voices; | |
| 54 | + struct SWVoice **pvoice; | |
| 55 | + struct pcm_ops *pcm_ops; | |
| 56 | +} HWVoice; | |
| 57 | + | |
| 58 | +extern struct pcm_ops oss_pcm_ops; | |
| 59 | +extern struct audio_output_driver oss_output_driver; | |
| 60 | + | |
| 61 | +extern struct pcm_ops sdl_pcm_ops; | |
| 62 | +extern struct audio_output_driver sdl_output_driver; | |
| 63 | + | |
| 64 | +extern struct pcm_ops wav_pcm_ops; | |
| 65 | +extern struct audio_output_driver wav_output_driver; | |
| 66 | + | |
| 67 | +extern struct pcm_ops fmod_pcm_ops; | |
| 68 | +extern struct audio_output_driver fmod_output_driver; | |
| 69 | + | |
| 70 | +struct audio_output_driver { | |
| 71 | + const char *name; | |
| 72 | + void *(*init) (void); | |
| 73 | + void (*fini) (void *); | |
| 74 | + struct pcm_ops *pcm_ops; | |
| 75 | + int can_be_default; | |
| 76 | + int max_voices; | |
| 77 | + int voice_size; | |
| 78 | +}; | |
| 79 | + | |
| 80 | +typedef struct AudioState { | |
| 81 | + int fixed_format; | |
| 82 | + int fixed_freq; | |
| 83 | + int fixed_channels; | |
| 84 | + int fixed_fmt; | |
| 85 | + int nb_hw_voices; | |
| 86 | + int voice_size; | |
| 87 | + int64_t ticks_threshold; | |
| 88 | + int freq_threshold; | |
| 89 | + void *opaque; | |
| 90 | + struct audio_output_driver *drv; | |
| 91 | +} AudioState; | |
| 92 | +extern AudioState audio_state; | |
| 93 | + | |
| 94 | +struct SWVoice { | |
| 95 | + int freq; | |
| 96 | + audfmt_e fmt; | |
| 97 | + int nchannels; | |
| 98 | + | |
| 99 | + int shift; | |
| 100 | + int align; | |
| 101 | + | |
| 102 | + t_sample *conv; | |
| 103 | + | |
| 104 | + int left; | |
| 105 | + int pos; | |
| 106 | + int bytes_per_second; | |
| 107 | + int64_t ratio; | |
| 108 | + st_sample_t *buf; | |
| 109 | + void *rate; | |
| 110 | + | |
| 111 | + int wpos; | |
| 112 | + int live; | |
| 113 | + int active; | |
| 114 | + int64_t old_ticks; | |
| 115 | + HWVoice *hw; | |
| 116 | + char *name; | |
| 117 | +}; | |
| 118 | + | |
| 119 | +struct pcm_ops { | |
| 120 | + int (*init) (HWVoice *hw, int freq, int nchannels, audfmt_e fmt); | |
| 121 | + void (*fini) (HWVoice *hw); | |
| 122 | + void (*run) (HWVoice *hw); | |
| 123 | + int (*write) (SWVoice *sw, void *buf, int size); | |
| 124 | + int (*ctl) (HWVoice *hw, int cmd, ...); | |
| 125 | +}; | |
| 126 | + | |
| 127 | +void pcm_sw_free_resources (SWVoice *sw); | |
| 128 | +int pcm_sw_alloc_resources (SWVoice *sw); | |
| 129 | +void pcm_sw_fini (SWVoice *sw); | |
| 130 | +int pcm_sw_init (SWVoice *sw, HWVoice *hw, int freq, | |
| 131 | + int nchannels, audfmt_e fmt); | |
| 132 | + | |
| 133 | +void pcm_hw_clear (HWVoice *hw, void *buf, int len); | |
| 134 | +HWVoice * pcm_hw_find_any (HWVoice *hw); | |
| 135 | +HWVoice * pcm_hw_find_any_active (HWVoice *hw); | |
| 136 | +HWVoice * pcm_hw_find_any_passive (HWVoice *hw); | |
| 137 | +HWVoice * pcm_hw_find_specific (HWVoice *hw, int freq, | |
| 138 | + int nchannels, audfmt_e fmt); | |
| 139 | +HWVoice * pcm_hw_add (int freq, int nchannels, audfmt_e fmt); | |
| 140 | +int pcm_hw_add_sw (HWVoice *hw, SWVoice *sw); | |
| 141 | +int pcm_hw_del_sw (HWVoice *hw, SWVoice *sw); | |
| 142 | +SWVoice * pcm_create_voice_pair (int freq, int nchannels, audfmt_e fmt); | |
| 143 | + | |
| 144 | +void pcm_hw_free_resources (HWVoice *hw); | |
| 145 | +int pcm_hw_alloc_resources (HWVoice *hw); | |
| 146 | +void pcm_hw_fini (HWVoice *hw); | |
| 147 | +void pcm_hw_gc (HWVoice *hw); | |
| 148 | +int pcm_hw_get_live (HWVoice *hw); | |
| 149 | +int pcm_hw_get_live2 (HWVoice *hw, int *nb_active); | |
| 150 | +void pcm_hw_dec_live (HWVoice *hw, int decr); | |
| 151 | +int pcm_hw_write (SWVoice *sw, void *buf, int len); | |
| 152 | + | |
| 153 | +int audio_get_conf_int (const char *key, int defval); | |
| 154 | +const char *audio_get_conf_str (const char *key, const char *defval); | |
| 155 | + | |
| 156 | +struct audio_output_driver; | |
| 157 | + | |
| 158 | +#define VOICE_ENABLE 1 | |
| 159 | +#define VOICE_DISABLE 2 | |
| 160 | + | |
| 161 | +#endif /* audio_int.h */ | ... | ... |
audio/fmodaudio.c
| ... | ... | @@ -25,9 +25,22 @@ |
| 25 | 25 | #include <fmod_errors.h> |
| 26 | 26 | #include "vl.h" |
| 27 | 27 | |
| 28 | -#define AUDIO_CAP "fmod" | |
| 29 | -#include "audio/audio.h" | |
| 30 | -#include "audio/fmodaudio.h" | |
| 28 | +#include "audio/audio_int.h" | |
| 29 | + | |
| 30 | +typedef struct FMODVoice { | |
| 31 | + HWVoice hw; | |
| 32 | + unsigned int old_pos; | |
| 33 | + FSOUND_SAMPLE *fmod_sample; | |
| 34 | + int channel; | |
| 35 | +} FMODVoice; | |
| 36 | + | |
| 37 | + | |
| 38 | +#define dolog(...) AUD_log ("fmod", __VA_ARGS__) | |
| 39 | +#ifdef DEBUG | |
| 40 | +#define ldebug(...) dolog (__VA_ARGS__) | |
| 41 | +#else | |
| 42 | +#define ldebug(...) | |
| 43 | +#endif | |
| 31 | 44 | |
| 32 | 45 | #define QC_FMOD_DRV "QEMU_FMOD_DRV" |
| 33 | 46 | #define QC_FMOD_FREQ "QEMU_FMOD_FREQ" | ... | ... |
audio/fmodaudio.h deleted
100644 โ 0
| 1 | -/* | |
| 2 | - * QEMU FMOD audio output driver header | |
| 3 | - * | |
| 4 | - * Copyright (c) 2004 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 | -#ifndef QEMU_FMODAUDIO_H | |
| 25 | -#define QEMU_FMODAUDIO_H | |
| 26 | - | |
| 27 | -#include <fmod.h> | |
| 28 | - | |
| 29 | -typedef struct FMODVoice { | |
| 30 | - struct HWVoice hw; | |
| 31 | - unsigned int old_pos; | |
| 32 | - FSOUND_SAMPLE *fmod_sample; | |
| 33 | - int channel; | |
| 34 | -} FMODVoice; | |
| 35 | - | |
| 36 | -extern struct pcm_ops fmod_pcm_ops; | |
| 37 | -extern struct audio_output_driver fmod_output_driver; | |
| 38 | - | |
| 39 | -#endif /* fmodaudio.h */ |
audio/ossaudio.c
| ... | ... | @@ -21,20 +21,32 @@ |
| 21 | 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| 22 | 22 | * THE SOFTWARE. |
| 23 | 23 | */ |
| 24 | - | |
| 25 | -/* Temporary kludge */ | |
| 26 | -#if defined __linux__ || (defined _BSD && !defined __APPLE__) | |
| 27 | -#include <assert.h> | |
| 28 | -#include "vl.h" | |
| 29 | - | |
| 30 | 24 | #include <sys/mman.h> |
| 31 | 25 | #include <sys/types.h> |
| 32 | 26 | #include <sys/ioctl.h> |
| 33 | 27 | #include <sys/soundcard.h> |
| 28 | +#include <assert.h> | |
| 29 | +#include "vl.h" | |
| 30 | + | |
| 31 | +#include "audio/audio_int.h" | |
| 32 | + | |
| 33 | +typedef struct OSSVoice { | |
| 34 | + HWVoice hw; | |
| 35 | + void *pcm_buf; | |
| 36 | + int fd; | |
| 37 | + int nfrags; | |
| 38 | + int fragsize; | |
| 39 | + int mmapped; | |
| 40 | + int old_optr; | |
| 41 | +} OSSVoice; | |
| 34 | 42 | |
| 35 | -#define AUDIO_CAP "oss" | |
| 36 | -#include "audio/audio.h" | |
| 37 | -#include "audio/ossaudio.h" | |
| 43 | + | |
| 44 | +#define dolog(...) AUD_log ("oss", __VA_ARGS__) | |
| 45 | +#ifdef DEBUG | |
| 46 | +#define ldebug(...) dolog (__VA_ARGS__) | |
| 47 | +#else | |
| 48 | +#define ldebug(...) | |
| 49 | +#endif | |
| 38 | 50 | |
| 39 | 51 | #define QC_OSS_FRAGSIZE "QEMU_OSS_FRAGSIZE" |
| 40 | 52 | #define QC_OSS_NFRAGS "QEMU_OSS_NFRAGS" |
| ... | ... | @@ -463,4 +475,3 @@ struct audio_output_driver oss_output_driver = { |
| 463 | 475 | INT_MAX, |
| 464 | 476 | sizeof (OSSVoice) |
| 465 | 477 | }; |
| 466 | -#endif | ... | ... |
audio/sdlaudio.c
| ... | ... | @@ -25,9 +25,18 @@ |
| 25 | 25 | #include <SDL/SDL_thread.h> |
| 26 | 26 | #include "vl.h" |
| 27 | 27 | |
| 28 | -#define AUDIO_CAP "sdl" | |
| 29 | -#include "audio/audio.h" | |
| 30 | -#include "audio/sdlaudio.h" | |
| 28 | +#include "audio/audio_int.h" | |
| 29 | + | |
| 30 | +typedef struct SDLVoice { | |
| 31 | + HWVoice hw; | |
| 32 | +} SDLVoice; | |
| 33 | + | |
| 34 | +#define dolog(...) AUD_log ("sdl", __VA_ARGS__) | |
| 35 | +#ifdef DEBUG | |
| 36 | +#define ldebug(...) dolog (__VA_ARGS__) | |
| 37 | +#else | |
| 38 | +#define ldebug(...) | |
| 39 | +#endif | |
| 31 | 40 | |
| 32 | 41 | #define QC_SDL_SAMPLES "QEMU_SDL_SAMPLES" |
| 33 | 42 | ... | ... |
audio/sdlaudio.h deleted
100644 โ 0
| 1 | -/* | |
| 2 | - * QEMU SDL audio output driver header | |
| 3 | - * | |
| 4 | - * Copyright (c) 2004 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 | -#ifndef QEMU_SDLAUDIO_H | |
| 25 | -#define QEMU_SDLAUDIO_H | |
| 26 | - | |
| 27 | -typedef struct SDLVoice { | |
| 28 | - struct HWVoice hw; | |
| 29 | -} SDLVoice; | |
| 30 | - | |
| 31 | -extern struct pcm_ops sdl_pcm_ops; | |
| 32 | -extern struct audio_output_driver sdl_output_driver; | |
| 33 | - | |
| 34 | -#endif /* sdlaudio.h */ |
audio/wavaudio.c
| ... | ... | @@ -23,9 +23,22 @@ |
| 23 | 23 | */ |
| 24 | 24 | #include "vl.h" |
| 25 | 25 | |
| 26 | -#define AUDIO_CAP "wav" | |
| 27 | -#include "audio/audio.h" | |
| 28 | -#include "audio/wavaudio.h" | |
| 26 | +#include "audio/audio_int.h" | |
| 27 | + | |
| 28 | +typedef struct WAVVoice { | |
| 29 | + HWVoice hw; | |
| 30 | + QEMUFile *f; | |
| 31 | + int64_t old_ticks; | |
| 32 | + void *pcm_buf; | |
| 33 | + int total_samples; | |
| 34 | +} WAVVoice; | |
| 35 | + | |
| 36 | +#define dolog(...) AUD_log ("wav", __VA_ARGS__) | |
| 37 | +#ifdef DEBUG | |
| 38 | +#define ldebug(...) dolog (__VA_ARGS__) | |
| 39 | +#else | |
| 40 | +#define ldebug(...) | |
| 41 | +#endif | |
| 29 | 42 | |
| 30 | 43 | static struct { |
| 31 | 44 | const char *wav_path; | ... | ... |
audio/wavaudio.h deleted
100644 โ 0
| 1 | -/* | |
| 2 | - * QEMU WAV audio output driver header | |
| 3 | - * | |
| 4 | - * Copyright (c) 2004 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 | -#ifndef QEMU_WAVAUDIO_H | |
| 25 | -#define QEMU_WAVAUDIO_H | |
| 26 | - | |
| 27 | -typedef struct WAVVoice { | |
| 28 | - struct HWVoice hw; | |
| 29 | - QEMUFile *f; | |
| 30 | - int64_t old_ticks; | |
| 31 | - void *pcm_buf; | |
| 32 | - int total_samples; | |
| 33 | -} WAVVoice; | |
| 34 | - | |
| 35 | -extern struct pcm_ops wav_pcm_ops; | |
| 36 | -extern struct audio_output_driver wav_output_driver; | |
| 37 | - | |
| 38 | -#endif /* wavaudio.h */ |
configure
| ... | ... | @@ -72,6 +72,8 @@ mingw32="no" |
| 72 | 72 | EXESUF="" |
| 73 | 73 | gdbstub="yes" |
| 74 | 74 | slirp="yes" |
| 75 | +adlib="no" | |
| 76 | +oss="no" | |
| 75 | 77 | |
| 76 | 78 | # OS specific |
| 77 | 79 | targetos=`uname -s` |
| ... | ... | @@ -81,18 +83,23 @@ mingw32="yes" |
| 81 | 83 | ;; |
| 82 | 84 | FreeBSD) |
| 83 | 85 | bsd="yes" |
| 86 | +oss="yes" | |
| 84 | 87 | ;; |
| 85 | 88 | NetBSD) |
| 86 | 89 | bsd="yes" |
| 90 | +oss="yes" | |
| 87 | 91 | ;; |
| 88 | 92 | OpenBSD) |
| 89 | 93 | bsd="yes" |
| 94 | +oss="yes" | |
| 90 | 95 | ;; |
| 91 | 96 | Darwin) |
| 92 | 97 | bsd="yes" |
| 93 | 98 | darwin="yes" |
| 94 | 99 | ;; |
| 95 | -*) ;; | |
| 100 | +*) | |
| 101 | +oss="yes" | |
| 102 | +;; | |
| 96 | 103 | esac |
| 97 | 104 | |
| 98 | 105 | if [ "$bsd" = "yes" ] ; then |
| ... | ... | @@ -147,6 +154,8 @@ for opt do |
| 147 | 154 | ;; |
| 148 | 155 | --disable-slirp) slirp="no" |
| 149 | 156 | ;; |
| 157 | + --enable-adlib) adlib="yes" | |
| 158 | + ;; | |
| 150 | 159 | esac |
| 151 | 160 | done |
| 152 | 161 | |
| ... | ... | @@ -316,6 +325,7 @@ echo "static build $static" |
| 316 | 325 | echo "SDL support $sdl" |
| 317 | 326 | echo "SDL static link $sdl_static" |
| 318 | 327 | echo "mingw32 support $mingw32" |
| 328 | +echo "Adlib support $adlib" | |
| 319 | 329 | |
| 320 | 330 | if test $sdl_too_old = "yes"; then |
| 321 | 331 | echo "-> Your SDL version is too old - please upgrade to have FFplay/SDL support" |
| ... | ... | @@ -416,6 +426,14 @@ if test "$slirp" = "yes" ; then |
| 416 | 426 | echo "CONFIG_SLIRP=yes" >> $config_mak |
| 417 | 427 | echo "#define CONFIG_SLIRP 1" >> $config_h |
| 418 | 428 | fi |
| 429 | +if test "$adlib" = "yes" ; then | |
| 430 | + echo "CONFIG_ADLIB=yes" >> $config_mak | |
| 431 | + echo "#define CONFIG_ADLIB 1" >> $config_h | |
| 432 | +fi | |
| 433 | +if test "$oss" = "yes" ; then | |
| 434 | + echo "CONFIG_OSS=yes" >> $config_mak | |
| 435 | + echo "#define CONFIG_OSS 1" >> $config_h | |
| 436 | +fi | |
| 419 | 437 | echo -n "VERSION=" >>$config_mak |
| 420 | 438 | head $source_path/VERSION >>$config_mak |
| 421 | 439 | echo "" >>$config_mak | ... | ... |
hw/adlib.c
| ... | ... | @@ -23,8 +23,12 @@ |
| 23 | 23 | */ |
| 24 | 24 | #include "vl.h" |
| 25 | 25 | |
| 26 | -#define AUDIO_CAP "adlib" | |
| 27 | -#include "audio/audio.h" | |
| 26 | +#define dolog(...) AUD_log ("adlib", __VA_ARGS__) | |
| 27 | +#ifdef DEBUG | |
| 28 | +#define ldebug(...) dolog (__VA_ARGS__) | |
| 29 | +#else | |
| 30 | +#define ldebug(...) | |
| 31 | +#endif | |
| 28 | 32 | |
| 29 | 33 | #ifdef USE_YMF262 |
| 30 | 34 | #define HAS_YMF262 1 | ... | ... |
hw/pc.c
| ... | ... | @@ -555,8 +555,19 @@ void pc_init(int ram_size, int vga_ram_size, int boot_device, |
| 555 | 555 | DMA_init(0); |
| 556 | 556 | |
| 557 | 557 | if (audio_enabled) { |
| 558 | - /* no audio supported yet for win32 */ | |
| 559 | 558 | AUD_init(); |
| 559 | +#ifdef USE_SB16 | |
| 560 | + if (sb16_enabled) | |
| 561 | + SB16_init (); | |
| 562 | +#endif | |
| 563 | +#ifdef CONFIG_ADLIB | |
| 564 | + if (adlib_enabled) | |
| 565 | + Adlib_init (); | |
| 566 | +#endif | |
| 567 | +#ifdef USE_GUS | |
| 568 | + if (gus_enabled) | |
| 569 | + GUS_init (); | |
| 570 | +#endif | |
| 560 | 571 | } |
| 561 | 572 | |
| 562 | 573 | floppy_controller = fdctrl_init(6, 2, 0, 0x3f0, fd_table); | ... | ... |
hw/sb16.c
| ... | ... | @@ -23,12 +23,16 @@ |
| 23 | 23 | */ |
| 24 | 24 | #include "vl.h" |
| 25 | 25 | |
| 26 | -/* #define DEBUG */ | |
| 27 | -#define AUDIO_CAP "sb16" | |
| 28 | -#include "audio/audio.h" | |
| 29 | - | |
| 30 | 26 | #define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0]))) |
| 31 | 27 | |
| 28 | +#define dolog(...) AUD_log ("sb16", __VA_ARGS__) | |
| 29 | +#ifdef DEBUG | |
| 30 | +#define ldebug(...) dolog (__VA_ARGS__) | |
| 31 | +#else | |
| 32 | +#define ldebug(...) | |
| 33 | +#endif | |
| 34 | + | |
| 35 | +/* #define DEBUG */ | |
| 32 | 36 | /* #define DEBUG_SB16_MOST */ |
| 33 | 37 | |
| 34 | 38 | #define IO_READ_PROTO(name) \ |
| ... | ... | @@ -511,7 +515,7 @@ static void command (SB16State *s, uint8_t cmd) |
| 511 | 515 | return; |
| 512 | 516 | |
| 513 | 517 | warn: |
| 514 | - dolog ("warning command %#x,%d is not trully understood yet\n", | |
| 518 | + dolog ("warning: command %#x,%d is not trully understood yet\n", | |
| 515 | 519 | cmd, s->needed_bytes); |
| 516 | 520 | s->cmd = cmd; |
| 517 | 521 | return; |
| ... | ... | @@ -1172,8 +1176,10 @@ static int SB_load (QEMUFile *f, void *opaque, int version_id) |
| 1172 | 1176 | qemu_get_be32s (f, &s->mixer_nreg); |
| 1173 | 1177 | qemu_get_buffer (f, s->mixer_regs, 256); |
| 1174 | 1178 | |
| 1175 | - if (s->voice) | |
| 1176 | - AUD_reset (s->voice); | |
| 1179 | + if (s->voice) { | |
| 1180 | + AUD_close (s->voice); | |
| 1181 | + s->voice = NULL; | |
| 1182 | + } | |
| 1177 | 1183 | |
| 1178 | 1184 | if (s->dma_running) { |
| 1179 | 1185 | if (s->freq) | ... | ... |
vl.c
| ... | ... | @@ -122,6 +122,9 @@ NetDriverState nd_table[MAX_NICS]; |
| 122 | 122 | QEMUTimer *gui_timer; |
| 123 | 123 | int vm_running; |
| 124 | 124 | int audio_enabled = 0; |
| 125 | +int sb16_enabled = 1; | |
| 126 | +int adlib_enabled = 1; | |
| 127 | +int gus_enabled = 1; | |
| 125 | 128 | int pci_enabled = 1; |
| 126 | 129 | int prep_enabled = 0; |
| 127 | 130 | int rtc_utc = 1; | ... | ... |
vl.h
| ... | ... | @@ -37,6 +37,7 @@ |
| 37 | 37 | #include <unistd.h> |
| 38 | 38 | #include <fcntl.h> |
| 39 | 39 | #include <sys/stat.h> |
| 40 | +#include "audio/audio.h" | |
| 40 | 41 | |
| 41 | 42 | #ifndef O_LARGEFILE |
| 42 | 43 | #define O_LARGEFILE 0 |
| ... | ... | @@ -112,6 +113,9 @@ void qemu_system_shutdown_request(void); |
| 112 | 113 | void main_loop_wait(int timeout); |
| 113 | 114 | |
| 114 | 115 | extern int audio_enabled; |
| 116 | +extern int sb16_enabled; | |
| 117 | +extern int adlib_enabled; | |
| 118 | +extern int gus_enabled; | |
| 115 | 119 | extern int ram_size; |
| 116 | 120 | extern int bios_size; |
| 117 | 121 | extern int rtc_utc; |
| ... | ... | @@ -554,8 +558,14 @@ void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table); |
| 554 | 558 | int pmac_ide_init (BlockDriverState **hd_table, |
| 555 | 559 | openpic_t *openpic, int irq); |
| 556 | 560 | |
| 557 | -/* audio.c */ | |
| 558 | -void AUD_init (void); | |
| 561 | +/* sb16.c */ | |
| 562 | +void SB16_init (void); | |
| 563 | + | |
| 564 | +/* adlib.c */ | |
| 565 | +void Adlib_init (void); | |
| 566 | + | |
| 567 | +/* gus.c */ | |
| 568 | +void GUS_init (void); | |
| 559 | 569 | |
| 560 | 570 | /* dma.c */ |
| 561 | 571 | typedef int (*DMA_transfer_handler) (void *opaque, int nchan, int pos, int size); | ... | ... |