All new accounts created on Gitlab now require administrator approval. If you invite any collaborators, please let Flux staff know so they can approve the accounts.

Commit 1d14ffa9 authored by bellard's avatar bellard

merged 15a_aqemu.patch audio patch (malc)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1584 c046a42c-6fe2-441c-8c8c-71466251a162
parent 3b0d4f61
version 0.7.3:
- Mac OS X cocoa improvements (Mike Kronenberg)
- DirectSound driver (malc)
- new audio options: '-soundhw' and 'audio-help' (malc)
- ES1370 PCI audio device (malc)
version 0.7.2:
- x86_64 fixes (Win2000 and Linux 2.6 boot in 32 bit)
......
......@@ -262,7 +262,7 @@ endif
VL_OBJS=vl.o osdep.o block.o readline.o monitor.o pci.o console.o
VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o block-bochs.o block-vpc.o block-vvfat.o
SOUND_HW = sb16.o
SOUND_HW = sb16.o es1370.o
AUDIODRV = audio.o noaudio.o wavaudio.o
ifdef CONFIG_SDL
AUDIODRV += sdlaudio.o
......@@ -270,29 +270,38 @@ endif
ifdef CONFIG_OSS
AUDIODRV += ossaudio.o
endif
pc.o: DEFINES := -DUSE_SB16 $(DEFINES)
ifdef CONFIG_ADLIB
SOUND_HW += fmopl.o adlib.o
ifdef CONFIG_COREAUDIO
AUDIODRV += coreaudio.o
endif
ifdef CONFIG_ALSA
AUDIODRV += alsaaudio.o
LIBS += -lasound
endif
ifdef CONFIG_DSOUND
AUDIODRV += dsoundaudio.o
LIBS += -lole32 -ldxguid
endif
ifdef CONFIG_FMOD
AUDIODRV += fmodaudio.o
audio.o fmodaudio.o: DEFINES := -I$(CONFIG_FMOD_INC) $(DEFINES)
LIBS += $(CONFIG_FMOD_LIB)
endif
ifdef CONFIG_ADLIB
SOUND_HW += fmopl.o adlib.o
endif
ifeq ($(TARGET_BASE_ARCH), i386)
# Hardware support
VL_OBJS+= ide.o ne2000.o pckbd.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pc.o
VL_OBJS+= cirrus_vga.o mixeng.o apic.o parallel.o
DEFINES += -DHAS_AUDIO
endif
ifeq ($(TARGET_BASE_ARCH), ppc)
VL_OBJS+= ppc.o ide.o ne2000.o pckbd.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o
VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o heathrow_pic.o mixeng.o
DEFINES += -DHAS_AUDIO
endif
ifeq ($(TARGET_ARCH), mips)
VL_OBJS+= mips_r4k.o dma.o vga.o serial.o ne2000.o i8254.o i8259.o
......@@ -317,7 +326,10 @@ VL_OBJS+=sdl.o
endif
ifdef CONFIG_COCOA
VL_OBJS+=cocoa.o
COCOA_LIBS=-F/System/Library/Frameworks -framework Cocoa
COCOA_LIBS=-F/System/Library/Frameworks -framework Cocoa -framework IOKit
ifdef CONFIG_COREAUDIO
COCOA_LIBS+=-framework CoreAudio
endif
endif
ifdef CONFIG_SLIRP
DEFINES+=-I$(SRC_PATH)/slirp
......@@ -349,6 +361,10 @@ ifeq ($(ARCH),ia64)
VL_LDFLAGS+=-Wl,-G0 -Wl,-T,$(SRC_PATH)/ia64.ld
endif
ifdef CONFIG_WIN32
SDL_LIBS := $(filter-out -mwindows, $(SDL_LIBS)) -mconsole
endif
$(QEMU_SYSTEM): $(VL_OBJS) libqemu.a
$(CC) $(VL_LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(COCOA_LIBS) $(VL_LIBS)
......@@ -364,6 +380,9 @@ sdlaudio.o: sdlaudio.c
depend: $(SRCS)
$(CC) -MM $(CFLAGS) $(DEFINES) $^ 1>.depend
vldepend: $(VL_OBJS:.o=.c)
$(CC) -MM $(CFLAGS) $(DEFINES) $^ 1>.depend
# libqemu
libqemu.a: $(LIBOBJS)
......@@ -415,8 +434,6 @@ op.o: op.c op_template.c op_mem.c
op_helper.o: op_helper_mem.c
endif
mixeng.o: mixeng.c mixeng.h mixeng_template.h
%.o: %.c
$(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
......@@ -434,3 +451,9 @@ endif
ifneq ($(wildcard .depend),)
include .depend
endif
ifeq (0, 1)
audio.o sdlaudio.o dsoundaudio.o ossaudio.o wavaudio.o noaudio.o \
fmodaudio.o alsaaudio.o mixeng.o: \
CFLAGS := $(CFLAGS) -Wall -Werror -W -Wsign-compare
endif
This diff is collapsed.
This diff is collapsed.
/*
* QEMU Audio subsystem header
*
* Copyright (c) 2003-2004 Vassili Karpov (malc)
*
*
* Copyright (c) 2003-2005 Vassili Karpov (malc)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
......@@ -24,7 +24,7 @@
#ifndef QEMU_AUDIO_H
#define QEMU_AUDIO_H
#include "mixeng.h"
typedef void (*audio_callback_fn_t) (void *opaque, int avail);
typedef enum {
AUD_FMT_U8,
......@@ -33,22 +33,60 @@ typedef enum {
AUD_FMT_S16
} audfmt_e;
typedef struct SWVoice SWVoice;
typedef struct SWVoiceOut SWVoiceOut;
typedef struct SWVoiceIn SWVoiceIn;
typedef struct QEMUAudioTimeStamp {
uint64_t old_ts;
} QEMUAudioTimeStamp;
void AUD_vlog (const char *cap, const char *fmt, va_list ap);
void AUD_log (const char *cap, const char *fmt, ...)
#ifdef __GNUC__
__attribute__ ((__format__ (__printf__, 2, 3)))
#endif
;
SWVoice * AUD_open (SWVoice *sw, const char *name, int freq,
int nchannels, audfmt_e fmt);
void AUD_init (void);
void AUD_log (const char *cap, const char *fmt, ...)
__attribute__ ((__format__ (__printf__, 2, 3)));;
void AUD_close (SWVoice *sw);
int AUD_write (SWVoice *sw, void *pcm_buf, int size);
void AUD_adjust (SWVoice *sw, int leftover);
void AUD_reset (SWVoice *sw);
int AUD_get_free (SWVoice *sw);
int AUD_get_buffer_size (SWVoice *sw);
void AUD_run (void);
void AUD_enable (SWVoice *sw, int on);
int AUD_calc_elapsed (SWVoice *sw);
void AUD_init (void);
void AUD_help (void);
SWVoiceOut *AUD_open_out (
SWVoiceOut *sw,
const char *name,
void *callback_opaque,
audio_callback_fn_t callback_fn,
int freq,
int nchannels,
audfmt_e fmt
);
void AUD_close_out (SWVoiceOut *sw);
int AUD_write (SWVoiceOut *sw, void *pcm_buf, int size);
int AUD_get_buffer_size_out (SWVoiceOut *sw);
void AUD_set_active_out (SWVoiceOut *sw, int on);
int AUD_is_active_out (SWVoiceOut *sw);
void AUD_init_time_stamp_out (SWVoiceOut *sw,
QEMUAudioTimeStamp *ts);
uint64_t AUD_time_stamp_get_elapsed_usec_out (SWVoiceOut *sw,
QEMUAudioTimeStamp *ts);
SWVoiceIn *AUD_open_in (
SWVoiceIn *sw,
const char *name,
void *callback_opaque,
audio_callback_fn_t callback_fn,
int freq,
int nchannels,
audfmt_e fmt
);
void AUD_close_in (SWVoiceIn *sw);
int AUD_read (SWVoiceIn *sw, void *pcm_buf, int size);
void AUD_adjust_in (SWVoiceIn *sw, int leftover);
void AUD_set_active_in (SWVoiceIn *sw, int on);
int AUD_is_active_in (SWVoiceIn *sw);
void AUD_init_time_stamp_in (SWVoiceIn *sw,
QEMUAudioTimeStamp *ts);
uint64_t AUD_time_stamp_get_elapsed_usec_in (SWVoiceIn *sw,
QEMUAudioTimeStamp *ts);
static inline void *advance (void *p, int incr)
{
......@@ -59,7 +97,21 @@ static inline void *advance (void *p, int incr)
uint32_t popcount (uint32_t u);
inline uint32_t lsbindex (uint32_t u);
#ifdef __GNUC__
#define audio_MIN(a, b) ( __extension__ ({ \
__typeof (a) ta = a; \
__typeof (b) tb = b; \
((ta)>(tb)?(tb):(ta)); \
}))
#define audio_MAX(a, b) ( __extension__ ({ \
__typeof (a) ta = a; \
__typeof (b) tb = b; \
((ta)<(tb)?(tb):(ta)); \
}))
#else
#define audio_MIN(a, b) ((a)>(b)?(b):(a))
#define audio_MAX(a, b) ((a)<(b)?(b):(a))
#endif
#endif /* audio.h */
/*
* QEMU Audio subsystem header
*
* Copyright (c) 2003-2004 Vassili Karpov (malc)
*
*
* Copyright (c) 2003-2005 Vassili Karpov (malc)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
......@@ -24,140 +24,266 @@
#ifndef QEMU_AUDIO_INT_H
#define QEMU_AUDIO_INT_H
#include "vl.h"
#include "sys-queue.h"
#ifdef CONFIG_COREAUDIO
#define FLOAT_MIXENG
/* #define RECIPROCAL */
#endif
#include "mixeng.h"
int audio_bug (const char *funcname, int cond);
struct audio_pcm_ops;
typedef enum {
AUD_OPT_INT,
AUD_OPT_FMT,
AUD_OPT_STR,
AUD_OPT_BOOL
} audio_option_tag_e;
struct audio_option {
const char *name;
audio_option_tag_e tag;
void *valp;
const char *descr;
int *overridenp;
int overriden;
};
struct audio_callback {
void *opaque;
audio_callback_fn_t fn;
};
struct pcm_ops;
struct audio_pcm_info {
int bits;
int sign;
int freq;
int nchannels;
int align;
int shift;
int bytes_per_second;
int swap_endian;
};
typedef struct HWVoice {
typedef struct HWVoiceOut {
int active;
int enabled;
int pending_disable;
int valid;
int freq;
struct audio_pcm_info info;
f_sample *clip;
audfmt_e fmt;
int nchannels;
int align;
int shift;
int rpos;
int bufsize;
uint64_t ts_helper;
int bytes_per_second;
st_sample_t *mix_buf;
int samples;
int64_t old_ticks;
int nb_voices;
struct SWVoice **pvoice;
struct pcm_ops *pcm_ops;
} HWVoice;
LIST_HEAD (sw_out_listhead, SWVoiceOut) sw_head;
struct audio_pcm_ops *pcm_ops;
LIST_ENTRY (HWVoiceOut) entries;
} HWVoiceOut;
extern struct pcm_ops no_pcm_ops;
extern struct audio_output_driver no_output_driver;
typedef struct HWVoiceIn {
int enabled;
int active;
struct audio_pcm_info info;
t_sample *conv;
extern struct pcm_ops oss_pcm_ops;
extern struct audio_output_driver oss_output_driver;
int wpos;
int bufsize;
int total_samples_captured;
uint64_t ts_helper;
extern struct pcm_ops sdl_pcm_ops;
extern struct audio_output_driver sdl_output_driver;
st_sample_t *conv_buf;
extern struct pcm_ops wav_pcm_ops;
extern struct audio_output_driver wav_output_driver;
int samples;
LIST_HEAD (sw_in_listhead, SWVoiceIn) sw_head;
struct audio_pcm_ops *pcm_ops;
LIST_ENTRY (HWVoiceIn) entries;
} HWVoiceIn;
extern struct pcm_ops fmod_pcm_ops;
extern struct audio_output_driver fmod_output_driver;
extern struct audio_driver no_audio_driver;
extern struct audio_driver oss_audio_driver;
extern struct audio_driver sdl_audio_driver;
extern struct audio_driver wav_audio_driver;
extern struct audio_driver fmod_audio_driver;
extern struct audio_driver alsa_audio_driver;
extern struct audio_driver coreaudio_audio_driver;
extern struct audio_driver dsound_audio_driver;
extern volume_t nominal_volume;
struct audio_output_driver {
struct audio_driver {
const char *name;
const char *descr;
struct audio_option *options;
void *(*init) (void);
void (*fini) (void *);
struct pcm_ops *pcm_ops;
struct audio_pcm_ops *pcm_ops;
int can_be_default;
int max_voices;
int voice_size;
int max_voices_out;
int max_voices_in;
int voice_size_out;
int voice_size_in;
};
typedef struct AudioState {
int fixed_format;
int fixed_freq;
int fixed_channels;
int fixed_fmt;
int nb_hw_voices;
int64_t ticks_threshold;
int freq_threshold;
int fixed_settings_out;
int fixed_freq_out;
int fixed_channels_out;
int fixed_fmt_out;
int nb_hw_voices_out;
int greedy_out;
int fixed_settings_in;
int fixed_freq_in;
int fixed_channels_in;
int fixed_fmt_in;
int nb_hw_voices_in;
int greedy_in;
void *opaque;
struct audio_output_driver *drv;
} AudioState;
extern AudioState audio_state;
struct audio_driver *drv;
struct SWVoice {
int freq;
audfmt_e fmt;
int nchannels;
QEMUTimer *ts;
union {
int usec;
int64_t ticks;
} period;
int shift;
int align;
int plive;
} AudioState;
extern AudioState audio_state;
struct SWVoiceOut {
struct audio_pcm_info info;
t_sample *conv;
int left;
int pos;
int bytes_per_second;
int64_t ratio;
st_sample_t *buf;
void *rate;
int total_hw_samples_mixed;
int active;
int empty;
HWVoiceOut *hw;
char *name;
volume_t vol;
struct audio_callback callback;
LIST_ENTRY (SWVoiceOut) entries;
};
int wpos;
int live;
struct SWVoiceIn {
int active;
int64_t old_ticks;
HWVoice *hw;
struct audio_pcm_info info;
int64_t ratio;
void *rate;
int total_hw_samples_acquired;
st_sample_t *conv_buf;
f_sample *clip;
HWVoiceIn *hw;
char *name;
volume_t vol;
struct audio_callback callback;
LIST_ENTRY (SWVoiceIn) entries;
};
struct pcm_ops {
int (*init) (HWVoice *hw, int freq, int nchannels, audfmt_e fmt);
void (*fini) (HWVoice *hw);
void (*run) (HWVoice *hw);
int (*write) (SWVoice *sw, void *buf, int size);
int (*ctl) (HWVoice *hw, int cmd, ...);
struct audio_pcm_ops {
int (*init_out)(HWVoiceOut *hw, int freq, int nchannels, audfmt_e fmt);
void (*fini_out)(HWVoiceOut *hw);
int (*run_out) (HWVoiceOut *hw);
int (*write) (SWVoiceOut *sw, void *buf, int size);
int (*ctl_out) (HWVoiceOut *hw, int cmd, ...);
int (*init_in) (HWVoiceIn *hw, int freq, int nchannels, audfmt_e fmt);
void (*fini_in) (HWVoiceIn *hw);
int (*run_in) (HWVoiceIn *hw);
int (*read) (SWVoiceIn *sw, void *buf, int size);
int (*ctl_in) (HWVoiceIn *hw, int cmd, ...);
};
void pcm_sw_free_resources (SWVoice *sw);
int pcm_sw_alloc_resources (SWVoice *sw);
void pcm_sw_fini (SWVoice *sw);
int pcm_sw_init (SWVoice *sw, HWVoice *hw, int freq,
int nchannels, audfmt_e fmt);
void pcm_hw_clear (HWVoice *hw, void *buf, int len);
HWVoice * pcm_hw_find_any (HWVoice *hw);
HWVoice * pcm_hw_find_any_active (HWVoice *hw);
HWVoice * pcm_hw_find_any_passive (HWVoice *hw);
HWVoice * pcm_hw_find_specific (HWVoice *hw, int freq,
int nchannels, audfmt_e fmt);
HWVoice * pcm_hw_add (int freq, int nchannels, audfmt_e fmt);
int pcm_hw_add_sw (HWVoice *hw, SWVoice *sw);
int pcm_hw_del_sw (HWVoice *hw, SWVoice *sw);
SWVoice * pcm_create_voice_pair (int freq, int nchannels, audfmt_e fmt);
void pcm_hw_free_resources (HWVoice *hw);
int pcm_hw_alloc_resources (HWVoice *hw);
void pcm_hw_fini (HWVoice *hw);
void pcm_hw_gc (HWVoice *hw);
int pcm_hw_get_live (HWVoice *hw);
int pcm_hw_get_live2 (HWVoice *hw, int *nb_active);
void pcm_hw_dec_live (HWVoice *hw, int decr);
int pcm_hw_write (SWVoice *sw, void *buf, int len);
int audio_get_conf_int (const char *key, int defval);
const char *audio_get_conf_str (const char *key, const char *defval);
struct audio_output_driver;
void audio_pcm_init_info (struct audio_pcm_info *info, int freq,
int nchannels, audfmt_e fmt, int swap_endian);
void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len);
int audio_pcm_sw_write (SWVoiceOut *sw, void *buf, int len);
int audio_pcm_hw_get_live_in (HWVoiceIn *hw);
int audio_pcm_sw_read (SWVoiceIn *sw, void *buf, int len);
int audio_pcm_hw_get_live_out (HWVoiceOut *hw);
int audio_pcm_hw_get_live_out2 (HWVoiceOut *hw, int *nb_live);
#define VOICE_ENABLE 1
#define VOICE_DISABLE 2
static inline int audio_ring_dist (int dst, int src, int len)
{
return (dst >= src) ? (dst - src) : (len - src + dst);
}
static inline int audio_need_to_swap_endian (int endianness)
{
#ifdef WORDS_BIGENDIAN
return endianness != 1;
#else
return endianness != 0;
#endif
}
#if defined __GNUC__
#define GCC_ATTR __attribute__ ((__unused__, __format__ (__printf__, 1, 2)))
#define INIT_FIELD(f) . f
#define GCC_FMT_ATTR(n, m) __attribute__ ((__format__ (printf, n, m)))
#else
#define GCC_ATTR /**/
#define INIT_FIELD(f) /**/
#define GCC_FMT_ATTR(n, m)
#endif
static void GCC_ATTR dolog (const char *fmt, ...)
{
va_list ap;
va_start (ap, fmt);
AUD_vlog (AUDIO_CAP, fmt, ap);
va_end (ap);
}
#ifdef DEBUG
static void GCC_ATTR ldebug (const char *fmt, ...)
{
va_list ap;
va_start (ap, fmt);
AUD_vlog (AUDIO_CAP, fmt, ap);
va_end (ap);
}
#else
#if defined NDEBUG && defined __GNUC__
#define ldebug(...)
#elif defined NDEBUG && defined _MSC_VER
#define ldebug __noop
#else
static void GCC_ATTR ldebug (const char *fmt, ...)
{
(void) fmt;
}
#endif
#endif
#undef GCC_ATTR
#define AUDIO_STRINGIFY_(n) #n
#define AUDIO_STRINGIFY(n) AUDIO_STRINGIFY_(n)
#if defined _MSC_VER || defined __GNUC__
#define AUDIO_FUNC __FUNCTION__
#else
#define AUDIO_FUNC __FILE__ ":" AUDIO_STRINGIFY (__LINE__)
#endif
#endif /* audio_int.h */
/*
* QEMU Audio subsystem header
*
* Copyright (c) 2005 Vassili Karpov (malc)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifdef DAC
#define TYPE out
#define HW glue (HWVoice, Out)
#define SW glue (SWVoice, Out)
#else
#define TYPE in
#define HW glue (HWVoice, In)
#define SW glue (SWVoice, In)
#endif
static void glue (audio_pcm_sw_fini_, TYPE) (SW *sw)
{
glue (audio_pcm_sw_free_resources_, TYPE) (sw);
if (sw->name) {
qemu_free (sw->name);
sw->name = NULL;
}
}
static void glue (audio_pcm_hw_add_sw_, TYPE) (HW *hw, SW *sw)
{
LIST_INSERT_HEAD (&hw->sw_head, sw, entries);
}
static void glue (audio_pcm_hw_del_sw_, TYPE) (SW *sw)
{