From ef79bbde537d6b9c745a7d86cb9df1d04c35590d Mon Sep 17 00:00:00 2001 From: PCSX* teams Date: Tue, 16 Nov 2010 14:15:22 +0200 Subject: pcsxr-1.9.92 --- plugins/dfsound/Makefile.am | 51 ++ plugins/dfsound/Makefile.in | 711 ++++++++++++++++++ plugins/dfsound/adsr.c | 641 +++++++++++++++++ plugins/dfsound/adsr.h | 19 + plugins/dfsound/alsa.c | 158 ++++ plugins/dfsound/cfg.c | 167 +++++ plugins/dfsound/cfg.h | 19 + plugins/dfsound/dma.c | 97 +++ plugins/dfsound/dma.h | 31 + plugins/dfsound/dsoundoss.h | 22 + plugins/dfsound/externals.h | 286 ++++++++ plugins/dfsound/freeze.c | 214 ++++++ plugins/dfsound/gauss_i.h | 150 ++++ plugins/dfsound/nullsnd.c | 24 + plugins/dfsound/oss.c | 159 +++++ plugins/dfsound/psemuxa.h | 28 + plugins/dfsound/pulseaudio.c | 354 +++++++++ plugins/dfsound/registers.c | 589 +++++++++++++++ plugins/dfsound/registers.h | 144 ++++ plugins/dfsound/regs.h | 27 + plugins/dfsound/reverb.c | 462 ++++++++++++ plugins/dfsound/reverb.h | 21 + plugins/dfsound/sdl.c | 135 ++++ plugins/dfsound/spu.c | 1029 +++++++++++++++++++++++++++ plugins/dfsound/spu.h | 21 + plugins/dfsound/spucfg-0.1df/dfsound.glade2 | 308 ++++++++ plugins/dfsound/spucfg-0.1df/main.c | 258 +++++++ plugins/dfsound/stdafx.h | 46 ++ plugins/dfsound/xa.c | 410 +++++++++++ plugins/dfsound/xa.h | 20 + 30 files changed, 6601 insertions(+) create mode 100644 plugins/dfsound/Makefile.am create mode 100644 plugins/dfsound/Makefile.in create mode 100644 plugins/dfsound/adsr.c create mode 100644 plugins/dfsound/adsr.h create mode 100644 plugins/dfsound/alsa.c create mode 100644 plugins/dfsound/cfg.c create mode 100644 plugins/dfsound/cfg.h create mode 100644 plugins/dfsound/dma.c create mode 100644 plugins/dfsound/dma.h create mode 100644 plugins/dfsound/dsoundoss.h create mode 100644 plugins/dfsound/externals.h create mode 100644 plugins/dfsound/freeze.c create mode 100644 plugins/dfsound/gauss_i.h create mode 100644 plugins/dfsound/nullsnd.c create mode 100644 plugins/dfsound/oss.c create mode 100644 plugins/dfsound/psemuxa.h create mode 100644 plugins/dfsound/pulseaudio.c create mode 100644 plugins/dfsound/registers.c create mode 100644 plugins/dfsound/registers.h create mode 100644 plugins/dfsound/regs.h create mode 100644 plugins/dfsound/reverb.c create mode 100644 plugins/dfsound/reverb.h create mode 100644 plugins/dfsound/sdl.c create mode 100644 plugins/dfsound/spu.c create mode 100644 plugins/dfsound/spu.h create mode 100644 plugins/dfsound/spucfg-0.1df/dfsound.glade2 create mode 100644 plugins/dfsound/spucfg-0.1df/main.c create mode 100644 plugins/dfsound/stdafx.h create mode 100644 plugins/dfsound/xa.c create mode 100644 plugins/dfsound/xa.h (limited to 'plugins/dfsound') diff --git a/plugins/dfsound/Makefile.am b/plugins/dfsound/Makefile.am new file mode 100644 index 0000000..88a7dc8 --- /dev/null +++ b/plugins/dfsound/Makefile.am @@ -0,0 +1,51 @@ +INCLUDES = -DPIXMAPDIR=\"${datadir}/pixmaps/\" \ + -DLOCALE_DIR=\"${datadir}/locale/\" \ + -DDATADIR=\"${datadir}/psemu/\" \ + $(GTK2_CFLAGS) $(GLADE2_CFLAGS) \ + -I../../include + +bindir = @libdir@/games/psemu/ +libdir = @libdir@/games/psemu/ + +lib_LTLIBRARIES = libDFSound.la + +libDFSound_la_SOURCES = spu.c cfg.c dma.c freeze.c registers.c + +libDFSound_la_CFLAGS = +libDFSound_la_LDFLAGS = -module -avoid-version -lpthread -lm + +if SOUND_ALSA +libDFSound_la_SOURCES += alsa.c +libDFSound_la_CFLAGS += -DUSEALSA=1 +libDFSound_la_LDFLAGS += $(ALSA_LIBS) +endif + +if SOUND_OSS +libDFSound_la_SOURCES += oss.c +libDFSound_la_CFLAGS += -DUSEOSS=1 +endif + +if SOUND_PULSEAUDIO +libDFSound_la_SOURCES += pulseaudio.c +libDFSound_la_CFLAGS += -DUSEPULSEAUDIO=1 $(PULSEAUDIO_CFLAGS) +libDFSound_la_LDFLAGS += $(PULSEAUDIO_LIBS) +endif + +if SOUND_SDL +libDFSound_la_SOURCES += sdl.c +libDFSound_la_CFLAGS += -DUSESDL=1 $(SDL_CFLAGS) +libDFSound_la_LDFLAGS += $(SDL_LIBS) +endif + +if SOUND_NULL +libDFSound_la_SOURCES += nullsnd.c +libDFSound_la_CFLAGS += -DUSENULL=1 +endif + +bin_PROGRAMS = cfgDFSound +cfgDFSound_SOURCES = spucfg-0.1df/main.c +cfgDFSound_LDADD = $(GTK2_LIBS) $(GLADE2_LIBS) + +glade_DATA = spucfg-0.1df/dfsound.glade2 +gladedir = $(datadir)/psemu/ +EXTRA_DIST = $(glade_DATA) diff --git a/plugins/dfsound/Makefile.in b/plugins/dfsound/Makefile.in new file mode 100644 index 0000000..70edf5b --- /dev/null +++ b/plugins/dfsound/Makefile.in @@ -0,0 +1,711 @@ +# Makefile.in generated by automake 1.10.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@SOUND_ALSA_TRUE@am__append_1 = alsa.c +@SOUND_ALSA_TRUE@am__append_2 = -DUSEALSA=1 +@SOUND_ALSA_TRUE@am__append_3 = $(ALSA_LIBS) +@SOUND_OSS_TRUE@am__append_4 = oss.c +@SOUND_OSS_TRUE@am__append_5 = -DUSEOSS=1 +@SOUND_PULSEAUDIO_TRUE@am__append_6 = pulseaudio.c +@SOUND_PULSEAUDIO_TRUE@am__append_7 = -DUSEPULSEAUDIO=1 $(PULSEAUDIO_CFLAGS) +@SOUND_PULSEAUDIO_TRUE@am__append_8 = $(PULSEAUDIO_LIBS) +@SOUND_SDL_TRUE@am__append_9 = sdl.c +@SOUND_SDL_TRUE@am__append_10 = -DUSESDL=1 $(SDL_CFLAGS) +@SOUND_SDL_TRUE@am__append_11 = $(SDL_LIBS) +@SOUND_NULL_TRUE@am__append_12 = nullsnd.c +@SOUND_NULL_TRUE@am__append_13 = -DUSENULL=1 +bin_PROGRAMS = cfgDFSound$(EXEEXT) +subdir = plugins/dfsound +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/include/config.h +CONFIG_CLEAN_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ + "$(DESTDIR)$(gladedir)" +libLTLIBRARIES_INSTALL = $(INSTALL) +LTLIBRARIES = $(lib_LTLIBRARIES) +libDFSound_la_LIBADD = +am__libDFSound_la_SOURCES_DIST = spu.c cfg.c dma.c freeze.c \ + registers.c alsa.c oss.c pulseaudio.c sdl.c nullsnd.c +@SOUND_ALSA_TRUE@am__objects_1 = libDFSound_la-alsa.lo +@SOUND_OSS_TRUE@am__objects_2 = libDFSound_la-oss.lo +@SOUND_PULSEAUDIO_TRUE@am__objects_3 = libDFSound_la-pulseaudio.lo +@SOUND_SDL_TRUE@am__objects_4 = libDFSound_la-sdl.lo +@SOUND_NULL_TRUE@am__objects_5 = libDFSound_la-nullsnd.lo +am_libDFSound_la_OBJECTS = libDFSound_la-spu.lo libDFSound_la-cfg.lo \ + libDFSound_la-dma.lo libDFSound_la-freeze.lo \ + libDFSound_la-registers.lo $(am__objects_1) $(am__objects_2) \ + $(am__objects_3) $(am__objects_4) $(am__objects_5) +libDFSound_la_OBJECTS = $(am_libDFSound_la_OBJECTS) +libDFSound_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libDFSound_la_CFLAGS) \ + $(CFLAGS) $(libDFSound_la_LDFLAGS) $(LDFLAGS) -o $@ +binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) +PROGRAMS = $(bin_PROGRAMS) +am_cfgDFSound_OBJECTS = main.$(OBJEXT) +cfgDFSound_OBJECTS = $(am_cfgDFSound_OBJECTS) +am__DEPENDENCIES_1 = +cfgDFSound_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libDFSound_la_SOURCES) $(cfgDFSound_SOURCES) +DIST_SOURCES = $(am__libDFSound_la_SOURCES_DIST) $(cfgDFSound_SOURCES) +gladeDATA_INSTALL = $(INSTALL_DATA) +DATA = $(glade_DATA) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALSA_CFLAGS = @ALSA_CFLAGS@ +ALSA_LIBS = @ALSA_LIBS@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLADE2_CFLAGS = @GLADE2_CFLAGS@ +GLADE2_LIBS = @GLADE2_LIBS@ +GLIB2_CFLAGS = @GLIB2_CFLAGS@ +GLIB2_LIBS = @GLIB2_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +GTK2_CFLAGS = @GTK2_CFLAGS@ +GTK2_LIBS = @GTK2_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBCDIO_CFLAGS = @LIBCDIO_CFLAGS@ +LIBCDIO_LIBS = @LIBCDIO_LIBS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NASM = @NASM@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PEOPSXGL = @PEOPSXGL@ +PKG_CONFIG = @PKG_CONFIG@ +POSUB = @POSUB@ +PULSEAUDIO_CFLAGS = @PULSEAUDIO_CFLAGS@ +PULSEAUDIO_LIBS = @PULSEAUDIO_LIBS@ +RANLIB = @RANLIB@ +SDL_CFLAGS = @SDL_CFLAGS@ +SDL_CONFIG = @SDL_CONFIG@ +SDL_LIBS = @SDL_LIBS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @libdir@/games/psemu/ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@/games/psemu/ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +INCLUDES = -DPIXMAPDIR=\"${datadir}/pixmaps/\" \ + -DLOCALE_DIR=\"${datadir}/locale/\" \ + -DDATADIR=\"${datadir}/psemu/\" \ + $(GTK2_CFLAGS) $(GLADE2_CFLAGS) \ + -I../../include + +lib_LTLIBRARIES = libDFSound.la +libDFSound_la_SOURCES = spu.c cfg.c dma.c freeze.c registers.c \ + $(am__append_1) $(am__append_4) $(am__append_6) \ + $(am__append_9) $(am__append_12) +libDFSound_la_CFLAGS = $(am__append_2) $(am__append_5) $(am__append_7) \ + $(am__append_10) $(am__append_13) +libDFSound_la_LDFLAGS = -module -avoid-version -lpthread -lm \ + $(am__append_3) $(am__append_8) $(am__append_11) +cfgDFSound_SOURCES = spucfg-0.1df/main.c +cfgDFSound_LDADD = $(GTK2_LIBS) $(GLADE2_LIBS) +glade_DATA = spucfg-0.1df/dfsound.glade2 +gladedir = $(datadir)/psemu/ +EXTRA_DIST = $(glade_DATA) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plugins/dfsound/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu plugins/dfsound/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + f=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \ + else :; fi; \ + done + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + p=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libDFSound.la: $(libDFSound_la_OBJECTS) $(libDFSound_la_DEPENDENCIES) + $(libDFSound_la_LINK) -rpath $(libdir) $(libDFSound_la_OBJECTS) $(libDFSound_la_LIBADD) $(LIBS) +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + if test -f $$p \ + || test -f $$p1 \ + ; then \ + f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ + else :; fi; \ + done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ + rm -f "$(DESTDIR)$(bindir)/$$f"; \ + done + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f $$p $$f"; \ + rm -f $$p $$f ; \ + done +cfgDFSound$(EXEEXT): $(cfgDFSound_OBJECTS) $(cfgDFSound_DEPENDENCIES) + @rm -f cfgDFSound$(EXEEXT) + $(LINK) $(cfgDFSound_OBJECTS) $(cfgDFSound_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libDFSound_la-alsa.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libDFSound_la-cfg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libDFSound_la-dma.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libDFSound_la-freeze.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libDFSound_la-nullsnd.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libDFSound_la-oss.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libDFSound_la-pulseaudio.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libDFSound_la-registers.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libDFSound_la-sdl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libDFSound_la-spu.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +libDFSound_la-spu.lo: spu.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libDFSound_la_CFLAGS) $(CFLAGS) -MT libDFSound_la-spu.lo -MD -MP -MF $(DEPDIR)/libDFSound_la-spu.Tpo -c -o libDFSound_la-spu.lo `test -f 'spu.c' || echo '$(srcdir)/'`spu.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libDFSound_la-spu.Tpo $(DEPDIR)/libDFSound_la-spu.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='spu.c' object='libDFSound_la-spu.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libDFSound_la_CFLAGS) $(CFLAGS) -c -o libDFSound_la-spu.lo `test -f 'spu.c' || echo '$(srcdir)/'`spu.c + +libDFSound_la-cfg.lo: cfg.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libDFSound_la_CFLAGS) $(CFLAGS) -MT libDFSound_la-cfg.lo -MD -MP -MF $(DEPDIR)/libDFSound_la-cfg.Tpo -c -o libDFSound_la-cfg.lo `test -f 'cfg.c' || echo '$(srcdir)/'`cfg.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libDFSound_la-cfg.Tpo $(DEPDIR)/libDFSound_la-cfg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cfg.c' object='libDFSound_la-cfg.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libDFSound_la_CFLAGS) $(CFLAGS) -c -o libDFSound_la-cfg.lo `test -f 'cfg.c' || echo '$(srcdir)/'`cfg.c + +libDFSound_la-dma.lo: dma.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libDFSound_la_CFLAGS) $(CFLAGS) -MT libDFSound_la-dma.lo -MD -MP -MF $(DEPDIR)/libDFSound_la-dma.Tpo -c -o libDFSound_la-dma.lo `test -f 'dma.c' || echo '$(srcdir)/'`dma.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libDFSound_la-dma.Tpo $(DEPDIR)/libDFSound_la-dma.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dma.c' object='libDFSound_la-dma.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libDFSound_la_CFLAGS) $(CFLAGS) -c -o libDFSound_la-dma.lo `test -f 'dma.c' || echo '$(srcdir)/'`dma.c + +libDFSound_la-freeze.lo: freeze.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libDFSound_la_CFLAGS) $(CFLAGS) -MT libDFSound_la-freeze.lo -MD -MP -MF $(DEPDIR)/libDFSound_la-freeze.Tpo -c -o libDFSound_la-freeze.lo `test -f 'freeze.c' || echo '$(srcdir)/'`freeze.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libDFSound_la-freeze.Tpo $(DEPDIR)/libDFSound_la-freeze.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='freeze.c' object='libDFSound_la-freeze.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libDFSound_la_CFLAGS) $(CFLAGS) -c -o libDFSound_la-freeze.lo `test -f 'freeze.c' || echo '$(srcdir)/'`freeze.c + +libDFSound_la-registers.lo: registers.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libDFSound_la_CFLAGS) $(CFLAGS) -MT libDFSound_la-registers.lo -MD -MP -MF $(DEPDIR)/libDFSound_la-registers.Tpo -c -o libDFSound_la-registers.lo `test -f 'registers.c' || echo '$(srcdir)/'`registers.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libDFSound_la-registers.Tpo $(DEPDIR)/libDFSound_la-registers.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='registers.c' object='libDFSound_la-registers.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libDFSound_la_CFLAGS) $(CFLAGS) -c -o libDFSound_la-registers.lo `test -f 'registers.c' || echo '$(srcdir)/'`registers.c + +libDFSound_la-alsa.lo: alsa.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libDFSound_la_CFLAGS) $(CFLAGS) -MT libDFSound_la-alsa.lo -MD -MP -MF $(DEPDIR)/libDFSound_la-alsa.Tpo -c -o libDFSound_la-alsa.lo `test -f 'alsa.c' || echo '$(srcdir)/'`alsa.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libDFSound_la-alsa.Tpo $(DEPDIR)/libDFSound_la-alsa.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='alsa.c' object='libDFSound_la-alsa.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libDFSound_la_CFLAGS) $(CFLAGS) -c -o libDFSound_la-alsa.lo `test -f 'alsa.c' || echo '$(srcdir)/'`alsa.c + +libDFSound_la-oss.lo: oss.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libDFSound_la_CFLAGS) $(CFLAGS) -MT libDFSound_la-oss.lo -MD -MP -MF $(DEPDIR)/libDFSound_la-oss.Tpo -c -o libDFSound_la-oss.lo `test -f 'oss.c' || echo '$(srcdir)/'`oss.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libDFSound_la-oss.Tpo $(DEPDIR)/libDFSound_la-oss.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='oss.c' object='libDFSound_la-oss.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libDFSound_la_CFLAGS) $(CFLAGS) -c -o libDFSound_la-oss.lo `test -f 'oss.c' || echo '$(srcdir)/'`oss.c + +libDFSound_la-pulseaudio.lo: pulseaudio.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libDFSound_la_CFLAGS) $(CFLAGS) -MT libDFSound_la-pulseaudio.lo -MD -MP -MF $(DEPDIR)/libDFSound_la-pulseaudio.Tpo -c -o libDFSound_la-pulseaudio.lo `test -f 'pulseaudio.c' || echo '$(srcdir)/'`pulseaudio.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libDFSound_la-pulseaudio.Tpo $(DEPDIR)/libDFSound_la-pulseaudio.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pulseaudio.c' object='libDFSound_la-pulseaudio.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libDFSound_la_CFLAGS) $(CFLAGS) -c -o libDFSound_la-pulseaudio.lo `test -f 'pulseaudio.c' || echo '$(srcdir)/'`pulseaudio.c + +libDFSound_la-sdl.lo: sdl.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libDFSound_la_CFLAGS) $(CFLAGS) -MT libDFSound_la-sdl.lo -MD -MP -MF $(DEPDIR)/libDFSound_la-sdl.Tpo -c -o libDFSound_la-sdl.lo `test -f 'sdl.c' || echo '$(srcdir)/'`sdl.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libDFSound_la-sdl.Tpo $(DEPDIR)/libDFSound_la-sdl.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sdl.c' object='libDFSound_la-sdl.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libDFSound_la_CFLAGS) $(CFLAGS) -c -o libDFSound_la-sdl.lo `test -f 'sdl.c' || echo '$(srcdir)/'`sdl.c + +libDFSound_la-nullsnd.lo: nullsnd.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libDFSound_la_CFLAGS) $(CFLAGS) -MT libDFSound_la-nullsnd.lo -MD -MP -MF $(DEPDIR)/libDFSound_la-nullsnd.Tpo -c -o libDFSound_la-nullsnd.lo `test -f 'nullsnd.c' || echo '$(srcdir)/'`nullsnd.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libDFSound_la-nullsnd.Tpo $(DEPDIR)/libDFSound_la-nullsnd.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nullsnd.c' object='libDFSound_la-nullsnd.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libDFSound_la_CFLAGS) $(CFLAGS) -c -o libDFSound_la-nullsnd.lo `test -f 'nullsnd.c' || echo '$(srcdir)/'`nullsnd.c + +main.o: spucfg-0.1df/main.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT main.o -MD -MP -MF $(DEPDIR)/main.Tpo -c -o main.o `test -f 'spucfg-0.1df/main.c' || echo '$(srcdir)/'`spucfg-0.1df/main.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/main.Tpo $(DEPDIR)/main.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='spucfg-0.1df/main.c' object='main.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o main.o `test -f 'spucfg-0.1df/main.c' || echo '$(srcdir)/'`spucfg-0.1df/main.c + +main.obj: spucfg-0.1df/main.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT main.obj -MD -MP -MF $(DEPDIR)/main.Tpo -c -o main.obj `if test -f 'spucfg-0.1df/main.c'; then $(CYGPATH_W) 'spucfg-0.1df/main.c'; else $(CYGPATH_W) '$(srcdir)/spucfg-0.1df/main.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/main.Tpo $(DEPDIR)/main.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='spucfg-0.1df/main.c' object='main.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o main.obj `if test -f 'spucfg-0.1df/main.c'; then $(CYGPATH_W) 'spucfg-0.1df/main.c'; else $(CYGPATH_W) '$(srcdir)/spucfg-0.1df/main.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-gladeDATA: $(glade_DATA) + @$(NORMAL_INSTALL) + test -z "$(gladedir)" || $(MKDIR_P) "$(DESTDIR)$(gladedir)" + @list='$(glade_DATA)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f=$(am__strip_dir) \ + echo " $(gladeDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(gladedir)/$$f'"; \ + $(gladeDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(gladedir)/$$f"; \ + done + +uninstall-gladeDATA: + @$(NORMAL_UNINSTALL) + @list='$(glade_DATA)'; for p in $$list; do \ + f=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(gladedir)/$$f'"; \ + rm -f "$(DESTDIR)$(gladedir)/$$f"; \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) +install-binPROGRAMS: install-libLTLIBRARIES + +installdirs: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(gladedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \ + clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-gladeDATA + +install-dvi: install-dvi-am + +install-exec-am: install-binPROGRAMS install-libLTLIBRARIES + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS uninstall-gladeDATA \ + uninstall-libLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ + clean-generic clean-libLTLIBRARIES clean-libtool ctags \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-binPROGRAMS \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-gladeDATA install-html \ + install-html-am install-info install-info-am \ + install-libLTLIBRARIES install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-binPROGRAMS \ + uninstall-gladeDATA uninstall-libLTLIBRARIES + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/plugins/dfsound/adsr.c b/plugins/dfsound/adsr.c new file mode 100644 index 0000000..2496e46 --- /dev/null +++ b/plugins/dfsound/adsr.c @@ -0,0 +1,641 @@ +/*************************************************************************** + adsr.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#include "stdafx.h" + +#define _IN_ADSR + +// will be included from spu.c +#ifdef _IN_SPU + +//////////////////////////////////////////////////////////////////////// +// ADSR func +//////////////////////////////////////////////////////////////////////// + +unsigned long RateTable[160]; + +void InitADSR(void) // INIT ADSR +{ + unsigned long r,rs,rd;int i; + + memset(RateTable,0,sizeof(unsigned long)*160); // build the rate table according to Neill's rules (see at bottom of file) + + r=3;rs=1;rd=0; + + for(i=32;i<160;i++) // we start at pos 32 with the real values... everything before is 0 + { + if(r<0x3FFFFFFF) + { + r+=rs; + rd++;if(rd==5) {rd=1;rs*=2;} + } + if(r>0x3FFFFFFF) r=0x3FFFFFFF; + + RateTable[i]=r; + } +} + +//////////////////////////////////////////////////////////////////////// + +INLINE void StartADSR(int ch) // MIX ADSR +{ + s_chan[ch].ADSRX.lVolume=1; // and init some adsr vars + s_chan[ch].ADSRX.State=0; + s_chan[ch].ADSRX.EnvelopeVol=0; +} + +//////////////////////////////////////////////////////////////////////// + +INLINE int MixADSR(int ch) // MIX ADSR +{ + if(s_chan[ch].bStop) // should be stopped: + { // do release + if(s_chan[ch].ADSRX.ReleaseModeExp) + { + switch((s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7) + { + case 0: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +0 + 32]; break; + case 1: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +4 + 32]; break; + case 2: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +6 + 32]; break; + case 3: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +8 + 32]; break; + case 4: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +9 + 32]; break; + case 5: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +10+ 32]; break; + case 6: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +11+ 32]; break; + case 7: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +12+ 32]; break; + } + } + else + { + s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x0C + 32]; + } + + if(s_chan[ch].ADSRX.EnvelopeVol<0) + { + s_chan[ch].ADSRX.EnvelopeVol=0; + s_chan[ch].bOn=0; + //s_chan[ch].bReverb=0; + //s_chan[ch].bNoise=0; + } + + s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21; + return s_chan[ch].ADSRX.lVolume; + } + else // not stopped yet? + { + if(s_chan[ch].ADSRX.State==0) // -> attack + { + if(s_chan[ch].ADSRX.AttackModeExp) + { + if(s_chan[ch].ADSRX.EnvelopeVol<0x60000000) + s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.AttackRate^0x7F)-0x10 + 32]; + else + s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.AttackRate^0x7F)-0x18 + 32]; + } + else + { + s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.AttackRate^0x7F)-0x10 + 32]; + } + + if(s_chan[ch].ADSRX.EnvelopeVol<0) + { + s_chan[ch].ADSRX.EnvelopeVol=0x7FFFFFFF; + s_chan[ch].ADSRX.State=1; + } + + s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21; + return s_chan[ch].ADSRX.lVolume; + } + //--------------------------------------------------// + if(s_chan[ch].ADSRX.State==1) // -> decay + { + switch((s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7) + { + case 0: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+0 + 32]; break; + case 1: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+4 + 32]; break; + case 2: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+6 + 32]; break; + case 3: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+8 + 32]; break; + case 4: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+9 + 32]; break; + case 5: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+10+ 32]; break; + case 6: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+11+ 32]; break; + case 7: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+12+ 32]; break; + } + + if(s_chan[ch].ADSRX.EnvelopeVol<0) s_chan[ch].ADSRX.EnvelopeVol=0; + if(((s_chan[ch].ADSRX.EnvelopeVol>>27)&0xF) <= s_chan[ch].ADSRX.SustainLevel) + { + s_chan[ch].ADSRX.State=2; + } + + s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21; + return s_chan[ch].ADSRX.lVolume; + } + //--------------------------------------------------// + if(s_chan[ch].ADSRX.State==2) // -> sustain + { + if(s_chan[ch].ADSRX.SustainIncrease) + { + if(s_chan[ch].ADSRX.SustainModeExp) + { + if(s_chan[ch].ADSRX.EnvelopeVol<0x60000000) + s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.SustainRate^0x7F)-0x10 + 32]; + else + s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.SustainRate^0x7F)-0x18 + 32]; + } + else + { + s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.SustainRate^0x7F)-0x10 + 32]; + } + + if(s_chan[ch].ADSRX.EnvelopeVol<0) + { + s_chan[ch].ADSRX.EnvelopeVol=0x7FFFFFFF; + } + } + else + { + if(s_chan[ch].ADSRX.SustainModeExp) + { + switch((s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7) + { + case 0: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +0 + 32];break; + case 1: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +4 + 32];break; + case 2: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +6 + 32];break; + case 3: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +8 + 32];break; + case 4: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +9 + 32];break; + case 5: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +10+ 32];break; + case 6: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +11+ 32];break; + case 7: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +12+ 32];break; + } + } + else + { + s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x0F + 32]; + } + + if(s_chan[ch].ADSRX.EnvelopeVol<0) + { + s_chan[ch].ADSRX.EnvelopeVol=0; + } + } + s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21; + return s_chan[ch].ADSRX.lVolume; + } + } + return 0; +} + +#endif + +/* +James Higgs ADSR investigations: + +PSX SPU Envelope Timings +~~~~~~~~~~~~~~~~~~~~~~~~ + +First, here is an extract from doomed's SPU doc, which explains the basics +of the SPU "volume envelope": + +*** doomed doc extract start *** + +-------------------------------------------------------------------------- +Voices. +-------------------------------------------------------------------------- +The SPU has 24 hardware voices. These voices can be used to reproduce sample +data, noise or can be used as frequency modulator on the next voice. +Each voice has it's own programmable ADSR envelope filter. The main volume +can be programmed independently for left and right output. + +The ADSR envelope filter works as follows: +Ar = Attack rate, which specifies the speed at which the volume increases + from zero to it's maximum value, as soon as the note on is given. The + slope can be set to lineair or exponential. +Dr = Decay rate specifies the speed at which the volume decreases to the + sustain level. Decay is always decreasing exponentially. +Sl = Sustain level, base level from which sustain starts. +Sr = Sustain rate is the rate at which the volume of the sustained note + increases or decreases. This can be either lineair or exponential. +Rr = Release rate is the rate at which the volume of the note decreases + as soon as the note off is given. + + lvl | + ^ | /\Dr __ + Sl _| _ / _ \__--- \ + | / ---__ \ Rr + | /Ar Sr \ \ + | / \\ + |/___________________\________ + ->time + +The overal volume can also be set to sweep up or down lineairly or +exponentially from it's current value. This can be done seperately +for left and right. + +Relevant SPU registers: +------------------------------------------------------------- +$1f801xx8 Attack/Decay/Sustain level +bit |0f|0e 0d 0c 0b 0a 09 08|07 06 05 04|03 02 01 00| +desc.|Am| Ar |Dr |Sl | + +Am 0 Attack mode Linear + 1 Exponential + +Ar 0-7f attack rate +Dr 0-f decay rate +Sl 0-f sustain level +------------------------------------------------------------- +$1f801xxa Sustain rate, Release Rate. +bit |0f|0e|0d|0c 0b 0a 09 08 07 06|05|04 03 02 01 00| +desc.|Sm|Sd| 0| Sr |Rm|Rr | + +Sm 0 sustain rate mode linear + 1 exponential +Sd 0 sustain rate mode increase + 1 decrease +Sr 0-7f Sustain Rate +Rm 0 Linear decrease + 1 Exponential decrease +Rr 0-1f Release Rate + +Note: decay mode is always Expontial decrease, and thus cannot +be set. +------------------------------------------------------------- +$1f801xxc Current ADSR volume +bit |0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00| +desc.|ADSRvol | + +ADSRvol Returns the current envelope volume when + read. +-- James' Note: return range: 0 -> 32767 + +*** doomed doc extract end *** + +By using a small PSX proggie to visualise the envelope as it was played, +the following results for envelope timing were obtained: + +1. Attack rate value (linear mode) + + Attack value range: 0 -> 127 + + Value | 48 | 52 | 56 | 60 | 64 | 68 | 72 | | 80 | + ----------------------------------------------------------------- + Frames | 11 | 21 | 42 | 84 | 169| 338| 676| |2890| + + Note: frames is no. of PAL frames to reach full volume (100% + amplitude) + + Hmm, noticing that the time taken to reach full volume doubles + every time we add 4 to our attack value, we know the equation is + of form: + frames = k * 2 ^ (value / 4) + + (You may ponder about envelope generator hardware at this point, + or maybe not... :) + + By substituting some stuff and running some checks, we get: + + k = 0.00257 (close enuf) + + therefore, + frames = 0.00257 * 2 ^ (value / 4) + If you just happen to be writing an emulator, then you can probably + use an equation like: + + %volume_increase_per_tick = 1 / frames + + + ------------------------------------ + Pete: + ms=((1<<(value>>2))*514)/10000 + ------------------------------------ + +2. Decay rate value (only has log mode) + + Decay value range: 0 -> 15 + + Value | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | + ------------------------------------------------ + frames | | | | | 6 | 12 | 24 | 47 | + + Note: frames here is no. of PAL frames to decay to 50% volume. + + formula: frames = k * 2 ^ (value) + + Substituting, we get: k = 0.00146 + + Further info on logarithmic nature: + frames to decay to sustain level 3 = 3 * frames to decay to + sustain level 9 + + Also no. of frames to 25% volume = roughly 1.85 * no. of frames to + 50% volume. + + Frag it - just use linear approx. + + ------------------------------------ + Pete: + ms=((1< 127 + + Value | 48 | 52 | 56 | 60 | 64 | 68 | 72 | + ------------------------------------------- + frames | 9 | 19 | 37 | 74 | 147| 293| 587| + + Here, frames = no. of PAL frames for volume amplitude to go from 100% + to 0% (or vice-versa). + + Same formula as for attack value, just a different value for k: + + k = 0.00225 + + ie: frames = 0.00225 * 2 ^ (value / 4) + + For emulation purposes: + + %volume_increase_or_decrease_per_tick = 1 / frames + + ------------------------------------ + Pete: + ms=((1<<(value>>2))*450)/10000 + ------------------------------------ + + +4. Release rate (linear mode) + + Release rate range: 0 -> 31 + + Value | 13 | 14 | 15 | 16 | 17 | + --------------------------------------------------------------- + frames | 18 | 36 | 73 | 146| 292| + + Here, frames = no. of PAL frames to decay from 100% vol to 0% vol + after "note-off" is triggered. + + Formula: frames = k * 2 ^ (value) + + And so: k = 0.00223 + + ------------------------------------ + Pete: + ms=((1< release phase + { + if(s_chan[ch].ADSR.ReleaseVal!=0) // -> release not 0: do release (if 0: stop right now) + { + if(!s_chan[ch].ADSR.ReleaseVol) // --> release just started? set up the release stuff + { + s_chan[ch].ADSR.ReleaseStartTime=s_chan[ch].ADSR.lTime; + s_chan[ch].ADSR.ReleaseVol=s_chan[ch].ADSR.lVolume; + s_chan[ch].ADSR.ReleaseTime = // --> calc how long does it take to reach the wanted sus level + (s_chan[ch].ADSR.ReleaseTime* + s_chan[ch].ADSR.ReleaseVol)/1024; + } + // -> NO release exp mode used (yet) + v=s_chan[ch].ADSR.ReleaseVol; // -> get last volume + lT=s_chan[ch].ADSR.lTime- // -> how much time is past? + s_chan[ch].ADSR.ReleaseStartTime; + l1=s_chan[ch].ADSR.ReleaseTime; + + if(lT we still have to release + { + v=v-((v*lT)/l1); // --> calc new volume + } + else // -> release is over: now really stop that sample + {v=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0;} + } + else // -> release IS 0: release at once + { + v=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0; + } + } + else + {//--------------------------------------------------// not in release phase: + v=1024; + lT=s_chan[ch].ADSR.lTime; + l1=s_chan[ch].ADSR.AttackTime; + + if(lT0) + { + if(l3!=0) v2+=((v-v2)*lT)/l3; + else v2=v; + } + else + { + if(l3!=0) v2-=(v2*lT)/l3; + else v2=v; + } + + if(v2>v) v2=v; + if(v2<=0) {v2=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0;} + + v=v2; + } + } + } + + //----------------------------------------------------// + // ok, done for this channel, so increase time + + s_chan[ch].ADSR.lTime+=1; // 1 = 1.020408f ms; + + if(v>1024) v=1024; // adjust volume + if(v<0) v=0; + s_chan[ch].ADSR.lVolume=v; // store act volume + + return v; // return the volume factor +*/ + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + + +/* +----------------------------------------------------------------------------- +Neill Corlett +Playstation SPU envelope timing notes +----------------------------------------------------------------------------- + +This is preliminary. This may be wrong. But the model described herein fits +all of my experimental data, and it's just simple enough to sound right. + +ADSR envelope level ranges from 0x00000000 to 0x7FFFFFFF internally. +The value returned by channel reg 0xC is (envelope_level>>16). + +Each sample, an increment or decrement value will be added to or +subtracted from this envelope level. + +Create the rate log table. The values double every 4 entries. + entry #0 = 4 + + 4, 5, 6, 7, + 8,10,12,14, + 16,20,24,28, ... + + entry #40 = 4096... + entry #44 = 8192... + entry #48 = 16384... + entry #52 = 32768... + entry #56 = 65536... + +increments and decrements are in terms of ratelogtable[n] +n may exceed the table bounds (plan on n being between -32 and 127). +table values are all clipped between 0x00000000 and 0x3FFFFFFF + +when you "voice on", the envelope is always fully reset. +(yes, it may click. the real thing does this too.) + +envelope level begins at zero. + +each state happens for at least 1 cycle +(transitions are not instantaneous) +this may result in some oddness: if the decay rate is uberfast, it will cut +the envelope from full down to half in one sample, potentially skipping over +the sustain level + +ATTACK +------ +- if the envelope level has overflowed past the max, clip to 0x7FFFFFFF and + proceed to DECAY. + +Linear attack mode: +- line extends upward to 0x7FFFFFFF +- increment per sample is ratelogtable[(Ar^0x7F)-0x10] + +Logarithmic attack mode: +if envelope_level < 0x60000000: + - line extends upward to 0x60000000 + - increment per sample is ratelogtable[(Ar^0x7F)-0x10] +else: + - line extends upward to 0x7FFFFFFF + - increment per sample is ratelogtable[(Ar^0x7F)-0x18] + +DECAY +----- +- if ((envelope_level>>27)&0xF) <= Sl, proceed to SUSTAIN. + Do not clip to the sustain level. +- current line ends at (envelope_level & 0x07FFFFFF) +- decrement per sample depends on (envelope_level>>28)&0x7 + 0: ratelogtable[(4*(Dr^0x1F))-0x18+0] + 1: ratelogtable[(4*(Dr^0x1F))-0x18+4] + 2: ratelogtable[(4*(Dr^0x1F))-0x18+6] + 3: ratelogtable[(4*(Dr^0x1F))-0x18+8] + 4: ratelogtable[(4*(Dr^0x1F))-0x18+9] + 5: ratelogtable[(4*(Dr^0x1F))-0x18+10] + 6: ratelogtable[(4*(Dr^0x1F))-0x18+11] + 7: ratelogtable[(4*(Dr^0x1F))-0x18+12] + (note that this is the same as the release rate formula, except that + decay rates 10-1F aren't possible... those would be slower in theory) + +SUSTAIN +------- +- no terminating condition except for voice off +- Sd=0 (increase) behavior is identical to ATTACK for both log and linear. +- Sd=1 (decrease) behavior: +Linear sustain decrease: +- line extends to 0x00000000 +- decrement per sample is ratelogtable[(Sr^0x7F)-0x0F] +Logarithmic sustain decrease: +- current line ends at (envelope_level & 0x07FFFFFF) +- decrement per sample depends on (envelope_level>>28)&0x7 + 0: ratelogtable[(Sr^0x7F)-0x1B+0] + 1: ratelogtable[(Sr^0x7F)-0x1B+4] + 2: ratelogtable[(Sr^0x7F)-0x1B+6] + 3: ratelogtable[(Sr^0x7F)-0x1B+8] + 4: ratelogtable[(Sr^0x7F)-0x1B+9] + 5: ratelogtable[(Sr^0x7F)-0x1B+10] + 6: ratelogtable[(Sr^0x7F)-0x1B+11] + 7: ratelogtable[(Sr^0x7F)-0x1B+12] + +RELEASE +------- +- if the envelope level has overflowed to negative, clip to 0 and QUIT. + +Linear release mode: +- line extends to 0x00000000 +- decrement per sample is ratelogtable[(4*(Rr^0x1F))-0x0C] + +Logarithmic release mode: +- line extends to (envelope_level & 0x0FFFFFFF) +- decrement per sample depends on (envelope_level>>28)&0x7 + 0: ratelogtable[(4*(Rr^0x1F))-0x18+0] + 1: ratelogtable[(4*(Rr^0x1F))-0x18+4] + 2: ratelogtable[(4*(Rr^0x1F))-0x18+6] + 3: ratelogtable[(4*(Rr^0x1F))-0x18+8] + 4: ratelogtable[(4*(Rr^0x1F))-0x18+9] + 5: ratelogtable[(4*(Rr^0x1F))-0x18+10] + 6: ratelogtable[(4*(Rr^0x1F))-0x18+11] + 7: ratelogtable[(4*(Rr^0x1F))-0x18+12] + +----------------------------------------------------------------------------- +*/ + diff --git a/plugins/dfsound/adsr.h b/plugins/dfsound/adsr.h new file mode 100644 index 0000000..ff2af1f --- /dev/null +++ b/plugins/dfsound/adsr.h @@ -0,0 +1,19 @@ +/*************************************************************************** + adsr.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +INLINE void StartADSR(int ch); +INLINE int MixADSR(int ch); diff --git a/plugins/dfsound/alsa.c b/plugins/dfsound/alsa.c new file mode 100644 index 0000000..2eba878 --- /dev/null +++ b/plugins/dfsound/alsa.c @@ -0,0 +1,158 @@ +/*************************************************************************** + alsa.c - description + ------------------- + begin : Sat Mar 01 2003 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#include "stdafx.h" + +#define _IN_OSS + +#include "externals.h" + +#define ALSA_PCM_NEW_HW_PARAMS_API +#define ALSA_PCM_NEW_SW_PARAMS_API +#include + +static snd_pcm_t *handle = NULL; +static snd_pcm_uframes_t buffer_size; + +// SETUP SOUND +void SetupSound(void) +{ + snd_pcm_hw_params_t *hwparams; + snd_pcm_status_t *status; + unsigned int pspeed; + int pchannels; + int format; + unsigned int buffer_time = 100000; + unsigned int period_time = buffer_time / 4; + int err; + + if (iDisStereo) pchannels = 1; + else pchannels=2; + + pspeed = 44100; + format = SND_PCM_FORMAT_S16; + + if ((err = snd_pcm_open(&handle, "default", + SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0) + { + printf("Audio open error: %s\n", snd_strerror(err)); + return; + } + + if((err = snd_pcm_nonblock(handle, 0))<0) + { + printf("Can't set blocking moded: %s\n", snd_strerror(err)); + return; + } + + snd_pcm_hw_params_alloca(&hwparams); + + if((err=snd_pcm_hw_params_any(handle, hwparams))<0) + { + printf("Broken configuration for this PCM: %s\n", snd_strerror(err)); + return; + } + + if((err=snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED))<0) + { + printf("Access type not available: %s\n", snd_strerror(err)); + return; + } + + if((err=snd_pcm_hw_params_set_format(handle, hwparams, format))<0) + { + printf("Sample format not available: %s\n", snd_strerror(err)); + return; + } + + if((err=snd_pcm_hw_params_set_channels(handle, hwparams, pchannels))<0) + { + printf("Channels count not available: %s\n", snd_strerror(err)); + return; + } + + if((err=snd_pcm_hw_params_set_rate_near(handle, hwparams, &pspeed, 0))<0) + { + printf("Rate not available: %s\n", snd_strerror(err)); + return; + } + + if((err=snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, 0))<0) + { + printf("Buffer time error: %s\n", snd_strerror(err)); + return; + } + + if((err=snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, 0))<0) + { + printf("Period time error: %s\n", snd_strerror(err)); + return; + } + + if((err=snd_pcm_hw_params(handle, hwparams))<0) + { + printf("Unable to install hw params: %s\n", snd_strerror(err)); + return; + } + + snd_pcm_status_alloca(&status); + if((err=snd_pcm_status(handle, status))<0) + { + printf("Unable to get status: %s\n", snd_strerror(err)); + return; + } + + buffer_size = snd_pcm_status_get_avail(status); +} + +// REMOVE SOUND +void RemoveSound(void) +{ + if(handle != NULL) + { + snd_pcm_drop(handle); + snd_pcm_close(handle); + handle = NULL; + } +} + +// GET BYTES BUFFERED +unsigned long SoundGetBytesBuffered(void) +{ + unsigned long l; + + if (handle == NULL) // failed to open? + return SOUNDSIZE; + l = snd_pcm_avail(handle); + if (l < 0) return 0; + if (l < buffer_size / 2) // can we write in at least the half of fragments? + l = SOUNDSIZE; // -> no? wait + else l = 0; // -> else go on + + return l; +} + +// FEED SOUND DATA +void SoundFeedStreamData(unsigned char* pSound,long lBytes) +{ + if (handle == NULL) return; + + if (snd_pcm_state(handle) == SND_PCM_STATE_XRUN) + snd_pcm_prepare(handle); + snd_pcm_writei(handle,pSound, + iDisStereo ? lBytes / 2 : lBytes / 4); +} diff --git a/plugins/dfsound/cfg.c b/plugins/dfsound/cfg.c new file mode 100644 index 0000000..2acb9c3 --- /dev/null +++ b/plugins/dfsound/cfg.c @@ -0,0 +1,167 @@ +/*************************************************************************** + cfg.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#include "stdafx.h" + +#define _IN_CFG + +#include "externals.h" + +//////////////////////////////////////////////////////////////////////// +// LINUX CONFIG/ABOUT HANDLING +//////////////////////////////////////////////////////////////////////// + +#include + +//////////////////////////////////////////////////////////////////////// +// START EXTERNAL CFG TOOL +//////////////////////////////////////////////////////////////////////// + +void StartCfgTool(char * pCmdLine) +{ + FILE * cf; + char filename[255]; + + strcpy(filename,"cfgDFSound"); + cf=fopen(filename,"rb"); + if(cf!=NULL) + { + fclose(cf); + if(fork()==0) + { + execl("./cfgDFSound","cfgDFSound",pCmdLine,NULL); + exit(0); + } + } + else + { + strcpy(filename,"cfg/cfgDFSound"); + cf=fopen(filename,"rb"); + if(cf!=NULL) + { + fclose(cf); + if(fork()==0) + { + chdir("cfg"); + execl("./cfgDFSound","cfgDFSound",pCmdLine,NULL); + exit(0); + } + } + else + { + sprintf(filename,"%s/cfgDFSound",getenv("HOME")); + cf=fopen(filename,"rb"); + if(cf!=NULL) + { + fclose(cf); + if(fork()==0) + { + chdir(getenv("HOME")); + execl("./cfgDFSound","cfgDFSound",pCmdLine,NULL); + exit(0); + } + } + else printf("Sound error: cfgDFSound not found!\n"); + } + } +} + +///////////////////////////////////////////////////////// +// READ LINUX CONFIG FILE +///////////////////////////////////////////////////////// + +void ReadConfigFile(void) +{ + FILE *in;char t[256];int len; + char * pB, * p; + + strcpy(t,"dfsound.cfg"); + in = fopen(t,"rb"); + if(!in) + { + strcpy(t,"cfg/dfsound.cfg"); + in = fopen(t,"rb"); + if(!in) + { + sprintf(t,"%s/dfsound.cfg",getenv("HOME")); + in = fopen(t,"rb"); + if(!in) return; + } + } + + pB = (char *)malloc(32767); + memset(pB,0,32767); + + len = fread(pB, 1, 32767, in); + fclose(in); + + strcpy(t,"\nVolume");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + if(p) iVolume=4-atoi(p+len); + if(iVolume<1) iVolume=1; + if(iVolume>4) iVolume=4; + + strcpy(t,"\nXAPitch");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + if(p) iXAPitch=atoi(p+len); + if(iXAPitch<0) iXAPitch=0; + if(iXAPitch>1) iXAPitch=1; + + strcpy(t,"\nHighCompMode");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + if(p) iUseTimer=atoi(p+len); + if(iUseTimer<0) iUseTimer=0; + // note: timer mode 1 (win time events) is not supported + // in linux. But timer mode 2 (spuupdate) is safe to use. + if(iUseTimer) iUseTimer=2; + + strcpy(t,"\nSPUIRQWait");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + if(p) iSPUIRQWait=atoi(p+len); + if(iSPUIRQWait<0) iSPUIRQWait=0; + if(iSPUIRQWait>1) iSPUIRQWait=1; + + strcpy(t,"\nUseReverb");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + if(p) iUseReverb=atoi(p+len); + if(iUseReverb<0) iUseReverb=0; + if(iUseReverb>2) iUseReverb=2; + + strcpy(t,"\nUseInterpolation");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + if(p) iUseInterpolation=atoi(p+len); + if(iUseInterpolation<0) iUseInterpolation=0; + if(iUseInterpolation>3) iUseInterpolation=3; + + strcpy(t,"\nDisStereo");p=strstr(pB,t);if(p) {p=strstr(p,"=");len=1;} + if(p) iDisStereo=atoi(p+len); + if(iDisStereo<0) iDisStereo=0; + if(iDisStereo>1) iDisStereo=1; + + free(pB); +} + +///////////////////////////////////////////////////////// +// READ CONFIG called by spu funcs +///////////////////////////////////////////////////////// + +void ReadConfig(void) +{ + iVolume=2; + iXAPitch=0; + iSPUIRQWait=1; + iUseTimer=2; + iUseReverb=2; + iUseInterpolation=2; + iDisStereo=0; + + ReadConfigFile(); +} diff --git a/plugins/dfsound/cfg.h b/plugins/dfsound/cfg.h new file mode 100644 index 0000000..f64d6d6 --- /dev/null +++ b/plugins/dfsound/cfg.h @@ -0,0 +1,19 @@ +/*************************************************************************** + cfg.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +void ReadConfig(void); +void StartCfgTool(char * pCmdLine); diff --git a/plugins/dfsound/dma.c b/plugins/dfsound/dma.c new file mode 100644 index 0000000..f92d066 --- /dev/null +++ b/plugins/dfsound/dma.c @@ -0,0 +1,97 @@ +/*************************************************************************** + dma.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#include "stdafx.h" + +#define _IN_DMA + +#include "externals.h" + +//////////////////////////////////////////////////////////////////////// +// READ DMA (one value) +//////////////////////////////////////////////////////////////////////// + +unsigned short CALLBACK SPUreadDMA(void) +{ + unsigned short s=spuMem[spuAddr>>1]; + spuAddr+=2; + if(spuAddr>0x7ffff) spuAddr=0; + + iSpuAsyncWait=0; + + return s; +} + +//////////////////////////////////////////////////////////////////////// +// READ DMA (many values) +//////////////////////////////////////////////////////////////////////// + +void CALLBACK SPUreadDMAMem(unsigned short * pusPSXMem,int iSize) +{ + int i; + + for(i=0;i>1]; // spu addr got by writeregister + spuAddr+=2; // inc spu addr + if(spuAddr>0x7ffff) spuAddr=0; // wrap + } + + iSpuAsyncWait=0; +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +// to investigate: do sound data updates by writedma affect spu +// irqs? Will an irq be triggered, if new data is written to +// the memory irq address? + +//////////////////////////////////////////////////////////////////////// +// WRITE DMA (one value) +//////////////////////////////////////////////////////////////////////// + +void CALLBACK SPUwriteDMA(unsigned short val) +{ + spuMem[spuAddr>>1] = val; // spu addr got by writeregister + + spuAddr+=2; // inc spu addr + if(spuAddr>0x7ffff) spuAddr=0; // wrap + + iSpuAsyncWait=0; +} + +//////////////////////////////////////////////////////////////////////// +// WRITE DMA (many values) +//////////////////////////////////////////////////////////////////////// + +void CALLBACK SPUwriteDMAMem(unsigned short * pusPSXMem,int iSize) +{ + int i; + + for(i=0;i>1] = *pusPSXMem++; // spu addr got by writeregister + spuAddr+=2; // inc spu addr + if(spuAddr>0x7ffff) spuAddr=0; // wrap + } + + iSpuAsyncWait=0; +} + +//////////////////////////////////////////////////////////////////////// diff --git a/plugins/dfsound/dma.h b/plugins/dfsound/dma.h new file mode 100644 index 0000000..440536f --- /dev/null +++ b/plugins/dfsound/dma.h @@ -0,0 +1,31 @@ +/*************************************************************************** + dma.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + + +unsigned short CALLBACK SPUreadDMA(void); +void CALLBACK SPUreadDMAMem(unsigned short * pusPSXMem,int iSize); +void CALLBACK SPUwriteDMA(unsigned short val); +void CALLBACK SPUwriteDMAMem(unsigned short * pusPSXMem,int iSize); diff --git a/plugins/dfsound/dsoundoss.h b/plugins/dfsound/dsoundoss.h new file mode 100644 index 0000000..3702312 --- /dev/null +++ b/plugins/dfsound/dsoundoss.h @@ -0,0 +1,22 @@ +/*************************************************************************** + dsoundoss.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +void SetupSound(void); +void RemoveSound(void); +unsigned long SoundGetBytesBuffered(void); +void SoundFeedStreamData(unsigned char* pSound,long lBytes); +unsigned long timeGetTime_spu(); diff --git a/plugins/dfsound/externals.h b/plugins/dfsound/externals.h new file mode 100644 index 0000000..f856204 --- /dev/null +++ b/plugins/dfsound/externals.h @@ -0,0 +1,286 @@ +/*************************************************************************** + externals.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#include + +///////////////////////////////////////////////////////// +// generic defines +///////////////////////////////////////////////////////// + +#define PSE_LT_SPU 4 +#define PSE_SPU_ERR_SUCCESS 0 +#define PSE_SPU_ERR -60 +#define PSE_SPU_ERR_NOTCONFIGURED PSE_SPU_ERR - 1 +#define PSE_SPU_ERR_INIT PSE_SPU_ERR - 2 +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +//////////////////////////////////////////////////////////////////////// +// spu defines +//////////////////////////////////////////////////////////////////////// + +// sound buffer sizes +// 400 ms complete sound buffer +#define SOUNDSIZE 70560 +// 137 ms test buffer... if less than that is buffered, a new upload will happen +#define TESTSIZE 24192 + +// num of channels +#define MAXCHAN 24 + +// ~ 1 ms of data +#define NSSIZE 45 + +/////////////////////////////////////////////////////////// +// struct defines +/////////////////////////////////////////////////////////// + +// ADSR INFOS PER CHANNEL +typedef struct +{ + int AttackModeExp; + long AttackTime; + long DecayTime; + long SustainLevel; + int SustainModeExp; + long SustainModeDec; + long SustainTime; + int ReleaseModeExp; + unsigned long ReleaseVal; + long ReleaseTime; + long ReleaseStartTime; + long ReleaseVol; + long lTime; + long lVolume; +} ADSRInfo; + +typedef struct +{ + int State; + int AttackModeExp; + int AttackRate; + int DecayRate; + int SustainLevel; + int SustainModeExp; + int SustainIncrease; + int SustainRate; + int ReleaseModeExp; + int ReleaseRate; + int EnvelopeVol; + long lVolume; + long lDummy1; + long lDummy2; +} ADSRInfoEx; + +/////////////////////////////////////////////////////////// + +// Tmp Flags + +// used for debug channel muting +#define FLAG_MUTE 1 + +// used for simple interpolation +#define FLAG_IPOL0 2 +#define FLAG_IPOL1 4 + +/////////////////////////////////////////////////////////// + +// MAIN CHANNEL STRUCT +typedef struct +{ + // no mutexes used anymore... don't need them to sync access + //HANDLE hMutex; + + int bNew; // start flag + + int iSBPos; // mixing stuff + int spos; + int sinc; + int SB[32+32]; // Pete added another 32 dwords in 1.6 ... prevents overflow issues with gaussian/cubic interpolation (thanx xodnizel!), and can be used for even better interpolations, eh? :) + int sval; + + unsigned char * pStart; // start ptr into sound mem + unsigned char * pCurr; // current pos in sound mem + unsigned char * pLoop; // loop ptr in sound mem + + int bOn; // is channel active (sample playing?) + int bStop; // is channel stopped (sample _can_ still be playing, ADSR Release phase) + int bReverb; // can we do reverb on this channel? must have ctrl register bit, to get active + int iActFreq; // current psx pitch + int iUsedFreq; // current pc pitch + int iLeftVolume; // left volume + int iLeftVolRaw; // left psx volume value + int bIgnoreLoop; // ignore loop bit, if an external loop address is used + int iMute; // mute mode + int iRightVolume; // right volume + int iRightVolRaw; // right psx volume value + int iRawPitch; // raw pitch (0...3fff) + int iIrqDone; // debug irq done flag + int s_1; // last decoding infos + int s_2; + int bRVBActive; // reverb active flag + int iRVBOffset; // reverb offset + int iRVBRepeat; // reverb repeat + int bNoise; // noise active flag + int bFMod; // freq mod (0=off, 1=sound channel, 2=freq channel) + int iRVBNum; // another reverb helper + int iOldNoise; // old noise val for this channel + ADSRInfo ADSR; // active ADSR settings + ADSRInfoEx ADSRX; // next ADSR settings (will be moved to active on sample start) +} SPUCHAN; + +/////////////////////////////////////////////////////////// + +typedef struct +{ + int StartAddr; // reverb area start addr in samples + int CurrAddr; // reverb area curr addr in samples + + int VolLeft; + int VolRight; + int iLastRVBLeft; + int iLastRVBRight; + int iRVBLeft; + int iRVBRight; + + int FB_SRC_A; // (offset) + int FB_SRC_B; // (offset) + int IIR_ALPHA; // (coef.) + int ACC_COEF_A; // (coef.) + int ACC_COEF_B; // (coef.) + int ACC_COEF_C; // (coef.) + int ACC_COEF_D; // (coef.) + int IIR_COEF; // (coef.) + int FB_ALPHA; // (coef.) + int FB_X; // (coef.) + int IIR_DEST_A0; // (offset) + int IIR_DEST_A1; // (offset) + int ACC_SRC_A0; // (offset) + int ACC_SRC_A1; // (offset) + int ACC_SRC_B0; // (offset) + int ACC_SRC_B1; // (offset) + int IIR_SRC_A0; // (offset) + int IIR_SRC_A1; // (offset) + int IIR_DEST_B0; // (offset) + int IIR_DEST_B1; // (offset) + int ACC_SRC_C0; // (offset) + int ACC_SRC_C1; // (offset) + int ACC_SRC_D0; // (offset) + int ACC_SRC_D1; // (offset) + int IIR_SRC_B1; // (offset) + int IIR_SRC_B0; // (offset) + int MIX_DEST_A0; // (offset) + int MIX_DEST_A1; // (offset) + int MIX_DEST_B0; // (offset) + int MIX_DEST_B1; // (offset) + int IN_COEF_L; // (coef.) + int IN_COEF_R; // (coef.) +} REVERBInfo; + +/////////////////////////////////////////////////////////// +// SPU.C globals +/////////////////////////////////////////////////////////// + +#ifndef _IN_SPU + +// psx buffers / addresses + +extern unsigned short regArea[]; +extern unsigned short spuMem[]; +extern unsigned char * spuMemC; +extern unsigned char * pSpuIrq; +extern unsigned char * pSpuBuffer; + +// user settings + +extern int iVolume; +extern int iXAPitch; +extern int iUseTimer; +extern int iSPUIRQWait; +extern int iDebugMode; +extern int iRecordMode; +extern int iUseReverb; +extern int iUseInterpolation; +extern int iDisStereo; +// MISC + +extern int iSpuAsyncWait; + +extern SPUCHAN s_chan[]; +extern REVERBInfo rvb; + +extern unsigned long dwNoiseVal; +extern unsigned short spuCtrl; +extern unsigned short spuStat; +extern unsigned short spuIrq; +extern unsigned long spuAddr; +extern int bEndThread; +extern int bThreadEnded; +extern int bSpuInit; +extern unsigned long dwNewChannel; + +extern int SSumR[]; +extern int SSumL[]; +extern int iCycle; +extern short * pS; + +extern void (CALLBACK *cddavCallback)(unsigned short,unsigned short); + +#endif + +/////////////////////////////////////////////////////////// +// XA.C globals +/////////////////////////////////////////////////////////// + +#ifndef _IN_XA + +extern xa_decode_t * xapGlobal; + +extern uint32_t * XAFeed; +extern uint32_t * XAPlay; +extern uint32_t * XAStart; +extern uint32_t * XAEnd; + +extern uint32_t XARepeat; +extern uint32_t XALastVal; + +extern uint32_t * CDDAFeed; +extern uint32_t * CDDAPlay; +extern uint32_t * CDDAStart; +extern uint32_t * CDDAEnd; + +extern int iLeftXAVol; +extern int iRightXAVol; + +#endif + +/////////////////////////////////////////////////////////// +// REVERB.C globals +/////////////////////////////////////////////////////////// + +#ifndef _IN_REVERB + +extern int * sRVBPlay; +extern int * sRVBEnd; +extern int * sRVBStart; +extern int iReverbOff; +extern int iReverbRepeat; +extern int iReverbNum; + +#endif diff --git a/plugins/dfsound/freeze.c b/plugins/dfsound/freeze.c new file mode 100644 index 0000000..12fdc1f --- /dev/null +++ b/plugins/dfsound/freeze.c @@ -0,0 +1,214 @@ +/*************************************************************************** + freeze.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#include "stdafx.h" + +#define _IN_FREEZE + +#include "externals.h" +#include "registers.h" +#include "spu.h" +#include "regs.h" + +//////////////////////////////////////////////////////////////////////// +// freeze structs +//////////////////////////////////////////////////////////////////////// + +typedef struct +{ + char szSPUName[8]; + uint32_t ulFreezeVersion; + uint32_t ulFreezeSize; + unsigned char cSPUPort[0x200]; + unsigned char cSPURam[0x80000]; + xa_decode_t xaS; +} SPUFreeze_t; + +typedef struct +{ + unsigned short spuIrq; + uint32_t pSpuIrq; + uint32_t spuAddr; + uint32_t dummy1; + uint32_t dummy2; + uint32_t dummy3; + + SPUCHAN s_chan[MAXCHAN]; + +} SPUOSSFreeze_t; + +//////////////////////////////////////////////////////////////////////// + +void LoadStateV5(SPUFreeze_t * pF); // newest version +void LoadStateUnknown(SPUFreeze_t * pF); // unknown format + +extern int lastch; + +//////////////////////////////////////////////////////////////////////// +// SPUFREEZE: called by main emu on savestate load/save +//////////////////////////////////////////////////////////////////////// + +long CALLBACK SPUfreeze(uint32_t ulFreezeMode,SPUFreeze_t * pF) +{ + int i;SPUOSSFreeze_t * pFO; + + if(!pF) return 0; // first check + + if(ulFreezeMode) // info or save? + {//--------------------------------------------------// + if(ulFreezeMode==1) + memset(pF,0,sizeof(SPUFreeze_t)+sizeof(SPUOSSFreeze_t)); + + strcpy(pF->szSPUName,"PBOSS"); + pF->ulFreezeVersion=5; + pF->ulFreezeSize=sizeof(SPUFreeze_t)+sizeof(SPUOSSFreeze_t); + + if(ulFreezeMode==2) return 1; // info mode? ok, bye + // save mode: + RemoveTimer(); // stop timer + + memcpy(pF->cSPURam,spuMem,0x80000); // copy common infos + memcpy(pF->cSPUPort,regArea,0x200); + + if(xapGlobal && XAPlay!=XAFeed) // some xa + { + pF->xaS=*xapGlobal; + } + else + memset(&pF->xaS,0,sizeof(xa_decode_t)); // or clean xa + + pFO=(SPUOSSFreeze_t *)(pF+1); // store special stuff + + pFO->spuIrq=spuIrq; + if(pSpuIrq) pFO->pSpuIrq = (unsigned long)pSpuIrq-(unsigned long)spuMemC; + + pFO->spuAddr=spuAddr; + if(pFO->spuAddr==0) pFO->spuAddr=0xbaadf00d; + + for(i=0;is_chan[i],(void *)&s_chan[i],sizeof(SPUCHAN)); + if(pFO->s_chan[i].pStart) + pFO->s_chan[i].pStart-=(unsigned long)spuMemC; + if(pFO->s_chan[i].pCurr) + pFO->s_chan[i].pCurr-=(unsigned long)spuMemC; + if(pFO->s_chan[i].pLoop) + pFO->s_chan[i].pLoop-=(unsigned long)spuMemC; + } + + SetupTimer(); // sound processing on again + + return 1; + //--------------------------------------------------// + } + + if(ulFreezeMode!=0) return 0; // bad mode? bye + + RemoveTimer(); // we stop processing while doing the save! + + memcpy(spuMem,pF->cSPURam,0x80000); // get ram + memcpy(regArea,pF->cSPUPort,0x200); + + if(pF->xaS.nsamples<=4032) // start xa again + SPUplayADPCMchannel(&pF->xaS); + + xapGlobal=0; + + if(!strcmp(pF->szSPUName,"PBOSS") && pF->ulFreezeVersion==5) + LoadStateV5(pF); + else LoadStateUnknown(pF); + + lastch = -1; + + // repair some globals + for(i=0;i<=62;i+=2) + SPUwriteRegister(H_Reverb+i,regArea[(H_Reverb+i-0xc00)>>1]); + SPUwriteRegister(H_SPUReverbAddr,regArea[(H_SPUReverbAddr-0xc00)>>1]); + SPUwriteRegister(H_SPUrvolL,regArea[(H_SPUrvolL-0xc00)>>1]); + SPUwriteRegister(H_SPUrvolR,regArea[(H_SPUrvolR-0xc00)>>1]); + + SPUwriteRegister(H_SPUctrl,(unsigned short)(regArea[(H_SPUctrl-0xc00)>>1]|0x4000)); + SPUwriteRegister(H_SPUstat,regArea[(H_SPUstat-0xc00)>>1]); + SPUwriteRegister(H_CDLeft,regArea[(H_CDLeft-0xc00)>>1]); + SPUwriteRegister(H_CDRight,regArea[(H_CDRight-0xc00)>>1]); + + // fix to prevent new interpolations from crashing + for(i=0;ispuIrq; + if(pFO->pSpuIrq) pSpuIrq = pFO->pSpuIrq+spuMemC; else pSpuIrq=NULL; + + if(pFO->spuAddr) + { + spuAddr = pFO->spuAddr; + if (spuAddr == 0xbaadf00d) spuAddr = 0; + } + + for(i=0;is_chan[i],sizeof(SPUCHAN)); + + s_chan[i].pStart+=(unsigned long)spuMemC; + s_chan[i].pCurr+=(unsigned long)spuMemC; + s_chan[i].pLoop+=(unsigned long)spuMemC; + s_chan[i].iMute=0; + s_chan[i].iIrqDone=0; + } +} + +//////////////////////////////////////////////////////////////////////// + +void LoadStateUnknown(SPUFreeze_t * pF) +{ + int i; + + for(i=0;i>1)) // can we write in at least the half of fragments? + l=SOUNDSIZE; // -> no? wait + else l=0; // -> else go on + } + + return l; +} + +//////////////////////////////////////////////////////////////////////// +// FEED SOUND DATA +//////////////////////////////////////////////////////////////////////// + +void SoundFeedStreamData(unsigned char* pSound,long lBytes) +{ + if(oss_audio_fd == -1) return; + write(oss_audio_fd,pSound,lBytes); +} diff --git a/plugins/dfsound/psemuxa.h b/plugins/dfsound/psemuxa.h new file mode 100644 index 0000000..84c6260 --- /dev/null +++ b/plugins/dfsound/psemuxa.h @@ -0,0 +1,28 @@ +//============================================ +//=== Audio XA decoding +//=== Kazzuya +//============================================ + +#ifndef DECODEXA_H +#define DECODEXA_H + +typedef struct +{ + long y0, y1; +} ADPCM_Decode_t; + +typedef struct +{ + int freq; + int nbits; + int stereo; + int nsamples; + ADPCM_Decode_t left, right; + short pcm[16384]; +} xa_decode_t; + +long xa_decode_sector( xa_decode_t *xdp, + unsigned char *sectorp, + int is_first_sector ); + +#endif diff --git a/plugins/dfsound/pulseaudio.c b/plugins/dfsound/pulseaudio.c new file mode 100644 index 0000000..6005155 --- /dev/null +++ b/plugins/dfsound/pulseaudio.c @@ -0,0 +1,354 @@ +/*************************************************************************** + pulseaudio.c - description + ------------------- +begin : Thu Feb 04 2010 +copyright : (C) 2010 by Tristin Celestin +email : cetris1@umbc.edu +comment : Much of this was taken from simple.c, in the pulseaudio + library +***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#include "stdafx.h" + +#ifdef USEPULSEAUDIO + +#define _IN_OSS + +#include "externals.h" +#include + +//////////////////////////////////////////////////////////////////////// +// pulseaudio structs +//////////////////////////////////////////////////////////////////////// + +typedef struct { + pa_threaded_mainloop *mainloop; + pa_context *context; + pa_mainloop_api *api; + pa_stream *stream; + pa_sample_spec spec; + int first; +} Device; + +typedef struct { + unsigned int frequency; + unsigned int latency_in_msec; +} Settings; + +//////////////////////////////////////////////////////////////////////// +// pulseaudio globals +//////////////////////////////////////////////////////////////////////// + +static Device device = { + .mainloop = NULL, + .api = NULL, + .context = NULL, + .stream = NULL +}; + +static Settings settings = { + .frequency = 44100, + .latency_in_msec = 20, +}; + +// the number of bytes written in SoundFeedStreamData +const int mixlen = 3240; + +// used to calculate how much space is used in the buffer, for debugging purposes +//int maxlength = 0; + +//////////////////////////////////////////////////////////////////////// +// CALLBACKS FOR THREADED MAINLOOP +//////////////////////////////////////////////////////////////////////// +static void context_state_cb (pa_context *context, void *userdata) +{ + Device *dev = userdata; + + if ((context == NULL) || (dev == NULL)) + return; + + switch (pa_context_get_state (context)) + { + case PA_CONTEXT_READY: + case PA_CONTEXT_TERMINATED: + case PA_CONTEXT_FAILED: + pa_threaded_mainloop_signal (dev->mainloop, 0); + break; + + case PA_CONTEXT_UNCONNECTED: + case PA_CONTEXT_CONNECTING: + case PA_CONTEXT_AUTHORIZING: + case PA_CONTEXT_SETTING_NAME: + break; + } +} + +static void stream_state_cb (pa_stream *stream, void * userdata) +{ + Device *dev = userdata; + + if ((stream == NULL) || (dev == NULL)) + return; + + switch (pa_stream_get_state (stream)) + { + case PA_STREAM_READY: + case PA_STREAM_FAILED: + case PA_STREAM_TERMINATED: + pa_threaded_mainloop_signal (dev->mainloop, 0); + break; + + case PA_STREAM_UNCONNECTED: + case PA_STREAM_CREATING: + break; + } +} + +static void stream_latency_update_cb (pa_stream *stream, void *userdata) +{ + Device *dev = userdata; + + if ((stream == NULL) || (dev == NULL)) + return; + + pa_threaded_mainloop_signal (dev->mainloop, 0); +} + +static void stream_request_cb (pa_stream *stream, size_t length, void *userdata) +{ + Device *dev = userdata; + + if ((stream == NULL) || (dev == NULL)) + return; + pa_threaded_mainloop_signal (dev->mainloop, 0); +} + +//////////////////////////////////////////////////////////////////////// +// SETUP SOUND +//////////////////////////////////////////////////////////////////////// + +void SetupSound (void) +{ + int error_number; + + // Acquire mainloop /////////////////////////////////////////////////////// + device.mainloop = pa_threaded_mainloop_new (); + if (device.mainloop == NULL) + { + fprintf (stderr, "Could not acquire PulseAudio main loop\n"); + return; + } + + // Acquire context //////////////////////////////////////////////////////// + device.api = pa_threaded_mainloop_get_api (device.mainloop); + device.context = pa_context_new (device.api, "PCSX"); + pa_context_set_state_callback (device.context, context_state_cb, &device); + + if (device.context == NULL) + { + fprintf (stderr, "Could not acquire PulseAudio device context\n"); + return; + } + + // Connect to PulseAudio server /////////////////////////////////////////// + if (pa_context_connect (device.context, NULL, 0, NULL) < 0) + { + error_number = pa_context_errno (device.context); + fprintf (stderr, "Could not connect to PulseAudio server: %s\n", pa_strerror(error_number)); + return; + } + + // Run mainloop until sever context is ready ////////////////////////////// + pa_threaded_mainloop_lock (device.mainloop); + if (pa_threaded_mainloop_start (device.mainloop) < 0) + { + fprintf (stderr, "Could not start mainloop\n"); + return; + } + + pa_context_state_t context_state; + context_state = pa_context_get_state (device.context); + while (context_state != PA_CONTEXT_READY) + { + context_state = pa_context_get_state (device.context); + if (! PA_CONTEXT_IS_GOOD (context_state)) + { + error_number = pa_context_errno (device.context); + fprintf (stderr, "Context state is not good: %s\n", pa_strerror (error_number)); + return; + } + else if (context_state == PA_CONTEXT_READY) + break; + else + fprintf (stderr, "PulseAudio context state is %d\n", context_state); + pa_threaded_mainloop_wait (device.mainloop); + } + + // Set sample spec //////////////////////////////////////////////////////// + device.spec.format = PA_SAMPLE_S16NE; + if (iDisStereo) + device.spec.channels = 1; + else + device.spec.channels = 2; + device.spec.rate = settings.frequency; + + pa_buffer_attr buffer_attributes; + buffer_attributes.tlength = pa_bytes_per_second (& device.spec) / 5; + buffer_attributes.maxlength = buffer_attributes.tlength * 3; + buffer_attributes.minreq = buffer_attributes.tlength / 3; + buffer_attributes.prebuf = buffer_attributes.tlength; + + //maxlength = buffer_attributes.maxlength; + //fprintf (stderr, "Total space: %u\n", buffer_attributes.maxlength); + //fprintf (stderr, "Minimum request size: %u\n", buffer_attributes.minreq); + //fprintf (stderr, "Bytes needed before playback: %u\n", buffer_attributes.prebuf); + //fprintf (stderr, "Target buffer size: %lu\n", buffer_attributes.tlength); + + // Acquire new stream using spec ////////////////////////////////////////// + device.stream = pa_stream_new (device.context, "PCSX", &device.spec, NULL); + if (device.stream == NULL) + { + error_number = pa_context_errno (device.context); + fprintf (stderr, "Could not acquire new PulseAudio stream: %s\n", pa_strerror (error_number)); + return; + } + + // Set callbacks for server events //////////////////////////////////////// + pa_stream_set_state_callback (device.stream, stream_state_cb, &device); + pa_stream_set_write_callback (device.stream, stream_request_cb, &device); + pa_stream_set_latency_update_callback (device.stream, stream_latency_update_cb, &device); + + // Ready stream for playback ////////////////////////////////////////////// + pa_stream_flags_t flags = (pa_stream_flags_t) (PA_STREAM_ADJUST_LATENCY | PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE); + //pa_stream_flags_t flags = (pa_stream_flags_t) (PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_EARLY_REQUESTS); + if (pa_stream_connect_playback (device.stream, NULL, &buffer_attributes, flags, NULL, NULL) < 0) + { + pa_context_errno (device.context); + fprintf (stderr, "Could not connect for playback: %s\n", pa_strerror (error_number)); + return; + } + + // Run mainloop until stream is ready ///////////////////////////////////// + pa_stream_state_t stream_state; + stream_state = pa_stream_get_state (device.stream); + while (stream_state != PA_STREAM_READY) + { + stream_state = pa_stream_get_state (device.stream); + + if (stream_state == PA_STREAM_READY) + break; + + else if (! PA_STREAM_IS_GOOD (stream_state)) + { + error_number = pa_context_errno (device.context); + fprintf (stderr, "Stream state is not good: %s\n", pa_strerror (error_number)); + return; + } + else + fprintf (stderr, "PulseAudio stream state is %d\n", stream_state); + pa_threaded_mainloop_wait (device.mainloop); + } + + pa_threaded_mainloop_unlock (device.mainloop); + + fprintf (stderr, "PulseAudio should be connected\n"); + return; +} + +//////////////////////////////////////////////////////////////////////// +// REMOVE SOUND +//////////////////////////////////////////////////////////////////////// +void RemoveSound (void) +{ + if (device.mainloop != NULL) + pa_threaded_mainloop_stop (device.mainloop); + + // Release in reverse order of acquisition + if (device.stream != NULL) + { + pa_stream_unref (device.stream); + device.stream = NULL; + + } + if (device.context != NULL) + { + pa_context_disconnect (device.context); + pa_context_unref (device.context); + device.context = NULL; + } + + if (device.mainloop != NULL) + { + pa_threaded_mainloop_free (device.mainloop); + device.mainloop = NULL; + } + +} + +//////////////////////////////////////////////////////////////////////// +// GET BYTES BUFFERED +//////////////////////////////////////////////////////////////////////// + +unsigned long SoundGetBytesBuffered (void) +{ + int free_space; + int error_code; + long latency; + int playing = 0; + + if ((device.mainloop == NULL) || (device.api == NULL) || ( device.context == NULL) || (device.stream == NULL)) + return SOUNDSIZE; + + pa_threaded_mainloop_lock (device.mainloop); + free_space = pa_stream_writable_size (device.stream); + pa_threaded_mainloop_unlock (device.mainloop); + + //fprintf (stderr, "Free space: %d\n", free_space); + //fprintf (stderr, "Used space: %d\n", maxlength - free_space); + if (free_space < mixlen * 3) + { + // Don't buffer anymore, just play + //fprintf (stderr, "Not buffering.\n"); + return SOUNDSIZE; + } + else + { + // Buffer some sound + //fprintf (stderr, "Buffering.\n"); + return 0; + } +} + +//////////////////////////////////////////////////////////////////////// +// FEED SOUND DATA +//////////////////////////////////////////////////////////////////////// + +void SoundFeedStreamData (unsigned char *pSound, long lBytes) +{ + int error_code; + int size; + + if (device.mainloop != NULL) + { + pa_threaded_mainloop_lock (device.mainloop); + if (pa_stream_write (device.stream, pSound, lBytes, NULL, 0LL, PA_SEEK_RELATIVE) < 0) + { + fprintf (stderr, "Could not perform write\n"); + } + else + { + //fprintf (stderr, "Wrote %d bytes\n", lBytes); + pa_threaded_mainloop_unlock (device.mainloop); + } + } +} +#endif diff --git a/plugins/dfsound/registers.c b/plugins/dfsound/registers.c new file mode 100644 index 0000000..b684914 --- /dev/null +++ b/plugins/dfsound/registers.c @@ -0,0 +1,589 @@ +/*************************************************************************** + registers.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#include "stdafx.h" + +#define _IN_REGISTERS + +#include "externals.h" +#include "registers.h" +#include "regs.h" +#include "reverb.h" + +/* +// adsr time values (in ms) by James Higgs ... see the end of +// the adsr.c source for details + +#define ATTACK_MS 514L +#define DECAYHALF_MS 292L +#define DECAY_MS 584L +#define SUSTAIN_MS 450L +#define RELEASE_MS 446L +*/ + +// we have a timebase of 1.020408f ms, not 1 ms... so adjust adsr defines +#define ATTACK_MS 494L +#define DECAYHALF_MS 286L +#define DECAY_MS 572L +#define SUSTAIN_MS 441L +#define RELEASE_MS 437L + +//////////////////////////////////////////////////////////////////////// +// WRITE REGISTERS: called by main emu +//////////////////////////////////////////////////////////////////////// + +void CALLBACK SPUwriteRegister(unsigned long reg, unsigned short val) +{ + const unsigned long r=reg&0xfff; + regArea[(r-0xc00)>>1] = val; + + if(r>=0x0c00 && r<0x0d80) // some channel info? + { + int ch=(r>>4)-0xc0; // calc channel + switch(r&0x0f) + { + //------------------------------------------------// r volume + case 0: + SetVolumeL((unsigned char)ch,val); + break; + //------------------------------------------------// l volume + case 2: + SetVolumeR((unsigned char)ch,val); + break; + //------------------------------------------------// pitch + case 4: + SetPitch(ch,val); + break; + //------------------------------------------------// start + case 6: + s_chan[ch].pStart=spuMemC+((unsigned long) val<<3); + break; + //------------------------------------------------// level with pre-calcs + case 8: + { + const unsigned long lval=val;unsigned long lx; + //---------------------------------------------// + s_chan[ch].ADSRX.AttackModeExp=(lval&0x8000)?1:0; + s_chan[ch].ADSRX.AttackRate=(lval>>8) & 0x007f; + s_chan[ch].ADSRX.DecayRate=(lval>>4) & 0x000f; + s_chan[ch].ADSRX.SustainLevel=lval & 0x000f; + //---------------------------------------------// + if(!iDebugMode) break; + //---------------------------------------------// stuff below is only for debug mode + + s_chan[ch].ADSR.AttackModeExp=(lval&0x8000)?1:0; //0x007f + + lx=(((lval>>8) & 0x007f)>>2); // attack time to run from 0 to 100% volume + lx=min(31,lx); // no overflow on shift! + if(lx) + { + lx = (1<>4) & 0x000f; // decay: + if(lx) // our const decay value is time it takes from 100% to 0% of volume + { + lx = ((1<<(lx))*DECAY_MS)/10000L; + if(!lx) lx=1; + } + s_chan[ch].ADSR.DecayTime = // so calc how long does it take to run from 100% to the wanted sus level + (lx*(1024-s_chan[ch].ADSR.SustainLevel))/1024; + } + break; + //------------------------------------------------// adsr times with pre-calcs + case 10: + { + const unsigned long lval=val;unsigned long lx; + + //----------------------------------------------// + s_chan[ch].ADSRX.SustainModeExp = (lval&0x8000)?1:0; + s_chan[ch].ADSRX.SustainIncrease= (lval&0x4000)?0:1; + s_chan[ch].ADSRX.SustainRate = (lval>>6) & 0x007f; + s_chan[ch].ADSRX.ReleaseModeExp = (lval&0x0020)?1:0; + s_chan[ch].ADSRX.ReleaseRate = lval & 0x001f; + //----------------------------------------------// + if(!iDebugMode) break; + //----------------------------------------------// stuff below is only for debug mode + + s_chan[ch].ADSR.SustainModeExp = (lval&0x8000)?1:0; + s_chan[ch].ADSR.ReleaseModeExp = (lval&0x0020)?1:0; + + lx=((((lval>>6) & 0x007f)>>2)); // sustain time... often very high + lx=min(31,lx); // values are used to hold the volume + if(lx) // until a sound stop occurs + { // the highest value we reach (due to + lx = (1< no multithread fuckups + s_chan[ch].pLoop=spuMemC+((unsigned long) val<<3); + s_chan[ch].bIgnoreLoop=1; + //ReleaseMutex(s_chan[ch].hMutex); // -> oki, on with the thread + break; + //------------------------------------------------// + } + iSpuAsyncWait=0; + return; + } + + switch(r) + { + //-------------------------------------------------// + case H_SPUaddr: + spuAddr = (unsigned long) val<<3; + break; + //-------------------------------------------------// + case H_SPUdata: + spuMem[spuAddr>>1] = val; + spuAddr+=2; + if(spuAddr>0x7ffff) spuAddr=0; + break; + //-------------------------------------------------// + case H_SPUctrl: + spuCtrl=val; + break; + //-------------------------------------------------// + case H_SPUstat: + spuStat=val & 0xf800; + break; + //-------------------------------------------------// + case H_SPUReverbAddr: + if(val==0xFFFF || val<=0x200) + {rvb.StartAddr=rvb.CurrAddr=0;} + else + { + const long iv=(unsigned long)val<<2; + if(rvb.StartAddr!=iv) + { + rvb.StartAddr=(unsigned long)val<<2; + rvb.CurrAddr=rvb.StartAddr; + } + } + break; + //-------------------------------------------------// + case H_SPUirqAddr: + spuIrq = val; + pSpuIrq=spuMemC+((unsigned long) val<<3); + break; + //-------------------------------------------------// + case H_SPUrvolL: + rvb.VolLeft=val; + break; + //-------------------------------------------------// + case H_SPUrvolR: + rvb.VolRight=val; + break; + //-------------------------------------------------// + +/* + case H_ExtLeft: + //auxprintf("EL %d\n",val); + break; + //-------------------------------------------------// + case H_ExtRight: + //auxprintf("ER %d\n",val); + break; + //-------------------------------------------------// + case H_SPUmvolL: + //auxprintf("ML %d\n",val); + break; + //-------------------------------------------------// + case H_SPUmvolR: + //auxprintf("MR %d\n",val); + break; + //-------------------------------------------------// + case H_SPUMute1: + //auxprintf("M0 %04x\n",val); + break; + //-------------------------------------------------// + case H_SPUMute2: + //auxprintf("M1 %04x\n",val); + break; +*/ + //-------------------------------------------------// + case H_SPUon1: + SoundOn(0,16,val); + break; + //-------------------------------------------------// + case H_SPUon2: + SoundOn(16,24,val); + break; + //-------------------------------------------------// + case H_SPUoff1: + SoundOff(0,16,val); + break; + //-------------------------------------------------// + case H_SPUoff2: + SoundOff(16,24,val); + break; + //-------------------------------------------------// + case H_CDLeft: + iLeftXAVol=val & 0x7fff; + if(cddavCallback) cddavCallback(0,val); + break; + case H_CDRight: + iRightXAVol=val & 0x7fff; + if(cddavCallback) cddavCallback(1,val); + break; + //-------------------------------------------------// + case H_FMod1: + FModOn(0,16,val); + break; + //-------------------------------------------------// + case H_FMod2: + FModOn(16,24,val); + break; + //-------------------------------------------------// + case H_Noise1: + NoiseOn(0,16,val); + break; + //-------------------------------------------------// + case H_Noise2: + NoiseOn(16,24,val); + break; + //-------------------------------------------------// + case H_RVBon1: + ReverbOn(0,16,val); + break; + //-------------------------------------------------// + case H_RVBon2: + ReverbOn(16,24,val); + break; + //-------------------------------------------------// + case H_Reverb+0: + + rvb.FB_SRC_A=val; + + // OK, here's the fake REVERB stuff... + // depending on effect we do more or less delay and repeats... bah + // still... better than nothing :) + + SetREVERB(val); + break; + + + case H_Reverb+2 : rvb.FB_SRC_B=(short)val; break; + case H_Reverb+4 : rvb.IIR_ALPHA=(short)val; break; + case H_Reverb+6 : rvb.ACC_COEF_A=(short)val; break; + case H_Reverb+8 : rvb.ACC_COEF_B=(short)val; break; + case H_Reverb+10 : rvb.ACC_COEF_C=(short)val; break; + case H_Reverb+12 : rvb.ACC_COEF_D=(short)val; break; + case H_Reverb+14 : rvb.IIR_COEF=(short)val; break; + case H_Reverb+16 : rvb.FB_ALPHA=(short)val; break; + case H_Reverb+18 : rvb.FB_X=(short)val; break; + case H_Reverb+20 : rvb.IIR_DEST_A0=(short)val; break; + case H_Reverb+22 : rvb.IIR_DEST_A1=(short)val; break; + case H_Reverb+24 : rvb.ACC_SRC_A0=(short)val; break; + case H_Reverb+26 : rvb.ACC_SRC_A1=(short)val; break; + case H_Reverb+28 : rvb.ACC_SRC_B0=(short)val; break; + case H_Reverb+30 : rvb.ACC_SRC_B1=(short)val; break; + case H_Reverb+32 : rvb.IIR_SRC_A0=(short)val; break; + case H_Reverb+34 : rvb.IIR_SRC_A1=(short)val; break; + case H_Reverb+36 : rvb.IIR_DEST_B0=(short)val; break; + case H_Reverb+38 : rvb.IIR_DEST_B1=(short)val; break; + case H_Reverb+40 : rvb.ACC_SRC_C0=(short)val; break; + case H_Reverb+42 : rvb.ACC_SRC_C1=(short)val; break; + case H_Reverb+44 : rvb.ACC_SRC_D0=(short)val; break; + case H_Reverb+46 : rvb.ACC_SRC_D1=(short)val; break; + case H_Reverb+48 : rvb.IIR_SRC_B1=(short)val; break; + case H_Reverb+50 : rvb.IIR_SRC_B0=(short)val; break; + case H_Reverb+52 : rvb.MIX_DEST_A0=(short)val; break; + case H_Reverb+54 : rvb.MIX_DEST_A1=(short)val; break; + case H_Reverb+56 : rvb.MIX_DEST_B0=(short)val; break; + case H_Reverb+58 : rvb.MIX_DEST_B1=(short)val; break; + case H_Reverb+60 : rvb.IN_COEF_L=(short)val; break; + case H_Reverb+62 : rvb.IN_COEF_R=(short)val; break; + } + + iSpuAsyncWait=0; +} + +//////////////////////////////////////////////////////////////////////// +// READ REGISTER: called by main emu +//////////////////////////////////////////////////////////////////////// + +unsigned short CALLBACK SPUreadRegister(unsigned long reg) +{ + const unsigned long r=reg&0xfff; + + iSpuAsyncWait=0; + + if(r>=0x0c00 && r<0x0d80) + { + switch(r&0x0f) + { + case 12: // get adsr vol + { + const int ch=(r>>4)-0xc0; + if(s_chan[ch].bNew) return 1; // we are started, but not processed? return 1 + if(s_chan[ch].ADSRX.lVolume && // same here... we haven't decoded one sample yet, so no envelope yet. return 1 as well + !s_chan[ch].ADSRX.EnvelopeVol) + return 1; + return (unsigned short)(s_chan[ch].ADSRX.EnvelopeVol>>16); + } + + case 14: // get loop address + { + const int ch=(r>>4)-0xc0; + if(s_chan[ch].pLoop==NULL) return 0; + return (unsigned short)((s_chan[ch].pLoop-spuMemC)>>3); + } + } + } + + switch(r) + { + case H_SPUctrl: + return spuCtrl; + + case H_SPUstat: + return spuStat; + + case H_SPUaddr: + return (unsigned short)(spuAddr>>3); + + case H_SPUdata: + { + unsigned short s=spuMem[spuAddr>>1]; + spuAddr+=2; + if(spuAddr>0x7ffff) spuAddr=0; + return s; + } + + case H_SPUirqAddr: + return spuIrq; + + //case H_SPUIsOn1: + // return IsSoundOn(0,16); + + //case H_SPUIsOn2: + // return IsSoundOn(16,24); + + } + + return regArea[(r-0xc00)>>1]; +} + +//////////////////////////////////////////////////////////////////////// +// SOUND ON register write +//////////////////////////////////////////////////////////////////////// + +void SoundOn(int start,int end,unsigned short val) // SOUND ON PSX COMAND +{ + int ch; + + for(ch=start;ch>=1) // loop channels + { + if((val&1) && s_chan[ch].pStart) // mmm... start has to be set before key on !?! + { + s_chan[ch].bIgnoreLoop=0; + s_chan[ch].bNew=1; + dwNewChannel|=(1<>=1) // loop channels + { + if(val&1) // && s_chan[i].bOn) mmm... + { + s_chan[ch].bStop=1; + } + } +} + +//////////////////////////////////////////////////////////////////////// +// FMOD register write +//////////////////////////////////////////////////////////////////////// + +void FModOn(int start,int end,unsigned short val) // FMOD ON PSX COMMAND +{ + int ch; + + for(ch=start;ch>=1) // loop channels + { + if(val&1) // -> fmod on/off + { + if(ch>0) + { + s_chan[ch].bFMod=1; // --> sound channel + s_chan[ch-1].bFMod=2; // --> freq channel + } + } + else + { + s_chan[ch].bFMod=0; // --> turn off fmod + } + } +} + +//////////////////////////////////////////////////////////////////////// +// NOISE register write +//////////////////////////////////////////////////////////////////////// + +void NoiseOn(int start,int end,unsigned short val) // NOISE ON PSX COMMAND +{ + int ch; + + for(ch=start;ch>=1) // loop channels + { + if(val&1) // -> noise on/off + { + s_chan[ch].bNoise=1; + } + else + { + s_chan[ch].bNoise=0; + } + } +} + +//////////////////////////////////////////////////////////////////////// +// LEFT VOLUME register write +//////////////////////////////////////////////////////////////////////// + +// please note: sweep and phase invert are wrong... but I've never seen +// them used + +void SetVolumeL(unsigned char ch,short vol) // LEFT VOLUME +{ + s_chan[ch].iLeftVolRaw=vol; + + if(vol&0x8000) // sweep? + { + short sInc=1; // -> sweep up? + if(vol&0x2000) sInc=-1; // -> or down? + if(vol&0x1000) vol^=0xffff; // -> mmm... phase inverted? have to investigate this + vol=((vol&0x7f)+1)/2; // -> sweep: 0..127 -> 0..64 + vol+=vol/(2*sInc); // -> HACK: we don't sweep right now, so we just raise/lower the volume by the half! + vol*=128; + } + else // no sweep: + { + if(vol&0x4000) // -> mmm... phase inverted? have to investigate this + //vol^=0xffff; + vol=0x3fff-(vol&0x3fff); + } + + vol&=0x3fff; + s_chan[ch].iLeftVolume=vol; // store volume +} + +//////////////////////////////////////////////////////////////////////// +// RIGHT VOLUME register write +//////////////////////////////////////////////////////////////////////// + +void SetVolumeR(unsigned char ch,short vol) // RIGHT VOLUME +{ + s_chan[ch].iRightVolRaw=vol; + + if(vol&0x8000) // comments... see above :) + { + short sInc=1; + if(vol&0x2000) sInc=-1; + if(vol&0x1000) vol^=0xffff; + vol=((vol&0x7f)+1)/2; + vol+=vol/(2*sInc); + vol*=128; + } + else + { + if(vol&0x4000) //vol=vol^=0xffff; + vol=0x3fff-(vol&0x3fff); + } + + vol&=0x3fff; + + s_chan[ch].iRightVolume=vol; +} + +//////////////////////////////////////////////////////////////////////// +// PITCH register write +//////////////////////////////////////////////////////////////////////// + +void SetPitch(int ch,unsigned short val) // SET PITCH +{ + int NP; + if(val>0x3fff) NP=0x3fff; // get pitch val + else NP=val; + + s_chan[ch].iRawPitch=NP; + + NP=(44100L*NP)/4096L; // calc frequency + if(NP<1) NP=1; // some security + s_chan[ch].iActFreq=NP; // store frequency +} + +//////////////////////////////////////////////////////////////////////// +// REVERB register write +//////////////////////////////////////////////////////////////////////// + +void ReverbOn(int start,int end,unsigned short val) // REVERB ON PSX COMMAND +{ + int ch; + + for(ch=start;ch>=1) // loop channels + { + if(val&1) // -> reverb on/off + { + s_chan[ch].bReverb=1; + } + else + { + s_chan[ch].bReverb=0; + } + } +} diff --git a/plugins/dfsound/registers.h b/plugins/dfsound/registers.h new file mode 100644 index 0000000..f2a9397 --- /dev/null +++ b/plugins/dfsound/registers.h @@ -0,0 +1,144 @@ +/*************************************************************************** + registers.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#define H_SPUReverbAddr 0x0da2 +#define H_SPUirqAddr 0x0da4 +#define H_SPUaddr 0x0da6 +#define H_SPUdata 0x0da8 +#define H_SPUctrl 0x0daa +#define H_SPUstat 0x0dae +#define H_SPUmvolL 0x0d80 +#define H_SPUmvolR 0x0d82 +#define H_SPUrvolL 0x0d84 +#define H_SPUrvolR 0x0d86 +#define H_SPUon1 0x0d88 +#define H_SPUon2 0x0d8a +#define H_SPUoff1 0x0d8c +#define H_SPUoff2 0x0d8e +#define H_FMod1 0x0d90 +#define H_FMod2 0x0d92 +#define H_Noise1 0x0d94 +#define H_Noise2 0x0d96 +#define H_RVBon1 0x0d98 +#define H_RVBon2 0x0d9a +#define H_SPUMute1 0x0d9c +#define H_SPUMute2 0x0d9e +#define H_CDLeft 0x0db0 +#define H_CDRight 0x0db2 +#define H_ExtLeft 0x0db4 +#define H_ExtRight 0x0db6 +#define H_Reverb 0x0dc0 +#define H_SPUPitch0 0x0c04 +#define H_SPUPitch1 0x0c14 +#define H_SPUPitch2 0x0c24 +#define H_SPUPitch3 0x0c34 +#define H_SPUPitch4 0x0c44 +#define H_SPUPitch5 0x0c54 +#define H_SPUPitch6 0x0c64 +#define H_SPUPitch7 0x0c74 +#define H_SPUPitch8 0x0c84 +#define H_SPUPitch9 0x0c94 +#define H_SPUPitch10 0x0ca4 +#define H_SPUPitch11 0x0cb4 +#define H_SPUPitch12 0x0cc4 +#define H_SPUPitch13 0x0cd4 +#define H_SPUPitch14 0x0ce4 +#define H_SPUPitch15 0x0cf4 +#define H_SPUPitch16 0x0d04 +#define H_SPUPitch17 0x0d14 +#define H_SPUPitch18 0x0d24 +#define H_SPUPitch19 0x0d34 +#define H_SPUPitch20 0x0d44 +#define H_SPUPitch21 0x0d54 +#define H_SPUPitch22 0x0d64 +#define H_SPUPitch23 0x0d74 + +#define H_SPUStartAdr0 0x0c06 +#define H_SPUStartAdr1 0x0c16 +#define H_SPUStartAdr2 0x0c26 +#define H_SPUStartAdr3 0x0c36 +#define H_SPUStartAdr4 0x0c46 +#define H_SPUStartAdr5 0x0c56 +#define H_SPUStartAdr6 0x0c66 +#define H_SPUStartAdr7 0x0c76 +#define H_SPUStartAdr8 0x0c86 +#define H_SPUStartAdr9 0x0c96 +#define H_SPUStartAdr10 0x0ca6 +#define H_SPUStartAdr11 0x0cb6 +#define H_SPUStartAdr12 0x0cc6 +#define H_SPUStartAdr13 0x0cd6 +#define H_SPUStartAdr14 0x0ce6 +#define H_SPUStartAdr15 0x0cf6 +#define H_SPUStartAdr16 0x0d06 +#define H_SPUStartAdr17 0x0d16 +#define H_SPUStartAdr18 0x0d26 +#define H_SPUStartAdr19 0x0d36 +#define H_SPUStartAdr20 0x0d46 +#define H_SPUStartAdr21 0x0d56 +#define H_SPUStartAdr22 0x0d66 +#define H_SPUStartAdr23 0x0d76 + +#define H_SPULoopAdr0 0x0c0e +#define H_SPULoopAdr1 0x0c1e +#define H_SPULoopAdr2 0x0c2e +#define H_SPULoopAdr3 0x0c3e +#define H_SPULoopAdr4 0x0c4e +#define H_SPULoopAdr5 0x0c5e +#define H_SPULoopAdr6 0x0c6e +#define H_SPULoopAdr7 0x0c7e +#define H_SPULoopAdr8 0x0c8e +#define H_SPULoopAdr9 0x0c9e +#define H_SPULoopAdr10 0x0cae +#define H_SPULoopAdr11 0x0cbe +#define H_SPULoopAdr12 0x0cce +#define H_SPULoopAdr13 0x0cde +#define H_SPULoopAdr14 0x0cee +#define H_SPULoopAdr15 0x0cfe +#define H_SPULoopAdr16 0x0d0e +#define H_SPULoopAdr17 0x0d1e +#define H_SPULoopAdr18 0x0d2e +#define H_SPULoopAdr19 0x0d3e +#define H_SPULoopAdr20 0x0d4e +#define H_SPULoopAdr21 0x0d5e +#define H_SPULoopAdr22 0x0d6e +#define H_SPULoopAdr23 0x0d7e + +#define H_SPU_ADSRLevel0 0x0c08 +#define H_SPU_ADSRLevel1 0x0c18 +#define H_SPU_ADSRLevel2 0x0c28 +#define H_SPU_ADSRLevel3 0x0c38 +#define H_SPU_ADSRLevel4 0x0c48 +#define H_SPU_ADSRLevel5 0x0c58 +#define H_SPU_ADSRLevel6 0x0c68 +#define H_SPU_ADSRLevel7 0x0c78 +#define H_SPU_ADSRLevel8 0x0c88 +#define H_SPU_ADSRLevel9 0x0c98 +#define H_SPU_ADSRLevel10 0x0ca8 +#define H_SPU_ADSRLevel11 0x0cb8 +#define H_SPU_ADSRLevel12 0x0cc8 +#define H_SPU_ADSRLevel13 0x0cd8 +#define H_SPU_ADSRLevel14 0x0ce8 +#define H_SPU_ADSRLevel15 0x0cf8 +#define H_SPU_ADSRLevel16 0x0d08 +#define H_SPU_ADSRLevel17 0x0d18 +#define H_SPU_ADSRLevel18 0x0d28 +#define H_SPU_ADSRLevel19 0x0d38 +#define H_SPU_ADSRLevel20 0x0d48 +#define H_SPU_ADSRLevel21 0x0d58 +#define H_SPU_ADSRLevel22 0x0d68 +#define H_SPU_ADSRLevel23 0x0d78 + diff --git a/plugins/dfsound/regs.h b/plugins/dfsound/regs.h new file mode 100644 index 0000000..3d2689b --- /dev/null +++ b/plugins/dfsound/regs.h @@ -0,0 +1,27 @@ +/*************************************************************************** + regs.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +void SoundOn(int start,int end,unsigned short val); +void SoundOff(int start,int end,unsigned short val); +void FModOn(int start,int end,unsigned short val); +void NoiseOn(int start,int end,unsigned short val); +void SetVolumeL(unsigned char ch,short vol); +void SetVolumeR(unsigned char ch,short vol); +void SetPitch(int ch,unsigned short val); +void ReverbOn(int start,int end,unsigned short val); +void CALLBACK SPUwriteRegister(unsigned long reg, unsigned short val); + diff --git a/plugins/dfsound/reverb.c b/plugins/dfsound/reverb.c new file mode 100644 index 0000000..92e31fc --- /dev/null +++ b/plugins/dfsound/reverb.c @@ -0,0 +1,462 @@ +/*************************************************************************** + reverb.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#include "stdafx.h" + +#define _IN_REVERB + +// will be included from spu.c +#ifdef _IN_SPU + +//////////////////////////////////////////////////////////////////////// +// globals +//////////////////////////////////////////////////////////////////////// + +// REVERB info and timing vars... + +int * sRVBPlay = 0; +int * sRVBEnd = 0; +int * sRVBStart = 0; +int iReverbOff = -1; // some delay factor for reverb +int iReverbRepeat = 0; +int iReverbNum = 1; + +//////////////////////////////////////////////////////////////////////// +// SET REVERB +//////////////////////////////////////////////////////////////////////// + +void SetREVERB(unsigned short val) +{ + switch(val) + { + case 0x0000: iReverbOff=-1; break; // off + case 0x007D: iReverbOff=32; iReverbNum=2; iReverbRepeat=128; break; // ok room + + case 0x0033: iReverbOff=32; iReverbNum=2; iReverbRepeat=64; break; // studio small + case 0x00B1: iReverbOff=48; iReverbNum=2; iReverbRepeat=96; break; // ok studio medium + case 0x00E3: iReverbOff=64; iReverbNum=2; iReverbRepeat=128; break; // ok studio large ok + + case 0x01A5: iReverbOff=128; iReverbNum=4; iReverbRepeat=32; break; // ok hall + case 0x033D: iReverbOff=256; iReverbNum=4; iReverbRepeat=64; break; // space echo + case 0x0001: iReverbOff=184; iReverbNum=3; iReverbRepeat=128; break; // echo/delay + case 0x0017: iReverbOff=128; iReverbNum=2; iReverbRepeat=128; break; // half echo + default: iReverbOff=32; iReverbNum=1; iReverbRepeat=0; break; + } +} + +//////////////////////////////////////////////////////////////////////// +// START REVERB +//////////////////////////////////////////////////////////////////////// + +INLINE void StartREVERB(int ch) +{ + if(s_chan[ch].bReverb && (spuCtrl&0x80)) // reverb possible? + { + if(iUseReverb==2) s_chan[ch].bRVBActive=1; + else + if(iUseReverb==1 && iReverbOff>0) // -> fake reverb used? + { + s_chan[ch].bRVBActive=1; // -> activate it + s_chan[ch].iRVBOffset=iReverbOff*45; + s_chan[ch].iRVBRepeat=iReverbRepeat*45; + s_chan[ch].iRVBNum =iReverbNum; + } + } + else s_chan[ch].bRVBActive=0; // else -> no reverb +} + +//////////////////////////////////////////////////////////////////////// +// HELPER FOR NEILL'S REVERB: re-inits our reverb mixing buf +//////////////////////////////////////////////////////////////////////// + +INLINE void InitREVERB(void) +{ + if(iUseReverb==2) + {memset(sRVBStart,0,NSSIZE*2*4);} +} + +//////////////////////////////////////////////////////////////////////// +// STORE REVERB +//////////////////////////////////////////////////////////////////////// + +INLINE void StoreREVERB(int ch,int ns) +{ + if(iUseReverb==0) return; + else + if(iUseReverb==2) // -------------------------------- // Neil's reverb + { + const int iRxl=(s_chan[ch].sval*s_chan[ch].iLeftVolume)/0x4000; + const int iRxr=(s_chan[ch].sval*s_chan[ch].iRightVolume)/0x4000; + + ns<<=1; + + *(sRVBStart+ns) +=iRxl; // -> we mix all active reverb channels into an extra buffer + *(sRVBStart+ns+1)+=iRxr; + } + else // --------------------------------------------- // Pete's easy fake reverb + { + int * pN;int iRn,iRr=0; + + // we use the half channel volume (/0x8000) for the first reverb effects, quarter for next and so on + + int iRxl=(s_chan[ch].sval*s_chan[ch].iLeftVolume)/0x8000; + int iRxr=(s_chan[ch].sval*s_chan[ch].iRightVolume)/0x8000; + + for(iRn=1;iRn<=s_chan[ch].iRVBNum;iRn++,iRr+=s_chan[ch].iRVBRepeat,iRxl/=2,iRxr/=2) + { + pN=sRVBPlay+((s_chan[ch].iRVBOffset+iRr+ns)<<1); + if(pN>=sRVBEnd) pN=sRVBStart+(pN-sRVBEnd); + + (*pN)+=iRxl; + pN++; + (*pN)+=iRxr; + } + } +} + +//////////////////////////////////////////////////////////////////////// + +INLINE int g_buffer(int iOff) // get_buffer content helper: takes care about wraps +{ + short * p=(short *)spuMem; + iOff=(iOff*4)+rvb.CurrAddr; + while(iOff>0x3FFFF) iOff=rvb.StartAddr+(iOff-0x40000); + while(iOff0x3FFFF) iOff=rvb.StartAddr+(iOff-0x40000); + while(iOff32767L) iVal=32767L; + *(p+iOff)=(short)iVal; +} + +//////////////////////////////////////////////////////////////////////// + +INLINE void s_buffer1(int iOff,int iVal) // set_buffer (+1 sample) content helper: takes care about wraps and clipping +{ + short * p=(short *)spuMem; + iOff=(iOff*4)+rvb.CurrAddr+1; + while(iOff>0x3FFFF) iOff=rvb.StartAddr+(iOff-0x40000); + while(iOff32767L) iVal=32767L; + *(p+iOff)=(short)iVal; +} + +//////////////////////////////////////////////////////////////////////// + +INLINE int MixREVERBLeft(int ns) +{ + if(iUseReverb==0) return 0; + else + if(iUseReverb==2) + { + static int iCnt=0; // this func will be called with 44.1 khz + + if(!rvb.StartAddr) // reverb is off + { + rvb.iLastRVBLeft=rvb.iLastRVBRight=rvb.iRVBLeft=rvb.iRVBRight=0; + return 0; + } + + iCnt++; + + if(iCnt&1) // we work on every second left value: downsample to 22 khz + { + if(spuCtrl&0x80) // -> reverb on? oki + { + int ACC0,ACC1,FB_A0,FB_A1,FB_B0,FB_B1; + + const int INPUT_SAMPLE_L=*(sRVBStart+(ns<<1)); + const int INPUT_SAMPLE_R=*(sRVBStart+(ns<<1)+1); + + const int IIR_INPUT_A0 = (g_buffer(rvb.IIR_SRC_A0) * rvb.IIR_COEF)/32768L + (INPUT_SAMPLE_L * rvb.IN_COEF_L)/32768L; + const int IIR_INPUT_A1 = (g_buffer(rvb.IIR_SRC_A1) * rvb.IIR_COEF)/32768L + (INPUT_SAMPLE_R * rvb.IN_COEF_R)/32768L; + const int IIR_INPUT_B0 = (g_buffer(rvb.IIR_SRC_B0) * rvb.IIR_COEF)/32768L + (INPUT_SAMPLE_L * rvb.IN_COEF_L)/32768L; + const int IIR_INPUT_B1 = (g_buffer(rvb.IIR_SRC_B1) * rvb.IIR_COEF)/32768L + (INPUT_SAMPLE_R * rvb.IN_COEF_R)/32768L; + + const int IIR_A0 = (IIR_INPUT_A0 * rvb.IIR_ALPHA)/32768L + (g_buffer(rvb.IIR_DEST_A0) * (32768L - rvb.IIR_ALPHA))/32768L; + const int IIR_A1 = (IIR_INPUT_A1 * rvb.IIR_ALPHA)/32768L + (g_buffer(rvb.IIR_DEST_A1) * (32768L - rvb.IIR_ALPHA))/32768L; + const int IIR_B0 = (IIR_INPUT_B0 * rvb.IIR_ALPHA)/32768L + (g_buffer(rvb.IIR_DEST_B0) * (32768L - rvb.IIR_ALPHA))/32768L; + const int IIR_B1 = (IIR_INPUT_B1 * rvb.IIR_ALPHA)/32768L + (g_buffer(rvb.IIR_DEST_B1) * (32768L - rvb.IIR_ALPHA))/32768L; + + s_buffer1(rvb.IIR_DEST_A0, IIR_A0); + s_buffer1(rvb.IIR_DEST_A1, IIR_A1); + s_buffer1(rvb.IIR_DEST_B0, IIR_B0); + s_buffer1(rvb.IIR_DEST_B1, IIR_B1); + + ACC0 = (g_buffer(rvb.ACC_SRC_A0) * rvb.ACC_COEF_A)/32768L + + (g_buffer(rvb.ACC_SRC_B0) * rvb.ACC_COEF_B)/32768L + + (g_buffer(rvb.ACC_SRC_C0) * rvb.ACC_COEF_C)/32768L + + (g_buffer(rvb.ACC_SRC_D0) * rvb.ACC_COEF_D)/32768L; + ACC1 = (g_buffer(rvb.ACC_SRC_A1) * rvb.ACC_COEF_A)/32768L + + (g_buffer(rvb.ACC_SRC_B1) * rvb.ACC_COEF_B)/32768L + + (g_buffer(rvb.ACC_SRC_C1) * rvb.ACC_COEF_C)/32768L + + (g_buffer(rvb.ACC_SRC_D1) * rvb.ACC_COEF_D)/32768L; + + FB_A0 = g_buffer(rvb.MIX_DEST_A0 - rvb.FB_SRC_A); + FB_A1 = g_buffer(rvb.MIX_DEST_A1 - rvb.FB_SRC_A); + FB_B0 = g_buffer(rvb.MIX_DEST_B0 - rvb.FB_SRC_B); + FB_B1 = g_buffer(rvb.MIX_DEST_B1 - rvb.FB_SRC_B); + + s_buffer(rvb.MIX_DEST_A0, ACC0 - (FB_A0 * rvb.FB_ALPHA)/32768L); + s_buffer(rvb.MIX_DEST_A1, ACC1 - (FB_A1 * rvb.FB_ALPHA)/32768L); + + s_buffer(rvb.MIX_DEST_B0, (rvb.FB_ALPHA * ACC0)/32768L - (FB_A0 * (int)(rvb.FB_ALPHA^0xFFFF8000))/32768L - (FB_B0 * rvb.FB_X)/32768L); + s_buffer(rvb.MIX_DEST_B1, (rvb.FB_ALPHA * ACC1)/32768L - (FB_A1 * (int)(rvb.FB_ALPHA^0xFFFF8000))/32768L - (FB_B1 * rvb.FB_X)/32768L); + + rvb.iLastRVBLeft = rvb.iRVBLeft; + rvb.iLastRVBRight = rvb.iRVBRight; + + rvb.iRVBLeft = (g_buffer(rvb.MIX_DEST_A0)+g_buffer(rvb.MIX_DEST_B0))/3; + rvb.iRVBRight = (g_buffer(rvb.MIX_DEST_A1)+g_buffer(rvb.MIX_DEST_B1))/3; + + rvb.iRVBLeft = (rvb.iRVBLeft * rvb.VolLeft) / 0x4000; + rvb.iRVBRight = (rvb.iRVBRight * rvb.VolRight) / 0x4000; + + rvb.CurrAddr++; + if(rvb.CurrAddr>0x3ffff) rvb.CurrAddr=rvb.StartAddr; + + return rvb.iLastRVBLeft+(rvb.iRVBLeft-rvb.iLastRVBLeft)/2; + } + else // -> reverb off + { + rvb.iLastRVBLeft=rvb.iLastRVBRight=rvb.iRVBLeft=rvb.iRVBRight=0; + } + + rvb.CurrAddr++; + if(rvb.CurrAddr>0x3ffff) rvb.CurrAddr=rvb.StartAddr; + } + + return rvb.iLastRVBLeft; + } + else // easy fake reverb: + { + const int iRV=*sRVBPlay; // -> simply take the reverb mix buf value + *sRVBPlay++=0; // -> init it after + if(sRVBPlay>=sRVBEnd) sRVBPlay=sRVBStart; // -> and take care about wrap arounds + return iRV; // -> return reverb mix buf val + } +} + +//////////////////////////////////////////////////////////////////////// + +INLINE int MixREVERBRight(void) +{ + if(iUseReverb==0) return 0; + else + if(iUseReverb==2) // Neill's reverb: + { + int i=rvb.iLastRVBRight+(rvb.iRVBRight-rvb.iLastRVBRight)/2; + rvb.iLastRVBRight=rvb.iRVBRight; + return i; // -> just return the last right reverb val (little bit scaled by the previous right val) + } + else // easy fake reverb: + { + const int iRV=*sRVBPlay; // -> simply take the reverb mix buf value + *sRVBPlay++=0; // -> init it after + if(sRVBPlay>=sRVBEnd) sRVBPlay=sRVBStart; // -> and take care about wrap arounds + return iRV; // -> return reverb mix buf val + } +} + +//////////////////////////////////////////////////////////////////////// + +#endif + +/* +----------------------------------------------------------------------------- +PSX reverb hardware notes +by Neill Corlett +----------------------------------------------------------------------------- + +Yadda yadda disclaimer yadda probably not perfect yadda well it's okay anyway +yadda yadda. + +----------------------------------------------------------------------------- + +Basics +------ + +- The reverb buffer is 22khz 16-bit mono PCM. +- It starts at the reverb address given by 1DA2, extends to + the end of sound RAM, and wraps back to the 1DA2 address. + +Setting the address at 1DA2 resets the current reverb work address. + +This work address ALWAYS increments every 1/22050 sec., regardless of +whether reverb is enabled (bit 7 of 1DAA set). + +And the contents of the reverb buffer ALWAYS play, scaled by the +"reverberation depth left/right" volumes (1D84/1D86). +(which, by the way, appear to be scaled so 3FFF=approx. 1.0, 4000=-1.0) + +----------------------------------------------------------------------------- + +Register names +-------------- + +These are probably not their real names. +These are probably not even correct names. +We will use them anyway, because we can. + +1DC0: FB_SRC_A (offset) +1DC2: FB_SRC_B (offset) +1DC4: IIR_ALPHA (coef.) +1DC6: ACC_COEF_A (coef.) +1DC8: ACC_COEF_B (coef.) +1DCA: ACC_COEF_C (coef.) +1DCC: ACC_COEF_D (coef.) +1DCE: IIR_COEF (coef.) +1DD0: FB_ALPHA (coef.) +1DD2: FB_X (coef.) +1DD4: IIR_DEST_A0 (offset) +1DD6: IIR_DEST_A1 (offset) +1DD8: ACC_SRC_A0 (offset) +1DDA: ACC_SRC_A1 (offset) +1DDC: ACC_SRC_B0 (offset) +1DDE: ACC_SRC_B1 (offset) +1DE0: IIR_SRC_A0 (offset) +1DE2: IIR_SRC_A1 (offset) +1DE4: IIR_DEST_B0 (offset) +1DE6: IIR_DEST_B1 (offset) +1DE8: ACC_SRC_C0 (offset) +1DEA: ACC_SRC_C1 (offset) +1DEC: ACC_SRC_D0 (offset) +1DEE: ACC_SRC_D1 (offset) +1DF0: IIR_SRC_B1 (offset) +1DF2: IIR_SRC_B0 (offset) +1DF4: MIX_DEST_A0 (offset) +1DF6: MIX_DEST_A1 (offset) +1DF8: MIX_DEST_B0 (offset) +1DFA: MIX_DEST_B1 (offset) +1DFC: IN_COEF_L (coef.) +1DFE: IN_COEF_R (coef.) + +The coefficients are signed fractional values. +-32768 would be -1.0 + 32768 would be 1.0 (if it were possible... the highest is of course 32767) + +The offsets are (byte/8) offsets into the reverb buffer. +i.e. you multiply them by 8, you get byte offsets. +You can also think of them as (samples/4) offsets. +They appear to be signed. They can be negative. +None of the documented presets make them negative, though. + +Yes, 1DF0 and 1DF2 appear to be backwards. Not a typo. + +----------------------------------------------------------------------------- + +What it does +------------ + +We take all reverb sources: +- regular channels that have the reverb bit on +- cd and external sources, if their reverb bits are on +and mix them into one stereo 44100hz signal. + +Lowpass/downsample that to 22050hz. The PSX uses a proper bandlimiting +algorithm here, but I haven't figured out the hysterically exact specifics. +I use an 8-tap filter with these coefficients, which are nice but probably +not the real ones: + +0.037828187894 +0.157538631280 +0.321159685278 +0.449322115345 +0.449322115345 +0.321159685278 +0.157538631280 +0.037828187894 + +So we have two input samples (INPUT_SAMPLE_L, INPUT_SAMPLE_R) every 22050hz. + +* IN MY EMULATION, I divide these by 2 to make it clip less. + (and of course the L/R output coefficients are adjusted to compensate) + The real thing appears to not do this. + +At every 22050hz tick: +- If the reverb bit is enabled (bit 7 of 1DAA), execute the reverb + steady-state algorithm described below +- AFTERWARDS, retrieve the "wet out" L and R samples from the reverb buffer + (This part may not be exactly right and I guessed at the coefs. TODO: check later.) + L is: 0.333 * (buffer[MIX_DEST_A0] + buffer[MIX_DEST_B0]) + R is: 0.333 * (buffer[MIX_DEST_A1] + buffer[MIX_DEST_B1]) +- Advance the current buffer position by 1 sample + +The wet out L and R are then upsampled to 44100hz and played at the +"reverberation depth left/right" (1D84/1D86) volume, independent of the main +volume. + +----------------------------------------------------------------------------- + +Reverb steady-state +------------------- + +The reverb steady-state algorithm is fairly clever, and of course by +"clever" I mean "batshit insane". + +buffer[x] is relative to the current buffer position, not the beginning of +the buffer. Note that all buffer offsets must wrap around so they're +contained within the reverb work area. + +Clipping is performed at the end... maybe also sooner, but definitely at +the end. + +IIR_INPUT_A0 = buffer[IIR_SRC_A0] * IIR_COEF + INPUT_SAMPLE_L * IN_COEF_L; +IIR_INPUT_A1 = buffer[IIR_SRC_A1] * IIR_COEF + INPUT_SAMPLE_R * IN_COEF_R; +IIR_INPUT_B0 = buffer[IIR_SRC_B0] * IIR_COEF + INPUT_SAMPLE_L * IN_COEF_L; +IIR_INPUT_B1 = buffer[IIR_SRC_B1] * IIR_COEF + INPUT_SAMPLE_R * IN_COEF_R; + +IIR_A0 = IIR_INPUT_A0 * IIR_ALPHA + buffer[IIR_DEST_A0] * (1.0 - IIR_ALPHA); +IIR_A1 = IIR_INPUT_A1 * IIR_ALPHA + buffer[IIR_DEST_A1] * (1.0 - IIR_ALPHA); +IIR_B0 = IIR_INPUT_B0 * IIR_ALPHA + buffer[IIR_DEST_B0] * (1.0 - IIR_ALPHA); +IIR_B1 = IIR_INPUT_B1 * IIR_ALPHA + buffer[IIR_DEST_B1] * (1.0 - IIR_ALPHA); + +buffer[IIR_DEST_A0 + 1sample] = IIR_A0; +buffer[IIR_DEST_A1 + 1sample] = IIR_A1; +buffer[IIR_DEST_B0 + 1sample] = IIR_B0; +buffer[IIR_DEST_B1 + 1sample] = IIR_B1; + +ACC0 = buffer[ACC_SRC_A0] * ACC_COEF_A + + buffer[ACC_SRC_B0] * ACC_COEF_B + + buffer[ACC_SRC_C0] * ACC_COEF_C + + buffer[ACC_SRC_D0] * ACC_COEF_D; +ACC1 = buffer[ACC_SRC_A1] * ACC_COEF_A + + buffer[ACC_SRC_B1] * ACC_COEF_B + + buffer[ACC_SRC_C1] * ACC_COEF_C + + buffer[ACC_SRC_D1] * ACC_COEF_D; + +FB_A0 = buffer[MIX_DEST_A0 - FB_SRC_A]; +FB_A1 = buffer[MIX_DEST_A1 - FB_SRC_A]; +FB_B0 = buffer[MIX_DEST_B0 - FB_SRC_B]; +FB_B1 = buffer[MIX_DEST_B1 - FB_SRC_B]; + +buffer[MIX_DEST_A0] = ACC0 - FB_A0 * FB_ALPHA; +buffer[MIX_DEST_A1] = ACC1 - FB_A1 * FB_ALPHA; +buffer[MIX_DEST_B0] = (FB_ALPHA * ACC0) - FB_A0 * (FB_ALPHA^0x8000) - FB_B0 * FB_X; +buffer[MIX_DEST_B1] = (FB_ALPHA * ACC1) - FB_A1 * (FB_ALPHA^0x8000) - FB_B1 * FB_X; + +----------------------------------------------------------------------------- +*/ + diff --git a/plugins/dfsound/reverb.h b/plugins/dfsound/reverb.h new file mode 100644 index 0000000..ce61818 --- /dev/null +++ b/plugins/dfsound/reverb.h @@ -0,0 +1,21 @@ +/*************************************************************************** + reverb.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +void SetREVERB(unsigned short val); +INLINE void StartREVERB(int ch); +INLINE void StoreREVERB(int ch,int ns); + diff --git a/plugins/dfsound/sdl.c b/plugins/dfsound/sdl.c new file mode 100644 index 0000000..45ccba2 --- /dev/null +++ b/plugins/dfsound/sdl.c @@ -0,0 +1,135 @@ +/* SDL Driver for P.E.Op.S Sound Plugin + * Copyright (c) 2010, Wei Mingzhi . + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA + */ + +#include "stdafx.h" + +#include "externals.h" +#include + +#define BUFFER_SIZE 22050 + +short *pSndBuffer = NULL; +int iBufSize = 0; +volatile int iReadPos = 0, iWritePos = 0; + +static void SOUND_FillAudio(void *unused, Uint8 *stream, int len) { + short *p = (short *)stream; + + len /= sizeof(short); + + while (iReadPos != iWritePos && len > 0) { + *p++ = pSndBuffer[iReadPos++]; + if (iReadPos >= iBufSize) iReadPos = 0; + --len; + } + + // Fill remaining space with zero + while (len > 0) { + *p++ = 0; + --len; + } +} + +static void InitSDL() { + if (SDL_WasInit(SDL_INIT_EVERYTHING)) { + SDL_InitSubSystem(SDL_INIT_AUDIO); + } else { + SDL_Init(SDL_INIT_AUDIO | SDL_INIT_NOPARACHUTE); + } +} + +static void DestroySDL() { + if (SDL_WasInit(SDL_INIT_EVERYTHING & ~SDL_INIT_AUDIO)) { + SDL_QuitSubSystem(SDL_INIT_AUDIO); + } else { + SDL_Quit(); + } +} + +void SetupSound(void) { + SDL_AudioSpec spec; + + if (pSndBuffer != NULL) return; + + InitSDL(); + + spec.freq = 44100; + spec.format = AUDIO_S16SYS; + spec.channels = iDisStereo ? 1 : 2; + spec.samples = 512; + spec.callback = SOUND_FillAudio; + + if (SDL_OpenAudio(&spec, NULL) < 0) { + DestroySDL(); + return; + } + + iBufSize = BUFFER_SIZE; + if (iDisStereo) iBufSize /= 2; + + pSndBuffer = (short *)malloc(iBufSize * sizeof(short)); + if (pSndBuffer == NULL) { + SDL_CloseAudio(); + return; + } + + iReadPos = 0; + iWritePos = 0; + + SDL_PauseAudio(0); +} + +void RemoveSound(void) { + if (pSndBuffer == NULL) return; + + SDL_CloseAudio(); + DestroySDL(); + + free(pSndBuffer); + pSndBuffer = NULL; +} + +unsigned long SoundGetBytesBuffered(void) { + int size; + + if (pSndBuffer == NULL) return SOUNDSIZE; + + size = iReadPos - iWritePos; + if (size <= 0) size += iBufSize; + + if (size < iBufSize / 2) return SOUNDSIZE; + + return 0; +} + +void SoundFeedStreamData(unsigned char *pSound, long lBytes) { + short *p = (short *)pSound; + + if (pSndBuffer == NULL) return; + + while (lBytes > 0) { + if (((iWritePos + 1) % iBufSize) == iReadPos) break; + + pSndBuffer[iWritePos] = *p++; + + ++iWritePos; + if (iWritePos >= iBufSize) iWritePos = 0; + + lBytes -= sizeof(short); + } +} diff --git a/plugins/dfsound/spu.c b/plugins/dfsound/spu.c new file mode 100644 index 0000000..c086c06 --- /dev/null +++ b/plugins/dfsound/spu.c @@ -0,0 +1,1029 @@ +/*************************************************************************** + spu.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#include "stdafx.h" + +#define _IN_SPU + +#include "externals.h" +#include "cfg.h" +#include "dsoundoss.h" +#include "regs.h" + +#ifdef ENABLE_NLS +#include +#include +#define _(x) gettext(x) +#define N_(x) (x) +#else +#define _(x) (x) +#define N_(x) (x) +#endif + +#if defined (USEMACOSX) +static char * libraryName = N_("Mac OS X Sound"); +#elif defined (USEALSA) +static char * libraryName = N_("ALSA Sound"); +#elif defined (USEOSS) +static char * libraryName = N_("OSS Sound"); +#elif defined (USESDL) +static char * libraryName = N_("SDL Sound"); +#elif defined (USEPULSEAUDIO) +static char * libraryName = N_("PulseAudio Sound"); +#else +static char * libraryName = N_("NULL Sound"); +#endif + +static char * libraryInfo = N_("P.E.Op.S. Sound Driver V1.7\nCoded by Pete Bernert and the P.E.Op.S. team\n"); + +// globals + +// psx buffer / addresses + +unsigned short regArea[10000]; +unsigned short spuMem[256*1024]; +unsigned char * spuMemC; +unsigned char * pSpuIrq=0; +unsigned char * pSpuBuffer; +unsigned char * pMixIrq=0; + +// user settings + +int iVolume=3; +int iXAPitch=1; +int iUseTimer=2; +int iSPUIRQWait=1; +int iDebugMode=0; +int iRecordMode=0; +int iUseReverb=2; +int iUseInterpolation=2; +int iDisStereo=0; + +// MAIN infos struct for each channel + +SPUCHAN s_chan[MAXCHAN+1]; // channel + 1 infos (1 is security for fmod handling) +REVERBInfo rvb; + +unsigned long dwNoiseVal=1; // global noise generator +int iSpuAsyncWait=0; + +unsigned short spuCtrl=0; // some vars to store psx reg infos +unsigned short spuStat=0; +unsigned short spuIrq=0; +unsigned long spuAddr=0xffffffff; // address into spu mem +int bEndThread=0; // thread handlers +int bThreadEnded=0; +int bSpuInit=0; +int bSPUIsOpen=0; + +static pthread_t thread = (pthread_t)-1; // thread id (linux) + +unsigned long dwNewChannel=0; // flags for faster testing, if new channel starts + +void (CALLBACK *irqCallback)(void)=0; // func of main emu, called on spu irq +void (CALLBACK *cddavCallback)(unsigned short,unsigned short)=0; + +// certain globals (were local before, but with the new timeproc I need em global) + +static const int f[5][2] = { { 0, 0 }, + { 60, 0 }, + { 115, -52 }, + { 98, -55 }, + { 122, -60 } }; +int SSumR[NSSIZE]; +int SSumL[NSSIZE]; +int iFMod[NSSIZE]; +int iCycle = 0; +short * pS; + +int lastch=-1; // last channel processed on spu irq in timer mode +static int lastns=0; // last ns pos +static int iSecureStart=0; // secure start counter + +//////////////////////////////////////////////////////////////////////// +// CODE AREA +//////////////////////////////////////////////////////////////////////// + +// dirty inline func includes + +#include "reverb.c" +#include "adsr.c" + +//////////////////////////////////////////////////////////////////////// +// helpers for simple interpolation + +// +// easy interpolation on upsampling, no special filter, just "Pete's common sense" tm +// +// instead of having n equal sample values in a row like: +// ____ +// |____ +// +// we compare the current delta change with the next delta change. +// +// if curr_delta is positive, +// +// - and next delta is smaller (or changing direction): +// \. +// -__ +// +// - and next delta significant (at least twice) bigger: +// --_ +// \. +// +// - and next delta is nearly same: +// \. +// \. +// +// +// if curr_delta is negative, +// +// - and next delta is smaller (or changing direction): +// _-- +// / +// +// - and next delta significant (at least twice) bigger: +// / +// __- +// +// - and next delta is nearly same: +// / +// / +// + + +INLINE void InterpolateUp(int ch) +{ + if(s_chan[ch].SB[32]==1) // flag == 1? calc step and set flag... and don't change the value in this pass + { + const int id1=s_chan[ch].SB[30]-s_chan[ch].SB[29]; // curr delta to next val + const int id2=s_chan[ch].SB[31]-s_chan[ch].SB[30]; // and next delta to next-next val :) + + s_chan[ch].SB[32]=0; + + if(id1>0) // curr delta positive + { + if(id2id1) + {s_chan[ch].SB[28]=id1;s_chan[ch].SB[32]=2;} + else + if(id2>(id1<<1)) + s_chan[ch].SB[28]=(id1*s_chan[ch].sinc)/0x10000L; + else + s_chan[ch].SB[28]=(id1*s_chan[ch].sinc)/0x20000L; + } + } + else + if(s_chan[ch].SB[32]==2) // flag 1: calc step and set flag... and don't change the value in this pass + { + s_chan[ch].SB[32]=0; + + s_chan[ch].SB[28]=(s_chan[ch].SB[28]*s_chan[ch].sinc)/0x20000L; + if(s_chan[ch].sinc<=0x8000) + s_chan[ch].SB[29]=s_chan[ch].SB[30]-(s_chan[ch].SB[28]*((0x10000/s_chan[ch].sinc)-1)); + else s_chan[ch].SB[29]+=s_chan[ch].SB[28]; + } + else // no flags? add bigger val (if possible), calc smaller step, set flag1 + s_chan[ch].SB[29]+=s_chan[ch].SB[28]; +} + +// +// even easier interpolation on downsampling, also no special filter, again just "Pete's common sense" tm +// + +INLINE void InterpolateDown(int ch) +{ + if(s_chan[ch].sinc>=0x20000L) // we would skip at least one val? + { + s_chan[ch].SB[29]+=(s_chan[ch].SB[30]-s_chan[ch].SB[29])/2; // add easy weight + if(s_chan[ch].sinc>=0x30000L) // we would skip even more vals? + s_chan[ch].SB[29]+=(s_chan[ch].SB[31]-s_chan[ch].SB[30])/2;// add additional next weight + } +} + +//////////////////////////////////////////////////////////////////////// +// helpers for gauss interpolation + +#define gval0 (((short*)(&s_chan[ch].SB[29]))[gpos]) +#define gval(x) (((short*)(&s_chan[ch].SB[29]))[(gpos+x)&3]) + +#include "gauss_i.h" + +//////////////////////////////////////////////////////////////////////// + +#include "xa.c" + +//////////////////////////////////////////////////////////////////////// +// START SOUND... called by main thread to setup a new sound on a channel +//////////////////////////////////////////////////////////////////////// + +INLINE void StartSound(int ch) +{ + StartADSR(ch); + StartREVERB(ch); + + s_chan[ch].pCurr=s_chan[ch].pStart; // set sample start + + s_chan[ch].s_1=0; // init mixing vars + s_chan[ch].s_2=0; + s_chan[ch].iSBPos=28; + + s_chan[ch].bNew=0; // init channel flags + s_chan[ch].bStop=0; + s_chan[ch].bOn=1; + + s_chan[ch].SB[29]=0; // init our interpolation helpers + s_chan[ch].SB[30]=0; + + if(iUseInterpolation>=2) // gauss interpolation? + {s_chan[ch].spos=0x30000L;s_chan[ch].SB[28]=0;} // -> start with more decoding + else {s_chan[ch].spos=0x10000L;s_chan[ch].SB[31]=0;} // -> no/simple interpolation starts with one 44100 decoding + + dwNewChannel&=~(1< take it and calc steps + s_chan[ch].sinc=s_chan[ch].iRawPitch<<4; + if(!s_chan[ch].sinc) s_chan[ch].sinc=1; + if(iUseInterpolation==1) s_chan[ch].SB[32]=1; // -> freq change in simle imterpolation mode: set flag +} + +//////////////////////////////////////////////////////////////////////// + +INLINE void FModChangeFrequency(int ch,int ns) +{ + int NP=s_chan[ch].iRawPitch; + + NP=((32768L+iFMod[ns])*NP)/32768L; + + if(NP>0x3fff) NP=0x3fff; + if(NP<0x1) NP=0x1; + + NP=(44100L*NP)/(4096L); // calc frequency + + s_chan[ch].iActFreq=NP; + s_chan[ch].iUsedFreq=NP; + s_chan[ch].sinc=(((NP/10)<<16)/4410); + if(!s_chan[ch].sinc) s_chan[ch].sinc=1; + if(iUseInterpolation==1) // freq change in simple interpolation mode + s_chan[ch].SB[32]=1; + iFMod[ns]=0; +} + +//////////////////////////////////////////////////////////////////////// + +// noise handler... just produces some noise data +// surely wrong... and no noise frequency (spuCtrl&0x3f00) will be used... +// and sometimes the noise will be used as fmod modulation... pfff + +INLINE int iGetNoiseVal(int ch) +{ + int fa; + + if((dwNoiseVal<<=1)&0x80000000L) + { + dwNoiseVal^=0x0040001L; + fa=((dwNoiseVal>>2)&0x7fff); + fa=-fa; + } + else fa=(dwNoiseVal>>2)&0x7fff; + + // mmm... depending on the noise freq we allow bigger/smaller changes to the previous val + fa=s_chan[ch].iOldNoise+((fa-s_chan[ch].iOldNoise)/((0x001f-((spuCtrl&0x3f00)>>9))+1)); + if(fa>32767L) fa=32767L; + if(fa<-32767L) fa=-32767L; + s_chan[ch].iOldNoise=fa; + + if(iUseInterpolation<2) // no gauss/cubic interpolation? + s_chan[ch].SB[29] = fa; // -> store noise val in "current sample" slot + return fa; +} + +//////////////////////////////////////////////////////////////////////// + +INLINE void StoreInterpolationVal(int ch,int fa) +{ + if(s_chan[ch].bFMod==2) // fmod freq channel + s_chan[ch].SB[29]=fa; + else + { + if((spuCtrl&0x4000)==0) fa=0; // muted? + else // else adjust + { + if(fa>32767L) fa=32767L; + if(fa<-32767L) fa=-32767L; + } + + if(iUseInterpolation>=2) // gauss/cubic interpolation + { + int gpos = s_chan[ch].SB[28]; + gval0 = fa; + gpos = (gpos+1) & 3; + s_chan[ch].SB[28] = gpos; + } + else + if(iUseInterpolation==1) // simple interpolation + { + s_chan[ch].SB[28] = 0; + s_chan[ch].SB[29] = s_chan[ch].SB[30]; // -> helpers for simple linear interpolation: delay real val for two slots, and calc the two deltas, for a 'look at the future behaviour' + s_chan[ch].SB[30] = s_chan[ch].SB[31]; + s_chan[ch].SB[31] = fa; + s_chan[ch].SB[32] = 1; // -> flag: calc new interolation + } + else s_chan[ch].SB[29]=fa; // no interpolation + } +} + +//////////////////////////////////////////////////////////////////////// + +INLINE int iGetInterpolationVal(int ch) +{ + int fa; + + if(s_chan[ch].bFMod==2) return s_chan[ch].SB[29]; + + switch(iUseInterpolation) + { + //--------------------------------------------------// + case 3: // cubic interpolation + { + long xd;int gpos; + xd = ((s_chan[ch].spos) >> 1)+1; + gpos = s_chan[ch].SB[28]; + + fa = gval(3) - 3*gval(2) + 3*gval(1) - gval0; + fa *= (xd - (2<<15)) / 6; + fa >>= 15; + fa += gval(2) - gval(1) - gval(1) + gval0; + fa *= (xd - (1<<15)) >> 1; + fa >>= 15; + fa += gval(1) - gval0; + fa *= xd; + fa >>= 15; + fa = fa + gval0; + + } break; + //--------------------------------------------------// + case 2: // gauss interpolation + { + int vl, vr;int gpos; + vl = (s_chan[ch].spos >> 6) & ~3; + gpos = s_chan[ch].SB[28]; + vr=(gauss[vl]*gval0)&~2047; + vr+=(gauss[vl+1]*gval(1))&~2047; + vr+=(gauss[vl+2]*gval(2))&~2047; + vr+=(gauss[vl+3]*gval(3))&~2047; + fa = vr>>11; + } break; + //--------------------------------------------------// + case 1: // simple interpolation + { + if(s_chan[ch].sinc<0x10000L) // -> upsampling? + InterpolateUp(ch); // --> interpolate up + else InterpolateDown(ch); // --> else down + fa=s_chan[ch].SB[29]; + } break; + //--------------------------------------------------// + default: // no interpolation + { + fa=s_chan[ch].SB[29]; + } break; + //--------------------------------------------------// + } + + return fa; +} + +//////////////////////////////////////////////////////////////////////// +// MAIN SPU FUNCTION +// here is the main job handler... thread, timer or direct func call +// basically the whole sound processing is done in this fat func! +//////////////////////////////////////////////////////////////////////// + +// 5 ms waiting phase, if buffer is full and no new sound has to get started +// .. can be made smaller (smallest val: 1 ms), but bigger waits give +// better performance + +#define PAUSE_W 5 +#define PAUSE_L 5000 + +//////////////////////////////////////////////////////////////////////// + +static void *MAINThread(void *arg) +{ + int s_1,s_2,fa,ns; +#ifndef _MACOSX + int voldiv = iVolume; +#else + const int voldiv = 2; +#endif + unsigned char * start;unsigned int nSample; + int ch,predict_nr,shift_factor,flags,d,s; + int bIRQReturn=0; + + while(!bEndThread) // until we are shutting down + { + // ok, at the beginning we are looking if there is + // enuff free place in the dsound/oss buffer to + // fill in new data, or if there is a new channel to start. + // if not, we wait (thread) or return (timer/spuasync) + // until enuff free place is available/a new channel gets + // started + + if(dwNewChannel) // new channel should start immedately? + { // (at least one bit 0 ... MAXCHANNEL is set?) + iSecureStart++; // -> set iSecure + if(iSecureStart>5) iSecureStart=0; // (if it is set 5 times - that means on 5 tries a new samples has been started - in a row, we will reset it, to give the sound update a chance) + } + else iSecureStart=0; // 0: no new channel should start + + while(!iSecureStart && !bEndThread && // no new start? no thread end? + (SoundGetBytesBuffered()>TESTSIZE)) // and still enuff data in sound buffer? + { + iSecureStart=0; // reset secure + + if(iUseTimer) return 0; // linux no-thread mode? bye + usleep(PAUSE_L); // else sleep for x ms (linux) + + if(dwNewChannel) iSecureStart=1; // if a new channel kicks in (or, of course, sound buffer runs low), we will leave the loop + } + + //--------------------------------------------------// continue from irq handling in timer mode? + + if(lastch>=0) // will be -1 if no continue is pending + { + ch=lastch; ns=lastns; lastch=-1; // -> setup all kind of vars to continue + goto GOON; // -> directly jump to the continue point + } + + //--------------------------------------------------// + //- main channel loop -// + //--------------------------------------------------// + { + for(ch=0;ch=0x10000L) + { + if(s_chan[ch].iSBPos==28) // 28 reached? + { + start=s_chan[ch].pCurr; // set up the current pos + + if (start == (unsigned char*)-1) // special "stop" sign + { + s_chan[ch].bOn=0; // -> turn everything off + s_chan[ch].ADSRX.lVolume=0; + s_chan[ch].ADSRX.EnvelopeVol=0; + goto ENDX; // -> and done for this channel + } + + s_chan[ch].iSBPos=0; + + //////////////////////////////////////////// spu irq handler here? mmm... do it later + + s_1=s_chan[ch].s_1; + s_2=s_chan[ch].s_2; + + predict_nr=(int)*start;start++; + shift_factor=predict_nr&0xf; + predict_nr >>= 4; + flags=(int)*start;start++; + + // -------------------------------------- // + + for (nSample=0;nSample<28;start++) + { + d=(int)*start; + s=((d&0xf)<<12); + if(s&0x8000) s|=0xffff0000; + + fa=(s >> shift_factor); + fa=fa + ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6); + s_2=s_1;s_1=fa; + s=((d & 0xf0) << 8); + + s_chan[ch].SB[nSample++]=fa; + + if(s&0x8000) s|=0xffff0000; + fa=(s>>shift_factor); + fa=fa + ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6); + s_2=s_1;s_1=fa; + + s_chan[ch].SB[nSample++]=fa; + } + + //////////////////////////////////////////// irq check + + if(irqCallback && (spuCtrl&0x40)) // some callback and irq active? + { + if((pSpuIrq > start-16 && // irq address reached? + pSpuIrq <= start) || + ((flags&1) && // special: irq on looping addr, when stop/loop flag is set + (pSpuIrq > s_chan[ch].pLoop-16 && + pSpuIrq <= s_chan[ch].pLoop))) + { + s_chan[ch].iIrqDone=1; // -> debug flag + irqCallback(); // -> call main emu + + if(iSPUIRQWait) // -> option: wait after irq for main emu + { + iSpuAsyncWait=1; + bIRQReturn=1; + } + } + } + + //////////////////////////////////////////// flag handler + + if((flags&4) && (!s_chan[ch].bIgnoreLoop)) + s_chan[ch].pLoop=start-16; // loop adress + + if(flags&1) // 1: stop/loop + { + // We play this block out first... + //if(!(flags&2)) // 1+2: do loop... otherwise: stop + if(flags!=3 || s_chan[ch].pLoop==NULL) // PETE: if we don't check exactly for 3, loop hang ups will happen (DQ4, for example) + { // and checking if pLoop is set avoids crashes, yeah + start = (unsigned char*)-1; + } + else + { + start = s_chan[ch].pLoop; + } + } + + s_chan[ch].pCurr=start; // store values for next cycle + s_chan[ch].s_1=s_1; + s_chan[ch].s_2=s_2; + + if(bIRQReturn) // special return for "spu irq - wait for cpu action" + { + bIRQReturn=0; + if(iUseTimer!=2) + { + DWORD dwWatchTime=timeGetTime_spu()+2500; + + while(iSpuAsyncWait && !bEndThread && + timeGetTime_spu() store 1T sample data, use that to do fmod on next channel + else // no fmod freq channel + { + ////////////////////////////////////////////// + // ok, left/right sound volume (psx volume goes from 0 ... 0x3fff) + + if(s_chan[ch].iMute) + s_chan[ch].sval=0; // debug mute + else + { + SSumL[ns]+=(s_chan[ch].sval*s_chan[ch].iLeftVolume)/0x4000L; + SSumR[ns]+=(s_chan[ch].sval*s_chan[ch].iRightVolume)/0x4000L; + } + + ////////////////////////////////////////////// + // now let us store sound data for reverb + + if(s_chan[ch].bRVBActive) StoreREVERB(ch,ns); + } + + //////////////////////////////////////////////// + // ok, go on until 1 ms data of this channel is collected + + ns++; + s_chan[ch].spos += s_chan[ch].sinc; + + } +ENDX: ; + } + } + + //---------------------------------------------------// + //- here we have another 1 ms of sound data + //---------------------------------------------------// + // mix XA infos (if any) + + MixXA(); + + /////////////////////////////////////////////////////// + // mix all channels (including reverb) into one buffer + + if(iDisStereo) // no stereo? + { + int dl, dr; + for (ns = 0; ns < NSSIZE; ns++) + { + SSumL[ns] += MixREVERBLeft(ns); + + dl = SSumL[ns] / voldiv; SSumL[ns] = 0; + if (dl < -32767) dl = -32767; if (dl > 32767) dl = 32767; + + SSumR[ns] += MixREVERBRight(); + + dr = SSumR[ns] / voldiv; SSumR[ns] = 0; + if (dr < -32767) dr = -32767; if (dr > 32767) dr = 32767; + *pS++ = (dl + dr) / 2; + } + } + else // stereo: + for (ns = 0; ns < NSSIZE; ns++) + { + SSumL[ns] += MixREVERBLeft(ns); + + d = SSumL[ns] / voldiv; SSumL[ns] = 0; + if (d < -32767) d = -32767; if (d > 32767) d = 32767; + *pS++ = d; + + SSumR[ns] += MixREVERBRight(); + + d = SSumR[ns] / voldiv; SSumR[ns] = 0; + if(d < -32767) d = -32767; if(d > 32767) d = 32767; + *pS++ = d; + } + + ////////////////////////////////////////////////////// + // special irq handling in the decode buffers (0x0000-0x1000) + // we know: + // the decode buffers are located in spu memory in the following way: + // 0x0000-0x03ff CD audio left + // 0x0400-0x07ff CD audio right + // 0x0800-0x0bff Voice 1 + // 0x0c00-0x0fff Voice 3 + // and decoded data is 16 bit for one sample + // we assume: + // even if voices 1/3 are off or no cd audio is playing, the internal + // play positions will move on and wrap after 0x400 bytes. + // Therefore: we just need a pointer from spumem+0 to spumem+3ff, and + // increase this pointer on each sample by 2 bytes. If this pointer + // (or 0x400 offsets of this pointer) hits the spuirq address, we generate + // an IRQ. Only problem: the "wait for cpu" option is kinda hard to do here + // in some of Peops timer modes. So: we ignore this option here (for now). + + if(pMixIrq && irqCallback) + { + for(ns=0;ns=pMixIrq+(ch*0x400) && pSpuIrqspuMemC+0x3ff) pMixIrq=spuMemC; + } + } + + InitREVERB(); + + // feed the sound + // wanna have around 1/60 sec (16.666 ms) updates + if (iCycle++ > 16) + { + SoundFeedStreamData((unsigned char *)pSpuBuffer, + ((unsigned char *)pS) - ((unsigned char *)pSpuBuffer)); + pS = (short *)pSpuBuffer; + iCycle = 0; + } + } + + // end of big main loop... + + bThreadEnded = 1; + + return 0; +} + +// SPU ASYNC... even newer epsxe func +// 1 time every 'cycle' cycles... harhar + +void CALLBACK SPUasync(unsigned long cycle) +{ + if(iSpuAsyncWait) + { + iSpuAsyncWait++; + if(iSpuAsyncWait<=64) return; + iSpuAsyncWait=0; + } + + if(iUseTimer==2) // special mode, only used in Linux by this spu (or if you enable the experimental Windows mode) + { + if(!bSpuInit) return; // -> no init, no call + + MAINThread(0); // -> linux high-compat mode + } +} + +// SPU UPDATE... new epsxe func +// 1 time every 32 hsync lines +// (312/32)x50 in pal +// (262/32)x60 in ntsc + +// since epsxe 1.5.2 (linux) uses SPUupdate, not SPUasync, I will +// leave that func in the linux port, until epsxe linux is using +// the async function as well + +void CALLBACK SPUupdate(void) +{ + SPUasync(0); +} + +// XA AUDIO + +void CALLBACK SPUplayADPCMchannel(xa_decode_t *xap) +{ + if(!xap) return; + if(!xap->freq) return; // no xa freq ? bye + + FeedXA(xap); // call main XA feeder +} + +// CDDA AUDIO +void CALLBACK SPUplayCDDAchannel(short *pcm, int nbytes) +{ + if (!pcm) return; + if (nbytes<=0) return; + + FeedCDDA((unsigned char *)pcm, nbytes); +} + +// SETUPTIMER: init of certain buffers and threads/timers +void SetupTimer(void) +{ + memset(SSumR,0,NSSIZE*sizeof(int)); // init some mixing buffers + memset(SSumL,0,NSSIZE*sizeof(int)); + memset(iFMod,0,NSSIZE*sizeof(int)); + pS=(short *)pSpuBuffer; // setup soundbuffer pointer + + bEndThread=0; // init thread vars + bThreadEnded=0; + bSpuInit=1; // flag: we are inited + + if(!iUseTimer) // linux: use thread + { + pthread_create(&thread, NULL, MAINThread, NULL); + } +} + +// REMOVETIMER: kill threads/timers +void RemoveTimer(void) +{ + bEndThread=1; // raise flag to end thread + + if(!iUseTimer) // linux tread? + { + int i=0; + while(!bThreadEnded && i<2000) {usleep(1000L);i++;} // -> wait until thread has ended + if(thread!=(pthread_t)-1) {pthread_cancel(thread);thread=(pthread_t)-1;} // -> cancel thread anyway + } + + bThreadEnded=0; // no more spu is running + bSpuInit=0; +} + +// SETUPSTREAMS: init most of the spu buffers +void SetupStreams(void) +{ + int i; + + pSpuBuffer=(unsigned char *)malloc(32768); // alloc mixing buffer + + if(iUseReverb==1) i=88200*2; + else i=NSSIZE*2; + + sRVBStart = (int *)malloc(i*4); // alloc reverb buffer + memset(sRVBStart,0,i*4); + sRVBEnd = sRVBStart + i; + sRVBPlay = sRVBStart; + + XAStart = // alloc xa buffer + (uint32_t *)malloc(44100 * sizeof(uint32_t)); + XAEnd = XAStart + 44100; + XAPlay = XAStart; + XAFeed = XAStart; + + CDDAStart = // alloc cdda buffer + (uint32_t *)malloc(16384 * sizeof(uint32_t)); + CDDAEnd = CDDAStart + 16384; + CDDAPlay = CDDAStart; + CDDAFeed = CDDAStart + 1; + + for(i=0;i init sustain + s_chan[i].iMute=0; + s_chan[i].iIrqDone=0; + s_chan[i].pLoop=spuMemC; + s_chan[i].pStart=spuMemC; + s_chan[i].pCurr=spuMemC; + } + + pMixIrq=spuMemC; // enable decoded buffer irqs by setting the address +} + +// REMOVESTREAMS: free most buffer +void RemoveStreams(void) +{ + free(pSpuBuffer); // free mixing buffer + pSpuBuffer = NULL; + free(sRVBStart); // free reverb buffer + sRVBStart = NULL; + free(XAStart); // free XA buffer + XAStart = NULL; + free(CDDAStart); // free CDDA buffer + CDDAStart = NULL; +} + +// INIT/EXIT STUFF + +// SPUINIT: this func will be called first by the main emu +long CALLBACK SPUinit(void) +{ + spuMemC = (unsigned char *)spuMem; // just small setup + memset((void *)&rvb, 0, sizeof(REVERBInfo)); + InitADSR(); + + iVolume = 3; + iReverbOff = -1; + spuIrq = 0; + spuAddr = 0xffffffff; + bEndThread = 0; + bThreadEnded = 0; + spuMemC = (unsigned char *)spuMem; + pMixIrq = 0; + memset((void *)s_chan, 0, (MAXCHAN + 1) * sizeof(SPUCHAN)); + pSpuIrq = 0; + iSPUIRQWait = 1; + lastch = -1; + + ReadConfig(); // read user stuff + SetupStreams(); // prepare streaming + + return 0; +} + +// SPUOPEN: called by main emu after init +long CALLBACK SPUopen(void) +{ + if (bSPUIsOpen) return 0; // security for some stupid main emus + + SetupSound(); // setup sound (before init!) + SetupTimer(); // timer for feeding data + + bSPUIsOpen = 1; + + return PSE_SPU_ERR_SUCCESS; +} + +// SPUCLOSE: called before shutdown +long CALLBACK SPUclose(void) +{ + if (!bSPUIsOpen) return 0; // some security + + bSPUIsOpen = 0; // no more open + + RemoveTimer(); // no more feeding + RemoveSound(); // no more sound handling + + return 0; +} + +// SPUSHUTDOWN: called by main emu on final exit +long CALLBACK SPUshutdown(void) +{ + SPUclose(); + RemoveStreams(); // no more streaming + + return 0; +} + +// SPUTEST: we don't test, we are always fine ;) +long CALLBACK SPUtest(void) +{ + return 0; +} + +// SPUCONFIGURE: call config dialog +long CALLBACK SPUconfigure(void) +{ +#ifdef _MACOSX + DoConfiguration(); +#else + StartCfgTool("CFG"); +#endif + return 0; +} + +// SPUABOUT: show about window +void CALLBACK SPUabout(void) +{ +#ifdef _MACOSX + DoAbout(); +#else + StartCfgTool("ABOUT"); +#endif +} + +// SETUP CALLBACKS +// this functions will be called once, +// passes a callback that should be called on SPU-IRQ/cdda volume change +void CALLBACK SPUregisterCallback(void (CALLBACK *callback)(void)) +{ + irqCallback = callback; +} + +void CALLBACK SPUregisterCDDAVolume(void (CALLBACK *CDDAVcallback)(unsigned short,unsigned short)) +{ + cddavCallback = CDDAVcallback; +} + +// COMMON PLUGIN INFO FUNCS +char * CALLBACK PSEgetLibName(void) +{ + return _(libraryName); +} + +unsigned long CALLBACK PSEgetLibType(void) +{ + return PSE_LT_SPU; +} + +unsigned long CALLBACK PSEgetLibVersion(void) +{ + return (1 << 16) | (6 << 8); +} + +char * SPUgetLibInfos(void) +{ + return _(libraryInfo); +} diff --git a/plugins/dfsound/spu.h b/plugins/dfsound/spu.h new file mode 100644 index 0000000..8912684 --- /dev/null +++ b/plugins/dfsound/spu.h @@ -0,0 +1,21 @@ +/*************************************************************************** + spu.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +void SetupTimer(void); +void RemoveTimer(void); +void CALLBACK SPUplayADPCMchannel(xa_decode_t *xap); +void CALLBACK SPUplayCDDAchannel(short *pcm, int bytes); \ No newline at end of file diff --git a/plugins/dfsound/spucfg-0.1df/dfsound.glade2 b/plugins/dfsound/spucfg-0.1df/dfsound.glade2 new file mode 100644 index 0000000..c071a09 --- /dev/null +++ b/plugins/dfsound/spucfg-0.1df/dfsound.glade2 @@ -0,0 +1,308 @@ + + + + + + True + 10 + Configure Sound + False + True + center + dialog + + + + True + vertical + 6 + + + True + 0 + + + True + 6 + 6 + 12 + 12 + + + True + 6 + 3 + 2 + 6 + 6 + + + True + 0 + Volume: + right + + + GTK_FILL + + + + + + True + 0 + Interpolation: + right + + + 2 + 3 + GTK_FILL + + + + + + True + 0 + Reverb: + right + + + 1 + 2 + GTK_FILL + + + + + + True + Low +Medium +Loud +Loudest + + + 1 + 2 + GTK_FILL + + + + + True + Off +Simple +Playstation + + + 1 + 2 + 1 + 2 + GTK_FILL + GTK_FILL + + + + + True + None +Simple +Gaussian +Cubic + + + 1 + 2 + 2 + 3 + GTK_FILL + GTK_FILL + + + + + + + + + True + <b>General</b> + True + + + label_item + + + + + 0 + + + + + True + 0 + + + True + 6 + 6 + 12 + 12 + + + True + 6 + vertical + 6 + + + Adjust XA speed + True + True + False + Choose this if XA music is played too quickly. + True + True + + + False + False + 0 + + + + + + + + + True + <b>XA Music</b> + True + + + label_item + + + + + 1 + + + + + True + 0 + + + True + 6 + 6 + 12 + 12 + + + True + 6 + vertical + 6 + + + High compatibility mode + True + True + False + Use the asynchronous SPU interface. + True + True + + + False + False + 0 + + + + + SPU IRQ Wait + True + True + False + Wait for CPU; only useful for some games. + True + True + + + False + False + 1 + + + + + Single channel sound + True + True + False + Play only one channel for a performance boost. + True + True + + + False + False + 2 + + + + + + + + + True + <b>Compatibility</b> + True + + + label_item + + + + + 2 + + + + + True + 12 + end + + + gtk-close + True + True + True + False + True + + + False + False + 0 + + + + + 3 + + + + + + diff --git a/plugins/dfsound/spucfg-0.1df/main.c b/plugins/dfsound/spucfg-0.1df/main.c new file mode 100644 index 0000000..dd38645 --- /dev/null +++ b/plugins/dfsound/spucfg-0.1df/main.c @@ -0,0 +1,258 @@ +#include "config.h" + +#include +#include +#include +#include +#include + +#include +#include + +#ifdef ENABLE_NLS +#include +#include +#endif + +#define READBINARY "rb" +#define WRITEBINARY "wb" +#define CONFIG_FILENAME "dfsound.cfg" + +void SaveConfig(GtkWidget *widget, gpointer user_datal); + +/* This function checks for the value being outside the accepted range, + and returns the appropriate boundary value */ +int set_limit (char *p, int len, int lower, int upper) +{ + int val = 0; + + if (p) + val = atoi(p + len); + + if (val < lower) + val = lower; + if (val > upper) + val = upper; + + return val; +} + +void on_about_clicked (GtkWidget *widget, gpointer user_data) +{ + gtk_widget_destroy (widget); + exit (0); +} + +void OnConfigClose(GtkWidget *widget, gpointer user_data) +{ + GladeXML *xml = (GladeXML *)user_data; + + gtk_widget_destroy(glade_xml_get_widget(xml, "CfgWnd")); + gtk_exit(0); +} + +int main(int argc, char *argv[]) +{ + GtkWidget *widget; + GladeXML *xml; + FILE *in; + char t[256]; + int len, val = 0; + char *pB, *p; + char cfg[255]; + +#ifdef ENABLE_NLS + setlocale (LC_ALL, ""); + bindtextdomain (GETTEXT_PACKAGE, LOCALE_DIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + textdomain (GETTEXT_PACKAGE); +#endif + + if (argc != 2) { + printf ("Usage: cfgDFSound {ABOUT | CFG}\n"); + return 0; + } + + if (strcmp(argv[1], "CFG") != 0 && strcmp(argv[1], "ABOUT") != 0) { + printf ("Usage: cfgDFSound {ABOUT | CFG}\n"); + return 0; + } + + gtk_set_locale(); + gtk_init(&argc, &argv); + + if (strcmp(argv[1], "ABOUT") == 0) { + const char *authors[]= {"Pete Bernert and the P.E.Op.S. team", "Ryan Schultz", "Andrew Burton", NULL}; + widget = gtk_about_dialog_new (); + gtk_about_dialog_set_name (GTK_ABOUT_DIALOG (widget), "dfsound PCSX Sound Plugin"); + gtk_about_dialog_set_version (GTK_ABOUT_DIALOG (widget), "1.6"); + gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG (widget), authors); + gtk_about_dialog_set_website (GTK_ABOUT_DIALOG (widget), "http://pcsx-df.sourceforge.net/"); + + g_signal_connect_data(GTK_OBJECT(widget), "response", + GTK_SIGNAL_FUNC(on_about_clicked), NULL, NULL, G_CONNECT_AFTER); + + gtk_widget_show (widget); + gtk_main(); + + return 0; + } + + xml = glade_xml_new(DATADIR "dfsound.glade2", "CfgWnd", NULL); + if (!xml) { + g_warning("We could not load the interface!"); + return 255; + } + + strcpy(cfg, CONFIG_FILENAME); + + in = fopen(cfg, READBINARY); + if (in) { + pB = (char *)malloc(32767); + memset(pB, 0, 32767); + len = fread(pB, 1, 32767, in); + fclose(in); + } else { + pB = 0; + printf ("Error - no configuration file\n"); + /* TODO Raise error - no configuration file */ + } + + /* ADB TODO Replace a lot of the following with common functions */ + if (pB) { + strcpy(t, "\nVolume"); + p = strstr(pB, t); + if (p) { + p = strstr(p, "="); + len = 1; + } + val = set_limit (p, len, 0, 4); + } else val = 2; + + gtk_combo_box_set_active(GTK_COMBO_BOX (glade_xml_get_widget(xml, "cbVolume2")), val); + + if (pB) { + strcpy(t, "\nUseInterpolation"); + p = strstr(pB, t); + if (p) { + p = strstr(p, "="); + len = 1; + } + val = set_limit (p, len, 0, 3); + } else val = 2; + + gtk_combo_box_set_active(GTK_COMBO_BOX (glade_xml_get_widget(xml, "cbInterpolation2")), val); + + if (pB) { + strcpy(t, "\nXAPitch"); + p = strstr(pB, t); + if (p) { + p = strstr(p, "="); + len = 1; + } + val = set_limit (p, len, 0, 1); + } else val = 0; + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "chkXASpeed")), val); + + if (pB) { + strcpy(t, "\nHighCompMode"); + p = strstr(pB, t); + if (p) { + p = strstr(p, "="); + len = 1; + } + val = set_limit (p, len, 0, 1); + } else val = 0; + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "chkHiCompat")), val); + + if (pB) { + strcpy(t, "\nSPUIRQWait"); + p = strstr(pB, t); + if (p) { + p = strstr(p, "="); + len = 1; + } + + val = set_limit (p, len, 0, 1); + } else val = 1; + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "chkIRQWait")), val); + + if (pB) { + strcpy(t, "\nDisStereo"); + p = strstr(pB, t); + if (p) { + p = strstr(p, "="); + len = 1; + } + + val = set_limit (p, len, 0, 1); + } else val = 0; + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "chkDisStereo")), val); + + if (pB) { + strcpy(t, "\nUseReverb"); + p = strstr(pB, t); + if (p) { + p = strstr(p, "="); + len = 1; + } + val = set_limit (p, len, 0, 2); + } else val = 2; + + gtk_combo_box_set_active(GTK_COMBO_BOX(glade_xml_get_widget(xml, "cbReverb2")), val); + + if (pB) + free(pB); + + widget = glade_xml_get_widget(xml, "CfgWnd"); + g_signal_connect_data(GTK_OBJECT(widget), "destroy", + GTK_SIGNAL_FUNC(SaveConfig), xml, NULL, 0); + + widget = glade_xml_get_widget(xml, "btn_close"); + g_signal_connect_data(GTK_OBJECT(widget), "clicked", + GTK_SIGNAL_FUNC(OnConfigClose), xml, NULL, G_CONNECT_AFTER); + + gtk_main(); + return 0; +} + +void SaveConfig(GtkWidget *widget, gpointer user_data) +{ + GladeXML *xml = (GladeXML *)user_data; + FILE *fp; + int val; + + fp = fopen(CONFIG_FILENAME, WRITEBINARY); + if (fp == NULL) { + fprintf(stderr, "Unable to write to configuration file %s!\n", CONFIG_FILENAME); + gtk_exit(0); + } + + val = gtk_combo_box_get_active(GTK_COMBO_BOX(glade_xml_get_widget(xml, "cbVolume2"))); + fprintf(fp, "\nVolume = %d\n", val); + + val = gtk_combo_box_get_active(GTK_COMBO_BOX(glade_xml_get_widget(xml, "cbInterpolation2"))); + fprintf(fp, "\nUseInterpolation = %d\n", val); + + val = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(xml, "chkXASpeed"))); + fprintf(fp, "\nXAPitch = %d\n", val); + + val = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(xml, "chkHiCompat"))); + fprintf(fp, "\nHighCompMode = %d\n", val); + + val = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(xml, "chkIRQWait"))); + fprintf(fp, "\nSPUIRQWait = %d\n", val); + + val = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(xml, "chkDisStereo"))); + fprintf(fp, "\nDisStereo = %d\n", val); + + val = gtk_combo_box_get_active(GTK_COMBO_BOX(glade_xml_get_widget(xml, "cbReverb2"))); + fprintf(fp, "\nUseReverb = %d\n", val); + + fclose(fp); + gtk_exit(0); +} diff --git a/plugins/dfsound/stdafx.h b/plugins/dfsound/stdafx.h new file mode 100644 index 0000000..8be8848 --- /dev/null +++ b/plugins/dfsound/stdafx.h @@ -0,0 +1,46 @@ +/*************************************************************************** + StdAfx.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#ifndef _MACOSX +#include "config.h" +#endif +#include +#include +#include +#include +#include +#ifdef USEOSS +#include +#endif +#include +#include +#define RRand(range) (random()%range) +#include +#include +#include + +#undef CALLBACK +#define CALLBACK +#define DWORD unsigned long +#define LOWORD(l) ((unsigned short)(l)) +#define HIWORD(l) ((unsigned short)(((unsigned long)(l) >> 16) & 0xFFFF)) + +#ifndef INLINE +#define INLINE inline +#endif + +#include "psemuxa.h" diff --git a/plugins/dfsound/xa.c b/plugins/dfsound/xa.c new file mode 100644 index 0000000..fdae4f9 --- /dev/null +++ b/plugins/dfsound/xa.c @@ -0,0 +1,410 @@ +/*************************************************************************** + xa.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#include "stdafx.h" +#define _IN_XA +#include + +// will be included from spu.c +#ifdef _IN_SPU + +//////////////////////////////////////////////////////////////////////// +// XA GLOBALS +//////////////////////////////////////////////////////////////////////// + +xa_decode_t * xapGlobal=0; + +uint32_t * XAFeed = NULL; +uint32_t * XAPlay = NULL; +uint32_t * XAStart = NULL; +uint32_t * XAEnd = NULL; + +uint32_t XARepeat = 0; +uint32_t XALastVal = 0; + +uint32_t * CDDAFeed = NULL; +uint32_t * CDDAPlay = NULL; +uint32_t * CDDAStart = NULL; +uint32_t * CDDAEnd = NULL; + +int iLeftXAVol = 32767; +int iRightXAVol = 32767; + +static int gauss_ptr = 0; +static int gauss_window[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + +#define gvall0 gauss_window[gauss_ptr] +#define gvall(x) gauss_window[(gauss_ptr+x)&3] +#define gvalr0 gauss_window[4+gauss_ptr] +#define gvalr(x) gauss_window[4+((gauss_ptr+x)&3)] + +//////////////////////////////////////////////////////////////////////// +// MIX XA & CDDA +//////////////////////////////////////////////////////////////////////// + +INLINE void MixXA(void) +{ + int ns; + uint32_t l; + + for(ns=0;ns>16)&0xffff)) * iRightXAVol)/32768; +#else + SSumL[ns]+=(((short)(XALastVal&0xffff)) * iLeftXAVol)/32767; + SSumR[ns]+=(((short)((XALastVal>>16)&0xffff)) * iRightXAVol)/32767; +#endif + } + + if(XAPlay==XAFeed && XARepeat) + { + XARepeat--; + for(;ns>16)&0xffff)) * iRightXAVol)/32768; +#else + SSumL[ns]+=(((short)(XALastVal&0xffff)) * iLeftXAVol)/32767; + SSumR[ns]+=(((short)((XALastVal>>16)&0xffff)) * iRightXAVol)/32767; +#endif + } + } + + for(ns=0;ns>16)&0xffff)) * iRightXAVol)/32767; + } +} + +//////////////////////////////////////////////////////////////////////// +// small linux time helper... only used for watchdog +//////////////////////////////////////////////////////////////////////// + +unsigned long timeGetTime_spu() +{ + struct timeval tv; + gettimeofday(&tv, 0); // well, maybe there are better ways + return tv.tv_sec * 1000 + tv.tv_usec/1000; // to do that, but at least it works +} + +//////////////////////////////////////////////////////////////////////// +// FEED XA +//////////////////////////////////////////////////////////////////////// + +INLINE void FeedXA(xa_decode_t *xap) +{ + int sinc,spos,i,iSize,iPlace,vl,vr; + + if(!bSPUIsOpen) return; + + xapGlobal = xap; // store info for save states + XARepeat = 100; // set up repeat + +#ifdef XA_HACK + iSize=((45500*xap->nsamples)/xap->freq); // get size +#else + iSize=((44100*xap->nsamples)/xap->freq); // get size +#endif + if(!iSize) return; // none? bye + + if(XAFeed=10) + { + if(!dwFPS) dwFPS=1; + dw1=1000000/dwFPS; + if(dw1>=(dwL1-100) && dw1<=(dwL1+100)) dw1=dwL1; + else dwL1=dw1; + dw2=(xap->freq*100/xap->nsamples); + if((!dw1)||((dw2+100)>=dw1)) iLastSize=0; + else + { + iLastSize=iSize*dw2/dw1; + if(iLastSize>iPlace) iLastSize=iPlace; + iSize=iLastSize; + } + iFPSCnt=0;dwFPS=0; + } + else + { + if(iLastSize) iSize=iLastSize; + } + } + //----------------------------------------------------// + + spos=0x10000L; + sinc = (xap->nsamples << 16) / iSize; // calc freq by num / size + + if(xap->stereo) +{ + uint32_t * pS=(uint32_t *)xap->pcm; + uint32_t l=0; + + if(iXAPitch) + { + int32_t l1,l2;short s; + for(i=0;i=0x10000L) + { + l = *pS++; + gauss_window[gauss_ptr] = (short)LOWORD(l); + gauss_window[4+gauss_ptr] = (short)HIWORD(l); + gauss_ptr = (gauss_ptr+1) & 3; + spos -= 0x10000L; + } + vl = (spos >> 6) & ~3; + vr=(gauss[vl]*gvall0)&~2047; + vr+=(gauss[vl+1]*gvall(1))&~2047; + vr+=(gauss[vl+2]*gvall(2))&~2047; + vr+=(gauss[vl+3]*gvall(3))&~2047; + l= (vr >> 11) & 0xffff; + vr=(gauss[vl]*gvalr0)&~2047; + vr+=(gauss[vl+1]*gvalr(1))&~2047; + vr+=(gauss[vl+2]*gvalr(2))&~2047; + vr+=(gauss[vl+3]*gvalr(3))&~2047; + l |= vr << 5; + } + else + { + while(spos>=0x10000L) + { + l = *pS++; + spos -= 0x10000L; + } + } + + s=(short)LOWORD(l); + l1=s; + l1=(l1*iPlace)/iSize; + if(l1<-32767) l1=-32767; + if(l1> 32767) l1=32767; + s=(short)HIWORD(l); + l2=s; + l2=(l2*iPlace)/iSize; + if(l2<-32767) l2=-32767; + if(l2> 32767) l2=32767; + l=(l1&0xffff)|(l2<<16); + + *XAFeed++=l; + + if(XAFeed==XAEnd) XAFeed=XAStart; + if(XAFeed==XAPlay) + { + if(XAPlay!=XAStart) XAFeed=XAPlay-1; + break; + } + + spos += sinc; + } + } + else + { + for(i=0;i=0x10000L) + { + l = *pS++; + gauss_window[gauss_ptr] = (short)LOWORD(l); + gauss_window[4+gauss_ptr] = (short)HIWORD(l); + gauss_ptr = (gauss_ptr+1) & 3; + spos -= 0x10000L; + } + vl = (spos >> 6) & ~3; + vr=(gauss[vl]*gvall0)&~2047; + vr+=(gauss[vl+1]*gvall(1))&~2047; + vr+=(gauss[vl+2]*gvall(2))&~2047; + vr+=(gauss[vl+3]*gvall(3))&~2047; + l= (vr >> 11) & 0xffff; + vr=(gauss[vl]*gvalr0)&~2047; + vr+=(gauss[vl+1]*gvalr(1))&~2047; + vr+=(gauss[vl+2]*gvalr(2))&~2047; + vr+=(gauss[vl+3]*gvalr(3))&~2047; + l |= vr << 5; + } + else + { + while(spos>=0x10000L) + { + l = *pS++; + spos -= 0x10000L; + } + } + + *XAFeed++=l; + + if(XAFeed==XAEnd) XAFeed=XAStart; + if(XAFeed==XAPlay) + { + if(XAPlay!=XAStart) XAFeed=XAPlay-1; + break; + } + + spos += sinc; + } + } + } + else + { + unsigned short * pS=(unsigned short *)xap->pcm; + uint32_t l;short s=0; + + if(iXAPitch) + { + int32_t l1; + for(i=0;i=0x10000L) + { + gauss_window[gauss_ptr] = (short)*pS++; + gauss_ptr = (gauss_ptr+1) & 3; + spos -= 0x10000L; + } + vl = (spos >> 6) & ~3; + vr=(gauss[vl]*gvall0)&~2047; + vr+=(gauss[vl+1]*gvall(1))&~2047; + vr+=(gauss[vl+2]*gvall(2))&~2047; + vr+=(gauss[vl+3]*gvall(3))&~2047; + l1=s= vr >> 11; + l1 &= 0xffff; + } + else + { + while(spos>=0x10000L) + { + s = *pS++; + spos -= 0x10000L; + } + l1=s; + } + + l1=(l1*iPlace)/iSize; + if(l1<-32767) l1=-32767; + if(l1> 32767) l1=32767; + l=(l1&0xffff)|(l1<<16); + *XAFeed++=l; + + if(XAFeed==XAEnd) XAFeed=XAStart; + if(XAFeed==XAPlay) + { + if(XAPlay!=XAStart) XAFeed=XAPlay-1; + break; + } + + spos += sinc; + } + } + else + { + for(i=0;i=0x10000L) + { + gauss_window[gauss_ptr] = (short)*pS++; + gauss_ptr = (gauss_ptr+1) & 3; + spos -= 0x10000L; + } + vl = (spos >> 6) & ~3; + vr=(gauss[vl]*gvall0)&~2047; + vr+=(gauss[vl+1]*gvall(1))&~2047; + vr+=(gauss[vl+2]*gvall(2))&~2047; + vr+=(gauss[vl+3]*gvall(3))&~2047; + l=s= vr >> 11; + l &= 0xffff; + } + else + { + while(spos>=0x10000L) + { + s = *pS++; + spos -= 0x10000L; + } + l=s; + } + + *XAFeed++=(l|(l<<16)); + + if(XAFeed==XAEnd) XAFeed=XAStart; + if(XAFeed==XAPlay) + { + if(XAPlay!=XAStart) XAFeed=XAPlay-1; + break; + } + + spos += sinc; + } + } + } +} + +//////////////////////////////////////////////////////////////////////// +// FEED CDDA +//////////////////////////////////////////////////////////////////////// + +INLINE void FeedCDDA(unsigned char *pcm, int nBytes) +{ + while(nBytes>0) + { + if(CDDAFeed==CDDAEnd) CDDAFeed=CDDAStart; + while(CDDAFeed==CDDAPlay-1|| + (CDDAFeed==CDDAEnd-1&&CDDAPlay==CDDAStart)) + { + if (!iUseTimer) usleep(1000); + else return; + } + *CDDAFeed++=(*pcm | (*(pcm+1)<<8) | (*(pcm+2)<<16) | (*(pcm+3)<<24)); + nBytes-=4; + pcm+=4; + } +} + +#endif diff --git a/plugins/dfsound/xa.h b/plugins/dfsound/xa.h new file mode 100644 index 0000000..0928eba --- /dev/null +++ b/plugins/dfsound/xa.h @@ -0,0 +1,20 @@ +/*************************************************************************** + xa.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +INLINE void MixXA(void); +INLINE void FeedXA(xa_decode_t *xap); +INLINE void FeedCDDA(unsigned char *pcm, int nBytes); -- cgit v1.2.3