diff options
author | Rainer Hochecker <fernetmenta@online.de> | 2015-01-07 11:31:14 +0100 |
---|---|---|
committer | Rainer Hochecker <fernetmenta@online.de> | 2015-03-19 16:04:23 +0100 |
commit | 0f6a8829e0894a145362ca9c2bc90ddf9781577a (patch) | |
tree | 524a796c4f570d330e5e0895276db23bc9ebc36a /lib/libmodplug/src | |
parent | 0333bf47a7fb9160a598c8ea32afd21f1947d6d9 (diff) |
paplayer: drop obsolete codecs from lib
Diffstat (limited to 'lib/libmodplug/src')
43 files changed, 0 insertions, 31025 deletions
diff --git a/lib/libmodplug/src/Makefile.am b/lib/libmodplug/src/Makefile.am deleted file mode 100644 index 5be33d4257..0000000000 --- a/lib/libmodplug/src/Makefile.am +++ /dev/null @@ -1,48 +0,0 @@ -AM_CPPFLAGS = -I$(top_srcdir)/src/libmodplug - -if MINGW32 - AM_LDFLAGS = -no-undefined -endif -lib_LTLIBRARIES = libmodplug.la -libmodplug_la_LIBADD = -lm -libmodplug_la_SOURCES = tables.h \ - sndmix.cpp \ - sndfile.cpp \ - snd_fx.cpp \ - snd_flt.cpp \ - snd_dsp.cpp \ - fastmix.cpp \ - mmcmp.cpp \ - load_xm.cpp \ - load_wav.cpp \ - load_umx.cpp \ - load_ult.cpp \ - load_stm.cpp \ - load_s3m.cpp \ - load_ptm.cpp \ - load_okt.cpp \ - load_mtm.cpp \ - load_mod.cpp \ - load_med.cpp \ - load_mdl.cpp \ - load_it.cpp \ - load_far.cpp \ - load_dsm.cpp \ - load_dmf.cpp \ - load_dbm.cpp \ - load_ams.cpp \ - load_amf.cpp \ - load_669.cpp \ - load_j2b.cpp \ - load_mt2.cpp \ - load_psm.cpp \ - load_abc.cpp \ - load_mid.cpp \ - load_pat.cpp \ - modplug.cpp - -libmodplugincludedir = $(includedir)/libmodplug - - -libmodpluginclude_HEADERS = libmodplug/stdafx.h libmodplug/sndfile.h libmodplug/it_defs.h modplug.h -noinst_HEADERS = load_pat.h diff --git a/lib/libmodplug/src/Makefile.in b/lib/libmodplug/src/Makefile.in deleted file mode 100644 index eec3568a5a..0000000000 --- a/lib/libmodplug/src/Makefile.in +++ /dev/null @@ -1,651 +0,0 @@ -# Makefile.in generated by automake 1.11 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008, 2009 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@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@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@ -subdir = src -DIST_COMMON = $(libmodpluginclude_HEADERS) $(noinst_HEADERS) \ - $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ - $(srcdir)/config.h.in -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/configure.in -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = config.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_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 = f=`echo $$p | sed -e 's|^.*/||'`; -am__install_max = 40 -am__nobase_strip_setup = \ - srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` -am__nobase_strip = \ - for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" -am__nobase_list = $(am__nobase_strip_setup); \ - for p in $$list; do echo "$$p $$p"; done | \ - sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ - $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ - if (++n[$$2] == $(am__install_max)) \ - { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ - END { for (dir in files) print dir, files[dir] }' -am__base_list = \ - sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ - sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' -am__installdirs = "$(DESTDIR)$(libdir)" \ - "$(DESTDIR)$(libmodplugincludedir)" -LTLIBRARIES = $(lib_LTLIBRARIES) -libmodplug_la_DEPENDENCIES = -am_libmodplug_la_OBJECTS = sndmix.lo sndfile.lo snd_fx.lo snd_flt.lo \ - snd_dsp.lo fastmix.lo mmcmp.lo load_xm.lo load_wav.lo \ - load_umx.lo load_ult.lo load_stm.lo load_s3m.lo load_ptm.lo \ - load_okt.lo load_mtm.lo load_mod.lo load_med.lo load_mdl.lo \ - load_it.lo load_far.lo load_dsm.lo load_dmf.lo load_dbm.lo \ - load_ams.lo load_amf.lo load_669.lo load_j2b.lo load_mt2.lo \ - load_psm.lo load_abc.lo load_mid.lo load_pat.lo modplug.lo -libmodplug_la_OBJECTS = $(am_libmodplug_la_OBJECTS) -DEFAULT_INCLUDES = -I.@am__isrc@ -depcomp = $(SHELL) $(top_srcdir)/depcomp -am__depfiles_maybe = depfiles -am__mv = mv -f -CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ - $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ - --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ - $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -CXXLD = $(CXX) -CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ - --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ - $(LDFLAGS) -o $@ -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 = $(libmodplug_la_SOURCES) -DIST_SOURCES = $(libmodplug_la_SOURCES) -HEADERS = $(libmodpluginclude_HEADERS) $(noinst_HEADERS) -ETAGS = etags -CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -AMTAR = @AMTAR@ -AR = @AR@ -AS = @AS@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPPFLAGS = @CPPFLAGS@ -CXX = @CXX@ -CXXCPP = @CXXCPP@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DLLTOOL = @DLLTOOL@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -FGREP = @FGREP@ -GREP = @GREP@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBOBJS = @LTLIBOBJS@ -MAKEINFO = @MAKEINFO@ -MKDIR_P = @MKDIR_P@ -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@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -VERSION = @VERSION@ -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_CXX = @ac_ct_CXX@ -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 = @bindir@ -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@ -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_alias = @target_alias@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -AM_CPPFLAGS = -I$(top_srcdir)/src/libmodplug -@MINGW32_TRUE@AM_LDFLAGS = -no-undefined -lib_LTLIBRARIES = libmodplug.la -libmodplug_la_LIBADD = -lm -libmodplug_la_SOURCES = tables.h \ - sndmix.cpp \ - sndfile.cpp \ - snd_fx.cpp \ - snd_flt.cpp \ - snd_dsp.cpp \ - fastmix.cpp \ - mmcmp.cpp \ - load_xm.cpp \ - load_wav.cpp \ - load_umx.cpp \ - load_ult.cpp \ - load_stm.cpp \ - load_s3m.cpp \ - load_ptm.cpp \ - load_okt.cpp \ - load_mtm.cpp \ - load_mod.cpp \ - load_med.cpp \ - load_mdl.cpp \ - load_it.cpp \ - load_far.cpp \ - load_dsm.cpp \ - load_dmf.cpp \ - load_dbm.cpp \ - load_ams.cpp \ - load_amf.cpp \ - load_669.cpp \ - load_j2b.cpp \ - load_mt2.cpp \ - load_psm.cpp \ - load_abc.cpp \ - load_mid.cpp \ - load_pat.cpp \ - modplug.cpp - -libmodplugincludedir = $(includedir)/libmodplug -libmodpluginclude_HEADERS = libmodplug/stdafx.h libmodplug/sndfile.h libmodplug/it_defs.h modplug.h -noinst_HEADERS = load_pat.h -all: config.h - $(MAKE) $(AM_MAKEFLAGS) all-am - -.SUFFIXES: -.SUFFIXES: .cpp .lo .o .obj -$(srcdir)/Makefile.in: $(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 src/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnu src/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: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): - -config.h: stamp-h1 - @if test ! -f $@; then \ - rm -f stamp-h1; \ - $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \ - else :; fi - -stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status - @rm -f stamp-h1 - cd $(top_builddir) && $(SHELL) ./config.status src/config.h -$(srcdir)/config.h.in: $(am__configure_deps) - ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) - rm -f stamp-h1 - touch $@ - -distclean-hdr: - -rm -f config.h stamp-h1 -install-libLTLIBRARIES: $(lib_LTLIBRARIES) - @$(NORMAL_INSTALL) - test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" - @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ - list2=; for p in $$list; do \ - if test -f $$p; then \ - list2="$$list2 $$p"; \ - else :; fi; \ - done; \ - test -z "$$list2" || { \ - echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ - $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ - } - -uninstall-libLTLIBRARIES: - @$(NORMAL_UNINSTALL) - @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ - for p in $$list; do \ - $(am__strip_dir) \ - echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ - $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ - 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 -libmodplug.la: $(libmodplug_la_OBJECTS) $(libmodplug_la_DEPENDENCIES) - $(CXXLINK) -rpath $(libdir) $(libmodplug_la_OBJECTS) $(libmodplug_la_LIBADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fastmix.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_669.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_abc.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_amf.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_ams.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_dbm.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_dmf.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_dsm.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_far.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_it.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_j2b.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_mdl.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_med.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_mid.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_mod.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_mt2.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_mtm.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_okt.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_pat.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_psm.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_ptm.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_s3m.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_stm.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_ult.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_umx.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_wav.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_xm.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mmcmp.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/modplug.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snd_dsp.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snd_flt.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snd_fx.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sndfile.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sndmix.Plo@am__quote@ - -.cpp.o: -@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< - -.cpp.obj: -@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` - -.cpp.lo: -@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs -install-libmodplugincludeHEADERS: $(libmodpluginclude_HEADERS) - @$(NORMAL_INSTALL) - test -z "$(libmodplugincludedir)" || $(MKDIR_P) "$(DESTDIR)$(libmodplugincludedir)" - @list='$(libmodpluginclude_HEADERS)'; test -n "$(libmodplugincludedir)" || list=; \ - for p in $$list; do \ - if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ - echo "$$d$$p"; \ - done | $(am__base_list) | \ - while read files; do \ - echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libmodplugincludedir)'"; \ - $(INSTALL_HEADER) $$files "$(DESTDIR)$(libmodplugincludedir)" || exit $$?; \ - done - -uninstall-libmodplugincludeHEADERS: - @$(NORMAL_UNINSTALL) - @list='$(libmodpluginclude_HEADERS)'; test -n "$(libmodplugincludedir)" || list=; \ - files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ - test -n "$$files" || exit 0; \ - echo " ( cd '$(DESTDIR)$(libmodplugincludedir)' && rm -f" $$files ")"; \ - cd "$(DESTDIR)$(libmodplugincludedir)" && rm -f $$files - -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) config.h.in $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - set x; \ - here=`pwd`; \ - list='$(SOURCES) $(HEADERS) config.h.in $(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; }; }'`; \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: CTAGS -CTAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - list='$(SOURCES) $(HEADERS) config.h.in $(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)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__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 "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$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) $(HEADERS) config.h -installdirs: - for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(libmodplugincludedir)"; 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) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_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-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-hdr distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: install-libmodplugincludeHEADERS - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: install-libLTLIBRARIES - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -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-libLTLIBRARIES \ - uninstall-libmodplugincludeHEADERS - -.MAKE: all install-am install-strip - -.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ - clean-libLTLIBRARIES clean-libtool ctags distclean \ - distclean-compile distclean-generic distclean-hdr \ - distclean-libtool distclean-tags distdir dvi dvi-am html \ - html-am info info-am install install-am install-data \ - install-data-am install-dvi install-dvi-am install-exec \ - install-exec-am install-html install-html-am install-info \ - install-info-am install-libLTLIBRARIES \ - install-libmodplugincludeHEADERS 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-libLTLIBRARIES \ - uninstall-libmodplugincludeHEADERS - - -# 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/lib/libmodplug/src/config.h.in b/lib/libmodplug/src/config.h.in deleted file mode 100644 index e4aac90f3a..0000000000 --- a/lib/libmodplug/src/config.h.in +++ /dev/null @@ -1,130 +0,0 @@ -/* src/config.h.in. Generated from configure.in by autoheader. */ - -/* Define if building universal (internal helper macro) */ -#undef AC_APPLE_UNIVERSAL_BUILD - -/* Define to 1 if you have the <dlfcn.h> header file. */ -#undef HAVE_DLFCN_H - -/* Define to 1 if you have the <inttypes.h> header file. */ -#undef HAVE_INTTYPES_H - -/* Define to 1 if you have the <malloc.h> header file. */ -#undef HAVE_MALLOC_H - -/* Define to 1 if you have the <memory.h> header file. */ -#undef HAVE_MEMORY_H - -/* Define to 1 if you have the `setenv' function. */ -#undef HAVE_SETENV - -/* Define to 1 if you have the <stdint.h> header file. */ -#undef HAVE_STDINT_H - -/* Define to 1 if you have the <stdlib.h> header file. */ -#undef HAVE_STDLIB_H - -/* Define to 1 if you have the <strings.h> header file. */ -#undef HAVE_STRINGS_H - -/* Define to 1 if you have the <string.h> header file. */ -#undef HAVE_STRING_H - -/* Define to 1 if you have the <sys/stat.h> header file. */ -#undef HAVE_SYS_STAT_H - -/* Define to 1 if you have the <sys/types.h> header file. */ -#undef HAVE_SYS_TYPES_H - -/* Define to 1 if you have the <unistd.h> header file. */ -#undef HAVE_UNISTD_H - -/* Define to the sub-directory in which libtool stores uninstalled libraries. - */ -#undef LT_OBJDIR - -/* Name of package */ -#undef PACKAGE - -/* Define to the address where bug reports for this package should be sent. */ -#undef PACKAGE_BUGREPORT - -/* Define to the full name of this package. */ -#undef PACKAGE_NAME - -/* Define to the full name and version of this package. */ -#undef PACKAGE_STRING - -/* Define to the one symbol short name of this package. */ -#undef PACKAGE_TARNAME - -/* Define to the home page for this package. */ -#undef PACKAGE_URL - -/* Define to the version of this package. */ -#undef PACKAGE_VERSION - -/* Define to 1 if you have the ANSI C header files. */ -#undef STDC_HEADERS - -/* Version number of package */ -#undef VERSION - -/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most - significant byte first (like Motorola and SPARC, unlike Intel). */ -#if defined AC_APPLE_UNIVERSAL_BUILD -# if defined __BIG_ENDIAN__ -# define WORDS_BIGENDIAN 1 -# endif -#else -# ifndef WORDS_BIGENDIAN -# undef WORDS_BIGENDIAN -# endif -#endif - -/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>, - <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the - #define below would cause a syntax error. */ -#undef _UINT32_T - -/* Define for Solaris 2.5.1 so the uint64_t typedef from <sys/synch.h>, - <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the - #define below would cause a syntax error. */ -#undef _UINT64_T - -/* Define for Solaris 2.5.1 so the uint8_t typedef from <sys/synch.h>, - <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the - #define below would cause a syntax error. */ -#undef _UINT8_T - -/* Define to the type of a signed integer type of width exactly 16 bits if - such a type exists and the standard includes do not define it. */ -#undef int16_t - -/* Define to the type of a signed integer type of width exactly 32 bits if - such a type exists and the standard includes do not define it. */ -#undef int32_t - -/* Define to the type of a signed integer type of width exactly 64 bits if - such a type exists and the standard includes do not define it. */ -#undef int64_t - -/* Define to the type of a signed integer type of width exactly 8 bits if such - a type exists and the standard includes do not define it. */ -#undef int8_t - -/* Define to the type of an unsigned integer type of width exactly 16 bits if - such a type exists and the standard includes do not define it. */ -#undef uint16_t - -/* Define to the type of an unsigned integer type of width exactly 32 bits if - such a type exists and the standard includes do not define it. */ -#undef uint32_t - -/* Define to the type of an unsigned integer type of width exactly 64 bits if - such a type exists and the standard includes do not define it. */ -#undef uint64_t - -/* Define to the type of an unsigned integer type of width exactly 8 bits if - such a type exists and the standard includes do not define it. */ -#undef uint8_t diff --git a/lib/libmodplug/src/fastmix.cpp b/lib/libmodplug/src/fastmix.cpp deleted file mode 100644 index 69570df084..0000000000 --- a/lib/libmodplug/src/fastmix.cpp +++ /dev/null @@ -1,2388 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque <olivierl@jps.net> - * Markus Fick <webmaster@mark-f.de> spline + fir-resampler -*/ - -#include "stdafx.h" -#include "sndfile.h" -#include <math.h> - -#ifdef MSC_VER -#pragma bss_seg(".modplug") -#endif - -// Front Mix Buffer (Also room for interleaved rear mix) -int MixSoundBuffer[MIXBUFFERSIZE*4]; - -// Reverb Mix Buffer -#ifndef MODPLUG_NO_REVERB -int MixReverbBuffer[MIXBUFFERSIZE*2]; -extern UINT gnReverbSend; -#endif - -#ifndef MODPLUG_FASTSOUNDLIB -int MixRearBuffer[MIXBUFFERSIZE*2]; -float MixFloatBuffer[MIXBUFFERSIZE*2]; -#endif - -#ifdef MSC_VER -#pragma bss_seg() -#endif - - -extern LONG gnDryROfsVol; -extern LONG gnDryLOfsVol; -extern LONG gnRvbROfsVol; -extern LONG gnRvbLOfsVol; - -// 4x256 taps polyphase FIR resampling filter -extern short int gFastSinc[]; -extern short int gKaiserSinc[]; // 8-taps polyphase -/* - *----------------------------------------------------------------------------- - cubic spline interpolation doc, - (derived from "digital image warping", g. wolberg) - - interpolation polynomial: f(x) = A3*(x-floor(x))**3 + A2*(x-floor(x))**2 + - A1*(x-floor(x)) + A0 - - with Y = equispaced data points (dist=1), YD = first derivates of data points and IP = floor(x) - the A[0..3] can be found by solving - A0 = Y[IP] - A1 = YD[IP] - A2 = 3*(Y[IP+1]-Y[IP])-2.0*YD[IP]-YD[IP+1] - A3 = -2.0 * (Y[IP+1]-Y[IP]) + YD[IP] - YD[IP+1] - - with the first derivates as - YD[IP] = 0.5 * (Y[IP+1] - Y[IP-1]); - YD[IP+1] = 0.5 * (Y[IP+2] - Y[IP]) - - the coefs becomes - A0 = Y[IP] - A1 = YD[IP] - = 0.5*(Y[IP+1] - Y[IP-1]); - A2 = 3.0*(Y[IP+1]-Y[IP])-2.0*YD[IP]-YD[IP+1] - = 3.0*(Y[IP+1]-Y[IP]) - 0.5*2.0*(Y[IP+1]-Y[IP-1]) - 0.5*(Y[IP+2]-Y[IP]) - = 3.0*Y[IP+1] - 3.0*Y[IP] - Y[IP+1] + Y[IP-1] - 0.5*Y[IP+2] + 0.5*Y[IP] - = -0.5*Y[IP+2] + 2.0 * Y[IP+1] - 2.5*Y[IP] + Y[IP-1] - = Y[IP-1] + 2 * Y[IP+1] - 0.5 * (5.0 * Y[IP] + Y[IP+2]) - A3 = -2.0*(Y[IP+1]-Y[IP]) + YD[IP] + YD[IP+1] - = -2.0*Y[IP+1] + 2.0*Y[IP] + 0.5*(Y[IP+1]-Y[IP-1]) + 0.5*(Y[IP+2]-Y[IP]) - = -2.0*Y[IP+1] + 2.0*Y[IP] + 0.5*Y[IP+1] - 0.5*Y[IP-1] + 0.5*Y[IP+2] - 0.5*Y[IP] - = 0.5 * Y[IP+2] - 1.5 * Y[IP+1] + 1.5 * Y[IP] - 0.5 * Y[IP-1] - = 0.5 * (3.0 * (Y[IP] - Y[IP+1]) - Y[IP-1] + YP[IP+2]) - - then interpolated data value is (horner rule) - out = (((A3*x)+A2)*x+A1)*x+A0 - - this gives parts of data points Y[IP-1] to Y[IP+2] of - part x**3 x**2 x**1 x**0 - Y[IP-1] -0.5 1 -0.5 0 - Y[IP] 1.5 -2.5 0 1 - Y[IP+1] -1.5 2 0.5 0 - Y[IP+2] 0.5 -0.5 0 0 - *--------------------------------------------------------------------------- - */ -// number of bits used to scale spline coefs -#define SPLINE_QUANTBITS 14 -#define SPLINE_QUANTSCALE (1L<<SPLINE_QUANTBITS) -#define SPLINE_8SHIFT (SPLINE_QUANTBITS-8) -#define SPLINE_16SHIFT (SPLINE_QUANTBITS) -// forces coefsset to unity gain -#define SPLINE_CLAMPFORUNITY -// log2(number) of precalculated splines (range is [4..14]) -#define SPLINE_FRACBITS 10 -#define SPLINE_LUTLEN (1L<<SPLINE_FRACBITS) - -class CzCUBICSPLINE -{ public: - CzCUBICSPLINE( ); - ~CzCUBICSPLINE( ); - static signed short lut[4*(1L<<SPLINE_FRACBITS)]; -}; - -signed short CzCUBICSPLINE::lut[4*(1L<<SPLINE_FRACBITS)]; - -CzCUBICSPLINE::CzCUBICSPLINE( ) -{ int _LIi; - int _LLen = (1L<<SPLINE_FRACBITS); - float _LFlen = 1.0f / (float)_LLen; - float _LScale = (float)SPLINE_QUANTSCALE; - for(_LIi=0;_LIi<_LLen;_LIi++) - { float _LCm1, _LC0, _LC1, _LC2; - float _LX = ((float)_LIi)*_LFlen; - int _LSum,_LIdx = _LIi<<2; - _LCm1 = (float)floor( 0.5 + _LScale*(-0.5*_LX*_LX*_LX + 1.0*_LX*_LX - 0.5*_LX ) ); - _LC0 = (float)floor( 0.5 + _LScale*( 1.5*_LX*_LX*_LX - 2.5*_LX*_LX + 1.0 ) ); - _LC1 = (float)floor( 0.5 + _LScale*(-1.5*_LX*_LX*_LX + 2.0*_LX*_LX + 0.5*_LX ) ); - _LC2 = (float)floor( 0.5 + _LScale*( 0.5*_LX*_LX*_LX - 0.5*_LX*_LX) ); - lut[_LIdx+0] = (signed short)( (_LCm1 < -_LScale) ? -_LScale : ((_LCm1 > _LScale) ? _LScale : _LCm1) ); - lut[_LIdx+1] = (signed short)( (_LC0 < -_LScale) ? -_LScale : ((_LC0 > _LScale) ? _LScale : _LC0 ) ); - lut[_LIdx+2] = (signed short)( (_LC1 < -_LScale) ? -_LScale : ((_LC1 > _LScale) ? _LScale : _LC1 ) ); - lut[_LIdx+3] = (signed short)( (_LC2 < -_LScale) ? -_LScale : ((_LC2 > _LScale) ? _LScale : _LC2 ) ); -#ifdef SPLINE_CLAMPFORUNITY - _LSum = lut[_LIdx+0]+lut[_LIdx+1]+lut[_LIdx+2]+lut[_LIdx+3]; - if( _LSum != SPLINE_QUANTSCALE ) - { int _LMax = _LIdx; - if( lut[_LIdx+1]>lut[_LMax] ) _LMax = _LIdx+1; - if( lut[_LIdx+2]>lut[_LMax] ) _LMax = _LIdx+2; - if( lut[_LIdx+3]>lut[_LMax] ) _LMax = _LIdx+3; - lut[_LMax] += (SPLINE_QUANTSCALE-_LSum); - } -#endif - } -} - -CzCUBICSPLINE::~CzCUBICSPLINE( ) -{ // nothing todo -} - -CzCUBICSPLINE sspline; - -/* - ------------------------------------------------------------------------------ - fir interpolation doc, - (derived from "an engineer's guide to fir digital filters", n.j. loy) - - calculate coefficients for ideal lowpass filter (with cutoff = fc in - 0..1 (mapped to 0..nyquist)) - c[-N..N] = (i==0) ? fc : sin(fc*pi*i)/(pi*i) - - then apply selected window to coefficients - c[-N..N] *= w(0..N) - with n in 2*N and w(n) being a window function (see loy) - - then calculate gain and scale filter coefs to have unity gain. - ------------------------------------------------------------------------------ -*/ -// quantizer scale of window coefs -#define WFIR_QUANTBITS 15 -#define WFIR_QUANTSCALE (1L<<WFIR_QUANTBITS) -#define WFIR_8SHIFT (WFIR_QUANTBITS-8) -#define WFIR_16BITSHIFT (WFIR_QUANTBITS) -// log2(number)-1 of precalculated taps range is [4..12] -#define WFIR_FRACBITS 10 -#define WFIR_LUTLEN ((1L<<(WFIR_FRACBITS+1))+1) -// number of samples in window -#define WFIR_LOG2WIDTH 3 -#define WFIR_WIDTH (1L<<WFIR_LOG2WIDTH) -#define WFIR_SMPSPERWING ((WFIR_WIDTH-1)>>1) -// cutoff (1.0 == pi/2) -#define WFIR_CUTOFF 0.90f -// wfir type -#define WFIR_HANN 0 -#define WFIR_HAMMING 1 -#define WFIR_BLACKMANEXACT 2 -#define WFIR_BLACKMAN3T61 3 -#define WFIR_BLACKMAN3T67 4 -#define WFIR_BLACKMAN4T92 5 -#define WFIR_BLACKMAN4T74 6 -#define WFIR_KAISER4T 7 -#define WFIR_TYPE WFIR_BLACKMANEXACT -// wfir help -#ifndef M_zPI -#define M_zPI 3.1415926535897932384626433832795 -#endif -#define M_zEPS 1e-8 -#define M_zBESSELEPS 1e-21 - -class CzWINDOWEDFIR -{ -public: - CzWINDOWEDFIR( ); - ~CzWINDOWEDFIR( ); - float coef( int _PCnr, float _POfs, float _PCut, int _PWidth, int _PType ) -//OLD args to coef: float _PPos, float _PFc, int _PLen ) - { - double _LWidthM1 = _PWidth-1; - double _LWidthM1Half = 0.5*_LWidthM1; - double _LPosU = ((double)_PCnr - _POfs); - double _LPos = _LPosU-_LWidthM1Half; - double _LPIdl = 2.0*M_zPI/_LWidthM1; - double _LWc,_LSi; - if( fabs(_LPos)<M_zEPS ) { - _LWc = 1.0; - _LSi = _PCut; - } else { - switch( _PType ) - { - case WFIR_HANN: - _LWc = 0.50 - 0.50 * cos(_LPIdl*_LPosU); - break; - case WFIR_HAMMING: - _LWc = 0.54 - 0.46 * cos(_LPIdl*_LPosU); - break; - case WFIR_BLACKMANEXACT: - _LWc = 0.42 - 0.50 * cos(_LPIdl*_LPosU) + - 0.08 * cos(2.0*_LPIdl*_LPosU); - break; - case WFIR_BLACKMAN3T61: - _LWc = 0.44959 - 0.49364 * cos(_LPIdl*_LPosU) + - 0.05677 * cos(2.0*_LPIdl*_LPosU); - break; - case WFIR_BLACKMAN3T67: - _LWc = 0.42323 - 0.49755 * cos(_LPIdl*_LPosU) + - 0.07922 * cos(2.0*_LPIdl*_LPosU); - break; - case WFIR_BLACKMAN4T92: - _LWc = 0.35875 - 0.48829 * cos(_LPIdl*_LPosU) + - 0.14128 * cos(2.0*_LPIdl*_LPosU) - - 0.01168 * cos(3.0*_LPIdl*_LPosU); - break; - case WFIR_BLACKMAN4T74: - _LWc = 0.40217 - 0.49703 * cos(_LPIdl*_LPosU) + - 0.09392 * cos(2.0*_LPIdl*_LPosU) - - 0.00183 * cos(3.0*_LPIdl*_LPosU); - break; - case WFIR_KAISER4T: - _LWc = 0.40243 - 0.49804 * cos(_LPIdl*_LPosU) + - 0.09831 * cos(2.0*_LPIdl*_LPosU) - - 0.00122 * cos(3.0*_LPIdl*_LPosU); - break; - default: - _LWc = 1.0; - break; - } - _LPos *= M_zPI; - _LSi = sin(_PCut*_LPos)/_LPos; - } - return (float)(_LWc*_LSi); - } - static signed short lut[WFIR_LUTLEN*WFIR_WIDTH]; -}; - -signed short CzWINDOWEDFIR::lut[WFIR_LUTLEN*WFIR_WIDTH]; - -CzWINDOWEDFIR::CzWINDOWEDFIR() -{ - int _LPcl; - float _LPcllen = (float)(1L<<WFIR_FRACBITS); // number of precalculated lines for 0..1 (-1..0) - float _LNorm = 1.0f / (float)(2.0f * _LPcllen); - float _LCut = WFIR_CUTOFF; - float _LScale = (float)WFIR_QUANTSCALE; - for( _LPcl=0;_LPcl<WFIR_LUTLEN;_LPcl++ ) - { - float _LGain,_LCoefs[WFIR_WIDTH]; - float _LOfs = ((float)_LPcl-_LPcllen)*_LNorm; - int _LCc,_LIdx = _LPcl<<WFIR_LOG2WIDTH; - for( _LCc=0,_LGain=0.0f;_LCc<WFIR_WIDTH;_LCc++ ) - { _LGain += (_LCoefs[_LCc] = coef( _LCc, _LOfs, _LCut, WFIR_WIDTH, WFIR_TYPE )); - } - _LGain = 1.0f/_LGain; - for( _LCc=0;_LCc<WFIR_WIDTH;_LCc++ ) - { float _LCoef = (float)floor( 0.5 + _LScale*_LCoefs[_LCc]*_LGain ); - lut[_LIdx+_LCc] = (signed short)( (_LCoef<-_LScale)?-_LScale:((_LCoef>_LScale)?_LScale:_LCoef) ); - } - } -} - -CzWINDOWEDFIR::~CzWINDOWEDFIR() -{ // nothing todo -} - -CzWINDOWEDFIR sfir; - -// ---------------------------------------------------------------------------- -// MIXING MACROS -// ---------------------------------------------------------------------------- -#define SNDMIX_BEGINSAMPLELOOP8\ - register MODCHANNEL * const pChn = pChannel;\ - nPos = pChn->nPosLo;\ - const signed char *p = (signed char *)(pChn->pCurrentSample+pChn->nPos);\ - if (pChn->dwFlags & CHN_STEREO) p += pChn->nPos;\ - int *pvol = pbuffer;\ - do { - -#define SNDMIX_BEGINSAMPLELOOP16\ - register MODCHANNEL * const pChn = pChannel;\ - nPos = pChn->nPosLo;\ - const signed short *p = (signed short *)(pChn->pCurrentSample+(pChn->nPos*2));\ - if (pChn->dwFlags & CHN_STEREO) p += pChn->nPos;\ - int *pvol = pbuffer;\ - do { - -#define SNDMIX_ENDSAMPLELOOP\ - nPos += pChn->nInc;\ - } while (pvol < pbufmax);\ - pChn->nPos += nPos >> 16;\ - pChn->nPosLo = nPos & 0xFFFF; - -#define SNDMIX_ENDSAMPLELOOP8 SNDMIX_ENDSAMPLELOOP -#define SNDMIX_ENDSAMPLELOOP16 SNDMIX_ENDSAMPLELOOP - -////////////////////////////////////////////////////////////////////////////// -// Mono - -// No interpolation -#define SNDMIX_GETMONOVOL8NOIDO\ - int vol = p[nPos >> 16] << 8; - -#define SNDMIX_GETMONOVOL16NOIDO\ - int vol = p[nPos >> 16]; - -// Linear Interpolation -#define SNDMIX_GETMONOVOL8LINEAR\ - int poshi = nPos >> 16;\ - int poslo = (nPos >> 8) & 0xFF;\ - int srcvol = p[poshi];\ - int destvol = p[poshi+1];\ - int vol = (srcvol<<8) + ((int)(poslo * (destvol - srcvol))); - -#define SNDMIX_GETMONOVOL16LINEAR\ - int poshi = nPos >> 16;\ - int poslo = (nPos >> 8) & 0xFF;\ - int srcvol = p[poshi];\ - int destvol = p[poshi+1];\ - int vol = srcvol + ((int)(poslo * (destvol - srcvol)) >> 8); - -// spline interpolation (2 guard bits should be enough???) -#define SPLINE_FRACSHIFT ((16-SPLINE_FRACBITS)-2) -#define SPLINE_FRACMASK (((1L<<(16-SPLINE_FRACSHIFT))-1)&~3) - -#define SNDMIX_GETMONOVOL8SPLINE \ - int poshi = nPos >> 16; \ - int poslo = (nPos >> SPLINE_FRACSHIFT) & SPLINE_FRACMASK; \ - int vol = (CzCUBICSPLINE::lut[poslo ]*(int)p[poshi-1] + \ - CzCUBICSPLINE::lut[poslo+1]*(int)p[poshi ] + \ - CzCUBICSPLINE::lut[poslo+3]*(int)p[poshi+2] + \ - CzCUBICSPLINE::lut[poslo+2]*(int)p[poshi+1]) >> SPLINE_8SHIFT; - -#define SNDMIX_GETMONOVOL16SPLINE \ - int poshi = nPos >> 16; \ - int poslo = (nPos >> SPLINE_FRACSHIFT) & SPLINE_FRACMASK; \ - int vol = (CzCUBICSPLINE::lut[poslo ]*(int)p[poshi-1] + \ - CzCUBICSPLINE::lut[poslo+1]*(int)p[poshi ] + \ - CzCUBICSPLINE::lut[poslo+3]*(int)p[poshi+2] + \ - CzCUBICSPLINE::lut[poslo+2]*(int)p[poshi+1]) >> SPLINE_16SHIFT; - - -// fir interpolation -#define WFIR_FRACSHIFT (16-(WFIR_FRACBITS+1+WFIR_LOG2WIDTH)) -#define WFIR_FRACMASK ((((1L<<(17-WFIR_FRACSHIFT))-1)&~((1L<<WFIR_LOG2WIDTH)-1))) -#define WFIR_FRACHALVE (1L<<(16-(WFIR_FRACBITS+2))) - -#define SNDMIX_GETMONOVOL8FIRFILTER \ - int poshi = nPos >> 16;\ - int poslo = (nPos & 0xFFFF);\ - int firidx = ((poslo+WFIR_FRACHALVE)>>WFIR_FRACSHIFT) & WFIR_FRACMASK; \ - int vol = (CzWINDOWEDFIR::lut[firidx+0]*(int)p[poshi+1-4]); \ - vol += (CzWINDOWEDFIR::lut[firidx+1]*(int)p[poshi+2-4]); \ - vol += (CzWINDOWEDFIR::lut[firidx+2]*(int)p[poshi+3-4]); \ - vol += (CzWINDOWEDFIR::lut[firidx+3]*(int)p[poshi+4-4]); \ - vol += (CzWINDOWEDFIR::lut[firidx+4]*(int)p[poshi+5-4]); \ - vol += (CzWINDOWEDFIR::lut[firidx+5]*(int)p[poshi+6-4]); \ - vol += (CzWINDOWEDFIR::lut[firidx+6]*(int)p[poshi+7-4]); \ - vol += (CzWINDOWEDFIR::lut[firidx+7]*(int)p[poshi+8-4]); \ - vol >>= WFIR_8SHIFT; - -#define SNDMIX_GETMONOVOL16FIRFILTER \ - int poshi = nPos >> 16;\ - int poslo = (nPos & 0xFFFF);\ - int firidx = ((poslo+WFIR_FRACHALVE)>>WFIR_FRACSHIFT) & WFIR_FRACMASK; \ - int vol1 = (CzWINDOWEDFIR::lut[firidx+0]*(int)p[poshi+1-4]); \ - vol1 += (CzWINDOWEDFIR::lut[firidx+1]*(int)p[poshi+2-4]); \ - vol1 += (CzWINDOWEDFIR::lut[firidx+2]*(int)p[poshi+3-4]); \ - vol1 += (CzWINDOWEDFIR::lut[firidx+3]*(int)p[poshi+4-4]); \ - int vol2 = (CzWINDOWEDFIR::lut[firidx+4]*(int)p[poshi+5-4]); \ - vol2 += (CzWINDOWEDFIR::lut[firidx+5]*(int)p[poshi+6-4]); \ - vol2 += (CzWINDOWEDFIR::lut[firidx+6]*(int)p[poshi+7-4]); \ - vol2 += (CzWINDOWEDFIR::lut[firidx+7]*(int)p[poshi+8-4]); \ - int vol = ((vol1>>1)+(vol2>>1)) >> (WFIR_16BITSHIFT-1); - -///////////////////////////////////////////////////////////////////////////// -// Stereo - -// No interpolation -#define SNDMIX_GETSTEREOVOL8NOIDO\ - int vol_l = p[(nPos>>16)*2] << 8;\ - int vol_r = p[(nPos>>16)*2+1] << 8; - -#define SNDMIX_GETSTEREOVOL16NOIDO\ - int vol_l = p[(nPos>>16)*2];\ - int vol_r = p[(nPos>>16)*2+1]; - -// Linear Interpolation -#define SNDMIX_GETSTEREOVOL8LINEAR\ - int poshi = nPos >> 16;\ - int poslo = (nPos >> 8) & 0xFF;\ - int srcvol_l = p[poshi*2];\ - int vol_l = (srcvol_l<<8) + ((int)(poslo * (p[poshi*2+2] - srcvol_l)));\ - int srcvol_r = p[poshi*2+1];\ - int vol_r = (srcvol_r<<8) + ((int)(poslo * (p[poshi*2+3] - srcvol_r))); - -#define SNDMIX_GETSTEREOVOL16LINEAR\ - int poshi = nPos >> 16;\ - int poslo = (nPos >> 8) & 0xFF;\ - int srcvol_l = p[poshi*2];\ - int vol_l = srcvol_l + ((int)(poslo * (p[poshi*2+2] - srcvol_l)) >> 8);\ - int srcvol_r = p[poshi*2+1];\ - int vol_r = srcvol_r + ((int)(poslo * (p[poshi*2+3] - srcvol_r)) >> 8);\ - -// Spline Interpolation -#define SNDMIX_GETSTEREOVOL8SPLINE \ - int poshi = nPos >> 16; \ - int poslo = (nPos >> SPLINE_FRACSHIFT) & SPLINE_FRACMASK; \ - int vol_l = (CzCUBICSPLINE::lut[poslo ]*(int)p[(poshi-1)*2 ] + \ - CzCUBICSPLINE::lut[poslo+1]*(int)p[(poshi )*2 ] + \ - CzCUBICSPLINE::lut[poslo+2]*(int)p[(poshi+1)*2 ] + \ - CzCUBICSPLINE::lut[poslo+3]*(int)p[(poshi+2)*2 ]) >> SPLINE_8SHIFT; \ - int vol_r = (CzCUBICSPLINE::lut[poslo ]*(int)p[(poshi-1)*2+1] + \ - CzCUBICSPLINE::lut[poslo+1]*(int)p[(poshi )*2+1] + \ - CzCUBICSPLINE::lut[poslo+2]*(int)p[(poshi+1)*2+1] + \ - CzCUBICSPLINE::lut[poslo+3]*(int)p[(poshi+2)*2+1]) >> SPLINE_8SHIFT; - -#define SNDMIX_GETSTEREOVOL16SPLINE \ - int poshi = nPos >> 16; \ - int poslo = (nPos >> SPLINE_FRACSHIFT) & SPLINE_FRACMASK; \ - int vol_l = (CzCUBICSPLINE::lut[poslo ]*(int)p[(poshi-1)*2 ] + \ - CzCUBICSPLINE::lut[poslo+1]*(int)p[(poshi )*2 ] + \ - CzCUBICSPLINE::lut[poslo+2]*(int)p[(poshi+1)*2 ] + \ - CzCUBICSPLINE::lut[poslo+3]*(int)p[(poshi+2)*2 ]) >> SPLINE_16SHIFT; \ - int vol_r = (CzCUBICSPLINE::lut[poslo ]*(int)p[(poshi-1)*2+1] + \ - CzCUBICSPLINE::lut[poslo+1]*(int)p[(poshi )*2+1] + \ - CzCUBICSPLINE::lut[poslo+2]*(int)p[(poshi+1)*2+1] + \ - CzCUBICSPLINE::lut[poslo+3]*(int)p[(poshi+2)*2+1]) >> SPLINE_16SHIFT; - -// fir interpolation -#define SNDMIX_GETSTEREOVOL8FIRFILTER \ - int poshi = nPos >> 16;\ - int poslo = (nPos & 0xFFFF);\ - int firidx = ((poslo+WFIR_FRACHALVE)>>WFIR_FRACSHIFT) & WFIR_FRACMASK; \ - int vol_l = (CzWINDOWEDFIR::lut[firidx+0]*(int)p[(poshi+1-4)*2 ]); \ - vol_l += (CzWINDOWEDFIR::lut[firidx+1]*(int)p[(poshi+2-4)*2 ]); \ - vol_l += (CzWINDOWEDFIR::lut[firidx+2]*(int)p[(poshi+3-4)*2 ]); \ - vol_l += (CzWINDOWEDFIR::lut[firidx+3]*(int)p[(poshi+4-4)*2 ]); \ - vol_l += (CzWINDOWEDFIR::lut[firidx+4]*(int)p[(poshi+5-4)*2 ]); \ - vol_l += (CzWINDOWEDFIR::lut[firidx+5]*(int)p[(poshi+6-4)*2 ]); \ - vol_l += (CzWINDOWEDFIR::lut[firidx+6]*(int)p[(poshi+7-4)*2 ]); \ - vol_l += (CzWINDOWEDFIR::lut[firidx+7]*(int)p[(poshi+8-4)*2 ]); \ - vol_l >>= WFIR_8SHIFT; \ - int vol_r = (CzWINDOWEDFIR::lut[firidx+0]*(int)p[(poshi+1-4)*2+1]); \ - vol_r += (CzWINDOWEDFIR::lut[firidx+1]*(int)p[(poshi+2-4)*2+1]); \ - vol_r += (CzWINDOWEDFIR::lut[firidx+2]*(int)p[(poshi+3-4)*2+1]); \ - vol_r += (CzWINDOWEDFIR::lut[firidx+3]*(int)p[(poshi+4-4)*2+1]); \ - vol_r += (CzWINDOWEDFIR::lut[firidx+4]*(int)p[(poshi+5-4)*2+1]); \ - vol_r += (CzWINDOWEDFIR::lut[firidx+5]*(int)p[(poshi+6-4)*2+1]); \ - vol_r += (CzWINDOWEDFIR::lut[firidx+6]*(int)p[(poshi+7-4)*2+1]); \ - vol_r += (CzWINDOWEDFIR::lut[firidx+7]*(int)p[(poshi+8-4)*2+1]); \ - vol_r >>= WFIR_8SHIFT; - -#define SNDMIX_GETSTEREOVOL16FIRFILTER \ - int poshi = nPos >> 16;\ - int poslo = (nPos & 0xFFFF);\ - int firidx = ((poslo+WFIR_FRACHALVE)>>WFIR_FRACSHIFT) & WFIR_FRACMASK; \ - int vol1_l = (CzWINDOWEDFIR::lut[firidx+0]*(int)p[(poshi+1-4)*2 ]); \ - vol1_l += (CzWINDOWEDFIR::lut[firidx+1]*(int)p[(poshi+2-4)*2 ]); \ - vol1_l += (CzWINDOWEDFIR::lut[firidx+2]*(int)p[(poshi+3-4)*2 ]); \ - vol1_l += (CzWINDOWEDFIR::lut[firidx+3]*(int)p[(poshi+4-4)*2 ]); \ - int vol2_l = (CzWINDOWEDFIR::lut[firidx+4]*(int)p[(poshi+5-4)*2 ]); \ - vol2_l += (CzWINDOWEDFIR::lut[firidx+5]*(int)p[(poshi+6-4)*2 ]); \ - vol2_l += (CzWINDOWEDFIR::lut[firidx+6]*(int)p[(poshi+7-4)*2 ]); \ - vol2_l += (CzWINDOWEDFIR::lut[firidx+7]*(int)p[(poshi+8-4)*2 ]); \ - int vol_l = ((vol1_l>>1)+(vol2_l>>1)) >> (WFIR_16BITSHIFT-1); \ - int vol1_r = (CzWINDOWEDFIR::lut[firidx+0]*(int)p[(poshi+1-4)*2+1]); \ - vol1_r += (CzWINDOWEDFIR::lut[firidx+1]*(int)p[(poshi+2-4)*2+1]); \ - vol1_r += (CzWINDOWEDFIR::lut[firidx+2]*(int)p[(poshi+3-4)*2+1]); \ - vol1_r += (CzWINDOWEDFIR::lut[firidx+3]*(int)p[(poshi+4-4)*2+1]); \ - int vol2_r = (CzWINDOWEDFIR::lut[firidx+4]*(int)p[(poshi+5-4)*2+1]); \ - vol2_r += (CzWINDOWEDFIR::lut[firidx+5]*(int)p[(poshi+6-4)*2+1]); \ - vol2_r += (CzWINDOWEDFIR::lut[firidx+6]*(int)p[(poshi+7-4)*2+1]); \ - vol2_r += (CzWINDOWEDFIR::lut[firidx+7]*(int)p[(poshi+8-4)*2+1]); \ - int vol_r = ((vol1_r>>1)+(vol2_r>>1)) >> (WFIR_16BITSHIFT-1); - -///////////////////////////////////////////////////////////////////////////// - -#define SNDMIX_STOREMONOVOL\ - pvol[0] += vol * pChn->nRightVol;\ - pvol[1] += vol * pChn->nLeftVol;\ - pvol += 2; - -#define SNDMIX_STORESTEREOVOL\ - pvol[0] += vol_l * pChn->nRightVol;\ - pvol[1] += vol_r * pChn->nLeftVol;\ - pvol += 2; - -#define SNDMIX_STOREFASTMONOVOL\ - int v = vol * pChn->nRightVol;\ - pvol[0] += v;\ - pvol[1] += v;\ - pvol += 2; - -#define SNDMIX_RAMPMONOVOL\ - nRampLeftVol += pChn->nLeftRamp;\ - nRampRightVol += pChn->nRightRamp;\ - pvol[0] += vol * (nRampRightVol >> VOLUMERAMPPRECISION);\ - pvol[1] += vol * (nRampLeftVol >> VOLUMERAMPPRECISION);\ - pvol += 2; - -#define SNDMIX_RAMPFASTMONOVOL\ - nRampRightVol += pChn->nRightRamp;\ - int fastvol = vol * (nRampRightVol >> VOLUMERAMPPRECISION);\ - pvol[0] += fastvol;\ - pvol[1] += fastvol;\ - pvol += 2; - -#define SNDMIX_RAMPSTEREOVOL\ - nRampLeftVol += pChn->nLeftRamp;\ - nRampRightVol += pChn->nRightRamp;\ - pvol[0] += vol_l * (nRampRightVol >> VOLUMERAMPPRECISION);\ - pvol[1] += vol_r * (nRampLeftVol >> VOLUMERAMPPRECISION);\ - pvol += 2; - - -/////////////////////////////////////////////////// -// Resonant Filters - -// Mono -#define MIX_BEGIN_FILTER\ - int fy1 = pChannel->nFilter_Y1;\ - int fy2 = pChannel->nFilter_Y2;\ - -#define MIX_END_FILTER\ - pChannel->nFilter_Y1 = fy1;\ - pChannel->nFilter_Y2 = fy2; - -#define SNDMIX_PROCESSFILTER\ - vol = (vol * pChn->nFilter_A0 + fy1 * pChn->nFilter_B0 + fy2 * pChn->nFilter_B1 + 4096) >> 13;\ - fy2 = fy1;\ - fy1 = vol;\ - -// Stereo -#define MIX_BEGIN_STEREO_FILTER\ - int fy1 = pChannel->nFilter_Y1;\ - int fy2 = pChannel->nFilter_Y2;\ - int fy3 = pChannel->nFilter_Y3;\ - int fy4 = pChannel->nFilter_Y4;\ - -#define MIX_END_STEREO_FILTER\ - pChannel->nFilter_Y1 = fy1;\ - pChannel->nFilter_Y2 = fy2;\ - pChannel->nFilter_Y3 = fy3;\ - pChannel->nFilter_Y4 = fy4;\ - -#define SNDMIX_PROCESSSTEREOFILTER\ - vol_l = (vol_l * pChn->nFilter_A0 + fy1 * pChn->nFilter_B0 + fy2 * pChn->nFilter_B1 + 4096) >> 13;\ - vol_r = (vol_r * pChn->nFilter_A0 + fy3 * pChn->nFilter_B0 + fy4 * pChn->nFilter_B1 + 4096) >> 13;\ - fy2 = fy1; fy1 = vol_l;\ - fy4 = fy3; fy3 = vol_r;\ - -////////////////////////////////////////////////////////// -// Interfaces - -typedef VOID (MPPASMCALL * LPMIXINTERFACE)(MODCHANNEL *, int *, int *); - -#define BEGIN_MIX_INTERFACE(func)\ - VOID MPPASMCALL func(MODCHANNEL *pChannel, int *pbuffer, int *pbufmax)\ - {\ - LONG nPos; - -#define END_MIX_INTERFACE()\ - SNDMIX_ENDSAMPLELOOP\ - } - -// Volume Ramps -#define BEGIN_RAMPMIX_INTERFACE(func)\ - BEGIN_MIX_INTERFACE(func)\ - LONG nRampRightVol = pChannel->nRampRightVol;\ - LONG nRampLeftVol = pChannel->nRampLeftVol; - -#define END_RAMPMIX_INTERFACE()\ - SNDMIX_ENDSAMPLELOOP\ - pChannel->nRampRightVol = nRampRightVol;\ - pChannel->nRightVol = nRampRightVol >> VOLUMERAMPPRECISION;\ - pChannel->nRampLeftVol = nRampLeftVol;\ - pChannel->nLeftVol = nRampLeftVol >> VOLUMERAMPPRECISION;\ - } - -#define BEGIN_FASTRAMPMIX_INTERFACE(func)\ - BEGIN_MIX_INTERFACE(func)\ - LONG nRampRightVol = pChannel->nRampRightVol; - -#define END_FASTRAMPMIX_INTERFACE()\ - SNDMIX_ENDSAMPLELOOP\ - pChannel->nRampRightVol = nRampRightVol;\ - pChannel->nRampLeftVol = nRampRightVol;\ - pChannel->nRightVol = nRampRightVol >> VOLUMERAMPPRECISION;\ - pChannel->nLeftVol = pChannel->nRightVol;\ - } - - -// Mono Resonant Filters -#define BEGIN_MIX_FLT_INTERFACE(func)\ - BEGIN_MIX_INTERFACE(func)\ - MIX_BEGIN_FILTER - - -#define END_MIX_FLT_INTERFACE()\ - SNDMIX_ENDSAMPLELOOP\ - MIX_END_FILTER\ - } - -#define BEGIN_RAMPMIX_FLT_INTERFACE(func)\ - BEGIN_MIX_INTERFACE(func)\ - LONG nRampRightVol = pChannel->nRampRightVol;\ - LONG nRampLeftVol = pChannel->nRampLeftVol;\ - MIX_BEGIN_FILTER - -#define END_RAMPMIX_FLT_INTERFACE()\ - SNDMIX_ENDSAMPLELOOP\ - MIX_END_FILTER\ - pChannel->nRampRightVol = nRampRightVol;\ - pChannel->nRightVol = nRampRightVol >> VOLUMERAMPPRECISION;\ - pChannel->nRampLeftVol = nRampLeftVol;\ - pChannel->nLeftVol = nRampLeftVol >> VOLUMERAMPPRECISION;\ - } - -// Stereo Resonant Filters -#define BEGIN_MIX_STFLT_INTERFACE(func)\ - BEGIN_MIX_INTERFACE(func)\ - MIX_BEGIN_STEREO_FILTER - - -#define END_MIX_STFLT_INTERFACE()\ - SNDMIX_ENDSAMPLELOOP\ - MIX_END_STEREO_FILTER\ - } - -#define BEGIN_RAMPMIX_STFLT_INTERFACE(func)\ - BEGIN_MIX_INTERFACE(func)\ - LONG nRampRightVol = pChannel->nRampRightVol;\ - LONG nRampLeftVol = pChannel->nRampLeftVol;\ - MIX_BEGIN_STEREO_FILTER - -#define END_RAMPMIX_STFLT_INTERFACE()\ - SNDMIX_ENDSAMPLELOOP\ - MIX_END_STEREO_FILTER\ - pChannel->nRampRightVol = nRampRightVol;\ - pChannel->nRightVol = nRampRightVol >> VOLUMERAMPPRECISION;\ - pChannel->nRampLeftVol = nRampLeftVol;\ - pChannel->nLeftVol = nRampLeftVol >> VOLUMERAMPPRECISION;\ - } - - -///////////////////////////////////////////////////// -// - -void MPPASMCALL X86_InitMixBuffer(int *pBuffer, UINT nSamples); -void MPPASMCALL X86_EndChannelOfs(MODCHANNEL *pChannel, int *pBuffer, UINT nSamples); -void MPPASMCALL X86_StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs); -void X86_StereoMixToFloat(const int *, float *, float *, UINT nCount); -void X86_FloatToStereoMix(const float *pIn1, const float *pIn2, int *pOut, UINT nCount); - -///////////////////////////////////////////////////// -// Mono samples functions - -BEGIN_MIX_INTERFACE(Mono8BitMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8NOIDO - SNDMIX_STOREMONOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(Mono16BitMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16NOIDO - SNDMIX_STOREMONOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(Mono8BitLinearMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8LINEAR - SNDMIX_STOREMONOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(Mono16BitLinearMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16LINEAR - SNDMIX_STOREMONOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(Mono8BitSplineMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8SPLINE - SNDMIX_STOREMONOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(Mono16BitSplineMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16SPLINE - SNDMIX_STOREMONOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(Mono8BitFirFilterMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8FIRFILTER - SNDMIX_STOREMONOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(Mono16BitFirFilterMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16FIRFILTER - SNDMIX_STOREMONOVOL -END_MIX_INTERFACE() - - -// Volume Ramps -BEGIN_RAMPMIX_INTERFACE(Mono8BitRampMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8NOIDO - SNDMIX_RAMPMONOVOL -END_RAMPMIX_INTERFACE() - -BEGIN_RAMPMIX_INTERFACE(Mono16BitRampMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16NOIDO - SNDMIX_RAMPMONOVOL -END_RAMPMIX_INTERFACE() - -BEGIN_RAMPMIX_INTERFACE(Mono8BitLinearRampMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8LINEAR - SNDMIX_RAMPMONOVOL -END_RAMPMIX_INTERFACE() - -BEGIN_RAMPMIX_INTERFACE(Mono16BitLinearRampMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16LINEAR - SNDMIX_RAMPMONOVOL -END_RAMPMIX_INTERFACE() - -BEGIN_RAMPMIX_INTERFACE(Mono8BitSplineRampMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8SPLINE - SNDMIX_RAMPMONOVOL -END_RAMPMIX_INTERFACE() - -BEGIN_RAMPMIX_INTERFACE(Mono16BitSplineRampMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16SPLINE - SNDMIX_RAMPMONOVOL -END_RAMPMIX_INTERFACE() - -BEGIN_RAMPMIX_INTERFACE(Mono8BitFirFilterRampMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8FIRFILTER - SNDMIX_RAMPMONOVOL -END_RAMPMIX_INTERFACE() - -BEGIN_RAMPMIX_INTERFACE(Mono16BitFirFilterRampMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16FIRFILTER - SNDMIX_RAMPMONOVOL -END_RAMPMIX_INTERFACE() - - -////////////////////////////////////////////////////// -// Fast mono mix for leftvol=rightvol (1 less imul) - -BEGIN_MIX_INTERFACE(FastMono8BitMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8NOIDO - SNDMIX_STOREFASTMONOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(FastMono16BitMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16NOIDO - SNDMIX_STOREFASTMONOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(FastMono8BitLinearMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8LINEAR - SNDMIX_STOREFASTMONOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(FastMono16BitLinearMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16LINEAR - SNDMIX_STOREFASTMONOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(FastMono8BitSplineMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8SPLINE - SNDMIX_STOREFASTMONOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(FastMono16BitSplineMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16SPLINE - SNDMIX_STOREFASTMONOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(FastMono8BitFirFilterMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8FIRFILTER - SNDMIX_STOREFASTMONOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(FastMono16BitFirFilterMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16FIRFILTER - SNDMIX_STOREFASTMONOVOL -END_MIX_INTERFACE() - - -// Fast Ramps -BEGIN_FASTRAMPMIX_INTERFACE(FastMono8BitRampMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8NOIDO - SNDMIX_RAMPFASTMONOVOL -END_FASTRAMPMIX_INTERFACE() - -BEGIN_FASTRAMPMIX_INTERFACE(FastMono16BitRampMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16NOIDO - SNDMIX_RAMPFASTMONOVOL -END_FASTRAMPMIX_INTERFACE() - -BEGIN_FASTRAMPMIX_INTERFACE(FastMono8BitLinearRampMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8LINEAR - SNDMIX_RAMPFASTMONOVOL -END_FASTRAMPMIX_INTERFACE() - -BEGIN_FASTRAMPMIX_INTERFACE(FastMono16BitLinearRampMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16LINEAR - SNDMIX_RAMPFASTMONOVOL -END_FASTRAMPMIX_INTERFACE() - -BEGIN_FASTRAMPMIX_INTERFACE(FastMono8BitSplineRampMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8SPLINE - SNDMIX_RAMPFASTMONOVOL -END_FASTRAMPMIX_INTERFACE() - -BEGIN_FASTRAMPMIX_INTERFACE(FastMono16BitSplineRampMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16SPLINE - SNDMIX_RAMPFASTMONOVOL -END_FASTRAMPMIX_INTERFACE() - -BEGIN_FASTRAMPMIX_INTERFACE(FastMono8BitFirFilterRampMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8FIRFILTER - SNDMIX_RAMPFASTMONOVOL -END_FASTRAMPMIX_INTERFACE() - -BEGIN_FASTRAMPMIX_INTERFACE(FastMono16BitFirFilterRampMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16FIRFILTER - SNDMIX_RAMPFASTMONOVOL -END_FASTRAMPMIX_INTERFACE() - - -////////////////////////////////////////////////////// -// Stereo samples - -BEGIN_MIX_INTERFACE(Stereo8BitMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETSTEREOVOL8NOIDO - SNDMIX_STORESTEREOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(Stereo16BitMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETSTEREOVOL16NOIDO - SNDMIX_STORESTEREOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(Stereo8BitLinearMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETSTEREOVOL8LINEAR - SNDMIX_STORESTEREOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(Stereo16BitLinearMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETSTEREOVOL16LINEAR - SNDMIX_STORESTEREOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(Stereo8BitSplineMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETSTEREOVOL8SPLINE - SNDMIX_STORESTEREOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(Stereo16BitSplineMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETSTEREOVOL16SPLINE - SNDMIX_STORESTEREOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(Stereo8BitFirFilterMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETSTEREOVOL8FIRFILTER - SNDMIX_STORESTEREOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(Stereo16BitFirFilterMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETSTEREOVOL16FIRFILTER - SNDMIX_STORESTEREOVOL -END_MIX_INTERFACE() - - -// Volume Ramps -BEGIN_RAMPMIX_INTERFACE(Stereo8BitRampMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETSTEREOVOL8NOIDO - SNDMIX_RAMPSTEREOVOL -END_RAMPMIX_INTERFACE() - -BEGIN_RAMPMIX_INTERFACE(Stereo16BitRampMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETSTEREOVOL16NOIDO - SNDMIX_RAMPSTEREOVOL -END_RAMPMIX_INTERFACE() - -BEGIN_RAMPMIX_INTERFACE(Stereo8BitLinearRampMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETSTEREOVOL8LINEAR - SNDMIX_RAMPSTEREOVOL -END_RAMPMIX_INTERFACE() - -BEGIN_RAMPMIX_INTERFACE(Stereo16BitLinearRampMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETSTEREOVOL16LINEAR - SNDMIX_RAMPSTEREOVOL -END_RAMPMIX_INTERFACE() - -BEGIN_RAMPMIX_INTERFACE(Stereo8BitSplineRampMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETSTEREOVOL8SPLINE - SNDMIX_RAMPSTEREOVOL -END_RAMPMIX_INTERFACE() - -BEGIN_RAMPMIX_INTERFACE(Stereo16BitSplineRampMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETSTEREOVOL16SPLINE - SNDMIX_RAMPSTEREOVOL -END_RAMPMIX_INTERFACE() - -BEGIN_RAMPMIX_INTERFACE(Stereo8BitFirFilterRampMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETSTEREOVOL8FIRFILTER - SNDMIX_RAMPSTEREOVOL -END_RAMPMIX_INTERFACE() - -BEGIN_RAMPMIX_INTERFACE(Stereo16BitFirFilterRampMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETSTEREOVOL16FIRFILTER - SNDMIX_RAMPSTEREOVOL -END_RAMPMIX_INTERFACE() - - - -////////////////////////////////////////////////////// -// Resonant Filter Mix - -#ifndef NO_FILTER - -// Mono Filter Mix -BEGIN_MIX_FLT_INTERFACE(FilterMono8BitMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8NOIDO - SNDMIX_PROCESSFILTER - SNDMIX_STOREMONOVOL -END_MIX_FLT_INTERFACE() - -BEGIN_MIX_FLT_INTERFACE(FilterMono16BitMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16NOIDO - SNDMIX_PROCESSFILTER - SNDMIX_STOREMONOVOL -END_MIX_FLT_INTERFACE() - -BEGIN_MIX_FLT_INTERFACE(FilterMono8BitLinearMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8LINEAR - SNDMIX_PROCESSFILTER - SNDMIX_STOREMONOVOL -END_MIX_FLT_INTERFACE() - -BEGIN_MIX_FLT_INTERFACE(FilterMono16BitLinearMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16LINEAR - SNDMIX_PROCESSFILTER - SNDMIX_STOREMONOVOL -END_MIX_FLT_INTERFACE() - -BEGIN_MIX_FLT_INTERFACE(FilterMono8BitSplineMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8SPLINE - SNDMIX_PROCESSFILTER - SNDMIX_STOREMONOVOL -END_MIX_FLT_INTERFACE() - -BEGIN_MIX_FLT_INTERFACE(FilterMono16BitSplineMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16SPLINE - SNDMIX_PROCESSFILTER - SNDMIX_STOREMONOVOL -END_MIX_FLT_INTERFACE() - -BEGIN_MIX_FLT_INTERFACE(FilterMono8BitFirFilterMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8FIRFILTER - SNDMIX_PROCESSFILTER - SNDMIX_STOREMONOVOL -END_MIX_FLT_INTERFACE() - -BEGIN_MIX_FLT_INTERFACE(FilterMono16BitFirFilterMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16FIRFILTER - SNDMIX_PROCESSFILTER - SNDMIX_STOREMONOVOL -END_MIX_FLT_INTERFACE() - -// Filter + Ramp -BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono8BitRampMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8NOIDO - SNDMIX_PROCESSFILTER - SNDMIX_RAMPMONOVOL -END_RAMPMIX_FLT_INTERFACE() - -BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono16BitRampMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16NOIDO - SNDMIX_PROCESSFILTER - SNDMIX_RAMPMONOVOL -END_RAMPMIX_FLT_INTERFACE() - -BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono8BitLinearRampMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8LINEAR - SNDMIX_PROCESSFILTER - SNDMIX_RAMPMONOVOL -END_RAMPMIX_FLT_INTERFACE() - -BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono16BitLinearRampMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16LINEAR - SNDMIX_PROCESSFILTER - SNDMIX_RAMPMONOVOL -END_RAMPMIX_FLT_INTERFACE() - -BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono8BitSplineRampMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8SPLINE - SNDMIX_PROCESSFILTER - SNDMIX_RAMPMONOVOL -END_RAMPMIX_FLT_INTERFACE() - -BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono16BitSplineRampMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16SPLINE - SNDMIX_PROCESSFILTER - SNDMIX_RAMPMONOVOL -END_RAMPMIX_FLT_INTERFACE() - -BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono8BitFirFilterRampMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8FIRFILTER - SNDMIX_PROCESSFILTER - SNDMIX_RAMPMONOVOL -END_RAMPMIX_FLT_INTERFACE() - -BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono16BitFirFilterRampMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16FIRFILTER - SNDMIX_PROCESSFILTER - SNDMIX_RAMPMONOVOL -END_RAMPMIX_FLT_INTERFACE() - - -// Stereo Filter Mix -BEGIN_MIX_STFLT_INTERFACE(FilterStereo8BitMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETSTEREOVOL8NOIDO - SNDMIX_PROCESSSTEREOFILTER - SNDMIX_STORESTEREOVOL -END_MIX_STFLT_INTERFACE() - -BEGIN_MIX_STFLT_INTERFACE(FilterStereo16BitMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETSTEREOVOL16NOIDO - SNDMIX_PROCESSSTEREOFILTER - SNDMIX_STORESTEREOVOL -END_MIX_STFLT_INTERFACE() - -BEGIN_MIX_STFLT_INTERFACE(FilterStereo8BitLinearMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETSTEREOVOL8LINEAR - SNDMIX_PROCESSSTEREOFILTER - SNDMIX_STORESTEREOVOL -END_MIX_STFLT_INTERFACE() - -BEGIN_MIX_STFLT_INTERFACE(FilterStereo16BitLinearMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETSTEREOVOL16LINEAR - SNDMIX_PROCESSSTEREOFILTER - SNDMIX_STORESTEREOVOL -END_MIX_STFLT_INTERFACE() - -BEGIN_MIX_STFLT_INTERFACE(FilterStereo8BitSplineMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETSTEREOVOL8SPLINE - SNDMIX_PROCESSSTEREOFILTER - SNDMIX_STORESTEREOVOL -END_MIX_STFLT_INTERFACE() - -BEGIN_MIX_STFLT_INTERFACE(FilterStereo16BitSplineMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETSTEREOVOL16SPLINE - SNDMIX_PROCESSSTEREOFILTER - SNDMIX_STORESTEREOVOL -END_MIX_STFLT_INTERFACE() - -BEGIN_MIX_STFLT_INTERFACE(FilterStereo8BitFirFilterMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETSTEREOVOL8FIRFILTER - SNDMIX_PROCESSSTEREOFILTER - SNDMIX_STORESTEREOVOL -END_MIX_STFLT_INTERFACE() - -BEGIN_MIX_STFLT_INTERFACE(FilterStereo16BitFirFilterMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETSTEREOVOL16FIRFILTER - SNDMIX_PROCESSSTEREOFILTER - SNDMIX_STORESTEREOVOL -END_MIX_STFLT_INTERFACE() - -// Stereo Filter + Ramp -BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo8BitRampMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETSTEREOVOL8NOIDO - SNDMIX_PROCESSSTEREOFILTER - SNDMIX_RAMPSTEREOVOL -END_RAMPMIX_STFLT_INTERFACE() - -BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo16BitRampMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETSTEREOVOL16NOIDO - SNDMIX_PROCESSSTEREOFILTER - SNDMIX_RAMPSTEREOVOL -END_RAMPMIX_STFLT_INTERFACE() - -BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo8BitLinearRampMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETSTEREOVOL8LINEAR - SNDMIX_PROCESSSTEREOFILTER - SNDMIX_RAMPSTEREOVOL -END_RAMPMIX_STFLT_INTERFACE() - -BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo16BitLinearRampMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETSTEREOVOL16LINEAR - SNDMIX_PROCESSSTEREOFILTER - SNDMIX_RAMPSTEREOVOL -END_RAMPMIX_STFLT_INTERFACE() - -BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo8BitSplineRampMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETSTEREOVOL8SPLINE - SNDMIX_PROCESSSTEREOFILTER - SNDMIX_RAMPSTEREOVOL -END_RAMPMIX_STFLT_INTERFACE() - -BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo16BitSplineRampMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETSTEREOVOL16SPLINE - SNDMIX_PROCESSSTEREOFILTER - SNDMIX_RAMPSTEREOVOL -END_RAMPMIX_STFLT_INTERFACE() - -BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo8BitFirFilterRampMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETSTEREOVOL8FIRFILTER - SNDMIX_PROCESSSTEREOFILTER - SNDMIX_RAMPSTEREOVOL -END_RAMPMIX_STFLT_INTERFACE() - -BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo16BitFirFilterRampMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETSTEREOVOL16FIRFILTER - SNDMIX_PROCESSSTEREOFILTER - SNDMIX_RAMPSTEREOVOL -END_RAMPMIX_STFLT_INTERFACE() - - -#else -// Mono -#define FilterMono8BitMix Mono8BitMix -#define FilterMono16BitMix Mono16BitMix -#define FilterMono8BitLinearMix Mono8BitLinearMix -#define FilterMono16BitLinearMix Mono16BitLinearMix -#define FilterMono8BitSplineMix Mono8BitSplineMix -#define FilterMono16BitSplineMix Mono16BitSplineMix -#define FilterMono8BitFirFilterMix Mono8BitFirFilterMix -#define FilterMono16BitFirFilterMix Mono16BitFirFilterMix -#define FilterMono8BitRampMix Mono8BitRampMix -#define FilterMono16BitRampMix Mono16BitRampMix -#define FilterMono8BitLinearRampMix Mono8BitLinearRampMix -#define FilterMono16BitLinearRampMix Mono16BitLinearRampMix -#define FilterMono8BitSplineRampMix Mono8BitSplineRampMix -#define FilterMono16BitSplineRampMix Mono16BitSplineRampMix -#define FilterMono8BitFirFilterRampMix Mono8BitFirFilterRampMix -#define FilterMono16BitFirFilterRampMix Mono16BitFirFilterRampMix -// Stereo -#define FilterStereo8BitMix Stereo8BitMix -#define FilterStereo16BitMix Stereo16BitMix -#define FilterStereo8BitLinearMix Stereo8BitLinearMix -#define FilterStereo16BitLinearMix Stereo16BitLinearMix -#define FilterStereo8BitSplineMix Stereo8BitSplineMix -#define FilterStereo16BitSplineMix Stereo16BitSplineMix -#define FilterStereo8BitFirFilterMix Stereo8BitFirFilterMix -#define FilterStereo16BitFirFilterMix Stereo16BitFirFilterMix -#define FilterStereo8BitRampMix Stereo8BitRampMix -#define FilterStereo16BitRampMix Stereo16BitRampMix -#define FilterStereo8BitLinearRampMix Stereo8BitLinearRampMix -#define FilterStereo16BitLinearRampMix Stereo16BitLinearRampMix -#define FilterStereo8BitSplineRampMix Stereo8BitSplineRampMix -#define FilterStereo16BitSplineRampMix Stereo16BitSplineRampMix -#define FilterStereo8BitFirFilterRampMix Stereo8BitFirFilterRampMix -#define FilterStereo16BitFirFilterRampMix Stereo16BitFirFilterRampMix - -#endif - -/////////////////////////////////////////////////////////////////////////////// -// -// Mix function tables -// -// -// Index is as follow: -// [b1-b0] format (8-bit-mono, 16-bit-mono, 8-bit-stereo, 16-bit-stereo) -// [b2] ramp -// [b3] filter -// [b5-b4] src type -// - -#define MIXNDX_16BIT 0x01 -#define MIXNDX_STEREO 0x02 -#define MIXNDX_RAMP 0x04 -#define MIXNDX_FILTER 0x08 -#define MIXNDX_LINEARSRC 0x10 -#define MIXNDX_SPLINESRC 0x20 -#define MIXNDX_FIRSRC 0x30 - -const LPMIXINTERFACE gpMixFunctionTable[2*2*16] = -{ - // No SRC - Mono8BitMix, Mono16BitMix, Stereo8BitMix, Stereo16BitMix, - Mono8BitRampMix, Mono16BitRampMix, Stereo8BitRampMix, - Stereo16BitRampMix, - // No SRC, Filter - FilterMono8BitMix, FilterMono16BitMix, FilterStereo8BitMix, - FilterStereo16BitMix, FilterMono8BitRampMix, FilterMono16BitRampMix, - FilterStereo8BitRampMix, FilterStereo16BitRampMix, - // Linear SRC - Mono8BitLinearMix, Mono16BitLinearMix, Stereo8BitLinearMix, - Stereo16BitLinearMix, Mono8BitLinearRampMix, Mono16BitLinearRampMix, - Stereo8BitLinearRampMix,Stereo16BitLinearRampMix, - // Linear SRC, Filter - FilterMono8BitLinearMix, FilterMono16BitLinearMix, - FilterStereo8BitLinearMix, FilterStereo16BitLinearMix, - FilterMono8BitLinearRampMix, FilterMono16BitLinearRampMix, - FilterStereo8BitLinearRampMix, FilterStereo16BitLinearRampMix, - - // FirFilter SRC - Mono8BitSplineMix, Mono16BitSplineMix, Stereo8BitSplineMix, - Stereo16BitSplineMix, Mono8BitSplineRampMix, Mono16BitSplineRampMix, - Stereo8BitSplineRampMix,Stereo16BitSplineRampMix, - // Spline SRC, Filter - FilterMono8BitSplineMix, FilterMono16BitSplineMix, - FilterStereo8BitSplineMix, FilterStereo16BitSplineMix, - FilterMono8BitSplineRampMix, FilterMono16BitSplineRampMix, - FilterStereo8BitSplineRampMix, FilterStereo16BitSplineRampMix, - - // FirFilter SRC - Mono8BitFirFilterMix, Mono16BitFirFilterMix, Stereo8BitFirFilterMix, - Stereo16BitFirFilterMix, Mono8BitFirFilterRampMix, - Mono16BitFirFilterRampMix, Stereo8BitFirFilterRampMix, - Stereo16BitFirFilterRampMix, - // FirFilter SRC, Filter - FilterMono8BitFirFilterMix, FilterMono16BitFirFilterMix, - FilterStereo8BitFirFilterMix, FilterStereo16BitFirFilterMix, - FilterMono8BitFirFilterRampMix, FilterMono16BitFirFilterRampMix, - FilterStereo8BitFirFilterRampMix, FilterStereo16BitFirFilterRampMix -}; - -const LPMIXINTERFACE gpFastMixFunctionTable[2*2*16] = -{ - // No SRC - FastMono8BitMix, FastMono16BitMix, Stereo8BitMix, Stereo16BitMix, - FastMono8BitRampMix, FastMono16BitRampMix, Stereo8BitRampMix, - Stereo16BitRampMix, - // No SRC, Filter - FilterMono8BitMix, FilterMono16BitMix, FilterStereo8BitMix, - FilterStereo16BitMix, FilterMono8BitRampMix, FilterMono16BitRampMix, - FilterStereo8BitRampMix, FilterStereo16BitRampMix, - // Linear SRC - FastMono8BitLinearMix, FastMono16BitLinearMix, Stereo8BitLinearMix, - Stereo16BitLinearMix, FastMono8BitLinearRampMix, - FastMono16BitLinearRampMix, Stereo8BitLinearRampMix, - Stereo16BitLinearRampMix, - // Linear SRC, Filter - FilterMono8BitLinearMix, FilterMono16BitLinearMix, - FilterStereo8BitLinearMix, FilterStereo16BitLinearMix, - FilterMono8BitLinearRampMix, FilterMono16BitLinearRampMix, - FilterStereo8BitLinearRampMix, FilterStereo16BitLinearRampMix, - - // Spline SRC - Mono8BitSplineMix, Mono16BitSplineMix, Stereo8BitSplineMix, - Stereo16BitSplineMix, Mono8BitSplineRampMix, Mono16BitSplineRampMix, - Stereo8BitSplineRampMix, Stereo16BitSplineRampMix, - // Spline SRC, Filter - FilterMono8BitSplineMix, FilterMono16BitSplineMix, - FilterStereo8BitSplineMix, FilterStereo16BitSplineMix, - FilterMono8BitSplineRampMix, FilterMono16BitSplineRampMix, - FilterStereo8BitSplineRampMix, FilterStereo16BitSplineRampMix, - - // FirFilter SRC - Mono8BitFirFilterMix, Mono16BitFirFilterMix, Stereo8BitFirFilterMix, - Stereo16BitFirFilterMix, Mono8BitFirFilterRampMix, - Mono16BitFirFilterRampMix, Stereo8BitFirFilterRampMix, - Stereo16BitFirFilterRampMix, - // FirFilter SRC, Filter - FilterMono8BitFirFilterMix, FilterMono16BitFirFilterMix, - FilterStereo8BitFirFilterMix, FilterStereo16BitFirFilterMix, - FilterMono8BitFirFilterRampMix, FilterMono16BitFirFilterRampMix, - FilterStereo8BitFirFilterRampMix, FilterStereo16BitFirFilterRampMix, -}; - - -///////////////////////////////////////////////////////////////////////// - -static LONG MPPFASTCALL GetSampleCount(MODCHANNEL *pChn, LONG nSamples) -//--------------------------------------------------------------------- -{ - LONG nLoopStart = (pChn->dwFlags & CHN_LOOP) ? pChn->nLoopStart : 0; - LONG nInc = pChn->nInc; - - if ((nSamples <= 0) || (!nInc) || (!pChn->nLength)) return 0; - // Under zero ? - if ((LONG)pChn->nPos < nLoopStart) - { - if (nInc < 0) - { - // Invert loop for bidi loops - LONG nDelta = ((nLoopStart - pChn->nPos) << 16) - (pChn->nPosLo & 0xffff); - pChn->nPos = nLoopStart | (nDelta>>16); - pChn->nPosLo = nDelta & 0xffff; - if (((LONG)pChn->nPos < nLoopStart) || - (pChn->nPos >= (nLoopStart+pChn->nLength)/2)) - { - pChn->nPos = nLoopStart; pChn->nPosLo = 0; - } - nInc = -nInc; - pChn->nInc = nInc; - pChn->dwFlags &= ~(CHN_PINGPONGFLAG); // go forward - if ((!(pChn->dwFlags & CHN_LOOP)) || (pChn->nPos >= pChn->nLength)) - { - pChn->nPos = pChn->nLength; - pChn->nPosLo = 0; - return 0; - } - } else - { - // We probably didn't hit the loop end yet - // (first loop), so we do nothing - if ((LONG)pChn->nPos < 0) pChn->nPos = 0; - } - } else - // Past the end - if (pChn->nPos >= pChn->nLength) - { - if (!(pChn->dwFlags & CHN_LOOP)) return 0; // not looping -> stop this channel - if (pChn->dwFlags & CHN_PINGPONGLOOP) - { - // Invert loop - if (nInc > 0) - { - nInc = -nInc; - pChn->nInc = nInc; - } - pChn->dwFlags |= CHN_PINGPONGFLAG; - // adjust loop position - LONG nDeltaHi = (pChn->nPos - pChn->nLength); - LONG nDeltaLo = 0x10000 - (pChn->nPosLo & 0xffff); - pChn->nPos = pChn->nLength - nDeltaHi - (nDeltaLo>>16); - pChn->nPosLo = nDeltaLo & 0xffff; - if ((pChn->nPos <= pChn->nLoopStart) || - (pChn->nPos >= pChn->nLength)) - pChn->nPos = pChn->nLength-1; - } else - { - if (nInc < 0) // This is a bug - { - nInc = -nInc; - pChn->nInc = nInc; - } - // Restart at loop start - pChn->nPos += nLoopStart - pChn->nLength; - if ((LONG)pChn->nPos < nLoopStart) - pChn->nPos = pChn->nLoopStart; - } - } - LONG nPos = pChn->nPos; - // too big increment, and/or too small loop length - if (nPos < nLoopStart) - { - if ((nPos < 0) || (nInc < 0)) return 0; - } - if ((nPos < 0) || (nPos >= (LONG)pChn->nLength)) return 0; - LONG nPosLo = (USHORT)pChn->nPosLo, nSmpCount = nSamples; - if (nInc < 0) - { - LONG nInv = -nInc; - LONG maxsamples = 16384 / ((nInv>>16)+1); - if (maxsamples < 2) maxsamples = 2; - if (nSamples > maxsamples) nSamples = maxsamples; - LONG nDeltaHi = (nInv>>16) * (nSamples - 1); - LONG nDeltaLo = (nInv&0xffff) * (nSamples - 1); - LONG nPosDest = nPos - nDeltaHi + ((nPosLo - nDeltaLo) >> 16); - if (nPosDest < nLoopStart) - { - nSmpCount = (ULONG)(((((LONGLONG)nPos - nLoopStart) << 16) + nPosLo - 1) / nInv) + 1; - } - } else - { - LONG maxsamples = 16384 / ((nInc>>16)+1); - if (maxsamples < 2) maxsamples = 2; - if (nSamples > maxsamples) nSamples = maxsamples; - LONG nDeltaHi = (nInc>>16) * (nSamples - 1); - LONG nDeltaLo = (nInc&0xffff) * (nSamples - 1); - LONG nPosDest = nPos + nDeltaHi + ((nPosLo + nDeltaLo)>>16); - if (nPosDest >= (LONG)pChn->nLength) - { - nSmpCount = (ULONG)(((((LONGLONG)pChn->nLength - nPos) << 16) - nPosLo - 1) / nInc) + 1; - } - } - if (nSmpCount <= 1) return 1; - if (nSmpCount > nSamples) return nSamples; - return nSmpCount; -} - - -UINT CSoundFile::CreateStereoMix(int count) -//----------------------------------------- -{ - LPLONG pOfsL, pOfsR; - DWORD nchused, nchmixed; - - if (!count) return 0; -#ifndef MODPLUG_FASTSOUNDLIB - if (gnChannels > 2) X86_InitMixBuffer(MixRearBuffer, count*2); -#endif - nchused = nchmixed = 0; - for (UINT nChn=0; nChn<m_nMixChannels; nChn++) - { - const LPMIXINTERFACE *pMixFuncTable; - MODCHANNEL * const pChannel = &Chn[ChnMix[nChn]]; - UINT nFlags, nMasterCh; - LONG nSmpCount; - int nsamples; - int *pbuffer; - - if (!pChannel->pCurrentSample) continue; - nMasterCh = (ChnMix[nChn] < m_nChannels) ? ChnMix[nChn]+1 : pChannel->nMasterChn; - pOfsR = &gnDryROfsVol; - pOfsL = &gnDryLOfsVol; - nFlags = 0; - if (pChannel->dwFlags & CHN_16BIT) nFlags |= MIXNDX_16BIT; - if (pChannel->dwFlags & CHN_STEREO) nFlags |= MIXNDX_STEREO; - #ifndef NO_FILTER - if (pChannel->dwFlags & CHN_FILTER) nFlags |= MIXNDX_FILTER; - #endif - if (!(pChannel->dwFlags & CHN_NOIDO)) - { - // use hq-fir mixer? - if( (gdwSoundSetup & (SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE)) == - (SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE) ) - nFlags += MIXNDX_FIRSRC; - else if( (gdwSoundSetup & (SNDMIX_HQRESAMPLER)) == SNDMIX_HQRESAMPLER ) - nFlags += MIXNDX_SPLINESRC; - else - nFlags += MIXNDX_LINEARSRC; // use - } - if ((nFlags < 0x40) && (pChannel->nLeftVol == pChannel->nRightVol) - && ((!pChannel->nRampLength) || (pChannel->nLeftRamp == pChannel->nRightRamp))) - { - pMixFuncTable = gpFastMixFunctionTable; - } else - { - pMixFuncTable = gpMixFunctionTable; - } - nsamples = count; -#ifndef MODPLUG_NO_REVERB - pbuffer = (gdwSoundSetup & SNDMIX_REVERB) ? MixReverbBuffer : MixSoundBuffer; - if (pChannel->dwFlags & CHN_NOREVERB) pbuffer = MixSoundBuffer; - if (pChannel->dwFlags & CHN_REVERB) pbuffer = MixReverbBuffer; - if (pbuffer == MixReverbBuffer) - { - if (!gnReverbSend) memset(MixReverbBuffer, 0, count * 8); - gnReverbSend += count; - } -#else - pbuffer = MixSoundBuffer; -#endif - nchused++; - //////////////////////////////////////////////////// - SampleLooping: - UINT nrampsamples = nsamples; - if (pChannel->nRampLength > 0) - { - if ((LONG)nrampsamples > pChannel->nRampLength) nrampsamples = pChannel->nRampLength; - } - if ((nSmpCount = GetSampleCount(pChannel, nrampsamples)) <= 0) - { - // Stopping the channel - pChannel->pCurrentSample = NULL; - pChannel->nLength = 0; - pChannel->nPos = 0; - pChannel->nPosLo = 0; - pChannel->nRampLength = 0; - X86_EndChannelOfs(pChannel, pbuffer, nsamples); - *pOfsR += pChannel->nROfs; - *pOfsL += pChannel->nLOfs; - pChannel->nROfs = pChannel->nLOfs = 0; - pChannel->dwFlags &= ~CHN_PINGPONGFLAG; - continue; - } - // Should we mix this channel ? - UINT naddmix; - if (((nchmixed >= m_nMaxMixChannels) && (!(gdwSoundSetup & SNDMIX_DIRECTTODISK))) - || ((!pChannel->nRampLength) && (!(pChannel->nLeftVol|pChannel->nRightVol)))) - { - LONG delta = (pChannel->nInc * (LONG)nSmpCount) + (LONG)pChannel->nPosLo; - pChannel->nPosLo = delta & 0xFFFF; - pChannel->nPos += (delta >> 16); - pChannel->nROfs = pChannel->nLOfs = 0; - pbuffer += nSmpCount*2; - naddmix = 0; - } else - // Do mixing - { - // Choose function for mixing - LPMIXINTERFACE pMixFunc; - pMixFunc = (pChannel->nRampLength) ? pMixFuncTable[nFlags|MIXNDX_RAMP] : pMixFuncTable[nFlags]; - int *pbufmax = pbuffer + (nSmpCount*2); - pChannel->nROfs = - *(pbufmax-2); - pChannel->nLOfs = - *(pbufmax-1); - pMixFunc(pChannel, pbuffer, pbufmax); - pChannel->nROfs += *(pbufmax-2); - pChannel->nLOfs += *(pbufmax-1); - pbuffer = pbufmax; - naddmix = 1; - - } - nsamples -= nSmpCount; - if (pChannel->nRampLength) - { - pChannel->nRampLength -= nSmpCount; - if (pChannel->nRampLength <= 0) - { - pChannel->nRampLength = 0; - pChannel->nRightVol = pChannel->nNewRightVol; - pChannel->nLeftVol = pChannel->nNewLeftVol; - pChannel->nRightRamp = pChannel->nLeftRamp = 0; - if ((pChannel->dwFlags & CHN_NOTEFADE) && (!(pChannel->nFadeOutVol))) - { - pChannel->nLength = 0; - pChannel->pCurrentSample = NULL; - } - } - } - if (nsamples > 0) goto SampleLooping; - nchmixed += naddmix; - } - return nchused; -} - - -#ifdef MSC_VER -#pragma warning (disable:4100) -#endif - -// Clip and convert to 8 bit -#ifdef MSC_VER -__declspec(naked) DWORD MPPASMCALL X86_Convert32To8(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax) -//------------------------------------------------------------------------------ -{ - _asm { - push ebx - push esi - push edi - mov ebx, 16[esp] // ebx = 8-bit buffer - mov esi, 20[esp] // esi = pBuffer - mov edi, 24[esp] // edi = lSampleCount - mov eax, 28[esp] - mov ecx, dword ptr [eax] // ecx = clipmin - mov eax, 32[esp] - mov edx, dword ptr [eax] // edx = clipmax -cliploop: - mov eax, dword ptr [esi] - inc ebx - cdq - and edx, (1 << (24-MIXING_ATTENUATION)) - 1 - add eax, edx - cmp eax, MIXING_CLIPMIN - jl cliplow - cmp eax, MIXING_CLIPMAX - jg cliphigh - cmp eax, ecx - jl updatemin - cmp eax, edx - jg updatemax -cliprecover: - add esi, 4 - sar eax, 24-MIXING_ATTENUATION - xor eax, 0x80 - dec edi - mov byte ptr [ebx-1], al - jnz cliploop - mov eax, 28[esp] - mov dword ptr [eax], ecx - mov eax, 32[esp] - mov dword ptr [eax], edx - mov eax, 24[esp] - pop edi - pop esi - pop ebx - ret -updatemin: - mov ecx, eax - jmp cliprecover -updatemax: - mov edx, eax - jmp cliprecover -cliplow: - mov ecx, MIXING_CLIPMIN - mov edx, MIXING_CLIPMAX - mov eax, MIXING_CLIPMIN - jmp cliprecover -cliphigh: - mov ecx, MIXING_CLIPMIN - mov edx, MIXING_CLIPMAX - mov eax, MIXING_CLIPMAX - jmp cliprecover - } -} -#else //MSC_VER -//---GCCFIX: Asm replaced with C function -// The C version was written by Rani Assaf <rani@magic.metawire.com>, I believe -DWORD MPPASMCALL X86_Convert32To8(LPVOID lp8, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax) -{ - int vumin = *lpMin, vumax = *lpMax; - unsigned char *p = (unsigned char *)lp8; - for (UINT i=0; i<lSampleCount; i++) - { - int n = pBuffer[i]; - if (n < MIXING_CLIPMIN) - n = MIXING_CLIPMIN; - else if (n > MIXING_CLIPMAX) - n = MIXING_CLIPMAX; - if (n < vumin) - vumin = n; - else if (n > vumax) - vumax = n; - p[i] = (n >> (24-MIXING_ATTENUATION)) ^ 0x80; // 8-bit unsigned - } - *lpMin = vumin; - *lpMax = vumax; - return lSampleCount; -} -#endif //MSC_VER, else - - -#ifdef MSC_VER -// Clip and convert to 16 bit -__declspec(naked) DWORD MPPASMCALL X86_Convert32To16(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax) -//------------------------------------------------------------------------------ -{ - _asm { - push ebx - push esi - push edi - mov ebx, 16[esp] // ebx = 16-bit buffer - mov eax, 28[esp] - mov esi, 20[esp] // esi = pBuffer - mov ecx, dword ptr [eax] // ecx = clipmin - mov edi, 24[esp] // edi = lSampleCount - mov eax, 32[esp] - push ebp - mov ebp, dword ptr [eax] // edx = clipmax -cliploop: - mov eax, dword ptr [esi] - add ebx, 2 - cdq - and edx, (1 << (16-MIXING_ATTENUATION)) - 1 - add esi, 4 - add eax, edx - cmp eax, MIXING_CLIPMIN - jl cliplow - cmp eax, MIXING_CLIPMAX - jg cliphigh - cmp eax, ecx - jl updatemin - cmp eax, ebp - jg updatemax -cliprecover: - sar eax, 16-MIXING_ATTENUATION - dec edi - mov word ptr [ebx-2], ax - jnz cliploop - mov edx, ebp - pop ebp - mov eax, 28[esp] - mov dword ptr [eax], ecx - mov eax, 32[esp] - mov dword ptr [eax], edx - mov eax, 24[esp] - pop edi - shl eax, 1 - pop esi - pop ebx - ret -updatemin: - mov ecx, eax - jmp cliprecover -updatemax: - mov ebp, eax - jmp cliprecover -cliplow: - mov ecx, MIXING_CLIPMIN - mov ebp, MIXING_CLIPMAX - mov eax, MIXING_CLIPMIN - jmp cliprecover -cliphigh: - mov ecx, MIXING_CLIPMIN - mov ebp, MIXING_CLIPMAX - mov eax, MIXING_CLIPMAX - jmp cliprecover - } -} -#else //MSC_VER -//---GCCFIX: Asm replaced with C function -// The C version was written by Rani Assaf <rani@magic.metawire.com>, I believe -DWORD MPPASMCALL X86_Convert32To16(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax) -{ - int vumin = *lpMin, vumax = *lpMax; - signed short *p = (signed short *)lp16; - for (UINT i=0; i<lSampleCount; i++) - { - int n = pBuffer[i]; - if (n < MIXING_CLIPMIN) - n = MIXING_CLIPMIN; - else if (n > MIXING_CLIPMAX) - n = MIXING_CLIPMAX; - if (n < vumin) - vumin = n; - else if (n > vumax) - vumax = n; - p[i] = n >> (16-MIXING_ATTENUATION); // 16-bit signed - } - *lpMin = vumin; - *lpMax = vumax; - return lSampleCount * 2; -} -#endif //MSC_VER, else - -#ifdef MSC_VER -// Clip and convert to 24 bit -__declspec(naked) DWORD MPPASMCALL X86_Convert32To24(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax) -//------------------------------------------------------------------------------ -{ - _asm { - push ebx - push esi - push edi - mov ebx, 16[esp] // ebx = 8-bit buffer - mov esi, 20[esp] // esi = pBuffer - mov edi, 24[esp] // edi = lSampleCount - mov eax, 28[esp] - mov ecx, dword ptr [eax] // ecx = clipmin - mov eax, 32[esp] - push ebp - mov edx, dword ptr [eax] // edx = clipmax -cliploop: - mov eax, dword ptr [esi] - mov ebp, eax - sar ebp, 31 - and ebp, (1 << (8-MIXING_ATTENUATION)) - 1 - add eax, ebp - cmp eax, MIXING_CLIPMIN - jl cliplow - cmp eax, MIXING_CLIPMAX - jg cliphigh - cmp eax, ecx - jl updatemin - cmp eax, edx - jg updatemax -cliprecover: - add ebx, 3 - sar eax, 8-MIXING_ATTENUATION - add esi, 4 - mov word ptr [ebx-3], ax - shr eax, 16 - dec edi - mov byte ptr [ebx-1], al - jnz cliploop - pop ebp - mov eax, 28[esp] - mov dword ptr [eax], ecx - mov eax, 32[esp] - mov dword ptr [eax], edx - mov edx, 24[esp] - mov eax, edx - pop edi - shl eax, 1 - pop esi - add eax, edx - pop ebx - ret -updatemin: - mov ecx, eax - jmp cliprecover -updatemax: - mov edx, eax - jmp cliprecover -cliplow: - mov ecx, MIXING_CLIPMIN - mov edx, MIXING_CLIPMAX - mov eax, MIXING_CLIPMIN - jmp cliprecover -cliphigh: - mov ecx, MIXING_CLIPMIN - mov edx, MIXING_CLIPMAX - mov eax, MIXING_CLIPMAX - jmp cliprecover - } -} -#else //MSC_VER -//---GCCFIX: Asm replaced with C function -DWORD MPPASMCALL X86_Convert32To24(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax) -{ - UINT i ; - int vumin = *lpMin, vumax = *lpMax; - int n,p ; - unsigned char* buf = (unsigned char*)lp16 ; - - for ( i=0; i<lSampleCount; i++) - { - n = pBuffer[i]; - if (n < MIXING_CLIPMIN) - n = MIXING_CLIPMIN; - else if (n > MIXING_CLIPMAX) - n = MIXING_CLIPMAX; - if (n < vumin) - vumin = n; - else if (n > vumax) - vumax = n; - p = n >> (8-MIXING_ATTENUATION) ; // 24-bit signed -#ifdef WORDS_BIGENDIAN - buf[i*3+0] = p & 0xFF0000 >> 24; - buf[i*3+1] = p & 0x00FF00 >> 16 ; - buf[i*3+2] = p & 0x0000FF ; -#else - buf[i*3+0] = p & 0x0000FF ; - buf[i*3+1] = p & 0x00FF00 >> 16; - buf[i*3+2] = p & 0xFF0000 >> 24; -#endif - } - *lpMin = vumin; - *lpMax = vumax; - return lSampleCount * 3; -} -#endif - -#ifdef MSC_VER -// Clip and convert to 32 bit -__declspec(naked) DWORD MPPASMCALL X86_Convert32To32(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax) -//------------------------------------------------------------------------------ -{ - _asm { - push ebx - push esi - push edi - mov ebx, 16[esp] // ebx = 32-bit buffer - mov esi, 20[esp] // esi = pBuffer - mov edi, 24[esp] // edi = lSampleCount - mov eax, 28[esp] - mov ecx, dword ptr [eax] // ecx = clipmin - mov eax, 32[esp] - mov edx, dword ptr [eax] // edx = clipmax -cliploop: - mov eax, dword ptr [esi] - add ebx, 4 - add esi, 4 - cmp eax, MIXING_CLIPMIN - jl cliplow - cmp eax, MIXING_CLIPMAX - jg cliphigh - cmp eax, ecx - jl updatemin - cmp eax, edx - jg updatemax -cliprecover: - shl eax, MIXING_ATTENUATION - dec edi - mov dword ptr [ebx-4], eax - jnz cliploop - mov eax, 28[esp] - mov dword ptr [eax], ecx - mov eax, 32[esp] - mov dword ptr [eax], edx - mov edx, 24[esp] - pop edi - mov eax, edx - pop esi - shl eax, 2 - pop ebx - ret -updatemin: - mov ecx, eax - jmp cliprecover -updatemax: - mov edx, eax - jmp cliprecover -cliplow: - mov ecx, MIXING_CLIPMIN - mov edx, MIXING_CLIPMAX - mov eax, MIXING_CLIPMIN - jmp cliprecover -cliphigh: - mov ecx, MIXING_CLIPMIN - mov edx, MIXING_CLIPMAX - mov eax, MIXING_CLIPMAX - jmp cliprecover - } -} -#else -//---GCCFIX: Asm replaced with C function -DWORD MPPASMCALL X86_Convert32To32(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax) -{ - UINT i ; - int vumin = *lpMin, vumax = *lpMax; - signed long *p = (signed long *)lp16; - - for ( i=0; i<lSampleCount; i++) - { - int n = pBuffer[i]; - if (n < MIXING_CLIPMIN) - n = MIXING_CLIPMIN; - else if (n > MIXING_CLIPMAX) - n = MIXING_CLIPMAX; - if (n < vumin) - vumin = n; - else if (n > vumax) - vumax = n; - p[i] = n << MIXING_ATTENUATION; // 32-bit signed - } - *lpMin = vumin; - *lpMax = vumax; - return lSampleCount * 4; -} -#endif - - -#ifdef MSC_VER -void MPPASMCALL X86_InitMixBuffer(int *pBuffer, UINT nSamples) -//------------------------------------------------------------ -{ - _asm { - mov ecx, nSamples - mov esi, pBuffer - xor eax, eax - mov edx, ecx - shr ecx, 2 - and edx, 3 - jz unroll4x -loop1x: - add esi, 4 - dec edx - mov dword ptr [esi-4], eax - jnz loop1x -unroll4x: - or ecx, ecx - jnz loop4x - jmp done -loop4x: - add esi, 16 - dec ecx - mov dword ptr [esi-16], eax - mov dword ptr [esi-12], eax - mov dword ptr [esi-8], eax - mov dword ptr [esi-4], eax - jnz loop4x -done:; - } -} -#else -//---GCCFIX: Asm replaced with C function -// Will fill in later. -void MPPASMCALL X86_InitMixBuffer(int *pBuffer, UINT nSamples) -{ - memset(pBuffer, 0, nSamples * sizeof(int)); -} -#endif - - -#ifdef MSC_VER -__declspec(naked) void MPPASMCALL X86_InterleaveFrontRear(int *pFrontBuf, int *pRearBuf, DWORD nSamples) -//------------------------------------------------------------------------------ -{ - _asm { - push ebx - push ebp - push esi - push edi - mov ecx, 28[esp] // ecx = samplecount - mov esi, 20[esp] // esi = front buffer - mov edi, 24[esp] // edi = rear buffer - lea esi, [esi+ecx*4] // esi = &front[N] - lea edi, [edi+ecx*4] // edi = &rear[N] - lea ebx, [esi+ecx*4] // ebx = &front[N*2] -interleaveloop: - mov eax, dword ptr [esi-8] - mov edx, dword ptr [esi-4] - sub ebx, 16 - mov ebp, dword ptr [edi-8] - mov dword ptr [ebx], eax - mov dword ptr [ebx+4], edx - mov eax, dword ptr [edi-4] - sub esi, 8 - sub edi, 8 - dec ecx - mov dword ptr [ebx+8], ebp - mov dword ptr [ebx+12], eax - jnz interleaveloop - pop edi - pop esi - pop ebp - pop ebx - ret - } -} -#else -//---GCCFIX: Asm replaced with C function -// Multichannel not supported. -void MPPASMCALL X86_InterleaveFrontRear(int *pFrontBuf, int *pRearBuf, DWORD nSamples) -{ -} -#endif - - -#ifdef MSC_VER -VOID MPPASMCALL X86_MonoFromStereo(int *pMixBuf, UINT nSamples) -//------------------------------------------------------------- -{ - _asm { - mov ecx, nSamples - mov esi, pMixBuf - mov edi, esi -stloop: - mov eax, dword ptr [esi] - mov edx, dword ptr [esi+4] - add edi, 4 - add esi, 8 - add eax, edx - sar eax, 1 - dec ecx - mov dword ptr [edi-4], eax - jnz stloop - } -} -#else -//---GCCFIX: Asm replaced with C function -VOID MPPASMCALL X86_MonoFromStereo(int *pMixBuf, UINT nSamples) -{ - UINT j; - for(UINT i = 0; i < nSamples; i++) - { - j = i << 1; - pMixBuf[i] = (pMixBuf[j] + pMixBuf[j + 1]) >> 1; - } -} -#endif - -#define OFSDECAYSHIFT 8 -#define OFSDECAYMASK 0xFF - - -#ifdef MSC_VER -void MPPASMCALL X86_StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs) -//------------------------------------------------------------------------------ -{ - _asm { - mov edi, pBuffer - mov ecx, nSamples - mov eax, lpROfs - mov edx, lpLOfs - mov eax, [eax] - mov edx, [edx] - or ecx, ecx - jz fill_loop - mov ebx, eax - or ebx, edx - jz fill_loop -ofsloop: - mov ebx, eax - mov esi, edx - neg ebx - neg esi - sar ebx, 31 - sar esi, 31 - and ebx, OFSDECAYMASK - and esi, OFSDECAYMASK - add ebx, eax - add esi, edx - sar ebx, OFSDECAYSHIFT - sar esi, OFSDECAYSHIFT - sub eax, ebx - sub edx, esi - mov ebx, eax - or ebx, edx - jz fill_loop - add edi, 8 - dec ecx - mov [edi-8], eax - mov [edi-4], edx - jnz ofsloop -fill_loop: - mov ebx, ecx - and ebx, 3 - jz fill4x -fill1x: - mov [edi], eax - mov [edi+4], edx - add edi, 8 - dec ebx - jnz fill1x -fill4x: - shr ecx, 2 - or ecx, ecx - jz done -fill4xloop: - mov [edi], eax - mov [edi+4], edx - mov [edi+8], eax - mov [edi+12], edx - add edi, 8*4 - dec ecx - mov [edi-16], eax - mov [edi-12], edx - mov [edi-8], eax - mov [edi-4], edx - jnz fill4xloop -done: - mov esi, lpROfs - mov edi, lpLOfs - mov [esi], eax - mov [edi], edx - } -} -#else -//---GCCFIX: Asm replaced with C function -#define OFSDECAYSHIFT 8 -#define OFSDECAYMASK 0xFF -void MPPASMCALL X86_StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs) -//---------------------------------------------------------------------------- -{ - int rofs = *lpROfs; - int lofs = *lpLOfs; - - if ((!rofs) && (!lofs)) - { - X86_InitMixBuffer(pBuffer, nSamples*2); - return; - } - for (UINT i=0; i<nSamples; i++) - { - int x_r = (rofs + (((-rofs)>>31) & OFSDECAYMASK)) >> OFSDECAYSHIFT; - int x_l = (lofs + (((-lofs)>>31) & OFSDECAYMASK)) >> OFSDECAYSHIFT; - rofs -= x_r; - lofs -= x_l; - pBuffer[i*2] = x_r; - pBuffer[i*2+1] = x_l; - } - *lpROfs = rofs; - *lpLOfs = lofs; -} -#endif - -#ifdef MSC_VER -void MPPASMCALL X86_EndChannelOfs(MODCHANNEL *pChannel, int *pBuffer, UINT nSamples) -//------------------------------------------------------------------------------ -{ - _asm { - mov esi, pChannel - mov edi, pBuffer - mov ecx, nSamples - mov eax, dword ptr [esi+MODCHANNEL.nROfs] - mov edx, dword ptr [esi+MODCHANNEL.nLOfs] - or ecx, ecx - jz brkloop -ofsloop: - mov ebx, eax - mov esi, edx - neg ebx - neg esi - sar ebx, 31 - sar esi, 31 - and ebx, OFSDECAYMASK - and esi, OFSDECAYMASK - add ebx, eax - add esi, edx - sar ebx, OFSDECAYSHIFT - sar esi, OFSDECAYSHIFT - sub eax, ebx - sub edx, esi - mov ebx, eax - add dword ptr [edi], eax - add dword ptr [edi+4], edx - or ebx, edx - jz brkloop - add edi, 8 - dec ecx - jnz ofsloop -brkloop: - mov esi, pChannel - mov dword ptr [esi+MODCHANNEL.nROfs], eax - mov dword ptr [esi+MODCHANNEL.nLOfs], edx - } -} -#else -//---GCCFIX: Asm replaced with C function -// Will fill in later. -void MPPASMCALL X86_EndChannelOfs(MODCHANNEL *pChannel, int *pBuffer, UINT nSamples) -{ - int rofs = pChannel->nROfs; - int lofs = pChannel->nLOfs; - - if ((!rofs) && (!lofs)) return; - for (UINT i=0; i<nSamples; i++) - { - int x_r = (rofs + (((-rofs)>>31) & OFSDECAYMASK)) >> OFSDECAYSHIFT; - int x_l = (lofs + (((-lofs)>>31) & OFSDECAYMASK)) >> OFSDECAYSHIFT; - rofs -= x_r; - lofs -= x_l; - pBuffer[i*2] += x_r; - pBuffer[i*2+1] += x_l; - } - pChannel->nROfs = rofs; - pChannel->nLOfs = lofs; -} -#endif - - -////////////////////////////////////////////////////////////////////////////////// -// Automatic Gain Control - -#ifndef NO_AGC - -// Limiter -#define MIXING_LIMITMAX (0x08100000) -#define MIXING_LIMITMIN (-MIXING_LIMITMAX) - -#ifdef MSC_VER -__declspec(naked) UINT MPPASMCALL X86_AGC(int *pBuffer, UINT nSamples, UINT nAGC) -//------------------------------------------------------------------------------ -{ - __asm { - push ebx - push ebp - push esi - push edi - mov esi, 20[esp] // esi = pBuffer+i - mov ecx, 24[esp] // ecx = i - mov edi, 28[esp] // edi = AGC (0..256) -agcloop: - mov eax, dword ptr [esi] - imul edi - shrd eax, edx, AGC_PRECISION - add esi, 4 - cmp eax, MIXING_LIMITMIN - jl agcupdate - cmp eax, MIXING_LIMITMAX - jg agcupdate -agcrecover: - dec ecx - mov dword ptr [esi-4], eax - jnz agcloop - mov eax, edi - pop edi - pop esi - pop ebp - pop ebx - ret -agcupdate: - dec edi - jmp agcrecover - } -} - -#pragma warning (default:4100) -#else -// Version for GCC -UINT MPPASMCALL X86_AGC(int *pBuffer, UINT nSamples, UINT nAGC) -{ - int x; - - while(nSamples) - { - x = ((long long int)(*pBuffer) * nAGC) >> AGC_PRECISION; - - if((x < MIXING_LIMITMIN) || (x > MIXING_LIMITMAX)) - nAGC--; - - *pBuffer = x; - - pBuffer++; - nSamples--; - } - - return nAGC; -} -#endif - -void CSoundFile::ProcessAGC(int count) -//------------------------------------ -{ - static DWORD gAGCRecoverCount = 0; - UINT agc = X86_AGC(MixSoundBuffer, count, gnAGC); - // Some kind custom law, so that the AGC stays quite stable, but slowly - // goes back up if the sound level stays below a level inversely - // proportional to the AGC level. (J'me comprends) - if ((agc >= gnAGC) && (gnAGC < AGC_UNITY) && (gnVUMeter < (0xFF - (gnAGC >> (AGC_PRECISION-7))) )) - { - gAGCRecoverCount += count; - UINT agctimeout = gdwMixingFreq + gnAGC; - if (gnChannels >= 2) agctimeout <<= 1; - if (gAGCRecoverCount >= agctimeout) - { - gAGCRecoverCount = 0; - gnAGC++; - } - } else - { - gnAGC = agc; - gAGCRecoverCount = 0; - } -} - - - -void CSoundFile::ResetAGC() -//------------------------- -{ - gnAGC = AGC_UNITY; -} - -#endif // NO_AGC diff --git a/lib/libmodplug/src/libmodplug/it_defs.h b/lib/libmodplug/src/libmodplug/it_defs.h deleted file mode 100644 index 89cb456515..0000000000 --- a/lib/libmodplug/src/libmodplug/it_defs.h +++ /dev/null @@ -1,134 +0,0 @@ -#ifndef _ITDEFS_H_ -#define _ITDEFS_H_ - -#pragma pack(1) - -typedef struct tagITFILEHEADER -{ - DWORD id; // 0x4D504D49 - CHAR songname[26]; - WORD reserved1; // 0x1004 - WORD ordnum; - WORD insnum; - WORD smpnum; - WORD patnum; - WORD cwtv; - WORD cmwt; - WORD flags; - WORD special; - BYTE globalvol; - BYTE mv; - BYTE speed; - BYTE tempo; - BYTE sep; - BYTE zero; - WORD msglength; - DWORD msgoffset; - DWORD reserved2; - BYTE chnpan[64]; - BYTE chnvol[64]; -} ITFILEHEADER; - - -typedef struct tagITENVELOPE -{ - BYTE flags; - BYTE num; - BYTE lpb; - BYTE lpe; - BYTE slb; - BYTE sle; - BYTE data[25*3]; - BYTE reserved; -} ITENVELOPE; - -// Old Impulse Instrument Format (cmwt < 0x200) -typedef struct tagITOLDINSTRUMENT -{ - DWORD id; // IMPI = 0x49504D49 - CHAR filename[12]; // DOS file name - BYTE zero; - BYTE flags; - BYTE vls; - BYTE vle; - BYTE sls; - BYTE sle; - WORD reserved1; - WORD fadeout; - BYTE nna; - BYTE dnc; - WORD trkvers; - BYTE nos; - BYTE reserved2; - CHAR name[26]; - WORD reserved3[3]; - BYTE keyboard[240]; - BYTE volenv[200]; - BYTE nodes[50]; -} ITOLDINSTRUMENT; - - -// Impulse Instrument Format -typedef struct tagITINSTRUMENT -{ - DWORD id; - CHAR filename[12]; - BYTE zero; - BYTE nna; - BYTE dct; - BYTE dca; - WORD fadeout; - signed char pps; - BYTE ppc; - BYTE gbv; - BYTE dfp; - BYTE rv; - BYTE rp; - WORD trkvers; - BYTE nos; - BYTE reserved1; - CHAR name[26]; - BYTE ifc; - BYTE ifr; - BYTE mch; - BYTE mpr; - WORD mbank; - BYTE keyboard[240]; - ITENVELOPE volenv; - ITENVELOPE panenv; - ITENVELOPE pitchenv; - BYTE dummy[4]; // was 7, but IT v2.17 saves 554 bytes -} ITINSTRUMENT; - - -// IT Sample Format -typedef struct ITSAMPLESTRUCT -{ - DWORD id; // 0x53504D49 - CHAR filename[12]; - BYTE zero; - BYTE gvl; - BYTE flags; - BYTE vol; - CHAR name[26]; - BYTE cvt; - BYTE dfp; - DWORD length; - DWORD loopbegin; - DWORD loopend; - DWORD C5Speed; - DWORD susloopbegin; - DWORD susloopend; - DWORD samplepointer; - BYTE vis; - BYTE vid; - BYTE vir; - BYTE vit; -} ITSAMPLESTRUCT; - -#pragma pack() - -extern BYTE autovibit2xm[8]; -extern BYTE autovibxm2it[8]; - -#endif diff --git a/lib/libmodplug/src/libmodplug/sndfile.h b/lib/libmodplug/src/libmodplug/sndfile.h deleted file mode 100644 index a6663205b9..0000000000 --- a/lib/libmodplug/src/libmodplug/sndfile.h +++ /dev/null @@ -1,1016 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque <olivierl@jps.net>, - * Adam Goode <adam@evdebs.org> (endian and char fixes for PPC) -*/ - -#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) -#include "config.h" -#define CONFIG_H_INCLUDED 1 -#endif - -#ifndef __SNDFILE_H -#define __SNDFILE_H - -#ifdef UNDER_CE -int _strnicmp(const char *str1,const char *str2, int n); -#endif - -#ifndef LPCBYTE -typedef const BYTE * LPCBYTE; -#endif - -#define MOD_AMIGAC2 0x1AB -#define MAX_SAMPLE_LENGTH 16000000 -#define MAX_SAMPLE_RATE 192000 -#define MAX_ORDERS 256 -#define MAX_PATTERNS 240 -#define MAX_SAMPLES 240 -#define MAX_INSTRUMENTS MAX_SAMPLES -#ifdef MODPLUG_FASTSOUNDLIB -#define MAX_CHANNELS 80 -#else -#define MAX_CHANNELS 128 -#endif -#define MAX_BASECHANNELS 64 -#define MAX_ENVPOINTS 32 -#define MIN_PERIOD 0x0020 -#define MAX_PERIOD 0xFFFF -#define MAX_PATTERNNAME 32 -#define MAX_CHANNELNAME 20 -#define MAX_INFONAME 80 -#define MAX_EQ_BANDS 6 -#define MAX_MIXPLUGINS 8 - - -#define MOD_TYPE_NONE 0x00 -#define MOD_TYPE_MOD 0x01 -#define MOD_TYPE_S3M 0x02 -#define MOD_TYPE_XM 0x04 -#define MOD_TYPE_MED 0x08 -#define MOD_TYPE_MTM 0x10 -#define MOD_TYPE_IT 0x20 -#define MOD_TYPE_669 0x40 -#define MOD_TYPE_ULT 0x80 -#define MOD_TYPE_STM 0x100 -#define MOD_TYPE_FAR 0x200 -#define MOD_TYPE_WAV 0x400 -#define MOD_TYPE_AMF 0x800 -#define MOD_TYPE_AMS 0x1000 -#define MOD_TYPE_DSM 0x2000 -#define MOD_TYPE_MDL 0x4000 -#define MOD_TYPE_OKT 0x8000 -#define MOD_TYPE_MID 0x10000 -#define MOD_TYPE_DMF 0x20000 -#define MOD_TYPE_PTM 0x40000 -#define MOD_TYPE_DBM 0x80000 -#define MOD_TYPE_MT2 0x100000 -#define MOD_TYPE_AMF0 0x200000 -#define MOD_TYPE_PSM 0x400000 -#define MOD_TYPE_J2B 0x800000 -#define MOD_TYPE_ABC 0x1000000 -#define MOD_TYPE_PAT 0x2000000 -#define MOD_TYPE_UMX 0x80000000 // Fake type -#define MAX_MODTYPE 24 - - - -// Channel flags: -// Bits 0-7: Sample Flags -#define CHN_16BIT 0x01 -#define CHN_LOOP 0x02 -#define CHN_PINGPONGLOOP 0x04 -#define CHN_SUSTAINLOOP 0x08 -#define CHN_PINGPONGSUSTAIN 0x10 -#define CHN_PANNING 0x20 -#define CHN_STEREO 0x40 -#define CHN_PINGPONGFLAG 0x80 -// Bits 8-31: Channel Flags -#define CHN_MUTE 0x100 -#define CHN_KEYOFF 0x200 -#define CHN_NOTEFADE 0x400 -#define CHN_SURROUND 0x800 -#define CHN_NOIDO 0x1000 -#define CHN_HQSRC 0x2000 -#define CHN_FILTER 0x4000 -#define CHN_VOLUMERAMP 0x8000 -#define CHN_VIBRATO 0x10000 -#define CHN_TREMOLO 0x20000 -#define CHN_PANBRELLO 0x40000 -#define CHN_PORTAMENTO 0x80000 -#define CHN_GLISSANDO 0x100000 -#define CHN_VOLENV 0x200000 -#define CHN_PANENV 0x400000 -#define CHN_PITCHENV 0x800000 -#define CHN_FASTVOLRAMP 0x1000000 -#define CHN_EXTRALOUD 0x2000000 -#define CHN_REVERB 0x4000000 -#define CHN_NOREVERB 0x8000000 - - -#define ENV_VOLUME 0x0001 -#define ENV_VOLSUSTAIN 0x0002 -#define ENV_VOLLOOP 0x0004 -#define ENV_PANNING 0x0008 -#define ENV_PANSUSTAIN 0x0010 -#define ENV_PANLOOP 0x0020 -#define ENV_PITCH 0x0040 -#define ENV_PITCHSUSTAIN 0x0080 -#define ENV_PITCHLOOP 0x0100 -#define ENV_SETPANNING 0x0200 -#define ENV_FILTER 0x0400 -#define ENV_VOLCARRY 0x0800 -#define ENV_PANCARRY 0x1000 -#define ENV_PITCHCARRY 0x2000 - -#define CMD_NONE 0 -#define CMD_ARPEGGIO 1 -#define CMD_PORTAMENTOUP 2 -#define CMD_PORTAMENTODOWN 3 -#define CMD_TONEPORTAMENTO 4 -#define CMD_VIBRATO 5 -#define CMD_TONEPORTAVOL 6 -#define CMD_VIBRATOVOL 7 -#define CMD_TREMOLO 8 -#define CMD_PANNING8 9 -#define CMD_OFFSET 10 -#define CMD_VOLUMESLIDE 11 -#define CMD_POSITIONJUMP 12 -#define CMD_VOLUME 13 -#define CMD_PATTERNBREAK 14 -#define CMD_RETRIG 15 -#define CMD_SPEED 16 -#define CMD_TEMPO 17 -#define CMD_TREMOR 18 -#define CMD_MODCMDEX 19 -#define CMD_S3MCMDEX 20 -#define CMD_CHANNELVOLUME 21 -#define CMD_CHANNELVOLSLIDE 22 -#define CMD_GLOBALVOLUME 23 -#define CMD_GLOBALVOLSLIDE 24 -#define CMD_KEYOFF 25 -#define CMD_FINEVIBRATO 26 -#define CMD_PANBRELLO 27 -#define CMD_XFINEPORTAUPDOWN 28 -#define CMD_PANNINGSLIDE 29 -#define CMD_SETENVPOSITION 30 -#define CMD_MIDI 31 - - -// Volume Column commands -#define VOLCMD_VOLUME 1 -#define VOLCMD_PANNING 2 -#define VOLCMD_VOLSLIDEUP 3 -#define VOLCMD_VOLSLIDEDOWN 4 -#define VOLCMD_FINEVOLUP 5 -#define VOLCMD_FINEVOLDOWN 6 -#define VOLCMD_VIBRATOSPEED 7 -#define VOLCMD_VIBRATO 8 -#define VOLCMD_PANSLIDELEFT 9 -#define VOLCMD_PANSLIDERIGHT 10 -#define VOLCMD_TONEPORTAMENTO 11 -#define VOLCMD_PORTAUP 12 -#define VOLCMD_PORTADOWN 13 - -#define RSF_16BIT 0x04 -#define RSF_STEREO 0x08 - -#define RS_PCM8S 0 // 8-bit signed -#define RS_PCM8U 1 // 8-bit unsigned -#define RS_PCM8D 2 // 8-bit delta values -#define RS_ADPCM4 3 // 4-bit ADPCM-packed -#define RS_PCM16D 4 // 16-bit delta values -#define RS_PCM16S 5 // 16-bit signed -#define RS_PCM16U 6 // 16-bit unsigned -#define RS_PCM16M 7 // 16-bit motorola order -#define RS_STPCM8S (RS_PCM8S|RSF_STEREO) // stereo 8-bit signed -#define RS_STPCM8U (RS_PCM8U|RSF_STEREO) // stereo 8-bit unsigned -#define RS_STPCM8D (RS_PCM8D|RSF_STEREO) // stereo 8-bit delta values -#define RS_STPCM16S (RS_PCM16S|RSF_STEREO) // stereo 16-bit signed -#define RS_STPCM16U (RS_PCM16U|RSF_STEREO) // stereo 16-bit unsigned -#define RS_STPCM16D (RS_PCM16D|RSF_STEREO) // stereo 16-bit delta values -#define RS_STPCM16M (RS_PCM16M|RSF_STEREO) // stereo 16-bit signed big endian -// IT 2.14 compressed samples -#define RS_IT2148 0x10 -#define RS_IT21416 0x14 -#define RS_IT2158 0x12 -#define RS_IT21516 0x16 -// AMS Packed Samples -#define RS_AMS8 0x11 -#define RS_AMS16 0x15 -// DMF Huffman compression -#define RS_DMF8 0x13 -#define RS_DMF16 0x17 -// MDL Huffman compression -#define RS_MDL8 0x20 -#define RS_MDL16 0x24 -#define RS_PTM8DTO16 0x25 -// Stereo Interleaved Samples -#define RS_STIPCM8S (RS_PCM8S|0x40|RSF_STEREO) // stereo 8-bit signed -#define RS_STIPCM8U (RS_PCM8U|0x40|RSF_STEREO) // stereo 8-bit unsigned -#define RS_STIPCM16S (RS_PCM16S|0x40|RSF_STEREO) // stereo 16-bit signed -#define RS_STIPCM16U (RS_PCM16U|0x40|RSF_STEREO) // stereo 16-bit unsigned -#define RS_STIPCM16M (RS_PCM16M|0x40|RSF_STEREO) // stereo 16-bit signed big endian -// 24-bit signed -#define RS_PCM24S (RS_PCM16S|0x80) // mono 24-bit signed -#define RS_STIPCM24S (RS_PCM16S|0x80|RSF_STEREO) // stereo 24-bit signed -#define RS_PCM32S (RS_PCM16S|0xC0) // mono 24-bit signed -#define RS_STIPCM32S (RS_PCM16S|0xC0|RSF_STEREO) // stereo 24-bit signed - -// NNA types -#define NNA_NOTECUT 0 -#define NNA_CONTINUE 1 -#define NNA_NOTEOFF 2 -#define NNA_NOTEFADE 3 - -// DCT types -#define DCT_NONE 0 -#define DCT_NOTE 1 -#define DCT_SAMPLE 2 -#define DCT_INSTRUMENT 3 - -// DNA types -#define DNA_NOTECUT 0 -#define DNA_NOTEOFF 1 -#define DNA_NOTEFADE 2 - -// Mixer Hardware-Dependent features -#define SYSMIX_ENABLEMMX 0x01 -#define SYSMIX_WINDOWSNT 0x02 -#define SYSMIX_SLOWCPU 0x04 -#define SYSMIX_FASTCPU 0x08 - -// Module flags -#define SONG_EMBEDMIDICFG 0x0001 -#define SONG_FASTVOLSLIDES 0x0002 -#define SONG_ITOLDEFFECTS 0x0004 -#define SONG_ITCOMPATMODE 0x0008 -#define SONG_LINEARSLIDES 0x0010 -#define SONG_PATTERNLOOP 0x0020 -#define SONG_STEP 0x0040 -#define SONG_PAUSED 0x0080 -#define SONG_FADINGSONG 0x0100 -#define SONG_ENDREACHED 0x0200 -#define SONG_GLOBALFADE 0x0400 -#define SONG_CPUVERYHIGH 0x0800 -#define SONG_FIRSTTICK 0x1000 -#define SONG_MPTFILTERMODE 0x2000 -#define SONG_SURROUNDPAN 0x4000 -#define SONG_EXFILTERRANGE 0x8000 -#define SONG_AMIGALIMITS 0x10000 - -// Global Options (Renderer) -#define SNDMIX_REVERSESTEREO 0x0001 -#define SNDMIX_NOISEREDUCTION 0x0002 -#define SNDMIX_AGC 0x0004 -#define SNDMIX_NORESAMPLING 0x0008 -#define SNDMIX_HQRESAMPLER 0x0010 -#define SNDMIX_MEGABASS 0x0020 -#define SNDMIX_SURROUND 0x0040 -#define SNDMIX_REVERB 0x0080 -#define SNDMIX_EQ 0x0100 -#define SNDMIX_SOFTPANNING 0x0200 -#define SNDMIX_ULTRAHQSRCMODE 0x0400 -// Misc Flags (can safely be turned on or off) -#define SNDMIX_DIRECTTODISK 0x10000 -#define SNDMIX_ENABLEMMX 0x20000 -#define SNDMIX_NOBACKWARDJUMPS 0x40000 -#define SNDMIX_MAXDEFAULTPAN 0x80000 // Used by the MOD loader - - -// Reverb Types (GM2 Presets) -enum { - REVERBTYPE_SMALLROOM, - REVERBTYPE_MEDIUMROOM, - REVERBTYPE_LARGEROOM, - REVERBTYPE_SMALLHALL, - REVERBTYPE_MEDIUMHALL, - REVERBTYPE_LARGEHALL, - NUM_REVERBTYPES -}; - - -enum { - SRCMODE_NEAREST, - SRCMODE_LINEAR, - SRCMODE_SPLINE, - SRCMODE_POLYPHASE, - NUM_SRC_MODES -}; - - -// Sample Struct -typedef struct _MODINSTRUMENT -{ - UINT nLength,nLoopStart,nLoopEnd; - UINT nSustainStart, nSustainEnd; - signed char *pSample; - UINT nC4Speed; - WORD nPan; - WORD nVolume; - WORD nGlobalVol; - WORD uFlags; - signed char RelativeTone; - signed char nFineTune; - BYTE nVibType; - BYTE nVibSweep; - BYTE nVibDepth; - BYTE nVibRate; - CHAR name[22]; -} MODINSTRUMENT; - - -// Instrument Struct -typedef struct _INSTRUMENTHEADER -{ - UINT nFadeOut; - DWORD dwFlags; - WORD nGlobalVol; - WORD nPan; - WORD VolPoints[MAX_ENVPOINTS]; - WORD PanPoints[MAX_ENVPOINTS]; - WORD PitchPoints[MAX_ENVPOINTS]; - BYTE VolEnv[MAX_ENVPOINTS]; - BYTE PanEnv[MAX_ENVPOINTS]; - BYTE PitchEnv[MAX_ENVPOINTS]; - BYTE Keyboard[128]; - BYTE NoteMap[128]; - - BYTE nVolEnv; - BYTE nPanEnv; - BYTE nPitchEnv; - BYTE nVolLoopStart; - BYTE nVolLoopEnd; - BYTE nVolSustainBegin; - BYTE nVolSustainEnd; - BYTE nPanLoopStart; - BYTE nPanLoopEnd; - BYTE nPanSustainBegin; - BYTE nPanSustainEnd; - BYTE nPitchLoopStart; - BYTE nPitchLoopEnd; - BYTE nPitchSustainBegin; - BYTE nPitchSustainEnd; - BYTE nNNA; - BYTE nDCT; - BYTE nDNA; - BYTE nPanSwing; - BYTE nVolSwing; - BYTE nIFC; - BYTE nIFR; - WORD wMidiBank; - BYTE nMidiProgram; - BYTE nMidiChannel; - BYTE nMidiDrumKey; - signed char nPPS; - unsigned char nPPC; - CHAR name[32]; - CHAR filename[12]; -} INSTRUMENTHEADER; - - -// Channel Struct -typedef struct _MODCHANNEL -{ - // First 32-bytes: Most used mixing information: don't change it - signed char * pCurrentSample; - DWORD nPos; - DWORD nPosLo; // actually 16-bit - LONG nInc; // 16.16 - LONG nRightVol; - LONG nLeftVol; - LONG nRightRamp; - LONG nLeftRamp; - // 2nd cache line - DWORD nLength; - DWORD dwFlags; - DWORD nLoopStart; - DWORD nLoopEnd; - LONG nRampRightVol; - LONG nRampLeftVol; - LONG nFilter_Y1, nFilter_Y2, nFilter_Y3, nFilter_Y4; - LONG nFilter_A0, nFilter_B0, nFilter_B1; - LONG nROfs, nLOfs; - LONG nRampLength; - // Information not used in the mixer - signed char * pSample; - LONG nNewRightVol, nNewLeftVol; - LONG nRealVolume, nRealPan; - LONG nVolume, nPan, nFadeOutVol; - LONG nPeriod, nC4Speed, nPortamentoDest; - INSTRUMENTHEADER *pHeader; - MODINSTRUMENT *pInstrument; - DWORD nVolEnvPosition, nPanEnvPosition, nPitchEnvPosition; - DWORD nMasterChn, nVUMeter; - LONG nGlobalVol, nInsVol; - LONG nFineTune, nTranspose; - LONG nPortamentoSlide, nAutoVibDepth; - UINT nAutoVibPos, nVibratoPos, nTremoloPos, nPanbrelloPos; - // 16-bit members - signed short nVolSwing, nPanSwing; - // 8-bit members - BYTE nNote, nNNA; - BYTE nNewNote, nNewIns, nCommand, nArpeggio; - BYTE nOldVolumeSlide, nOldFineVolUpDown; - BYTE nOldPortaUpDown, nOldFinePortaUpDown; - BYTE nOldPanSlide, nOldChnVolSlide; - BYTE nVibratoType, nVibratoSpeed, nVibratoDepth; - BYTE nTremoloType, nTremoloSpeed, nTremoloDepth; - BYTE nPanbrelloType, nPanbrelloSpeed, nPanbrelloDepth; - BYTE nOldCmdEx, nOldVolParam, nOldTempo; - BYTE nOldOffset, nOldHiOffset; - BYTE nCutOff, nResonance; - BYTE nRetrigCount, nRetrigParam; - BYTE nTremorCount, nTremorParam; - BYTE nPatternLoop, nPatternLoopCount; - BYTE nRowNote, nRowInstr; - BYTE nRowVolCmd, nRowVolume; - BYTE nRowCommand, nRowParam; - BYTE nLeftVU, nRightVU; - BYTE nActiveMacro, nPadding; -} MODCHANNEL; - - -typedef struct _MODCHANNELSETTINGS -{ - UINT nPan; - UINT nVolume; - DWORD dwFlags; - UINT nMixPlugin; - char szName[MAX_CHANNELNAME]; // changed from CHAR -} MODCHANNELSETTINGS; - - -typedef struct _MODCOMMAND -{ - BYTE note; - BYTE instr; - BYTE volcmd; - BYTE command; - BYTE vol; - BYTE param; -} MODCOMMAND, *LPMODCOMMAND; - -//////////////////////////////////////////////////////////////////// -// Mix Plugins -#define MIXPLUG_MIXREADY 0x01 // Set when cleared - -class IMixPlugin -{ -public: - virtual ~IMixPlugin(); - virtual int AddRef() = 0; - virtual int Release() = 0; - virtual void SaveAllParameters() = 0; - virtual void RestoreAllParameters() = 0; - virtual void Process(float *pOutL, float *pOutR, unsigned long nSamples) = 0; - virtual void Init(unsigned long nFreq, int bReset) = 0; - virtual void MidiSend(DWORD dwMidiCode) = 0; - virtual void MidiCommand(UINT nMidiCh, UINT nMidiProg, UINT note, UINT vol) = 0; -}; - - -#define MIXPLUG_INPUTF_MASTEREFFECT 0x01 // Apply to master mix -#define MIXPLUG_INPUTF_BYPASS 0x02 // Bypass effect -#define MIXPLUG_INPUTF_WETMIX 0x04 // Wet Mix (dry added) - -typedef struct _SNDMIXPLUGINSTATE -{ - DWORD dwFlags; // MIXPLUG_XXXX - LONG nVolDecayL, nVolDecayR; // Buffer click removal - int *pMixBuffer; // Stereo effect send buffer - float *pOutBufferL; // Temp storage for int -> float conversion - float *pOutBufferR; -} SNDMIXPLUGINSTATE, *PSNDMIXPLUGINSTATE; - -typedef struct _SNDMIXPLUGININFO -{ - DWORD dwPluginId1; - DWORD dwPluginId2; - DWORD dwInputRouting; // MIXPLUG_INPUTF_XXXX - DWORD dwOutputRouting; // 0=mix 0x80+=fx - DWORD dwReserved[4]; // Reserved for routing info - CHAR szName[32]; - CHAR szLibraryName[64]; // original DLL name -} SNDMIXPLUGININFO, *PSNDMIXPLUGININFO; // Size should be 128 - -typedef struct _SNDMIXPLUGIN -{ - IMixPlugin *pMixPlugin; - PSNDMIXPLUGINSTATE pMixState; - ULONG nPluginDataSize; - PVOID pPluginData; - SNDMIXPLUGININFO Info; -} SNDMIXPLUGIN, *PSNDMIXPLUGIN; - -typedef BOOL (*PMIXPLUGINCREATEPROC)(PSNDMIXPLUGIN); - -//////////////////////////////////////////////////////////////////// - -enum { - MIDIOUT_START=0, - MIDIOUT_STOP, - MIDIOUT_TICK, - MIDIOUT_NOTEON, - MIDIOUT_NOTEOFF, - MIDIOUT_VOLUME, - MIDIOUT_PAN, - MIDIOUT_BANKSEL, - MIDIOUT_PROGRAM, -}; - - -typedef struct MODMIDICFG -{ - char szMidiGlb[9*32]; // changed from CHAR - char szMidiSFXExt[16*32]; // changed from CHAR - char szMidiZXXExt[128*32]; // changed from CHAR -} MODMIDICFG, *LPMODMIDICFG; - -#define NOTE_MAX 120 //Defines maximum notevalue as well as maximum number of notes. - -typedef VOID (* LPSNDMIXHOOKPROC)(int *, unsigned long, unsigned long); // buffer, samples, channels - - - -//============== -class CSoundFile -//============== -{ -public: // Static Members - static UINT m_nXBassDepth, m_nXBassRange; - static UINT m_nReverbDepth, m_nReverbDelay, gnReverbType; - static UINT m_nProLogicDepth, m_nProLogicDelay; - static UINT m_nStereoSeparation; - static UINT m_nMaxMixChannels; - static LONG m_nStreamVolume; - static DWORD gdwSysInfo, gdwSoundSetup, gdwMixingFreq, gnBitsPerSample, gnChannels; - static UINT gnAGC, gnVolumeRampSamples, gnVUMeter, gnCPUUsage; - static LPSNDMIXHOOKPROC gpSndMixHook; - static PMIXPLUGINCREATEPROC gpMixPluginCreateProc; - -public: // for Editing - MODCHANNEL Chn[MAX_CHANNELS]; // Channels - UINT ChnMix[MAX_CHANNELS]; // Channels to be mixed - MODINSTRUMENT Ins[MAX_SAMPLES]; // Instruments - INSTRUMENTHEADER *Headers[MAX_INSTRUMENTS]; // Instrument Headers - MODCHANNELSETTINGS ChnSettings[MAX_BASECHANNELS]; // Channels settings - MODCOMMAND *Patterns[MAX_PATTERNS]; // Patterns - WORD PatternSize[MAX_PATTERNS]; // Patterns Lengths - BYTE Order[MAX_ORDERS]; // Pattern Orders - MODMIDICFG m_MidiCfg; // Midi macro config table - SNDMIXPLUGIN m_MixPlugins[MAX_MIXPLUGINS]; // Mix plugins - UINT m_nDefaultSpeed, m_nDefaultTempo, m_nDefaultGlobalVolume; - DWORD m_dwSongFlags; // Song flags SONG_XXXX - UINT m_nChannels, m_nMixChannels, m_nMixStat, m_nBufferCount; - UINT m_nType, m_nSamples, m_nInstruments; - UINT m_nTickCount, m_nTotalCount, m_nPatternDelay, m_nFrameDelay; - UINT m_nMusicSpeed, m_nMusicTempo; - UINT m_nNextRow, m_nRow; - UINT m_nPattern,m_nCurrentPattern,m_nNextPattern,m_nRestartPos; - UINT m_nMasterVolume, m_nGlobalVolume, m_nSongPreAmp; - UINT m_nFreqFactor, m_nTempoFactor, m_nOldGlbVolSlide; - LONG m_nMinPeriod, m_nMaxPeriod, m_nRepeatCount, m_nInitialRepeatCount; - DWORD m_nGlobalFadeSamples, m_nGlobalFadeMaxSamples; - UINT m_nMaxOrderPosition; - UINT m_nPatternNames; - LPSTR m_lpszSongComments, m_lpszPatternNames; - char m_szNames[MAX_INSTRUMENTS][32]; // changed from CHAR - CHAR CompressionTable[16]; - -public: - CSoundFile(); - ~CSoundFile(); - -public: - BOOL Create(LPCBYTE lpStream, DWORD dwMemLength=0); - BOOL Destroy(); - UINT GetType() const { return m_nType; } - UINT GetNumChannels() const; - UINT GetLogicalChannels() const { return m_nChannels; } - BOOL SetMasterVolume(UINT vol, BOOL bAdjustAGC=FALSE); - UINT GetMasterVolume() const { return m_nMasterVolume; } - UINT GetNumPatterns() const; - UINT GetNumInstruments() const; - UINT GetNumSamples() const { return m_nSamples; } - UINT GetCurrentPos() const; - UINT GetCurrentPattern() const { return m_nPattern; } - UINT GetCurrentOrder() const { return m_nCurrentPattern; } - UINT GetSongComments(LPSTR s, UINT cbsize, UINT linesize=32); - UINT GetRawSongComments(LPSTR s, UINT cbsize, UINT linesize=32); - UINT GetMaxPosition() const; - void SetCurrentPos(UINT nPos); - void SetCurrentOrder(UINT nOrder); - void GetTitle(LPSTR s) const { lstrcpyn(s,m_szNames[0],32); } - LPCSTR GetTitle() const { return m_szNames[0]; } - UINT GetSampleName(UINT nSample,LPSTR s=NULL) const; - UINT GetInstrumentName(UINT nInstr,LPSTR s=NULL) const; - UINT GetMusicSpeed() const { return m_nMusicSpeed; } - UINT GetMusicTempo() const { return m_nMusicTempo; } - DWORD GetLength(BOOL bAdjust, BOOL bTotal=FALSE); - DWORD GetSongTime() { return GetLength(FALSE, TRUE); } - void SetRepeatCount(int n) { m_nRepeatCount = n; m_nInitialRepeatCount = n; } - int GetRepeatCount() const { return m_nRepeatCount; } - BOOL IsPaused() const { return (m_dwSongFlags & SONG_PAUSED) ? TRUE : FALSE; } - void LoopPattern(int nPat, int nRow=0); - void CheckCPUUsage(UINT nCPU); - BOOL SetPatternName(UINT nPat, LPCSTR lpszName); - BOOL GetPatternName(UINT nPat, LPSTR lpszName, UINT cbSize=MAX_PATTERNNAME) const; - // Module Loaders - BOOL ReadXM(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadS3M(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadMod(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadMed(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadMTM(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadSTM(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadIT(LPCBYTE lpStream, DWORD dwMemLength); - BOOL Read669(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadUlt(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadWav(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadDSM(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadFAR(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadAMS(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadAMS2(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadMDL(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadOKT(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadDMF(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadPTM(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadDBM(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadAMF(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadMT2(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadPSM(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadJ2B(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadUMX(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadABC(LPCBYTE lpStream, DWORD dwMemLength); - BOOL TestABC(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadMID(LPCBYTE lpStream, DWORD dwMemLength); - BOOL TestMID(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadPAT(LPCBYTE lpStream, DWORD dwMemLength); - BOOL TestPAT(LPCBYTE lpStream, DWORD dwMemLength); - // Save Functions -#ifndef MODPLUG_NO_FILESAVE - UINT WriteSample(FILE *f, MODINSTRUMENT *pins, UINT nFlags, UINT nMaxLen=0); - BOOL SaveXM(LPCSTR lpszFileName, UINT nPacking=0); - BOOL SaveS3M(LPCSTR lpszFileName, UINT nPacking=0); - BOOL SaveMod(LPCSTR lpszFileName, UINT nPacking=0); - BOOL SaveIT(LPCSTR lpszFileName, UINT nPacking=0); -#endif // MODPLUG_NO_FILESAVE - // MOD Convert function - UINT GetBestSaveFormat() const; - UINT GetSaveFormats() const; - void ConvertModCommand(MODCOMMAND *) const; - void S3MConvert(MODCOMMAND *m, BOOL bIT) const; - void S3MSaveConvert(UINT *pcmd, UINT *pprm, BOOL bIT) const; - WORD ModSaveCommand(const MODCOMMAND *m, BOOL bXM) const; - -public: - // Real-time sound functions - VOID ResetChannels(); - - UINT Read(LPVOID lpBuffer, UINT cbBuffer); - UINT CreateStereoMix(int count); - BOOL FadeSong(UINT msec); - BOOL GlobalFadeSong(UINT msec); - UINT GetTotalTickCount() const { return m_nTotalCount; } - VOID ResetTotalTickCount() { m_nTotalCount = 0; } - -public: - // Mixer Config - static BOOL InitPlayer(BOOL bReset=FALSE); - static BOOL SetWaveConfig(UINT nRate,UINT nBits,UINT nChannels,BOOL bMMX=FALSE); - static BOOL SetResamplingMode(UINT nMode); // SRCMODE_XXXX - static BOOL IsStereo() { return (gnChannels > 1) ? TRUE : FALSE; } - static DWORD GetSampleRate() { return gdwMixingFreq; } - static DWORD GetBitsPerSample() { return gnBitsPerSample; } - static DWORD InitSysInfo(); - static DWORD GetSysInfo() { return gdwSysInfo; } - // AGC - static BOOL GetAGC() { return (gdwSoundSetup & SNDMIX_AGC) ? TRUE : FALSE; } - static void SetAGC(BOOL b); - static void ResetAGC(); - static void ProcessAGC(int count); - - //GCCFIX -- added these functions back in! - static BOOL SetWaveConfigEx(BOOL bSurround,BOOL bNoOverSampling,BOOL bReverb,BOOL hqido,BOOL bMegaBass,BOOL bNR,BOOL bEQ); - // DSP Effects - static void InitializeDSP(BOOL bReset); - static void ProcessStereoDSP(int count); - static void ProcessMonoDSP(int count); - // [Reverb level 0(quiet)-100(loud)], [delay in ms, usually 40-200ms] - static BOOL SetReverbParameters(UINT nDepth, UINT nDelay); - // [XBass level 0(quiet)-100(loud)], [cutoff in Hz 10-100] - static BOOL SetXBassParameters(UINT nDepth, UINT nRange); - // [Surround level 0(quiet)-100(heavy)] [delay in ms, usually 5-40ms] - static BOOL SetSurroundParameters(UINT nDepth, UINT nDelay); -public: - BOOL ReadNote(); - BOOL ProcessRow(); - BOOL ProcessEffects(); - UINT GetNNAChannel(UINT nChn) const; - void CheckNNA(UINT nChn, UINT instr, int note, BOOL bForceCut); - void NoteChange(UINT nChn, int note, BOOL bPorta=FALSE, BOOL bResetEnv=TRUE); - void InstrumentChange(MODCHANNEL *pChn, UINT instr, BOOL bPorta=FALSE,BOOL bUpdVol=TRUE,BOOL bResetEnv=TRUE); - // Channel Effects - void PortamentoUp(MODCHANNEL *pChn, UINT param); - void PortamentoDown(MODCHANNEL *pChn, UINT param); - void FinePortamentoUp(MODCHANNEL *pChn, UINT param); - void FinePortamentoDown(MODCHANNEL *pChn, UINT param); - void ExtraFinePortamentoUp(MODCHANNEL *pChn, UINT param); - void ExtraFinePortamentoDown(MODCHANNEL *pChn, UINT param); - void TonePortamento(MODCHANNEL *pChn, UINT param); - void Vibrato(MODCHANNEL *pChn, UINT param); - void FineVibrato(MODCHANNEL *pChn, UINT param); - void VolumeSlide(MODCHANNEL *pChn, UINT param); - void PanningSlide(MODCHANNEL *pChn, UINT param); - void ChannelVolSlide(MODCHANNEL *pChn, UINT param); - void FineVolumeUp(MODCHANNEL *pChn, UINT param); - void FineVolumeDown(MODCHANNEL *pChn, UINT param); - void Tremolo(MODCHANNEL *pChn, UINT param); - void Panbrello(MODCHANNEL *pChn, UINT param); - void RetrigNote(UINT nChn, UINT param); - void NoteCut(UINT nChn, UINT nTick); - void KeyOff(UINT nChn); - int PatternLoop(MODCHANNEL *, UINT param); - void ExtendedMODCommands(UINT nChn, UINT param); - void ExtendedS3MCommands(UINT nChn, UINT param); - void ExtendedChannelEffect(MODCHANNEL *, UINT param); - void ProcessMidiMacro(UINT nChn, LPCSTR pszMidiMacro, UINT param=0); - void SetupChannelFilter(MODCHANNEL *pChn, BOOL bReset, int flt_modifier=256) const; - // Low-Level effect processing - void DoFreqSlide(MODCHANNEL *pChn, LONG nFreqSlide); - // Global Effects - void SetTempo(UINT param); - void SetSpeed(UINT param); - void GlobalVolSlide(UINT param); - DWORD IsSongFinished(UINT nOrder, UINT nRow) const; - BOOL IsValidBackwardJump(UINT nStartOrder, UINT nStartRow, UINT nJumpOrder, UINT nJumpRow) const; - // Read/Write sample functions - signed char GetDeltaValue(signed char prev, UINT n) const { return (signed char)(prev + CompressionTable[n & 0x0F]); } - UINT PackSample(int &sample, int next); - BOOL CanPackSample(LPSTR pSample, UINT nLen, UINT nPacking, BYTE *result=NULL); - UINT ReadSample(MODINSTRUMENT *pIns, UINT nFlags, LPCSTR pMemFile, DWORD dwMemLength); - BOOL DestroySample(UINT nSample); - BOOL DestroyInstrument(UINT nInstr); - BOOL IsSampleUsed(UINT nSample); - BOOL IsInstrumentUsed(UINT nInstr); - BOOL RemoveInstrumentSamples(UINT nInstr); - UINT DetectUnusedSamples(BOOL *); - BOOL RemoveSelectedSamples(BOOL *); - void AdjustSampleLoop(MODINSTRUMENT *pIns); - // I/O from another sound file - BOOL ReadInstrumentFromSong(UINT nInstr, CSoundFile *, UINT nSrcInstrument); - BOOL ReadSampleFromSong(UINT nSample, CSoundFile *, UINT nSrcSample); - // Period/Note functions - UINT GetNoteFromPeriod(UINT period) const; - UINT GetPeriodFromNote(UINT note, int nFineTune, UINT nC4Speed) const; - UINT GetFreqFromPeriod(UINT period, UINT nC4Speed, int nPeriodFrac=0) const; - // Misc functions - MODINSTRUMENT *GetSample(UINT n) { return Ins+n; } - void ResetMidiCfg(); - UINT MapMidiInstrument(DWORD dwProgram, UINT nChannel, UINT nNote); - BOOL ITInstrToMPT(const void *p, INSTRUMENTHEADER *penv, UINT trkvers); - UINT SaveMixPlugins(FILE *f=NULL, BOOL bUpdate=TRUE); - UINT LoadMixPlugins(const void *pData, UINT nLen); -#ifndef NO_FILTER - DWORD CutOffToFrequency(UINT nCutOff, int flt_modifier=256) const; // [0-255] => [1-10KHz] -#endif - - // Static helper functions -public: - static DWORD TransposeToFrequency(int transp, int ftune=0); - static int FrequencyToTranspose(DWORD freq); - static void FrequencyToTranspose(MODINSTRUMENT *psmp); - - // System-Dependant functions -public: - static MODCOMMAND *AllocatePattern(UINT rows, UINT nchns); - static signed char* AllocateSample(UINT nbytes); - static void FreePattern(LPVOID pat); - static void FreeSample(LPVOID p); - static UINT Normalize24BitBuffer(LPBYTE pbuffer, UINT cbsizebytes, DWORD lmax24, DWORD dwByteInc); -}; - - -// inline DWORD BigEndian(DWORD x) { return ((x & 0xFF) << 24) | ((x & 0xFF00) << 8) | ((x & 0xFF0000) >> 8) | ((x & 0xFF000000) >> 24); } -// inline WORD BigEndianW(WORD x) { return (WORD)(((x >> 8) & 0xFF) | ((x << 8) & 0xFF00)); } - - -////////////////////////////////////////////////////////// -// WAVE format information - -#pragma pack(1) - -// Standard IFF chunks IDs -#define IFFID_FORM 0x4d524f46 -#define IFFID_RIFF 0x46464952 -#define IFFID_WAVE 0x45564157 -#define IFFID_LIST 0x5453494C -#define IFFID_INFO 0x4F464E49 - -// IFF Info fields -#define IFFID_ICOP 0x504F4349 -#define IFFID_IART 0x54524149 -#define IFFID_IPRD 0x44525049 -#define IFFID_INAM 0x4D414E49 -#define IFFID_ICMT 0x544D4349 -#define IFFID_IENG 0x474E4549 -#define IFFID_ISFT 0x54465349 -#define IFFID_ISBJ 0x4A425349 -#define IFFID_IGNR 0x524E4749 -#define IFFID_ICRD 0x44524349 - -// Wave IFF chunks IDs -#define IFFID_wave 0x65766177 -#define IFFID_fmt 0x20746D66 -#define IFFID_wsmp 0x706D7377 -#define IFFID_pcm 0x206d6370 -#define IFFID_data 0x61746164 -#define IFFID_smpl 0x6C706D73 -#define IFFID_xtra 0x61727478 - -typedef struct WAVEFILEHEADER -{ - DWORD id_RIFF; // "RIFF" - DWORD filesize; // file length-8 - DWORD id_WAVE; -} WAVEFILEHEADER; - - -typedef struct WAVEFORMATHEADER -{ - DWORD id_fmt; // "fmt " - DWORD hdrlen; // 16 - WORD format; // 1 - WORD channels; // 1:mono, 2:stereo - DWORD freqHz; // sampling freq - DWORD bytessec; // bytes/sec=freqHz*samplesize - WORD samplesize; // sizeof(sample) - WORD bitspersample; // bits per sample (8/16) -} WAVEFORMATHEADER; - - -typedef struct WAVEDATAHEADER -{ - DWORD id_data; // "data" - DWORD length; // length of data -} WAVEDATAHEADER; - - -typedef struct WAVESMPLHEADER -{ - // SMPL - DWORD smpl_id; // "smpl" -> 0x6C706D73 - DWORD smpl_len; // length of smpl: 3Ch (54h with sustain loop) - DWORD dwManufacturer; - DWORD dwProduct; - DWORD dwSamplePeriod; // 1000000000/freqHz - DWORD dwBaseNote; // 3Ch = C-4 -> 60 + RelativeTone - DWORD dwPitchFraction; - DWORD dwSMPTEFormat; - DWORD dwSMPTEOffset; - DWORD dwSampleLoops; // number of loops - DWORD cbSamplerData; -} WAVESMPLHEADER; - - -typedef struct SAMPLELOOPSTRUCT -{ - DWORD dwIdentifier; - DWORD dwLoopType; // 0=normal, 1=bidi - DWORD dwLoopStart; - DWORD dwLoopEnd; // Byte offset ? - DWORD dwFraction; - DWORD dwPlayCount; // Loop Count, 0=infinite -} SAMPLELOOPSTRUCT; - - -typedef struct WAVESAMPLERINFO -{ - WAVESMPLHEADER wsiHdr; - SAMPLELOOPSTRUCT wsiLoops[2]; -} WAVESAMPLERINFO; - - -typedef struct WAVELISTHEADER -{ - DWORD list_id; // "LIST" -> 0x5453494C - DWORD list_len; - DWORD info; // "INFO" -} WAVELISTHEADER; - - -typedef struct WAVEEXTRAHEADER -{ - DWORD xtra_id; // "xtra" -> 0x61727478 - DWORD xtra_len; - DWORD dwFlags; - WORD wPan; - WORD wVolume; - WORD wGlobalVol; - WORD wReserved; - BYTE nVibType; - BYTE nVibSweep; - BYTE nVibDepth; - BYTE nVibRate; -} WAVEEXTRAHEADER; - -#pragma pack() - -/////////////////////////////////////////////////////////// -// Low-level Mixing functions - -#define MIXBUFFERSIZE 512 -#define MIXING_ATTENUATION 4 -#define MIXING_CLIPMIN (-0x08000000) -#define MIXING_CLIPMAX (0x07FFFFFF) -#define VOLUMERAMPPRECISION 12 -#define FADESONGDELAY 100 -#define EQ_BUFFERSIZE (MIXBUFFERSIZE) -#define AGC_PRECISION 9 -#define AGC_UNITY (1 << AGC_PRECISION) - -// Calling conventions -#ifdef MSC_VER -#define MPPASMCALL __cdecl -#define MPPFASTCALL __fastcall -#else -#define MPPASMCALL -#define MPPFASTCALL -#endif - -#define MOD2XMFineTune(k) ((int)( (signed char)((k)<<4) )) -#define XM2MODFineTune(k) ((int)( (k>>4)&0x0f )) - -int _muldiv(long a, long b, long c); -int _muldivr(long a, long b, long c); - - -// Byte swapping functions from the GNU C Library and libsdl - -/* Swap bytes in 16 bit value. */ -#ifdef __GNUC__ -# define bswap_16(x) \ - (__extension__ \ - ({ unsigned short int __bsx = (x); \ - ((((__bsx) >> 8) & 0xff) | (((__bsx) & 0xff) << 8)); })) -#else -static __inline unsigned short int -bswap_16 (unsigned short int __bsx) -{ - return ((((__bsx) >> 8) & 0xff) | (((__bsx) & 0xff) << 8)); -} -#endif - -/* Swap bytes in 32 bit value. */ -#ifdef __GNUC__ -# define bswap_32(x) \ - (__extension__ \ - ({ unsigned int __bsx = (x); \ - ((((__bsx) & 0xff000000) >> 24) | (((__bsx) & 0x00ff0000) >> 8) | \ - (((__bsx) & 0x0000ff00) << 8) | (((__bsx) & 0x000000ff) << 24)); })) -#else -static __inline unsigned int -bswap_32 (unsigned int __bsx) -{ - return ((((__bsx) & 0xff000000) >> 24) | (((__bsx) & 0x00ff0000) >> 8) | - (((__bsx) & 0x0000ff00) << 8) | (((__bsx) & 0x000000ff) << 24)); -} -#endif - -#if (defined ARM) && (defined _WIN32_WCE) -static __inline unsigned short int -ARM_get16(const void *data) -{ - unsigned short int s; - memcpy(&s,data,sizeof(s)); - return s; -} - -static __inline unsigned int -ARM_get32(const void *data) -{ - unsigned int s; - memcpy(&s,data,sizeof(s)); - return s; -} - -#define bswapLE16(X) ARM_get16(&X) -#define bswapLE32(X) ARM_get32(&X) -#define bswapBE16(X) bswap_16(ARM_get16(&X)) -#define bswapBE32(X) bswap_32(ARM_get32(&X)) - -// From libsdl -#elif WORDS_BIGENDIAN -#define bswapLE16(X) bswap_16(X) -#define bswapLE32(X) bswap_32(X) -#define bswapBE16(X) (X) -#define bswapBE32(X) (X) -#else -#define bswapLE16(X) (X) -#define bswapLE32(X) (X) -#define bswapBE16(X) bswap_16(X) -#define bswapBE32(X) bswap_32(X) -#endif - -#endif diff --git a/lib/libmodplug/src/libmodplug/stdafx.h b/lib/libmodplug/src/libmodplug/stdafx.h deleted file mode 100644 index e4815aaaf2..0000000000 --- a/lib/libmodplug/src/libmodplug/stdafx.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Rani Assaf <rani@magic.metawire.com>, - * Olivier Lapicque <olivierl@jps.net>, - * Adam Goode <adam@evdebs.org> (endian and char fixes for PPC) - */ - -#ifndef _STDAFX_H_ -#define _STDAFX_H_ - -/* Autoconf detection of stdint/inttypes */ -#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) -# include "config.h" -# define CONFIG_H_INCLUDED 1 -#endif -#ifdef HAVE_INTTYPES_H -# include <inttypes.h> -#endif -#ifdef HAVE_STDINT_H -# include <stdint.h> -#endif - - -#ifdef _WIN32 - -#ifdef MSC_VER -#pragma warning (disable:4201) -#pragma warning (disable:4514) -#endif - -#define WIN32_LEAN_AND_MEAN -#include <windows.h> -#include <windowsx.h> -#include <mmsystem.h> -#include <stdio.h> -#include <malloc.h> - -#pragma warning(disable:4996) - -typedef unsigned __int32 uint32_t; -typedef __int32 int32_t; -typedef unsigned __int16 uint16_t; -typedef __int16 int16_t; -typedef unsigned __int8 uint8_t; -typedef __int8 int8_t; - -#define srandom(_seed) srand(_seed) -#define random() rand() -#define sleep(_ms) Sleep(_ms) -#define strncasecmp strnicmp -#define strcasecmp stricmp - -inline void ProcessPlugins(int n) {} - -#else - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#ifdef HAVE_MALLOC_H -#include <malloc.h> -#endif - -typedef int8_t CHAR; -typedef uint8_t UCHAR; -typedef uint8_t* PUCHAR; -typedef uint16_t USHORT; -typedef uint32_t ULONG; -typedef uint32_t UINT; -typedef uint32_t DWORD; -typedef int32_t LONG; -typedef int64_t LONGLONG; -typedef int32_t* LPLONG; -typedef uint32_t* LPDWORD; -typedef uint16_t WORD; -typedef uint8_t BYTE; -typedef uint8_t* LPBYTE; -typedef bool BOOL; -typedef char* LPSTR; -typedef void* LPVOID; -typedef uint16_t* LPWORD; -typedef const char* LPCSTR; -typedef void* PVOID; -typedef void VOID; - -inline LONG MulDiv (long a, long b, long c) -{ - // if (!c) return 0; - return ((uint64_t) a * (uint64_t) b ) / c; -} - -#define MODPLUG_NO_FILESAVE -#define NO_AGC -#define LPCTSTR LPCSTR -#define lstrcpyn strncpy -#define lstrcpy strcpy -#define lstrcmp strcmp -#define WAVE_FORMAT_PCM 1 -//#define ENABLE_EQ - -#define GHND 0 - -inline int8_t * GlobalAllocPtr(unsigned int, size_t size) -{ - int8_t * p = (int8_t *) malloc(size); - - if (p != NULL) memset(p, 0, size); - return p; -} - -inline void ProcessPlugins(int n) {} - -#define GlobalFreePtr(p) free((void *)(p)) - -#define strnicmp(a,b,c) strncasecmp(a,b,c) -#define wsprintf sprintf - -#ifndef FALSE -#define FALSE false -#endif - -#ifndef TRUE -#define TRUE true -#endif - -#endif // _WIN32 - -#endif - - - diff --git a/lib/libmodplug/src/load_669.cpp b/lib/libmodplug/src/load_669.cpp deleted file mode 100644 index a0dbfabd76..0000000000 --- a/lib/libmodplug/src/load_669.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque <olivierl@jps.net>, - * Adam Goode <adam@evdebs.org> (endian and char fixes for PPC) -*/ - -//////////////////////////////////////////////////////////// -// 669 Composer / UNIS 669 module loader -//////////////////////////////////////////////////////////// - -#include "stdafx.h" -#include "sndfile.h" - -//#pragma warning(disable:4244) - -typedef struct tagFILEHEADER669 -{ - WORD sig; // 'if' or 'JN' - signed char songmessage[108]; // Song Message - BYTE samples; // number of samples (1-64) - BYTE patterns; // number of patterns (1-128) - BYTE restartpos; - BYTE orders[128]; - BYTE tempolist[128]; - BYTE breaks[128]; -} FILEHEADER669; - - -typedef struct tagSAMPLE669 -{ - BYTE filename[13]; - BYTE length[4]; // when will somebody think about DWORD align ??? - BYTE loopstart[4]; - BYTE loopend[4]; -} SAMPLE669; - - -BOOL CSoundFile::Read669(const BYTE *lpStream, DWORD dwMemLength) -//--------------------------------------------------------------- -{ - BOOL b669Ext; - const FILEHEADER669 *pfh = (const FILEHEADER669 *)lpStream; - const SAMPLE669 *psmp = (const SAMPLE669 *)(lpStream + 0x1F1); - DWORD dwMemPos = 0; - - if ((!lpStream) || (dwMemLength < sizeof(FILEHEADER669))) return FALSE; - if ((bswapLE16(pfh->sig) != 0x6669) && (bswapLE16(pfh->sig) != 0x4E4A)) return FALSE; - b669Ext = (bswapLE16(pfh->sig) == 0x4E4A) ? TRUE : FALSE; - if ((!pfh->samples) || (pfh->samples > 64) || (pfh->restartpos >= 128) - || (!pfh->patterns) || (pfh->patterns > 128)) return FALSE; - DWORD dontfuckwithme = 0x1F1 + pfh->samples * sizeof(SAMPLE669) + pfh->patterns * 0x600; - if (dontfuckwithme > dwMemLength) return FALSE; - for (UINT ichk=0; ichk<pfh->samples; ichk++) - { - DWORD len = bswapLE32(*((DWORD *)(&psmp[ichk].length))); - dontfuckwithme += len; - } - if (dontfuckwithme > dwMemLength) return FALSE; - // That should be enough checking: this must be a 669 module. - m_nType = MOD_TYPE_669; - m_dwSongFlags |= SONG_LINEARSLIDES; - m_nMinPeriod = 28 << 2; - m_nMaxPeriod = 1712 << 3; - m_nDefaultTempo = 125; - m_nDefaultSpeed = 6; - m_nChannels = 8; - memcpy(m_szNames[0], pfh->songmessage, 16); - m_nSamples = pfh->samples; - for (UINT nins=1; nins<=m_nSamples; nins++, psmp++) - { - DWORD len = bswapLE32(*((DWORD *)(&psmp->length))); - DWORD loopstart = bswapLE32(*((DWORD *)(&psmp->loopstart))); - DWORD loopend = bswapLE32(*((DWORD *)(&psmp->loopend))); - if (len > MAX_SAMPLE_LENGTH) len = MAX_SAMPLE_LENGTH; - if ((loopend > len) && (!loopstart)) loopend = 0; - if (loopend > len) loopend = len; - if (loopstart + 4 >= loopend) loopstart = loopend = 0; - Ins[nins].nLength = len; - Ins[nins].nLoopStart = loopstart; - Ins[nins].nLoopEnd = loopend; - if (loopend) Ins[nins].uFlags |= CHN_LOOP; - memcpy(m_szNames[nins], psmp->filename, 13); - Ins[nins].nVolume = 256; - Ins[nins].nGlobalVol = 64; - Ins[nins].nPan = 128; - } - // Song Message - m_lpszSongComments = new char[109]; - memcpy(m_lpszSongComments, pfh->songmessage, 108); - m_lpszSongComments[108] = 0; - // Reading Orders - memcpy(Order, pfh->orders, 128); - m_nRestartPos = pfh->restartpos; - if (Order[m_nRestartPos] >= pfh->patterns) m_nRestartPos = 0; - // Reading Pattern Break Locations - for (UINT npan=0; npan<8; npan++) - { - ChnSettings[npan].nPan = (npan & 1) ? 0x30 : 0xD0; - ChnSettings[npan].nVolume = 64; - } - // Reading Patterns - dwMemPos = 0x1F1 + pfh->samples * 25; - for (UINT npat=0; npat<pfh->patterns; npat++) - { - Patterns[npat] = AllocatePattern(64, m_nChannels); - if (!Patterns[npat]) break; - PatternSize[npat] = 64; - MODCOMMAND *m = Patterns[npat]; - const BYTE *p = lpStream + dwMemPos; - for (UINT row=0; row<64; row++) - { - MODCOMMAND *mspeed = m; - if ((row == pfh->breaks[npat]) && (row != 63)) - { - for (UINT i=0; i<8; i++) - { - m[i].command = CMD_PATTERNBREAK; - m[i].param = 0; - } - } - for (UINT n=0; n<8; n++, m++, p+=3) - { - UINT note = p[0] >> 2; - UINT instr = ((p[0] & 0x03) << 4) | (p[1] >> 4); - UINT vol = p[1] & 0x0F; - if (p[0] < 0xFE) - { - m->note = note + 37; - m->instr = instr + 1; - } - if (p[0] <= 0xFE) - { - m->volcmd = VOLCMD_VOLUME; - m->vol = (vol << 2) + 2; - } - if (p[2] != 0xFF) - { - UINT command = p[2] >> 4; - UINT param = p[2] & 0x0F; - switch(command) - { - case 0x00: command = CMD_PORTAMENTOUP; break; - case 0x01: command = CMD_PORTAMENTODOWN; break; - case 0x02: command = CMD_TONEPORTAMENTO; break; - case 0x03: command = CMD_MODCMDEX; param |= 0x50; break; - case 0x04: command = CMD_VIBRATO; param |= 0x40; break; - case 0x05: if (param) command = CMD_SPEED; else command = 0; param += 2; break; - case 0x06: if (param == 0) { command = CMD_PANNINGSLIDE; param = 0xFE; } else - if (param == 1) { command = CMD_PANNINGSLIDE; param = 0xEF; } else - command = 0; - break; - default: command = 0; - } - if (command) - { - if (command == CMD_SPEED) mspeed = NULL; - m->command = command; - m->param = param; - } - } - } - if ((!row) && (mspeed)) - { - for (UINT i=0; i<8; i++) if (!mspeed[i].command) - { - mspeed[i].command = CMD_SPEED; - mspeed[i].param = pfh->tempolist[npat] + 2; - break; - } - } - } - dwMemPos += 0x600; - } - // Reading Samples - for (UINT n=1; n<=m_nSamples; n++) - { - UINT len = Ins[n].nLength; - if (dwMemPos >= dwMemLength) break; - if (len > 4) ReadSample(&Ins[n], RS_PCM8U, (LPSTR)(lpStream+dwMemPos), dwMemLength - dwMemPos); - dwMemPos += len; - } - return TRUE; -} - - diff --git a/lib/libmodplug/src/load_abc.cpp b/lib/libmodplug/src/load_abc.cpp deleted file mode 100644 index fd708578bb..0000000000 --- a/lib/libmodplug/src/load_abc.cpp +++ /dev/null @@ -1,5142 +0,0 @@ -/* - - MikMod Sound System - - By Jake Stine of Divine Entertainment (1996-2000) - - Support: - If you find problems with this code, send mail to: - air@divent.org - - Distribution / Code rights: - Use this source code in any fashion you see fit. Giving me credit where - credit is due is optional, depending on your own levels of integrity and - honesty. - - ----------------------------------------- - Module: LOAD_ABC - - ABC module loader. - by Peter Grootswagers (2006) - <email:pgrootswagers@planet.nl> - - Portability: - All systems - all compilers (hopefully) -*/ - -#include <stdlib.h> -#include <time.h> -#include <string.h> -#include <math.h> -#include <ctype.h> -#include "stdafx.h" - -#ifdef NEWMIKMOD -#include "mikmod.h" -#include "uniform.h" -typedef UBYTE BYTE; -typedef UWORD WORD; -#else -#include "stdafx.h" -#include "sndfile.h" -#endif - -#include "load_pat.h" - -#define MAXABCINCLUDES 8 -#define MAXCHORDNAMES 80 -#define ABC_ENV_DUMPTRACKS "MMABC_DUMPTRACKS" -#define ABC_ENV_NORANDOMPICK "MMABC_NO_RANDOM_PICK" - -// gchords use tracks with vpos 1 thru 7 -// drums use track with vpos 8 -// voice chords use vpos 0 and vpos from 11 up -#define GCHORDBPOS 1 -#define GCHORDFPOS 2 -#define GCHORDCPOS 3 -#define DRUMPOS 8 -#define DRONEPOS1 9 -#define DRONEPOS2 10 - -// in the patterns a whole note at unmodified tempo is 16 rows -#define ROWSPERNOTE 16 -// a 1/64-th note played in triool equals a 1/96-th note, to be able -// to play them and also to play the 1/64-th we need a resolution of 192 -// because 2/192 = 1/96 and 3/192 = 1/64 -#define RESOLUTION 192 - -#pragma pack(1) - -/************************************************************************** -**************************************************************************/ -#ifdef NEWMIKMOD -static char ABC_Version[] = "ABC+2.0 (draft IV)"; -#endif - -typedef enum { - note, - octave, - smpno, - volume, - effect, - effoper -} ABCEVENT_X_NOTE; - -typedef enum { - none, - trill, - bow, - accent -} ABCEVENT_X_EFFECT; - -typedef enum { - cmdflag, - command, - chordnum, - chordnote, - chordbase, - jumptype -} ABCEVENT_X_CMD; - -typedef enum { - cmdsegno = '$', - cmdcapo = 'B', - cmdchord = 'C', - cmdfine = 'F', - cmdhide = 'H', - cmdjump = 'J', - cmdloop = 'L', - cmdcoda = 'O', - cmdpartbrk = 'P', - cmdsync = 'S', - cmdtempo = 'T', - cmdvariant = 'V', - cmdtocoda = 'X' -} ABCEVENT_CMD; - -typedef enum { - jumpnormal, - jumpfade, - jumpdacapo, - jumpdcfade, - jumpdasegno, - jumpdsfade, - jumpfine, - jumptocoda, - jumpvariant, - jumpnot -} ABCEVENT_JUMPTYPE; - -typedef struct _ABCEVENT -{ - struct _ABCEVENT *next; - uint32_t tracktick; - union { - uint8_t par[6]; - struct { - uint8_t flg; - uint8_t cmd; - uint32_t lpar; // for variant selections, bit pattern - }; - }; - uint8_t part; - uint8_t tiednote; -} ABCEVENT; - -typedef struct _ABCTRACK -{ - struct _ABCTRACK *next; - ABCEVENT *head; - ABCEVENT *tail; - ABCEVENT *capostart; - ABCEVENT *tienote; - int transpose; - int octave_shift; - uint32_t slidevoltime; // for crescendo and diminuendo - int slidevol; // -2:fade away, -1:diminuendo, 0:none, +1:crescendo - uint8_t vno; // 0 is track is free for use, from previous song in multi-songbook - uint8_t vpos; // 0 is main voice, other is subtrack for gchords, gchords or drumnotes - uint8_t tiedvpos; - uint8_t mute; - uint8_t chan; // 10 is percussion channel, any other is melodic channel - uint8_t volume; - uint8_t instr; // current instrument for this track - uint8_t legato; - char v[22]; // first twenty characters are significant -} ABCTRACK; - -typedef struct _ABCMACRO -{ - struct _ABCMACRO *next; - char *name; - char *subst; - char *n; -} ABCMACRO; - -/************************************************************************** -**************************************************************************/ - -typedef struct _ABCHANDLE -{ -#ifdef NEWMIKMOD - MM_ALLOC *allochandle; - MM_ALLOC *macrohandle; - MM_ALLOC *trackhandle; - MM_ALLOC *ho; -#endif - ABCMACRO *macro; - ABCMACRO *umacro; - ABCTRACK *track; - long int pickrandom; - unsigned int len; - int speed; - char *line; - char *beatstring; - uint8_t beat[4]; // a:first note, b:strong notes, c:weak notes, n:strong note every n - char gchord[80]; // last setting for gchord - char drum[80]; // last setting for drum - char drumins[80]; // last setting for drum - char drumvol[80]; // last setting for drum - uint32_t barticks; - // parse variables, declared here to avoid parameter pollution - int abcchordvol, abcchordprog, abcbassvol, abcbassprog; - int ktrans; - int drumon, gchordon, droneon; - int dronegm, dronepitch[2], dronevol[2]; - ABCTRACK *tp, *tpc, *tpr; - uint32_t tracktime; -} ABCHANDLE; - -static int global_voiceno, global_octave_shift, global_tempo_factor, global_tempo_divider; -static char global_part; -static uint32_t global_songstart; -/* Named guitar chords */ -static char chordname[MAXCHORDNAMES][8]; -static int chordnotes[MAXCHORDNAMES][6]; -static int chordlen[MAXCHORDNAMES]; -static int chordsnamed = 0; - -static const char *sig[] = { - " C D EF G A Bc d ef g a b", // 7 sharps C# - " C D EF G AB c d ef g ab ", // 6 sharps F# - " C DE F G AB c de f g ab ", // 5 sharps B - " C DE F GA B c de f ga b ", // 4 sharps E - " CD E F GA B cd e f ga b ", // 3 sharps A - " CD E FG A B cd e fg a b ", // 2 sharps D - " C D E FG A Bc d e fg a b", // 1 sharps G - " C D EF G A Bc d ef g a b", // 0 sharps C - " C D EF G AB c d ef g ab ", // 1 flats F - " C DE F G AB c de f g ab ", // 2 flats Bb - " C DE F GA B c de f ga b ", // 3 flats Eb - " CD E F GA B cd e f ga b ", // 4 flats Ab - " CD E FG A B cd e fg a b ", // 5 flats Db - "C D E FG A Bc d e fg a b ", // 6 flats Gb - "C D EF G A Bc d ef g a b ", // 7 flats Cb -// 0123456789012345678901234 -}; - -static const char *keySigs[] = { -/* 0....:....1....:....2....:....3....:....4....:....5. */ - "7 sharps: C# A#m G#Mix D#Dor E#Phr F#Lyd B#Loc ", - "6 sharps: F# D#m C#Mix G#Dor A#Phr BLyd E#Loc ", - "5 sharps: B G#m F#Mix C#Dor D#Phr ELyd A#Loc ", - "4 sharps: E C#m BMix F#Dor G#Phr ALyd D#Loc ", - "3 sharps: A F#m EMix BDor C#Phr DLyd G#Loc ", - "2 sharps: D Bm AMix EDor F#Phr GLyd C#Loc ", - "1 sharp : G Em DMix ADor BPhr CLyd F#Loc ", - "0 sharps: C Am GMix DDor EPhr FLyd BLoc ", - "1 flat : F Dm CMix GDor APhr BbLyd ELoc ", - "2 flats : Bb Gm FMix CDor DPhr EbLyd ALoc ", - "3 flats : Eb Cm BbMix FDor GPhr AbLyd DLoc ", - "4 flats : Ab Fm EbMix BbDor CPhr DbLyd GLoc ", - "5 flats : Db Bbm AbMix EbDor FPhr GbLyd CLoc ", - "6 flats : Gb Ebm DbMix AbDor BbPhr CbLyd FLoc ", - "7 flats : Cb Abm GbMix DbDor EbPhr FbLyd BbLoc ", - 0 -}; - -// local prototypes -static int abc_getnumber(const char *p, int *number); -static ABCTRACK *abc_locate_track(ABCHANDLE *h, const char *voice, int pos); -static void abc_add_event(ABCHANDLE *h, ABCTRACK *tp, ABCEVENT *e); -static void abc_add_setloop(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime); -static void abc_add_setjumploop(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime, ABCEVENT_JUMPTYPE j); -static uint32_t abc_pattracktime(ABCHANDLE *h, uint32_t tracktime); -static int abc_patno(ABCHANDLE *h, uint32_t tracktime); - -#ifndef HAVE_SETENV -static void setenv(const char *name, const char *value, int overwrite) -{ - int len = strlen(name)+1+strlen(value)+1; - char *str = (char *)alloca(len); - sprintf(str, "%s=%s", name, value); - putenv(str); -} -#endif - - -static int abc_isvalidchar(unsigned char c) { - return(isalpha(c) || isdigit(c) || isspace(c) || c == '%' || c == ':'); -} - - -static void abc_message(const char *s1, const char *s2) -{ - char txt[256]; - if( strlen(s1) + strlen(s2) > 255 ) return; - sprintf(txt, s1, s2); -#ifdef NEWMIKMOD - _mmlog(txt); -#else - fprintf(stderr, "load_abc > %s\n", txt); -#endif -} - -static uint32_t modticks(uint32_t abcticks) -{ - return abcticks / RESOLUTION; -} - -static uint32_t abcticks(uint32_t modticks) -{ - return modticks * RESOLUTION; -} - -static uint32_t notelen_notediv_to_ticks(int speed, int len, int div) -{ - uint32_t u; - u = (ROWSPERNOTE * RESOLUTION * speed * len * global_tempo_factor) / (div * global_tempo_divider); - return u; -} - -static void abc_dumptracks(ABCHANDLE *h, const char *p) -{ - ABCTRACK *t; - ABCEVENT *e; - int n,pat,row,tck; - char nn[3]; - if( !h ) return; - for( t=h->track; t; t=t->next ) { - printf("track %d.%d chan=%d %s\n", (int)(t->vno), (int)(t->vpos), - (int)(t->chan), (char *)(t->v)); - if( strcmp(p,"nonotes") ) - n = 1; - else - n = 0; - for( e=t->head; e; e=e->next ) { - tck = modticks(e->tracktick); - row = tck / h->speed; - pat = row / 64; - tck = tck % h->speed; - row = row % 64; - nn[0] = ( e->tracktick % abcticks(h->speed * 64) ) ? ' ': '-'; - if( e->flg == 1 ) { - printf(" %6d.%02d.%d%c%c %d.%d %s ", - pat, row, tck, nn[0], (int)(e->part), (int)(t->vno), - (int)(t->vpos), (char *)(t->v)); - if( e->cmd == cmdchord ) { - nn[0] = "CCCDDEFFGGAABccddeffggaabb"[e->par[chordnote]]; - nn[1] = "b # # # # # # # # # # #"[e->par[chordnote]]; - nn[2] = '\0'; - if( isspace(nn[1]) ) nn[1] = '\0'; - printf("CMD %c: gchord %s%s", - (char)(e->cmd), nn, chordname[e->par[chordnum]]); - if( e->par[chordbase] != e->par[chordnote] ) { - nn[0] = "CCCDDEFFGGAABccddeffggaabb"[e->par[chordbase]]; - nn[1] = "b # # # # # # # # # # #"[e->par[chordbase]]; - nn[2] = '\0'; - printf("/%s", nn); - } - printf("\n"); - } - else - printf("CMD %c @%p 0x%08lX\n", - (char)(e->cmd), e, - (unsigned long)(e->lpar)); - if( strcmp(p,"nonotes") ) - n = 1; - else - n = 0; - } - else if( n ) { - printf(" %6d.%02d.%d%c%c %d.%d %s ", pat, row, tck, nn[0], e->part, t->vno, t->vpos, t->v); - if( e->par[note] ) { - nn[0] = "CCCDDEFFGGAABccddeffggaabb"[e->par[note]-23]; - nn[1] = "b # # # # # # # # # # #"[e->par[note]-23]; - nn[2] = '\0'; - } - else strcpy(nn,"--"); - printf("NOTE %s octave %d inst %s vol %03d\n", - nn, e->par[octave], pat_gm_name(pat_smptogm(e->par[smpno])),e->par[volume]); - if( strcmp(p,"all") ) - n = 0; - } - } - } -} - -#ifdef NEWMIKMOD - -#define MMFILE MMSTREAM -#define mmfgetc(x) _mm_read_SBYTE(x) -#define mmfeof(x) _mm_feof(x) -#define mmfgets(buf,sz,f) _mm_fgets(f,buf,sz) -#define mmftell(x) _mm_ftell(x) -#define mmfseek(f,p,w) _mm_fseek(f,p,w) -#define mmfopen(s,m) _mm_fopen(s,m) -#define mmfclose(f) _mm_fclose(f) - -#else - -#define MMSTREAM FILE -#define _mm_fopen(name,mode) fopen(name,mode) -#define _mm_fgets(f,buf,sz) fgets(buf,sz,f) -#define _mm_fseek(f,pos,whence) fseek(f,pos,whence) -#define _mm_ftell(f) ftell(f) -#define _mm_read_UBYTES(buf,sz,f) fread(buf,sz,1,f) -#define _mm_read_SBYTES(buf,sz,f) fread(buf,sz,1,f) -#define _mm_feof(f) feof(f) -#define _mm_fclose(f) fclose(f) -#define DupStr(h,buf,sz) strdup(buf) -#define _mm_calloc(h,n,sz) calloc(n,sz) -#define _mm_recalloc(h,buf,sz,elsz) realloc(buf,sz) -#undef _mm_free -#define _mm_free(h,p) free(p) - -typedef struct { - char *mm; - int sz; - int pos; -} MMFILE; - -static MMFILE *mmfopen(const char *name, const char *mode) -{ - FILE *fp; - MMFILE *mmfile; - long len; - if( *mode != 'r' ) return NULL; - fp = fopen(name, mode); - if( !fp ) return NULL; - fseek(fp, 0, SEEK_END); - len = ftell(fp); - mmfile = (MMFILE *)malloc(len+sizeof(MMFILE)); - if( !mmfile ) return NULL; - fseek(fp, 0, SEEK_SET); - fread(&mmfile[1],1,len,fp); - fclose(fp); - mmfile->mm = (char *)&mmfile[1]; - mmfile->sz = len; - mmfile->pos = 0; - return mmfile; -} - -static void mmfclose(MMFILE *mmfile) -{ - free(mmfile); -} - -static bool mmfeof(MMFILE *mmfile) -{ - if( mmfile->pos < 0 ) return TRUE; - if( mmfile->pos < mmfile->sz ) return FALSE; - return TRUE; -} - -static int mmfgetc(MMFILE *mmfile) -{ - int b; - if( mmfeof(mmfile) ) return EOF; - b = mmfile->mm[mmfile->pos]; - mmfile->pos++; - if( b=='\r' && mmfile->mm[mmfile->pos] == '\n' ) { - b = '\n'; - mmfile->pos++; - } - return b; -} - -static void mmfgets(char buf[], unsigned int bufsz, MMFILE *mmfile) -{ - int i,b; - for( i=0; i<(int)bufsz-1; i++ ) { - b = mmfgetc(mmfile); - if( b==EOF ) break; - buf[i] = b; - if( b == '\n' ) break; - } - buf[i] = '\0'; -} - -static long mmftell(MMFILE *mmfile) -{ - return mmfile->pos; -} - -static void mmfseek(MMFILE *mmfile, long p, int whence) -{ - switch(whence) { - case SEEK_SET: - mmfile->pos = p; - break; - case SEEK_CUR: - mmfile->pos += p; - break; - case SEEK_END: - mmfile->pos = mmfile->sz + p; - break; - } -} -#endif - -// ===================================================================================== -static ABCEVENT *abc_new_event(ABCHANDLE *h, uint32_t abctick, const char data[]) -// ===================================================================================== -{ - ABCEVENT *retval; - int i; - - retval = (ABCEVENT *)_mm_calloc(h->trackhandle, 1,sizeof(ABCEVENT)); - retval->next = NULL; - retval->tracktick = abctick; - for( i=0; i<6; i++ ) - retval->par[i] = data[i]; - retval->part = global_part; - retval->tiednote = 0; - return retval; -} - -// ============================================================================= -static ABCEVENT *abc_copy_event(ABCHANDLE *h, ABCEVENT *se) -// ============================================================================= -{ - ABCEVENT *e; - e = (ABCEVENT *)_mm_calloc(h->trackhandle, 1,sizeof(ABCEVENT)); - e->next = NULL; - e->tracktick = se->tracktick; - e->flg = se->flg; - e->cmd = se->cmd; - e->lpar = se->lpar; - e->part = se->part; - return e; -} - -// ============================================================================= -static void abc_new_macro(ABCHANDLE *h, const char *m) -// ============================================================================= -{ - ABCMACRO *retval; - const char *p; - char buf[256],*q; - for( p=m; *p && isspace(*p); p++ ) ; - for( q=buf; *p && *p != '='; p++ ) - *q++ = *p; - if( q != buf ) - while( isspace(q[-1]) ) q--; - *q = '\0'; - retval = (ABCMACRO *)_mm_calloc(h->macrohandle, 1,sizeof(ABCTRACK)); - retval->name = DupStr(h->macrohandle, buf,strlen(buf)); - retval->n = strrchr(retval->name, 'n'); // for transposing macro's - for( p++; *p && isspace(*p); p++ ) ; - strncpy(buf,p,200); - for( q=&buf[strlen(buf)-1]; q!=buf && isspace(*q); q-- ) *q = '\0'; - retval->subst = DupStr(h->macrohandle, buf, strlen(buf)); - retval->next = h->macro; - h->macro = retval; -} - -// ============================================================================= -static void abc_new_umacro(ABCHANDLE *h, const char *m) -// ============================================================================= -{ - ABCMACRO *retval, *mp; - const char *p; - char buf[256], let[2], *q; - for( p=m; *p && isspace(*p); p++ ) ; - for( q=buf; *p && *p != '='; p++ ) - *q++ = *p; - if( q != buf ) - while( isspace(q[-1]) ) q--; - *q = '\0'; - if( strlen(buf) > 1 || strchr("~HIJKLMNOPQRSTUVWXY",toupper(buf[0])) == 0 || strchr("xy",buf[0]) ) return; - strcpy(let,buf); - for( p++; *p && isspace(*p); p++ ) ; - strncpy(buf,p,200); - for( q=&buf[strlen(buf)-1]; q!=buf && isspace(*q); q-- ) *q = '\0'; - for( q=buf; *q; q++ ) if( *q == '!' ) *q = '+'; // translate oldstyle to newstyle - if( !strcmp(buf,"+nil+") ) { // delete a macro - mp = NULL; - for( retval=h->umacro; retval; retval = retval->next ) { - if( retval->name[0] == let[0] ) { // delete this one - if( mp ) mp->next = retval->next; - else h->umacro = retval->next; - _mm_free(h->macrohandle, retval); - return; - } - mp = retval; - } - return; - } - retval = (ABCMACRO *)_mm_calloc(h->macrohandle, 1,sizeof(ABCTRACK)); - retval->name = DupStr(h->macrohandle, let,1); - retval->subst = DupStr(h->macrohandle, buf, strlen(buf)); - retval->n = 0; - retval->next = h->umacro; // by placing it up front we mask out the old macro until we +nil+ it - h->umacro = retval; -} - -// ============================================================================= -static ABCTRACK *abc_new_track(ABCHANDLE *h, const char *voice, int pos) -// ============================================================================= -{ - ABCTRACK *retval; - if( !pos ) global_voiceno++; - retval = (ABCTRACK *)_mm_calloc(h->trackhandle, 1,sizeof(ABCTRACK)); - retval->next = NULL; - retval->vno = global_voiceno; - retval->vpos = pos; - retval->tiedvpos = pos; - retval->instr = 1; - strncpy(retval->v, voice, 20); - retval->v[20] = '\0'; - retval->head = NULL; - retval->tail = NULL; - retval->capostart = NULL; - retval->tienote = NULL; - retval->mute = 0; - retval->chan = 0; - retval->transpose = 0; - retval->volume = h->track? h->track->volume: 120; - retval->slidevoltime = 0; - retval->slidevol = 0; - retval->legato = 0; - return retval; -} - -static int abc_numtracks(ABCHANDLE *h) -{ - int n; - ABCTRACK *t; - n=0; - for( t = h->track; t; t=t->next ) - n++; - return n; -} - -static int abc_interval(const char *s, const char *d) -{ - const char *p; - int i,j,k; - int n,oct,m[2]; - for( j=0; j<2; j++ ) { - if( j ) p = d; - else p = s; - switch(p[0]) { - case '^': - n = p[1]; - i = 2; - break; - case '_': - n = p[1]; - i = 2; - break; - case '=': - n = p[1]; - i = 2; - break; - default: - n = p[0]; - i = 1; - break; - } - for( k=0; k<25; k++ ) - if( n == sig[7][k] ) - break; - oct = 4; // ABC note pitch C is C4 and pitch c is C5 - if( k > 12 ) { - oct++; - k -= 12; - } - while( p[i] == ',' || p[i] == '\'' ) { - if( p[i] == ',' ) - oct--; - else - oct++; - i++; - } - m[j] = k + 12 * oct; - } - return m[0] - m[1]; -} - -static int abc_transpose(const char *v) -{ - int i,j,t; - const char *m = "B", *mv = ""; - t = 0; - global_octave_shift = 99; - for( ; *v && *v != ']'; v++ ) { - if( !strncasecmp(v,"t=",2) ) { - v+=2; - if( *v=='-' ) { - j = -1; - v++; - } - else j = 1; - v+=abc_getnumber(v,&i); - t += i * j; - global_octave_shift = 0; - } - if( !strncasecmp(v,"octave=",7) ) { - v+=7; - if( *v=='-' ) { - j = -1; - v++; - } - else j = 1; - v+=abc_getnumber(v,&i); - t += i * j * 12; - global_octave_shift = 0; - } - if( !strncasecmp(v,"transpose=",10) ) { - v+=10; - if( *v=='-' ) { - j = -1; - v++; - } - else j = 1; - v+=abc_getnumber(v,&i); - t += i * j; - global_octave_shift = 0; - } - if( !strncasecmp(v,"octave=",7) ) { // used in kv304*.abc - v+=7; - if( *v=='-' ) { - j = -1; - v++; - } - else j = 1; - v+=abc_getnumber(v,&i); - t += i * j * 12; - global_octave_shift = 0; - } - if( !strncasecmp(v,"m=",2) ) { - v += 2; - mv = v; // get the pitch for the middle staff line - while( *v && *v != ' ' && *v != ']' ) v++; - global_octave_shift = 0; - } - if( !strncasecmp(v,"middle=",7) ) { - v += 7; - mv = v; // get the pitch for the middle staff line - while( *v && *v != ' ' && *v != ']' ) v++; - global_octave_shift = 0; - } - if( !strncasecmp(v,"clef=",5) ) - v += 5; - j = 1; - if( !strncasecmp(v,"treble",6) ) { - j = 0; - v += 6; - switch( *v ) { - case '1': v++; m = "d"; break; - case '2': v++; - default: m = "B"; break; - case '3': v++; m = "G"; break; - case '4': v++; m = "E"; break; - case '5': v++; m = "C"; break; - } - global_octave_shift = 0; - } - if( j && !strncasecmp(v,"bass",4) ) { - m = "D,"; - j = 0; - v += 4; - switch( *v ) { - case '1': v++; m = "C"; break; - case '2': v++; m = "A,"; break; - case '3': v++; m = "F,"; break; - case '4': v++; - default: m = "D,"; break; - case '5': v++; m = "B,,"; break; - } - if( global_octave_shift == 99 ) - global_octave_shift = -2; - } - if( j && !strncasecmp(v,"tenor",5) ) { - j = 0; - v += 5; - switch( *v ) { - case '1': v++; m = "G"; break; - case '2': v++; m = "E"; break; - case '3': v++; m = "C"; break; - case '4': v++; - default: m = "A,"; break; - case '5': v++; m = "F,"; break; - } - if( global_octave_shift == 99 ) - global_octave_shift = 1; - } - if( j && !strncasecmp(v,"alto",4) ) { - j = 0; - v += 4; - switch( *v ) { - case '1': v++; m = "G"; break; - case '2': v++; m = "E"; break; - case '3': v++; - default: m = "C"; break; - case '4': v++; m = "A,"; break; - case '5': v++; m = "F,"; break; - } - if( global_octave_shift == 99 ) - global_octave_shift = 1; - } - if( j && strchr("+-",*v) && *v && v[1]=='8' ) { - switch(*v) { - case '+': - t += 12; - break; - case '-': - t -= 12; - break; - } - v += 2; - if( !strncasecmp(v,"va",2) ) v += 2; - global_octave_shift = 0; - j = 0; - } - if( j ) { - while( *v && *v != ' ' && *v != ']' ) v++; - } - } - if( strlen(mv) > 0 ) // someone set the middle note - t += abc_interval(mv, m); - if( global_octave_shift == 99 ) - global_octave_shift = 0; - return t; -} - -// ============================================================================= -static ABCTRACK *abc_locate_track(ABCHANDLE *h, const char *voice, int pos) -// ============================================================================= -{ - ABCTRACK *tr, *prev, *trunused; - char vc[21]; - int i, trans=0, voiceno=0, instrno = 1, channo = 0; - for( ; *voice == ' '; voice++ ) ; // skip leading spaces - for( i=0; *voice && *voice != ']' && *voice != '%' && !isspace(*voice); voice++ ) // can work with inline voice instructions - vc[i++] = *voice; - vc[i] = '\0'; - prev = NULL; - trunused = NULL; - if( !pos ) trans = abc_transpose(voice); - for( tr=h->track; tr; tr=tr->next ) { - if( tr->vno == 0 ) { - if( !trunused ) trunused = tr; // must reuse mastertrack (h->track) as first - } - else { - if( !strncasecmp(tr->v, vc, 20) ) { - if( tr->vpos == pos ) - return tr; - trans = tr->transpose; - global_octave_shift = tr->octave_shift; - voiceno = tr->vno; - instrno = tr->instr; - channo = tr->chan; - } - } - prev = tr; - } - if( trunused ) { - tr = trunused; - if( pos ) { - tr->vno = voiceno; - tr->instr = instrno; - tr->chan = channo; - } - else { - global_voiceno++; - tr->vno = global_voiceno; - tr->instr = 1; - tr->chan = 0; - } - tr->vpos = pos; - tr->tiedvpos = pos; - strncpy(tr->v, vc, 20); - tr->v[20] = '\0'; - tr->mute = 0; - tr->transpose = trans; - tr->octave_shift = global_octave_shift; - tr->volume = h->track->volume; - tr->tienote = NULL; - tr->legato = 0; - return tr; - } - tr = abc_new_track(h, vc, pos); - if( pos ) { - tr->vno = voiceno; - tr->instr = instrno; - tr->chan = channo; - } - tr->transpose = trans; - tr->octave_shift = global_octave_shift; - if( prev ) prev->next = tr; - else h->track = tr; - return tr; -} - -// ============================================================================= -static ABCTRACK *abc_check_track(ABCHANDLE *h, ABCTRACK *tp) -// ============================================================================= -{ - if( !tp ) { - tp = abc_locate_track(h, "", 0); // must work for voiceless abc too... - tp->transpose = h->ktrans; - } - return tp; -} - -static void abc_add_capo(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime) -{ - ABCEVENT *e; - char d[6]; - d[0] = d[1] = d[2] = d[3] = d[4] = d[5] = 0; - d[cmdflag] = 1; - d[command] = cmdcapo; - e = abc_new_event(h, tracktime, d); - tp->capostart = e; - abc_add_event(h, tp, e); // do this last (recursion danger) -} - -static void abc_add_segno(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime) -{ - ABCEVENT *e; - char d[6]; - d[0] = d[1] = d[2] = d[3] = d[4] = d[5] = 0; - d[cmdflag] = 1; - d[command] = cmdsegno; - e = abc_new_event(h, tracktime, d); - abc_add_event(h, tp, e); -} - -static void abc_add_coda(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime) -{ - ABCEVENT *e; - char d[6]; - d[0] = d[1] = d[2] = d[3] = d[4] = d[5] = 0; - d[cmdflag] = 1; - d[command] = cmdcoda; - e = abc_new_event(h, tracktime, d); - abc_add_event(h, tp, e); -} - -static void abc_add_fine(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime) -{ - ABCEVENT *e; - char d[6]; - d[0] = d[1] = d[2] = d[3] = d[4] = d[5] = 0; - d[cmdflag] = 1; - d[command] = cmdfine; - e = abc_new_event(h, tracktime, d); - abc_add_event(h, tp, e); -} - -static void abc_add_tocoda(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime) -{ - ABCEVENT *e; - char d[6]; - d[0] = d[1] = d[2] = d[3] = d[4] = d[5] = 0; - d[cmdflag] = 1; - d[command] = cmdtocoda; - e = abc_new_event(h, tracktime, d); - abc_add_event(h, tp, e); -} - -// first track is dirigent, remove all control events from other tracks -// to keep the information where the events should be relative to note events -// in the same tick the ticks are octated and four added for note events -// the control events that come before the note events get a decremented tick, -// those that come after get an incremented tick, for example: -// ctrl ctrl note ctrl ctrl note -// original: t t t t t+1 t+1 -// recoded: 8t+1 8t+2 8t+4 8t+5 8t+11 8t+12 -static void abc_remove_unnecessary_events(ABCHANDLE *h) -{ - ABCTRACK *tp,*ptp; - ABCEVENT *ep, *el; - uint32_t ct, et; - int d; - ptp = NULL; - for( tp=h->track; tp; tp=tp->next ) { - el = NULL; - ep = tp->head; - ct = 0; - d = -3; - while( ep ) { - et = ep->tracktick; - ep->tracktick <<= 3; - ep->tracktick += 4; - if( ep->flg == 1 ) { - ep->tracktick += d; - d++; - if( d == 0 ) d = -1; - if( d == 4 ) d = 3; - if( tp!=h->track ) ep->cmd = cmdhide; - switch( ep->cmd ) { - case cmdhide: - case cmdsync: - if( el ) { - el->next = ep->next; - _mm_free(h->trackhandle,ep); - ep = el->next; - } - else { - tp->head = ep->next; - _mm_free(h->trackhandle,ep); - ep = tp->head; - } - break; - default: - el = ep; - ep = ep->next; - break; - } - } - else { - el = ep; - ep = ep->next; - d = 1; - } - if( et > ct ) - d = -3; - ct = et; - } - if( !tp->head ) { // no need to keep empty tracks... - if( ptp ) { - ptp->next = tp->next; - _mm_free(h->trackhandle,tp); - tp = ptp; - } - else { - h->track = tp->next; - _mm_free(h->trackhandle,tp); - tp = h->track; - } - } - ptp = tp; // remember previous track - } -} - -// set ticks back, and handle partbreaks -static void abc_retick_events(ABCHANDLE *h) -{ - ABCTRACK *tp; - ABCEVENT *ep; - uint32_t et, tt=0, at = abcticks(64 * h->speed); - for( tp=h->track; tp; tp=tp->next ) { - // make ticks relative - tt = 0; - for( ep=tp->head; ep; ep=ep->next ) { - et = ep->tracktick >> 3; - ep->tracktick = et - tt; - tt = et; - } - // make ticks absolute again, skipping no-op partbreaks - tt = 0; - for( ep=tp->head; ep; ep=ep->next ) { - ep->tracktick += tt; - tt = ep->tracktick; - if( ep->flg == 1 && ep->cmd == cmdpartbrk ) { - if( tt % at ) { - tt += at; - tt /= at; - tt *= at; - ep->tracktick -= abcticks(h->speed); // break plays current row - } - else ep->cmd = cmdhide; - } - } - } -} - -// make sure every track has the control events it needs, this way it is not -// necessary to have redundant +segno+ +D.C.+ etc in the voices, the first voice -// is the master, it is pointed to by the member 'track' in the ABCHANDLE -static void abc_synchronise_tracks(ABCHANDLE *h) -{ - ABCTRACK *tp; - uint32_t tm; // tracktime in master - ABCEVENT *em, *es, *et, *ec; // events in master, slave, slave temporary and copied event - if( !h || !h->track ) return; - abc_remove_unnecessary_events(h); - for( tp = h->track->next; tp; tp = tp->next ) { - for( em=h->track->head; em; em=em->next ) { - if( em->flg == 1 ) { // some kind of control event - switch( em->cmd ) { - case cmdchord: - case cmdhide: - case cmdtempo: - case cmdsync: - break; - default: // check to see if copy is necessary - ec = abc_copy_event(h, em); - tm = em->tracktick; - es = tp->head; // allways search from the begin... - for( et=es; et && et->tracktick <= tm; et=et->next ) - es = et; - if( es == NULL || es->tracktick > tm ) { // special case: head of track - ec->next = es; - tp->head = ec; - } - else { - ec->next = es->next; - es->next = ec; - } - break; - } - } - } - } - abc_retick_events(h); -} - -static void abc_add_event(ABCHANDLE *h, ABCTRACK *tp, ABCEVENT *e) -{ - if( !tp->capostart ) abc_add_capo(h, tp, global_songstart); - if( tp->tail ) { - tp->tail->next = e; - tp->tail = e; - } - else { - tp->head = e; - tp->tail = e; - } -} - -static void abc_add_partbreak(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime) -{ - ABCEVENT *e; - char d[6]; - d[0] = d[1] = d[2] = d[3] = d[4] = d[5] = 0; - d[cmdflag] = 1; - d[command] = cmdpartbrk; - e = abc_new_event(h, tracktime, d); - abc_add_event(h, tp, e); -} - -static void abc_add_tempo_event(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime, int tempo) -{ - ABCEVENT *e; - char d[6]; - d[0] = d[1] = d[2] = d[3] = d[4] = d[5] = 0; - d[cmdflag] = 1; - d[command] = cmdtempo; - e = abc_new_event(h, tracktime, d); - e->lpar = tempo; - abc_add_event(h, tp, e); -} - -static void abc_add_noteoff(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime) -{ - ABCEVENT *e; - char d[6]; - d[note] = 0; - d[octave] = 0; - d[smpno] = pat_gmtosmp(tp->instr); - d[volume] = 0; - d[effect] = 0; - d[effoper] = 0; - e = abc_new_event(h, tracktime, d); - abc_add_event(h, tp, e); -} - -static int abc_dynamic_volume(ABCTRACK *tp, uint32_t tracktime, int vol) -{ - uint32_t slidetime; - int voldelta; - if( tp->mute ) return 0; - if( tp->slidevol == 0 ) return vol; - if( tracktime < tp->slidevoltime ) return vol; - slidetime = modticks(tracktime - tp->slidevoltime); - voldelta = (slidetime * 15) / 64 / 6; // slide from say mf up to f in one pattern's time - if( tp->slidevol > -2 && voldelta > 15 ) voldelta = 15; // never to much dynamics - if( tp->slidevol > 0 ) vol += voldelta; - else vol -= voldelta; - if( vol < 2 ) vol = 2; // xmms divides this by 2.... - if( vol > 127 ) vol = 127; - return vol; -} - -static void abc_track_untie_short_chordnotes(ABCHANDLE *h) -{ - ABCTRACK *tp; - int vn; - tp = h->tp; - vn = tp->vno; - for( tp = h->track; tp; tp = tp->next ) - if( tp != h->tp && tp->vno == vn && tp->tienote ) { - abc_message("short notes in chord can not be tied:\n%s", h->line); - tp->tienote = 0; - } -} - -static void abc_track_clear_tiednote(ABCHANDLE *h) -{ - ABCTRACK *tp; - int vn; - tp = h->tp; - vn = tp->vno; - for( tp = h->track; tp; tp = tp->next ) - if( tp->vno == vn ) tp->tienote = 0; -} - -static void abc_track_clear_tiedvpos(ABCHANDLE *h) -{ - ABCTRACK *tp; - int vn; - tp = h->tp; - vn = tp->vno; - for( tp = h->track; tp; tp = tp->next ) - if( tp->vno == vn ) tp->tiedvpos = tp->vpos; -} - -static ABCTRACK *abc_track_with_note_tied(ABCHANDLE *h, uint32_t tracktime, int n, int oct) -{ - int vn, vp; - ABCTRACK *tp; - ABCEVENT *e; - tp = h->tp; - vn = tp->vno; - vp = tp->vpos; - for( tp = h->track; tp; tp = tp->next ) { - if( tp->vno == vn ) { - e = tp->tienote; - if( e && e->tracktick < tracktime - && e->par[octave] == oct && abs(e->par[note] - n) < 3 ) { - if( tp->vpos != vp ) tp->tiedvpos = vp; - h->tp = tp; - return tp; - } - } - } - tp = h->tp; - vp = tp->tiedvpos; - if( tp->vpos != vp ) { - // chord note track allready returned in previous call - for( tp = h->track; tp; tp = tp->next ) { - if( tp->vno == vn && tp->vpos == vp ) { - tp->tiedvpos = h->tp->vpos; - h->tp = tp; - return tp; - } - } - } - return h->tp; -} - -static int abc_add_noteon(ABCHANDLE *h, int ch, const char *p, uint32_t tracktime, char *barkey, int vol, ABCEVENT_X_EFFECT fx, int fxop) -{ - ABCEVENT *e; - ABCTRACK *tp; - int i,j,k; - int n,oct; - char d[6]; - tp = h->tp; - switch(ch) { - case '^': - if( p[0] == '^' ) { - n = p[1]; - i = 2; - ch = 'x'; - } - else { - n = p[0]; - i = 1; - } - break; - case '_': - if( p[0] == '_' ) { - n = p[1]; - i = 2; - ch = 'b'; - } - else { - n = p[0]; - i = 1; - } - break; - case '=': - n = p[0]; - i = 1; - break; - default: - n = ch; - i = 0; - break; - } - for( k=0; k<51; k++ ) { - if( n == barkey[k] ) - break; - } - j = k; - if( k > 24 ) - k -= 25; // had something like A# over Bb key F signature.... - if( i ) { - // propagate accidentals if necessary - // DON'T do redundant accidentals they're always relative to C-scale - for( k=0; k<25; k++ ) { - if( n == sig[7][k] ) - break; - } - if( k < 25 ) { // only do real notes... - switch(ch) { - case 'x': - k++; - case '^': - k++; - break; - case 'b': - k--; - case '_': - k--; - break; - case '=': - break; - } - if( j < 25 ) // was it not A# over Bb? - barkey[j] = ' '; - barkey[k] = n; - } - } - oct = 3; // ABC note pitch C is C4 and pitch c is C5 - if( k < 25 ) { - k += tp->transpose; - while( k > 12 ) { - oct++; - k -= 12; - } - while( k < 0 ) { - oct--; - k += 12; - } - d[note] = 23 + k; // C0 is midi notenumber 24 - } - else - d[note] = 0; // someone has doen ^X3 or something like it... - while( p[i] && strchr(",'",p[i]) ) { - if( p[i]==',' ) oct--; - else oct++; - i++; - tp->octave_shift = 0; // forget we ever had to look at it - } - if( tp->octave_shift ) - tp->transpose += 12 * tp->octave_shift; - oct += tp->octave_shift; - tp->octave_shift = 0; // after the first note we never have to look at it again - if( oct < 0 ) oct = 0; - if( oct > 9 ) oct = 9; - d[octave] = oct; - d[smpno] = pat_gmtosmp(tp->instr); - d[volume] = abc_dynamic_volume(tp, tracktime, vol); - d[effect] = fx; // effect - d[effoper] = fxop; - tp = abc_track_with_note_tied(h, tracktime, d[note], oct); - if( tp->tienote ) { - if( tp->tienote->par[note] != d[note] ) { - if( abs(tp->tienote->par[note] - d[note]) < 3 ) { - // may be tied over bar symbol, recover local accidental to barkey - k = tp->tienote->par[note] - 23 - tp->transpose; - while( k < 0 ) k += 12; - while( k > 12 ) k -= 12; - if( (isupper(n) && barkey[k+12] == ' ') || (islower(n) && barkey[k] == ' ') ) { - barkey[j] = ' '; - if( isupper(n) ) - barkey[k] = n; - else - barkey[k+12] = n; - d[note] = tp->tienote->par[note]; - d[octave] = tp->tienote->par[octave]; - } - } - } - } - if( tp->tienote - && tp->tienote->par[note] == d[note] - && tp->tienote->par[octave] == d[octave] ) { - for( e = tp->tienote; e; e = e->next ) { - if( e->par[note] == 0 && e->par[octave] == 0 ) { // undo noteoff - e->flg = 1; - e->cmd = cmdhide; - e->lpar = 0; - break; - } - } - tp->tienote->tiednote = 1; // mark him for the pattern writers - for( j=i; isdigit(p[j]) || p[j]=='/'; j++ ) ; // look ahead to see if this one is tied too - if( p[j] != '-' ) // is this note tied too? - tp->tienote = NULL; // if not the tie ends here... - return i; - } - tp->tienote = NULL; - if( tp->tail - && tp->tail->tracktick == tracktime - && tp->tail->par[note] == 0 - && tp->tail->par[octave] == 0 ) { - for( j=0; j<6; j++ ) - tp->tail->par[j] = d[j]; - } - else { - e = abc_new_event(h, tracktime, d); - abc_add_event(h, tp, e); - } - if( i > 0 && p[i-1] == '"' ) { - i--; // someone coded a weird note like ^"E" - abc_message("strange note encountered scanning %s", h->line); - } - return i; -} - -static void abc_add_dronenote(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime, int nnum, int vol) -{ - ABCEVENT *e; - int j,k; - int oct; - char d[6]; - oct = -1; // ABC note pitch C is C4 and pitch c is C5 - k = nnum + 1; - while( k > 12 ) { - oct++; - k -= 12; - } - while( k < 0 ) { - oct--; - k += 12; - } - if( oct < 0 ) oct = 0; - d[note] = 23 + k; // C0 is midi notenumber 24 - d[octave] = oct; - d[smpno] = pat_gmtosmp(tp->instr); - d[volume] = abc_dynamic_volume(tp, tracktime, vol); - d[effect] = 0; // effect - d[effoper] = 0; - if( tp->tail - && tp->tail->tracktick == tracktime - && tp->tail->par[note] == 0 - && tp->tail->par[octave] == 0 ) { - for( j=0; j<6; j++ ) - tp->tail->par[j] = d[j]; - } - else { - e = abc_new_event(h, tracktime, d); - abc_add_event(h, tp, e); - } -} - -static void abc_add_chordnote(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime, int nnum, int vol) -{ - abc_add_dronenote(h, tp, tracktime, nnum + 23, tp->mute? 0: vol); -} - -static void abc_add_drumnote(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime, int nnum, int vol) -{ - abc_add_dronenote(h, tp, tracktime, nnum, tp->mute? 0: vol); -} - -static void abc_add_variant_start(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime, int n) -{ - ABCEVENT *e; - char d[6]; - d[0] = d[1] = d[2] = d[3] = d[4] = d[5] = 0; - d[cmdflag] = 1; - d[command] = cmdvariant; - e = abc_new_event(h, tracktime, d); - e->lpar = 1<<n; - abc_add_event(h, tp, e); -} - -static void abc_add_variant_choise(ABCTRACK *tp, int n) -{ - tp->tail->lpar |= 1<<n; -} - -static void abc_add_chord(const char *p, ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime) -{ - ABCEVENT *e; - char d[6]; - char s[8]; - int i; - const char *n = " C D EF G A Bc d ef g a b"; - d[0] = d[1] = d[2] = d[3] = d[4] = d[5] = 0; - d[cmdflag] = 1; - d[command] = cmdchord; - if( p[0] == '(' ) p++; // chord between parens like: (C) - for( i=0; n[i]; i++ ) - if( *p == n[i] ) { - d[chordnote] = i; - break; - } - p++; - switch(*p) { - case 'b': - d[chordnote]--; - p++; - break; - case '#': - d[chordnote]++; - p++; - break; - } - d[chordbase] = d[chordnote]; - for( i=0; p[i] && p[i] != '"' && p[i] != '/' && p[i] != '(' && p[i] != ')' && p[i] != ' '; i++ ) s[i] = p[i]; - s[i] = '\0'; - p = &p[i]; - if( *p=='/' ) { - p++; - for( i=0; n[i]; i++ ) - if( *p == n[i] ) { - d[chordbase] = i; - break; - } - p++; - switch(*p) { - case 'b': - d[chordbase]--; - p++; - break; - case '#': - d[chordbase]++; - p++; - break; - } - } - for( i=0; i<chordsnamed; i++ ) - if( !strcmp(s, chordname[i]) ) { - d[chordnum] = i; - break; - } - if( i==chordsnamed ) { - abc_message("Failure: unrecognized chordname %s",s); - return; - } - e = abc_new_event(h, tracktime, d); - abc_add_event(h, tp, e); -} - -static void abc_add_setloop(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime) -{ - ABCEVENT *e; - char d[6]; - d[0] = d[1] = d[2] = d[3] = d[4] = d[5] = 0; - d[cmdflag] = 1; - d[command] = cmdloop; - e = abc_new_event(h, tracktime, d); - abc_add_event(h, tp, e); -} - -static void abc_fade_track(ABCTRACK *tp, ABCEVENT *e) -{ - while(e) { - if( e->flg != 1 && e->par[note] != 0 ) - e->par[volume] = abc_dynamic_volume(tp, e->tracktick, e->par[volume]); - e = e->next; - } -} - -static void abc_add_setjumploop(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime, ABCEVENT_JUMPTYPE j) -{ - ABCEVENT *e; - char d[8]; - d[0] = d[1] = d[2] = d[3] = d[4] = d[5] = 0; - d[cmdflag] = 1; - d[command] = cmdjump; - d[jumptype] = j; - e = abc_new_event(h, tracktime, d); - abc_add_event(h, tp, e); -} - -static void abc_add_sync(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime) -{ - ABCEVENT *e; - char d[6]; - e = tp->tail; - if( e && e->tracktick == tracktime ) return; - if( e && e->flg == 1 && e->cmd == cmdsync ) { - e->tracktick = tracktime; - return; - } - d[0] = d[1] = d[2] = d[3] = d[4] = d[5] = 0; - d[cmdflag] = 1; - d[command] = cmdsync; - e = abc_new_event(h, tracktime, d); - abc_add_event(h, tp, e); -} - -static void abc_add_gchord_syncs(ABCHANDLE *h, ABCTRACK *tpc, uint32_t tracktime) -{ - ABCTRACK *tp; - int i; - for( i = GCHORDBPOS; i < DRUMPOS; i++ ) { - tp = abc_locate_track(h, tpc->v, i); - abc_add_sync(h,tp,tracktime); - } -} - -static void abc_add_drum_sync(ABCHANDLE *h, ABCTRACK *tpr, uint32_t tracktime) -{ - ABCTRACK *tp; - tp = abc_locate_track(h, tpr->v, DRUMPOS); - abc_add_sync(h,tp,tracktime); -} - -static int abc_getnumber(const char *p, int *number) -{ - int i,h; - i = 0; - h = 0; - while( isdigit(p[i]) ) { - h = 10 * h + p[i] - '0'; - i++; - } - if( i==0 ) - *number = 1; - else - *number = h; - return i; -} - -static int abc_getexpr(const char *p, int *number) -{ - int i, term, total; - i = 0; - while( isspace(p[i]) ) - i++; - if( p[i] == '(' ) { - i += abc_getexpr(p+i+1, number); - while( p[i] && (p[i] != ')') ) - i++; - return i; - } - i += abc_getnumber(p+i, &total); - while( isspace(p[i]) ) - i++; - while( p[i] == '+' ) { - i += abc_getexpr(p+i+1, &term); - total += term; - while( isspace(p[i]) ) - i++; - } - *number = total; - return i; -} - -static int abc_notelen(const char *p, int *len, int *div) -{ - int i,h,k; - i = abc_getnumber(p,len); - h = 1; - while( p[i] == '/' ) { - h *= 2; - i++; - } - if( isdigit(p[i]) ) { - h /= 2; - i += abc_getnumber(p+i,&k); - } - else k = 1; - *div = h * k; - return i; -} - -static int abc_brokenrithm(const char *p, int *nl, int *nd, int *b, int hornpipe) -{ - switch( *b ) { - case '<': - *nl *= 3; - *nd *= 2; - hornpipe = 0; - break; - case '>': - *nd *= 2; - hornpipe = 0; - break; - } - *b = *p; - switch( *b ) { - case '>': - *nl *= 3; - *nd *= 2; - return 1; - case '<': - *nd *= 2; - return 1; - default: - *b = 0; - break; - } - if( hornpipe ) { // still true then make 1/8 notes broken rithme - if( *nl == 1 && *nd == 1 ) { - *b = '>'; - *nl = 3; - *nd = 2; - } - } - return 0; -} - -// put p notes in the time q for the next r notes -static int abc_tuplet(int *nl, int *nd, int p, int q, int r) -{ - if( !r ) return 0; - *nl *= q; - *nd *= p; - return r - 1; -} - -// evaluate [Q:"string" n1/m1 n2/m2 n3/m3 n4/m4=bpm "string"] -// minimal form [Q:"string"] -// most used form [Q: 1/4=120] -static int abc_extract_tempo(const char *p, int invoice) -{ - int nl, nd, ns, in, tempo; - int nl1=0, nd1, notes, state; - const char *q; - in = 0; - nl = 0; - nd = 1; - ns = 120; - notes = 0; - state = 0; - for( q=p; *q; q++ ) { - if( in ) { - if( *q=='"' ) - in = 0; - } - else { - if( *q == ']' ) break; - switch( *q ) { - case '"': - in = 1; - break; - case '/': - notes++; - state = 1; - nl1 = ns; - break; - case '=': - break; - default: - if( isdigit(*q) ) { - if( state ) { - q+=abc_getnumber(q,&nd1)-1; - state = 0; - nl = nl * nd1 + nl1 * nd; - nd = nd * nd1; - } - else - q+=abc_getnumber(q,&ns)-1; - } - break; - } - } - } - if( !notes ) { - nl = 1; - nd = 4; - } - if( !nd ) tempo = 120; - else tempo = ns * nl * 4 / nd; // mod tempo is really BPM where one B is equal to a quartnote - if( invoice ) { - nl = global_tempo_factor; - nd = global_tempo_divider; - } - global_tempo_factor = 1; - global_tempo_divider = 1; - while( tempo/global_tempo_divider > 255 ) - global_tempo_divider++; - tempo /= global_tempo_divider; - while( tempo * global_tempo_factor < 256 ) - global_tempo_factor++; - global_tempo_factor--; - tempo *= global_tempo_factor; - if( tempo * 3 < 512 ) { - global_tempo_factor *= 3; - global_tempo_divider *= 2; - tempo = (tempo * 3) / 2; - } - if( invoice ) { - if( nl != global_tempo_factor || nd != global_tempo_divider ) { - ns = (tempo * nl * global_tempo_divider) / (nd * global_tempo_factor); - if( ns > 31 && ns < 256 ) { - tempo = ns; - global_tempo_factor = nl; - global_tempo_divider = nd; - } - else - abc_message("Failure: inconvenient tempo change in middle of voice (%s)", p); - } - } - return tempo; -} - -static void abc_set_parts(char **d, char *p) -{ - int i,j,k,m,n; - char *q; -#ifdef NEWMIKMOD - static MM_ALLOC *h; - if( *d ) _mmalloc_close(h); -#else - if( *d ) free(*d); -#endif - *d = 0; - if( !p ) return; - for( i=0; p[i] && p[i] != '%'; i++ ) { - if( !strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ().0123456789 ",p[i]) ) { - abc_message("invalid characters in part string scanning P:%s", p); - return; - } - } -#ifdef NEWMIKMOD - h = _mmalloc_create("Load_ABC_parts", NULL); -#endif - // decode constructs like "((AB)2.(CD)2)3.(AB)E2" to "ABABCDCDABABCDCDABABCDCDABEE" - // first compute needed storage... - j=0; - k=0; - for( i=0; p[i] && p[i] != '%'; i++ ) { - if( isupper(p[i]) ) { - j++; - } - if( isdigit(p[i]) ) { - n=abc_getnumber(p+i,&k); - if( p[i-1] == ')' ) - j *= k; // never mind multiple parens, just take the worst case - else - j += k-1; - i += n-1; - } - } - q = (char *)_mm_calloc(h, j+1, sizeof(char)); // enough storage for the worst case - // now copy bytes from p to *d, taking parens and digits in account - j = 0; - for( i=0; p[i] && p[i] != '%'; i++ ) { - if( isdigit(p[i]) || isupper(p[i]) || p[i] == '(' || p[i] == ')' ) { - if( p[i] == ')' ) { - for( n=j; n > 0 && q[n-1] != '('; n-- ) ; // find open paren in q - // q[n+1] to q[j] contains the substring that must be repeated - if( n > 0 ) { - for( k = n; k<j; k++ ) q[k-1] = q[k]; // shift to the left... - j--; - } - else - abc_message("Warning: Unbalanced right parens in P: definition %s",p); - n = j - n + 1; // number of repeatable characters - i += abc_getnumber(p+i+1,&k); - while( k-- > 1 ) { - for( m=0; m<n; m++ ) { - q[j] = q[j-n]; - j++; - } - } - continue; - } - if( isdigit(p[i]) ) { - n = abc_getnumber(p+i,&k); - i += n - 1; - while( k-- > 1 ) { - q[j] = q[j-1]; - j++; - } - continue; - } - q[j] = p[i]; - j++; - } - } - q[j] = '\0'; - // remove any left over parens - for( i=0; i<j; i++ ) { - if( q[i] == '(' ) { - abc_message("Warning: Unbalanced left parens in P: definition %s",p); - for( k=i; k<j; k++ ) q[k] = q[k+1]; - j--; - } - } - *d = q; -} - -static void abc_appendpart(ABCHANDLE *h, ABCTRACK *tp, uint32_t pt1, uint32_t pt2) -{ - ABCEVENT *e, *ec; - uint32_t dt; - dt = tp->tail->tracktick - pt1; - for( e=tp->head; e && e->tracktick <= pt2; e=e->next ) { - if( e->tracktick >= pt1 ) { - if( e->flg != 1 || e->cmd == cmdsync || e->cmd == cmdchord ) { - if( e != tp->tail ) { - // copy this event at tail - ec = abc_copy_event(h,e); - ec->tracktick += dt; - ec->part = '*'; - tp->tail->next = ec; - tp->tail = ec; - } - } - } - } - abc_add_sync(h, tp, pt2 + dt); // make sure there is progression... -} - -static uint32_t abc_pattracktime(ABCHANDLE *h, uint32_t tracktime) -{ - ABCEVENT *e; - uint32_t dt,et,pt=abcticks(64 * h->speed); - if(!h || !h->track || !h->track->head ) return 0; - dt = 0; - for( e=h->track->head; e && e->tracktick <= tracktime; e=e->next ) { - if( e->flg == 1 && e->cmd == cmdpartbrk ) { - et = e->tracktick + dt; - if( et % pt ) { - et += pt; - et /= pt; - et *= pt; - dt = et - e->tracktick; - } - } - } - return (tracktime + dt); -} - -static int abc_patno(ABCHANDLE *h, uint32_t tracktime) -{ - return modticks(abc_pattracktime(h, tracktime)) / 64 / h->speed; -} - -static void abc_stripoff(ABCHANDLE *h, ABCTRACK *tp, uint32_t tt) -{ - ABCEVENT *e1, *e2; - e2 = NULL; - for( e1 = tp->head; e1 && e1->tracktick <= tt; e1=e1->next ) - e2 = e1; - if( e2 ) { - e1 = e2->next; - tp->tail = e2; - e2->next = NULL; - } - else { - e1 = tp->tail; - tp->head = NULL; - tp->tail = NULL; - } - while( e1 ) { - e2 = e1->next; - _mm_free(h->trackhandle,e1); - e1 = e2; - } -} - -static void abc_keeptiednotes(ABCHANDLE *h, uint32_t fromtime, uint32_t totime) { - ABCTRACK *tp; - ABCEVENT *e,*n,*f; - if( totime <= fromtime ) return; - for( tp=h->track; tp; tp=tp->next ) { - if( tp->vno ) { // if track is in use... - n = NULL; - for( e=tp->head; e && e->tracktick < fromtime; e = e->next ) - if( e->flg != 1 ) n = e; // remember it when it is a note event - if( n && n->tiednote ) { // we've a candidate to tie over the break - while( e && e->tracktick < totime ) e=e->next; // skip to other part - if( e && e->tracktick == totime ) { // if this is on begin row of this part - f = NULL; - while( !f && e && e->tracktick == totime ) { - if( e->flg != 1 ) f = e; - e = e->next; - } - if( f && f->par[note] ) { // pfoeie, we've found a candidate - if( abs(n->par[note] - f->par[note]) < 3 ) { // undo the note on - f->flg = 1; - f->cmd = cmdhide; - f->lpar = 0; - } - } - } - } - } - } -} - -static uint32_t abc_fade_tracks(ABCHANDLE *h, char *abcparts, uint32_t ptt[27]) -{ - ABCTRACK *tp; - ABCEVENT *e0; - char *p; - int vol; - uint32_t pt1, pt2; - uint32_t tt; - tt = h->track->tail->tracktick; - for( tp=h->track->next; tp; tp=tp->next ) { - if( !tp->tail ) abc_add_sync(h, tp, tt); // no empty tracks please... - if( tp->tail->tracktick > tt ) abc_stripoff(h, tp, tt); // should not happen.... - if( tp->tail->tracktick < tt ) abc_add_sync(h, tp, tt); - } - for( tp=h->track; tp; tp=tp->next ) { - vol = 127; - e0 = tp->tail; - if( tp->slidevol != -2 ) { - tp->slidevol = -2; - tp->slidevoltime = e0->tracktick; - } - tp->mute = 0; // unmute track for safety, notes in a muted track already have zero volume... - while( vol > 5 ) { - for( p=abcparts; *p && vol > 5; p++ ) { - pt1 = ptt[*p-'A']; - pt2 = ptt[*p-'A'+1]; - abc_appendpart(h, tp, pt1, pt2); - vol = abc_dynamic_volume(tp, tp->tail->tracktick, 127); - } - } - abc_fade_track(tp,e0); - } - return h->track->tail->tracktick; -} - -static void abc_song_to_parts(ABCHANDLE *h, char **abcparts, BYTE partp[27][2]) -{ - uint32_t starttick; - ABCEVENT *e; - int i, fading, loop, normal, partno, partsegno, partloop, partcoda, parttocoda, partfine, skip, x, y; - int vmask[27],nextp[27]; - uint32_t ptt[27]; - char buf[256]; // must be enough, mod's cannot handle more than 240 patterns - char *pfade; - if( !h || !h->track || !h->track->capostart ) return; - strcpy(buf,"A"); // initialize our temporary array - i = 1; - loop = 1; - partno = 0; - partsegno = 0; - partloop = 0; - partcoda = -1; - parttocoda = -1; - partfine = -1; - starttick = h->track->capostart->tracktick; - ptt[0] = starttick; - vmask[0] = -1; - nextp[0] = 1; - for( e=h->track->capostart; e; e=e->next ) { - if( e->flg == 1 ) { - switch( e->cmd ) { - case cmdpartbrk: - if( e->tracktick > starttick) { - starttick = e->tracktick; // do not make empty parts - if( partno < 26 ) { - partno++; - ptt[partno] = starttick; - } - if( i < 255 ) buf[i++] = partno+'A'; - vmask[partno] = -1; - nextp[partno] = partno+1; - } - break; - case cmdloop: - partloop = partno; - loop = 1; // start counting anew... - break; - case cmdvariant: - vmask[partno] = e->lpar; - break; - case cmdjump: - x = 0; - fading = 0; - normal = 0; - skip = 0; - pfade = &buf[i]; - switch( e->par[jumptype] ) { - case jumpfade: - fading = 1; - case jumpnormal: - normal = 1; - x = partloop; - loop++; - break; - case jumpdsfade: - fading = 1; - case jumpdasegno: - x = partsegno; - break; - case jumpdcfade: - fading = 1; - case jumpdacapo: - x = 0; - break; - default: - x = 0; - break; - } - if( vmask[partno] != -1 ) nextp[partno] = x; - if( partno < 26 ) ptt[partno+1] = e->tracktick; // for handling ties over breaks - while( x <= partno ) { - if( skip == 1 && x == partcoda ) skip = 0; - y = !skip; - if( y ) { - if( !normal ) { - if( x == partfine ) skip = 2; - if( x == parttocoda ) skip = 1; - y = !skip; - } - if( !(vmask[x] & (1<<loop)) ) y = 0; - } - if( y ) { - if( i < 255 ) buf[i++] = x+'A'; - if( nextp[x] != x + 1 ) loop++; - x = nextp[x]; - } - else - x++; - } - if( fading && partno < 26 && i < 255 ) { // add single part with fading tracks - partno++; - ptt[partno] = e->tracktick; - buf[i] = '\0'; // close up pfade with zero byte - starttick = abc_fade_tracks(h, pfade, ptt); - buf[i++] = partno+'A'; - partno++; - ptt[partno] = starttick; - buf[i++] = partno+'A'; // one extra to throw away... - e = h->track->tail; // this is the edge of the world captain... - } - break; - case cmdtocoda: - parttocoda = partno; - break; - case cmdcoda: - partcoda = partno; - break; - case cmdfine: - partfine = partno; - break; - case cmdsegno: - partsegno = partno; - break; - } - } - e->part = partno+'a'; // small caps for generated parts... - } - i--; // strip off last partno - if( partno > 0 ) partno--; - buf[i] = '\0'; - if( i > 1 ) { - for( i=1; buf[i]; i++ ) { - if( buf[i] != buf[i-1] + 1 ) { - x = buf[i-1] - 'A'; - y = buf[i] - 'A'; - abc_keeptiednotes(h, ptt[x+1], ptt[y]); - } - } - } - starttick = h->track->tail->tracktick; - ptt[partno+1] = starttick; - for( i=0; i<=partno; i++ ) { - partp[i][0] = abc_patno(h, ptt[i]); - partp[i][1] = abc_patno(h, ptt[i+1]); - } - // calculate end point of last part - starttick = abc_pattracktime(h, starttick); - if( starttick % abcticks(64 * h->speed) ) - partp[partno][1]++; - abc_set_parts(abcparts, buf); -} - -// ===================================================================================== -static char *abc_fgets(MMFILE *mmfile, char buf[], unsigned int bufsz) -// ===================================================================================== -{ - if( mmfeof(mmfile) ) return NULL; - mmfgets(buf,bufsz,mmfile); - return buf; -} - -// ===================================================================================== -static char *abc_fgetbytes(MMFILE *mmfile, char buf[], unsigned int bufsz) -// ===================================================================================== -{ - unsigned int i; - long pos; - if( mmfeof(mmfile) ) return NULL; - for( i=0; i<bufsz-2; i++ ) { - buf[i] = (char)mmfgetc(mmfile); - if( buf[i] == '\n' ) break; - if( buf[i] == '\r' ) { - pos = mmftell(mmfile); - if( mmfgetc(mmfile) != '\n' ) mmfseek(mmfile, pos, SEEK_SET); - buf[i] = '\n'; - break; - } - } - if( buf[i] == '\n' ) i++; - buf[i] = '\0'; - return buf; -} - -static void abc_substitute(ABCHANDLE *h, char *target, char *s) -{ - char *p, *q; - int i; - int l = strlen(target); - int n = strlen(s); - while( (p=strstr(h->line, target)) ) { - if( (i=strlen(h->line)) + n - l >= (int)h->len ) { - h->line = (char *)_mm_recalloc(h->allochandle, h->line, h->len<<1, sizeof(char)); - h->len <<= 1; - p=strstr(h->line, target); - } - if( n > l ) { - for( q=&h->line[i]; q>p; q-- ) q[n-l] = q[0]; - for( q=s; *q; q++ ) *p++ = *q; - } - else { - strcpy(p,s); - strcat(p,p+l); - } - } -} - -static void abc_preprocess(ABCHANDLE *h, ABCMACRO *m) -{ - int i, j, k, l, a, b; - char t[32]; - char s[200],*p; - if( m->n ) { - k = m->n - m->name; - for( i=0; i<14; i++ ) { - strncpy(t, m->name, 32); - t[k] = "CDEFGABcdefgab"[i]; - l = strlen(m->subst); - p = s; - for( j=0; j<l; j++ ) { - a = m->subst[j]; - if( a > 'g' && islower(a) ) { - b = a - 'n'; - a = "CDEFGABCDEFGABcdefgabcdefgab"[i+b+7]; - *p++ = a; - if( i+b < 0 ) - *p++ = ','; - if( i+b > 13 ) - *p++ = '\''; - } - else *p++ = a; - } - *p = '\0'; - abc_substitute(h, t, s); - } - } - else - abc_substitute(h, m->name, m->subst); -} - -static char *abc_gets(ABCHANDLE *h, MMFILE *mmfile) -{ - int i; - ABCMACRO *mp; - if( !h->len ) { - h->len = 64; // initial line size, adequate for most abc's - h->line = (char *)_mm_calloc(h->allochandle, h->len, sizeof(char)); - } - if( abc_fgetbytes(mmfile, h->line, h->len) ) { - while( (i=strlen(h->line)) > (int)(h->len - 3) ) { - // line too short, double it - h->line = (char *)_mm_recalloc(h->allochandle, h->line, h->len<<1, sizeof(char)); - if( h->line[i-1] != '\n' ) - abc_fgetbytes(mmfile, &h->line[i], h->len); - h->len <<= 1; - } - h->line[i-1] = '\0'; // strip off newline - for( mp=h->macro; mp; mp=mp->next ) - abc_preprocess(h,mp); - return h->line; - } - return NULL; -} - -static int abc_parse_decorations(ABCHANDLE *h, ABCTRACK *tp, const char *p) -{ - int vol=0; - if( !strncmp(p,"mp",2) ) vol = 75; - if( !strncmp(p,"mf",2) ) vol = 90; - if( !strncmp(p,"sfz",3) ) vol = 100; - if( *p == 'p' ) { - vol = 60; - while( *p++ == 'p' ) vol -= 15; - if( vol < 1 ) vol = 1; - } - if( *p == 'f' ) { - vol = 105; - while( *p++ == 'f' ) vol += 15; - if( vol > 135 ) vol = 127; // ffff - if( vol > 127 ) vol = 125; // fff - } - if( vol ) { - tp->volume = vol; - if( tp == h->track ) { // copy volume over to all voice tracks - for( ; tp; tp=tp->next ) { - if( tp->vpos == 0 || tp->vpos > DRONEPOS2 ) tp->volume = vol; - } - tp = h->track; - } - } - return tp->volume; -} - -// ===================================================================================== -#ifdef NEWMIKMOD -BOOL ABC_Test(MMSTREAM *mmfile) -#else -BOOL CSoundFile::TestABC(const BYTE *lpStream, DWORD dwMemLength) -#endif -// ===================================================================================== -{ - char id[128]; - bool hasK = false, hasX = false; - // scan file for first K: line (last in header) -#ifdef NEWMIKMOD - _mm_fseek(mmfile,0,SEEK_SET); - while(abc_fgets(mmfile,id,128)) { -#else - MMFILE mmfile; - mmfile.mm = (char *)lpStream; - mmfile.sz = dwMemLength; - mmfseek(&mmfile,0,SEEK_SET); - while(abc_fgets(&mmfile,id,128)) { -#endif - if (id[0] == 0) continue; // blank line. - if (id[0] == '%' && id[1] != '%') continue; // comment line. - - if (!abc_isvalidchar(id[0]) || !abc_isvalidchar(id[1])) { - return(0); // probably not an ABC. - } - if(id[0]=='K' - && id[1]==':' - && (isalpha(id[2]) || isspace(id[2])) ) hasK = true; - if (id[0]=='X' - && id[1]== ':' - && (abc_isvalidchar(id[2])) ) hasX = true; - if (hasK && hasX) { return 1; printf("valid\n"); } - } - return 0; -} - -// ===================================================================================== -static ABCHANDLE *ABC_Init(void) -{ - ABCHANDLE *retval; - char *p; - char buf[10]; -#ifdef NEWMIKMOD - MM_ALLOC *allochandle; - - allochandle = _mmalloc_create("Load_ABC", NULL); - retval = (ABCHANDLE *)_mm_calloc(allochandle, 1,sizeof(ABCHANDLE)); - if( !retval ) return NULL; - retval->allochandle = allochandle; - allochandle = _mmalloc_create("Load_ABC_macros", NULL); - retval->macrohandle = allochandle; - allochandle = _mmalloc_create("Load_ABC_tracks", NULL); - retval->trackhandle = allochandle; -#else - retval = (ABCHANDLE *)calloc(1,sizeof(ABCHANDLE)); - if( !retval ) return NULL; -#endif - retval->track = NULL; - retval->macro = NULL; - retval->umacro = NULL; - retval->beatstring = NULL; - retval->pickrandom = 0; - retval->len = 0; - retval->line = NULL; - strcpy(retval->gchord, ""); - retval->barticks = 0; - p = getenv(ABC_ENV_NORANDOMPICK); - if( p ) { - if( isdigit(*p) ) - retval->pickrandom = atoi(p); - if( *p == '-' ) { -#ifdef NEWMIKMOD - retval->pickrandom = atoi(p+1); - sprintf(buf,"-%ld",retval->pickrandom+1); -#else - retval->pickrandom = atoi(p+1)-1; // xmms preloads the file - sprintf(buf,"-%ld",retval->pickrandom+2); -#endif - setenv(ABC_ENV_NORANDOMPICK, buf, 1); - } - } - else { - srandom((unsigned int)time(0)); // initialize random generator with seed - retval->pickrandom = 1+(int)(10000.0*random()/(RAND_MAX+1.0)); - // can handle pickin' from songbooks with 10.000 songs -#ifdef NEWMIKMOD - sprintf(buf,"-%ld",retval->pickrandom+1); // next in sequence -#else - sprintf(buf,"-%ld",retval->pickrandom); // xmms preloads the file -#endif - setenv(ABC_ENV_NORANDOMPICK, buf, 1); - } - return retval; -} - -#ifndef NEWMIKMOD -static void ABC_CleanupTrack(ABCTRACK *tp) -{ - ABCEVENT *ep, *en; - if( tp ) { - for( ep=tp->head; ep; ep = en ) { - en=ep->next; - free(ep); - } - tp->head = NULL; - } -} - -static void ABC_CleanupMacro(ABCMACRO *m) -{ - if( m->name ) - free(m->name); - if( m->subst ) - free(m->subst); - free(m); -} -#endif - -// ===================================================================================== -static void ABC_CleanupTracks(ABCHANDLE *handle) -// ===================================================================================== -{ -#ifdef NEWMIKMOD - if(handle && handle->trackhandle) { - _mmalloc_close(handle->trackhandle); - handle->trackhandle = 0; - } -#else - ABCTRACK *tp, *tn; - if(handle) { - for( tp=handle->track; tp; tp = tn ) { - tn=tp->next; - ABC_CleanupTrack(tp); - } - handle->track = NULL; - } -#endif -} - -// ===================================================================================== -static void ABC_CleanupMacros(ABCHANDLE *handle) -// ===================================================================================== -{ -#ifdef NEWMIKMOD - if(handle && handle->macrohandle) { - _mmalloc_close(handle->macrohandle); - handle->macrohandle = 0; - } -#else - ABCMACRO *mp, *mn; - if(handle) { - for( mp=handle->macro; mp; mp = mn ) { - mn=mp->next; - ABC_CleanupMacro(mp); - } - for( mp=handle->umacro; mp; mp = mn ) { - mn=mp->next; - ABC_CleanupMacro(mp); - } - handle->macro = NULL; - handle->umacro = NULL; - } -#endif -} - -// ===================================================================================== -static void ABC_Cleanup(ABCHANDLE *handle) -// ===================================================================================== -{ -#ifdef NEWMIKMOD - if(handle && handle->allochandle) { -#else - if(handle) { -#endif - ABC_CleanupMacros(handle); - ABC_CleanupTracks(handle); -#ifdef NEWMIKMOD - _mmalloc_close(handle->allochandle); - handle->allochandle = 0; - handle->len = 0; -#else - if( handle->line ) - free(handle->line); - if( handle->beatstring ) - free(handle->beatstring); - free(handle); -#endif - } -} - -static int abc_is_global_event(ABCEVENT *e) -{ - return e->flg == 1 && (e->cmd == cmdtempo || e->cmd == cmdpartbrk); -} - -static ABCEVENT *abc_next_global(ABCEVENT *e) -{ - for( ; e && !abc_is_global_event(e); e=e->next ) ; - return e; -} - -static ABCEVENT *abc_next_note(ABCEVENT *e) -{ - for( ; e && e->flg == 1; e=e->next ) ; - return e; -} - -// ============================================================================= -#ifdef NEWMIKMOD -static void ABC_ReadPatterns(UNIMOD *of, ABCHANDLE *h, int numpat) -// ============================================================================= -{ - int pat,row,i,ch,trillbits; - BYTE n,ins,vol; - ABCTRACK *t; - ABCEVENT *e, *en, *ef, *el; - uint32_t tt1, tt2; - UNITRK_EFFECT eff; - - // initialize start points of event list in tracks - for( t = h->track; t; t = t->next ) t->capostart = t->head; - trillbits = 0; // trill effect admininstration: one bit per channel, max 32 channnels - for( pat = 0; pat < numpat; pat++ ) { - utrk_reset(of->ut); - for( row = 0; row < 64; row++ ) { - tt1 = abcticks((pat * 64 + row ) * h->speed); - tt2 = tt1 + abcticks(h->speed); - ch = 0; - for( e=abc_next_global(h->track->capostart); e && e->tracktick < tt2; e=abc_next_global(e->next) ) { - if( e && e->tracktick >= tt1 ) { // we have a tempo event in this row - switch( e->cmd ) { - case cmdtempo: - eff.effect = UNI_GLOB_TEMPO; - eff.param.u = e->lpar; - eff.framedly = UFD_RUNONCE; - utrk_write_global(of->ut, &eff, PTMEM_TEMPO); - break; - case cmdpartbrk: - eff.effect = UNI_GLOB_PATBREAK; - eff.param.u = 0; - eff.framedly = UFD_RUNONCE; - utrk_write_global(of->ut, &eff, UNIMEM_NONE); - break; - } - } - } - for( t = h->track; t; t = t->next ) { - for( e=abc_next_note(t->capostart); e && e->tracktick < tt1; e=abc_next_note(e->next) ) - t->capostart = e; - i = 0; - ef = NULL; - en = e; - el = e; - for( ; e && e->tracktick < tt2; e=abc_next_note(e->next) ) { // we have a note event in this row - t->capostart = e; - i++; - if( e->par[volume] ) { - if( !ef ) ef = e; - el = e; - } - } - if( i ) { - trillbits &= ~(1<<ch); - utrk_settrack(of->ut, ch); - if( i == 1 || ef == el || !ef ) { // only one event in this row - if( ef ) e = ef; - else e = en; - el = t->capostart; - i = e->par[note] + ((e->par[octave])*12); - if( t->chan == 10 ) { - n = pat_gm_drumnote(i) + 23; - ins = pat_gmtosmp(pat_gm_drumnr(i)); - } - else { - n = pat_modnote(i); - ins = e->par[smpno]; - } - eff.framedly = modticks(e->tracktick - tt1); - vol = e->par[volume]; - if( e->par[effect] == accent ) { - vol += vol / 10; - if( vol > 127 ) vol = 127; - } - if (vol <= 0) {} - else if( el->par[volume] == 0 ) { - eff.framedly = modticks(el->tracktick - tt1); - eff.param.u = 0; - eff.param.byte_a = n; - eff.param.byte_b = ins; - eff.effect = UNI_NOTEKILL; - utrk_write_local(of->ut, &eff, UNIMEM_NONE); - } - else { - switch( e->par[effect] ) { - case trill: - eff.effect = UNI_VIBRATO_DEPTH; - eff.param.u = 12; // depth 1.5 - utrk_write_local(of->ut, &eff, PTMEM_VIBRATO_DEPTH); - eff.effect = UNI_VIBRATO_SPEED; - eff.param.u = 48; // speed 12 - utrk_write_local(of->ut, &eff, PTMEM_VIBRATO_SPEED); - trillbits |= (1<<ch); - break; - case bow: - eff.effect = UNI_PITCHSLIDE; - eff.framedly = (h->speed/2)|UFD_RUNONCE; - eff.param.s = 2; - utrk_write_local(of->ut, &eff, (e->par[effoper])? PTMEM_PITCHSLIDEUP: PTMEM_PITCHSLIDEDN); - break; - default: - break; - } - if( eff.framedly ) { - eff.param.u = 0; - eff.param.byte_a = n; - eff.param.byte_b = ins; - eff.effect = UNI_NOTEDELAY; - utrk_write_local(of->ut, &eff, UNIMEM_NONE); - } - } - utrk_write_inst(of->ut, ins); - utrk_write_note(of->ut, n); // <- normal note - pt_write_effect(of->ut, 0xc, vol); - } - else { - // two notes in one row, use FINEPITCHSLIDE runonce effect - // start first note on first tick and framedly runonce on seconds note tick - // use volume and instrument of last note - if( t->chan == 10 ) { - i = el->par[note] + ((el->par[octave])*12); - n = pat_gm_drumnote(i) + 23; - ins = pat_gmtosmp(pat_gm_drumnr(i)); - i = n; // cannot change instrument here.. - } - else { - i = ef->par[note] + ((ef->par[octave])*12); - n = pat_modnote(i); - ins = el->par[smpno]; - i = pat_modnote(el->par[note] + ((el->par[octave])*12)); - } - vol = el->par[volume]; - eff.effect = UNI_PITCHSLIDE; - eff.framedly = modticks(el->tracktick - tt1)|UFD_RUNONCE; - eff.param.s = ((i > n)?i-n:n-i); - utrk_write_inst(of->ut, ins); - utrk_write_note(of->ut, n); // <- normal note - pt_write_effect(of->ut, 0xc, vol); - utrk_write_local(of->ut, &eff, (i > n)? PTMEM_PITCHSLIDEUP: PTMEM_PITCHSLIDEDN); - } - } - else { // no new notes, keep on trilling... - if( trillbits & (1<<ch) ) { - utrk_settrack(of->ut, ch); - eff.effect = UNI_VIBRATO_DEPTH; - eff.param.u = 12; // depth 1.5 - utrk_write_local(of->ut, &eff, PTMEM_VIBRATO_DEPTH); - eff.effect = UNI_VIBRATO_SPEED; - eff.param.u = 60; // speed 15 - utrk_write_local(of->ut, &eff, PTMEM_VIBRATO_SPEED); - } - } - ch++; - } - utrk_newline(of->ut); - } - if(!utrk_dup_pattern(of->ut,of)) return; - } -} - -#else - -static int ABC_ReadPatterns(MODCOMMAND *pattern[], WORD psize[], ABCHANDLE *h, int numpat, int channels) -// ===================================================================================== -{ - int pat,row,i,ch,trillbits; - BYTE n,ins,vol; - ABCTRACK *t; - ABCEVENT *e, *en, *ef, *el; - uint32_t tt1, tt2; - MODCOMMAND *m; - int patbrk, tempo; - if( numpat > MAX_PATTERNS ) numpat = MAX_PATTERNS; - - // initialize start points of event list in tracks - for( t = h->track; t; t = t->next ) t->capostart = t->head; - trillbits = 0; // trill effect admininstration: one bit per channel, max 32 channnels - for( pat = 0; pat < numpat; pat++ ) { - pattern[pat] = CSoundFile::AllocatePattern(64, channels); - if( !pattern[pat] ) return 0; - psize[pat] = 64; - for( row = 0; row < 64; row++ ) { - tt1 = abcticks((pat * 64 + row ) * h->speed); - tt2 = tt1 + abcticks(h->speed); - ch = 0; - tempo = 0; - patbrk = 0; - for( e=abc_next_global(h->track->capostart); e && e->tracktick < tt2; e=abc_next_global(e->next) ) { - if( e && e->tracktick >= tt1 ) { // we have a tempo event in this row - switch( e->cmd ) { - case cmdtempo: - tempo = e->lpar; - break; - case cmdpartbrk: - patbrk = 1; - break; - } - } - } - for( t = h->track; t; t = t->next ) { - for( e=abc_next_note(t->capostart); e && e->tracktick < tt1; e=abc_next_note(e->next) ) ; - i = 0; - ef = NULL; - en = e; - el = e; - for( ; e && e->tracktick < tt2; e=abc_next_note(e->next) ) { // we have a note event in this row - t->capostart = e; - i++; - if( e->par[volume] ) { - if( !ef ) ef = e; - el = e; - } - } - m = &pattern[pat][row * channels + ch]; - m->param = 0; - m->command = CMD_NONE; - if( i ) { - trillbits &= ~(1<<ch); - if( i == 1 || ef == el || !ef ) { // only one event in this row - if( ef ) e = ef; - else e = en; - el = t->capostart; - i = e->par[note] + ((e->par[octave])*12); - if( t->chan == 10 ) { - n = pat_gm_drumnote(i) + 23; - ins = pat_gmtosmp(pat_gm_drumnr(i)); - } - else { - n = pat_modnote(i); - ins = e->par[smpno]; - } - vol = e->par[volume]/2; - if( e->par[volume] > 0 ) { - if( e->par[effect] == accent ) vol += vol / 20; - if( vol > 64 ) vol = 64; - if( el->par[volume] == 0 ) { // note cut - m->param = el->tracktick - tt1; - m->command = CMD_S3MCMDEX; - m->param |= 0xC0; - } - else { - switch( e->par[effect] ) { - case trill: - m->command = CMD_VIBRATO; - m->param = 0xC2; // speed 12 depth 2 - trillbits |= (1<<ch); - break; - case bow: - m->command = CMD_XFINEPORTAUPDOWN; - m->param |= (e->par[effoper])? 0x12: 0x22; - break; - default: - m->param = modticks(e->tracktick - tt1); - if( m->param ) { // note delay - m->command = CMD_S3MCMDEX; - m->param |= 0xD0; - } - break; - } - } - } - m->instr = ins; - m->note = n; // <- normal note - m->volcmd = VOLCMD_VOLUME; - m->vol = vol; - } - else { - // two notes in one row, use FINEPITCHSLIDE runonce effect - // start first note on first tick and framedly runonce on seconds note tick - // use volume and instrument of last note - if( t->chan == 10 ) { - i = el->par[note] + ((el->par[octave])*12); - n = pat_gm_drumnote(i) + 23; - ins = pat_gmtosmp(pat_gm_drumnr(i)); - i = n; // cannot change instrument here.. - } - else { - i = ef->par[note] + ((ef->par[octave])*12); - n = pat_modnote(i); - ins = el->par[smpno]; - i = pat_modnote(el->par[note] + ((el->par[octave])*12)); - } - vol = el->par[volume]/2; - if( vol > 64 ) vol = 64; - m->instr = ins; - m->note = n; // <- normal note - m->volcmd = VOLCMD_VOLUME; - m->vol = vol; - m->param = ((i > n)?i-n:n-i); - if( m->param < 16 ) { - if( m->param ) { - m->command = CMD_XFINEPORTAUPDOWN; - m->param |= (i > n)? 0x10: 0x20; - } - else { // retrigger same note... - m->command = CMD_RETRIG; - m->param = modticks(el->tracktick - tt1); - } - } - else - m->command = (i > n)? CMD_PORTAMENTOUP: CMD_PORTAMENTODOWN; - } - } - else { // no new notes, keep on trilling... - if( trillbits & (1<<ch) ) { - m = &pattern[pat][row * channels + ch]; - m->command = CMD_VIBRATO; - m->param = 0; // inherited from first effect - m->instr = 0; - m->note = 0; - m->volcmd = 0; - m->vol = 0; - } - } - if( m->param == 0 && m->command == CMD_NONE ) { - if( tempo ) { - m->command = CMD_TEMPO; - m->param = tempo; - tempo = 0; - } - else { - if( patbrk ) { - m->command = CMD_PATTERNBREAK; - patbrk = 0; - } - } - } - ch++; - } - if( tempo || patbrk ) return 1; - } - } - return 0; -} - -#endif - -static int ABC_Key(const char *p) -{ - int i,j; - char c[8]; - const char *q; - while( isspace(*p) ) p++; - i = 0; - q = p; - for( i=0; i<8 && *p && *p != ']'; p++ ) { - if( isspace(*p) ) { - while( isspace(*p) ) p++; - if( strncasecmp(p, "min", 3) && strncasecmp(p, "maj", 3) ) - break; - } - c[i] = *p; - i++; - } - c[i] = '\0'; - if( !strcmp(c,"Hp") || !strcmp(c,"HP") ) // highland pipes - strcpy(c,"Bm"); // two sharps at c and f - if( !strcasecmp(c+1, "minor") ) i=2; - if( !strcasecmp(c+2, "minor") ) i=3; - if( !strcasecmp(c+1, "major") ) i=1; - if( !strcasecmp(c+2, "major") ) i=2; - if( !strcasecmp(c+1, "min") ) i=2; - if( !strcasecmp(c+2, "min") ) i=3; - if( !strcasecmp(c+1, "maj") ) i=1; - if( !strcasecmp(c+2, "maj") ) i=2; - for( ; i<6; i++ ) - c[i] = ' '; - c[i] = '\0'; - for( i=0; keySigs[i]; i++ ) { - for( j=10; j<46; j+=6 ) - if( !strncasecmp(keySigs[i]+j, c, 6) ) - return i; - } - abc_message("Failure: Unrecognised K: field %s", q); - return 7; -} - -static char *abc_skip_word(char *p) -{ - while( isspace(*p) ) p++; - while( *p && !isspace(*p) && *p != ']') p++; - while( isspace(*p) ) p++; - return p; -} - -static uint32_t abc_tracktime(ABCTRACK *tp) -{ - uint32_t tracktime; - if( tp->tail ) tracktime = tp->tail->tracktick; - else tracktime = 0; - if( tracktime < global_songstart ) - tracktime = global_songstart; - return tracktime; -} - -static void abc_addchordname(const char *s, int len, const int *notes) -// adds chord name and note set to list of known chords -{ - int i, j; - if(strlen(s) > 7) { - abc_message("Failure: Chord name cannot exceed 7 characters, %s", s); - return; - } - if(len > 6) { - abc_message("Failure: Named chord cannot have more than 6 notes, %s", s); - return; - } - for( i=0; i < chordsnamed; i++ ) { - if(strcmp(s, chordname[i]) == 0) { - /* change chord */ - chordlen[i] = len; - for(j = 0; j < len; j++) chordnotes[i][j] = notes[j]; - return; - } - } - if(chordsnamed > MAXCHORDNAMES - 1) - abc_message("Failure: Too many Guitar Chord Names used, %s", s); - else { - strcpy(chordname[chordsnamed], s); - chordlen[chordsnamed] = len; - for(j = 0; j < len; j++) chordnotes[chordsnamed][j] = notes[j]; - chordsnamed++; - } -} - -static void abc_setup_chordnames() -// set up named guitar chords -{ - static const int list_Maj[3] = { 0, 4, 7 }; - static const int list_m[3] = { 0, 3, 7 }; - static const int list_7[4] = { 0, 4, 7, 10 }; - static const int list_m7[4] = { 0, 3, 7, 10 }; - static const int list_maj7[4] = { 0, 4, 7, 11 }; - static const int list_M7[4] = { 0, 4, 7, 11 }; - static const int list_6[4] = { 0, 4, 7, 9 }; - static const int list_m6[4] = { 0, 3, 7, 9 }; - static const int list_aug[3] = { 0, 4, 8 }; - static const int list_plus[3] = { 0, 4, 8 }; - static const int list_aug7[4] = { 0, 4, 8, 10 }; - static const int list_dim[3] = { 0, 3, 6 }; - static const int list_dim7[4] = { 0, 3, 6, 9 }; - static const int list_9[5] = { 0, 4, 7, 10, 2 }; - static const int list_m9[5] = { 0, 3, 7, 10, 2 }; - static const int list_maj9[5] = { 0, 4, 7, 11, 2 }; - static const int list_M9[5] = { 0, 4, 7, 11, 2 }; - static const int list_11[6] = { 0, 4, 7, 10, 2, 5 }; - static const int list_dim9[5] = { 0, 4, 7, 10, 13 }; - static const int list_sus[3] = { 0, 5, 7 }; - static const int list_sus9[3] = { 0, 2, 7 }; - static const int list_7sus[4] = { 0, 5, 7, 10 }; - static const int list_7sus4[4] = { 0, 5, 7, 10 }; - static const int list_7sus9[4] = { 0, 2, 7, 10 }; - static const int list_9sus4[5] = { 0, 5, 10, 14, 19 }; - static const int list_5[2] = { 0, 7 }; - static const int list_13[6] = { 0, 4, 7, 10, 16, 21 }; - - chordsnamed = 0; - abc_addchordname("", 3, list_Maj); - abc_addchordname("m", 3, list_m); - abc_addchordname("7", 4, list_7); - abc_addchordname("m7", 4, list_m7); - abc_addchordname("maj7", 4, list_maj7); - abc_addchordname("M7", 4, list_M7); - abc_addchordname("6", 4, list_6); - abc_addchordname("m6", 4, list_m6); - abc_addchordname("aug", 3, list_aug); - abc_addchordname("+", 3, list_plus); - abc_addchordname("aug7", 4, list_aug7); - abc_addchordname("7+", 4, list_aug7); - abc_addchordname("dim", 3, list_dim); - abc_addchordname("dim7", 4, list_dim7); - abc_addchordname("9", 5, list_9); - abc_addchordname("m9", 5, list_m9); - abc_addchordname("maj9", 5, list_maj9); - abc_addchordname("M9", 5, list_M9); - abc_addchordname("11", 6, list_11); - abc_addchordname("dim9", 5, list_dim9); - abc_addchordname("sus", 3, list_sus); - abc_addchordname("sus9", 3, list_sus9); - abc_addchordname("7sus", 4, list_7sus); - abc_addchordname("7sus4", 4, list_7sus4); - abc_addchordname("7sus9", 4, list_7sus9); - abc_addchordname("9sus4", 5, list_9sus4); - abc_addchordname("5", 2, list_5); - abc_addchordname("13", 6, list_13); -} - -static int abc_MIDI_getnumber(const char *p) -{ - int n; - while( isspace(*p) ) p++; - abc_getnumber(p, &n); - if( n < 0 ) n = 0; - if( n > 127 ) n = 127; - return n; -} - -static int abc_MIDI_getprog(const char *p) -{ - int n; - while( isspace(*p) ) p++; - abc_getnumber(p, &n); - if( n < 1 ) n = 1; - if( n > 128 ) n = 128; - return n; -} - -// MIDI drone <instr0> <pitch1> <pitch2> <vel1> <vel2> -static void abc_MIDI_drone(const char *p, int *gm, int *ptch, int *vol) -{ - int i; - while( isspace(*p) ) p++; - p += abc_getnumber(p, &i); - i++; // adjust for 1..128 - if( i>0 && i < 129 ) - *gm = i; - else - *gm = 71; // bassoon - while( isspace(*p) ) p++; - p += abc_getnumber(p, &i); - if( i>0 && i < 127 ) - ptch[0] = i; - else - ptch[0] = 45; - while( isspace(*p) ) p++; - p += abc_getnumber(p, &i); - if( i>0 && i < 127 ) - ptch[1] = i; - else - ptch[1] = 33; - while( isspace(*p) ) p++; - p += abc_getnumber(p, &i); - if( i>0 && i < 127 ) - vol[0] = i; - else - vol[0] = 80; - while( isspace(*p) ) p++; - p += abc_getnumber(p, &i); - if( i>0 && i < 127 ) - vol[1] = i; - else - vol[1] = 80; -} - -static void abc_chan_to_tracks(ABCHANDLE *h, int tno, int ch) -{ - ABCTRACK *tp; - if( tno>0 && tno<33 ) { - for( tp=h->track; tp; tp=tp->next ) { - if( tp->vno == tno && (tp->vpos < GCHORDBPOS || tp->vpos > DRONEPOS2) ) - tp->chan = ch; - } - } -} - -// %%MIDI channel int1 -// channel numbers are 1-16 -static void abc_MIDI_channel(const char *p, ABCTRACK *tp, ABCHANDLE *h) -{ - int i1, i2; - i1 = tp? tp->vno: 1; - for( ; *p && isspace(*p); p++ ) ; - if( isdigit(*p) ) { - p += abc_getnumber(p, &i2); - if( i2 >= 1 && i2 <= 16 ) - abc_chan_to_tracks(h, i1, i2); // we start at 1 - } -} - -static void abc_instr_to_tracks(ABCHANDLE *h, int tno, int gm) -{ - ABCTRACK *tp; - if( tno>0 && tno<33 && gm>0 && gm<129 ) { - for( tp=h->track; tp; tp=tp->next ) { - if( tp->vno == tno && (tp->vpos < GCHORDBPOS || tp->vpos > DRONEPOS2) ) - tp->instr = gm; - } - } -} - -// %%MIDI program [int1] <int2> -// instrument numbers are 0-127 -static void abc_MIDI_program(const char *p, ABCTRACK *tp, ABCHANDLE *h) -{ - int i1, i2; - i1 = tp? tp->vno: 1; - for( ; *p && isspace(*p); p++ ) ; - if( isdigit(*p) ) { - p += abc_getnumber(p, &i2); - for( ; *p && isspace(*p); p++ ) ; - if( isdigit(*p) ) { - i1 = i2; - p += abc_getnumber(p, &i2); - } - abc_instr_to_tracks(h, i1, i2 + 1); // we start at 1 - } -} - -static void abc_mute_voice(ABCHANDLE *h, ABCTRACK *tp, int m) -{ - ABCTRACK *t; - for( t=h->track; t; t=t->next ) { - if( t->vno == tp->vno ) t->mute = m; - } -} - -// %%MIDI voice [<ID>] [instrument=<integer> [bank=<integer>]] [mute] -// instrument numbers are 1-128 -static void abc_MIDI_voice(const char *p, ABCTRACK *tp, ABCHANDLE *h) -{ - int i1, i2; - for( ; *p && isspace(*p); p++ ) ; - if( strncmp(p,"instrument=",11) && strncmp(p,"mute",4) ) { - tp = abc_locate_track(h, p, 0); - for( ; *p && !isspace(*p); p++ ) ; - for( ; *p && isspace(*p); p++ ) ; - } - i1 = tp? tp->vno: 1; - i2 = 0; - if( !strncmp(p,"instrument=",11) && isdigit(p[11]) ) { - p += 11; - p += abc_getnumber(p, &i2); - for( ; *p && isspace(*p); p++ ) ; - if( !strncmp(p,"bank=",5) && isdigit(p[5]) ) { - for( ; *p && !isspace(*p); p++ ) ; - for( ; *p && isspace(*p); p++ ) ; - } - } - if( tp ) abc_mute_voice(h,tp,0); - if( !strncmp(p,"mute",4) && (p[4]=='\0' || p[4]=='%' || isspace(p[4])) ) { - if( tp ) abc_mute_voice(h,tp,1); - } - abc_instr_to_tracks(h, i1, i2); // starts already at 1 (draft 4.0) -} - -// %%MIDI chordname <string> <int1> <int2> ... <int6> -static void abc_MIDI_chordname(const char *p) -{ - char name[20]; - int i, notes[6]; - - for( ; *p && isspace(*p); p++ ) ; - i = 0; - while ((i < 19) && (*p != ' ') && (*p != '\0')) { - name[i] = *p; - p = p + 1; - i = i + 1; - } - name[i] = '\0'; - if(*p != ' ') { - abc_message("Failure: Bad format for chordname command, %s", p); - } - else { - i = 0; - while ((i <= 6) && isspace(*p)) { - for( ; *p && isspace(*p); p++ ) ; - p += abc_getnumber(p, ¬es[i]); - i = i + 1; - } - abc_addchordname(name, i, notes); - } -} - -// %%MIDI drum <string> <inst 1> ... <inst n> <vol 1> ... <vol n> -// instrument numbers are 0-127 -static int abc_MIDI_drum(const char *p, ABCHANDLE *h) -{ - char *q; - int i,n,m; - while( isspace(*p) ) p++; - if( !strncmp(p,"on",2) && (isspace(p[2]) || p[2] == '\0') ) return 2; - if( !strncmp(p,"off",3) && (isspace(p[3]) || p[3] == '\0') ) return 1; - n = 0; - for( q = h->drum; *p && !isspace(*p); p++ ) { - if( !strchr("dz0123456789",*p) ) break; - *q++ = *p; - if( !isdigit(*p) ) { - if( !isdigit(p[1]) ) *q++ = '1'; - n++; // count the silences too.... - } - } - *q = '\0'; - q = h->drumins; - for( i = 0; i<n; i++ ) { - if( h->drum[i*2] == 'd' ) { - while( isspace(*p) ) p++; - if( !isdigit(*p) ) { - m = 0; - while( !isspace(*p) ) p++; - } - else - p += abc_getnumber(p,&m); - q[i] = m + 1; // we start at 1 - } - else q[i] = 0; - } - q = h->drumvol; - for( i = 0; i<n; i++ ) { - if( h->drum[i*2] == 'd' ) { - while( isspace(*p) ) p++; - if( !isdigit(*p) ) { - m = 0; - while( !isspace(*p) ) p++; - } - else - p += abc_getnumber(p,&m); - q[i] = m; - } - else q[i] = 0; - } - return 0; -} - -// %%MIDI gchord <string> -static int abc_MIDI_gchord(const char *p, ABCHANDLE *h) -{ - char *q; - while( isspace(*p) ) p++; - if( !strncmp(p,"on",2) && (isspace(p[2]) || p[2] == '\0') ) return 2; - if( !strncmp(p,"off",3) && (isspace(p[3]) || p[3] == '\0') ) return 1; - for( q = h->gchord; *p && !isspace(*p); p++ ) { - if( !strchr("fbcz0123456789ghijGHIJ",*p) ) break; - *q++ = *p; - if( !isdigit(*p) && !isdigit(p[1]) ) *q++ = '1'; - } - *q = '\0'; - return 0; -} - -static void abc_metric_gchord(ABCHANDLE *h, int mlen, int mdiv) -{ - switch( 16 * mlen + mdiv ) { - case 0x24: - case 0x44: - case 0x22: - abc_MIDI_gchord("fzczfzcz", h); - break; - case 0x64: - case 0x32: - abc_MIDI_gchord("fzczczfzczcz", h); - break; - case 0x34: - case 0x38: - abc_MIDI_gchord("fzczcz", h); - break; - case 0x68: - abc_MIDI_gchord("fzcfzc", h); - break; - case 0x98: - abc_MIDI_gchord("fzcfzcfzc", h); - break; - case 0xc8: - abc_MIDI_gchord("fzcfzcfzcfzc", h); - break; - default: - if( mlen % 3 == 0 ) - abc_MIDI_gchord("fzcfzcfzcfzcfzcfzcfzcfzcfzc", h); - else - abc_MIDI_gchord("fzczfzczfzczfzczfzczfzczfzcz", h); - if( mdiv == 8 ) h->gchord[mlen*2] = '\0'; - else h->gchord[mlen*4] = '\0'; - break; - } -} - -static void abc_MIDI_legato(const char *p, ABCTRACK *tp) -{ - for( ; *p && isspace(*p); p++ ) ; - if( !strncmp(p,"off",3) ) tp->legato = 0; - else tp->legato = 1; -} - -static void abc_M_field(const char *p, int *mlen, int *mdiv) -{ - if( !strncmp(p,"none",4) ) { - *mlen = 1; - *mdiv = 1; - return; - } - if( !strncmp(p,"C|",2) ) { - *mlen = 2; - *mdiv = 2; - return; - } - if( *p == 'C' ) { - *mlen = 4; - *mdiv = 4; - return; - } - p += abc_getexpr(p,mlen); - sscanf(p," / %d", mdiv); -} - -static int abc_drum_steps(const char *dch) -{ - const char *p; - int i=0; - for( p=dch; *p; p++ ) { - if( isdigit(*p) ) i += *p - '0';; - } - return i; -} - -static void abc_add_drum(ABCHANDLE *h, uint32_t tracktime, uint32_t bartime) -{ - ABCEVENT *e; - ABCTRACK *tp; - uint32_t etime, ctime , rtime, stime; - int i, g, steps, gnote, gsteps, nnum; - steps = abc_drum_steps(h->drum); - ctime = h->barticks; - // look up the last event in tpr drumtrack - tp = abc_locate_track(h, h->tpr->v, DRUMPOS); - e = tp->tail; - etime = e? e->tracktick: bartime; - if( etime > tracktime ) return; - if( etime < bartime ) rtime = h->barticks - ((bartime - etime) % h->barticks); - else rtime = (etime - bartime) % h->barticks; - stime = ctime*steps; - rtime *= steps; - rtime += stime; - gsteps = strlen(h->drum)/2; - g = 0; - while( rtime > stime ) { - rtime -= ctime*(h->drum[g*2+1] - '0'); - if( ++g == gsteps ) g = 0; - } - stime = (tracktime - etime) * steps; - rtime = 0; - while( rtime < stime ) { - gnote = h->drum[g*2]; - i = h->drum[g*2+1] - '0'; - if(gnote=='d') { - tp->instr = pat_gm_drumnr(h->drumins[g]-1); - nnum = pat_gm_drumnote(h->drumins[g]); - abc_add_drumnote(h, tp, etime + rtime/steps, nnum, h->drumvol[g]); - abc_add_noteoff(h,tp,etime + ( rtime + ctime * i )/steps); - } - if( ++g == gsteps ) g = 0; - rtime += ctime * i; - } -} - -static int abc_gchord_steps(const char *gch) -{ - const char *p; - int i=0; - for( p=gch; *p; p++ ) - if( isdigit(*p) ) i += *p - '0'; - return i; -} - -static void abc_add_gchord(ABCHANDLE *h, uint32_t tracktime, uint32_t bartime) -{ - ABCEVENT *e, *c; - ABCTRACK *tp; - uint32_t etime, ctime , rtime, stime; - int i, g, steps, gnote, gcnum, gsteps, nnum, glen; - // look up the last chord event in tpc - c = 0; - for( e = h->tpc->head; e; e = e->next ) - if( e->flg == 1 && e->cmd == cmdchord ) - c = e; - if( !c ) return; - gcnum = c->par[chordnum]; - steps = abc_gchord_steps(h->gchord); - ctime = h->barticks; - etime = 0; - for( i = GCHORDBPOS; i < DRUMPOS; i++ ) { - tp = abc_locate_track(h, h->tpc->v, i); - e = tp->tail; - if( !e ) e = c; - stime = e->tracktick; - if( stime > etime ) etime = stime; - } - if( etime > tracktime ) return; - if( etime < bartime ) rtime = h->barticks - ((bartime - etime) % h->barticks); - else rtime = (etime - bartime) % h->barticks; - stime = ctime * steps; - rtime *= steps; - rtime += stime; - gsteps = strlen(h->gchord); - g = 0; - while( rtime > stime ) { - glen = h->gchord[2*g+1] - '0'; - rtime -= ctime * glen; - if( ++g == gsteps ) g = 0; - } - stime = (tracktime - etime) * steps; - rtime = 0; - while( rtime < stime ) { - gnote = h->gchord[2*g]; - glen = h->gchord[2*g+1] - '0'; - if( ++g == gsteps ) g = 0; - nnum = 0; - switch(gnote) { - case 'b': - tp = abc_locate_track(h, h->tpc->v, GCHORDFPOS); - tp->instr = h->abcbassprog; - nnum = c->par[chordnote]+chordnotes[gcnum][0]+24; - abc_add_chordnote(h, tp, etime + rtime/steps, nnum, h->abcbassvol); - abc_add_noteoff(h,tp,etime + ( rtime + ctime * glen )/steps); - case 'c': - for( i = 1; i < chordlen[gcnum]; i++ ) { - tp = abc_locate_track(h, h->tpc->v, i+GCHORDFPOS); - tp->instr = h->abcchordprog; - nnum = c->par[chordnote]+chordnotes[gcnum][i]+24; - abc_add_chordnote(h, tp, etime + rtime/steps, nnum, h->abcchordvol); - abc_add_noteoff(h,tp,etime + ( rtime + ctime * glen )/steps); - } - rtime += ctime * glen; - break; - case 'f': - tp = abc_locate_track(h, h->tpc->v, GCHORDFPOS); - tp->instr = h->abcbassprog; - nnum = c->par[chordbase]+12; - abc_add_chordnote(h, tp, etime + rtime/steps, nnum, h->abcbassvol); - rtime += ctime * glen; - abc_add_noteoff(h,tp,etime + rtime/steps); - break; - case 'g': - case 'h': - case 'i': - case 'j': - case 'G': - case 'H': - case 'I': - case 'J': - i = toupper(gnote) - 'G'; - nnum = 0; - if( i < chordlen[gcnum] ) { - tp = abc_locate_track(h, h->tpc->v, GCHORDFPOS+i+1); - tp->instr = h->abcchordprog; - nnum = c->par[chordnote]+chordnotes[gcnum][i]+24; - if( isupper(gnote) ) nnum -= 12; - abc_add_chordnote(h, tp, etime + rtime/steps, nnum, h->abcchordvol); - } - rtime += ctime * glen; - if( nnum ) abc_add_noteoff(h,tp,etime + rtime/steps); - break; - case 'z': - rtime += ctime * glen; - break; - } - } -} - -// %%MIDI beat a b c n -// -// controls the way note velocities are selected. The first note in a bar has -// velocity a. Other "strong" notes have velocity b and all the rest have velocity -// c. a, b and c must be in the range 0-128. The parameter n determines which -// notes are "strong". If the time signature is x/y, then each note is given -// a position number k = 0, 1, 2 .. x-1 within each bar. Note that the units for -// n are not the unit note length. If k is a multiple of n, then the note is -// "strong". The volume specifiers !ppp! to !fff! are equivalent to the -// following : -// -// !ppp! = %%MIDI beat 30 20 10 1 -// !pp! = %%MIDI beat 45 35 20 1 -// !p! = %%MIDI beat 60 50 35 1 -// !mp! = %%MIDI beat 75 65 50 1 -// !mf! = %%MIDI beat 90 80 65 1 -// !f! = %%MIDI beat 105 95 80 1 -// !ff! = %%MIDI beat 120 110 95 1 -// !fff! = %%MIDI beat 127 125 110 1 -static void abc_MIDI_beat(ABCHANDLE *h, const char *p) -{ - int i,j; - h->beat[0] = 127; - h->beat[1] = 125; - h->beat[2] = 110; - h->beat[3] = 1; - for( j=0; j<4; j++ ) { - while( isspace(*p) ) p++; - if( *p ) { - p += abc_getnumber(p, &i); - if( i < 0 ) i = 0; - if( i > 127 ) i = 127; - h->beat[j] = i; - } - } - if( h->beat[3] == 0 ) h->beat[3] = 1; // BB Ruud says: do not let you make mad -} - -// -// %%MIDI beatstring <string of f, m and p> -// -// This provides an alternative way of specifying where the strong and weak -// stresses fall within a bar. 'f' means velocity a (normally strong), 'm' -// means velocity b (medium velocity) and 'p' means velocity c (soft velocity). -// For example, if the time signature is 7/8 with stresses on the first, fourth -// and sixth notes in the bar, we could use the following -// -// %%MIDI beatstring fppmpmp -static void abc_MIDI_beatstring(ABCHANDLE *h, const char *p) -{ - while( isspace(*p) ) p++; - if( h->beatstring ) _mm_free(h->allochandle, h->beatstring); - if( strlen(p) ) - h->beatstring = DupStr(h->allochandle,p,strlen(p)+1); - else - h->beatstring = NULL; -} - -static int abc_beat_vol(ABCHANDLE *h, int abcvol, int barpos) -{ - int vol; - if( h->beatstring ) { - vol = (h->beat[2] * 9) / 10; - if( barpos < (int)strlen(h->beatstring) ) { - switch(h->beatstring[barpos]) { - case 'f': - vol = h->beat[0]; - break; - case 'm': - vol = h->beat[1]; - break; - case 'p': - vol = h->beat[2]; - break; - default: - break; - } - } - } - else { - if( (barpos % h->beat[3]) == 0 ) { - if( barpos ) - vol = h->beat[1]; - else - vol = h->beat[0]; - } - else - vol = h->beat[2]; - } - vol *= abcvol; - vol /= 128; - return vol; -} - -static void abc_init_partpat(BYTE partp[27][2]) -{ - int i; - for( i=0; i<27; i++ ) { - partp[i][0] = 0xff; - partp[i][1] = 0; - } -} - -static int abc_partpat_to_orderlist(BYTE partp[27][2], const char *abcparts, ABCHANDLE *h, BYTE **list, int orderlen) -{ - int t, partsused; - const char *p; - BYTE *orderlist = *list; - static int ordersize = 0; - if( *list == NULL ) { - ordersize = 128; - orderlist = (BYTE *)_mm_calloc(h->ho, ordersize, sizeof(BYTE)); - *list = orderlist; - } - if( abcparts ) { - partsused = 0; - for( p = abcparts; *p; p++ ) { - for( t = partp[*p - 'A'][0]; t < partp[*p - 'A'][1]; t++ ) { - if( orderlen == ordersize ) { - ordersize <<= 1; - orderlist = (BYTE *)_mm_recalloc(h->ho, orderlist, ordersize, sizeof(BYTE)); - *list = orderlist; - } - orderlist[orderlen] = t; - orderlen++; - partsused++; - } - } - if( partsused ) return orderlen; - } - // some fool wrote a P: string in the header but didn't use P: in the body - for( t = partp[26][0]; t < partp[26][1]; t++ ) { - if( orderlen == ordersize ) { - ordersize <<= 1; - orderlist = (BYTE *)_mm_recalloc(h->ho, orderlist, ordersize, sizeof(BYTE)); - *list = orderlist; - } - orderlist[orderlen] = t; - orderlen++; - } - return orderlen; -} - -static void abc_globalslide(ABCHANDLE *h, uint32_t tracktime, int slide) -{ - ABCTRACK *tp; - ABCEVENT *e; - int hslide; - hslide = h->track? h->track->slidevol: slide; - for( tp=h->track; tp; tp = tp->next ) { - if( slide ) { - tp->slidevoltime = tracktime; - if( slide == 2 ) - tp->slidevol = 0; - } - if( tp->slidevol > -2 && slide < 2 ) - tp->slidevol = slide; - } - if( h->track && h->track->tail - && hslide != slide && slide == -2 - && h->track->tail->tracktick >= tracktime ) { - // need to update jumptypes in mastertrack from tracktime on... - for( e=h->track->head; e; e=e->next ) { - if( e->flg == 1 && e->cmd == cmdjump && e->tracktick >= tracktime ) { - switch( e->par[jumptype] ) { - case jumpnormal: - case jumpfade: - e->par[jumptype] = jumpfade; - break; - case jumpdacapo: - case jumpdcfade: - e->par[jumptype] = jumpdcfade; - break; - case jumpdasegno: - case jumpdsfade: - e->par[jumptype] = jumpdsfade; - break; - } - } - } - } -} - -static void abc_recalculate_tracktime(ABCHANDLE *h) { - ABCTRACK *ttp; - h->tracktime = 0; - for( ttp=h->track; ttp; ttp=ttp->next ) - if( ttp->tail && ttp->tail->tracktick > h->tracktime ) - h->tracktime = ttp->tail->tracktick; -} - -static void abc_MIDI_command(ABCHANDLE *h, char *p, char delim) { - int t; - // interpret some of the possibilitys - if( !strncmp(p,"bassprog",8) && isspace(p[8]) ) h->abcbassprog = abc_MIDI_getprog(p+8)+1; - if( !strncmp(p,"bassvol",7) && isspace(p[7]) ) h->abcbassvol = abc_MIDI_getnumber(p+7); - if( !strncmp(p,"beat",4) && isspace(p[4]) ) abc_MIDI_beat(h, p+4); - if( !strncmp(p,"beatstring",10) && isspace(p[10]) ) abc_MIDI_beatstring(h, p+4); - if( !strncmp(p,"chordname",9) && isspace(p[9]) ) abc_MIDI_chordname(p+9); - if( !strncmp(p,"chordprog",9) && isspace(p[9]) ) h->abcchordprog = abc_MIDI_getprog(p+9)+1; - if( !strncmp(p,"chordvol",8) && isspace(p[8]) ) h->abcchordvol = abc_MIDI_getnumber(p+8); - if( !strncmp(p,"drone",5) && isspace(p[5]) ) abc_MIDI_drone(p+5, &h->dronegm, h->dronepitch, h->dronevol); - if( !strncmp(p,"droneoff",8) && (p[8]=='\0' || p[8]==delim || isspace(p[8])) ) h->droneon = 0; - if( !strncmp(p,"droneon",7) && (p[7]=='\0' || p[7]==delim || isspace(p[7])) ) h->droneon = 1; - t = h->drumon; - if( !strncmp(p,"drum",4) && isspace(p[4]) ) { - h->drumon = abc_MIDI_drum(p+4, h); - if( h->drumon ) --h->drumon; - else h->drumon = t; - } - if( !strncmp(p,"drumoff",7) && (p[7]=='\0' || p[7]==delim || isspace(p[7])) ) h->drumon = 0; - if( !strncmp(p,"drumon",6) && (p[6]=='\0' || p[6]==delim || isspace(p[6])) ) h->drumon = 1; - if( t != h->drumon ) { - if( h->drumon && !h->tpr ) h->tpr = h->track; - if( h->tpr ) abc_add_drum_sync(h, h->tpr, h->tracktime); // don't start drumming from the beginning of time! - if( h->tpr && !h->drumon ) h->tpr = NULL; - } - t = h->gchordon; - if( !strncmp(p,"gchord",6) && (p[6]=='\0' || p[6]==delim || isspace(p[6])) ) { - h->gchordon = abc_MIDI_gchord(p+6, h); - if( h->gchordon ) --h->gchordon; - else h->gchordon = t; - } - if( !strncmp(p,"gchordoff",9) && (p[9]=='\0' || p[9]==delim || isspace(p[9])) ) h->gchordon = 0; - if( !strncmp(p,"gchordon",8) && (p[8]=='\0' || p[8]==delim || isspace(p[8])) ) h->gchordon = 1; - if( t != h->gchordon ) { - if( h->tpc ) abc_add_gchord_syncs(h, h->tpc, h->tracktime); - } - if( !strncmp(p,"channel",7) && isspace(p[7]) ) - abc_MIDI_channel(p+8, h->tp = abc_check_track(h, h->tp), h); - if( !strncmp(p,"program",7) && isspace(p[7]) ) - abc_MIDI_program(p+8, h->tp = abc_check_track(h, h->tp), h); - if( !strncmp(p,"voice",5) && isspace(p[5]) ) - abc_MIDI_voice(p+6, h->tp = abc_check_track(h, h->tp), h); - if( !strncmp(p,"legato",6) && (p[6]=='\0' || p[6]==delim || isspace(p[6])) ) - abc_MIDI_legato(p+6, h->tp = abc_check_track(h, h->tp)); -} - -// continuate line that ends with a backslash, can't do this in abc_gets because voice lines -// can have comment lines in between that must be parsed properly, for example: -// [V:1] cdef gabc' |\ << continuation backslash -// %%MIDI program 25 -// c'bag fedc | -// informational lines can have this too, so it is rather convoluted code... -static char *abc_continuated(ABCHANDLE *h, MMFILE *mmf, char *p) { - char *pm, *p1, *p2 = 0; - int continued; - pm = p; - while( pm[strlen(pm)-1]=='\\' ) { - p1 = strdup(pm); - if( p2 ) free(p2); - continued = 1; - while( continued ) { - continued = 0; - pm = abc_gets(h, mmf); - if( !pm ) { - abc_message("line not properly continued\n%s", p1); - return p1; - } - while( *pm && isspace(*pm) ) ++pm; - if( !strncmp(pm,"%%",2) ) { - for( p2 = pm+2; *p2 && isspace(*p2); p2++ ) ; - if( !strncmp(p2,"MIDI",4) && (p2[4]=='=' || isspace(p2[4])) ) { - for( p2+=5; *p2 && isspace(*p2); p2++ ) ; - if( *p2 == '=' ) - for( p2+=1; *p2 && isspace(*p2); p2++ ) ; - abc_MIDI_command(h,p2,'%'); - } - continued = 1; - } - } - p2 = (char *)malloc(strlen(p1)+strlen(pm)); - if( !p2 ) { - abc_message("macro line too long\n%s", p1); - return p1; - } - p1[strlen(p1)-1] = '\0'; // strip off the backslash - strcpy(p2,p1); - strcat(p2,pm); - pm = p2; - free(p1); - } - return pm; -} - -// ===================================================================================== -#ifdef NEWMIKMOD -BOOL ABC_Load(ABCHANDLE *h, UNIMOD *of, MMSTREAM *mmfile) -#else -BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength) -#endif -{ - static int avoid_reentry = 0; -#ifdef NEWMIKMOD -#define m_nDefaultTempo of->inittempo -#else - ABCHANDLE *h; - uint32_t numpat; - MMFILE mm, *mmfile; -#endif - uint32_t t; - char *line, *p, *pp, ch, ch0=0; - char barsig[52]; // for propagated accidental key signature within bar - char *abcparts; - uint8_t partpat[27][2], *orderlist; - int orderlen; - enum { NOWHERE, INBETWEEN, INHEAD, INBODY, INSKIPFORX, INSKIPFORQUOTE } abcstate; - ABCEVENT_JUMPTYPE j; - ABCEVENT_X_EFFECT abceffect; - int abceffoper; - int abcxcount=0, abcxwanted=0, abcxnumber=1; - int abckey, abcrate, abcchord, abcvol, abcbeatvol, abcnoslurs, abcnolegato, abcfermata, abcarpeggio, abcto; - int abctempo; - int cnotelen=0, cnotediv=0, snotelen, snotediv, mnotelen, mnotediv, notelen, notediv; - // c for chords, s for standard L: setting, m for M: barlength - int abchornpipe, brokenrithm, tupletp, tupletq, tupletr; - int ktempo; - uint32_t abcgrace=0, bartime, thistime=0; - ABCTRACK *tpd, *ttp; - ABCMACRO *mp; - int mmsp; -#ifdef NEWMIKMOD - MMSTREAM *mmstack[MAXABCINCLUDES]; - h->ho = _mmalloc_create("Load_ABC_ORDERLIST", NULL); -#else - MMFILE *mmstack[MAXABCINCLUDES]; - if( !TestABC(lpStream, dwMemLength) ) return FALSE; - h = ABC_Init(); - if( !h ) return FALSE; - mmfile = &mm; - mm.mm = (char *)lpStream; - mm.sz = dwMemLength; - mm.pos = 0; -#endif - while( avoid_reentry ) sleep(1); - avoid_reentry = 1; - pat_resetsmp(); - pat_init_patnames(); - m_nDefaultTempo = 0; - global_voiceno = 0; - abckey = 0; - h->tracktime = 0; - global_songstart = 0; - h->speed = 6; - abcrate = 240; - global_tempo_factor = 2; - global_tempo_divider = 1; - abctempo = 0; - ktempo = 0; - abceffect = none; - abceffoper = 0; - abcvol = 120; - h->abcchordvol = abcvol; - h->abcbassvol = abcvol; - h->abcchordprog = 25; // acoustic guitar - h->abcbassprog = 33; // acoustic bass - abcparts = 0; - abcnoslurs = 1; - abcnolegato = 1; - abcfermata = 0; - abcarpeggio = 0; - abcto = 0; - snotelen = 0; - snotediv = 0; - mnotelen = 1; - mnotediv = 1; - abchornpipe = 0; - brokenrithm = 0; - tupletp = 0; - tupletq = 0; - tupletr = 0; - h->ktrans = 0; - h->drumon = 0; - h->gchordon = 1; - h->droneon = 0; - h->tracktime = 0; - bartime = 0; - h->tp = NULL; - h->tpc = NULL; - h->tpr = NULL; - tpd = NULL; - h->dronegm = 71; - h->dronepitch[0] = 45; - h->dronepitch[1] = 33; - h->dronevol[0] = 80; - h->dronevol[1] = 80; - abc_new_umacro(h, "v = +downbow+"); - abc_new_umacro(h, "u = +upbow+"); - abc_new_umacro(h, "O = +coda+"); - abc_new_umacro(h, "S = +segno+"); - abc_new_umacro(h, "P = +uppermordent+"); - abc_new_umacro(h, "M = +lowermordent+"); - abc_new_umacro(h, "L = +emphasis+"); - abc_new_umacro(h, "H = +fermata+"); - abc_new_umacro(h, "T = +trill+"); - abc_new_umacro(h, "~ = +roll+"); - abc_setup_chordnames(); - abc_init_partpat(partpat); - abc_MIDI_beat(h, ""); // reset beat array - abc_MIDI_beatstring(h, ""); // reset beatstring - orderlist = NULL; - orderlen = 0; - mmsp = 1; - mmstack[0] = mmfile; - mmfseek(mmfile,0,SEEK_SET); - abcstate = NOWHERE; - if( h->pickrandom ) { - abcstate = INSKIPFORX; - abcxcount = 0; - mmfseek(mmfile,0,SEEK_SET); - while( (line=abc_gets(h, mmfile)) ) { - for( p=line; isspace(*p); p++ ) ; - if( !strncmp(p,"X:",2) ) abcxcount++; - } - if( abcxcount == 0 ) - abcstate = NOWHERE; - else - abcxwanted = (h->pickrandom - 1) % abcxcount; - abcxcount = 0; - mmfseek(mmfile,0,SEEK_SET); - } - while( mmsp > 0 ) { - mmsp--; - while((line=abc_gets(h, mmstack[mmsp]))) { - for( p=line; isspace(*p); p++ ) ; - switch(abcstate) { - case INSKIPFORX: - if( !strncmp(p,"X:",2) ) { - if( abcxcount++ != abcxwanted ) - break; - } - // fall through - case INBETWEEN: - if( !strncmp(p,"X:",2) ) { - abcstate = INHEAD; -#ifdef NEWMIKMOD - of->songname = NULL; -#else - memset(m_szNames[0], 0, 32); -#endif - for( p+=2; isspace(*p); p++ ) ; - abcxnumber = atoi(p); - abchornpipe = 0; - h->droneon = 0; - h->dronegm = 71; - h->dronepitch[0] = 45; - h->dronepitch[1] = 33; - h->dronevol[0] = 80; - h->dronevol[1] = 80; - for( ttp = h->track; ttp; ttp=ttp->next ) { - ttp->vno = 0; // mark track unused - ttp->capostart = NULL; - } - h->tp = NULL; // forget old voices - h->tpc = NULL; - h->tpr = NULL; - global_voiceno = 0; - abc_set_parts(&abcparts, 0); - abcgrace = 0; - h->ktrans = 0; - ktempo = 0; - h->gchordon = 1; - h->drumon = 0; - global_songstart = h->tracktime; - abc_MIDI_beat(h, ""); // reset beat array - abc_MIDI_beatstring(h, ""); // reset beatstring - strcpy(h->gchord, ""); // reset gchord string - abcnolegato = 1; // reset legato switch - } - break; - case NOWHERE: - if( p[0] != '\0' && p[1] == ':' ) { - abcstate = INHEAD; - abc_set_parts(&abcparts, 0); - strcpy(h->gchord, ""); - if( h->drumon && h->tpr ) abc_add_drum_sync(h, h->tpr, h->tracktime); - if( h->tpc && !h->gchordon ) abc_add_gchord_syncs(h, h->tpc, h->tracktime); - h->gchordon = 1; - h->drumon = 0; - } - else - break; - case INHEAD: - if( !strncmp(p,"L:",2) ) { - sscanf(p+2," %d / %d", &snotelen, &snotediv); - break; - } - if( !strncmp(p,"M:",2) ) { - abc_M_field(p+2, &mnotelen, &mnotediv); - break; - } - if( !strncmp(p,"P:",2) ) { - abc_set_parts(&abcparts, p+2); - break; - } - if( !strncmp(p,"Q:",2) ) { - abctempo = abc_extract_tempo(p+2,0); - ktempo = 1; - if( h->track ) { - // make h->tracktime start of a new age... - abc_add_partbreak(h, h->track, h->tracktime); - abc_add_tempo_event(h, h->track, h->tracktime, abctempo); - } - if( m_nDefaultTempo == 0 ) m_nDefaultTempo = abctempo; - break; - } - if( !strncmp(p,"T:",2) ) { - char buf[200]; - if( strchr(p,'%') ) *strchr(p,'%') = '\0'; - for( t=strlen(p)-1; isspace(p[t]); t-- ) - p[t]='\0'; - for( t=2; isspace(p[t]); t++ ) ; -#ifdef NEWMIKMOD - if( of->songname ) - strcpy(buf,of->songname); - else - strcpy(buf,""); -#else - strcpy(buf,m_szNames[0]); -#endif - if( strlen(buf) + strlen(p+t) > 199 ) p[t+199-strlen(buf)] = '\0'; // chop it of - if( strlen(buf) ) strcat(buf," "); // add a space - strcat(buf, p+t); -#ifdef NEWMIKMOD - of->songname = DupStr(of->allochandle, buf, strlen(buf)); -#else - if( strlen(buf) > 31 ) buf[31] = '\0'; // chop it of - strcpy(m_szNames[0], buf); -#endif - break; - } - if( !strncmp(p,"R:",2) ) { - for( p+=2; isspace(*p); p++ ) ; - if( !strncmp(p,"hornpipe",8) && (isspace(p[8]) || p[8]=='\0') ) abchornpipe = 1; - else abchornpipe = 0; - break; - } - if( !strncmp(p,"V:",2) ) { - for( t=2; p[t]==' '; t++ ) ; - h->tp = abc_locate_track(h, p+t, 0); - abcvol = h->tp->volume; - abcnolegato = !h->tp->legato; - if( !abcnolegato ) abcnoslurs = 0; - break; - } - if( !strncmp(p,"K:",2) ) { - abcstate = INBODY; - abckey = ABC_Key(p+2); - sprintf(barsig, "%s%s", sig[abckey], sig[abckey]); // reset the key signature - p = abc_skip_word(p+2); - h->ktrans = abc_transpose(p); - *p = '%'; // force skip rest of line - if( snotelen == 0 ) { // calculate default notelen from meter M: - if( mnotediv == 0 ) mnotediv = mnotelen = 1; // do'nt get nuked - snotelen = 100 * mnotelen / mnotediv; - if( snotelen > 74 ) - snotediv = 8; - else - snotediv = 16; - snotelen = 1; - } - abceffect = none; - abceffoper = 0; - if( !(snotelen == 1 && snotediv == 8) ) abchornpipe = 0; // no matter what they said at R: - brokenrithm = 0; - global_part = ' '; - abcgrace = 0; - abcnoslurs = abcnolegato; - abcto = 0; - h->tpc = NULL; // reset chord track - tpd = NULL; // reset drone track - h->tpr = NULL; // reset drum track - if( !strlen(h->gchord) ) abc_metric_gchord(h, mnotelen, mnotediv); - h->barticks = notelen_notediv_to_ticks(h->speed, mnotelen, mnotediv); - if( abctempo && !ktempo ) { // did not set tempo in this songpiece so reset to abcrate - abctempo = 0; - global_tempo_factor = 2; - global_tempo_divider = 1; - if( h->track ) { - // make h->tracktime start of a new age... - abc_add_partbreak(h, h->track, h->tracktime); - abc_add_tempo_event(h, h->track, h->tracktime, abcrate); - } - if( m_nDefaultTempo == 0 ) m_nDefaultTempo = abcrate; - } - abc_init_partpat(partpat); - partpat[26][0] = abc_patno(h, h->tracktime); - partpat[26][1] = 0; - abc_globalslide(h, h->tracktime, 2); // reset all volumeslides - break; - } - if( !strlen(p) ) - abcstate = INBETWEEN; - break; - case INSKIPFORQUOTE: - while( (ch=*p++) && (ch != '"') ) - ; - if( !ch ) break; - abcstate = INBODY; - // fall through - case INBODY: - if( !strlen(p) && h->track ) { // end of this song - abcstate = h->pickrandom? INSKIPFORX: INBETWEEN; - // last but not least shut off all pending events - abc_recalculate_tracktime(h); - for( ttp=h->track; ttp; ttp=ttp->next ) - abc_add_noteoff(h,ttp,h->tracktime); - abc_add_partbreak(h, h->track, h->tracktime); - t = abc_patno(h, h->tracktime); - if( abc_pattracktime(h, h->tracktime) % abcticks(64 * h->speed) ) t++; - if( global_part == ' ' ) { - partpat[26][1] = t; - if( abcparts ) { - for( t=0; t<26; t++ ) - if( partpat[t][0] < partpat[t][1] ) break; - if( t == 26 ) { - abc_message("parts (%s) set but not used", abcparts); - abc_set_parts(&abcparts, 0); // forget the parts array - } - } - } - else - partpat[global_part - 'A'][1] = t; - if( !abcparts ) abc_song_to_parts(h, &abcparts, partpat); - orderlen = abc_partpat_to_orderlist(partpat, abcparts, h, &orderlist, orderlen); - } - if( !strncmp(p,"V:",2) ) { - for( t=2; p[t]==' '; t++ ) ; - h->tp = abc_locate_track(h, p+t, 0); - sprintf(barsig, "%s%s", sig[abckey], sig[abckey]); // reset the key signature - abcgrace = 0; - brokenrithm = 0; - h->tracktime = abc_tracktime(h->tp); - bartime = h->tracktime; // it is not friendly to break voices in the middle of a track... - abcnolegato = !h->tp->legato; - if( !abcnolegato ) abcnoslurs = 0; - *p = '%'; // make me skip the rest of the line.... - } - if( !strncmp(p,"K:",2) ) { - abckey = ABC_Key(p+2); - sprintf(barsig, "%s%s", sig[abckey], sig[abckey]); // reset the key signature - p = abc_skip_word(p+2); - h->ktrans = abc_transpose(p); - *p = '%'; // make me skip the rest of the line.... - } - if( !strncmp(p,"L:",2) ) { - sscanf(p+2," %d / %d", &snotelen, &snotediv); - *p = '%'; // make me skip the rest of the line.... - } - if( !strncmp(p,"M:",2) ) { - abc_M_field(p+2, &mnotelen, &mnotediv); - h->barticks = notelen_notediv_to_ticks(h->speed, mnotelen, mnotediv); - *p = '%'; // make me skip the rest of the line.... - } - if( !strncmp(p,"Q:",2) ) { - abctempo = abc_extract_tempo(p+2,ch0=='\\'); - if( !h->track ) { - h->tp = abc_check_track(h, h->track); - h->tp->vno = 0; // mark reuseable (temporarely, until first notes come up) - } - abc_add_tempo_event(h, h->track, h->tracktime, abctempo); - *p = '%'; // make me skip the rest of the line.... - } - if( !strncmp(p,"T:",2) ) { - char buf[200]; - if( strchr(p,'%') ) *strchr(p,'%') = '\0'; - for( t=strlen(p)-1; isspace(p[t]); t-- ) - p[t]='\0'; - for( t=2; isspace(p[t]); t++ ) ; -#ifdef NEWMIKMOD - if( of->songname ) - strcpy(buf,of->songname); - else - strcpy(buf,""); -#else - strcpy(buf,m_szNames[0]); -#endif - if( strlen(buf) + strlen(p+t) > 198 ) p[t+198-strlen(buf)] = '\0'; // chop it of - if( strlen(buf) ) strcat(buf," "); // add a space - strcat(buf, p+t); -#ifdef NEWMIKMOD - of->songname = DupStr(of->allochandle, buf, strlen(buf)); -#else - if( strlen(buf) > 31 ) buf[31] = '\0'; // chop it of - strcpy(m_szNames[0], buf); -#endif - *p = '%'; // make me skip the rest of the line.... - } - break; - } - if( !strncmp(p,"m:",2) ) { - if( abcstate != INSKIPFORX ) { - char *pm; - pm = abc_continuated(h, mmstack[mmsp], p); - abc_new_macro(h, pm+2); - if( pm != p ) { - free(pm); - if( h->tp ) abcnolegato = !h->tp->legato; - if( !abcnolegato ) abcnoslurs = 0; - } - } - *p = '%'; // skip rest of line - } - if( !strncmp(p,"U:",2) ) { - abc_new_umacro(h, p+2); - *p = '%'; // skip rest of line - } - if( !strncmp(p,"w:",2) ) { // inline lyrics - *p = '%'; // skip rest of line - } - if( !strncmp(p,"W:",2) ) { // lyrics at end of song body - *p = '%'; // skip rest of line - } - if( !strncmp(p,"d:",2) ) { // oldstyle decorations - abc_message("warning: old style decorations not handled\n%s", p); - *p = '%'; // skip rest of line - } - if( !strncmp(p,"s:",2) ) { // newstyle decorations (symbols) - abc_message("warning: new style decorations not handled\n%s", p); - *p = '%'; // skip rest of line - } - if( !strncmp(p,"I:",2) && abcstate != INSKIPFORX ) { // handle like oldstyle '%%command' lines - p[0]= '%'; - p[1]= '%'; - } - if( !strncmp(p,"%%",2) ) { - for( p+=2; *p && isspace(*p); p++ ) ; - if( !strncmp(p,"abc-include",11) && isspace(p[11]) ) { - for( t=12; isspace(p[t]); t++ ) ; - if( p[t] ) { - mmsp++; - if( mmsp == MAXABCINCLUDES ) { - mmsp--; - abc_message("failure: too many abc-include's, %s", &p[t]); - } else { - mmstack[mmsp] = mmfopen(&p[t], "r"); - if( !mmstack[mmsp] ) { - mmsp--; - abc_message("failure: abc-include file %s not found", &p[t]); - } - } - } - else abc_message("failure: abc-include missing file name, %s", p); - } - if( !strncmp(p,"MIDI",4) && (p[4]=='=' || isspace(p[4])) && abcstate != INSKIPFORX ) { - for( p+=5; *p && isspace(*p); p++ ) ; - if( *p == '=' ) - for( p+=1; *p && isspace(*p); p++ ) ; - abc_MIDI_command(h,p,'%'); - if( h->tp ) abcnolegato = !h->tp->legato; - if( !abcnolegato ) abcnoslurs = 0; - } - if(*p) *p = '%'; // skip rest of line - } - if( abcstate == INBODY ) { - if( *p == 'P' && p[1] == ':' ) { // a line with a part indication - if( abcparts != NULL ) { - // make h->tracktime start of a new age... - if( !h->track ) { - h->tp = abc_check_track(h, h->track); - h->tp->vno = 0; // mark reuseable (temporarely, until first notes come up) - } - h->tracktime = h->track? abc_tracktime(h->track): 0; // global parts are voice independent - abc_add_partbreak(h, h->track, h->tracktime); - t = abc_patno(h, h->tracktime); - if( global_part == ' ' ) { - partpat[26][1] = t; - if( abcparts ) { - for( t=0; t<26; t++ ) - if( partpat[t][0] < partpat[t][1] ) break; - if( t == 26 ) { - abc_message("parts (%s) set but not used", abcparts); - abc_set_parts(&abcparts, 0); // forget the parts array - } - } - } - else - partpat[global_part - 'A'][1] = t; - // give every new coming abcevent the desired part indication - while( p[2]==' ' || p[2]=='.' ) p++; // skip blancs and dots - if( isupper(p[2]) ) - global_part = p[2]; - else - global_part = ' '; - if( global_part == ' ' ) - partpat[26][0] = t; - else - partpat[global_part - 'A'][0] = t; - } - *p = '%'; // make me skip the rest of the line.... - } - if( h->droneon && !tpd ) { - tpd = h->track; - if( tpd ) { - tpd = abc_locate_track(h, tpd->v, DRONEPOS1); - tpd->instr = h->dronegm; - abc_add_dronenote(h, tpd, h->tracktime, h->dronepitch[0], h->dronevol[0]); - tpd = abc_locate_track(h, tpd->v, DRONEPOS2); - tpd->instr = h->dronegm; - abc_add_dronenote(h, tpd, h->tracktime, h->dronepitch[1], h->dronevol[1]); - } - } - if( tpd && !h->droneon ) { - tpd = abc_locate_track(h, tpd->v, DRONEPOS1); - abc_add_noteoff(h, tpd, h->tracktime); - tpd = abc_locate_track(h, tpd->v, DRONEPOS2); - abc_add_noteoff(h, tpd, h->tracktime); - tpd = NULL; - } - if( h->drumon && !h->tpr ) { - h->tpr = h->track; - if( h->tpr ) abc_add_drum_sync(h, h->tpr, h->tracktime); // don't start drumming from the beginning of time! - } - if( h->tpr && !h->drumon ) h->tpr = NULL; - if( *p != '%' ) { // skip uninteresting lines - // plough thru the songline gathering mos.... - ch0 = ' '; - pp = 0; - while( (ch = *p++) ) { - if( isalpha(ch) && *p != ':' ) { // maybe a macro - for( mp=h->umacro; mp; mp=mp->next ) { - if( ch == mp->name[0] ) { - pp = p; - p = mp->subst; - ch = *p++; - break; - } - } - } - switch(ch) { - case '%': - abcto = 0; - while( *p ) p++; - break; - case '[': // chord follows or some inline field - abcto = 0; - if( *p=='|' ) break; // [| a thick-thin bar line, loop around and let case '|' handle it - if( !strncmp(p,"V:",2) ) { // inline voice change - for( t=2; isspace(p[t]); t++ ) ; - h->tp = abc_locate_track(h, p+t, 0); - for( ; *p && *p != ']'; p++ ) ; - abcgrace = 0; - brokenrithm = 0; - sprintf(barsig, "%s%s", sig[abckey], sig[abckey]); // reset the key signature - h->tracktime = abc_tracktime(h->tp); - bartime = h->tracktime; // it is not wise to break voices in the middle of a track... - abcvol = h->tp->volume; - abcnolegato = !h->tp->legato; - if( !abcnolegato ) abcnoslurs = 0; - break; - } - if( !strncmp(p,"K:",2) ) { - abckey = ABC_Key(p+2); - sprintf(barsig, "%s%s", sig[abckey], sig[abckey]); // reset the key signature - p = abc_skip_word(p+2); - h->ktrans = abc_transpose(p); - for( ; *p && *p != ']'; p++ ) ; - break; - } - if( !strncmp(p,"M:",2) ) { - abc_M_field(p+2, &mnotelen, &mnotediv); - for( ; *p && *p != ']'; p++ ) ; - h->barticks = notelen_notediv_to_ticks(h->speed, mnotelen, mnotediv); - break; - } - if( !strncmp(p,"P:",2) ) { // a [P:X] field inline - if( abcparts != NULL ) { - // make h->tracktime start of a new age... - abc_add_partbreak(h, h->track, h->tracktime); - t = abc_patno(h, h->tracktime); - if( global_part == ' ' ) - partpat[26][1] = t; - else - partpat[global_part - 'A'][1] = t; - // give every new coming abcevent the desired part indication - while( isspace(p[2]) || p[2]=='.' ) p++; // skip blancs and dots - if( isupper(p[2]) ) - global_part = p[2]; - else - global_part = ' '; - if( global_part == ' ' ) - partpat[26][0] = t; - else - partpat[global_part - 'A'][0] = t; - } - for( ; *p && *p != ']'; p++ ) ; - break; - } - if( !strncmp(p,"Q:",2) ) { - abctempo = abc_extract_tempo(p+2,1); - for( ; *p && *p != ']'; p++ ) ; - abc_add_tempo_event(h, h->track, h->tracktime, abctempo); - break; - } - if( !strncmp(p,"I:",2) ) { // interpret some of the possibilitys - for( p += 2; isspace(*p); p++ ) ; - if( !strncmp(p,"MIDI",4) && (p[4]=='=' || isspace(p[4])) ) { // interpret some of the possibilitys - for( p += 4; isspace(*p); p++ ) ; - if( *p == '=' ) - for( p += 1; isspace(*p); p++ ) ; - abc_MIDI_command(h, p, ']'); - if( h->tp ) abcnolegato = !h->tp->legato; - if( !abcnolegato ) abcnoslurs = 0; - } - for( ; *p && *p != ']'; p++ ) ; // skip rest of inline field - } - if( *p && p[1] == ':' ) { // some other kind of inline field - for( ; *p && *p != ']'; p++ ) ; - break; - } - if( *p && strchr("abcdefgABCDEFG^_=",*p) ) { - int cnl[8],cnd[8],vnl,nl0=0,nd0=0; // for chords with notes of varying length - abcchord = 0; - vnl = 0; - h->tp = abc_check_track(h, h->tp); - abc_track_clear_tiedvpos(h); - abcbeatvol = abc_beat_vol(h, abcvol, (h->tracktime - bartime)/notelen_notediv_to_ticks(h->speed,1,mnotediv)); - while( (ch=*p++) && (ch != ']') ) { - h->tp = abc_locate_track(h, h->tp->v, abcchord? abcchord+DRONEPOS2: 0); - p += abc_add_noteon(h, ch, p, h->tracktime, barsig, abcbeatvol, abceffect, abceffoper); - p += abc_notelen(p, ¬elen, ¬ediv); - if( *p == '-' ) { - p++; - if( h->tp->tail->flg != 1 ) - h->tp->tienote = h->tp->tail; - } - if( abcchord<8 ) { - cnl[abcchord] = notelen; - cnd[abcchord] = notediv; - } - if( abcchord==0 ) { - cnotelen = notelen; - cnotediv = notediv; - nl0 = notelen; - nd0 = notediv; - } - else { - if( cnotelen != notelen || cnotediv != notediv ) { - vnl = 1; - // update to longest duration - if( cnotelen * notediv < notelen * cnotediv ) { - cnotelen = notelen; - cnotediv = notediv; - abc_track_untie_short_chordnotes(h); - } - if( cnotelen * notediv > notelen * cnotediv ) { - if( h->tp->tienote ) { - abc_message("short notes in chord can not be tied:\n%s", h->line); - h->tp->tienote = 0; // short chord notes cannot be tied... - } - } - // update to shortest duration - if( nl0 * notediv > notelen * nd0 ) { - nl0 = notelen; - nd0 = notediv; - } - } - } - abcchord++; - } - p += abc_notelen(p, ¬elen, ¬ediv); - if( (ch = *p) == '-' ) p++; // tied chord... - if( abcarpeggio ) { // update starttime in the noteon events... - thistime = notelen_notediv_to_ticks(h->speed, nl0*notelen*snotelen, nd0*notediv*snotediv)/abcchord; - if( thistime > abcticks(h->speed) ) thistime = abcticks(h->speed); - for( nl0=1; nl0<abcchord; nl0++ ) { - h->tp = abc_locate_track(h, h->tp->v, nl0+DRONEPOS2); - h->tp->tail->tracktick = h->tracktime + thistime * nl0; - } - } - notelen *= cnotelen; - notediv *= cnotediv; - tupletr = abc_tuplet(¬elen, ¬ediv, tupletp, tupletq, tupletr); - while( isspace(*p) ) p++; // allow spacing in broken rithm notation - p += abc_brokenrithm(p, ¬elen, ¬ediv, &brokenrithm, abchornpipe); - thistime = notelen_notediv_to_ticks(h->speed, notelen*snotelen, notediv*snotediv); - if( abcfermata ) { - thistime <<= 1; - abcfermata = 0; - } - if( thistime > abcgrace ) { - thistime -= abcgrace; - abcgrace = 0; - } - else { - abcgrace -= thistime; - thistime = abcticks(h->speed); - abcgrace += abcticks(h->speed); - } - h->tracktime += thistime; - while( abcchord>0 ) { - abcchord--; - h->tp = abc_locate_track(h, h->tp->v, abcchord? abcchord+DRONEPOS2: 0); - if( vnl && (abcchord < 8) && (cnl[abcchord] != cnotelen || cnd[abcchord] != cnotediv) ) { - abc_add_noteoff(h, h->tp, - h->tracktime - thistime - + (thistime * cnl[abcchord] * cnotediv)/(cnd[abcchord] * cnotelen) ); - } - else { - if( ch=='-' && h->tp->tail->flg != 1 ) - h->tp->tienote = h->tp->tail; // copy noteon event to tienote in track - if( thistime > abcticks(h->speed) ) - abc_add_noteoff(h, h->tp, h->tracktime - abcnoslurs); - else - abc_add_noteoff(h, h->tp, h->tracktime); - } - } - if( h->gchordon && (h->tp == h->tpc) ) - abc_add_gchord(h, h->tracktime, bartime); - if( h->drumon && (h->tp == h->tpr) ) - abc_add_drum(h, h->tracktime, bartime); - abcarpeggio = 0; - if( abceffoper != 255 ) abceffect = none; - break; - } - if( isdigit(*p) ) { // different endings in repeats [i,j,n-r,s,... - h->tp = abc_check_track(h, h->tp); - abc_add_partbreak(h, h->tp, h->tracktime); - p += abc_getnumber(p, ¬elen); - abc_add_variant_start(h, h->tp, h->tracktime, notelen); - while( *p==',' || *p=='-' ) { - if( *p==',' ) { - p++; - p += abc_getnumber(p, ¬elen); - abc_add_variant_choise(h->tp, notelen); - } - else { - p++; - p += abc_getnumber(p, ¬ediv); - while( notelen < notediv ) { - notelen++; - abc_add_variant_choise(h->tp, notelen); - } - } - } - break; - } - // collect the notes in the chord - break; - case '(': // slurs follow or some tuplet (duplet, triplet etc.) - abcto = 0; - if( isdigit(*p) ) { - p += abc_getnumber(p,&tupletp); - tupletr = tupletp; // ABC draft 2.0 (4.13): if r is not given it defaults to p - switch( tupletp ) { // ABC draft 2.0 (4.13): q defaults depending on p and time signature - case 2: case 4: case 8: - tupletq = 3; - break; - case 3: case 6: - tupletq = 2; - break; - default: - if( snotediv == 8 ) - tupletq = 3; - else - tupletq = 2; - break; - } - if( *p==':' ) { - p++; - if( isdigit(*p) ) p += abc_getnumber(p,&tupletq); - if( *p==':' ) { - p++; - if( isdigit(*p) ) p += abc_getnumber(p,&tupletr); - } - } - } - else - abcnoslurs=0; - break; - case ')': // end of slurs - abcto = 0; - abcnoslurs = abcnolegato; - break; - case '{': // grace notes follow - abcto = 0; - h->tp = abc_check_track(h, h->tp); - abc_track_clear_tiedvpos(h); - abcgrace = 0; - abcbeatvol = abc_beat_vol(h, abcvol, (h->tracktime - bartime)/notelen_notediv_to_ticks(h->speed,1,mnotediv)); - while( (ch=*p++) && (ch != '}') ) { - p += abc_add_noteon(h, ch, p, h->tracktime+abcgrace, barsig, abcbeatvol, none, 0); - p += abc_notelen(p, ¬elen, ¬ediv); - if( *p=='-' ) { - p++; - if( h->tp->tail->flg != 1 ) - h->tp->tienote = h->tp->tail; - } - notediv *= 4; // grace notes factor 4 shorter (1/8 => 1/32) - abcgrace += notelen_notediv_to_ticks(h->speed, notelen*snotelen, notediv*snotediv); - abc_add_noteoff(h, h->tp, h->tracktime + abcgrace); - } - h->tracktime += abcgrace; - abc_add_sync(h, h->tp, h->tracktime); - if( h->gchordon && (h->tp == h->tpc) ) - abc_add_gchord(h, h->tracktime, bartime); - if( h->drumon && (h->tp == h->tpr) ) - abc_add_drum(h, h->tracktime, bartime); - break; - case '|': // bar symbols - abcto = 0; - if( h->gchordon && h->tp && (h->tp == h->tpc) ) - abc_add_gchord(h, h->tracktime, bartime); - if( h->drumon && (h->tp == h->tpr) ) - abc_add_drum(h, h->tracktime, bartime); - sprintf(barsig, "%s%s", sig[abckey], sig[abckey]); // reset the key signature - bartime = h->tracktime; - if( h->tp && h->tp->vpos ) h->tp = abc_locate_track(h, h->tp->v, 0); // reset from voice overlay - if( isdigit(*p) ) { // different endings in repeats |i,j,n-r,s,... - h->tp = abc_check_track(h, h->tp); - abc_add_partbreak(h, h->tp, h->tracktime); - p += abc_getnumber(p, ¬elen); - abc_add_variant_start(h, h->tp, h->tracktime, notelen); - while( *p==',' || *p=='-' ) { - if( *p==',' ) { - p++; - p += abc_getnumber(p, ¬elen); - abc_add_variant_choise(h->tp, notelen); - } - else { - p++; - p += abc_getnumber(p, ¬ediv); - while( notelen < notediv ) { - notelen++; - abc_add_variant_choise(h->tp, notelen); - } - } - } - break; - } - if( *p==':' ) { // repeat start - p++; - h->tp = abc_check_track(h, h->tp); - abc_add_partbreak(h, h->tp, h->tracktime); - abc_add_setloop(h, h->tp, h->tracktime); - } - break; - case '&': // voice overlay - abcto = 0; - h->tracktime = bartime; - h->tp = abc_check_track(h, h->tp); - t = h->tp->vpos; - h->tp = abc_locate_track(h, h->tp->v, t? t+1: DRONEPOS2+1); - break; - case ']': // staff break, end of song - abcto = 0; - break; - case ':': // repeat jump - abcto = 0; - h->tp = abc_check_track(h, h->tp); - j = (h->tp->slidevol == -2)? jumpfade: jumpnormal; - abc_add_setjumploop(h, h->tp, h->tracktime, j); - abc_add_partbreak(h, h->tp, h->tracktime); - if( *p==':' ) { // repeat start without intermediate bar symbol - p++; - abc_add_setloop(h, h->tp, h->tracktime); - } - break; - case '"': // chord notation - if( !strchr("_^<>@", *p) && !isdigit(*p) ) { // if it's not a annotation string - h->tp = abc_check_track(h, h->tp); - if( !h->tpc ) h->tpc = abc_locate_track(h, h->tp->v, 0); - if( h->tp == h->tpc ) abc_add_chord(p, h, h->tpc, h->tracktime); // only do chords for one voice - } - abcto = 0; - while( (ch=*p++) && (ch != '"') ) { - if( !strncasecmp(p,"fade",4) && h->track && h->track->slidevol > -2 ) - abc_globalslide(h, h->tracktime, -2); // set volumeslide to fade away... - if( !strncasecmp(p,"to coda",7) ) { - h->tp = abc_check_track(h, h->tp); - abc_add_partbreak(h, h->tp, h->tracktime); - abc_add_tocoda(h, h->tp, h->tracktime); - p+=7; - abcto = -1; - } - else - if( !isspace(*p) ) abcto = 0; - if( !strncasecmp(p,"to",2) && (isspace(p[2]) || p[2] == '"') ) abcto = 1; - } - if( !ch ) abcstate = INSKIPFORQUOTE; - break; - case '\\': // skip the rest of this line, should be the end of the line anyway - while( (ch=*p++) ) - ; - ch = '\\'; // remember for invoice tempo changes.... - break; - case '!': // line break, or deprecated old style decoration - case '+': // decorations new style - if( !strncmp(p,"coda",4) && p[4] == ch ) { - h->tp = abc_check_track(h, h->tp); - if( abcto ) { - if( abcto > 0 ) { - abc_add_partbreak(h, h->tp, h->tracktime); - abc_add_tocoda(h, h->tp, h->tracktime); - } - } - else { - abc_add_partbreak(h, h->tp, h->tracktime); - abc_add_coda(h, h->tp, h->tracktime); - } - p += 5; - abcto = 0; - break; - } - abcto = 0; - if( !strncmp(p,"arpeggio",8) && p[8] == ch ) { - abcarpeggio = 1; - p += 9; - break; - } - if( !strncmp(p,"crescendo(",10) && p[10] == ch ) { - h->tp = abc_check_track(h, h->tp); - abc_globalslide(h, h->tracktime, 1); - p += 11; - break; - } - if( !strncmp(p,"crescendo)",10) && p[10] == ch ) { - h->tp = abc_check_track(h, h->tp); - abc_globalslide(h, h->tracktime, 0); - p += 11; - break; - } - if( !strncmp(p,"<(",2) && p[2] == ch ) { - h->tp = abc_check_track(h, h->tp); - abc_globalslide(h, h->tracktime, 1); - p += 3; - break; - } - if( !strncmp(p,"<)",2) && p[2] == ch ) { - h->tp = abc_check_track(h, h->tp); - abc_globalslide(h, h->tracktime, 0); - p += 3; - break; - } - if( !strncmp(p,"dimimuendo(",11) && p[11] == ch ) { - h->tp = abc_check_track(h, h->tp); - abc_globalslide(h, h->tracktime, -1); - p += 12; - break; - } - if( !strncmp(p,"diminuendo)",11) && p[11] == ch ) { - h->tp = abc_check_track(h, h->tp); - abc_globalslide(h, h->tracktime, 0); - p += 12; - break; - } - if( !strncmp(p,">(",2) && p[2] == ch ) { - h->tp = abc_check_track(h, h->tp); - abc_globalslide(h, h->tracktime, -1); - p += 3; - break; - } - if( !strncmp(p,">)",2) && p[2] == ch ) { - h->tp = abc_check_track(h, h->tp); - abc_globalslide(h, h->tracktime, 0); - p += 3; - break; - } - if( !strncmp(p,"upbow",5) && p[5] == ch ) { - abceffect = bow; - abceffoper = 1; - p += 6; - break; - } - if( !strncmp(p,"downbow",7) && p[7] == ch ) { - abceffect = bow; - abceffoper = 0; - p += 8; - break; - } - if( !strncmp(p,"trill",5) && p[5] == ch ) { - abceffect = trill; - abceffoper = 0; - p += 6; - break; - } - if( !strncmp(p,"trill(",6) && p[6] == ch ) { - abceffect = trill; - abceffoper = 255; - p += 7; - break; - } - if( !strncmp(p,"trill)",6) && p[6] == ch ) { - abceffect = none; - abceffoper = 0; - p += 7; - break; - } - if( !strncmp(p,"accent",6) && p[6] == ch ) { - abceffect = accent; - abceffoper = 0; - p += 7; - break; - } - if( !strncmp(p,"emphasis",8) && p[8] == ch ) { - abceffect = accent; - abceffoper = 0; - p += 9; - break; - } - if( !strncmp(p,">",1) && p[1] == ch ) { - abceffect = accent; - abceffoper = 0; - p += 2; - break; - } - if( !strncmp(p,"fermata",7) && p[7] == ch ) { - abcfermata = 1; - p += 8; - break; - } - if( !strncmp(p,"fine",4) && p[4] == ch ) { - h->tp = abc_check_track(h, h->tp); - abc_add_partbreak(h, h->tp, h->tracktime); - abc_add_fine(h, h->tp, h->tracktime); - p += 5; - break; - } - if( !strncmp(p,"segno",5) && p[5] == ch ) { - h->tp = abc_check_track(h, h->tp); - abc_add_partbreak(h, h->tp, h->tracktime); - abc_add_segno(h, h->tp, h->tracktime); - p += 6; - break; - } - if( !strncmp(p,"tocoda",6) && p[6] == ch ) { - h->tp = abc_check_track(h, h->tp); - abc_add_partbreak(h, h->tp, h->tracktime); - abc_add_tocoda(h, h->tp, h->tracktime); - p += 7; - break; - } - if( !strncmp(p,"D.C.",4) && p[4] == ch ) { - h->tp = abc_check_track(h, h->tp); - j = (h->tp->slidevol == -2)? jumpdcfade: jumpdacapo; - abc_add_setjumploop(h, h->tp, h->tracktime, j); - abc_add_partbreak(h, h->tp, h->tracktime); - p += 5; - break; - } - if( !strncmp(p,"D.S.",4) && p[4] == ch ) { - h->tp = abc_check_track(h, h->tp); - j = (h->tp->slidevol == -2)? jumpdsfade: jumpdasegno; - abc_add_setjumploop(h, h->tp, h->tracktime, j); - abc_add_partbreak(h, h->tp, h->tracktime); - p += 5; - break; - } - if( !strncmp(p,"dacapo",6) && p[6] == ch ) { - h->tp = abc_check_track(h, h->tp); - j = (h->tp->slidevol == -2)? jumpdcfade: jumpdacapo; - abc_add_setjumploop(h, h->tp, h->tracktime, j); - abc_add_partbreak(h, h->tp, h->tracktime); - p += 7; - break; - } - if( !strncmp(p,"dacoda",6) && p[6] == ch ) { - h->tp = abc_check_track(h, h->tp); - j = (h->tp->slidevol == -2)? jumpdcfade: jumpdacapo; - abc_add_setjumploop(h, h->tp, h->tracktime, j); - abc_add_partbreak(h, h->tp, h->tracktime); - p += 7; - break; - } - if( ch == '!' ) { - for( t=0; p[t] && strchr("|[:]!",p[t])==0 && !isspace(p[t]); t++ ) ; - if( p[t] == '!' ) { // volume and other decorations, deprecated - h->tp = abc_check_track(h, h->tp); - abcvol = abc_parse_decorations(h, h->tp, p); - p = &p[t+1]; - } - } - else { - h->tp = abc_check_track(h, h->tp); - abcvol = abc_parse_decorations(h, h->tp, p); - while( (ch=*p++) && (ch != '+') ) - ; - } - break; - case '`': // back quotes are for readability - break; - case '.': // staccato marks - break; - default: // some kinda note must follow - if( strchr("abcdefgABCDEFG^_=X",ch) ) { - h->tp = abc_check_track(h, h->tp); - abc_track_clear_tiedvpos(h); - abcbeatvol = abc_beat_vol(h, abcvol, (h->tracktime - bartime)/notelen_notediv_to_ticks(h->speed,1,mnotediv)); - p += abc_add_noteon(h, ch, p, h->tracktime, barsig, abcbeatvol, abceffect, abceffoper); - if( abceffoper != 255 ) abceffect = none; - p += abc_notelen(p, ¬elen, ¬ediv); - if( *p=='-' ) { - p++; - if( h->tp->tail->flg != 1 ) - h->tp->tienote = h->tp->tail; - } - tupletr = abc_tuplet(¬elen, ¬ediv, tupletp, tupletq, tupletr); - while( isspace(*p) ) p++; // allow spacing in broken rithm notation - p += abc_brokenrithm(p, ¬elen, ¬ediv, &brokenrithm, abchornpipe); - thistime = notelen_notediv_to_ticks(h->speed, notelen*snotelen, notediv*snotediv); - if( abcfermata ) { - thistime <<= 1; - abcfermata = 0; - } - if( thistime > abcgrace ) { - thistime -= abcgrace; - abcgrace = 0; - } - else { - abcgrace -= thistime; - thistime = abcticks(h->speed); - abcgrace += abcticks(h->speed); - } - h->tracktime += thistime; - if( thistime > abcticks(h->speed) ) - abc_add_noteoff(h, h->tp, h->tracktime - abcnoslurs - (( ch0 == '.')? thistime / 2: 0)); - else - abc_add_noteoff(h, h->tp, h->tracktime); - abc_add_sync(h, h->tp, h->tracktime); - if( h->gchordon && (h->tp == h->tpc) ) - abc_add_gchord(h, h->tracktime, bartime); - if( h->drumon && (h->tp == h->tpr) ) - abc_add_drum(h, h->tracktime, bartime); - abcarpeggio = 0; - break; - } - if( strchr("zx",ch) ) { - h->tp = abc_check_track(h, h->tp); - abc_track_clear_tiednote(h); - p += abc_notelen(p, ¬elen, ¬ediv); - tupletr = abc_tuplet(¬elen, ¬ediv, tupletp, tupletq, tupletr); - while( isspace(*p) ) p++; // allow spacing in broken rithm notation - p += abc_brokenrithm(p, ¬elen, ¬ediv, &brokenrithm, abchornpipe); - thistime = notelen_notediv_to_ticks(h->speed, notelen*snotelen, notediv*snotediv); - if( abcfermata ) { - thistime <<= 1; - abcfermata = 0; - } - if( thistime > abcgrace ) { - thistime -= abcgrace; - abcgrace = 0; - } - else { - abcgrace -= thistime; - thistime = abcticks(h->speed); - abcgrace += abcticks(h->speed); - } - h->tracktime += thistime; - abc_add_sync(h, h->tp, h->tracktime); - if( h->gchordon && (h->tp == h->tpc) ) - abc_add_gchord(h, h->tracktime, bartime); - if( h->drumon && (h->tp == h->tpr) ) - abc_add_drum(h, h->tracktime, bartime); - abcarpeggio = 0; - break; - } - if( strchr("Z",ch) ) { - h->tp = abc_check_track(h, h->tp); - abc_track_clear_tiednote(h); - p += abc_notelen(p, ¬elen, ¬ediv); - thistime = notelen_notediv_to_ticks(h->speed, notelen*mnotelen, notediv*mnotediv); - if( abcfermata ) { - thistime <<= 1; - abcfermata = 0; - } - if( thistime > abcgrace ) { - thistime -= abcgrace; - abcgrace = 0; - } - else { - abcgrace -= thistime; - thistime = abcticks(h->speed); - abcgrace += abcticks(h->speed); - } - h->tracktime += thistime; - sprintf(barsig, "%s%s", sig[abckey], sig[abckey]); // reset the key signature - abc_add_sync(h, h->tp, h->tracktime); - if( h->gchordon && (h->tp == h->tpc) ) - abc_add_gchord(h, h->tracktime, bartime); - if( h->drumon && (h->tp == h->tpr) ) - abc_add_drum(h, h->tracktime, bartime); - abcarpeggio = 0; - break; - } - if( isalpha(ch) && *p==':' ) { - // some unprocessed field line? - while( *p ) p++; // skip it - break; - } - break; - } - ch0 = ch; // remember previous char, can be staccato dot... - if( pp ) { // did we have a U: macro substitution? - if( !*p ) { - p = pp; - pp = 0; - } - } - } - } - } - } - if( mmsp ) mmfclose(mmstack[mmsp]); - } - ABC_CleanupMacros(h); // we dont need them anymore - if( !h->track ) { - char buf[10]; - sprintf(buf,"%d",abcxnumber); - abc_message("abc X:%s has no body", buf); - h->track = abc_check_track(h, h->track); // for sanity... - } - if( abcstate == INBODY ) { - // last but not least shut off all pending events - abc_recalculate_tracktime(h); - for( ttp=h->track; ttp; ttp=ttp->next ) - abc_add_noteoff(h,ttp,h->tracktime); - abc_add_partbreak(h, h->track, h->tracktime); - t = abc_patno(h, h->tracktime); - if( abc_pattracktime(h, h->tracktime) % abcticks(64 * h->speed) ) t++; - if( global_part == ' ' ) { - partpat[26][1] = t; - if( abcparts ) { - for( t=0; t<26; t++ ) - if( partpat[t][0] < partpat[t][1] ) break; - if( t == 26 ) { - abc_message("parts (%s) set but not used", abcparts); - abc_set_parts(&abcparts, 0); // forget the parts array - } - } - } - else - partpat[global_part - 'A'][1] = t; - if( !abcparts ) abc_song_to_parts(h, &abcparts, partpat); - orderlen = abc_partpat_to_orderlist(partpat, abcparts, h, &orderlist, orderlen); - } - abc_synchronise_tracks(h); // distribute all control events - abc_recalculate_tracktime(h); -/* - - abctrack: - tracktick long - note byte - octave byte - instrument byte - effects byte - - tick = tracktick modulo speed - row = (tracktick div speed) modulo 64 - pat = (tracktick div speed) div 64 - ord = calculated - -*/ - if( (p=getenv(ABC_ENV_DUMPTRACKS)) ) { - printf("P:%s\n",abcparts); - for( t=0; t<26; t++ ) - if( partpat[t][1] >= partpat[t][0] ) - printf(" %c ",t+'A'); - if( partpat[26][1] >= partpat[26][0] ) - printf("All"); - printf("\n"); - for( t=0; t<27; t++ ) - if( partpat[t][1] >= partpat[t][0] ) - printf("%3d ",partpat[t][0]); - printf("\n"); - for( t=0; t<27; t++ ) - if( partpat[t][1] >= partpat[t][0] ) - printf("%3d ",partpat[t][1]); - printf("\n"); - for( t=0; (int)t<orderlen; t++ ) - printf("%3d ",t); - printf("\n"); - for( t=0; (int)t<orderlen; t++ ) - printf("%3d ",orderlist[t]); - printf("\n"); - abc_dumptracks(h,p); - } - // set module variables - if( abctempo == 0 ) abctempo = abcrate; - if( m_nDefaultTempo == 0 ) m_nDefaultTempo = abctempo; -#ifdef NEWMIKMOD - of->memsize = PTMEM_LAST; // Number of memory slots to reserve! - of->modtype = _mm_strdup(of->allochandle, ABC_Version); - of->numpat = 1+(modticks(h->tracktime) / h->speed / 64); - of->numpos = orderlen; - of->reppos = 0; - of->initspeed = h->speed; - of->numchn = abc_numtracks(h); - of->numtrk = of->numpat * of->numchn; - of->initvolume = 64; - of->pansep = 128; - // orderlist - if(!AllocPositions(of, orderlen)) { - avoid_reentry = 0; - return FALSE; - } - for(t=0; t<orderlen; t++) - of->positions[t] = orderlist[t]; - _mmalloc_close(h->ho); // get rid of orderlist memory -#else - m_nType = MOD_TYPE_ABC; - numpat = 1+(modticks(h->tracktime) / h->speed / 64); - m_nDefaultSpeed = h->speed; - m_nChannels = abc_numtracks(h); - m_dwSongFlags = SONG_LINEARSLIDES; - m_nMinPeriod = 28 << 2; - m_nMaxPeriod = 1712 << 3; - // orderlist - for(t=0; t < (uint32_t)orderlen; t++) - Order[t] = orderlist[t]; - free(orderlist); // get rid of orderlist memory -#endif -#ifdef NEWMIKMOD - // ============================== - // Load the pattern info now! - if(!AllocTracks(of)) return 0; - if(!AllocPatterns(of)) return 0; - of->ut = utrk_init(of->numchn, h->allochandle); - utrk_memory_reset(of->ut); - utrk_local_memflag(of->ut, PTMEM_PORTAMENTO, TRUE, FALSE); - ABC_ReadPatterns(of, h, of->numpat); - // load instruments after building the patterns (chan == 10 track handling) - if( !PAT_Load_Instruments(of) ) { - avoid_reentry = 0; - return FALSE; - } - // ============================================================ - // set panning positions - for(t=0; t<of->numchn; t++) { - of->panning[t] = PAN_LEFT+((t+2)%5)*((PAN_RIGHT - PAN_LEFT)/5); // 0x30 = std s3m val - } -#else - // ============================== - // Load the pattern info now! - if( ABC_ReadPatterns(Patterns, PatternSize, h, numpat, m_nChannels) ) { - // :^( need one more channel to handle the global events ;^b - m_nChannels++; - h->tp = abc_locate_track(h, "", 99); - abc_add_sync(h, h->tp, h->tracktime); - for( t=0; t<numpat; t++ ) { - FreePattern(Patterns[t]); - Patterns[t] = NULL; - } - ABC_ReadPatterns(Patterns, PatternSize, h, numpat, m_nChannels); - } - // load instruments after building the patterns (chan == 10 track handling) - if( !PAT_Load_Instruments(this) ) { - avoid_reentry = 0; - return FALSE; - } - // ============================================================ - // set panning positions - for(t=0; t<m_nChannels; t++) { - ChnSettings[t].nPan = 0x30+((t+2)%5)*((0xD0 - 0x30)/5); // 0x30 = std s3m val - ChnSettings[t].nVolume = 64; - } -#endif - avoid_reentry = 0; // it is safe now, I'm finished - abc_set_parts(&abcparts, 0); // free the parts array -#ifndef NEWMIKMOD - ABC_Cleanup(h); // we dont need it anymore -#endif - return 1; -} - -#ifdef NEWMIKMOD -// ===================================================================================== -CHAR *ABC_LoadTitle(MMSTREAM *mmfile) -// ===================================================================================== -{ - char s[128]; - int i; - // get the first line with T:songtitle - _mm_fseek(mmfile,0,SEEK_SET); - while(abc_fgets(mmfile,s,128)) { - if( s[0]=='T' && s[1]==':' ) { - for( i=2; s[i]==' '; i++ ) ; - return(DupStr(NULL, s+i,strlen(s+i))); - } - } - return NULL; -} - -MLOADER load_abc = -{ - "ABC", - "ABC draft 2.0", - 0x30, - NULL, - ABC_Test, - (void *(*)(void))ABC_Init, - (void (*)(ML_HANDLE *))ABC_Cleanup, - /* Every single loader seems to need one of these! */ - (BOOL (*)(ML_HANDLE *, UNIMOD *, MMSTREAM *))ABC_Load, - ABC_LoadTitle -}; -#endif diff --git a/lib/libmodplug/src/load_amf.cpp b/lib/libmodplug/src/load_amf.cpp deleted file mode 100644 index dd806a0787..0000000000 --- a/lib/libmodplug/src/load_amf.cpp +++ /dev/null @@ -1,418 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque <olivierl@jps.net> -*/ - -/////////////////////////////////////////////////// -// -// AMF module loader -// -// There is 2 types of AMF files: -// - ASYLUM Music Format -// - Advanced Music Format(DSM) -// -/////////////////////////////////////////////////// -#include "stdafx.h" -#include "sndfile.h" - -//#define AMFLOG - -//#pragma warning(disable:4244) - -#pragma pack(1) - -typedef struct _AMFFILEHEADER -{ - UCHAR szAMF[3]; - UCHAR version; - CHAR title[32]; - UCHAR numsamples; - UCHAR numorders; - USHORT numtracks; - UCHAR numchannels; -} AMFFILEHEADER; - -typedef struct _AMFSAMPLE -{ - UCHAR type; - CHAR samplename[32]; - CHAR filename[13]; - ULONG offset; - ULONG length; - USHORT c2spd; - UCHAR volume; -} AMFSAMPLE; - - -#pragma pack() - - -#ifdef AMFLOG -extern void Log(LPCSTR, ...); -#endif - -VOID AMF_Unpack(MODCOMMAND *pPat, const BYTE *pTrack, UINT nRows, UINT nChannels) -//------------------------------------------------------------------------------- -{ - UINT lastinstr = 0; - UINT nTrkSize = bswapLE16(*(USHORT *)pTrack); - nTrkSize += (UINT)pTrack[2] << 16; - pTrack += 3; - while (nTrkSize--) - { - UINT row = pTrack[0]; - UINT cmd = pTrack[1]; - UINT arg = pTrack[2]; - if (row >= nRows) break; - MODCOMMAND *m = pPat + row * nChannels; - if (cmd < 0x7F) // note+vol - { - m->note = cmd+1; - if (!m->instr) m->instr = lastinstr; - m->volcmd = VOLCMD_VOLUME; - m->vol = arg; - } else - if (cmd == 0x7F) // duplicate row - { - signed char rdelta = (signed char)arg; - int rowsrc = (int)row + (int)rdelta; - if ((rowsrc >= 0) && (rowsrc < (int)nRows)) memcpy(m, &pPat[rowsrc*nChannels],sizeof(pPat[rowsrc*nChannels])); - } else - if (cmd == 0x80) // instrument - { - m->instr = arg+1; - lastinstr = m->instr; - } else - if (cmd == 0x83) // volume - { - m->volcmd = VOLCMD_VOLUME; - m->vol = arg; - } else - // effect - { - UINT command = cmd & 0x7F; - UINT param = arg; - switch(command) - { - // 0x01: Set Speed - case 0x01: command = CMD_SPEED; break; - // 0x02: Volume Slide - // 0x0A: Tone Porta + Vol Slide - // 0x0B: Vibrato + Vol Slide - case 0x02: command = CMD_VOLUMESLIDE; - case 0x0A: if (command == 0x0A) command = CMD_TONEPORTAVOL; - case 0x0B: if (command == 0x0B) command = CMD_VIBRATOVOL; - if (param & 0x80) param = (-(signed char)param)&0x0F; - else param = (param&0x0F)<<4; - break; - // 0x04: Porta Up/Down - case 0x04: if (param & 0x80) { command = CMD_PORTAMENTOUP; param = (-(signed char)param)&0x7F; } - else { command = CMD_PORTAMENTODOWN; } break; - // 0x06: Tone Portamento - case 0x06: command = CMD_TONEPORTAMENTO; break; - // 0x07: Tremor - case 0x07: command = CMD_TREMOR; break; - // 0x08: Arpeggio - case 0x08: command = CMD_ARPEGGIO; break; - // 0x09: Vibrato - case 0x09: command = CMD_VIBRATO; break; - // 0x0C: Pattern Break - case 0x0C: command = CMD_PATTERNBREAK; break; - // 0x0D: Position Jump - case 0x0D: command = CMD_POSITIONJUMP; break; - // 0x0F: Retrig - case 0x0F: command = CMD_RETRIG; break; - // 0x10: Offset - case 0x10: command = CMD_OFFSET; break; - // 0x11: Fine Volume Slide - case 0x11: if (param) { command = CMD_VOLUMESLIDE; - if (param & 0x80) param = 0xF0|((-(signed char)param)&0x0F); - else param = 0x0F|((param&0x0F)<<4); - } else command = 0; break; - // 0x12: Fine Portamento - // 0x16: Extra Fine Portamento - case 0x12: - case 0x16: if (param) { int mask = (command == 0x16) ? 0xE0 : 0xF0; - command = (param & 0x80) ? CMD_PORTAMENTOUP : CMD_PORTAMENTODOWN; - if (param & 0x80) param = mask|((-(signed char)param)&0x0F); - else param |= mask; - } else command = 0; break; - // 0x13: Note Delay - case 0x13: command = CMD_S3MCMDEX; param = 0xD0|(param & 0x0F); break; - // 0x14: Note Cut - case 0x14: command = CMD_S3MCMDEX; param = 0xC0|(param & 0x0F); break; - // 0x15: Set Tempo - case 0x15: command = CMD_TEMPO; break; - // 0x17: Panning - case 0x17: param = (param+64)&0x7F; - if (m->command) { if (!m->volcmd) { m->volcmd = VOLCMD_PANNING; m->vol = param/2; } command = 0; } - else { command = CMD_PANNING8; } - // Unknown effects - default: command = param = 0; - } - if (command) - { - m->command = command; - m->param = param; - } - } - pTrack += 3; - } -} - - - -BOOL CSoundFile::ReadAMF(LPCBYTE lpStream, const DWORD dwMemLength) -//----------------------------------------------------------- -{ - const AMFFILEHEADER *pfh = (AMFFILEHEADER *)lpStream; - DWORD dwMemPos; - - if ((!lpStream) || (dwMemLength < 2048)) return FALSE; - if ((!strncmp((LPCTSTR)lpStream, "ASYLUM Music Format V1.0", 25)) && (dwMemLength > 4096)) - { - UINT numorders, numpats, numsamples; - - dwMemPos = 32; - numpats = lpStream[dwMemPos+3]; - numorders = lpStream[dwMemPos+4]; - numsamples = 64; - dwMemPos += 6; - if ((!numpats) || (numpats > MAX_PATTERNS) || (!numorders) - || (numpats*64*32 + 294 + 37*64 >= dwMemLength)) return FALSE; - m_nType = MOD_TYPE_AMF0; - m_nChannels = 8; - m_nInstruments = 0; - m_nSamples = 31; - m_nDefaultTempo = 125; - m_nDefaultSpeed = 6; - for (UINT iOrd=0; iOrd<MAX_ORDERS; iOrd++) - { - Order[iOrd] = (iOrd < numorders) ? lpStream[dwMemPos+iOrd] : 0xFF; - } - dwMemPos = 294; // ??? - for (UINT iSmp=0; iSmp<numsamples; iSmp++) - { - MODINSTRUMENT *psmp = &Ins[iSmp+1]; - memcpy(m_szNames[iSmp+1], lpStream+dwMemPos, 22); - psmp->nFineTune = MOD2XMFineTune(lpStream[dwMemPos+22]); - psmp->nVolume = lpStream[dwMemPos+23]; - psmp->nGlobalVol = 64; - if (psmp->nVolume > 0x40) psmp->nVolume = 0x40; - psmp->nVolume <<= 2; - psmp->nLength = bswapLE32(*((LPDWORD)(lpStream+dwMemPos+25))); - psmp->nLoopStart = bswapLE32(*((LPDWORD)(lpStream+dwMemPos+29))); - psmp->nLoopEnd = psmp->nLoopStart + bswapLE32(*((LPDWORD)(lpStream+dwMemPos+33))); - if ((psmp->nLoopEnd > psmp->nLoopStart) && (psmp->nLoopEnd <= psmp->nLength)) - { - psmp->uFlags = CHN_LOOP; - } else - { - psmp->nLoopStart = psmp->nLoopEnd = 0; - } - if ((psmp->nLength) && (iSmp>31)) m_nSamples = iSmp+1; - dwMemPos += 37; - } - for (UINT iPat=0; iPat<numpats; iPat++) - { - MODCOMMAND *p = AllocatePattern(64, m_nChannels); - if (!p) break; - Patterns[iPat] = p; - PatternSize[iPat] = 64; - const UCHAR *pin = lpStream + dwMemPos; - for (UINT i=0; i<8*64; i++) - { - p->note = 0; - - if (pin[0]) - { - p->note = pin[0] + 13; - } - p->instr = pin[1]; - p->command = pin[2]; - p->param = pin[3]; - if (p->command > 0x0F) - { - #ifdef AMFLOG - Log("0x%02X.0x%02X ?", p->command, p->param); - #endif - p->command = 0; - } - ConvertModCommand(p); - pin += 4; - p++; - } - dwMemPos += 64*32; - } - // Read samples - for (UINT iData=0; iData<m_nSamples; iData++) - { - MODINSTRUMENT *psmp = &Ins[iData+1]; - if (psmp->nLength) - { - if (dwMemPos > dwMemLength) return FALSE; - dwMemPos += ReadSample(psmp, RS_PCM8S, (LPCSTR)(lpStream+dwMemPos), dwMemLength); - } - } - return TRUE; - } - //////////////////////////// - // DSM/AMF - USHORT *ptracks[MAX_PATTERNS]; - DWORD sampleseekpos[MAX_SAMPLES]; - - if ((pfh->szAMF[0] != 'A') || (pfh->szAMF[1] != 'M') || (pfh->szAMF[2] != 'F') - || (pfh->version < 10) || (pfh->version > 14) || (!bswapLE16(pfh->numtracks)) - || (!pfh->numorders) || (pfh->numorders > MAX_PATTERNS) - || (!pfh->numsamples) || (pfh->numsamples > MAX_SAMPLES) - || (pfh->numchannels < 4) || (pfh->numchannels > 32)) - return FALSE; - memcpy(m_szNames[0], pfh->title, 32); - dwMemPos = sizeof(AMFFILEHEADER); - m_nType = MOD_TYPE_AMF; - m_nChannels = pfh->numchannels; - m_nSamples = pfh->numsamples; - m_nInstruments = 0; - // Setup Channel Pan Positions - if (pfh->version >= 11) - { - signed char *panpos = (signed char *)(lpStream + dwMemPos); - UINT nchannels = (pfh->version >= 13) ? 32 : 16; - for (UINT i=0; i<nchannels; i++) - { - int pan = (panpos[i] + 64) * 2; - if (pan < 0) pan = 0; - if (pan > 256) { pan = 128; ChnSettings[i].dwFlags |= CHN_SURROUND; } - ChnSettings[i].nPan = pan; - } - dwMemPos += nchannels; - } else - { - for (UINT i=0; i<16; i++) - { - ChnSettings[i].nPan = (lpStream[dwMemPos+i] & 1) ? 0x30 : 0xD0; - } - dwMemPos += 16; - } - // Get Tempo/Speed - m_nDefaultTempo = 125; - m_nDefaultSpeed = 6; - if (pfh->version >= 13) - { - if (lpStream[dwMemPos] >= 32) m_nDefaultTempo = lpStream[dwMemPos]; - if (lpStream[dwMemPos+1] <= 32) m_nDefaultSpeed = lpStream[dwMemPos+1]; - dwMemPos += 2; - } - // Setup sequence list - for (UINT iOrd=0; iOrd<MAX_ORDERS; iOrd++) - { - Order[iOrd] = 0xFF; - if (iOrd < pfh->numorders) - { - Order[iOrd] = iOrd; - PatternSize[iOrd] = 64; - if (pfh->version >= 14) - { - PatternSize[iOrd] = bswapLE16(*(USHORT *)(lpStream+dwMemPos)); - dwMemPos += 2; - } - ptracks[iOrd] = (USHORT *)(lpStream+dwMemPos); - dwMemPos += m_nChannels * sizeof(USHORT); - } - } - if (dwMemPos + m_nSamples * (sizeof(AMFSAMPLE)+8) > dwMemLength) return TRUE; - // Read Samples - UINT maxsampleseekpos = 0; - for (UINT iIns=0; iIns<m_nSamples; iIns++) - { - MODINSTRUMENT *pins = &Ins[iIns+1]; - AMFSAMPLE *psh = (AMFSAMPLE *)(lpStream + dwMemPos); - - dwMemPos += sizeof(AMFSAMPLE); - memcpy(m_szNames[iIns+1], psh->samplename, 32); - memcpy(pins->name, psh->filename, 13); - pins->nLength = bswapLE32(psh->length); - pins->nC4Speed = bswapLE16(psh->c2spd); - pins->nGlobalVol = 64; - pins->nVolume = psh->volume * 4; - if (pfh->version >= 11) - { - pins->nLoopStart = bswapLE32(*(DWORD *)(lpStream+dwMemPos)); - pins->nLoopEnd = bswapLE32(*(DWORD *)(lpStream+dwMemPos+4)); - dwMemPos += 8; - } else - { - pins->nLoopStart = bswapLE16(*(WORD *)(lpStream+dwMemPos)); - pins->nLoopEnd = pins->nLength; - dwMemPos += 2; - } - sampleseekpos[iIns] = 0; - if ((psh->type) && (bswapLE32(psh->offset) < dwMemLength-1)) - { - sampleseekpos[iIns] = bswapLE32(psh->offset); - if (bswapLE32(psh->offset) > maxsampleseekpos) - maxsampleseekpos = bswapLE32(psh->offset); - if ((pins->nLoopEnd > pins->nLoopStart + 2) - && (pins->nLoopEnd <= pins->nLength)) pins->uFlags |= CHN_LOOP; - } - } - // Read Track Mapping Table - USHORT *pTrackMap = (USHORT *)(lpStream+dwMemPos); - UINT realtrackcnt = 0; - dwMemPos += pfh->numtracks * sizeof(USHORT); - for (UINT iTrkMap=0; iTrkMap<pfh->numtracks; iTrkMap++) - { - if (realtrackcnt < pTrackMap[iTrkMap]) realtrackcnt = pTrackMap[iTrkMap]; - } - // Store tracks positions - BYTE **pTrackData = new BYTE *[realtrackcnt]; - memset(pTrackData, 0, sizeof(pTrackData)); - for (UINT iTrack=0; iTrack<realtrackcnt; iTrack++) if (dwMemPos + 3 <= dwMemLength) - { - UINT nTrkSize = bswapLE16(*(USHORT *)(lpStream+dwMemPos)); - nTrkSize += (UINT)lpStream[dwMemPos+2] << 16; - if (dwMemPos + nTrkSize * 3 + 3 <= dwMemLength) - { - pTrackData[iTrack] = (BYTE *)(lpStream + dwMemPos); - } - dwMemPos += nTrkSize * 3 + 3; - } - // Create the patterns from the list of tracks - for (UINT iPat=0; iPat<pfh->numorders; iPat++) - { - MODCOMMAND *p = AllocatePattern(PatternSize[iPat], m_nChannels); - if (!p) break; - Patterns[iPat] = p; - for (UINT iChn=0; iChn<m_nChannels; iChn++) - { - UINT nTrack = bswapLE16(ptracks[iPat][iChn]); - if ((nTrack) && (nTrack <= pfh->numtracks)) - { - UINT realtrk = bswapLE16(pTrackMap[nTrack-1]); - if (realtrk) - { - realtrk--; - if ((realtrk < realtrackcnt) && (pTrackData[realtrk])) - { - AMF_Unpack(p+iChn, pTrackData[realtrk], PatternSize[iPat], m_nChannels); - } - } - } - } - } - delete[] pTrackData; - // Read Sample Data - for (UINT iSeek=1; iSeek<=maxsampleseekpos; iSeek++) - { - if (dwMemPos >= dwMemLength) break; - for (UINT iSmp=0; iSmp<m_nSamples; iSmp++) if (iSeek == sampleseekpos[iSmp]) - { - MODINSTRUMENT *pins = &Ins[iSmp+1]; - dwMemPos += ReadSample(pins, RS_PCM8U, (LPCSTR)(lpStream+dwMemPos), dwMemLength-dwMemPos); - break; - } - } - return TRUE; -} - diff --git a/lib/libmodplug/src/load_ams.cpp b/lib/libmodplug/src/load_ams.cpp deleted file mode 100644 index c5f12dc99a..0000000000 --- a/lib/libmodplug/src/load_ams.cpp +++ /dev/null @@ -1,628 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque <olivierl@jps.net> -*/ - -////////////////////////////////////////////// -// AMS module loader // -////////////////////////////////////////////// -#include "stdafx.h" -#include "sndfile.h" - -//#pragma warning(disable:4244) - -#pragma pack(1) - -typedef struct AMSFILEHEADER -{ - char szHeader[7]; // "Extreme" // changed from CHAR - BYTE verlo, verhi; // 0x??,0x01 - BYTE chncfg; - BYTE samples; - WORD patterns; - WORD orders; - BYTE vmidi; - WORD extra; -} AMSFILEHEADER; - -typedef struct AMSSAMPLEHEADER -{ - DWORD length; - DWORD loopstart; - DWORD loopend; - BYTE finetune_and_pan; - WORD samplerate; // C-2 = 8363 - BYTE volume; // 0-127 - BYTE infobyte; -} AMSSAMPLEHEADER; - - -#pragma pack() - - - -BOOL CSoundFile::ReadAMS(LPCBYTE lpStream, DWORD dwMemLength) -//----------------------------------------------------------- -{ - BYTE pkinf[MAX_SAMPLES]; - AMSFILEHEADER *pfh = (AMSFILEHEADER *)lpStream; - DWORD dwMemPos; - UINT tmp, tmp2; - - if ((!lpStream) || (dwMemLength < 1024)) return FALSE; - if ((pfh->verhi != 0x01) || (strncmp(pfh->szHeader, "Extreme", 7)) - || (!pfh->patterns) || (!pfh->orders) || (!pfh->samples) || (pfh->samples > MAX_SAMPLES) - || (pfh->patterns > MAX_PATTERNS) || (pfh->orders > MAX_ORDERS)) - { - return ReadAMS2(lpStream, dwMemLength); - } - dwMemPos = sizeof(AMSFILEHEADER) + pfh->extra; - if (dwMemPos + pfh->samples * sizeof(AMSSAMPLEHEADER) + 256 >= dwMemLength) return FALSE; - m_nType = MOD_TYPE_AMS; - m_nInstruments = 0; - m_nChannels = (pfh->chncfg & 0x1F) + 1; - m_nSamples = pfh->samples; - for (UINT nSmp=1; nSmp<=m_nSamples; nSmp++, dwMemPos += sizeof(AMSSAMPLEHEADER)) - { - AMSSAMPLEHEADER *psh = (AMSSAMPLEHEADER *)(lpStream + dwMemPos); - MODINSTRUMENT *pins = &Ins[nSmp]; - pins->nLength = psh->length; - pins->nLoopStart = psh->loopstart; - pins->nLoopEnd = psh->loopend; - pins->nGlobalVol = 64; - pins->nVolume = psh->volume << 1; - pins->nC4Speed = psh->samplerate; - pins->nPan = (psh->finetune_and_pan & 0xF0); - if (pins->nPan < 0x80) pins->nPan += 0x10; - pins->nFineTune = MOD2XMFineTune(psh->finetune_and_pan & 0x0F); - pins->uFlags = (psh->infobyte & 0x80) ? CHN_16BIT : 0; - if ((pins->nLoopEnd <= pins->nLength) && (pins->nLoopStart+4 <= pins->nLoopEnd)) pins->uFlags |= CHN_LOOP; - pkinf[nSmp] = psh->infobyte; - } - // Read Song Name - tmp = lpStream[dwMemPos++]; - if (dwMemPos + tmp + 1 >= dwMemLength) return TRUE; - tmp2 = (tmp < 32) ? tmp : 31; - if (tmp2) memcpy(m_szNames[0], lpStream+dwMemPos, tmp2); - m_szNames[0][tmp2] = 0; - dwMemPos += tmp; - // Read sample names - for (UINT sNam=1; sNam<=m_nSamples; sNam++) - { - if (dwMemPos + 32 >= dwMemLength) return TRUE; - tmp = lpStream[dwMemPos++]; - tmp2 = (tmp < 32) ? tmp : 31; - if (tmp2) memcpy(m_szNames[sNam], lpStream+dwMemPos, tmp2); - dwMemPos += tmp; - } - // Skip Channel names - for (UINT cNam=0; cNam<m_nChannels; cNam++) - { - if (dwMemPos + 32 >= dwMemLength) return TRUE; - tmp = lpStream[dwMemPos++]; - dwMemPos += tmp; - } - // Read Pattern Names - m_lpszPatternNames = new char[pfh->patterns * 32]; // changed from CHAR - if (!m_lpszPatternNames) return TRUE; - m_nPatternNames = pfh->patterns; - memset(m_lpszPatternNames, 0, m_nPatternNames * 32); - for (UINT pNam=0; pNam < m_nPatternNames; pNam++) - { - if (dwMemPos + 32 >= dwMemLength) return TRUE; - tmp = lpStream[dwMemPos++]; - tmp2 = (tmp < 32) ? tmp : 31; - if (tmp2) memcpy(m_lpszPatternNames+pNam*32, lpStream+dwMemPos, tmp2); - dwMemPos += tmp; - } - // Read Song Comments - tmp = *((WORD *)(lpStream+dwMemPos)); - dwMemPos += 2; - if (dwMemPos + tmp >= dwMemLength) return TRUE; - if (tmp) - { - m_lpszSongComments = new char[tmp+1]; // changed from CHAR - if (!m_lpszSongComments) return TRUE; - memset(m_lpszSongComments, 0, tmp+1); - memcpy(m_lpszSongComments, lpStream + dwMemPos, tmp); - dwMemPos += tmp; - } - // Read Order List - for (UINT iOrd=0; iOrd<pfh->orders; iOrd++, dwMemPos += 2) - { - UINT n = *((WORD *)(lpStream+dwMemPos)); - Order[iOrd] = (BYTE)n; - } - // Read Patterns - for (UINT iPat=0; iPat<pfh->patterns; iPat++) - { - if (dwMemPos + 4 >= dwMemLength) return TRUE; - UINT len = *((DWORD *)(lpStream + dwMemPos)); - dwMemPos += 4; - if ((len >= dwMemLength) || (dwMemPos + len > dwMemLength)) return TRUE; - PatternSize[iPat] = 64; - MODCOMMAND *m = AllocatePattern(PatternSize[iPat], m_nChannels); - if (!m) return TRUE; - Patterns[iPat] = m; - const BYTE *p = lpStream + dwMemPos; - UINT row = 0, i = 0; - while ((row < PatternSize[iPat]) && (i+2 < len)) - { - BYTE b0 = p[i++]; - BYTE b1 = p[i++]; - BYTE b2 = 0; - UINT ch = b0 & 0x3F; - // Note+Instr - if (!(b0 & 0x40)) - { - b2 = p[i++]; - if (ch < m_nChannels) - { - if (b1 & 0x7F) m[ch].note = (b1 & 0x7F) + 25; - m[ch].instr = b2; - } - if (b1 & 0x80) - { - b0 |= 0x40; - b1 = p[i++]; - } - } - // Effect - if (b0 & 0x40) - { - anothercommand: - if (b1 & 0x40) - { - if (ch < m_nChannels) - { - m[ch].volcmd = VOLCMD_VOLUME; - m[ch].vol = b1 & 0x3F; - } - } else - { - b2 = p[i++]; - if (ch < m_nChannels) - { - UINT cmd = b1 & 0x3F; - if (cmd == 0x0C) - { - m[ch].volcmd = VOLCMD_VOLUME; - m[ch].vol = b2 >> 1; - } else - if (cmd == 0x0E) - { - if (!m[ch].command) - { - UINT command = CMD_S3MCMDEX; - UINT param = b2; - switch(param & 0xF0) - { - case 0x00: if (param & 0x08) { param &= 0x07; param |= 0x90; } else {command=param=0;} break; - case 0x10: command = CMD_PORTAMENTOUP; param |= 0xF0; break; - case 0x20: command = CMD_PORTAMENTODOWN; param |= 0xF0; break; - case 0x30: param = (param & 0x0F) | 0x10; break; - case 0x40: param = (param & 0x0F) | 0x30; break; - case 0x50: param = (param & 0x0F) | 0x20; break; - case 0x60: param = (param & 0x0F) | 0xB0; break; - case 0x70: param = (param & 0x0F) | 0x40; break; - case 0x90: command = CMD_RETRIG; param &= 0x0F; break; - case 0xA0: if (param & 0x0F) { command = CMD_VOLUMESLIDE; param = (param << 4) | 0x0F; } else command=param=0; break; - case 0xB0: if (param & 0x0F) { command = CMD_VOLUMESLIDE; param |= 0xF0; } else command=param=0; break; - } - m[ch].command = command; - m[ch].param = param; - } - } else - { - m[ch].command = cmd; - m[ch].param = b2; - ConvertModCommand(&m[ch]); - } - } - } - if (b1 & 0x80) - { - b1 = p[i++]; - if (i <= len) goto anothercommand; - } - } - if (b0 & 0x80) - { - row++; - m += m_nChannels; - } - } - dwMemPos += len; - } - // Read Samples - for (UINT iSmp=1; iSmp<=m_nSamples; iSmp++) if (Ins[iSmp].nLength) - { - if (dwMemPos >= dwMemLength - 9) return TRUE; - UINT flags = (Ins[iSmp].uFlags & CHN_16BIT) ? RS_AMS16 : RS_AMS8; - dwMemPos += ReadSample(&Ins[iSmp], flags, (LPSTR)(lpStream+dwMemPos), dwMemLength-dwMemPos); - } - return TRUE; -} - - -///////////////////////////////////////////////////////////////////// -// AMS 2.2 loader - -#pragma pack(1) - -typedef struct AMS2FILEHEADER -{ - DWORD dwHdr1; // AMShdr - WORD wHdr2; - BYTE b1A; // 0x1A - BYTE titlelen; // 30-bytes max - CHAR szTitle[30]; // [titlelen] -} AMS2FILEHEADER; - -typedef struct AMS2SONGHEADER -{ - WORD version; - BYTE instruments; - WORD patterns; - WORD orders; - WORD bpm; - BYTE speed; - BYTE channels; - BYTE commands; - BYTE rows; - WORD flags; -} AMS2SONGHEADER; - -typedef struct AMS2INSTRUMENT -{ - BYTE samples; - BYTE notemap[NOTE_MAX]; -} AMS2INSTRUMENT; - -typedef struct AMS2ENVELOPE -{ - BYTE speed; - BYTE sustain; - BYTE loopbegin; - BYTE loopend; - BYTE points; - BYTE info[3]; -} AMS2ENVELOPE; - -typedef struct AMS2SAMPLE -{ - DWORD length; - DWORD loopstart; - DWORD loopend; - WORD frequency; - BYTE finetune; - WORD c4speed; - CHAR transpose; - BYTE volume; - BYTE flags; -} AMS2SAMPLE; - - -#pragma pack() - - -BOOL CSoundFile::ReadAMS2(LPCBYTE lpStream, DWORD dwMemLength) -//------------------------------------------------------------ -{ - AMS2FILEHEADER *pfh = (AMS2FILEHEADER *)lpStream; - AMS2SONGHEADER *psh; - DWORD dwMemPos; - BYTE smpmap[16]; - BYTE packedsamples[MAX_SAMPLES]; - - if ((pfh->dwHdr1 != 0x68534D41) || (pfh->wHdr2 != 0x7264) - || (pfh->b1A != 0x1A) || (pfh->titlelen > 30)) return FALSE; - dwMemPos = pfh->titlelen + 8; - psh = (AMS2SONGHEADER *)(lpStream + dwMemPos); - if (((psh->version & 0xFF00) != 0x0200) || (!psh->instruments) - || (psh->instruments > MAX_INSTRUMENTS) || (!psh->patterns) || (!psh->orders)) return FALSE; - dwMemPos += sizeof(AMS2SONGHEADER); - if (pfh->titlelen) - { - memcpy(m_szNames, pfh->szTitle, pfh->titlelen); - m_szNames[0][pfh->titlelen] = 0; - } - m_nType = MOD_TYPE_AMS; - m_nChannels = 32; - m_nDefaultTempo = psh->bpm >> 8; - m_nDefaultSpeed = psh->speed; - m_nInstruments = psh->instruments; - m_nSamples = 0; - if (psh->flags & 0x40) m_dwSongFlags |= SONG_LINEARSLIDES; - for (UINT nIns=1; nIns<=m_nInstruments; nIns++) - { - UINT insnamelen = lpStream[dwMemPos]; - CHAR *pinsname = (CHAR *)(lpStream+dwMemPos+1); - dwMemPos += insnamelen + 1; - AMS2INSTRUMENT *pins = (AMS2INSTRUMENT *)(lpStream + dwMemPos); - dwMemPos += sizeof(AMS2INSTRUMENT); - if (dwMemPos + 1024 >= dwMemLength) return TRUE; - AMS2ENVELOPE *volenv, *panenv, *pitchenv; - volenv = (AMS2ENVELOPE *)(lpStream+dwMemPos); - dwMemPos += 5 + volenv->points*3; - panenv = (AMS2ENVELOPE *)(lpStream+dwMemPos); - dwMemPos += 5 + panenv->points*3; - pitchenv = (AMS2ENVELOPE *)(lpStream+dwMemPos); - dwMemPos += 5 + pitchenv->points*3; - INSTRUMENTHEADER *penv = new INSTRUMENTHEADER; - if (!penv) return TRUE; - memset(smpmap, 0, sizeof(smpmap)); - memset(penv, 0, sizeof(INSTRUMENTHEADER)); - for (UINT ismpmap=0; ismpmap<pins->samples; ismpmap++) - { - if ((ismpmap >= 16) || (m_nSamples+1 >= MAX_SAMPLES)) break; - m_nSamples++; - smpmap[ismpmap] = m_nSamples; - } - penv->nGlobalVol = 64; - penv->nPan = 128; - penv->nPPC = 60; - Headers[nIns] = penv; - if (insnamelen) - { - if (insnamelen > 31) insnamelen = 31; - memcpy(penv->name, pinsname, insnamelen); - penv->name[insnamelen] = 0; - } - for (UINT inotemap=0; inotemap<NOTE_MAX; inotemap++) - { - penv->NoteMap[inotemap] = inotemap+1; - penv->Keyboard[inotemap] = smpmap[pins->notemap[inotemap] & 0x0F]; - } - // Volume Envelope - { - UINT pos = 0; - penv->nVolEnv = (volenv->points > 16) ? 16 : volenv->points; - penv->nVolSustainBegin = penv->nVolSustainEnd = volenv->sustain; - penv->nVolLoopStart = volenv->loopbegin; - penv->nVolLoopEnd = volenv->loopend; - for (UINT i=0; i<penv->nVolEnv; i++) - { - penv->VolEnv[i] = (BYTE)((volenv->info[i*3+2] & 0x7F) >> 1); - pos += volenv->info[i*3] + ((volenv->info[i*3+1] & 1) << 8); - penv->VolPoints[i] = (WORD)pos; - } - } - penv->nFadeOut = (((lpStream[dwMemPos+2] & 0x0F) << 8) | (lpStream[dwMemPos+1])) << 3; - UINT envflags = lpStream[dwMemPos+3]; - if (envflags & 0x01) penv->dwFlags |= ENV_VOLLOOP; - if (envflags & 0x02) penv->dwFlags |= ENV_VOLSUSTAIN; - if (envflags & 0x04) penv->dwFlags |= ENV_VOLUME; - dwMemPos += 5; - // Read Samples - for (UINT ismp=0; ismp<pins->samples; ismp++) - { - MODINSTRUMENT *psmp = ((ismp < 16) && (smpmap[ismp])) ? &Ins[smpmap[ismp]] : NULL; - UINT smpnamelen = lpStream[dwMemPos]; - if ((psmp) && (smpnamelen) && (smpnamelen <= 22)) - { - memcpy(m_szNames[smpmap[ismp]], lpStream+dwMemPos+1, smpnamelen); - } - dwMemPos += smpnamelen + 1; - if (psmp) - { - AMS2SAMPLE *pams = (AMS2SAMPLE *)(lpStream+dwMemPos); - psmp->nGlobalVol = 64; - psmp->nPan = 128; - psmp->nLength = pams->length; - psmp->nLoopStart = pams->loopstart; - psmp->nLoopEnd = pams->loopend; - psmp->nC4Speed = pams->c4speed; - psmp->RelativeTone = pams->transpose; - psmp->nVolume = pams->volume / 2; - packedsamples[smpmap[ismp]] = pams->flags; - if (pams->flags & 0x04) psmp->uFlags |= CHN_16BIT; - if (pams->flags & 0x08) psmp->uFlags |= CHN_LOOP; - if (pams->flags & 0x10) psmp->uFlags |= CHN_PINGPONGLOOP; - } - dwMemPos += sizeof(AMS2SAMPLE); - } - } - if (dwMemPos + 256 >= dwMemLength) return TRUE; - // Comments - { - UINT composernamelen = lpStream[dwMemPos]; - if (composernamelen) - { - m_lpszSongComments = new char[composernamelen+1]; // changed from CHAR - if (m_lpszSongComments) - { - memcpy(m_lpszSongComments, lpStream+dwMemPos+1, composernamelen); - m_lpszSongComments[composernamelen] = 0; - } - } - dwMemPos += composernamelen + 1; - // channel names - for (UINT i=0; i<32; i++) - { - UINT chnnamlen = lpStream[dwMemPos]; - if ((chnnamlen) && (chnnamlen < MAX_CHANNELNAME)) - { - memcpy(ChnSettings[i].szName, lpStream+dwMemPos+1, chnnamlen); - } - dwMemPos += chnnamlen + 1; - if (dwMemPos + chnnamlen + 256 >= dwMemLength) return TRUE; - } - // packed comments (ignored) - UINT songtextlen = *((LPDWORD)(lpStream+dwMemPos)); - dwMemPos += songtextlen; - if (dwMemPos + 256 >= dwMemLength) return TRUE; - } - // Order List - { - for (UINT i=0; i<MAX_ORDERS; i++) - { - Order[i] = 0xFF; - if (dwMemPos + 2 >= dwMemLength) return TRUE; - if (i < psh->orders) - { - Order[i] = lpStream[dwMemPos]; - dwMemPos += 2; - } - } - } - // Pattern Data - for (UINT ipat=0; ipat<psh->patterns; ipat++) - { - if (dwMemPos+8 >= dwMemLength) return TRUE; - UINT packedlen = *((LPDWORD)(lpStream+dwMemPos)); - UINT numrows = 1 + (UINT)(lpStream[dwMemPos+4]); - //UINT patchn = 1 + (UINT)(lpStream[dwMemPos+5] & 0x1F); - //UINT patcmds = 1 + (UINT)(lpStream[dwMemPos+5] >> 5); - UINT patnamlen = lpStream[dwMemPos+6]; - dwMemPos += 4; - if ((ipat < MAX_PATTERNS) && (packedlen < dwMemLength-dwMemPos) && (numrows >= 8)) - { - if ((patnamlen) && (patnamlen < MAX_PATTERNNAME)) - { - char s[MAX_PATTERNNAME]; // changed from CHAR - memcpy(s, lpStream+dwMemPos+3, patnamlen); - s[patnamlen] = 0; - SetPatternName(ipat, s); - } - PatternSize[ipat] = numrows; - Patterns[ipat] = AllocatePattern(numrows, m_nChannels); - if (!Patterns[ipat]) return TRUE; - // Unpack Pattern Data - LPCBYTE psrc = lpStream + dwMemPos; - UINT pos = 3 + patnamlen; - UINT row = 0; - while ((pos < packedlen) && (row < numrows)) - { - MODCOMMAND *m = Patterns[ipat] + row * m_nChannels; - UINT byte1 = psrc[pos++]; - UINT ch = byte1 & 0x1F; - // Read Note + Instr - if (!(byte1 & 0x40)) - { - UINT byte2 = psrc[pos++]; - UINT note = byte2 & 0x7F; - if (note) m[ch].note = (note > 1) ? (note-1) : 0xFF; - m[ch].instr = psrc[pos++]; - // Read Effect - while (byte2 & 0x80) - { - byte2 = psrc[pos++]; - if (byte2 & 0x40) - { - m[ch].volcmd = VOLCMD_VOLUME; - m[ch].vol = byte2 & 0x3F; - } else - { - UINT command = byte2 & 0x3F; - UINT param = psrc[pos++]; - if (command == 0x0C) - { - m[ch].volcmd = VOLCMD_VOLUME; - m[ch].vol = param / 2; - } else - if (command < 0x10) - { - m[ch].command = command; - m[ch].param = param; - ConvertModCommand(&m[ch]); - } else - { - // TODO: AMS effects - } - } - } - } - if (byte1 & 0x80) row++; - } - } - dwMemPos += packedlen; - } - // Read Samples - for (UINT iSmp=1; iSmp<=m_nSamples; iSmp++) if (Ins[iSmp].nLength) - { - if (dwMemPos >= dwMemLength - 9) return TRUE; - UINT flags; - if (packedsamples[iSmp] & 0x03) - { - flags = (Ins[iSmp].uFlags & CHN_16BIT) ? RS_AMS16 : RS_AMS8; - } else - { - flags = (Ins[iSmp].uFlags & CHN_16BIT) ? RS_PCM16S : RS_PCM8S; - } - dwMemPos += ReadSample(&Ins[iSmp], flags, (LPSTR)(lpStream+dwMemPos), dwMemLength-dwMemPos); - } - return TRUE; -} - - -///////////////////////////////////////////////////////////////////// -// AMS Sample unpacking - -void AMSUnpack(const char *psrc, UINT inputlen, char *pdest, UINT dmax, char packcharacter) -{ - UINT tmplen = dmax; - signed char *amstmp = new signed char[tmplen]; - - if (!amstmp) return; - // Unpack Loop - { - signed char *p = amstmp; - UINT i=0, j=0; - while ((i < inputlen) && (j < tmplen)) - { - signed char ch = psrc[i++]; - if (ch == packcharacter) - { - BYTE ch2 = psrc[i++]; - if (ch2) - { - ch = psrc[i++]; - while (ch2--) - { - p[j++] = ch; - if (j >= tmplen) break; - } - } else p[j++] = packcharacter; - } else p[j++] = ch; - } - } - // Bit Unpack Loop - { - signed char *p = amstmp; - UINT bitcount = 0x80, dh; - UINT k=0; - for (UINT i=0; i<dmax; i++) - { - BYTE al = *p++; - dh = 0; - for (UINT count=0; count<8; count++) - { - UINT bl = al & bitcount; - bl = ((bl|(bl<<8)) >> ((dh+8-count) & 7)) & 0xFF; - bitcount = ((bitcount|(bitcount<<8)) >> 1) & 0xFF; - pdest[k++] |= bl; - if (k >= dmax) - { - k = 0; - dh++; - } - } - bitcount = ((bitcount|(bitcount<<8)) >> dh) & 0xFF; - } - } - // Delta Unpack - { - signed char old = 0; - for (UINT i=0; i<dmax; i++) - { - int pos = ((LPBYTE)pdest)[i]; - if ((pos != 128) && (pos & 0x80)) pos = -(pos & 0x7F); - old -= (signed char)pos; - pdest[i] = old; - } - } - delete amstmp; -} - diff --git a/lib/libmodplug/src/load_dbm.cpp b/lib/libmodplug/src/load_dbm.cpp deleted file mode 100644 index 363579d5e0..0000000000 --- a/lib/libmodplug/src/load_dbm.cpp +++ /dev/null @@ -1,368 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque <olivierl@jps.net>, - * Adam Goode <adam@evdebs.org> (endian and char fixes for PPC) -*/ - -/////////////////////////////////////////////////////////////// -// -// DigiBooster Pro Module Loader (*.dbm) -// -// Note: this loader doesn't handle multiple songs -// -/////////////////////////////////////////////////////////////// - -#include "stdafx.h" -#include "sndfile.h" - -//#pragma warning(disable:4244) - -#define DBM_FILE_MAGIC 0x304d4244 -#define DBM_ID_NAME 0x454d414e -#define DBM_NAMELEN 0x2c000000 -#define DBM_ID_INFO 0x4f464e49 -#define DBM_INFOLEN 0x0a000000 -#define DBM_ID_SONG 0x474e4f53 -#define DBM_ID_INST 0x54534e49 -#define DBM_ID_VENV 0x564e4556 -#define DBM_ID_PATT 0x54544150 -#define DBM_ID_SMPL 0x4c504d53 - -#pragma pack(1) - -typedef struct DBMFILEHEADER -{ - DWORD dbm_id; // "DBM0" = 0x304d4244 - WORD trkver; // Tracker version: 02.15 - WORD reserved; - DWORD name_id; // "NAME" = 0x454d414e - DWORD name_len; // name length: always 44 - CHAR songname[44]; - DWORD info_id; // "INFO" = 0x4f464e49 - DWORD info_len; // 0x0a000000 - WORD instruments; - WORD samples; - WORD songs; - WORD patterns; - WORD channels; - DWORD song_id; // "SONG" = 0x474e4f53 - DWORD song_len; - CHAR songname2[44]; - WORD orders; -// WORD orderlist[0]; // orderlist[orders] in words -} DBMFILEHEADER; - -typedef struct DBMINSTRUMENT -{ - CHAR name[30]; - WORD sampleno; - WORD volume; - DWORD finetune; - DWORD loopstart; - DWORD looplen; - WORD panning; - WORD flags; -} DBMINSTRUMENT; - -typedef struct DBMENVELOPE -{ - WORD instrument; - BYTE flags; - BYTE numpoints; - BYTE sustain1; - BYTE loopbegin; - BYTE loopend; - BYTE sustain2; - WORD volenv[2*32]; -} DBMENVELOPE; - -typedef struct DBMPATTERN -{ - WORD rows; - DWORD packedsize; - BYTE patterndata[2]; // [packedsize] -} DBMPATTERN; - -typedef struct DBMSAMPLE -{ - DWORD flags; - DWORD samplesize; - BYTE sampledata[2]; // [samplesize] -} DBMSAMPLE; - -#pragma pack() - - -BOOL CSoundFile::ReadDBM(const BYTE *lpStream, DWORD dwMemLength) -//--------------------------------------------------------------- -{ - DBMFILEHEADER *pfh = (DBMFILEHEADER *)lpStream; - DWORD dwMemPos; - UINT nOrders, nSamples, nInstruments, nPatterns; - - if ((!lpStream) || (dwMemLength <= sizeof(DBMFILEHEADER)) || (!pfh->channels) - || (pfh->dbm_id != DBM_FILE_MAGIC) || (!pfh->songs) || (pfh->song_id != DBM_ID_SONG) - || (pfh->name_id != DBM_ID_NAME) || (pfh->name_len != DBM_NAMELEN) - || (pfh->info_id != DBM_ID_INFO) || (pfh->info_len != DBM_INFOLEN)) return FALSE; - dwMemPos = sizeof(DBMFILEHEADER); - nOrders = bswapBE16(pfh->orders); - if (dwMemPos + 2 * nOrders + 8*3 >= dwMemLength) return FALSE; - nInstruments = bswapBE16(pfh->instruments); - nSamples = bswapBE16(pfh->samples); - nPatterns = bswapBE16(pfh->patterns); - m_nType = MOD_TYPE_DBM; - m_nChannels = bswapBE16(pfh->channels); - if (m_nChannels < 4) m_nChannels = 4; - if (m_nChannels > 64) m_nChannels = 64; - memcpy(m_szNames[0], (pfh->songname[0]) ? pfh->songname : pfh->songname2, 32); - m_szNames[0][31] = 0; - for (UINT iOrd=0; iOrd < nOrders; iOrd++) - { - Order[iOrd] = lpStream[dwMemPos+iOrd*2+1]; - if (iOrd >= MAX_ORDERS-2) break; - } - dwMemPos += 2*nOrders; - while (dwMemPos + 10 < dwMemLength) - { - DWORD chunk_id = ((LPDWORD)(lpStream+dwMemPos))[0]; - DWORD chunk_size = bswapBE32(((LPDWORD)(lpStream+dwMemPos))[1]); - DWORD chunk_pos; - - dwMemPos += 8; - chunk_pos = dwMemPos; - if ((dwMemPos + chunk_size > dwMemLength) || (chunk_size > dwMemLength)) break; - dwMemPos += chunk_size; - // Instruments - if (chunk_id == DBM_ID_INST) - { - if (nInstruments >= MAX_INSTRUMENTS) nInstruments = MAX_INSTRUMENTS-1; - for (UINT iIns=0; iIns<nInstruments; iIns++) - { - MODINSTRUMENT *psmp; - INSTRUMENTHEADER *penv; - DBMINSTRUMENT *pih; - UINT nsmp; - - if (chunk_pos + sizeof(DBMINSTRUMENT) > dwMemPos) break; - if ((penv = new INSTRUMENTHEADER) == NULL) break; - pih = (DBMINSTRUMENT *)(lpStream+chunk_pos); - nsmp = bswapBE16(pih->sampleno); - psmp = ((nsmp) && (nsmp < MAX_SAMPLES)) ? &Ins[nsmp] : NULL; - memset(penv, 0, sizeof(INSTRUMENTHEADER)); - memcpy(penv->name, pih->name, 30); - if (psmp) - { - memcpy(m_szNames[nsmp], pih->name, 30); - m_szNames[nsmp][30] = 0; - } - Headers[iIns+1] = penv; - penv->nFadeOut = 1024; // ??? - penv->nGlobalVol = 64; - penv->nPan = bswapBE16(pih->panning); - if ((penv->nPan) && (penv->nPan < 256)) - penv->dwFlags = ENV_SETPANNING; - else - penv->nPan = 128; - penv->nPPC = 5*12; - for (UINT i=0; i<NOTE_MAX; i++) - { - penv->Keyboard[i] = nsmp; - penv->NoteMap[i] = i+1; - } - // Sample Info - if (psmp) - { - DWORD sflags = bswapBE16(pih->flags); - psmp->nVolume = bswapBE16(pih->volume) * 4; - if ((!psmp->nVolume) || (psmp->nVolume > 256)) psmp->nVolume = 256; - psmp->nGlobalVol = 64; - psmp->nC4Speed = bswapBE32(pih->finetune); - int f2t = FrequencyToTranspose(psmp->nC4Speed); - psmp->RelativeTone = f2t >> 7; - psmp->nFineTune = f2t & 0x7F; - if ((pih->looplen) && (sflags & 3)) - { - psmp->nLoopStart = bswapBE32(pih->loopstart); - psmp->nLoopEnd = psmp->nLoopStart + bswapBE32(pih->looplen); - psmp->uFlags |= CHN_LOOP; - psmp->uFlags &= ~CHN_PINGPONGLOOP; - if (sflags & 2) psmp->uFlags |= CHN_PINGPONGLOOP; - } - } - chunk_pos += sizeof(DBMINSTRUMENT); - m_nInstruments = iIns+1; - } - } else - // Volume Envelopes - if (chunk_id == DBM_ID_VENV) - { - UINT nEnvelopes = lpStream[chunk_pos+1]; - - chunk_pos += 2; - for (UINT iEnv=0; iEnv<nEnvelopes; iEnv++) - { - DBMENVELOPE *peh; - UINT nins; - - if (chunk_pos + sizeof(DBMENVELOPE) > dwMemPos) break; - peh = (DBMENVELOPE *)(lpStream+chunk_pos); - nins = bswapBE16(peh->instrument); - if ((nins) && (nins < MAX_INSTRUMENTS) && (Headers[nins]) && (peh->numpoints)) - { - INSTRUMENTHEADER *penv = Headers[nins]; - - if (peh->flags & 1) penv->dwFlags |= ENV_VOLUME; - if (peh->flags & 2) penv->dwFlags |= ENV_VOLSUSTAIN; - if (peh->flags & 4) penv->dwFlags |= ENV_VOLLOOP; - penv->nVolEnv = peh->numpoints + 1; - if (penv->nVolEnv > MAX_ENVPOINTS) penv->nVolEnv = MAX_ENVPOINTS; - penv->nVolLoopStart = peh->loopbegin; - penv->nVolLoopEnd = peh->loopend; - penv->nVolSustainBegin = penv->nVolSustainEnd = peh->sustain1; - for (UINT i=0; i<penv->nVolEnv; i++) - { - penv->VolPoints[i] = bswapBE16(peh->volenv[i*2]); - penv->VolEnv[i] = (BYTE)bswapBE16(peh->volenv[i*2+1]); - } - } - chunk_pos += sizeof(DBMENVELOPE); - } - } else - // Packed Pattern Data - if (chunk_id == DBM_ID_PATT) - { - if (nPatterns > MAX_PATTERNS) nPatterns = MAX_PATTERNS; - for (UINT iPat=0; iPat<nPatterns; iPat++) - { - DBMPATTERN *pph; - DWORD pksize; - UINT nRows; - - if (chunk_pos + sizeof(DBMPATTERN) > dwMemPos) break; - pph = (DBMPATTERN *)(lpStream+chunk_pos); - pksize = bswapBE32(pph->packedsize); - if ((chunk_pos + pksize + 6 > dwMemPos) || (pksize > dwMemPos)) break; - nRows = bswapBE16(pph->rows); - if ((nRows >= 4) && (nRows <= 256)) - { - MODCOMMAND *m = AllocatePattern(nRows, m_nChannels); - if (m) - { - LPBYTE pkdata = (LPBYTE)&pph->patterndata; - UINT row = 0; - UINT i = 0; - - PatternSize[iPat] = nRows; - Patterns[iPat] = m; - while ((i+3<pksize) && (row < nRows)) - { - UINT ch = pkdata[i++]; - - if (ch) - { - BYTE b = pkdata[i++]; - ch--; - if (ch < m_nChannels) - { - if (b & 0x01) - { - UINT note = pkdata[i++]; - - if (note == 0x1F) note = 0xFF; else - if ((note) && (note < 0xFE)) - { - note = ((note >> 4)*12) + (note & 0x0F) + 13; - } - m[ch].note = note; - } - if (b & 0x02) m[ch].instr = pkdata[i++]; - if (b & 0x3C) - { - UINT cmd1 = 0xFF, param1 = 0, cmd2 = 0xFF, param2 = 0; - if (b & 0x04) cmd1 = (UINT)pkdata[i++]; - if (b & 0x08) param1 = pkdata[i++]; - if (b & 0x10) cmd2 = (UINT)pkdata[i++]; - if (b & 0x20) param2 = pkdata[i++]; - if (cmd1 == 0x0C) - { - m[ch].volcmd = VOLCMD_VOLUME; - m[ch].vol = param1; - cmd1 = 0xFF; - } else - if (cmd2 == 0x0C) - { - m[ch].volcmd = VOLCMD_VOLUME; - m[ch].vol = param2; - cmd2 = 0xFF; - } - if ((cmd1 > 0x13) || ((cmd1 >= 0x10) && (cmd2 < 0x10))) - { - cmd1 = cmd2; - param1 = param2; - cmd2 = 0xFF; - } - if (cmd1 <= 0x13) - { - m[ch].command = cmd1; - m[ch].param = param1; - ConvertModCommand(&m[ch]); - } - } - } else - { - if (b & 0x01) i++; - if (b & 0x02) i++; - if (b & 0x04) i++; - if (b & 0x08) i++; - if (b & 0x10) i++; - if (b & 0x20) i++; - } - } else - { - row++; - m += m_nChannels; - } - } - } - } - chunk_pos += 6 + pksize; - } - } else - // Reading Sample Data - if (chunk_id == DBM_ID_SMPL) - { - if (nSamples >= MAX_SAMPLES) nSamples = MAX_SAMPLES-1; - m_nSamples = nSamples; - for (UINT iSmp=1; iSmp<=nSamples; iSmp++) - { - MODINSTRUMENT *pins; - DBMSAMPLE *psh; - DWORD samplesize; - DWORD sampleflags; - - if (chunk_pos + sizeof(DBMSAMPLE) >= dwMemPos) break; - psh = (DBMSAMPLE *)(lpStream+chunk_pos); - chunk_pos += 8; - samplesize = bswapBE32(psh->samplesize); - sampleflags = bswapBE32(psh->flags); - pins = &Ins[iSmp]; - pins->nLength = samplesize; - if (sampleflags & 2) - { - pins->uFlags |= CHN_16BIT; - samplesize <<= 1; - } - if ((chunk_pos+samplesize > dwMemPos) || (samplesize > dwMemLength)) break; - if (sampleflags & 3) - { - ReadSample(pins, (pins->uFlags & CHN_16BIT) ? RS_PCM16M : RS_PCM8S, - (LPSTR)(psh->sampledata), samplesize); - } - chunk_pos += samplesize; - } - } - } - return TRUE; -} - diff --git a/lib/libmodplug/src/load_dmf.cpp b/lib/libmodplug/src/load_dmf.cpp deleted file mode 100644 index f8b803b6a6..0000000000 --- a/lib/libmodplug/src/load_dmf.cpp +++ /dev/null @@ -1,606 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque <olivierl@jps.net> -*/ - -/////////////////////////////////////////////////////// -// DMF DELUSION DIGITAL MUSIC FILEFORMAT (X-Tracker) // -/////////////////////////////////////////////////////// -#include "stdafx.h" -#include "sndfile.h" - -//#define DMFLOG - -//#pragma warning(disable:4244) - -#pragma pack(1) - -typedef struct DMFHEADER -{ - DWORD id; // "DDMF" = 0x464d4444 - BYTE version; // 4 - CHAR trackername[8]; // "XTRACKER" - CHAR songname[30]; - CHAR composer[20]; - BYTE date[3]; -} DMFHEADER; - -typedef struct DMFINFO -{ - DWORD id; // "INFO" - DWORD infosize; -} DMFINFO; - -typedef struct DMFSEQU -{ - DWORD id; // "SEQU" - DWORD seqsize; - WORD loopstart; - WORD loopend; - WORD sequ[2]; -} DMFSEQU; - -typedef struct DMFPATT -{ - DWORD id; // "PATT" - DWORD patsize; - WORD numpat; // 1-1024 - BYTE tracks; - BYTE firstpatinfo; -} DMFPATT; - -typedef struct DMFTRACK -{ - BYTE tracks; - BYTE beat; // [hi|lo] -> hi=ticks per beat, lo=beats per measure - WORD ticks; // max 512 - DWORD jmpsize; -} DMFTRACK; - -typedef struct DMFSMPI -{ - DWORD id; - DWORD size; - BYTE samples; -} DMFSMPI; - -typedef struct DMFSAMPLE -{ - DWORD len; - DWORD loopstart; - DWORD loopend; - WORD c3speed; - BYTE volume; - BYTE flags; -} DMFSAMPLE; - -#pragma pack() - - -#ifdef DMFLOG -extern void Log(LPCSTR s, ...); -#endif - - -BOOL CSoundFile::ReadDMF(const BYTE *lpStream, DWORD dwMemLength) -//--------------------------------------------------------------- -{ - DMFHEADER *pfh = (DMFHEADER *)lpStream; - DMFINFO *psi; - DMFSEQU *sequ; - DWORD dwMemPos; - BYTE infobyte[32]; - BYTE smplflags[MAX_SAMPLES]; - - if ((!lpStream) || (dwMemLength < 1024)) return FALSE; - if ((pfh->id != 0x464d4444) || (!pfh->version) || (pfh->version & 0xF0)) return FALSE; - dwMemPos = 66; - memcpy(m_szNames[0], pfh->songname, 30); - m_szNames[0][30] = 0; - m_nType = MOD_TYPE_DMF; - m_nChannels = 0; -#ifdef DMFLOG - Log("DMF version %d: \"%s\": %d bytes (0x%04X)\n", pfh->version, m_szNames[0], dwMemLength, dwMemLength); -#endif - while (dwMemPos + 7 < dwMemLength) - { - DWORD id = *((LPDWORD)(lpStream+dwMemPos)); - - switch(id) - { - // "INFO" - case 0x4f464e49: - // "CMSG" - case 0x47534d43: - psi = (DMFINFO *)(lpStream+dwMemPos); - if (id == 0x47534d43) dwMemPos++; - if ((psi->infosize > dwMemLength) || (psi->infosize + dwMemPos + 8 > dwMemLength)) goto dmfexit; - if ((psi->infosize >= 8) && (!m_lpszSongComments)) - { - m_lpszSongComments = new char[psi->infosize]; // changed from CHAR - if (m_lpszSongComments) - { - for (UINT i=0; i<psi->infosize-1; i++) - { - CHAR c = lpStream[dwMemPos+8+i]; - if ((i % 40) == 39) - m_lpszSongComments[i] = 0x0d; - else - m_lpszSongComments[i] = (c < ' ') ? ' ' : c; - } - m_lpszSongComments[psi->infosize-1] = 0; - } - } - dwMemPos += psi->infosize + 8 - 1; - break; - - // "SEQU" - case 0x55514553: - sequ = (DMFSEQU *)(lpStream+dwMemPos); - if ((sequ->seqsize >= dwMemLength) || (dwMemPos + sequ->seqsize + 12 > dwMemLength)) goto dmfexit; - { - UINT nseq = sequ->seqsize >> 1; - if (nseq >= MAX_ORDERS-1) nseq = MAX_ORDERS-1; - if (sequ->loopstart < nseq) m_nRestartPos = sequ->loopstart; - for (UINT i=0; i<nseq; i++) Order[i] = (BYTE)sequ->sequ[i]; - } - dwMemPos += sequ->seqsize + 8; - break; - - // "PATT" - case 0x54544150: - if (!m_nChannels) - { - DMFPATT *patt = (DMFPATT *)(lpStream+dwMemPos); - UINT numpat; - DWORD dwPos = dwMemPos + 11; - if ((patt->patsize >= dwMemLength) || (dwMemPos + patt->patsize + 8 > dwMemLength)) goto dmfexit; - numpat = patt->numpat; - if (numpat > MAX_PATTERNS) numpat = MAX_PATTERNS; - m_nChannels = patt->tracks; - if (m_nChannels < patt->firstpatinfo) m_nChannels = patt->firstpatinfo; - if (m_nChannels > 32) m_nChannels = 32; - if (m_nChannels < 4) m_nChannels = 4; - for (UINT npat=0; npat<numpat; npat++) - { - DMFTRACK *pt = (DMFTRACK *)(lpStream+dwPos); - #ifdef DMFLOG - Log("Pattern #%d: %d tracks, %d rows\n", npat, pt->tracks, pt->ticks); - #endif - UINT tracks = pt->tracks; - if (tracks > 32) tracks = 32; - UINT ticks = pt->ticks; - if (ticks > 256) ticks = 256; - if (ticks < 16) ticks = 16; - dwPos += 8; - if ((pt->jmpsize >= dwMemLength) || (dwPos + pt->jmpsize + 4 >= dwMemLength)) break; - PatternSize[npat] = (WORD)ticks; - MODCOMMAND *m = AllocatePattern(PatternSize[npat], m_nChannels); - if (!m) goto dmfexit; - Patterns[npat] = m; - DWORD d = dwPos; - dwPos += pt->jmpsize; - UINT ttype = 1; - UINT tempo = 125; - UINT glbinfobyte = 0; - UINT pbeat = (pt->beat & 0xf0) ? pt->beat>>4 : 8; - BOOL tempochange = (pt->beat & 0xf0) ? TRUE : FALSE; - memset(infobyte, 0, sizeof(infobyte)); - for (UINT row=0; row<ticks; row++) - { - MODCOMMAND *p = &m[row*m_nChannels]; - // Parse track global effects - if (!glbinfobyte) - { - BYTE info = lpStream[d++]; - BYTE infoval = 0; - if ((info & 0x80) && (d < dwPos)) glbinfobyte = lpStream[d++]; - info &= 0x7f; - if ((info) && (d < dwPos)) infoval = lpStream[d++]; - switch(info) - { - case 1: ttype = 0; tempo = infoval; tempochange = TRUE; break; - case 2: ttype = 1; tempo = infoval; tempochange = TRUE; break; - case 3: pbeat = infoval>>4; tempochange = ttype; break; - #ifdef DMFLOG - default: if (info) Log("GLB: %02X.%02X\n", info, infoval); - #endif - } - } else - { - glbinfobyte--; - } - // Parse channels - for (UINT i=0; i<tracks; i++) if (!infobyte[i]) - { - MODCOMMAND cmd = {0,0,0,0,0,0}; - BYTE info = lpStream[d++]; - if (info & 0x80) infobyte[i] = lpStream[d++]; - // Instrument - if (info & 0x40) - { - cmd.instr = lpStream[d++]; - } - // Note - if (info & 0x20) - { - cmd.note = lpStream[d++]; - if ((cmd.note) && (cmd.note < 0xfe)) cmd.note &= 0x7f; - if ((cmd.note) && (cmd.note < 128)) cmd.note += 24; - } - // Volume - if (info & 0x10) - { - cmd.volcmd = VOLCMD_VOLUME; - cmd.vol = (lpStream[d++]+3)>>2; - } - // Effect 1 - if (info & 0x08) - { - BYTE efx = lpStream[d++]; - BYTE eval = lpStream[d++]; - switch(efx) - { - // 1: Key Off - case 1: if (!cmd.note) cmd.note = 0xFE; break; - // 2: Set Loop - // 4: Sample Delay - case 4: if (eval&0xe0) { cmd.command = CMD_S3MCMDEX; cmd.param = (eval>>5)|0xD0; } break; - // 5: Retrig - case 5: if (eval&0xe0) { cmd.command = CMD_RETRIG; cmd.param = (eval>>5); } break; - // 6: Offset - case 6: cmd.command = CMD_OFFSET; cmd.param = eval; break; - #ifdef DMFLOG - default: Log("FX1: %02X.%02X\n", efx, eval); - #endif - } - } - // Effect 2 - if (info & 0x04) - { - BYTE efx = lpStream[d++]; - BYTE eval = lpStream[d++]; - switch(efx) - { - // 1: Finetune - case 1: if (eval&0xf0) { cmd.command = CMD_S3MCMDEX; cmd.param = (eval>>4)|0x20; } break; - // 2: Note Delay - case 2: if (eval&0xe0) { cmd.command = CMD_S3MCMDEX; cmd.param = (eval>>5)|0xD0; } break; - // 3: Arpeggio - case 3: if (eval) { cmd.command = CMD_ARPEGGIO; cmd.param = eval; } break; - // 4: Portamento Up - case 4: cmd.command = CMD_PORTAMENTOUP; cmd.param = (eval >= 0xe0) ? 0xdf : eval; break; - // 5: Portamento Down - case 5: cmd.command = CMD_PORTAMENTODOWN; cmd.param = (eval >= 0xe0) ? 0xdf : eval; break; - // 6: Tone Portamento - case 6: cmd.command = CMD_TONEPORTAMENTO; cmd.param = eval; break; - // 8: Vibrato - case 8: cmd.command = CMD_VIBRATO; cmd.param = eval; break; - // 12: Note cut - case 12: if (eval & 0xe0) { cmd.command = CMD_S3MCMDEX; cmd.param = (eval>>5)|0xc0; } - else if (!cmd.note) { cmd.note = 0xfe; } break; - #ifdef DMFLOG - default: Log("FX2: %02X.%02X\n", efx, eval); - #endif - } - } - // Effect 3 - if (info & 0x02) - { - BYTE efx = lpStream[d++]; - BYTE eval = lpStream[d++]; - switch(efx) - { - // 1: Vol Slide Up - case 1: if (eval == 0xff) break; - eval = (eval+3)>>2; if (eval > 0x0f) eval = 0x0f; - cmd.command = CMD_VOLUMESLIDE; cmd.param = eval<<4; break; - // 2: Vol Slide Down - case 2: if (eval == 0xff) break; - eval = (eval+3)>>2; if (eval > 0x0f) eval = 0x0f; - cmd.command = CMD_VOLUMESLIDE; cmd.param = eval; break; - // 7: Set Pan - case 7: if (!cmd.volcmd) { cmd.volcmd = VOLCMD_PANNING; cmd.vol = (eval+3)>>2; } - else { cmd.command = CMD_PANNING8; cmd.param = eval; } break; - // 8: Pan Slide Left - case 8: eval = (eval+3)>>2; if (eval > 0x0f) eval = 0x0f; - cmd.command = CMD_PANNINGSLIDE; cmd.param = eval<<4; break; - // 9: Pan Slide Right - case 9: eval = (eval+3)>>2; if (eval > 0x0f) eval = 0x0f; - cmd.command = CMD_PANNINGSLIDE; cmd.param = eval; break; - #ifdef DMFLOG - default: Log("FX3: %02X.%02X\n", efx, eval); - #endif - - } - } - // Store effect - if (i < m_nChannels) p[i] = cmd; - if (d > dwPos) - { - #ifdef DMFLOG - Log("Unexpected EOP: row=%d\n", row); - #endif - break; - } - } else - { - infobyte[i]--; - } - - // Find free channel for tempo change - if (tempochange) - { - tempochange = FALSE; - UINT speed=6, modtempo=tempo; - UINT rpm = ((ttype) && (pbeat)) ? tempo*pbeat : (tempo+1)*15; - for (speed=30; speed>1; speed--) - { - modtempo = rpm*speed/24; - if (modtempo <= 200) break; - if ((speed < 6) && (modtempo < 256)) break; - } - #ifdef DMFLOG - Log("Tempo change: ttype=%d pbeat=%d tempo=%3d -> speed=%d tempo=%d\n", - ttype, pbeat, tempo, speed, modtempo); - #endif - for (UINT ich=0; ich<m_nChannels; ich++) if (!p[ich].command) - { - if (speed) - { - p[ich].command = CMD_SPEED; - p[ich].param = (BYTE)speed; - speed = 0; - } else - if ((modtempo >= 32) && (modtempo < 256)) - { - p[ich].command = CMD_TEMPO; - p[ich].param = (BYTE)modtempo; - modtempo = 0; - } else - { - break; - } - } - } - if (d >= dwPos) break; - } - #ifdef DMFLOG - Log(" %d/%d bytes remaining\n", dwPos-d, pt->jmpsize); - #endif - if (dwPos + 8 >= dwMemLength) break; - } - dwMemPos += patt->patsize + 8; - } - break; - - // "SMPI": Sample Info - case 0x49504d53: - { - DMFSMPI *pds = (DMFSMPI *)(lpStream+dwMemPos); - if (pds->size <= dwMemLength - dwMemPos) - { - DWORD dwPos = dwMemPos + 9; - m_nSamples = pds->samples; - if (m_nSamples >= MAX_SAMPLES) m_nSamples = MAX_SAMPLES-1; - for (UINT iSmp=1; iSmp<=m_nSamples; iSmp++) - { - UINT namelen = lpStream[dwPos]; - smplflags[iSmp] = 0; - if (dwPos+namelen+1+sizeof(DMFSAMPLE) > dwMemPos+pds->size+8) break; - if (namelen) - { - UINT rlen = (namelen < 32) ? namelen : 31; - memcpy(m_szNames[iSmp], lpStream+dwPos+1, rlen); - m_szNames[iSmp][rlen] = 0; - } - dwPos += namelen + 1; - DMFSAMPLE *psh = (DMFSAMPLE *)(lpStream+dwPos); - MODINSTRUMENT *psmp = &Ins[iSmp]; - psmp->nLength = psh->len; - psmp->nLoopStart = psh->loopstart; - psmp->nLoopEnd = psh->loopend; - psmp->nC4Speed = psh->c3speed; - psmp->nGlobalVol = 64; - psmp->nVolume = (psh->volume) ? ((WORD)psh->volume)+1 : (WORD)256; - psmp->uFlags = (psh->flags & 2) ? CHN_16BIT : 0; - if (psmp->uFlags & CHN_16BIT) psmp->nLength >>= 1; - if (psh->flags & 1) psmp->uFlags |= CHN_LOOP; - smplflags[iSmp] = psh->flags; - dwPos += (pfh->version < 8) ? 22 : 30; - #ifdef DMFLOG - Log("SMPI %d/%d: len=%d flags=0x%02X\n", iSmp, m_nSamples, psmp->nLength, psh->flags); - #endif - } - } - dwMemPos += pds->size + 8; - } - break; - - // "SMPD": Sample Data - case 0x44504d53: - { - DWORD dwPos = dwMemPos + 8; - UINT ismpd = 0; - for (UINT iSmp=1; iSmp<=m_nSamples; iSmp++) - { - ismpd++; - DWORD pksize; - if (dwPos + 4 >= dwMemLength) - { - #ifdef DMFLOG - Log("Unexpected EOF at sample %d/%d! (pos=%d)\n", iSmp, m_nSamples, dwPos); - #endif - break; - } - pksize = *((LPDWORD)(lpStream+dwPos)); - #ifdef DMFLOG - Log("sample %d: pos=0x%X pksize=%d ", iSmp, dwPos, pksize); - Log("len=%d flags=0x%X [%08X]\n", Ins[iSmp].nLength, smplflags[ismpd], *((LPDWORD)(lpStream+dwPos+4))); - #endif - dwPos += 4; - if (pksize > dwMemLength - dwPos) - { - #ifdef DMFLOG - Log("WARNING: pksize=%d, but only %d bytes left\n", pksize, dwMemLength-dwPos); - #endif - pksize = dwMemLength - dwPos; - } - if ((pksize) && (iSmp <= m_nSamples)) - { - UINT flags = (Ins[iSmp].uFlags & CHN_16BIT) ? RS_PCM16S : RS_PCM8S; - if (smplflags[ismpd] & 4) flags = (Ins[iSmp].uFlags & CHN_16BIT) ? RS_DMF16 : RS_DMF8; - ReadSample(&Ins[iSmp], flags, (LPSTR)(lpStream+dwPos), pksize); - } - dwPos += pksize; - } - dwMemPos = dwPos; - } - break; - - // "ENDE": end of file - case 0x45444e45: - goto dmfexit; - - // Unrecognized id, or "ENDE" field - default: - dwMemPos += 4; - break; - } - } -dmfexit: - if (!m_nChannels) - { - if (!m_nSamples) - { - m_nType = MOD_TYPE_NONE; - return FALSE; - } - m_nChannels = 4; - } - return TRUE; -} - - -/////////////////////////////////////////////////////////////////////// -// DMF Compression - -#pragma pack(1) - -typedef struct DMF_HNODE -{ - short int left, right; - BYTE value; -} DMF_HNODE; - -typedef struct DMF_HTREE -{ - LPBYTE ibuf, ibufmax; - DWORD bitbuf; - UINT bitnum; - UINT lastnode, nodecount; - DMF_HNODE nodes[256]; -} DMF_HTREE; - -#pragma pack() - - -// DMF Huffman ReadBits -BYTE DMFReadBits(DMF_HTREE *tree, UINT nbits) -//------------------------------------------- -{ - BYTE x = 0, bitv = 1; - while (nbits--) - { - if (tree->bitnum) - { - tree->bitnum--; - } else - { - tree->bitbuf = (tree->ibuf < tree->ibufmax) ? *(tree->ibuf++) : 0; - tree->bitnum = 7; - } - if (tree->bitbuf & 1) x |= bitv; - bitv <<= 1; - tree->bitbuf >>= 1; - } - return x; -} - -// -// tree: [8-bit value][12-bit index][12-bit index] = 32-bit -// - -void DMFNewNode(DMF_HTREE *tree) -//------------------------------ -{ - BYTE isleft, isright; - UINT actnode; - - actnode = tree->nodecount; - if (actnode > 255) return; - tree->nodes[actnode].value = DMFReadBits(tree, 7); - isleft = DMFReadBits(tree, 1); - isright = DMFReadBits(tree, 1); - actnode = tree->lastnode; - if (actnode > 255) return; - tree->nodecount++; - tree->lastnode = tree->nodecount; - if (isleft) - { - tree->nodes[actnode].left = tree->lastnode; - DMFNewNode(tree); - } else - { - tree->nodes[actnode].left = -1; - } - tree->lastnode = tree->nodecount; - if (isright) - { - tree->nodes[actnode].right = tree->lastnode; - DMFNewNode(tree); - } else - { - tree->nodes[actnode].right = -1; - } -} - - -int DMFUnpack(LPBYTE psample, LPBYTE ibuf, LPBYTE ibufmax, UINT maxlen) -//---------------------------------------------------------------------- -{ - DMF_HTREE tree; - UINT actnode; - BYTE value, sign, delta = 0; - - memset(&tree, 0, sizeof(tree)); - tree.ibuf = ibuf; - tree.ibufmax = ibufmax; - DMFNewNode(&tree); - value = 0; - for (UINT i=0; i<maxlen; i++) - { - actnode = 0; - sign = DMFReadBits(&tree, 1); - do - { - if (DMFReadBits(&tree, 1)) - actnode = tree.nodes[actnode].right; - else - actnode = tree.nodes[actnode].left; - if (actnode > 255) break; - delta = tree.nodes[actnode].value; - if ((tree.ibuf >= tree.ibufmax) && (!tree.bitnum)) break; - } while ((tree.nodes[actnode].left >= 0) && (tree.nodes[actnode].right >= 0)); - if (sign) delta ^= 0xFF; - value += delta; - psample[i] = (i) ? value : 0; - } -#ifdef DMFLOG -// Log("DMFUnpack: %d remaining bytes\n", tree.ibufmax-tree.ibuf); -#endif - return tree.ibuf - ibuf; -} - - diff --git a/lib/libmodplug/src/load_dsm.cpp b/lib/libmodplug/src/load_dsm.cpp deleted file mode 100644 index 4f51469f83..0000000000 --- a/lib/libmodplug/src/load_dsm.cpp +++ /dev/null @@ -1,236 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque <olivierl@jps.net> -*/ - -////////////////////////////////////////////// -// DSIK Internal Format (DSM) module loader // -////////////////////////////////////////////// -#include "stdafx.h" -#include "sndfile.h" - -#pragma pack(1) - -#define DSMID_RIFF 0x46464952 // "RIFF" -#define DSMID_DSMF 0x464d5344 // "DSMF" -#define DSMID_SONG 0x474e4f53 // "SONG" -#define DSMID_INST 0x54534e49 // "INST" -#define DSMID_PATT 0x54544150 // "PATT" - - -typedef struct DSMNOTE -{ - BYTE note,ins,vol,cmd,inf; -} DSMNOTE; - - -typedef struct DSMINST -{ - DWORD id_INST; - DWORD inst_len; - CHAR filename[13]; - BYTE flags; - BYTE flags2; - BYTE volume; - DWORD length; - DWORD loopstart; - DWORD loopend; - DWORD reserved1; - WORD c2spd; - WORD reserved2; - CHAR samplename[28]; -} DSMINST; - - -typedef struct DSMFILEHEADER -{ - DWORD id_RIFF; // "RIFF" - DWORD riff_len; - DWORD id_DSMF; // "DSMF" - DWORD id_SONG; // "SONG" - DWORD song_len; -} DSMFILEHEADER; - - -typedef struct DSMSONG -{ - CHAR songname[28]; - WORD reserved1; - WORD flags; - DWORD reserved2; - WORD numord; - WORD numsmp; - WORD numpat; - WORD numtrk; - BYTE globalvol; - BYTE mastervol; - BYTE speed; - BYTE bpm; - BYTE panpos[16]; - BYTE orders[128]; -} DSMSONG; - -typedef struct DSMPATT -{ - DWORD id_PATT; - DWORD patt_len; - BYTE dummy1; - BYTE dummy2; -} DSMPATT; - -#pragma pack() - - -BOOL CSoundFile::ReadDSM(LPCBYTE lpStream, DWORD dwMemLength) -//----------------------------------------------------------- -{ - DSMFILEHEADER *pfh = (DSMFILEHEADER *)lpStream; - DSMSONG *psong; - DWORD dwMemPos; - UINT nPat, nSmp; - - if ((!lpStream) || (dwMemLength < 1024) || (pfh->id_RIFF != DSMID_RIFF) - || (pfh->riff_len + 8 > dwMemLength) || (pfh->riff_len < 1024) - || (pfh->id_DSMF != DSMID_DSMF) || (pfh->id_SONG != DSMID_SONG) - || (pfh->song_len > dwMemLength)) return FALSE; - psong = (DSMSONG *)(lpStream + sizeof(DSMFILEHEADER)); - dwMemPos = sizeof(DSMFILEHEADER) + pfh->song_len; - m_nType = MOD_TYPE_DSM; - m_nChannels = psong->numtrk; - if (m_nChannels < 4) m_nChannels = 4; - if (m_nChannels > 16) m_nChannels = 16; - m_nSamples = psong->numsmp; - if (m_nSamples > MAX_SAMPLES) m_nSamples = MAX_SAMPLES; - m_nDefaultSpeed = psong->speed; - m_nDefaultTempo = psong->bpm; - m_nDefaultGlobalVolume = psong->globalvol << 2; - if ((!m_nDefaultGlobalVolume) || (m_nDefaultGlobalVolume > 256)) m_nDefaultGlobalVolume = 256; - m_nSongPreAmp = psong->mastervol & 0x7F; - for (UINT iOrd=0; iOrd<MAX_ORDERS; iOrd++) - { - Order[iOrd] = (BYTE)((iOrd < psong->numord) ? psong->orders[iOrd] : 0xFF); - } - for (UINT iPan=0; iPan<16; iPan++) - { - ChnSettings[iPan].nPan = 0x80; - if (psong->panpos[iPan] <= 0x80) - { - ChnSettings[iPan].nPan = psong->panpos[iPan] << 1; - } - } - memcpy(m_szNames[0], psong->songname, 28); - nPat = 0; - nSmp = 1; - while (dwMemPos < dwMemLength - 8) - { - DSMPATT *ppatt = (DSMPATT *)(lpStream + dwMemPos); - DSMINST *pins = (DSMINST *)(lpStream+dwMemPos); - // Reading Patterns - if (ppatt->id_PATT == DSMID_PATT) - { - dwMemPos += 8; - if (dwMemPos + ppatt->patt_len >= dwMemLength) break; - DWORD dwPos = dwMemPos; - dwMemPos += ppatt->patt_len; - MODCOMMAND *m = AllocatePattern(64, m_nChannels); - if (!m) break; - PatternSize[nPat] = 64; - Patterns[nPat] = m; - UINT row = 0; - while ((row < 64) && (dwPos + 2 <= dwMemPos)) - { - UINT flag = lpStream[dwPos++]; - if (flag) - { - UINT ch = (flag & 0x0F) % m_nChannels; - if (flag & 0x80) - { - UINT note = lpStream[dwPos++]; - if (note) - { - if (note <= 12*9) note += 12; - m[ch].note = (BYTE)note; - } - } - if (flag & 0x40) - { - m[ch].instr = lpStream[dwPos++]; - } - if (flag & 0x20) - { - m[ch].volcmd = VOLCMD_VOLUME; - m[ch].vol = lpStream[dwPos++]; - } - if (flag & 0x10) - { - UINT command = lpStream[dwPos++]; - UINT param = lpStream[dwPos++]; - switch(command) - { - // 4-bit Panning - case 0x08: - switch(param & 0xF0) - { - case 0x00: param <<= 4; break; - case 0x10: command = 0x0A; param = (param & 0x0F) << 4; break; - case 0x20: command = 0x0E; param = (param & 0x0F) | 0xA0; break; - case 0x30: command = 0x0E; param = (param & 0x0F) | 0x10; break; - case 0x40: command = 0x0E; param = (param & 0x0F) | 0x20; break; - default: command = 0; - } - break; - // Portamentos - case 0x11: - case 0x12: - command &= 0x0F; - break; - // 3D Sound (?) - case 0x13: - command = 'X' - 55; - param = 0x91; - break; - default: - // Volume + Offset (?) - command = ((command & 0xF0) == 0x20) ? 0x09 : 0; - } - m[ch].command = (BYTE)command; - m[ch].param = (BYTE)param; - if (command) ConvertModCommand(&m[ch]); - } - } else - { - m += m_nChannels; - row++; - } - } - nPat++; - } else - // Reading Samples - if ((nSmp <= m_nSamples) && (pins->id_INST == DSMID_INST)) - { - if (dwMemPos + pins->inst_len >= dwMemLength - 8) break; - DWORD dwPos = dwMemPos + sizeof(DSMINST); - dwMemPos += 8 + pins->inst_len; - memcpy(m_szNames[nSmp], pins->samplename, 28); - MODINSTRUMENT *psmp = &Ins[nSmp]; - memcpy(psmp->name, pins->filename, 13); - psmp->nGlobalVol = 64; - psmp->nC4Speed = pins->c2spd; - psmp->uFlags = (WORD)((pins->flags & 1) ? CHN_LOOP : 0); - psmp->nLength = pins->length; - psmp->nLoopStart = pins->loopstart; - psmp->nLoopEnd = pins->loopend; - psmp->nVolume = (WORD)(pins->volume << 2); - if (psmp->nVolume > 256) psmp->nVolume = 256; - UINT smptype = (pins->flags & 2) ? RS_PCM8S : RS_PCM8U; - ReadSample(psmp, smptype, (LPCSTR)(lpStream+dwPos), dwMemLength - dwPos); - nSmp++; - } else - { - break; - } - } - return TRUE; -} - diff --git a/lib/libmodplug/src/load_far.cpp b/lib/libmodplug/src/load_far.cpp deleted file mode 100644 index 4bc2d9590a..0000000000 --- a/lib/libmodplug/src/load_far.cpp +++ /dev/null @@ -1,270 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque <olivierl@jps.net> -*/ - -//////////////////////////////////////// -// Farandole (FAR) module loader // -//////////////////////////////////////// -#include "stdafx.h" -#include "sndfile.h" - -//#pragma warning(disable:4244) - -#define FARFILEMAGIC 0xFE524146 // "FAR" - -#pragma pack(1) - -typedef struct FARHEADER1 -{ - DWORD id; // file magic FAR= - CHAR songname[40]; // songname - CHAR magic2[3]; // 13,10,26 - WORD headerlen; // remaining length of header in bytes - BYTE version; // 0xD1 - BYTE onoff[16]; - BYTE edit1[9]; - BYTE speed; - BYTE panning[16]; - BYTE edit2[4]; - WORD stlen; -} FARHEADER1; - -typedef struct FARHEADER2 -{ - BYTE orders[256]; - BYTE numpat; - BYTE snglen; - BYTE loopto; - WORD patsiz[256]; -} FARHEADER2; - -typedef struct FARSAMPLE -{ - CHAR samplename[32]; - DWORD length; - BYTE finetune; - BYTE volume; - DWORD reppos; - DWORD repend; - BYTE type; - BYTE loop; -} FARSAMPLE; - -#pragma pack() - - -BOOL CSoundFile::ReadFAR(const BYTE *lpStream, DWORD dwMemLength) -//--------------------------------------------------------------- -{ - FARHEADER1 *pmh1 = (FARHEADER1 *)lpStream; - FARHEADER2 *pmh2; - DWORD dwMemPos = sizeof(FARHEADER1); - UINT headerlen; - BYTE samplemap[8]; - - if ((!lpStream) || (dwMemLength < 1024) || (bswapLE32(pmh1->id) != FARFILEMAGIC) - || (pmh1->magic2[0] != 13) || (pmh1->magic2[1] != 10) || (pmh1->magic2[2] != 26)) return FALSE; - headerlen = bswapLE16(pmh1->headerlen); - pmh1->stlen = bswapLE16( pmh1->stlen ); /* inplace byteswap -- Toad */ - if ((headerlen >= dwMemLength) || (dwMemPos + pmh1->stlen + sizeof(FARHEADER2) >= dwMemLength)) return FALSE; - // Globals - m_nType = MOD_TYPE_FAR; - m_nChannels = 16; - m_nInstruments = 0; - m_nSamples = 0; - m_nSongPreAmp = 0x20; - m_nDefaultSpeed = pmh1->speed; - m_nDefaultTempo = 80; - m_nDefaultGlobalVolume = 256; - - memcpy(m_szNames[0], pmh1->songname, 32); - // Channel Setting - for (UINT nchpan=0; nchpan<16; nchpan++) - { - ChnSettings[nchpan].dwFlags = 0; - ChnSettings[nchpan].nPan = ((pmh1->panning[nchpan] & 0x0F) << 4) + 8; - ChnSettings[nchpan].nVolume = 64; - } - // Reading comment - if (pmh1->stlen) - { - UINT szLen = pmh1->stlen; - if (szLen > dwMemLength - dwMemPos) szLen = dwMemLength - dwMemPos; - if ((m_lpszSongComments = new char[szLen + 1]) != NULL) - { - memcpy(m_lpszSongComments, lpStream+dwMemPos, szLen); - m_lpszSongComments[szLen] = 0; - } - dwMemPos += pmh1->stlen; - } - // Reading orders - pmh2 = (FARHEADER2 *)(lpStream + dwMemPos); - dwMemPos += sizeof(FARHEADER2); - if (dwMemPos >= dwMemLength) return TRUE; - for (UINT iorder=0; iorder<MAX_ORDERS; iorder++) - { - Order[iorder] = (iorder <= pmh2->snglen) ? pmh2->orders[iorder] : 0xFF; - } - m_nRestartPos = pmh2->loopto; - // Reading Patterns - dwMemPos += headerlen - (869 + pmh1->stlen); - if (dwMemPos >= dwMemLength) return TRUE; - - // byteswap pattern data -- Toad - UINT psfix = 0 ; - while( psfix++ < 256 ) - { - pmh2->patsiz[psfix] = bswapLE16( pmh2->patsiz[psfix] ) ; - } - // end byteswap of pattern data - - WORD *patsiz = (WORD *)pmh2->patsiz; - for (UINT ipat=0; ipat<256; ipat++) if (patsiz[ipat]) - { - UINT patlen = patsiz[ipat]; - if ((ipat >= MAX_PATTERNS) || (patsiz[ipat] < 2)) - { - dwMemPos += patlen; - continue; - } - if (dwMemPos + patlen >= dwMemLength) return TRUE; - UINT rows = (patlen - 2) >> 6; - if (!rows) - { - dwMemPos += patlen; - continue; - } - if (rows > 256) rows = 256; - if (rows < 16) rows = 16; - PatternSize[ipat] = rows; - if ((Patterns[ipat] = AllocatePattern(rows, m_nChannels)) == NULL) return TRUE; - MODCOMMAND *m = Patterns[ipat]; - UINT patbrk = lpStream[dwMemPos]; - const BYTE *p = lpStream + dwMemPos + 2; - UINT max = rows*16*4; - if (max > patlen-2) max = patlen-2; - for (UINT len=0; len<max; len += 4, m++) - { - BYTE note = p[len]; - BYTE ins = p[len+1]; - BYTE vol = p[len+2]; - BYTE eff = p[len+3]; - if (note) - { - m->instr = ins + 1; - m->note = note + 36; - } - if (vol & 0x0F) - { - m->volcmd = VOLCMD_VOLUME; - m->vol = (vol & 0x0F) << 2; - if (m->vol <= 4) m->vol = 0; - } - switch(eff & 0xF0) - { - // 1.x: Portamento Up - case 0x10: - m->command = CMD_PORTAMENTOUP; - m->param = eff & 0x0F; - break; - // 2.x: Portamento Down - case 0x20: - m->command = CMD_PORTAMENTODOWN; - m->param = eff & 0x0F; - break; - // 3.x: Tone-Portamento - case 0x30: - m->command = CMD_TONEPORTAMENTO; - m->param = (eff & 0x0F) << 2; - break; - // 4.x: Retrigger - case 0x40: - m->command = CMD_RETRIG; - m->param = 6 / (1+(eff&0x0F)) + 1; - break; - // 5.x: Set Vibrato Depth - case 0x50: - m->command = CMD_VIBRATO; - m->param = (eff & 0x0F); - break; - // 6.x: Set Vibrato Speed - case 0x60: - m->command = CMD_VIBRATO; - m->param = (eff & 0x0F) << 4; - break; - // 7.x: Vol Slide Up - case 0x70: - m->command = CMD_VOLUMESLIDE; - m->param = (eff & 0x0F) << 4; - break; - // 8.x: Vol Slide Down - case 0x80: - m->command = CMD_VOLUMESLIDE; - m->param = (eff & 0x0F); - break; - // A.x: Port to vol - case 0xA0: - m->volcmd = VOLCMD_VOLUME; - m->vol = ((eff & 0x0F) << 2) + 4; - break; - // B.x: Set Balance - case 0xB0: - m->command = CMD_PANNING8; - m->param = (eff & 0x0F) << 4; - break; - // F.x: Set Speed - case 0xF0: - m->command = CMD_SPEED; - m->param = eff & 0x0F; - break; - default: - if ((patbrk) && (patbrk+1 == (len >> 6)) && (patbrk+1 != rows-1)) - { - m->command = CMD_PATTERNBREAK; - patbrk = 0; - } - } - } - dwMemPos += patlen; - } - // Reading samples - if (dwMemPos + 8 >= dwMemLength) return TRUE; - memcpy(samplemap, lpStream+dwMemPos, 8); - dwMemPos += 8; - MODINSTRUMENT *pins = &Ins[1]; - for (UINT ismp=0; ismp<64; ismp++, pins++) if (samplemap[ismp >> 3] & (1 << (ismp & 7))) - { - if (dwMemPos + sizeof(FARSAMPLE) > dwMemLength) return TRUE; - FARSAMPLE *pfs = (FARSAMPLE *)(lpStream + dwMemPos); - dwMemPos += sizeof(FARSAMPLE); - m_nSamples = ismp + 1; - memcpy(m_szNames[ismp+1], pfs->samplename, 32); - pfs->length = bswapLE32( pfs->length ) ; /* endian fix - Toad */ - pins->nLength = pfs->length ; - pins->nLoopStart = bswapLE32(pfs->reppos) ; - pins->nLoopEnd = bswapLE32(pfs->repend) ; - pins->nFineTune = 0; - pins->nC4Speed = 8363*2; - pins->nGlobalVol = 64; - pins->nVolume = pfs->volume << 4; - pins->uFlags = 0; - if ((pins->nLength > 3) && (dwMemPos + 4 < dwMemLength)) - { - if (pfs->type & 1) - { - pins->uFlags |= CHN_16BIT; - pins->nLength >>= 1; - pins->nLoopStart >>= 1; - pins->nLoopEnd >>= 1; - } - if ((pfs->loop & 8) && (pins->nLoopEnd > 4)) pins->uFlags |= CHN_LOOP; - ReadSample(pins, (pins->uFlags & CHN_16BIT) ? RS_PCM16S : RS_PCM8S, - (LPSTR)(lpStream+dwMemPos), dwMemLength - dwMemPos); - } - dwMemPos += pfs->length; - } - return TRUE; -} - diff --git a/lib/libmodplug/src/load_it.cpp b/lib/libmodplug/src/load_it.cpp deleted file mode 100644 index daa80a2a76..0000000000 --- a/lib/libmodplug/src/load_it.cpp +++ /dev/null @@ -1,1515 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque <olivierl@jps.net>, - * Adam Goode <adam@evdebs.org> (Endian and char fixes for PPC) - * Marco Trillo <toad@arsystel.com> (Endian fixes for SaveIT, XM->IT Sample Converter) - * -*/ - -#include "stdafx.h" -#include "sndfile.h" -#include "it_defs.h" - -#ifdef _MSC_VER -#pragma warning(disable:4244) -#endif - -BYTE autovibit2xm[8] = -{ 0, 3, 1, 4, 2, 0, 0, 0 }; - -BYTE autovibxm2it[8] = -{ 0, 2, 4, 1, 3, 0, 0, 0 }; - -////////////////////////////////////////////////////////// -// Impulse Tracker IT file support - -// for conversion of XM samples -extern WORD XMPeriodTable[96+8]; -extern UINT XMLinearTable[768]; - -static inline UINT ConvertVolParam(UINT value) -//-------------------------------------------- -{ - return (value > 9) ? 9 : value; -} - - -BOOL CSoundFile::ITInstrToMPT(const void *p, INSTRUMENTHEADER *penv, UINT trkvers) -//-------------------------------------------------------------------------------- -{ - if (trkvers < 0x0200) - { - const ITOLDINSTRUMENT *pis = (const ITOLDINSTRUMENT *)p; - memcpy(penv->name, pis->name, 26); - memcpy(penv->filename, pis->filename, 12); - penv->nFadeOut = bswapLE16(pis->fadeout) << 6; - penv->nGlobalVol = 64; - for (UINT j=0; j<NOTE_MAX; j++) - { - UINT note = pis->keyboard[j*2]; - UINT ins = pis->keyboard[j*2+1]; - if (ins < MAX_SAMPLES) penv->Keyboard[j] = ins; - if (note < 128) penv->NoteMap[j] = note+1; - else if (note >= 0xFE) penv->NoteMap[j] = note; - } - if (pis->flags & 0x01) penv->dwFlags |= ENV_VOLUME; - if (pis->flags & 0x02) penv->dwFlags |= ENV_VOLLOOP; - if (pis->flags & 0x04) penv->dwFlags |= ENV_VOLSUSTAIN; - penv->nVolLoopStart = pis->vls; - penv->nVolLoopEnd = pis->vle; - penv->nVolSustainBegin = pis->sls; - penv->nVolSustainEnd = pis->sle; - penv->nVolEnv = 25; - for (UINT ev=0; ev<25; ev++) - { - if ((penv->VolPoints[ev] = pis->nodes[ev*2]) == 0xFF) - { - penv->nVolEnv = ev; - break; - } - penv->VolEnv[ev] = pis->nodes[ev*2+1]; - } - penv->nNNA = pis->nna; - penv->nDCT = pis->dnc; - penv->nPan = 0x80; - } else - { - const ITINSTRUMENT *pis = (const ITINSTRUMENT *)p; - memcpy(penv->name, pis->name, 26); - memcpy(penv->filename, pis->filename, 12); - penv->nMidiProgram = pis->mpr; - penv->nMidiChannel = pis->mch; - penv->wMidiBank = bswapLE16(pis->mbank); - penv->nFadeOut = bswapLE16(pis->fadeout) << 5; - penv->nGlobalVol = pis->gbv >> 1; - if (penv->nGlobalVol > 64) penv->nGlobalVol = 64; - for (UINT j=0; j<NOTE_MAX; j++) - { - UINT note = pis->keyboard[j*2]; - UINT ins = pis->keyboard[j*2+1]; - if (ins < MAX_SAMPLES) penv->Keyboard[j] = ins; - if (note < 128) penv->NoteMap[j] = note+1; - else if (note >= 0xFE) penv->NoteMap[j] = note; - } - // Volume Envelope - if (pis->volenv.flags & 1) penv->dwFlags |= ENV_VOLUME; - if (pis->volenv.flags & 2) penv->dwFlags |= ENV_VOLLOOP; - if (pis->volenv.flags & 4) penv->dwFlags |= ENV_VOLSUSTAIN; - if (pis->volenv.flags & 8) penv->dwFlags |= ENV_VOLCARRY; - penv->nVolEnv = pis->volenv.num; - if (penv->nVolEnv > 25) penv->nVolEnv = 25; - - penv->nVolLoopStart = pis->volenv.lpb; - penv->nVolLoopEnd = pis->volenv.lpe; - penv->nVolSustainBegin = pis->volenv.slb; - penv->nVolSustainEnd = pis->volenv.sle; - // Panning Envelope - if (pis->panenv.flags & 1) penv->dwFlags |= ENV_PANNING; - if (pis->panenv.flags & 2) penv->dwFlags |= ENV_PANLOOP; - if (pis->panenv.flags & 4) penv->dwFlags |= ENV_PANSUSTAIN; - if (pis->panenv.flags & 8) penv->dwFlags |= ENV_PANCARRY; - penv->nPanEnv = pis->panenv.num; - if (penv->nPanEnv > 25) penv->nPanEnv = 25; - penv->nPanLoopStart = pis->panenv.lpb; - penv->nPanLoopEnd = pis->panenv.lpe; - penv->nPanSustainBegin = pis->panenv.slb; - penv->nPanSustainEnd = pis->panenv.sle; - // Pitch Envelope - if (pis->pitchenv.flags & 1) penv->dwFlags |= ENV_PITCH; - if (pis->pitchenv.flags & 2) penv->dwFlags |= ENV_PITCHLOOP; - if (pis->pitchenv.flags & 4) penv->dwFlags |= ENV_PITCHSUSTAIN; - if (pis->pitchenv.flags & 8) penv->dwFlags |= ENV_PITCHCARRY; - if (pis->pitchenv.flags & 0x80) penv->dwFlags |= ENV_FILTER; - penv->nPitchEnv = pis->pitchenv.num; - if (penv->nPitchEnv > 25) penv->nPitchEnv = 25; - penv->nPitchLoopStart = pis->pitchenv.lpb; - penv->nPitchLoopEnd = pis->pitchenv.lpe; - penv->nPitchSustainBegin = pis->pitchenv.slb; - penv->nPitchSustainEnd = pis->pitchenv.sle; - // Envelopes Data - for (UINT ev=0; ev<25; ev++) - { - penv->VolEnv[ev] = pis->volenv.data[ev*3]; - penv->VolPoints[ev] = (pis->volenv.data[ev*3+2] << 8) | (pis->volenv.data[ev*3+1]); - penv->PanEnv[ev] = pis->panenv.data[ev*3] + 32; - penv->PanPoints[ev] = (pis->panenv.data[ev*3+2] << 8) | (pis->panenv.data[ev*3+1]); - penv->PitchEnv[ev] = pis->pitchenv.data[ev*3] + 32; - penv->PitchPoints[ev] = (pis->pitchenv.data[ev*3+2] << 8) | (pis->pitchenv.data[ev*3+1]); - } - penv->nNNA = pis->nna; - penv->nDCT = pis->dct; - penv->nDNA = pis->dca; - penv->nPPS = pis->pps; - penv->nPPC = pis->ppc; - penv->nIFC = pis->ifc; - penv->nIFR = pis->ifr; - penv->nVolSwing = pis->rv; - penv->nPanSwing = pis->rp; - penv->nPan = (pis->dfp & 0x7F) << 2; - if (penv->nPan > 256) penv->nPan = 128; - if (pis->dfp < 0x80) penv->dwFlags |= ENV_SETPANNING; - } - if ((penv->nVolLoopStart >= 25) || (penv->nVolLoopEnd >= 25)) penv->dwFlags &= ~ENV_VOLLOOP; - if ((penv->nVolSustainBegin >= 25) || (penv->nVolSustainEnd >= 25)) penv->dwFlags &= ~ENV_VOLSUSTAIN; - return TRUE; -} - - -BOOL CSoundFile::ReadIT(const BYTE *lpStream, DWORD dwMemLength) -//-------------------------------------------------------------- -{ - ITFILEHEADER pifh = *(ITFILEHEADER *)lpStream; - DWORD dwMemPos = sizeof(ITFILEHEADER); - DWORD inspos[MAX_INSTRUMENTS]; - DWORD smppos[MAX_SAMPLES]; - DWORD patpos[MAX_PATTERNS]; - BYTE chnmask[64], channels_used[64]; - MODCOMMAND lastvalue[64]; - - pifh.id = bswapLE32(pifh.id); - pifh.reserved1 = bswapLE16(pifh.reserved1); - pifh.ordnum = bswapLE16(pifh.ordnum); - pifh.insnum = bswapLE16(pifh.insnum); - pifh.smpnum = bswapLE16(pifh.smpnum); - pifh.patnum = bswapLE16(pifh.patnum); - pifh.cwtv = bswapLE16(pifh.cwtv); - pifh.cmwt = bswapLE16(pifh.cmwt); - pifh.flags = bswapLE16(pifh.flags); - pifh.special = bswapLE16(pifh.special); - pifh.msglength = bswapLE16(pifh.msglength); - pifh.msgoffset = bswapLE32(pifh.msgoffset); - pifh.reserved2 = bswapLE32(pifh.reserved2); - - if ((!lpStream) || (dwMemLength < 0x100)) return FALSE; - if ((pifh.id != 0x4D504D49) || (pifh.insnum >= MAX_INSTRUMENTS) - || (!pifh.smpnum) || (pifh.smpnum >= MAX_INSTRUMENTS) || (!pifh.ordnum)) return FALSE; - if (dwMemPos + pifh.ordnum + pifh.insnum*4 - + pifh.smpnum*4 + pifh.patnum*4 > dwMemLength) return FALSE; - m_nType = MOD_TYPE_IT; - if (pifh.flags & 0x08) m_dwSongFlags |= SONG_LINEARSLIDES; - if (pifh.flags & 0x10) m_dwSongFlags |= SONG_ITOLDEFFECTS; - if (pifh.flags & 0x20) m_dwSongFlags |= SONG_ITCOMPATMODE; - if (pifh.flags & 0x80) m_dwSongFlags |= SONG_EMBEDMIDICFG; - if (pifh.flags & 0x1000) m_dwSongFlags |= SONG_EXFILTERRANGE; - memcpy(m_szNames[0], pifh.songname, 26); - m_szNames[0][26] = 0; - // Global Volume - if (pifh.globalvol) - { - m_nDefaultGlobalVolume = pifh.globalvol << 1; - if (!m_nDefaultGlobalVolume) m_nDefaultGlobalVolume = 256; - if (m_nDefaultGlobalVolume > 256) m_nDefaultGlobalVolume = 256; - } - if (pifh.speed) m_nDefaultSpeed = pifh.speed; - if (pifh.tempo) m_nDefaultTempo = pifh.tempo; - m_nSongPreAmp = pifh.mv & 0x7F; - // Reading Channels Pan Positions - for (int ipan=0; ipan<64; ipan++) if (pifh.chnpan[ipan] != 0xFF) - { - ChnSettings[ipan].nVolume = pifh.chnvol[ipan]; - ChnSettings[ipan].nPan = 128; - if (pifh.chnpan[ipan] & 0x80) ChnSettings[ipan].dwFlags |= CHN_MUTE; - UINT n = pifh.chnpan[ipan] & 0x7F; - if (n <= 64) ChnSettings[ipan].nPan = n << 2; - if (n == 100) ChnSettings[ipan].dwFlags |= CHN_SURROUND; - } - if (m_nChannels < 4) m_nChannels = 4; - // Reading Song Message - if ((pifh.special & 0x01) && (pifh.msglength) && (pifh.msgoffset + pifh.msglength < dwMemLength)) - { - m_lpszSongComments = new char[pifh.msglength+1]; - if (m_lpszSongComments) - { - memcpy(m_lpszSongComments, lpStream+pifh.msgoffset, pifh.msglength); - m_lpszSongComments[pifh.msglength] = 0; - } - } - // Reading orders - UINT nordsize = pifh.ordnum; - if (nordsize > MAX_ORDERS) nordsize = MAX_ORDERS; - memcpy(Order, lpStream+dwMemPos, nordsize); - dwMemPos += pifh.ordnum; - // Reading Instrument Offsets - memset(inspos, 0, sizeof(inspos)); - UINT inspossize = pifh.insnum; - if (inspossize > MAX_INSTRUMENTS) inspossize = MAX_INSTRUMENTS; - inspossize <<= 2; - memcpy(inspos, lpStream+dwMemPos, inspossize); - for (UINT j=0; j < (inspossize>>2); j++) - { - inspos[j] = bswapLE32(inspos[j]); - } - dwMemPos += pifh.insnum * 4; - // Reading Samples Offsets - memset(smppos, 0, sizeof(smppos)); - UINT smppossize = pifh.smpnum; - if (smppossize > MAX_SAMPLES) smppossize = MAX_SAMPLES; - smppossize <<= 2; - memcpy(smppos, lpStream+dwMemPos, smppossize); - for (UINT j=0; j < (smppossize>>2); j++) - { - smppos[j] = bswapLE32(smppos[j]); - } - dwMemPos += pifh.smpnum * 4; - // Reading Patterns Offsets - memset(patpos, 0, sizeof(patpos)); - UINT patpossize = pifh.patnum; - if (patpossize > MAX_PATTERNS) patpossize = MAX_PATTERNS; - patpossize <<= 2; - memcpy(patpos, lpStream+dwMemPos, patpossize); - for (UINT j=0; j < (patpossize>>2); j++) - { - patpos[j] = bswapLE32(patpos[j]); - } - dwMemPos += pifh.patnum * 4; - // Reading IT Extra Info - if (dwMemPos + 2 < dwMemLength) - { - UINT nflt = bswapLE16(*((WORD *)(lpStream + dwMemPos))); - dwMemPos += 2; - if (dwMemPos + nflt * 8 < dwMemLength) dwMemPos += nflt * 8; - } - // Reading Midi Output & Macros - if (m_dwSongFlags & SONG_EMBEDMIDICFG) - { - if (dwMemPos + sizeof(MODMIDICFG) < dwMemLength) - { - memcpy(&m_MidiCfg, lpStream+dwMemPos, sizeof(MODMIDICFG)); - dwMemPos += sizeof(MODMIDICFG); - } - } - // Read pattern names: "PNAM" - if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x4d414e50)) - { - UINT len = bswapLE32(*((DWORD *)(lpStream+dwMemPos+4))); - dwMemPos += 8; - if ((dwMemPos + len <= dwMemLength) && (len <= MAX_PATTERNS*MAX_PATTERNNAME) && (len >= MAX_PATTERNNAME)) - { - m_lpszPatternNames = new char[len]; - if (m_lpszPatternNames) - { - m_nPatternNames = len / MAX_PATTERNNAME; - memcpy(m_lpszPatternNames, lpStream+dwMemPos, len); - } - dwMemPos += len; - } - } - // 4-channels minimum - m_nChannels = 4; - // Read channel names: "CNAM" - if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x4d414e43)) - { - UINT len = bswapLE32(*((DWORD *)(lpStream+dwMemPos+4))); - dwMemPos += 8; - if ((dwMemPos + len <= dwMemLength) && (len <= 64*MAX_CHANNELNAME)) - { - UINT n = len / MAX_CHANNELNAME; - if (n > m_nChannels) m_nChannels = n; - for (UINT i=0; i<n; i++) - { - memcpy(ChnSettings[i].szName, (lpStream+dwMemPos+i*MAX_CHANNELNAME), MAX_CHANNELNAME); - ChnSettings[i].szName[MAX_CHANNELNAME-1] = 0; - } - dwMemPos += len; - } - } - // Read mix plugins information - if (dwMemPos + 8 < dwMemLength) - { - dwMemPos += LoadMixPlugins(lpStream+dwMemPos, dwMemLength-dwMemPos); - } - // Checking for unused channels - UINT npatterns = pifh.patnum; - if (npatterns > MAX_PATTERNS) npatterns = MAX_PATTERNS; - for (UINT patchk=0; patchk<npatterns; patchk++) - { - memset(chnmask, 0, sizeof(chnmask)); - if ((!patpos[patchk]) || ((DWORD)patpos[patchk] + 4 >= dwMemLength)) continue; - UINT len = bswapLE16(*((WORD *)(lpStream+patpos[patchk]))); - UINT rows = bswapLE16(*((WORD *)(lpStream+patpos[patchk]+2))); - if ((rows < 4) || (rows > 256)) continue; - if (patpos[patchk]+8+len > dwMemLength) continue; - UINT i = 0; - const BYTE *p = lpStream+patpos[patchk]+8; - UINT nrow = 0; - while (nrow<rows) - { - if (i >= len) break; - BYTE b = p[i++]; - if (!b) - { - nrow++; - continue; - } - UINT ch = b & 0x7F; - if (ch) ch = (ch - 1) & 0x3F; - if (b & 0x80) - { - if (i >= len) break; - chnmask[ch] = p[i++]; - } - // Channel used - if (chnmask[ch] & 0x0F) - { - if ((ch >= m_nChannels) && (ch < 64)) m_nChannels = ch+1; - } - // Note - if (chnmask[ch] & 1) i++; - // Instrument - if (chnmask[ch] & 2) i++; - // Volume - if (chnmask[ch] & 4) i++; - // Effect - if (chnmask[ch] & 8) i += 2; - if (i >= len) break; - } - } - // Reading Instruments - m_nInstruments = 0; - if (pifh.flags & 0x04) m_nInstruments = pifh.insnum; - if (m_nInstruments >= MAX_INSTRUMENTS) m_nInstruments = MAX_INSTRUMENTS-1; - for (UINT nins=0; nins<m_nInstruments; nins++) - { - if ((inspos[nins] > 0) && (inspos[nins] < dwMemLength - sizeof(ITOLDINSTRUMENT))) - { - INSTRUMENTHEADER *penv = new INSTRUMENTHEADER; - if (!penv) continue; - Headers[nins+1] = penv; - memset(penv, 0, sizeof(INSTRUMENTHEADER)); - ITInstrToMPT(lpStream + inspos[nins], penv, pifh.cmwt); - } - } - // Reading Samples - m_nSamples = pifh.smpnum; - if (m_nSamples >= MAX_SAMPLES) m_nSamples = MAX_SAMPLES-1; - for (UINT nsmp=0; nsmp<pifh.smpnum; nsmp++) if ((smppos[nsmp]) && (smppos[nsmp] + sizeof(ITSAMPLESTRUCT) <= dwMemLength)) - { - ITSAMPLESTRUCT pis = *(ITSAMPLESTRUCT *)(lpStream+smppos[nsmp]); - pis.id = bswapLE32(pis.id); - pis.length = bswapLE32(pis.length); - pis.loopbegin = bswapLE32(pis.loopbegin); - pis.loopend = bswapLE32(pis.loopend); - pis.C5Speed = bswapLE32(pis.C5Speed); - pis.susloopbegin = bswapLE32(pis.susloopbegin); - pis.susloopend = bswapLE32(pis.susloopend); - pis.samplepointer = bswapLE32(pis.samplepointer); - - if (pis.id == 0x53504D49) - { - MODINSTRUMENT *pins = &Ins[nsmp+1]; - memcpy(pins->name, pis.filename, 12); - pins->uFlags = 0; - pins->nLength = 0; - pins->nLoopStart = pis.loopbegin; - pins->nLoopEnd = pis.loopend; - pins->nSustainStart = pis.susloopbegin; - pins->nSustainEnd = pis.susloopend; - pins->nC4Speed = pis.C5Speed; - if (!pins->nC4Speed) pins->nC4Speed = 8363; - if (pis.C5Speed < 256) pins->nC4Speed = 256; - pins->nVolume = pis.vol << 2; - if (pins->nVolume > 256) pins->nVolume = 256; - pins->nGlobalVol = pis.gvl; - if (pins->nGlobalVol > 64) pins->nGlobalVol = 64; - if (pis.flags & 0x10) pins->uFlags |= CHN_LOOP; - if (pis.flags & 0x20) pins->uFlags |= CHN_SUSTAINLOOP; - if (pis.flags & 0x40) pins->uFlags |= CHN_PINGPONGLOOP; - if (pis.flags & 0x80) pins->uFlags |= CHN_PINGPONGSUSTAIN; - pins->nPan = (pis.dfp & 0x7F) << 2; - if (pins->nPan > 256) pins->nPan = 256; - if (pis.dfp & 0x80) pins->uFlags |= CHN_PANNING; - pins->nVibType = autovibit2xm[pis.vit & 7]; - pins->nVibRate = pis.vis; - pins->nVibDepth = pis.vid & 0x7F; - pins->nVibSweep = (pis.vir + 3) / 4; - if ((pis.samplepointer) && (pis.samplepointer < dwMemLength) && (pis.length)) - { - pins->nLength = pis.length; - if (pins->nLength > MAX_SAMPLE_LENGTH) pins->nLength = MAX_SAMPLE_LENGTH; - UINT flags = (pis.cvt & 1) ? RS_PCM8S : RS_PCM8U; - if (pis.flags & 2) - { - flags += 5; - if (pis.flags & 4) flags |= RSF_STEREO; - pins->uFlags |= CHN_16BIT; - // IT 2.14 16-bit packed sample ? - if (pis.flags & 8) flags = ((pifh.cmwt >= 0x215) && (pis.cvt & 4)) ? RS_IT21516 : RS_IT21416; - } else - { - if (pis.flags & 4) flags |= RSF_STEREO; - if (pis.cvt == 0xFF) flags = RS_ADPCM4; else - // IT 2.14 8-bit packed sample ? - if (pis.flags & 8) flags = ((pifh.cmwt >= 0x215) && (pis.cvt & 4)) ? RS_IT2158 : RS_IT2148; - } - ReadSample(&Ins[nsmp+1], flags, (LPSTR)(lpStream+pis.samplepointer), dwMemLength - pis.samplepointer); - } - } - memcpy(m_szNames[nsmp+1], pis.name, 26); - } - // Reading Patterns - for (UINT npat=0; npat<npatterns; npat++) - { - if ((!patpos[npat]) || ((DWORD)patpos[npat] + 4 >= dwMemLength)) - { - PatternSize[npat] = 64; - Patterns[npat] = AllocatePattern(64, m_nChannels); - continue; - } - - UINT len = bswapLE16(*((WORD *)(lpStream+patpos[npat]))); - UINT rows = bswapLE16(*((WORD *)(lpStream+patpos[npat]+2))); - if ((rows < 4) || (rows > 256)) continue; - if (patpos[npat]+8+len > dwMemLength) continue; - PatternSize[npat] = rows; - if ((Patterns[npat] = AllocatePattern(rows, m_nChannels)) == NULL) continue; - memset(lastvalue, 0, sizeof(lastvalue)); - memset(chnmask, 0, sizeof(chnmask)); - MODCOMMAND *m = Patterns[npat]; - UINT i = 0; - const BYTE *p = lpStream+patpos[npat]+8; - UINT nrow = 0; - while (nrow<rows) - { - if (i >= len) break; - BYTE b = p[i++]; - if (!b) - { - nrow++; - m+=m_nChannels; - continue; - } - UINT ch = b & 0x7F; - if (ch) ch = (ch - 1) & 0x3F; - if (b & 0x80) - { - if (i >= len) break; - chnmask[ch] = p[i++]; - } - if ((chnmask[ch] & 0x10) && (ch < m_nChannels)) - { - m[ch].note = lastvalue[ch].note; - } - if ((chnmask[ch] & 0x20) && (ch < m_nChannels)) - { - m[ch].instr = lastvalue[ch].instr; - } - if ((chnmask[ch] & 0x40) && (ch < m_nChannels)) - { - m[ch].volcmd = lastvalue[ch].volcmd; - m[ch].vol = lastvalue[ch].vol; - } - if ((chnmask[ch] & 0x80) && (ch < m_nChannels)) - { - m[ch].command = lastvalue[ch].command; - m[ch].param = lastvalue[ch].param; - } - if (chnmask[ch] & 1) // Note - { - if (i >= len) break; - UINT note = p[i++]; - if (ch < m_nChannels) - { - if (note < 0x80) note++; - m[ch].note = note; - lastvalue[ch].note = note; - channels_used[ch] = TRUE; - } - } - if (chnmask[ch] & 2) - { - if (i >= len) break; - UINT instr = p[i++]; - if (ch < m_nChannels) - { - m[ch].instr = instr; - lastvalue[ch].instr = instr; - } - } - if (chnmask[ch] & 4) - { - if (i >= len) break; - UINT vol = p[i++]; - if (ch < m_nChannels) - { - // 0-64: Set Volume - if (vol <= 64) { m[ch].volcmd = VOLCMD_VOLUME; m[ch].vol = vol; } else - // 128-192: Set Panning - if ((vol >= 128) && (vol <= 192)) { m[ch].volcmd = VOLCMD_PANNING; m[ch].vol = vol - 128; } else - // 65-74: Fine Volume Up - if (vol < 75) { m[ch].volcmd = VOLCMD_FINEVOLUP; m[ch].vol = vol - 65; } else - // 75-84: Fine Volume Down - if (vol < 85) { m[ch].volcmd = VOLCMD_FINEVOLDOWN; m[ch].vol = vol - 75; } else - // 85-94: Volume Slide Up - if (vol < 95) { m[ch].volcmd = VOLCMD_VOLSLIDEUP; m[ch].vol = vol - 85; } else - // 95-104: Volume Slide Down - if (vol < 105) { m[ch].volcmd = VOLCMD_VOLSLIDEDOWN; m[ch].vol = vol - 95; } else - // 105-114: Pitch Slide Up - if (vol < 115) { m[ch].volcmd = VOLCMD_PORTADOWN; m[ch].vol = vol - 105; } else - // 115-124: Pitch Slide Down - if (vol < 125) { m[ch].volcmd = VOLCMD_PORTAUP; m[ch].vol = vol - 115; } else - // 193-202: Portamento To - if ((vol >= 193) && (vol <= 202)) { m[ch].volcmd = VOLCMD_TONEPORTAMENTO; m[ch].vol = vol - 193; } else - // 203-212: Vibrato - if ((vol >= 203) && (vol <= 212)) { m[ch].volcmd = VOLCMD_VIBRATOSPEED; m[ch].vol = vol - 203; } - lastvalue[ch].volcmd = m[ch].volcmd; - lastvalue[ch].vol = m[ch].vol; - } - } - // Reading command/param - if (chnmask[ch] & 8) - { - if (i > len - 2) break; - UINT cmd = p[i++]; - UINT param = p[i++]; - if (ch < m_nChannels) - { - if (cmd) - { - m[ch].command = cmd; - m[ch].param = param; - S3MConvert(&m[ch], TRUE); - lastvalue[ch].command = m[ch].command; - lastvalue[ch].param = m[ch].param; - } - } - } - } - } - for (UINT ncu=0; ncu<MAX_BASECHANNELS; ncu++) - { - if (ncu>=m_nChannels) - { - ChnSettings[ncu].nVolume = 64; - ChnSettings[ncu].dwFlags &= ~CHN_MUTE; - } - } - m_nMinPeriod = 8; - m_nMaxPeriod = 0xF000; - return TRUE; -} - - -#ifndef MODPLUG_NO_FILESAVE -//#define SAVEITTIMESTAMP -#ifdef _MSC_VER -#pragma warning(disable:4100) -#endif - -BOOL CSoundFile::SaveIT(LPCSTR lpszFileName, UINT nPacking) -//--------------------------------------------------------- -{ - DWORD dwPatNamLen, dwChnNamLen; - ITFILEHEADER header, writeheader; - ITINSTRUMENT iti, writeiti; - ITSAMPLESTRUCT itss; - BYTE smpcount[MAX_SAMPLES]; - DWORD inspos[MAX_INSTRUMENTS]; - DWORD patpos[MAX_PATTERNS]; - DWORD smppos[MAX_SAMPLES]; - DWORD dwPos = 0, dwHdrPos = 0, dwExtra = 2; - WORD patinfo[4]; - BYTE chnmask[64]; - BYTE buf[512]; - MODCOMMAND lastvalue[64]; - FILE *f; - - - if ((!lpszFileName) || ((f = fopen(lpszFileName, "wb")) == NULL)) return FALSE; - memset(inspos, 0, sizeof(inspos)); - memset(patpos, 0, sizeof(patpos)); - memset(smppos, 0, sizeof(smppos)); - // Writing Header - memset(&header, 0, sizeof(header)); - dwPatNamLen = 0; - dwChnNamLen = 0; - header.id = 0x4D504D49; // IMPM - lstrcpyn((char *)header.songname, m_szNames[0], 27); - header.reserved1 = 0x1004; - header.ordnum = 0; - while ((header.ordnum < MAX_ORDERS) && (Order[header.ordnum] < 0xFF)) header.ordnum++; - if (header.ordnum < MAX_ORDERS) Order[header.ordnum++] = 0xFF; - header.insnum = m_nInstruments; - header.smpnum = m_nSamples; - header.patnum = MAX_PATTERNS; - while ((header.patnum > 0) && (!Patterns[header.patnum-1])) header.patnum--; - header.cwtv = 0x217; - header.cmwt = 0x200; - header.flags = 0x0001; - header.special = 0x0006; - if (m_nInstruments) header.flags |= 0x04; - if (m_dwSongFlags & SONG_LINEARSLIDES) header.flags |= 0x08; - if (m_dwSongFlags & SONG_ITOLDEFFECTS) header.flags |= 0x10; - if (m_dwSongFlags & SONG_ITCOMPATMODE) header.flags |= 0x20; - if (m_dwSongFlags & SONG_EXFILTERRANGE) header.flags |= 0x1000; - header.globalvol = m_nDefaultGlobalVolume >> 1; - header.mv = m_nSongPreAmp; - // clip song pre-amp values (between 0x20 and 0x7f) - if (header.mv < 0x20) header.mv = 0x20; - if (header.mv > 0x7F) header.mv = 0x7F; - header.speed = m_nDefaultSpeed; - header.tempo = m_nDefaultTempo; - header.sep = m_nStereoSeparation; - dwHdrPos = sizeof(header) + header.ordnum; - // Channel Pan and Volume - memset(header.chnpan, 0xFF, 64); - memset(header.chnvol, 64, 64); - for (UINT ich=0; ich<m_nChannels; ich++) - { - header.chnpan[ich] = ChnSettings[ich].nPan >> 2; - if (ChnSettings[ich].dwFlags & CHN_SURROUND) header.chnpan[ich] = 100; - header.chnvol[ich] = ChnSettings[ich].nVolume; - if (ChnSettings[ich].dwFlags & CHN_MUTE) header.chnpan[ich] |= 0x80; - if (ChnSettings[ich].szName[0]) - { - dwChnNamLen = (ich+1) * MAX_CHANNELNAME; - } - } - if (dwChnNamLen) dwExtra += dwChnNamLen + 8; -#ifdef SAVEITTIMESTAMP - dwExtra += 8; // Time Stamp -#endif - if (m_dwSongFlags & SONG_EMBEDMIDICFG) - { - header.flags |= 0x80; - header.special |= 0x08; - dwExtra += sizeof(MODMIDICFG); - } - // Pattern Names - if ((m_nPatternNames) && (m_lpszPatternNames)) - { - dwPatNamLen = m_nPatternNames * MAX_PATTERNNAME; - while ((dwPatNamLen >= MAX_PATTERNNAME) && (!m_lpszPatternNames[dwPatNamLen-MAX_PATTERNNAME])) dwPatNamLen -= MAX_PATTERNNAME; - if (dwPatNamLen < MAX_PATTERNNAME) dwPatNamLen = 0; - if (dwPatNamLen) dwExtra += dwPatNamLen + 8; - } - // Mix Plugins - dwExtra += SaveMixPlugins(NULL, TRUE); - // Comments - if (m_lpszSongComments) - { - header.special |= 1; - header.msglength = strlen(m_lpszSongComments)+1; - header.msgoffset = dwHdrPos + dwExtra + header.insnum*4 + header.patnum*4 + header.smpnum*4; - } - // Write file header - memcpy(&writeheader, &header, sizeof(header)); - - // Byteswap header information - writeheader.id = bswapLE32(writeheader.id); - writeheader.reserved1 = bswapLE16(writeheader.reserved1); - writeheader.ordnum = bswapLE16(writeheader.ordnum); - writeheader.insnum = bswapLE16(writeheader.insnum); - writeheader.smpnum = bswapLE16(writeheader.smpnum); - writeheader.patnum = bswapLE16(writeheader.patnum); - writeheader.cwtv = bswapLE16(writeheader.cwtv); - writeheader.cmwt = bswapLE16(writeheader.cmwt); - writeheader.flags = bswapLE16(writeheader.flags); - writeheader.special = bswapLE16(writeheader.special); - writeheader.msglength = bswapLE16(writeheader.msglength); - writeheader.msgoffset = bswapLE32(writeheader.msgoffset); - writeheader.reserved2 = bswapLE32(writeheader.reserved2); - - fwrite(&writeheader, 1, sizeof(writeheader), f); - - fwrite(Order, 1, header.ordnum, f); - if (header.insnum) fwrite(inspos, 4, header.insnum, f); - if (header.smpnum) fwrite(smppos, 4, header.smpnum, f); - if (header.patnum) fwrite(patpos, 4, header.patnum, f); - // Writing editor history information - { -#ifdef SAVEITTIMESTAMP - SYSTEMTIME systime; - FILETIME filetime; - WORD timestamp[4]; - WORD nInfoEx = 1; - memset(timestamp, 0, sizeof(timestamp)); - fwrite(&nInfoEx, 1, 2, f); - GetSystemTime(&systime); - SystemTimeToFileTime(&systime, &filetime); - FileTimeToDosDateTime(&filetime, ×tamp[0], ×tamp[1]); - fwrite(timestamp, 1, 8, f); -#else - WORD nInfoEx = 0; - fwrite(&nInfoEx, 1, 2, f); -#endif - } - // Writing midi cfg - if (header.flags & 0x80) - { - fwrite(&m_MidiCfg, 1, sizeof(MODMIDICFG), f); - } - // Writing pattern names - if (dwPatNamLen) - { - DWORD d = bswapLE32(0x4d414e50); - UINT len= bswapLE32(dwPatNamLen); - fwrite(&d, 1, 4, f); - fwrite(&len, 1, 4, f); - fwrite(m_lpszPatternNames, 1, dwPatNamLen, f); - } - // Writing channel Names - if (dwChnNamLen) - { - DWORD d = bswapLE32(0x4d414e43); - UINT len= bswapLE32(dwChnNamLen); - fwrite(&d, 1, 4, f); - fwrite(&len, 1, 4, f); - UINT nChnNames = dwChnNamLen / MAX_CHANNELNAME; - for (UINT inam=0; inam<nChnNames; inam++) - { - fwrite(ChnSettings[inam].szName, 1, MAX_CHANNELNAME, f); - } - } - // Writing mix plugins info - SaveMixPlugins(f, FALSE); - // Writing song message - dwPos = dwHdrPos + dwExtra + (header.insnum + header.smpnum + header.patnum) * 4; - if (header.special & 1) - { - dwPos += strlen(m_lpszSongComments) + 1; - fwrite(m_lpszSongComments, 1, strlen(m_lpszSongComments)+1, f); - } - // Writing instruments - for (UINT nins=1; nins<=header.insnum; nins++) - { - memset(&iti, 0, sizeof(iti)); - iti.id = 0x49504D49; // "IMPI" - iti.trkvers = 0x211; - if (Headers[nins]) - { - INSTRUMENTHEADER *penv = Headers[nins]; - memset(smpcount, 0, sizeof(smpcount)); - memcpy(iti.filename, penv->filename, 12); - memcpy(iti.name, penv->name, 26); - iti.mbank = penv->wMidiBank; - iti.mpr = penv->nMidiProgram; - iti.mch = penv->nMidiChannel; - iti.nna = penv->nNNA; - iti.dct = penv->nDCT; - iti.dca = penv->nDNA; - iti.fadeout = penv->nFadeOut >> 5; - iti.pps = penv->nPPS; - iti.ppc = penv->nPPC; - iti.gbv = (BYTE)(penv->nGlobalVol << 1); - iti.dfp = (BYTE)penv->nPan >> 2; - if (!(penv->dwFlags & ENV_SETPANNING)) iti.dfp |= 0x80; - iti.rv = penv->nVolSwing; - iti.rp = penv->nPanSwing; - iti.ifc = penv->nIFC; - iti.ifr = penv->nIFR; - iti.nos = 0; - for (UINT i=0; i<NOTE_MAX; i++) if (penv->Keyboard[i] < MAX_SAMPLES) - { - UINT smp = penv->Keyboard[i]; - if ((smp) && (!smpcount[smp])) - { - smpcount[smp] = 1; - iti.nos++; - } - iti.keyboard[i*2] = penv->NoteMap[i] - 1; - iti.keyboard[i*2+1] = smp; - } - // Writing Volume envelope - if (penv->dwFlags & ENV_VOLUME) iti.volenv.flags |= 0x01; - if (penv->dwFlags & ENV_VOLLOOP) iti.volenv.flags |= 0x02; - if (penv->dwFlags & ENV_VOLSUSTAIN) iti.volenv.flags |= 0x04; - if (penv->dwFlags & ENV_VOLCARRY) iti.volenv.flags |= 0x08; - iti.volenv.num = (BYTE)penv->nVolEnv; - iti.volenv.lpb = (BYTE)penv->nVolLoopStart; - iti.volenv.lpe = (BYTE)penv->nVolLoopEnd; - iti.volenv.slb = penv->nVolSustainBegin; - iti.volenv.sle = penv->nVolSustainEnd; - // Writing Panning envelope - if (penv->dwFlags & ENV_PANNING) iti.panenv.flags |= 0x01; - if (penv->dwFlags & ENV_PANLOOP) iti.panenv.flags |= 0x02; - if (penv->dwFlags & ENV_PANSUSTAIN) iti.panenv.flags |= 0x04; - if (penv->dwFlags & ENV_PANCARRY) iti.panenv.flags |= 0x08; - iti.panenv.num = (BYTE)penv->nPanEnv; - iti.panenv.lpb = (BYTE)penv->nPanLoopStart; - iti.panenv.lpe = (BYTE)penv->nPanLoopEnd; - iti.panenv.slb = penv->nPanSustainBegin; - iti.panenv.sle = penv->nPanSustainEnd; - // Writing Pitch Envelope - if (penv->dwFlags & ENV_PITCH) iti.pitchenv.flags |= 0x01; - if (penv->dwFlags & ENV_PITCHLOOP) iti.pitchenv.flags |= 0x02; - if (penv->dwFlags & ENV_PITCHSUSTAIN) iti.pitchenv.flags |= 0x04; - if (penv->dwFlags & ENV_PITCHCARRY) iti.pitchenv.flags |= 0x08; - if (penv->dwFlags & ENV_FILTER) iti.pitchenv.flags |= 0x80; - iti.pitchenv.num = (BYTE)penv->nPitchEnv; - iti.pitchenv.lpb = (BYTE)penv->nPitchLoopStart; - iti.pitchenv.lpe = (BYTE)penv->nPitchLoopEnd; - iti.pitchenv.slb = (BYTE)penv->nPitchSustainBegin; - iti.pitchenv.sle = (BYTE)penv->nPitchSustainEnd; - // Writing Envelopes data - for (UINT ev=0; ev<25; ev++) - { - iti.volenv.data[ev*3] = penv->VolEnv[ev]; - iti.volenv.data[ev*3+1] = penv->VolPoints[ev] & 0xFF; - iti.volenv.data[ev*3+2] = penv->VolPoints[ev] >> 8; - iti.panenv.data[ev*3] = penv->PanEnv[ev] - 32; - iti.panenv.data[ev*3+1] = penv->PanPoints[ev] & 0xFF; - iti.panenv.data[ev*3+2] = penv->PanPoints[ev] >> 8; - iti.pitchenv.data[ev*3] = penv->PitchEnv[ev] - 32; - iti.pitchenv.data[ev*3+1] = penv->PitchPoints[ev] & 0xFF; - iti.pitchenv.data[ev*3+2] = penv->PitchPoints[ev] >> 8; - } - } else - // Save Empty Instrument - { - for (UINT i=0; i<NOTE_MAX; i++) iti.keyboard[i*2] = i; - iti.ppc = 5*12; - iti.gbv = 128; - iti.dfp = 0x20; - iti.ifc = 0xFF; - } - if (!iti.nos) iti.trkvers = 0; - // Writing instrument - inspos[nins-1] = dwPos; - dwPos += sizeof(ITINSTRUMENT); - - memcpy(&writeiti, &iti, sizeof(ITINSTRUMENT)); - - writeiti.fadeout = bswapLE16(writeiti.fadeout); - writeiti.id = bswapLE32(writeiti.id); - writeiti.trkvers = bswapLE16(writeiti.trkvers); - writeiti.mbank = bswapLE16(writeiti.mbank); - - fwrite(&writeiti, 1, sizeof(ITINSTRUMENT), f); - } - // Writing sample headers - memset(&itss, 0, sizeof(itss)); - for (UINT hsmp=0; hsmp<header.smpnum; hsmp++) - { - smppos[hsmp] = dwPos; - dwPos += sizeof(ITSAMPLESTRUCT); - fwrite(&itss, 1, sizeof(ITSAMPLESTRUCT), f); - } - // Writing Patterns - for (UINT npat=0; npat<header.patnum; npat++) - { - DWORD dwPatPos = dwPos; - UINT len; - if (!Patterns[npat]) continue; - patpos[npat] = dwPos; - patinfo[0] = 0; - patinfo[1] = bswapLE16(PatternSize[npat]); - patinfo[2] = 0; - patinfo[3] = 0; - // Check for empty pattern - if (PatternSize[npat] == 64) - { - MODCOMMAND *pzc = Patterns[npat]; - UINT iz, nz = PatternSize[npat] * m_nChannels; - for (iz=0; iz<nz; iz++) - { - if ((pzc[iz].note) || (pzc[iz].instr) - || (pzc[iz].volcmd) || (pzc[iz].command)) break; - } - if (iz == nz) - { - patpos[npat] = 0; - continue; - } - } - fwrite(patinfo, 8, 1, f); - dwPos += 8; - memset(chnmask, 0xFF, sizeof(chnmask)); - memset(lastvalue, 0, sizeof(lastvalue)); - MODCOMMAND *m = Patterns[npat]; - for (UINT row=0; row<PatternSize[npat]; row++) - { - len = 0; - for (UINT ch=0; ch<m_nChannels; ch++, m++) - { - BYTE b = 0; - UINT command = m->command; - UINT param = m->param; - UINT vol = 0xFF; - UINT note = m->note; - if (note) b |= 1; - if ((note) && (note < 0x80)) note--; // 0xfe->0x80 --Toad - if (m->instr) b |= 2; - if (m->volcmd) - { - UINT volcmd = m->volcmd; - switch(volcmd) - { - case VOLCMD_VOLUME: vol = m->vol; if (vol > 64) vol = 64; break; - case VOLCMD_PANNING: vol = m->vol + 128; if (vol > 192) vol = 192; break; - case VOLCMD_VOLSLIDEUP: vol = 85 + ConvertVolParam(m->vol); break; - case VOLCMD_VOLSLIDEDOWN: vol = 95 + ConvertVolParam(m->vol); break; - case VOLCMD_FINEVOLUP: vol = 65 + ConvertVolParam(m->vol); break; - case VOLCMD_FINEVOLDOWN: vol = 75 + ConvertVolParam(m->vol); break; - case VOLCMD_VIBRATOSPEED: vol = 203 + ConvertVolParam(m->vol); break; - case VOLCMD_VIBRATO: vol = 203; break; - case VOLCMD_TONEPORTAMENTO: vol = 193 + ConvertVolParam(m->vol); break; - case VOLCMD_PORTADOWN: vol = 105 + ConvertVolParam(m->vol); break; - case VOLCMD_PORTAUP: vol = 115 + ConvertVolParam(m->vol); break; - default: vol = 0xFF; - } - } - if (vol != 0xFF) b |= 4; - if (command) - { - S3MSaveConvert(&command, ¶m, TRUE); - if (command) b |= 8; - } - // Packing information - if (b) - { - // Same note ? - if (b & 1) - { - if ((note == lastvalue[ch].note) && (lastvalue[ch].volcmd & 1)) - { - b &= ~1; - b |= 0x10; - } else - { - lastvalue[ch].note = note; - lastvalue[ch].volcmd |= 1; - } - } - // Same instrument ? - if (b & 2) - { - if ((m->instr == lastvalue[ch].instr) && (lastvalue[ch].volcmd & 2)) - { - b &= ~2; - b |= 0x20; - } else - { - lastvalue[ch].instr = m->instr; - lastvalue[ch].volcmd |= 2; - } - } - // Same volume column byte ? - if (b & 4) - { - if ((vol == lastvalue[ch].vol) && (lastvalue[ch].volcmd & 4)) - { - b &= ~4; - b |= 0x40; - } else - { - lastvalue[ch].vol = vol; - lastvalue[ch].volcmd |= 4; - } - } - // Same command / param ? - if (b & 8) - { - if ((command == lastvalue[ch].command) && (param == lastvalue[ch].param) && (lastvalue[ch].volcmd & 8)) - { - b &= ~8; - b |= 0x80; - } else - { - lastvalue[ch].command = command; - lastvalue[ch].param = param; - lastvalue[ch].volcmd |= 8; - } - } - if (b != chnmask[ch]) - { - chnmask[ch] = b; - buf[len++] = (ch+1) | 0x80; - buf[len++] = b; - } else - { - buf[len++] = ch+1; - } - if (b & 1) buf[len++] = note; - if (b & 2) buf[len++] = m->instr; - if (b & 4) buf[len++] = vol; - if (b & 8) - { - buf[len++] = command; - buf[len++] = param; - } - } - } - buf[len++] = 0; - dwPos += len; - patinfo[0] += len; - fwrite(buf, 1, len, f); - } - fseek(f, dwPatPos, SEEK_SET); - patinfo[0] = bswapLE16(patinfo[0]); // byteswap -- Toad - fwrite(patinfo, 8, 1, f); - fseek(f, dwPos, SEEK_SET); - } - // Writing Sample Data - for (UINT nsmp=1; nsmp<=header.smpnum; nsmp++) - { - MODINSTRUMENT *psmp = &Ins[nsmp]; - memset(&itss, 0, sizeof(itss)); - memcpy(itss.filename, psmp->name, 12); - memcpy(itss.name, m_szNames[nsmp], 26); - itss.id = 0x53504D49; - itss.gvl = (BYTE)psmp->nGlobalVol; - if (m_nInstruments) - { - for (UINT iu=1; iu<=m_nInstruments; iu++) if (Headers[iu]) - { - INSTRUMENTHEADER *penv = Headers[iu]; - for (UINT ju=0; ju<128; ju++) if (penv->Keyboard[ju] == nsmp) - { - itss.flags = 0x01; - break; - } - } - } else - { - itss.flags = 0x01; - } - if (psmp->uFlags & CHN_LOOP) itss.flags |= 0x10; - if (psmp->uFlags & CHN_SUSTAINLOOP) itss.flags |= 0x20; - if (psmp->uFlags & CHN_PINGPONGLOOP) itss.flags |= 0x40; - if (psmp->uFlags & CHN_PINGPONGSUSTAIN) itss.flags |= 0x80; - itss.C5Speed = psmp->nC4Speed; - if (!itss.C5Speed) // if no C5Speed assume it is XM Sample - { - UINT period; - - /** - * C5 note => number 61, but in XM samples: - * RealNote = Note + RelativeTone - */ - period = GetPeriodFromNote(61+psmp->RelativeTone, psmp->nFineTune, 0); - - if (period) - itss.C5Speed = GetFreqFromPeriod(period, 0, 0); - /** - * If it didn`t work, it may not be a XM file; - * so put the default C5Speed, 8363Hz. - */ - if (!itss.C5Speed) itss.C5Speed = 8363; - } - - itss.length = psmp->nLength; - itss.loopbegin = psmp->nLoopStart; - itss.loopend = psmp->nLoopEnd; - itss.susloopbegin = psmp->nSustainStart; - itss.susloopend = psmp->nSustainEnd; - itss.vol = psmp->nVolume >> 2; - itss.dfp = psmp->nPan >> 2; - itss.vit = autovibxm2it[psmp->nVibType & 7]; - itss.vis = psmp->nVibRate; - itss.vid = psmp->nVibDepth; - itss.vir = (psmp->nVibSweep < 64) ? psmp->nVibSweep * 4 : 255; - if (psmp->uFlags & CHN_PANNING) itss.dfp |= 0x80; - if ((psmp->pSample) && (psmp->nLength)) itss.cvt = 0x01; - UINT flags = RS_PCM8S; -#ifndef NO_PACKING - if (nPacking) - { - if ((!(psmp->uFlags & (CHN_16BIT|CHN_STEREO))) - && (CanPackSample((char *)psmp->pSample, psmp->nLength, nPacking))) - { - flags = RS_ADPCM4; - itss.cvt = 0xFF; - } - } else -#endif // NO_PACKING - { - if (psmp->uFlags & CHN_STEREO) - { - flags = RS_STPCM8S; - itss.flags |= 0x04; - } - if (psmp->uFlags & CHN_16BIT) - { - itss.flags |= 0x02; - flags = (psmp->uFlags & CHN_STEREO) ? RS_STPCM16S : RS_PCM16S; - } - } - itss.samplepointer = dwPos; - fseek(f, smppos[nsmp-1], SEEK_SET); - - itss.id = bswapLE32(itss.id); - itss.length = bswapLE32(itss.length); - itss.loopbegin = bswapLE32(itss.loopbegin); - itss.loopend = bswapLE32(itss.loopend); - itss.C5Speed = bswapLE32(itss.C5Speed); - itss.susloopbegin = bswapLE32(itss.susloopbegin); - itss.susloopend = bswapLE32(itss.susloopend); - itss.samplepointer = bswapLE32(itss.samplepointer); - - fwrite(&itss, 1, sizeof(ITSAMPLESTRUCT), f); - fseek(f, dwPos, SEEK_SET); - if ((psmp->pSample) && (psmp->nLength)) - { - dwPos += WriteSample(f, psmp, flags); - } - } - // Updating offsets - fseek(f, dwHdrPos, SEEK_SET); - - /* <Toad> Now we can byteswap them ;-) */ - UINT WW; - UINT WX; - WX = (UINT)header.insnum; - WX <<= 2; - for (WW=0; WW < (WX>>2); WW++) - inspos[WW] = bswapLE32(inspos[WW]); - - WX = (UINT)header.smpnum; - WX <<= 2; - for (WW=0; WW < (WX>>2); WW++) - smppos[WW] = bswapLE32(smppos[WW]); - - WX=(UINT)header.patnum; - WX <<= 2; - for (WW=0; WW < (WX>>2); WW++) - patpos[WW] = bswapLE32(patpos[WW]); - - if (header.insnum) fwrite(inspos, 4, header.insnum, f); - if (header.smpnum) fwrite(smppos, 4, header.smpnum, f); - if (header.patnum) fwrite(patpos, 4, header.patnum, f); - fclose(f); - return TRUE; -} - -#ifdef _MSC_VER -//#pragma warning(default:4100) -#endif -#endif // MODPLUG_NO_FILESAVE - -////////////////////////////////////////////////////////////////////////////// -// IT 2.14 compression - -DWORD ITReadBits(DWORD &bitbuf, UINT &bitnum, LPBYTE &ibuf, CHAR n) -//----------------------------------------------------------------- -{ - DWORD retval = 0; - UINT i = n; - - if (n > 0) - { - do - { - if (!bitnum) - { - bitbuf = *ibuf++; - bitnum = 8; - } - retval >>= 1; - retval |= bitbuf << 31; - bitbuf >>= 1; - bitnum--; - i--; - } while (i); - i = n; - } - return (retval >> (32-i)); -} - -#define IT215_SUPPORT -void ITUnpack8Bit(signed char *pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dwMemLength, BOOL b215) -//------------------------------------------------------------------------------------------- -{ - signed char *pDst = pSample; - LPBYTE pSrc = lpMemFile; - DWORD wHdr = 0; - DWORD wCount = 0; - DWORD bitbuf = 0; - UINT bitnum = 0; - BYTE bLeft = 0, bTemp = 0, bTemp2 = 0; - - while (dwLen) - { - if (!wCount) - { - wCount = 0x8000; - wHdr = bswapLE16(*((LPWORD)pSrc)); - pSrc += 2; - bLeft = 9; - bTemp = bTemp2 = 0; - bitbuf = bitnum = 0; - } - DWORD d = wCount; - if (d > dwLen) d = dwLen; - // Unpacking - DWORD dwPos = 0; - do - { - WORD wBits = (WORD)ITReadBits(bitbuf, bitnum, pSrc, bLeft); - if (bLeft < 7) - { - DWORD i = 1 << (bLeft-1); - DWORD j = wBits & 0xFFFF; - if (i != j) goto UnpackByte; - wBits = (WORD)(ITReadBits(bitbuf, bitnum, pSrc, 3) + 1) & 0xFF; - bLeft = ((BYTE)wBits < bLeft) ? (BYTE)wBits : (BYTE)((wBits+1) & 0xFF); - goto Next; - } - if (bLeft < 9) - { - WORD i = (0xFF >> (9 - bLeft)) + 4; - WORD j = i - 8; - if ((wBits <= j) || (wBits > i)) goto UnpackByte; - wBits -= j; - bLeft = ((BYTE)(wBits & 0xFF) < bLeft) ? (BYTE)(wBits & 0xFF) : (BYTE)((wBits+1) & 0xFF); - goto Next; - } - if (bLeft >= 10) goto SkipByte; - if (wBits >= 256) - { - bLeft = (BYTE)(wBits + 1) & 0xFF; - goto Next; - } - UnpackByte: - if (bLeft < 8) - { - BYTE shift = 8 - bLeft; - signed char c = (signed char)(wBits << shift); - c >>= shift; - wBits = (WORD)c; - } - wBits += bTemp; - bTemp = (BYTE)wBits; - bTemp2 += bTemp; -#ifdef IT215_SUPPORT - pDst[dwPos] = (b215) ? bTemp2 : bTemp; -#else - pDst[dwPos] = bTemp; -#endif - SkipByte: - dwPos++; - Next: - if (pSrc >= lpMemFile+dwMemLength+1) return; - } while (dwPos < d); - // Move On - wCount -= d; - dwLen -= d; - pDst += d; - } -} - - -void ITUnpack16Bit(signed char *pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dwMemLength, BOOL b215) -//-------------------------------------------------------------------------------------------- -{ - signed short *pDst = (signed short *)pSample; - LPBYTE pSrc = lpMemFile; - DWORD wHdr = 0; - DWORD wCount = 0; - DWORD bitbuf = 0; - UINT bitnum = 0; - BYTE bLeft = 0; - signed short wTemp = 0, wTemp2 = 0; - - while (dwLen) - { - if (!wCount) - { - wCount = 0x4000; - wHdr = bswapLE16(*((LPWORD)pSrc)); - pSrc += 2; - bLeft = 17; - wTemp = wTemp2 = 0; - bitbuf = bitnum = 0; - } - DWORD d = wCount; - if (d > dwLen) d = dwLen; - // Unpacking - DWORD dwPos = 0; - do - { - DWORD dwBits = ITReadBits(bitbuf, bitnum, pSrc, bLeft); - if (bLeft < 7) - { - DWORD i = 1 << (bLeft-1); - DWORD j = dwBits; - if (i != j) goto UnpackByte; - dwBits = ITReadBits(bitbuf, bitnum, pSrc, 4) + 1; - bLeft = ((BYTE)(dwBits & 0xFF) < bLeft) ? (BYTE)(dwBits & 0xFF) : (BYTE)((dwBits+1) & 0xFF); - goto Next; - } - if (bLeft < 17) - { - DWORD i = (0xFFFF >> (17 - bLeft)) + 8; - DWORD j = (i - 16) & 0xFFFF; - if ((dwBits <= j) || (dwBits > (i & 0xFFFF))) goto UnpackByte; - dwBits -= j; - bLeft = ((BYTE)(dwBits & 0xFF) < bLeft) ? (BYTE)(dwBits & 0xFF) : (BYTE)((dwBits+1) & 0xFF); - goto Next; - } - if (bLeft >= 18) goto SkipByte; - if (dwBits >= 0x10000) - { - bLeft = (BYTE)(dwBits + 1) & 0xFF; - goto Next; - } - UnpackByte: - if (bLeft < 16) - { - BYTE shift = 16 - bLeft; - signed short c = (signed short)(dwBits << shift); - c >>= shift; - dwBits = (DWORD)c; - } - dwBits += wTemp; - wTemp = (signed short)dwBits; - wTemp2 += wTemp; -#ifdef IT215_SUPPORT - pDst[dwPos] = (b215) ? wTemp2 : wTemp; -#else - pDst[dwPos] = wTemp; -#endif - SkipByte: - dwPos++; - Next: - if (pSrc >= lpMemFile+dwMemLength+1) return; - } while (dwPos < d); - // Move On - wCount -= d; - dwLen -= d; - pDst += d; - if (pSrc >= lpMemFile+dwMemLength) break; - } -} - - -UINT CSoundFile::SaveMixPlugins(FILE *f, BOOL bUpdate) -//---------------------------------------------------- -{ - DWORD chinfo[64]; - CHAR s[32]; - DWORD nPluginSize, writeSwapDWORD; - SNDMIXPLUGININFO writePluginInfo; - UINT nTotalSize = 0; - UINT nChInfo = 0; - - for (UINT i=0; i<MAX_MIXPLUGINS; i++) - { - PSNDMIXPLUGIN p = &m_MixPlugins[i]; - if ((p->Info.dwPluginId1) || (p->Info.dwPluginId2)) - { - nPluginSize = sizeof(SNDMIXPLUGININFO)+4; // plugininfo+4 (datalen) - if ((p->pMixPlugin) && (bUpdate)) - { - p->pMixPlugin->SaveAllParameters(); - } - if (p->pPluginData) - { - nPluginSize += p->nPluginDataSize; - } - if (f) - { - s[0] = 'F'; - s[1] = 'X'; - s[2] = '0' + (i/10); - s[3] = '0' + (i%10); - fwrite(s, 1, 4, f); - writeSwapDWORD = bswapLE32(nPluginSize); - fwrite(&writeSwapDWORD, 1, 4, f); - - // Copy Information To Be Written for ByteSwapping - memcpy(&writePluginInfo, &p->Info, sizeof(SNDMIXPLUGININFO)); - writePluginInfo.dwPluginId1 = bswapLE32(p->Info.dwPluginId1); - writePluginInfo.dwPluginId2 = bswapLE32(p->Info.dwPluginId2); - writePluginInfo.dwInputRouting = bswapLE32(p->Info.dwInputRouting); - writePluginInfo.dwOutputRouting = bswapLE32(p->Info.dwOutputRouting); - for (UINT j=0; j<4; j++) - { - writePluginInfo.dwReserved[j] = bswapLE32(p->Info.dwReserved[j]); - } - - fwrite(&writePluginInfo, 1, sizeof(SNDMIXPLUGININFO), f); - writeSwapDWORD = bswapLE32(m_MixPlugins[i].nPluginDataSize); - fwrite(&writeSwapDWORD, 1, 4, f); - if (m_MixPlugins[i].pPluginData) - { - fwrite(m_MixPlugins[i].pPluginData, 1, m_MixPlugins[i].nPluginDataSize, f); - } - } - nTotalSize += nPluginSize + 8; - } - } - for (UINT j=0; j<m_nChannels; j++) - { - if (j < 64) - { - if ((chinfo[j] = ChnSettings[j].nMixPlugin) != 0) - { - nChInfo = j+1; - chinfo[j] = bswapLE32(chinfo[j]); // inplace BS - } - } - } - if (nChInfo) - { - if (f) - { - nPluginSize = bswapLE32(0x58464843); - fwrite(&nPluginSize, 1, 4, f); - nPluginSize = nChInfo*4; - writeSwapDWORD = bswapLE32(nPluginSize); - fwrite(&writeSwapDWORD, 1, 4, f); - fwrite(chinfo, 1, nPluginSize, f); - } - nTotalSize += nChInfo*4 + 8; - } - return nTotalSize; -} - - -UINT CSoundFile::LoadMixPlugins(const void *pData, UINT nLen) -//----------------------------------------------------------- -{ - const BYTE *p = (const BYTE *)pData; - UINT nPos = 0; - - while (nPos+8 < nLen) - { - DWORD nPluginSize; - UINT nPlugin; - - nPluginSize = bswapLE32(*(DWORD *)(p+nPos+4)); - if (nPluginSize > nLen-nPos-8) break;; - if ((bswapLE32(*(DWORD *)(p+nPos))) == 0x58464843) - { - for (UINT ch=0; ch<64; ch++) if (ch*4 < nPluginSize) - { - ChnSettings[ch].nMixPlugin = bswapLE32(*(DWORD *)(p+nPos+8+ch*4)); - } - } else - { - if ((p[nPos] != 'F') || (p[nPos+1] != 'X') - || (p[nPos+2] < '0') || (p[nPos+3] < '0')) - { - break; - } - nPlugin = (p[nPos+2]-'0')*10 + (p[nPos+3]-'0'); - if ((nPlugin < MAX_MIXPLUGINS) && (nPluginSize >= sizeof(SNDMIXPLUGININFO)+4)) - { - DWORD dwExtra = bswapLE32(*(DWORD *)(p+nPos+8+sizeof(SNDMIXPLUGININFO))); - m_MixPlugins[nPlugin].Info = *(const SNDMIXPLUGININFO *)(p+nPos+8); - m_MixPlugins[nPlugin].Info.dwPluginId1 = bswapLE32(m_MixPlugins[nPlugin].Info.dwPluginId1); - m_MixPlugins[nPlugin].Info.dwPluginId2 = bswapLE32(m_MixPlugins[nPlugin].Info.dwPluginId2); - m_MixPlugins[nPlugin].Info.dwInputRouting = bswapLE32(m_MixPlugins[nPlugin].Info.dwInputRouting); - m_MixPlugins[nPlugin].Info.dwOutputRouting = bswapLE32(m_MixPlugins[nPlugin].Info.dwOutputRouting); - for (UINT j=0; j<4; j++) - { - m_MixPlugins[nPlugin].Info.dwReserved[j] = bswapLE32(m_MixPlugins[nPlugin].Info.dwReserved[j]); - } - if ((dwExtra) && (dwExtra <= nPluginSize-sizeof(SNDMIXPLUGININFO)-4)) - { - m_MixPlugins[nPlugin].nPluginDataSize = 0; - m_MixPlugins[nPlugin].pPluginData = new signed char [dwExtra]; - if (m_MixPlugins[nPlugin].pPluginData) - { - m_MixPlugins[nPlugin].nPluginDataSize = dwExtra; - memcpy(m_MixPlugins[nPlugin].pPluginData, p+nPos+8+sizeof(SNDMIXPLUGININFO)+4, dwExtra); - } - } - } - } - nPos += nPluginSize + 8; - } - return nPos; -} - diff --git a/lib/libmodplug/src/load_j2b.cpp b/lib/libmodplug/src/load_j2b.cpp deleted file mode 100644 index 2d86ce823f..0000000000 --- a/lib/libmodplug/src/load_j2b.cpp +++ /dev/null @@ -1,15 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque <olivierl@jps.net> -*/ - - -/////////////////////////////////////////////////// -// -// J2B module loader -// -/////////////////////////////////////////////////// -#include "stdafx.h" -#include "sndfile.h" - diff --git a/lib/libmodplug/src/load_mdl.cpp b/lib/libmodplug/src/load_mdl.cpp deleted file mode 100644 index bb0b4e6653..0000000000 --- a/lib/libmodplug/src/load_mdl.cpp +++ /dev/null @@ -1,503 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque <olivierl@jps.net> -*/ - -////////////////////////////////////////////// -// DigiTracker (MDL) module loader // -////////////////////////////////////////////// -#include "stdafx.h" -#include "sndfile.h" - -//#pragma warning(disable:4244) - -typedef struct MDLSONGHEADER -{ - DWORD id; // "DMDL" = 0x4C444D44 - BYTE version; -} MDLSONGHEADER; - - -typedef struct MDLINFOBLOCK -{ - CHAR songname[32]; - CHAR composer[20]; - WORD norders; - WORD repeatpos; - BYTE globalvol; - BYTE speed; - BYTE tempo; - BYTE channelinfo[32]; - BYTE seq[256]; -} MDLINFOBLOCK; - - -typedef struct MDLPATTERNDATA -{ - BYTE channels; - BYTE lastrow; // nrows = lastrow+1 - CHAR name[16]; - WORD data[1]; -} MDLPATTERNDATA; - - -void ConvertMDLCommand(MODCOMMAND *m, UINT eff, UINT data) -//-------------------------------------------------------- -{ - UINT command = 0, param = data; - switch(eff) - { - case 0x01: command = CMD_PORTAMENTOUP; break; - case 0x02: command = CMD_PORTAMENTODOWN; break; - case 0x03: command = CMD_TONEPORTAMENTO; break; - case 0x04: command = CMD_VIBRATO; break; - case 0x05: command = CMD_ARPEGGIO; break; - case 0x07: command = (param < 0x20) ? CMD_SPEED : CMD_TEMPO; break; - case 0x08: command = CMD_PANNING8; param <<= 1; break; - case 0x0B: command = CMD_POSITIONJUMP; break; - case 0x0C: command = CMD_GLOBALVOLUME; break; - case 0x0D: command = CMD_PATTERNBREAK; param = (data & 0x0F) + (data>>4)*10; break; - case 0x0E: - command = CMD_S3MCMDEX; - switch(data & 0xF0) - { - case 0x00: command = 0; break; // What is E0x in MDL (there is a bunch) ? - case 0x10: if (param & 0x0F) { param |= 0xF0; command = CMD_PANNINGSLIDE; } else command = 0; break; - case 0x20: if (param & 0x0F) { param = (param << 4) | 0x0F; command = CMD_PANNINGSLIDE; } else command = 0; break; - case 0x30: param = (data & 0x0F) | 0x10; break; // glissando - case 0x40: param = (data & 0x0F) | 0x30; break; // vibrato waveform - case 0x60: param = (data & 0x0F) | 0xB0; break; - case 0x70: param = (data & 0x0F) | 0x40; break; // tremolo waveform - case 0x90: command = CMD_RETRIG; param &= 0x0F; break; - case 0xA0: param = (data & 0x0F) << 4; command = CMD_GLOBALVOLSLIDE; break; - case 0xB0: param = data & 0x0F; command = CMD_GLOBALVOLSLIDE; break; - case 0xF0: param = ((data >> 8) & 0x0F) | 0xA0; break; - } - break; - case 0x0F: command = CMD_SPEED; break; - case 0x10: if ((param & 0xF0) != 0xE0) { command = CMD_VOLUMESLIDE; if ((param & 0xF0) == 0xF0) param = ((param << 4) | 0x0F); else param >>= 2; } break; - case 0x20: if ((param & 0xF0) != 0xE0) { command = CMD_VOLUMESLIDE; if ((param & 0xF0) != 0xF0) param >>= 2; } break; - case 0x30: command = CMD_RETRIG; break; - case 0x40: command = CMD_TREMOLO; break; - case 0x50: command = CMD_TREMOR; break; - case 0xEF: if (param > 0xFF) param = 0xFF; command = CMD_OFFSET; break; - } - if (command) - { - m->command = command; - m->param = param; - } -} - - -void UnpackMDLTrack(MODCOMMAND *pat, UINT nChannels, UINT nRows, UINT nTrack, const BYTE *lpTracks) -//------------------------------------------------------------------------------------------------- -{ - MODCOMMAND cmd, *m = pat; - UINT len = *((WORD *)lpTracks); - UINT pos = 0, row = 0, i; - lpTracks += 2; - for (UINT ntrk=1; ntrk<nTrack; ntrk++) - { - lpTracks += len; - len = *((WORD *)lpTracks); - lpTracks += 2; - } - cmd.note = cmd.instr = 0; - cmd.volcmd = cmd.vol = 0; - cmd.command = cmd.param = 0; - while ((row < nRows) && (pos < len)) - { - UINT xx; - BYTE b = lpTracks[pos++]; - xx = b >> 2; - switch(b & 0x03) - { - case 0x01: - for (i=0; i<=xx; i++) - { - if (row) *m = *(m-nChannels); - m += nChannels; - row++; - if (row >= nRows) break; - } - break; - - case 0x02: - if (xx < row) *m = pat[nChannels*xx]; - m += nChannels; - row++; - break; - - case 0x03: - { - cmd.note = (xx & 0x01) ? lpTracks[pos++] : 0; - cmd.instr = (xx & 0x02) ? lpTracks[pos++] : 0; - cmd.volcmd = cmd.vol = 0; - cmd.command = cmd.param = 0; - if ((cmd.note < NOTE_MAX-12) && (cmd.note)) cmd.note += 12; - UINT volume = (xx & 0x04) ? lpTracks[pos++] : 0; - UINT commands = (xx & 0x08) ? lpTracks[pos++] : 0; - UINT command1 = commands & 0x0F; - UINT command2 = commands & 0xF0; - UINT param1 = (xx & 0x10) ? lpTracks[pos++] : 0; - UINT param2 = (xx & 0x20) ? lpTracks[pos++] : 0; - if ((command1 == 0x0E) && ((param1 & 0xF0) == 0xF0) && (!command2)) - { - param1 = ((param1 & 0x0F) << 8) | param2; - command1 = 0xEF; - command2 = param2 = 0; - } - if (volume) - { - cmd.volcmd = VOLCMD_VOLUME; - cmd.vol = (volume+1) >> 2; - } - ConvertMDLCommand(&cmd, command1, param1); - if ((cmd.command != CMD_SPEED) - && (cmd.command != CMD_TEMPO) - && (cmd.command != CMD_PATTERNBREAK)) - ConvertMDLCommand(&cmd, command2, param2); - *m = cmd; - m += nChannels; - row++; - } - break; - - // Empty Slots - default: - row += xx+1; - m += (xx+1)*nChannels; - if (row >= nRows) break; - } - } -} - - - -BOOL CSoundFile::ReadMDL(const BYTE *lpStream, DWORD dwMemLength) -//--------------------------------------------------------------- -{ - DWORD dwMemPos, dwPos, blocklen, dwTrackPos; - const MDLSONGHEADER *pmsh = (const MDLSONGHEADER *)lpStream; - MDLINFOBLOCK *pmib; - MDLPATTERNDATA *pmpd; - UINT i,j, norders = 0, npatterns = 0, ntracks = 0; - UINT ninstruments = 0, nsamples = 0; - WORD block; - WORD patterntracks[MAX_PATTERNS*32]; - BYTE smpinfo[MAX_SAMPLES]; - BYTE insvolenv[MAX_INSTRUMENTS]; - BYTE inspanenv[MAX_INSTRUMENTS]; - LPCBYTE pvolenv, ppanenv, ppitchenv; - UINT nvolenv, npanenv, npitchenv; - - if ((!lpStream) || (dwMemLength < 1024)) return FALSE; - if ((pmsh->id != 0x4C444D44) || ((pmsh->version & 0xF0) > 0x10)) return FALSE; - memset(patterntracks, 0, sizeof(patterntracks)); - memset(smpinfo, 0, sizeof(smpinfo)); - memset(insvolenv, 0, sizeof(insvolenv)); - memset(inspanenv, 0, sizeof(inspanenv)); - dwMemPos = 5; - dwTrackPos = 0; - pvolenv = ppanenv = ppitchenv = NULL; - nvolenv = npanenv = npitchenv = 0; - m_nSamples = m_nInstruments = 0; - while (dwMemPos+6 < dwMemLength) - { - block = *((WORD *)(lpStream+dwMemPos)); - blocklen = *((DWORD *)(lpStream+dwMemPos+2)); - dwMemPos += 6; - if (dwMemPos + blocklen > dwMemLength) - { - if (dwMemPos == 11) return FALSE; - break; - } - switch(block) - { - // IN: infoblock - case 0x4E49: - pmib = (MDLINFOBLOCK *)(lpStream+dwMemPos); - memcpy(m_szNames[0], pmib->songname, 32); - norders = pmib->norders; - if (norders > MAX_ORDERS) norders = MAX_ORDERS; - m_nRestartPos = pmib->repeatpos; - m_nDefaultGlobalVolume = pmib->globalvol; - m_nDefaultTempo = pmib->tempo; - m_nDefaultSpeed = pmib->speed; - m_nChannels = 4; - for (i=0; i<32; i++) - { - ChnSettings[i].nVolume = 64; - ChnSettings[i].nPan = (pmib->channelinfo[i] & 0x7F) << 1; - if (pmib->channelinfo[i] & 0x80) - ChnSettings[i].dwFlags |= CHN_MUTE; - else - m_nChannels = i+1; - } - for (j=0; j<norders; j++) Order[j] = pmib->seq[j]; - break; - // ME: song message - case 0x454D: - if (blocklen) - { - if (m_lpszSongComments) delete [] m_lpszSongComments; - m_lpszSongComments = new char[blocklen]; - if (m_lpszSongComments) - { - memcpy(m_lpszSongComments, lpStream+dwMemPos, blocklen); - m_lpszSongComments[blocklen-1] = 0; - } - } - break; - // PA: Pattern Data - case 0x4150: - npatterns = lpStream[dwMemPos]; - if (npatterns > MAX_PATTERNS) npatterns = MAX_PATTERNS; - dwPos = dwMemPos + 1; - for (i=0; i<npatterns; i++) - { - if (dwPos+18 >= dwMemLength) break; - pmpd = (MDLPATTERNDATA *)(lpStream + dwPos); - if (pmpd->channels > 32) break; - PatternSize[i] = pmpd->lastrow+1; - if (m_nChannels < pmpd->channels) m_nChannels = pmpd->channels; - dwPos += 18 + 2*pmpd->channels; - for (j=0; j<pmpd->channels; j++) - { - patterntracks[i*32+j] = pmpd->data[j]; - } - } - break; - // TR: Track Data - case 0x5254: - if (dwTrackPos) break; - ntracks = *((WORD *)(lpStream+dwMemPos)); - dwTrackPos = dwMemPos+2; - break; - // II: Instruments - case 0x4949: - ninstruments = lpStream[dwMemPos]; - dwPos = dwMemPos+1; - for (i=0; i<ninstruments; i++) - { - UINT nins = lpStream[dwPos]; - if ((nins >= MAX_INSTRUMENTS) || (!nins)) break; - if (m_nInstruments < nins) m_nInstruments = nins; - if (!Headers[nins]) - { - UINT note = 12; - if ((Headers[nins] = new INSTRUMENTHEADER) == NULL) break; - INSTRUMENTHEADER *penv = Headers[nins]; - memset(penv, 0, sizeof(INSTRUMENTHEADER)); - memcpy(penv->name, lpStream+dwPos+2, 32); - penv->nGlobalVol = 64; - penv->nPPC = 5*12; - for (j=0; j<lpStream[dwPos+1]; j++) - { - const BYTE *ps = lpStream+dwPos+34+14*j; - while ((note < (UINT)(ps[1]+12)) && (note < NOTE_MAX)) - { - penv->NoteMap[note] = note+1; - if (ps[0] < MAX_SAMPLES) - { - int ismp = ps[0]; - penv->Keyboard[note] = ps[0]; - Ins[ismp].nVolume = ps[2]; - Ins[ismp].nPan = ps[4] << 1; - Ins[ismp].nVibType = ps[11]; - Ins[ismp].nVibSweep = ps[10]; - Ins[ismp].nVibDepth = ps[9]; - Ins[ismp].nVibRate = ps[8]; - } - penv->nFadeOut = (ps[7] << 8) | ps[6]; - if (penv->nFadeOut == 0xFFFF) penv->nFadeOut = 0; - note++; - } - // Use volume envelope ? - if (ps[3] & 0x80) - { - penv->dwFlags |= ENV_VOLUME; - insvolenv[nins] = (ps[3] & 0x3F) + 1; - } - // Use panning envelope ? - if (ps[5] & 0x80) - { - penv->dwFlags |= ENV_PANNING; - inspanenv[nins] = (ps[5] & 0x3F) + 1; - } - } - } - dwPos += 34 + 14*lpStream[dwPos+1]; - } - for (j=1; j<=m_nInstruments; j++) if (!Headers[j]) - { - Headers[j] = new INSTRUMENTHEADER; - if (Headers[j]) memset(Headers[j], 0, sizeof(INSTRUMENTHEADER)); - } - break; - // VE: Volume Envelope - case 0x4556: - if ((nvolenv = lpStream[dwMemPos]) == 0) break; - if (dwMemPos + nvolenv*32 + 1 <= dwMemLength) pvolenv = lpStream + dwMemPos + 1; - break; - // PE: Panning Envelope - case 0x4550: - if ((npanenv = lpStream[dwMemPos]) == 0) break; - if (dwMemPos + npanenv*32 + 1 <= dwMemLength) ppanenv = lpStream + dwMemPos + 1; - break; - // FE: Pitch Envelope - case 0x4546: - if ((npitchenv = lpStream[dwMemPos]) == 0) break; - if (dwMemPos + npitchenv*32 + 1 <= dwMemLength) ppitchenv = lpStream + dwMemPos + 1; - break; - // IS: Sample Infoblock - case 0x5349: - nsamples = lpStream[dwMemPos]; - dwPos = dwMemPos+1; - for (i=0; i<nsamples; i++, dwPos += 59) - { - UINT nins = lpStream[dwPos]; - if ((nins >= MAX_SAMPLES) || (!nins)) continue; - if (m_nSamples < nins) m_nSamples = nins; - MODINSTRUMENT *pins = &Ins[nins]; - memcpy(m_szNames[nins], lpStream+dwPos+1, 32); - memcpy(pins->name, lpStream+dwPos+33, 8); - pins->nC4Speed = *((DWORD *)(lpStream+dwPos+41)); - pins->nLength = *((DWORD *)(lpStream+dwPos+45)); - pins->nLoopStart = *((DWORD *)(lpStream+dwPos+49)); - pins->nLoopEnd = pins->nLoopStart + *((DWORD *)(lpStream+dwPos+53)); - if (pins->nLoopEnd > pins->nLoopStart) pins->uFlags |= CHN_LOOP; - pins->nGlobalVol = 64; - if (lpStream[dwPos+58] & 0x01) - { - pins->uFlags |= CHN_16BIT; - pins->nLength >>= 1; - pins->nLoopStart >>= 1; - pins->nLoopEnd >>= 1; - } - if (lpStream[dwPos+58] & 0x02) pins->uFlags |= CHN_PINGPONGLOOP; - smpinfo[nins] = (lpStream[dwPos+58] >> 2) & 3; - } - break; - // SA: Sample Data - case 0x4153: - dwPos = dwMemPos; - for (i=1; i<=m_nSamples; i++) if ((Ins[i].nLength) && (!Ins[i].pSample) && (smpinfo[i] != 3) && (dwPos < dwMemLength)) - { - MODINSTRUMENT *pins = &Ins[i]; - UINT flags = (pins->uFlags & CHN_16BIT) ? RS_PCM16S : RS_PCM8S; - if (!smpinfo[i]) - { - dwPos += ReadSample(pins, flags, (LPSTR)(lpStream+dwPos), dwMemLength - dwPos); - } else - { - DWORD dwLen = *((DWORD *)(lpStream+dwPos)); - dwPos += 4; - if ((dwPos+dwLen <= dwMemLength) && (dwLen > 4)) - { - flags = (pins->uFlags & CHN_16BIT) ? RS_MDL16 : RS_MDL8; - ReadSample(pins, flags, (LPSTR)(lpStream+dwPos), dwLen); - } - dwPos += dwLen; - } - } - break; - } - dwMemPos += blocklen; - } - // Unpack Patterns - if ((dwTrackPos) && (npatterns) && (m_nChannels) && (ntracks)) - { - for (UINT ipat=0; ipat<npatterns; ipat++) - { - if ((Patterns[ipat] = AllocatePattern(PatternSize[ipat], m_nChannels)) == NULL) break; - for (UINT chn=0; chn<m_nChannels; chn++) if ((patterntracks[ipat*32+chn]) && (patterntracks[ipat*32+chn] <= ntracks)) - { - MODCOMMAND *m = Patterns[ipat] + chn; - UnpackMDLTrack(m, m_nChannels, PatternSize[ipat], patterntracks[ipat*32+chn], lpStream+dwTrackPos); - } - } - } - // Set up envelopes - for (UINT iIns=1; iIns<=m_nInstruments; iIns++) if (Headers[iIns]) - { - INSTRUMENTHEADER *penv = Headers[iIns]; - // Setup volume envelope - if ((nvolenv) && (pvolenv) && (insvolenv[iIns])) - { - LPCBYTE pve = pvolenv; - for (UINT nve=0; nve<nvolenv; nve++, pve+=33) if (pve[0]+1 == insvolenv[iIns]) - { - WORD vtick = 1; - penv->nVolEnv = 15; - for (UINT iv=0; iv<15; iv++) - { - if (iv) vtick += pve[iv*2+1]; - penv->VolPoints[iv] = vtick; - penv->VolEnv[iv] = pve[iv*2+2]; - if (!pve[iv*2+1]) - { - penv->nVolEnv = iv+1; - break; - } - } - penv->nVolSustainBegin = penv->nVolSustainEnd = pve[31] & 0x0F; - if (pve[31] & 0x10) penv->dwFlags |= ENV_VOLSUSTAIN; - if (pve[31] & 0x20) penv->dwFlags |= ENV_VOLLOOP; - penv->nVolLoopStart = pve[32] & 0x0F; - penv->nVolLoopEnd = pve[32] >> 4; - } - } - // Setup panning envelope - if ((npanenv) && (ppanenv) && (inspanenv[iIns])) - { - LPCBYTE ppe = ppanenv; - for (UINT npe=0; npe<npanenv; npe++, ppe+=33) if (ppe[0]+1 == inspanenv[iIns]) - { - WORD vtick = 1; - penv->nPanEnv = 15; - for (UINT iv=0; iv<15; iv++) - { - if (iv) vtick += ppe[iv*2+1]; - penv->PanPoints[iv] = vtick; - penv->PanEnv[iv] = ppe[iv*2+2]; - if (!ppe[iv*2+1]) - { - penv->nPanEnv = iv+1; - break; - } - } - if (ppe[31] & 0x10) penv->dwFlags |= ENV_PANSUSTAIN; - if (ppe[31] & 0x20) penv->dwFlags |= ENV_PANLOOP; - penv->nPanLoopStart = ppe[32] & 0x0F; - penv->nPanLoopEnd = ppe[32] >> 4; - } - } - } - m_dwSongFlags |= SONG_LINEARSLIDES; - m_nType = MOD_TYPE_MDL; - return TRUE; -} - - -///////////////////////////////////////////////////////////////////////// -// MDL Sample Unpacking - -// MDL Huffman ReadBits compression -WORD MDLReadBits(DWORD &bitbuf, UINT &bitnum, LPBYTE &ibuf, CHAR n) -//----------------------------------------------------------------- -{ - WORD v = (WORD)(bitbuf & ((1 << n) - 1) ); - bitbuf >>= n; - bitnum -= n; - if (bitnum <= 24) - { - bitbuf |= (((DWORD)(*ibuf++)) << bitnum); - bitnum += 8; - } - return v; -} - - diff --git a/lib/libmodplug/src/load_med.cpp b/lib/libmodplug/src/load_med.cpp deleted file mode 100644 index 0caebee30e..0000000000 --- a/lib/libmodplug/src/load_med.cpp +++ /dev/null @@ -1,924 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque <olivierl@jps.net>, - * Adam Goode <adam@evdebs.org> (endian and char fixes for PPC) -*/ - -#include "stdafx.h" -#include "sndfile.h" - -//#define MED_LOG - -#ifdef MED_LOG -extern void Log(LPCSTR s, ...); -#endif - -////////////////////////////////////////////////////////// -// OctaMed MED file support (import only) - -// flags -#define MMD_FLAG_FILTERON 0x1 -#define MMD_FLAG_JUMPINGON 0x2 -#define MMD_FLAG_JUMP8TH 0x4 -#define MMD_FLAG_INSTRSATT 0x8 // instruments are attached (this is a module) -#define MMD_FLAG_VOLHEX 0x10 -#define MMD_FLAG_STSLIDE 0x20 // SoundTracker mode for slides -#define MMD_FLAG_8CHANNEL 0x40 // OctaMED 8 channel song -#define MMD_FLAG_SLOWHQ 0x80 // HQ slows playing speed (V2-V4 compatibility) -// flags2 -#define MMD_FLAG2_BMASK 0x1F -#define MMD_FLAG2_BPM 0x20 -#define MMD_FLAG2_MIX 0x80 // uses Mixing (V7+) -// flags3: -#define MMD_FLAG3_STEREO 0x1 // mixing in Stereo mode -#define MMD_FLAG3_FREEPAN 0x2 // free panning -#define MMD_FLAG3_GM 0x4 // module designed for GM/XG compatibility - - -// generic MMD tags -#define MMDTAG_END 0 -#define MMDTAG_PTR 0x80000000 // data needs relocation -#define MMDTAG_MUSTKNOW 0x40000000 // loader must fail if this isn't recognized -#define MMDTAG_MUSTWARN 0x20000000 // loader must warn if this isn't recognized - -// ExpData tags -// # of effect groups, including the global group (will -// override settings in MMDSong struct), default = 1 -#define MMDTAG_EXP_NUMFXGROUPS 1 -#define MMDTAG_TRK_NAME (MMDTAG_PTR|1) // trackinfo tags -#define MMDTAG_TRK_NAMELEN 2 // namelen includes zero term. -#define MMDTAG_TRK_FXGROUP 3 -// effectinfo tags -#define MMDTAG_FX_ECHOTYPE 1 -#define MMDTAG_FX_ECHOLEN 2 -#define MMDTAG_FX_ECHODEPTH 3 -#define MMDTAG_FX_STEREOSEP 4 -#define MMDTAG_FX_GROUPNAME (MMDTAG_PTR|5) // the Global Effects group shouldn't have name saved! -#define MMDTAG_FX_GRPNAMELEN 6 // namelen includes zero term. - -#pragma pack(1) - -typedef struct tagMEDMODULEHEADER -{ - DWORD id; // MMD1-MMD3 - DWORD modlen; // Size of file - DWORD song; // Position in file for this song - WORD psecnum; - WORD pseq; - DWORD blockarr; // Position in file for blocks - DWORD mmdflags; - DWORD smplarr; // Position in file for samples - DWORD reserved; - DWORD expdata; // Absolute offset in file for ExpData (0 if not present) - DWORD reserved2; - WORD pstate; - WORD pblock; - WORD pline; - WORD pseqnum; - WORD actplayline; - BYTE counter; - BYTE extra_songs; // # of songs - 1 -} MEDMODULEHEADER; - - -typedef struct tagMMD0SAMPLE -{ - WORD rep, replen; - BYTE midich; - BYTE midipreset; - BYTE svol; - signed char strans; -} MMD0SAMPLE; - - -// Sample header is immediately followed by sample data... -typedef struct tagMMDSAMPLEHEADER -{ - DWORD length; // length of *one* *unpacked* channel in *bytes* - WORD type; - // if non-negative - // bits 0-3 reserved for multi-octave instruments, not supported on the PC - // 0x10: 16 bit (otherwise 8 bit) - // 0x20: Stereo (otherwise mono) - // 0x40: Uses DeltaCode - // 0x80: Packed data - // -1: Synth - // -2: Hybrid - // if type indicates packed data, these fields follow, otherwise we go right to the data - WORD packtype; // Only 1 = ADPCM is supported - WORD subtype; // Packing subtype - // ADPCM subtype - // 1: g723_40 - // 2: g721 - // 3: g723_24 - BYTE commonflags; // flags common to all packtypes (none defined so far) - BYTE packerflags; // flags for the specific packtype - ULONG leftchlen; // packed length of left channel in bytes - ULONG rightchlen; // packed length of right channel in bytes (ONLY PRESENT IN STEREO SAMPLES) - BYTE SampleData[1]; // Sample Data -} MMDSAMPLEHEADER; - - -// MMD0/MMD1 song header -typedef struct tagMMD0SONGHEADER -{ - MMD0SAMPLE sample[63]; - WORD numblocks; // # of blocks - WORD songlen; // # of entries used in playseq - BYTE playseq[256]; // Play sequence - WORD deftempo; // BPM tempo - signed char playtransp; // Play transpose - BYTE flags; // 0x10: Hex Volumes | 0x20: ST/NT/PT Slides | 0x40: 8 Channels song - BYTE flags2; // [b4-b0]+1: Tempo LPB, 0x20: tempo mode, 0x80: mix_conv=on - BYTE tempo2; // tempo TPL - BYTE trkvol[16]; // track volumes - BYTE mastervol; // master volume - BYTE numsamples; // # of samples (max=63) -} MMD0SONGHEADER; - - -// MMD2/MMD3 song header -typedef struct tagMMD2SONGHEADER -{ - MMD0SAMPLE sample[63]; - WORD numblocks; // # of blocks - WORD numsections; // # of sections - DWORD playseqtable; // filepos of play sequence - DWORD sectiontable; // filepos of sections table (WORD array) - DWORD trackvols; // filepos of tracks volume (BYTE array) - WORD numtracks; // # of tracks (max 64) - WORD numpseqs; // # of play sequences - DWORD trackpans; // filepos of tracks pan values (BYTE array) - LONG flags3; // 0x1:stereo_mix, 0x2:free_panning, 0x4:GM/XG compatibility - WORD voladj; // vol_adjust (set to 100 if 0) - WORD channels; // # of channels (4 if =0) - BYTE mix_echotype; // 1:normal,2:xecho - BYTE mix_echodepth; // 1..6 - WORD mix_echolen; // > 0 - signed char mix_stereosep; // -4..4 - BYTE pad0[223]; - WORD deftempo; // BPM tempo - signed char playtransp; // play transpose - BYTE flags; // 0x1:filteron, 0x2:jumpingon, 0x4:jump8th, 0x8:instr_attached, 0x10:hex_vol, 0x20:PT_slides, 0x40:8ch_conv,0x80:hq slows playing speed - BYTE flags2; // 0x80:mix_conv=on, [b4-b0]+1:tempo LPB, 0x20:tempo_mode - BYTE tempo2; // tempo TPL - BYTE pad1[16]; - BYTE mastervol; // master volume - BYTE numsamples; // # of samples (max 63) -} MMD2SONGHEADER; - -// For MMD0 the note information is held in 3 bytes, byte0, byte1, byte2. For reference we -// number the bits in each byte 0..7, where 0 is the low bit. -// The note is held as bits 5..0 of byte0 -// The instrument is encoded in 6 bits, bits 7 and 6 of byte0 and bits 7,6,5,4 of byte1 -// The command number is bits 3,2,1,0 of byte1, command data is in byte2: -// For command 0, byte2 represents the second data byte, otherwise byte2 -// represents the first data byte. -typedef struct tagMMD0BLOCK -{ - BYTE numtracks; - BYTE lines; // File value is 1 less than actual, so 0 -> 1 line -} MMD0BLOCK; // BYTE data[lines+1][tracks][3]; - - -// For MMD1,MMD2,MMD3 the note information is carried in 4 bytes, byte0, byte1, -// byte2 and byte3 -// The note is held as byte0 (values above 0x84 are ignored) -// The instrument is held as byte1 -// The command number is held as byte2, command data is in byte3 -// For commands 0 and 0x19 byte3 represents the second data byte, -// otherwise byte2 represents the first data byte. -typedef struct tagMMD1BLOCK -{ - WORD numtracks; // Number of tracks, may be > 64, but then that data is skipped. - WORD lines; // Stored value is 1 less than actual, so 0 -> 1 line - DWORD info; // Offset of BlockInfo (if 0, no block_info is present) -} MMD1BLOCK; - - -typedef struct tagMMD1BLOCKINFO -{ - DWORD hlmask; // Unimplemented - ignore - DWORD blockname; // file offset of block name - DWORD blocknamelen; // length of block name (including term. 0) - DWORD pagetable; // file offset of command page table - DWORD cmdexttable; // file offset of command extension table - DWORD reserved[4]; // future expansion -} MMD1BLOCKINFO; - - -// A set of play sequences is stored as an array of ULONG files offsets -// Each offset points to the play sequence itself. -typedef struct tagMMD2PLAYSEQ -{ - CHAR name[32]; - DWORD command_offs; // filepos of command table - DWORD reserved; - WORD length; - WORD seq[512]; // skip if > 0x8000 -} MMD2PLAYSEQ; - - -// A command table contains commands that effect a particular play sequence -// entry. The only commands read in are STOP or POSJUMP, all others are ignored -// POSJUMP is presumed to have extra bytes containing a WORD for the position -typedef struct tagMMDCOMMAND -{ - WORD offset; // Offset within current sequence entry - BYTE cmdnumber; // STOP (537) or POSJUMP (538) (others skipped) - BYTE extra_count; - BYTE extra_bytes[4];// [extra_count]; -} MMDCOMMAND; // Last entry has offset == 0xFFFF, cmd_number == 0 and 0 extrabytes - - -typedef struct tagMMD0EXP -{ - DWORD nextmod; // File offset of next Hdr - DWORD exp_smp; // Pointer to extra instrument data - WORD s_ext_entries; // Number of extra instrument entries - WORD s_ext_entrsz; // Size of extra instrument data - DWORD annotxt; - DWORD annolen; - DWORD iinfo; // Instrument names - WORD i_ext_entries; - WORD i_ext_entrsz; - DWORD jumpmask; - DWORD rgbtable; - BYTE channelsplit[4]; // Only used if 8ch_conv (extra channel for every nonzero entry) - DWORD n_info; - DWORD songname; // Song name - DWORD songnamelen; - DWORD dumps; - DWORD mmdinfo; - DWORD mmdrexx; - DWORD mmdcmd3x; - DWORD trackinfo_ofs; // ptr to song->numtracks ptrs to tag lists - DWORD effectinfo_ofs; // ptr to group ptrs - DWORD tag_end; -} MMD0EXP; - -#pragma pack() - - - -static void MedConvert(MODCOMMAND *p, const MMD0SONGHEADER *pmsh) -//--------------------------------------------------------------- -{ - const BYTE bpmvals[9] = { 179,164,152,141,131,123,116,110,104}; - - UINT command = p->command; - UINT param = p->param; - switch(command) - { - case 0x00: if (param) command = CMD_ARPEGGIO; else command = 0; break; - case 0x01: command = CMD_PORTAMENTOUP; break; - case 0x02: command = CMD_PORTAMENTODOWN; break; - case 0x03: command = CMD_TONEPORTAMENTO; break; - case 0x04: command = CMD_VIBRATO; break; - case 0x05: command = CMD_TONEPORTAVOL; break; - case 0x06: command = CMD_VIBRATOVOL; break; - case 0x07: command = CMD_TREMOLO; break; - case 0x0A: if (param & 0xF0) param &= 0xF0; command = CMD_VOLUMESLIDE; if (!param) command = 0; break; - case 0x0B: command = CMD_POSITIONJUMP; break; - case 0x0C: command = CMD_VOLUME; - if (pmsh->flags & MMD_FLAG_VOLHEX) - { - if (param < 0x80) - { - param = (param+1) / 2; - } else command = 0; - } else - { - if (param <= 0x99) - { - param = (param >> 4)*10+((param & 0x0F) % 10); - if (param > 64) param = 64; - } else command = 0; - } - break; - case 0x09: command = (param < 0x20) ? CMD_SPEED : CMD_TEMPO; break; - case 0x0D: if (param & 0xF0) param &= 0xF0; command = CMD_VOLUMESLIDE; if (!param) command = 0; break; - case 0x0F: // Set Tempo / Special - // F.00 = Pattern Break - if (!param) command = CMD_PATTERNBREAK; else - // F.01 - F.F0: Set tempo/speed - if (param <= 0xF0) - { - if (pmsh->flags & MMD_FLAG_8CHANNEL) - { - param = (param > 10) ? 99 : bpmvals[param-1]; - } else - // F.01 - F.0A: Set Speed - if (param <= 0x0A) - { - command = CMD_SPEED; - } else - // Old tempo - if (!(pmsh->flags2 & MMD_FLAG2_BPM)) - { - param = _muldiv(param, 5*715909, 2*474326); - } - // F.0B - F.F0: Set Tempo (assumes LPB=4) - if (param > 0x0A) - { - command = CMD_TEMPO; - if (param < 0x21) param = 0x21; - if (param > 240) param = 240; - } - } else - switch(param) - { - // F.F1: Retrig 2x - case 0xF1: - command = CMD_MODCMDEX; - param = 0x93; - break; - // F.F2: Note Delay 2x - case 0xF2: - command = CMD_MODCMDEX; - param = 0xD3; - break; - // F.F3: Retrig 3x - case 0xF3: - command = CMD_MODCMDEX; - param = 0x92; - break; - // F.F4: Note Delay 1/3 - case 0xF4: - command = CMD_MODCMDEX; - param = 0xD2; - break; - // F.F5: Note Delay 2/3 - case 0xF5: - command = CMD_MODCMDEX; - param = 0xD4; - break; - // F.F8: Filter Off - case 0xF8: - command = CMD_MODCMDEX; - param = 0x00; - break; - // F.F9: Filter On - case 0xF9: - command = CMD_MODCMDEX; - param = 0x01; - break; - // F.FD: Very fast tone-portamento - case 0xFD: - command = CMD_TONEPORTAMENTO; - param = 0xFF; - break; - // F.FE: End Song - case 0xFE: - command = CMD_SPEED; - param = 0; - break; - // F.FF: Note Cut - case 0xFF: - command = CMD_MODCMDEX; - param = 0xC0; - break; - default: -#ifdef MED_LOG - Log("Unknown Fxx command: cmd=0x%02X param=0x%02X\n", command, param); -#endif - param = command = 0; - } - break; - // 11.0x: Fine Slide Up - case 0x11: - command = CMD_MODCMDEX; - if (param > 0x0F) param = 0x0F; - param |= 0x10; - break; - // 12.0x: Fine Slide Down - case 0x12: - command = CMD_MODCMDEX; - if (param > 0x0F) param = 0x0F; - param |= 0x20; - break; - // 14.xx: Vibrato - case 0x14: - command = CMD_VIBRATO; - break; - // 15.xx: FineTune - case 0x15: - command = CMD_MODCMDEX; - param &= 0x0F; - param |= 0x50; - break; - // 16.xx: Pattern Loop - case 0x16: - command = CMD_MODCMDEX; - if (param > 0x0F) param = 0x0F; - param |= 0x60; - break; - // 18.xx: Note Cut - case 0x18: - command = CMD_MODCMDEX; - if (param > 0x0F) param = 0x0F; - param |= 0xC0; - break; - // 19.xx: Sample Offset - case 0x19: - command = CMD_OFFSET; - break; - // 1A.0x: Fine Volume Up - case 0x1A: - command = CMD_MODCMDEX; - if (param > 0x0F) param = 0x0F; - param |= 0xA0; - break; - // 1B.0x: Fine Volume Down - case 0x1B: - command = CMD_MODCMDEX; - if (param > 0x0F) param = 0x0F; - param |= 0xB0; - break; - // 1D.xx: Pattern Break - case 0x1D: - command = CMD_PATTERNBREAK; - break; - // 1E.0x: Pattern Delay - case 0x1E: - command = CMD_MODCMDEX; - if (param > 0x0F) param = 0x0F; - param |= 0xE0; - break; - // 1F.xy: Retrig - case 0x1F: - command = CMD_RETRIG; - param &= 0x0F; - break; - // 2E.xx: set panning - case 0x2E: - command = CMD_MODCMDEX; - param = ((param + 0x10) & 0xFF) >> 1; - if (param > 0x0F) param = 0x0F; - param |= 0x80; - break; - default: -#ifdef MED_LOG - // 0x2E ? - Log("Unknown command: cmd=0x%02X param=0x%02X\n", command, param); -#endif - command = param = 0; - } - p->command = command; - p->param = param; -} - - -BOOL CSoundFile::ReadMed(const BYTE *lpStream, DWORD dwMemLength) -//--------------------------------------------------------------- -{ - const MEDMODULEHEADER *pmmh; - const MMD0SONGHEADER *pmsh; - const MMD2SONGHEADER *pmsh2; - const MMD0EXP *pmex; - DWORD dwBlockArr, dwSmplArr, dwExpData, wNumBlocks; - LPDWORD pdwTable; - CHAR version; - UINT deftempo; - int playtransp = 0; - - if ((!lpStream) || (dwMemLength < 0x200)) return FALSE; - pmmh = (MEDMODULEHEADER *)lpStream; - if (((pmmh->id & 0x00FFFFFF) != 0x444D4D) || (!pmmh->song)) return FALSE; - // Check for 'MMDx' - DWORD dwSong = bswapBE32(pmmh->song); - if ((dwSong >= dwMemLength) || (dwSong + sizeof(MMD0SONGHEADER) >= dwMemLength)) return FALSE; - version = (signed char)((pmmh->id >> 24) & 0xFF); - if ((version < '0') || (version > '3')) return FALSE; -#ifdef MED_LOG - Log("\nLoading MMD%c module (flags=0x%02X)...\n", version, bswapBE32(pmmh->mmdflags)); - Log(" modlen = %d\n", bswapBE32(pmmh->modlen)); - Log(" song = 0x%08X\n", bswapBE32(pmmh->song)); - Log(" psecnum = %d\n", bswapBE16(pmmh->psecnum)); - Log(" pseq = %d\n", bswapBE16(pmmh->pseq)); - Log(" blockarr = 0x%08X\n", bswapBE32(pmmh->blockarr)); - Log(" mmdflags = 0x%08X\n", bswapBE32(pmmh->mmdflags)); - Log(" smplarr = 0x%08X\n", bswapBE32(pmmh->smplarr)); - Log(" reserved = 0x%08X\n", bswapBE32(pmmh->reserved)); - Log(" expdata = 0x%08X\n", bswapBE32(pmmh->expdata)); - Log(" reserved2= 0x%08X\n", bswapBE32(pmmh->reserved2)); - Log(" pstate = %d\n", bswapBE16(pmmh->pstate)); - Log(" pblock = %d\n", bswapBE16(pmmh->pblock)); - Log(" pline = %d\n", bswapBE16(pmmh->pline)); - Log(" pseqnum = %d\n", bswapBE16(pmmh->pseqnum)); - Log(" actplayline=%d\n", bswapBE16(pmmh->actplayline)); - Log(" counter = %d\n", pmmh->counter); - Log(" extra_songs = %d\n", pmmh->extra_songs); - Log("\n"); -#endif - m_nType = MOD_TYPE_MED; - m_nSongPreAmp = 0x20; - dwBlockArr = bswapBE32(pmmh->blockarr); - dwSmplArr = bswapBE32(pmmh->smplarr); - dwExpData = bswapBE32(pmmh->expdata); - if ((dwExpData) && (dwExpData+sizeof(MMD0EXP) < dwMemLength)) - pmex = (MMD0EXP *)(lpStream+dwExpData); - else - pmex = NULL; - pmsh = (MMD0SONGHEADER *)(lpStream + dwSong); - pmsh2 = (MMD2SONGHEADER *)pmsh; -#ifdef MED_LOG - if (version < '2') - { - Log("MMD0 Header:\n"); - Log(" numblocks = %d\n", bswapBE16(pmsh->numblocks)); - Log(" songlen = %d\n", bswapBE16(pmsh->songlen)); - Log(" playseq = "); - for (UINT idbg1=0; idbg1<16; idbg1++) Log("%2d, ", pmsh->playseq[idbg1]); - Log("...\n"); - Log(" deftempo = 0x%04X\n", bswapBE16(pmsh->deftempo)); - Log(" playtransp = %d\n", (signed char)pmsh->playtransp); - Log(" flags(1,2) = 0x%02X, 0x%02X\n", pmsh->flags, pmsh->flags2); - Log(" tempo2 = %d\n", pmsh->tempo2); - Log(" trkvol = "); - for (UINT idbg2=0; idbg2<16; idbg2++) Log("0x%02X, ", pmsh->trkvol[idbg2]); - Log("...\n"); - Log(" mastervol = 0x%02X\n", pmsh->mastervol); - Log(" numsamples = %d\n", pmsh->numsamples); - } else - { - Log("MMD2 Header:\n"); - Log(" numblocks = %d\n", bswapBE16(pmsh2->numblocks)); - Log(" numsections= %d\n", bswapBE16(pmsh2->numsections)); - Log(" playseqptr = 0x%04X\n", bswapBE32(pmsh2->playseqtable)); - Log(" sectionptr = 0x%04X\n", bswapBE32(pmsh2->sectiontable)); - Log(" trackvols = 0x%04X\n", bswapBE32(pmsh2->trackvols)); - Log(" numtracks = %d\n", bswapBE16(pmsh2->numtracks)); - Log(" numpseqs = %d\n", bswapBE16(pmsh2->numpseqs)); - Log(" trackpans = 0x%04X\n", bswapBE32(pmsh2->trackpans)); - Log(" flags3 = 0x%08X\n", bswapBE32(pmsh2->flags3)); - Log(" voladj = %d\n", bswapBE16(pmsh2->voladj)); - Log(" channels = %d\n", bswapBE16(pmsh2->channels)); - Log(" echotype = %d\n", pmsh2->mix_echotype); - Log(" echodepth = %d\n", pmsh2->mix_echodepth); - Log(" echolen = %d\n", bswapBE16(pmsh2->mix_echolen)); - Log(" stereosep = %d\n", (signed char)pmsh2->mix_stereosep); - Log(" deftempo = 0x%04X\n", bswapBE16(pmsh2->deftempo)); - Log(" playtransp = %d\n", (signed char)pmsh2->playtransp); - Log(" flags(1,2) = 0x%02X, 0x%02X\n", pmsh2->flags, pmsh2->flags2); - Log(" tempo2 = %d\n", pmsh2->tempo2); - Log(" mastervol = 0x%02X\n", pmsh2->mastervol); - Log(" numsamples = %d\n", pmsh->numsamples); - } - Log("\n"); -#endif - wNumBlocks = bswapBE16(pmsh->numblocks); - m_nChannels = 4; - m_nSamples = pmsh->numsamples; - if (m_nSamples > 63) m_nSamples = 63; - // Tempo - m_nDefaultTempo = 125; - deftempo = bswapBE16(pmsh->deftempo); - if (!deftempo) deftempo = 125; - if (pmsh->flags2 & MMD_FLAG2_BPM) - { - UINT tempo_tpl = (pmsh->flags2 & MMD_FLAG2_BMASK) + 1; - if (!tempo_tpl) tempo_tpl = 4; - deftempo *= tempo_tpl; - deftempo /= 4; - #ifdef MED_LOG - Log("newtempo: %3d bpm (bpm=%3d lpb=%2d)\n", deftempo, bswapBE16(pmsh->deftempo), (pmsh->flags2 & MMD_FLAG2_BMASK)+1); - #endif - } else - { - deftempo = _muldiv(deftempo, 5*715909, 2*474326); - #ifdef MED_LOG - Log("oldtempo: %3d bpm (bpm=%3d)\n", deftempo, bswapBE16(pmsh->deftempo)); - #endif - } - // Speed - m_nDefaultSpeed = pmsh->tempo2; - if (!m_nDefaultSpeed) m_nDefaultSpeed = 6; - if (deftempo < 0x21) deftempo = 0x21; - if (deftempo > 255) - { - while ((m_nDefaultSpeed > 3) && (deftempo > 260)) - { - deftempo = (deftempo * (m_nDefaultSpeed - 1)) / m_nDefaultSpeed; - m_nDefaultSpeed--; - } - if (deftempo > 255) deftempo = 255; - } - m_nDefaultTempo = deftempo; - // Reading Samples - for (UINT iSHdr=0; iSHdr<m_nSamples; iSHdr++) - { - MODINSTRUMENT *pins = &Ins[iSHdr+1]; - pins->nLoopStart = bswapBE16(pmsh->sample[iSHdr].rep) << 1; - pins->nLoopEnd = pins->nLoopStart + (bswapBE16(pmsh->sample[iSHdr].replen) << 1); - pins->nVolume = (pmsh->sample[iSHdr].svol << 2); - pins->nGlobalVol = 64; - if (pins->nVolume > 256) pins->nVolume = 256; - pins->RelativeTone = -12 * pmsh->sample[iSHdr].strans; - pins->nPan = 128; - if (pins->nLoopEnd) pins->uFlags |= CHN_LOOP; - } - // Common Flags - if (!(pmsh->flags & 0x20)) m_dwSongFlags |= SONG_FASTVOLSLIDES; - // Reading play sequence - if (version < '2') - { - UINT nbo = pmsh->songlen >> 8; - if (nbo >= MAX_ORDERS) nbo = MAX_ORDERS-1; - if (!nbo) nbo = 1; - memcpy(Order, pmsh->playseq, nbo); - playtransp = pmsh->playtransp; - } else - { - UINT nOrders, nSections; - UINT nTrks = bswapBE16(pmsh2->numtracks); - if ((nTrks >= 4) && (nTrks <= 32)) m_nChannels = nTrks; - DWORD playseqtable = bswapBE32(pmsh2->playseqtable); - UINT numplayseqs = bswapBE16(pmsh2->numpseqs); - if (!numplayseqs) numplayseqs = 1; - nOrders = 0; - nSections = bswapBE16(pmsh2->numsections); - DWORD sectiontable = bswapBE32(pmsh2->sectiontable); - if ((!nSections) || (!sectiontable) || (sectiontable >= dwMemLength-2)) nSections = 1; - nOrders = 0; - for (UINT iSection=0; iSection<nSections; iSection++) - { - UINT nplayseq = 0; - if ((sectiontable) && (sectiontable < dwMemLength-2)) - { - nplayseq = lpStream[sectiontable+1]; - sectiontable += 2; // WORDs - } else - { - nSections = 0; - } - UINT pseq = 0; - - if ((playseqtable) && (playseqtable + nplayseq*4 < dwMemLength)) - { - pseq = bswapBE32(((LPDWORD)(lpStream+playseqtable))[nplayseq]); - } - if ((pseq) && (pseq < dwMemLength - sizeof(MMD2PLAYSEQ))) - { - MMD2PLAYSEQ *pmps = (MMD2PLAYSEQ *)(lpStream + pseq); - if (!m_szNames[0][0]) memcpy(m_szNames[0], pmps->name, 31); - UINT n = bswapBE16(pmps->length); - if (pseq+n <= dwMemLength) - { - for (UINT i=0; i<n; i++) - { - UINT seqval = pmps->seq[i] >> 8; - if ((seqval < wNumBlocks) && (nOrders < MAX_ORDERS-1)) - { - Order[nOrders++] = seqval; - } - } - } - } - } - playtransp = pmsh2->playtransp; - while (nOrders < MAX_ORDERS) Order[nOrders++] = 0xFF; - } - // Reading Expansion structure - if (pmex) - { - // Channel Split - if ((m_nChannels == 4) && (pmsh->flags & 0x40)) - { - for (UINT i8ch=0; i8ch<4; i8ch++) - { - if (pmex->channelsplit[i8ch]) m_nChannels++; - } - } - // Song Comments - uint32_t annotxt = bswapBE32(pmex->annotxt); - uint32_t annolen = bswapBE32(pmex->annolen); - if ((annotxt) && (annolen) && (annotxt + annolen > annotxt) // overflow checks. - && (annotxt+annolen <= dwMemLength)) - { - m_lpszSongComments = new char[annolen+1]; - memcpy(m_lpszSongComments, lpStream+annotxt, annolen); - m_lpszSongComments[annolen] = 0; - } - // Song Name - uint32_t songname = bswapBE32(pmex->songname); - uint32_t songnamelen = bswapBE32(pmex->songnamelen); - if ((songname) && (songnamelen) && (songname+songnamelen > songname) - && (songname+songnamelen <= dwMemLength)) - { - if (songnamelen > 31) songnamelen = 31; - memcpy(m_szNames[0], lpStream+songname, songnamelen); - m_szNames[0][31] = '\0'; - } - // Sample Names - DWORD smpinfoex = bswapBE32(pmex->iinfo); - if (smpinfoex) - { - DWORD iinfoptr = bswapBE32(pmex->iinfo); - UINT ientries = bswapBE16(pmex->i_ext_entries); - UINT ientrysz = bswapBE16(pmex->i_ext_entrsz); - - if ((iinfoptr) && (ientrysz < 256) && - (ientries*ientrysz < dwMemLength) && - (iinfoptr < dwMemLength - (ientries*ientrysz))) - { - LPCSTR psznames = (LPCSTR)(lpStream + iinfoptr); - UINT maxnamelen = ientrysz; - // copy a max of 32 bytes. - if (maxnamelen > 32) maxnamelen = 32; - for (UINT i=0; i<ientries; i++) if (i < m_nSamples) - { - lstrcpyn(m_szNames[i+1], psznames + i*ientrysz, maxnamelen); - m_szNames[i+1][31] = '\0'; - } - } - } - // Track Names - DWORD trackinfo_ofs = bswapBE32(pmex->trackinfo_ofs); - if ((trackinfo_ofs) && (trackinfo_ofs + m_nChannels * 4 < dwMemLength)) - { - DWORD *ptrktags = (DWORD *)(lpStream + trackinfo_ofs); - for (UINT i=0; i<m_nChannels; i++) - { - DWORD trknameofs = 0, trknamelen = 0; - DWORD trktagofs = bswapBE32(ptrktags[i]); - if (trktagofs) - { - while (trktagofs+8 < dwMemLength) - { - DWORD ntag = bswapBE32(*(DWORD *)(lpStream + trktagofs)); - if (ntag == MMDTAG_END) break; - DWORD tagdata = bswapBE32(*(DWORD *)(lpStream + trktagofs + 4)); - switch(ntag) - { - case MMDTAG_TRK_NAMELEN: trknamelen = tagdata; break; - case MMDTAG_TRK_NAME: trknameofs = tagdata; break; - } - trktagofs += 8; - } - if (trknamelen > MAX_CHANNELNAME) trknamelen = MAX_CHANNELNAME; - if ((trknameofs) && (trknameofs + trknamelen < dwMemLength)) - { - lstrcpyn(ChnSettings[i].szName, (LPCSTR)(lpStream+trknameofs), MAX_CHANNELNAME); - ChnSettings[i].szName[MAX_CHANNELNAME-1] = '\0'; - } - } - } - } - } - // Reading samples - if (dwSmplArr > dwMemLength - 4*m_nSamples) return TRUE; - pdwTable = (LPDWORD)(lpStream + dwSmplArr); - for (UINT iSmp=0; iSmp<m_nSamples; iSmp++) if (pdwTable[iSmp]) - { - UINT dwPos = bswapBE32(pdwTable[iSmp]); - if ((dwPos >= dwMemLength) || (dwPos + sizeof(MMDSAMPLEHEADER) >= dwMemLength)) continue; - MMDSAMPLEHEADER *psdh = (MMDSAMPLEHEADER *)(lpStream + dwPos); - UINT len = bswapBE32(psdh->length); - #ifdef MED_LOG - Log("SampleData %d: stype=0x%02X len=%d\n", iSmp, bswapBE16(psdh->type), len); - #endif - if ((len > MAX_SAMPLE_LENGTH) || (dwPos + len + 6 > dwMemLength)) len = 0; - UINT flags = RS_PCM8S, stype = bswapBE16(psdh->type); - LPSTR psdata = (LPSTR)(lpStream + dwPos + 6); - if (stype & 0x80) - { - psdata += (stype & 0x20) ? 14 : 6; - } else - { - if (stype & 0x10) - { - Ins[iSmp+1].uFlags |= CHN_16BIT; - len /= 2; - flags = (stype & 0x20) ? RS_STPCM16M : RS_PCM16M; - } else - { - flags = (stype & 0x20) ? RS_STPCM8S : RS_PCM8S; - } - if (stype & 0x20) len /= 2; - } - Ins[iSmp+1].nLength = len; - ReadSample(&Ins[iSmp+1], flags, psdata, dwMemLength - dwPos - 6); - } - // Reading patterns (blocks) - if (wNumBlocks > MAX_PATTERNS) wNumBlocks = MAX_PATTERNS; - if ((!dwBlockArr) || (dwBlockArr > dwMemLength - 4*wNumBlocks)) return TRUE; - pdwTable = (LPDWORD)(lpStream + dwBlockArr); - playtransp += (version == '3') ? 24 : 48; - for (UINT iBlk=0; iBlk<wNumBlocks; iBlk++) - { - UINT dwPos = bswapBE32(pdwTable[iBlk]); - if ((!dwPos) || (dwPos >= dwMemLength) || (dwPos >= dwMemLength - 8)) continue; - UINT lines = 64, tracks = 4; - if (version == '0') - { - const MMD0BLOCK *pmb = (const MMD0BLOCK *)(lpStream + dwPos); - lines = pmb->lines + 1; - tracks = pmb->numtracks; - if (!tracks) tracks = m_nChannels; - if ((Patterns[iBlk] = AllocatePattern(lines, m_nChannels)) == NULL) continue; - PatternSize[iBlk] = lines; - MODCOMMAND *p = Patterns[iBlk]; - LPBYTE s = (LPBYTE)(lpStream + dwPos + 2); - UINT maxlen = tracks*lines*3; - if (maxlen + dwPos > dwMemLength - 2) break; - for (UINT y=0; y<lines; y++) - { - for (UINT x=0; x<tracks; x++, s+=3) if (x < m_nChannels) - { - BYTE note = s[0] & 0x3F; - BYTE instr = s[1] >> 4; - if (s[0] & 0x80) instr |= 0x10; - if (s[0] & 0x40) instr |= 0x20; - if ((note) && (note <= 132)) p->note = note + playtransp; - p->instr = instr; - p->command = s[1] & 0x0F; - p->param = s[2]; - // if (!iBlk) Log("%02X.%02X.%02X | ", s[0], s[1], s[2]); - MedConvert(p, pmsh); - p++; - } - //if (!iBlk) Log("\n"); - } - } else - { - MMD1BLOCK *pmb = (MMD1BLOCK *)(lpStream + dwPos); - #ifdef MED_LOG - Log("MMD1BLOCK: lines=%2d, tracks=%2d, offset=0x%04X\n", - bswapBE16(pmb->lines), bswapBE16(pmb->numtracks), bswapBE32(pmb->info)); - #endif - MMD1BLOCKINFO *pbi = NULL; - BYTE *pcmdext = NULL; - lines = (pmb->lines >> 8) + 1; - tracks = pmb->numtracks >> 8; - if (!tracks) tracks = m_nChannels; - if ((Patterns[iBlk] = AllocatePattern(lines, m_nChannels)) == NULL) continue; - PatternSize[iBlk] = (WORD)lines; - DWORD dwBlockInfo = bswapBE32(pmb->info); - if ((dwBlockInfo) && (dwBlockInfo < dwMemLength - sizeof(MMD1BLOCKINFO))) - { - pbi = (MMD1BLOCKINFO *)(lpStream + dwBlockInfo); - #ifdef MED_LOG - Log(" BLOCKINFO: blockname=0x%04X namelen=%d pagetable=0x%04X &cmdexttable=0x%04X\n", - bswapBE32(pbi->blockname), bswapBE32(pbi->blocknamelen), bswapBE32(pbi->pagetable), bswapBE32(pbi->cmdexttable)); - #endif - if ((pbi->blockname) && (pbi->blocknamelen)) - { - DWORD nameofs = bswapBE32(pbi->blockname); - UINT namelen = bswapBE32(pbi->blocknamelen); - if ((nameofs < dwMemLength) && (nameofs+namelen < dwMemLength)) - { - SetPatternName(iBlk, (LPCSTR)(lpStream+nameofs)); - } - } - if (pbi->cmdexttable) - { - DWORD cmdexttable = bswapBE32(pbi->cmdexttable); - if (cmdexttable < dwMemLength - 4) - { - cmdexttable = bswapBE32(*(DWORD *)(lpStream + cmdexttable)); - if ((cmdexttable) && (cmdexttable <= dwMemLength - lines*tracks)) - { - pcmdext = (BYTE *)(lpStream + cmdexttable); - } - } - } - } - MODCOMMAND *p = Patterns[iBlk]; - LPBYTE s = (LPBYTE)(lpStream + dwPos + 8); - UINT maxlen = tracks*lines*4; - if (maxlen + dwPos > dwMemLength - 8) break; - for (UINT y=0; y<lines; y++) - { - for (UINT x=0; x<tracks; x++, s+=4) if (x < m_nChannels) - { - BYTE note = s[0]; - if ((note) && (note <= 132)) - { - int rnote = note + playtransp; - if (rnote < 1) rnote = 1; - if (rnote > 120) rnote = 120; - p->note = (BYTE)rnote; - } - p->instr = s[1]; - p->command = s[2]; - p->param = s[3]; - if (pcmdext) p->vol = pcmdext[x]; - MedConvert(p, pmsh); - p++; - } - if (pcmdext) pcmdext += tracks; - } - } - } - // Setup channel pan positions - for (UINT iCh=0; iCh<m_nChannels; iCh++) - { - ChnSettings[iCh].nPan = (((iCh&3) == 1) || ((iCh&3) == 2)) ? 0xC0 : 0x40; - ChnSettings[iCh].nVolume = 64; - } - return TRUE; -} - - diff --git a/lib/libmodplug/src/load_mid.cpp b/lib/libmodplug/src/load_mid.cpp deleted file mode 100644 index 5a84b3500b..0000000000 --- a/lib/libmodplug/src/load_mid.cpp +++ /dev/null @@ -1,2020 +0,0 @@ -/* - - MikMod Sound System - - By Jake Stine of Divine Entertainment (1996-2000) - - Support: - If you find problems with this code, send mail to: - air@divent.org - - Distribution / Code rights: - Use this source code in any fashion you see fit. Giving me credit where - credit is due is optional, depending on your own levels of integrity and - honesty. - - ----------------------------------------- - Module: LOAD_MID - - MID module loader. - by Peter Grootswagers (2006) - <email:pgrootswagers@planet.nl> - - Portability: - All systems - all compilers (hopefully) -*/ - -#include <stdlib.h> -#include <time.h> -#include <string.h> -#include <math.h> -#include <ctype.h> -#include "stdafx.h" - -#ifdef NEWMIKMOD -#include "mikmod.h" -#include "uniform.h" -#include "itshare.h" // for STMEM_PITCHSLIDE -typedef UBYTE BYTE; -typedef UWORD WORD; -#define MAX_POLYPHONY 12 // max notes in one midi channel -#define MAX_TRACKS 63 // max mod tracks -#define WHEELSHIFT 11 // how many bits the 13bit midi wheel value must shift right -#else -#include "stdafx.h" -#include "sndfile.h" -#define PAN_LEFT 0x30 -#define PAN_RIGHT 0xD0 -#define MAX_POLYPHONY 16 // max notes in one midi channel -#define MAX_TRACKS (MAX_BASECHANNELS-6) // max mod tracks -#define WHEELSHIFT 10 // how many bits the 13bit midi wheel value must shift right -#endif - -#include "load_pat.h" - -#define ROWSPERNOTE 16 -#define ENV_MMMID_SPEED "MMMID_SPEED" -#define ENV_MMMID_DEBUG "MMMID_DEBUG" -#define ENV_MMMID_VERBOSE "MMMID_VERBOSE" - -/************************************************************************** -**************************************************************************/ -#ifdef NEWMIKMOD -static char MID_Version[] = "Musical Instrument Digital Interface"; -#endif - -typedef enum { - none, - wheeldown, - wheelup, - fxbrk, - tmpo, - fxsync, - modwheel, - mainvol, - prog -} MIDEVENT_X_EFFECT; - -typedef struct _MIDEVENT -{ - struct _MIDEVENT *next; - ULONG tracktick; - BYTE flg; // 1 = note present - BYTE note; - BYTE volume; - BYTE smpno; - BYTE fx; - BYTE fxparam; -} MIDEVENT; - -typedef struct _MIDTRACK -{ - struct _MIDTRACK *next; - MIDEVENT *head; - MIDEVENT *tail; - MIDEVENT *workevent; // keeps track of events in track - int balance; // last balance on this track - ULONG vtracktick; // tracktick of last note event (on or off) - BYTE chan; - BYTE vpos; // 0xff is track is free for use, otherwise it's the note playing on this track - BYTE volume; // last note volume on this track - BYTE instr; // current instrument for this track -} MIDTRACK; - -#ifdef NEWMIKMOD - -#define MMFILE MMSTREAM -#define mmfseek(f,p,w) _mm_fseek(f,p,w) -#define mmftell(x) _mm_ftell(x) -#define mmreadUBYTE(f) _mm_read_UBYTE(f) -#define mmreadSBYTES(buf,sz,f) _mm_read_SBYTES(buf,sz,f) -#define mmreadUBYTES(buf,sz,f) _mm_read_UBYTES(buf,sz,f) - -#else - -#define MMSTREAM FILE -#define _mm_fseek(f,pos,whence) fseek(f,pos,whence) -#define _mm_read_UBYTES(buf,sz,f) fread(buf,sz,1,f) -#define _mm_read_SBYTES(buf,sz,f) fread(buf,sz,1,f) -#define DupStr(h,buf,sz) strdup(buf) -#define _mm_calloc(h,n,sz) calloc(n,sz) -#define _mm_recalloc(h,buf,sz,elsz) realloc(buf,sz) -#undef _mm_free -#define _mm_free(h,p) free(p) - -typedef struct { - char *mm; - int sz; - int pos; -} MMFILE; - -static void mmfseek(MMFILE *mmfile, long p, int whence) -{ - switch(whence) { - case SEEK_SET: - mmfile->pos = p; - break; - case SEEK_CUR: - mmfile->pos += p; - break; - case SEEK_END: - mmfile->pos = mmfile->sz + p; - break; - } -} - -static long mmftell(MMFILE *mmfile) -{ - return mmfile->pos; -} - -static BYTE mmreadUBYTE(MMFILE *mmfile) -{ - BYTE b; - b = (BYTE)mmfile->mm[mmfile->pos]; - mmfile->pos++; - return b; -} - -static void mmreadUBYTES(BYTE *buf, long sz, MMFILE *mmfile) -{ - memcpy(buf, &mmfile->mm[mmfile->pos], sz); - mmfile->pos += sz; -} - -static void mmreadSBYTES(char *buf, long sz, MMFILE *mmfile) -{ - memcpy(buf, &mmfile->mm[mmfile->pos], sz); - mmfile->pos += sz; -} - -#endif - -/************************************************************************** -**************************************************************************/ - -typedef struct _MIDHANDLE -{ -#ifdef NEWMIKMOD - MM_ALLOC *allochandle; - MM_ALLOC *trackhandle; -#endif - MMFILE *mmf; - MIDTRACK *track; - MIDTRACK *tp; - ULONG tracktime; - const char *debug; - const char *verbose; - int speed; - int midispeed; - int midiformat; - int resolution; - int miditracks; - int divider; - int tempo; - int percussion; - long deltatime; -} MIDHANDLE; - -static void mid_dump_tracks(MIDHANDLE *h) -{ - MIDTRACK *tr; - MIDEVENT *e; - int t; - printf("tracktime = %ld\n", (long)(h->tracktime)); - printf("speed = %d\n", h->speed); - printf("midispeed = %d\n", h->midispeed); - printf("midiformat = %d\n", h->midiformat); - printf("resolution = %d\n", h->resolution); - printf("miditracks = %d\n", h->miditracks); - printf("divider = %d\n", h->divider); - printf("tempo = %d\n", h->tempo); - printf("percussion = %d\n", h->percussion); - printf("deltatime = %ld\n", h->deltatime); - t = 0; - for( tr=h->track; tr; tr = tr->next ) { - t++; - printf("TRACK %2d chan=%d note=0x%02x vol=%d pan=0x%02x instr=%d\n", t, tr->chan + 1, tr->vpos, tr->balance, tr->volume, tr->instr); - for( e=tr->head; e; e=e->next ) { - printf("%2d %6ld %s %3d %3d %3d ", - t, (long)(e->tracktick), - e->flg? "NOTE": "CTRL", e->note, e->volume, e->smpno); - switch( e->fx ) { - case fxbrk: printf("fxbrk\n");break; - case fxsync: printf("fxsync\n");break; - case prog: printf("prog %d\n", e->fxparam);break; - case mainvol: printf("mainvol %d\n", e->fxparam);break; - case modwheel: printf("modwheel %d\n", e->fxparam);break; - case wheeldown: printf("wheeldown %d\n", e->fxparam);break; - case wheelup: printf("wheelup %d\n", e->fxparam);break; - case tmpo: printf("tmpo %d\n", e->fxparam);break; - default: printf("\n");break; - } - } - } -} - -static void mid_message(const char *s1, const char *s2) -{ - char txt[256]; - if( strlen(s1) + strlen(s2) > 255 ) return; - sprintf(txt, s1, s2); -#ifdef NEWMIKMOD - _mmlog(txt); -#else - fprintf(stderr, "load_mid > %s\n", txt); -#endif -} - -static ULONG miditicks(MIDHANDLE *h, ULONG modtick) -{ - return modtick * h->divider / ROWSPERNOTE / h->speed; -} - -static ULONG modticks(MIDHANDLE *h, ULONG miditick) -{ - return miditick * ROWSPERNOTE * h->speed / h->divider; -} - -static void mid_adjust_for_optimal_tempo(MIDHANDLE *h, int maxtempo) -{ - // the tempo is adjusted so that the maximum tempo is 255 - // this way we have the biggest change that very short notes get played - // and we make sure the tempo doesn't become too large or too small - // if the piece in hand isn't so weird it changes tempo from 20 to 255, that is. - // tempo is only registered in first track (h->track) because it is a global event - MIDEVENT *e; - int d, t; - if( maxtempo < 1 ) return; - d = h->divider; - t = maxtempo; - h->divider = (t * d) / 255; - while( (h->midispeed = miditicks(h, h->speed)) < h->speed ) { - ++t; - h->divider = (t * d) / 255; - } - if( h->verbose && t > maxtempo ) - printf("Adjusted maximum tempo from %d to %d to get %d miditicks per patternrow\n", - maxtempo, 2 * maxtempo - t, h->midispeed); - if( h->track ) { - for( e=h->track->head; e; e=e->next ) { - if( e->fx == tmpo ) - e->fxparam = (255 * e->fxparam ) / t; - } - } -} - -// ===================================================================================== -static MIDEVENT *mid_new_event(MIDHANDLE *h) -// ===================================================================================== -{ - MIDEVENT *retval; - - retval = (MIDEVENT *)_mm_calloc(h->trackhandle, 1,sizeof(MIDEVENT)); - retval->next = NULL; - retval->tracktick = h->tracktime; - retval->flg = 0; - retval->note = 0; - retval->volume = 0; - retval->smpno = 0; - retval->fx = none; - retval->fxparam = 0; - return retval; -} - -// ===================================================================================== -static MIDTRACK *mid_new_track(MIDHANDLE *h, int mch, int pos) -// ===================================================================================== -{ - MIDTRACK *retval; - retval = (MIDTRACK *)_mm_calloc(h->trackhandle, 1,sizeof(MIDTRACK)); - retval->next = NULL; - retval->vpos = pos; - retval->instr = 1; - retval->chan = mch; - retval->head = NULL; - retval->tail = NULL; - retval->workevent = NULL; - retval->vtracktick = 0; - retval->volume = h->track? h->track->volume: 120; - retval->balance = 64; - return retval; -} - -static int mid_numtracks(MIDHANDLE *h) -{ - int n; - MIDTRACK *t; - n=0; - for( t = h->track; t; t=t->next ) - n++; - return n; -} - -// find out how many midichannel we have -static int mid_numchans(MIDHANDLE *h) -{ - int i,c,n; - MIDTRACK *t; - c = 0; - for( t = h->track; t; t=t->next ) - c |= (1<<t->chan); - n = 0; - for( i=0; i<16; i++ ) - if( c & (1<<i) ) n++; - return n; -} - -// find out which ordinal a midichannel has -static int mid_ordchan(MIDHANDLE *h, int mch) -{ - int i,c,n; - MIDTRACK *t; - c = 0; - for( t = h->track; t; t=t->next ) - c |= (1<<t->chan); - n = 0; - for( i=0; i<mch; i++ ) - if( c & (1<<i) ) n++; - return n; -} - -static void mid_rewind_tracks(MIDHANDLE *h) -{ - MIDTRACK *tr; - h->tracktime = 0; - for( tr = h->track; tr; tr = tr->next ) { - tr->vpos = 0xff; - tr->workevent = tr->head; - tr->vtracktick = 0; - } -} - -static void mid_update_track(MIDTRACK *tr) -{ - MIDEVENT *e; - e = tr->workevent; - if( e->flg ) { - if( e->volume ) tr->vpos = e->note; - else tr->vpos = 0xff; - tr->volume = e->volume; - tr->vtracktick = e->tracktick; - } - if( e->fx == prog ) tr->instr = e->fxparam; -} - -static void mid_sync_track(MIDTRACK *tr, ULONG tracktime) -{ - MIDEVENT *e; - e = tr->workevent; - if( e && e->tracktick > tracktime ) e = tr->head; // start again.... - for( ; e && e->tracktick <= tracktime; e=e->next ) { - tr->workevent = e; - mid_update_track(tr); - } -} - -// ===================================================================================== -static MIDTRACK *mid_find_track(MIDHANDLE *h, int mch, int pos) -// ===================================================================================== -{ - MIDTRACK *tr; - for( tr=h->track; tr; tr=tr->next ) { - mid_sync_track(tr, h->tracktime); - if( tr->chan == mch && tr->vpos == pos ) - return tr; - } - return NULL; -} - -// ===================================================================================== -static MIDTRACK *mid_locate_track(MIDHANDLE *h, int mch, int pos) -// ===================================================================================== -{ - MIDTRACK *tr, *prev, *trunused; - MIDEVENT *e; - int instrno = 1; - int polyphony; - int vol = 0, bal = 0; - int numtracks; - ULONG tmin; - prev = NULL; - trunused = NULL; - polyphony = 0; - numtracks = 0; - tmin = h->midispeed; // minimal distance between note events in track - // look up track with desired channel and pos (note) - for( tr=h->track; tr; tr=tr->next ) { - mid_sync_track(tr, h->tracktime); - if( tr->chan == mch ) { - if( tr->vpos == pos ) - return tr; - if( tr->vpos == 0xff ) { - // check if track with silence is quiet long enough - if( h->tracktime > tr->vtracktick + tmin ) trunused = tr; - } - else vol = tr->volume; - instrno = tr->instr; - bal = tr->balance; - polyphony++; - } - numtracks++; - prev = tr; - } - if( trunused ) { - trunused->vpos = pos; - return trunused; - } - if( polyphony > MAX_POLYPHONY || (polyphony > 0 && numtracks > MAX_TRACKS) ) { // do not use up too much channels - for( tr=h->track; tr; tr=tr->next ) { - if( tr->chan == mch ) { - e = tr->workevent; - if( h->tracktime > e->tracktick + tmin ) { - tmin = h->tracktime - e->tracktick; - trunused = tr; - } - } - } - if( trunused ) { - trunused->vpos = pos; - return trunused; - } - } - if( numtracks > MAX_TRACKS ) { // we can not allocate new tracks - tmin = 0; - for( tr=h->track; tr; tr=tr->next ) { - if( tr->chan == mch ) { - e = tr->workevent; - if( h->tracktime >= e->tracktick + tmin ) { - tmin = h->tracktime - e->tracktick; - trunused = tr; - } - } - } - if( trunused ) { - trunused->vpos = pos; - return trunused; - } - tmin = 0; - for( tr=h->track; tr; tr=tr->next ) { - e = tr->workevent; - if( h->tracktime >= e->tracktick + tmin ) { - tmin = h->tracktime - e->tracktick; - trunused = tr; - } - } - if( trunused ) { - trunused->vpos = pos; - trunused->chan = mch; - return trunused; - } - } - tr = mid_new_track(h, mch, pos); - tr->instr = instrno; - tr->volume = vol; - tr->balance = bal; - if( prev ) prev->next = tr; - else h->track = tr; - return tr; -} - -static void mid_add_event(MIDHANDLE *h, MIDTRACK *tp, MIDEVENT *e) -{ - MIDEVENT *ew, *ep; - ep = NULL; - ew = tp->workevent; - if( ew && ew->tracktick > e->tracktick ) ew = tp->head; // start again from the beginning... - for( ; ew && ew->tracktick <= e->tracktick; ew = ew->next ) { - ep = ew; - tp->workevent = ew; - mid_update_track(tp); - } - if( ep ) { - ep->next = e; - e->next = ew; - } - else { - e->next = tp->head; - tp->head = e; - } - if( !e->next ) - tp->tail = e; - tp->workevent = e; - mid_update_track(tp); -} - -static void mid_add_tempo_event(MIDHANDLE *h, int tempo) -{ - MIDEVENT *e; - e = mid_new_event(h); - e->flg = 0; - e->fx = tmpo; - e->fxparam = tempo; - mid_add_event(h, h->track, e); -} - -static void mid_add_partbreak(MIDHANDLE *h) -{ - MIDEVENT *e; - e = mid_new_event(h); - e->flg = 0; - e->fx = fxbrk; - mid_add_event(h, h->track, e); -} - -static void mid_add_noteoff(MIDHANDLE *h, MIDTRACK *tp) -{ - MIDEVENT *e; - e = mid_new_event(h); - e->flg = 1; - e->note = tp->vpos; - e->smpno = tp->instr; - mid_add_event(h, tp, e); -} - -static void mid_add_noteon(MIDHANDLE *h, MIDTRACK *tp, int n, int vol) -{ - MIDEVENT *e; - e = mid_new_event(h); - e->flg = 1; - e->note = n; - e->smpno = tp->instr; - e->volume = vol; - mid_add_event(h, tp, e); -} - -static BYTE modtremolo(int midimod) -{ - int m; - if( midimod == 0 ) return 0; - if( midimod > 63 ) { - m = (128 - midimod) / 4; - if( m==0 ) m = 1; - return m|0xf0; // find slide down - } - m = midimod / 4; - if( m==0 ) m = 1; - return (m<<4)|0x0f; // find slide up -} - -// ===================================================================================== -static void mid_mod_wheel(MIDHANDLE *h, int mch, int mod) -// ===================================================================================== -{ - MIDTRACK *tr; - MIDEVENT *e; - for( tr=h->track; tr; tr=tr->next ) { - if( tr->chan == mch ) { - mid_sync_track(tr, h->tracktime); - if( tr->vpos != 0xff ) { // only on tracks with notes on... - e = mid_new_event(h); - e->flg = 0; - e->fx = modwheel; - e->fxparam = modtremolo(mod); - mid_add_event(h, tr, e); - } - } - } -} - -// ===================================================================================== -static void mid_main_volume(MIDHANDLE *h, int mch, int vol) -// ===================================================================================== -{ - MIDTRACK *tr; - MIDEVENT *e; - for( tr=h->track; tr; tr=tr->next ) { - if( tr->chan == mch ) { - e = mid_new_event(h); - e->flg = 0; - e->fx = mainvol; - e->fxparam = vol; - mid_add_event(h, tr, e); - } - } -} - -// transform 0..63..127 to left..center..right in 2n+1 areas -static int modpan(int midipan, int n) -{ - int npan, area, x; - x = 2 * n + 1; - area = (midipan * x * (PAN_RIGHT - PAN_LEFT))>>7; - npan = (PAN_LEFT * x + area) / x; - return npan; -} - -// ===================================================================================== -static void mid_pan(MIDHANDLE *h, int mch, int pan) -// ===================================================================================== -{ - MIDTRACK *tr; - int hits; - hits = 0; - for( tr=h->track; tr; tr=tr->next ) { - if( tr->chan == mch ) { - hits++; - tr->balance = pan; - } - } - if( !hits ) { - tr = mid_locate_track(h, mch, 0xff); - tr->balance = pan; - } -} - -// ===================================================================================== -static void mid_add_program(MIDHANDLE *h, int mch, int pr) -// ===================================================================================== -{ - MIDTRACK *tr; - MIDEVENT *e; - int hits; - hits = 0; - for( tr=h->track; tr; tr=tr->next ) { - if( tr->chan == mch ) { - hits++; - e = mid_new_event(h); - e->flg = 0; - e->fx = prog; - e->fxparam = pat_gmtosmp(pr + 1); - mid_add_event(h, tr, e); - } - } - if( !hits ) { - tr = mid_locate_track(h, mch, 0xff); - e = mid_new_event(h); - e->flg = 0; - e->fx = prog; - e->fxparam = pat_gmtosmp(pr + 1); - mid_add_event(h, tr, e); - } -} - -// ===================================================================================== -static void mid_all_notes_off(MIDHANDLE *h, int mch) -// ===================================================================================== -{ - MIDTRACK *tr; - if( h->debug ) printf("%ld %d all notes off\n",(long)(h->tracktime), mch+1); - for( tr=h->track; tr; tr=tr->next ) { - if( tr->chan == mch || mch == -1 ) { - mid_sync_track(tr, h->tracktime); - if( tr->vpos != 0xff ) - mid_add_noteoff(h, tr); - } - } -} - -#ifndef NEWMIKMOD -static void mid_add_sync(MIDHANDLE *h, MIDTRACK *tp) -{ - MIDEVENT *e; - e = mid_new_event(h); - e->flg = 0; - e->fx = fxsync; - mid_add_event(h, tp, e); -} -#endif - -static BYTE mid_to_mod_wheel(unsigned int midwheel) -{ - unsigned int i; - if( midwheel == 0 ) return 0; - i = midwheel >> WHEELSHIFT; - return i+1; -} - -static void mid_add_wheel(MIDHANDLE *h, MIDTRACK *tp, int wheel) -{ - MIDEVENT *e; - e = mid_new_event(h); - e->flg = 0; - if( wheel < 0 ) { - e->fx = wheeldown; - e->fxparam = mid_to_mod_wheel(-wheel); - } - else { - e->fx = wheelup; - e->fxparam = mid_to_mod_wheel(wheel); - } - mid_add_event(h, tp, e); -} - -static void mid_add_pitchwheel(MIDHANDLE *h, int mch, int wheel) -{ - MIDTRACK *tr; - int hits; - hits = 0; - for( tr=h->track; tr; tr=tr->next ) { - if( tr->chan == mch ) { - hits++; - mid_sync_track(tr, h->tracktime); - if( tr->vpos != 0xff ) // only on tracks with notes on... - mid_add_wheel(h, tr, wheel); - } - } - if( !hits ) { // special case in midiformat 1 events in first track... - tr = mid_locate_track(h, mch, 0xff); - mid_add_wheel(h, tr, wheel); - } -} - -static long int mid_read_long(MIDHANDLE *h) -{ - BYTE buf[4]; - mmreadUBYTES(buf, 4, h->mmf); - return (buf[0]<<24)|(buf[1]<<16)|(buf[2]<<8)|buf[3]; -} - -static short int mid_read_short(MIDHANDLE *h) -{ - BYTE buf[2]; - mmreadUBYTES(buf, 2, h->mmf); - return (buf[0]<<8)|buf[1]; -} - -static BYTE mid_read_byte(MIDHANDLE *h) -{ - return mmreadUBYTE(h->mmf); -} - -static int mid_read_delta(MIDHANDLE *h) -{ - BYTE bits; - int i, d; - d = 0; - for( i=0; i<4; ) { - bits = mid_read_byte(h); - i++; - d = (d<<7)|(bits&0x7f); - if( !(bits & 0x80) ) - break; - } - h->deltatime = d; - return i; -} - -// ===================================================================================== -#ifdef NEWMIKMOD -BOOL MID_Test(MMSTREAM *mmfile) -#else -BOOL CSoundFile::TestMID(const BYTE *lpStream, DWORD dwMemLength) -#endif -// ===================================================================================== -{ - char id[5]; - MIDHANDLE h; -#ifdef NEWMIKMOD - h.mmf = mmfile; -#else - MMFILE mm; - mm.mm = (char *)lpStream; - mm.sz = dwMemLength; - h.mmf = &mm; -#endif - mmfseek(h.mmf,0,SEEK_SET); - mmreadSBYTES(id, 4, h.mmf); - id[4] = '\0'; - return !strcmp(id,"MThd") && mid_read_long(&h) == 6; -} - -// ===================================================================================== -static MIDHANDLE *MID_Init(void) -{ - MIDHANDLE *retval; -#ifdef NEWMIKMOD - MM_ALLOC *allochandle; - - allochandle = _mmalloc_create("Load_MID", NULL); - retval = (MIDHANDLE *)_mm_calloc(allochandle, 1,sizeof(MIDHANDLE)); - if( !retval ) return NULL; - retval->allochandle = allochandle; - allochandle = _mmalloc_create("Load_ABC_tracks", NULL); - retval->trackhandle = allochandle; -#else - retval = (MIDHANDLE *)calloc(1,sizeof(MIDHANDLE)); - if( !retval ) return NULL; -#endif - retval->track = NULL; - retval->percussion = 0; - retval->debug = NULL; - return retval; -} - -#ifndef NEWMIKMOD -static void MID_CleanupTrack(MIDTRACK *tp) -{ - MIDEVENT *ep, *en; - if( tp ) { - for( ep=tp->head; ep; ep = en ) { - en=ep->next; - free(ep); - } - tp->head = NULL; - } -} -#endif - -// ===================================================================================== -static void MID_CleanupTracks(MIDHANDLE *handle) -// ===================================================================================== -{ -#ifdef NEWMIKMOD - if(handle && handle->trackhandle) { - _mmalloc_close(handle->trackhandle); - handle->trackhandle = 0; - } -#else - MIDTRACK *tp, *tn; - if(handle) { - for( tp=handle->track; tp; tp = tn ) { - tn=tp->next; - MID_CleanupTrack(tp); - } - handle->track = NULL; - } -#endif -} - -// ===================================================================================== -static void MID_Cleanup(MIDHANDLE *handle) -// ===================================================================================== -{ -#ifdef NEWMIKMOD - if(handle && handle->allochandle) { - MID_CleanupTracks(handle); - _mmalloc_close(handle->allochandle); - handle->allochandle = 0; - } -#else - if(handle) { - MID_CleanupTracks(handle); - free(handle); - handle = 0; - } -#endif -} - -static int mid_is_global_event(MIDEVENT *e) -{ - return (e->fx == tmpo || e->fx == fxbrk); -} - -static MIDEVENT *mid_next_global(MIDEVENT *e) -{ - for( ; e && !mid_is_global_event(e); e=e->next ) ; - return e; -} - -static MIDEVENT *mid_next_fx(MIDEVENT *e) -{ - for( ; e && e->fx == none; e=e->next ) ; - return e; -} - -static int mid_is_note_event(MIDEVENT *e) -{ -#ifdef LOOPED_NOTES_OFF - return (e->flg == 0); -#else - if( e->flg == 0 ) return 0; - if( e->volume ) return 1; - return pat_smplooped(e->smpno); // let non looping samples die out... -#endif -} - -static MIDEVENT *mid_next_note(MIDEVENT *e) -{ - for( ; e && !mid_is_note_event(e); e=e->next ) ; - return e; -} - -// ===================================================================================== -#ifdef NEWMIKMOD -static void MID_ReadPatterns(UNIMOD *of, MIDHANDLE *h, int numpat) -// ===================================================================================== -{ - int pat,row,i,ch,trkset; - BYTE n,ins,vol; - MIDTRACK *t; - MIDEVENT *e, *en, *ef, *el; - ULONG tt1, tt2; - UNITRK_EFFECT eff; - - // initialize start points of event list in tracks - for( t = h->track; t; t = t->next ) t->workevent = t->head; - for( pat = 0; pat < numpat; pat++ ) { - utrk_reset(of->ut); - for( row = 0; row < 64; row++ ) { - tt1 = miditicks(h, (pat * 64 + row ) * h->speed); - tt2 = tt1 + h->midispeed; - for( e=mid_next_global(h->track->workevent); e && e->tracktick < tt2; e=mid_next_global(e->next) ) { - if( e && e->tracktick >= tt1 ) { // we have a controller event in this row - switch( e->fx ) { - case tmpo: - eff.effect = UNI_GLOB_TEMPO; - eff.param.u = e->fxparam; - eff.framedly = UFD_RUNONCE; - utrk_write_global(of->ut, &eff, PTMEM_TEMPO); - break; - case fxbrk: - eff.effect = UNI_GLOB_PATBREAK; - eff.param.u = 0; - eff.framedly = UFD_RUNONCE; - utrk_write_global(of->ut, &eff, UNIMEM_NONE); - break; - } - } - } - ch = 0; - for( t = h->track; t; t = t->next ) { - trkset = 0; - e = NULL; - for( el=mid_next_fx(t->workevent); el && el->tracktick < tt2; el=mid_next_fx(el->next) ) { - if( el && el->tracktick >= tt1 ) { - switch( el->fx ) { - case modwheel: - case wheelup: - case wheeldown: - e = el; - default: - break; - } - } - } - if( e ) { // we have a controller event in this row - switch( e->fx ) { - case modwheel: - if( !trkset ) { - utrk_settrack(of->ut, ch); - trkset = 1; - } - eff.effect = UNI_VOLSLIDE; - eff.framedly = UFD_RUNONCE; - if( (e->fxparam & 0x0f) == 0x0f ) - eff.param.s = (e->fxparam >> 3)&0x1f; - else - eff.param.s = -((e->fxparam & 0x0f)*2); - utrk_write_local(of->ut, &eff, STMEM_VOLSLIDE); - break; - case wheelup: - if( !trkset ) { - utrk_settrack(of->ut, ch); - trkset = 1; - } - eff.effect = UNI_PITCHSLIDE; - eff.framedly = UFD_RUNONCE; - eff.param.s = e->fxparam; - utrk_write_local(of->ut, &eff, STMEM_PITCHSLIDE); - break; - case wheeldown: - if( !trkset ) { - utrk_settrack(of->ut, ch); - trkset = 1; - } - eff.effect = UNI_PITCHSLIDE; - eff.framedly = UFD_RUNONCE; - eff.param.s = -(int)(e->fxparam); - utrk_write_local(of->ut, &eff, STMEM_PITCHSLIDE); - break; - } - } - for( e=mid_next_note(t->workevent); e && e->tracktick < tt1; e=mid_next_note(e->next) ) - t->workevent = e; - i = 0; - ef = NULL; - en = e; - el = e; - for( ; e && e->tracktick < tt2; e=mid_next_note(e->next) ) { // we have a note event in this row - t->workevent = e; - i++; - if( e->volume ) { - if( !ef ) ef = e; - el = e; - } - } - if( i ) { - if( !trkset ) { - utrk_settrack(of->ut, ch); - trkset = 1; - } - if( i == 1 || ef == el || !ef ) { // only one event in this row - if( ef ) e = ef; - else e = en; - el = t->workevent; - n = pat_modnote(e->note); - ins = e->smpno; - eff.framedly = modticks(h, e->tracktick - tt1); - eff.param.u = 0; - eff.param.byte_a = n; - eff.param.byte_b = ins; - vol = e->volume; - if( vol == 0 ) { - eff.effect = UNI_NOTEKILL; - utrk_write_local(of->ut, &eff, UNIMEM_NONE); - } - else { - if( el->volume == 0 ) { - eff.framedly = modticks(h, el->tracktick - tt1); - eff.effect = UNI_NOTEKILL; - utrk_write_local(of->ut, &eff, UNIMEM_NONE); - } - else { - if( eff.framedly ) { - eff.effect = UNI_NOTEDELAY; - utrk_write_local(of->ut, &eff, UNIMEM_NONE); - } - } - } - utrk_write_inst(of->ut, ins); - utrk_write_note(of->ut, n); // <- normal note - pt_write_effect(of->ut, 0xc, vol); - } - else { - // two notes in one row, use FINEPITCHSLIDE runonce effect - // start first note on first tick and framedly runonce on seconds note tick - // use volume and instrument of last note - n = pat_modnote(ef->note); - i = pat_modnote(el->note); - ins = el->smpno; - vol = el->volume; - eff.effect = UNI_PITCHSLIDE; - eff.framedly = modticks(h, el->tracktick - tt1)|UFD_RUNONCE; - eff.param.s = ((i > n)?i-n:n-i); - utrk_write_inst(of->ut, ins); - utrk_write_note(of->ut, n); // <- normal note - pt_write_effect(of->ut, 0xc, vol); - utrk_write_local(of->ut, &eff, (i > n)? PTMEM_PITCHSLIDEUP: PTMEM_PITCHSLIDEDN); - } - } - ch++; - } - utrk_newline(of->ut); - } - if(!utrk_dup_pattern(of->ut,of)) return; - } -} - -#else - -static int MID_ReadPatterns(MODCOMMAND *pattern[], WORD psize[], MIDHANDLE *h, int numpat, int channels) -// ===================================================================================== -{ - int pat,row,i,ch; - BYTE n,ins,vol; - MIDTRACK *t; - MIDEVENT *e, *en, *ef, *el; - ULONG tt1, tt2; - MODCOMMAND *m; - int patbrk, tempo; - if( numpat > MAX_PATTERNS ) numpat = MAX_PATTERNS; - - // initialize start points of event list in tracks - for( t = h->track; t; t = t->next ) t->workevent = t->head; - for( pat = 0; pat < numpat; pat++ ) { - pattern[pat] = CSoundFile::AllocatePattern(64, channels); - if( !pattern[pat] ) return 0; - psize[pat] = 64; - for( row = 0; row < 64; row++ ) { - tt1 = miditicks(h, (pat * 64 + row ) * h->speed); - tt2 = tt1 + h->midispeed; - ch = 0; - tempo = 0; - patbrk = 0; - for( e=mid_next_global(h->track->workevent); e && e->tracktick < tt2; e=mid_next_global(e->next) ) { - if( e && e->tracktick >= tt1 ) { // we have a controller event in this row - switch( e->fx ) { - case tmpo: - tempo = e->fxparam; - break; - case fxbrk: - patbrk = 1; - break; - } - } - } - for( t = h->track; t; t = t->next ) { - m = &pattern[pat][row * channels + ch]; - m->param = 0; - m->command = CMD_NONE; - for( e=mid_next_fx(t->workevent); e && e->tracktick < tt2; e=mid_next_fx(e->next) ) { - if( e && e->tracktick >= tt1 ) { // we have a controller event in this row - switch( e->fx ) { - case modwheel: - m->param = e->fxparam; - m->command = CMD_VOLUMESLIDE; - break; - case wheelup: - m->param = e->fxparam|0x10; - m->command = CMD_XFINEPORTAUPDOWN; - break; - case wheeldown: - m->param = e->fxparam|0x20; - m->command = CMD_XFINEPORTAUPDOWN; - break; - } - } - } - for( e=mid_next_note(t->workevent); e && e->tracktick < tt1; e=mid_next_note(e->next) ) - t->workevent = e; - i = 0; - ef = NULL; - en = e; - el = e; - for( ; e && e->tracktick < tt2; e=mid_next_note(e->next) ) { // we have a note event in this row - t->workevent = e; - i++; - if( e->volume ) { - if( !ef ) ef = e; - el = e; - } - } - if( i ) { - if( i == 1 || ef == el || !ef ) { // only one event in this row or a note on with some note off - if( ef ) e = ef; - else e = en; - el = t->workevent; - n = pat_modnote(e->note); - ins = e->smpno; - if( e->volume == 0 ) { - m->param = (BYTE)modticks(h, e->tracktick - tt1); - if( m->param ) { // note cut - m->command = CMD_S3MCMDEX; - m->param |= 0xC0; - } - else { - m->param = 0; - m->command = CMD_KEYOFF; - } - vol = 0; - } - else { - vol = e->volume/2; - if( el->volume == 0 ) { - m->param = (BYTE)modticks(h, el->tracktick - tt1); - if( m->param ) { // note cut - m->command = CMD_S3MCMDEX; - m->param |= 0xC0; - } - } - else { - m->param = (BYTE)modticks(h, e->tracktick - tt1); - if( m->param ) { // note delay - m->command = CMD_S3MCMDEX; - m->param |= 0xD0; - } - } - } - m->instr = ins; - m->note = n; // <- normal note - m->volcmd = VOLCMD_VOLUME; - m->vol = vol; - } - else { - // two notes in one row, use FINEPITCHSLIDE runonce effect - // start first note on first tick and framedly runonce on seconds note tick - // use volume and instrument of last note - n = pat_modnote(ef->note); - i = pat_modnote(el->note); - ins = el->smpno; - vol = el->volume/2; - if( vol > 64 ) vol = 64; - m->instr = ins; - m->note = n; // <- normal note - m->volcmd = VOLCMD_VOLUME; - m->vol = vol; - m->param = ((i > n)?i-n:n-i); - if( m->param < 16 ) { - if( m->param ) { - m->command = CMD_XFINEPORTAUPDOWN; - m->param |= (i > n)? 0x10: 0x20; - } - else { // retrigger same note... - m->command = CMD_RETRIG; - m->param = (BYTE)modticks(h, el->tracktick - tt1); - } - } - else - m->command = (i > n)? CMD_PORTAMENTOUP: CMD_PORTAMENTODOWN; - } - } - if( m->param == 0 && m->command == CMD_NONE ) { - if( tempo ) { - m->command = CMD_TEMPO; - m->param = tempo; - tempo = 0; - } - else { - if( patbrk ) { - m->command = CMD_PATTERNBREAK; - patbrk = 0; - } - } - } - ch++; - } - if( tempo || patbrk ) return 1; - } - } - return 0; -} - -#endif - -static ULONG mid_next_tracktick(MIDEVENT *e) -{ - MIDEVENT *en; - en = e->next; - if( en ) return en->tracktick; - return 0x7fffffff; // practically indefinite -} - -// cut off alle events that follow the given event -static void mid_stripoff(MIDTRACK *tp, MIDEVENT *e) -{ -#ifndef NEWMIKMOD - MIDEVENT *ep, *en; - for( ep=e->next; ep; ep = en ) { - en=ep->next; - free(ep); - } -#endif - e->next = NULL; - tp->tail = e; - tp->workevent = tp->head; - mid_sync_track(tp, e->tracktick); -} - -static void mid_notes_to_percussion(MIDTRACK *tp, ULONG adjust, ULONG tmin) -{ - MIDEVENT *e, *lno = 0; - int n = 0,v; - ULONG ton, toff = 0, tnext; - v = 0x7f; // as loud as it gets - ton = 0; - for( e=tp->head; e; e=e->next ) { - if( e->tracktick < adjust ) e->tracktick = 0; - else e->tracktick -= adjust; - if( e->flg == 1 ) { - if( e->volume > 0 ) { - n = e->note; - e->smpno = pat_gmtosmp(pat_gm_drumnr(n)); - e->note = pat_gm_drumnote(n); - e->volume = (v * e->volume) / 128; - if( v && !e->volume ) e->volume = 1; - ton = e->tracktick; - } - else { - toff = ton + tmin; - if( toff > e->tracktick ) { - tnext = mid_next_tracktick(e); - if( toff + tmin < tnext ) e->tracktick = toff; - else { - if( toff < tnext ) e->tracktick = toff - 1; - else e->tracktick = tnext - 1; - } - } - toff = e->tracktick; - lno = e; - } - } - else { - if( e->fx == mainvol ) { - v = e->fxparam; - if( !v && ton > toff ) { - e->flg = 1; - e->volume = 0; - e->note = pat_gm_drumnote(n); - toff = e->tracktick; - lno = e; - } - } - } - } - if( ton > toff ) { - char info[32]; - sprintf(info,"%ld > %ld note %d", (long)ton, (long)toff, n); - mid_message("drum track ends with note on (%s)", info); - } - if( lno && lno->next ) mid_stripoff(tp, lno); -} - -static void mid_prog_to_notes(MIDTRACK *tp, ULONG adjust, ULONG tmin) -{ - MIDEVENT *e, *lno = 0; - int i = 0, n = 0, v = 0x7f; - ULONG ton, toff = 0, tnext; - ton = 0; - for( e=tp->head; e; e=e->next ) { - if( e->tracktick < adjust ) e->tracktick = 0; - else e->tracktick -= adjust; - if( e->flg == 1 ) { - if( !i ) i = pat_gmtosmp(1); // happens in eternal2.mid - e->smpno = i; - n = e->note; - if( e->volume > 0 ) { - e->volume = (v * e->volume) / 128; - if( v && !e->volume ) e->volume = 1; - ton = e->tracktick; - } - else { - toff = ton + tmin; - if( toff > e->tracktick ) { - tnext = mid_next_tracktick(e); - if( toff + tmin < tnext ) e->tracktick = toff; - else { - if( toff < tnext ) e->tracktick = toff - 1; - else e->tracktick = tnext - 1; - } - } - toff = e->tracktick; - lno = e; - } - } - else { - if( e->fx == prog ) i = e->fxparam; - if( e->fx == mainvol ) { - v = e->fxparam; - if( !v && ton > toff ) { - e->flg = 1; - e->volume = 0; - e->note = n; - toff = e->tracktick; - lno = e; - } - } - } - } - if( ton > toff ) { - char info[40]; - sprintf(info,"channel %d, %ld > %ld note %d", tp->chan + 1, (long)ton, (long)toff, n); - mid_message("melody track ends with note on (%s)", info); - } - if( lno && lno->next ) mid_stripoff(tp, lno); -} - -static int midiword(BYTE *b) -{ - int i; - i = (b[0]&0x7f)|((b[1]&0x7f)<<7); - return i; -} - -static int midishort(BYTE *b) -{ - return midiword(b) - 0x2000; -} - -ULONG mid_first_noteonevent_tick(MIDEVENT *e) -{ - while( e && (e->flg == 0 || e->volume == 0) ) e=e->next; - if( !e ) return 0x7fffffff; - return e->tracktick; -} - -// ===================================================================================== -#ifdef NEWMIKMOD -BOOL MID_Load(MIDHANDLE *h, UNIMOD *of, MMSTREAM *mmfile) -#else -BOOL CSoundFile::ReadMID(const BYTE *lpStream, DWORD dwMemLength) -#endif -{ - static int avoid_reentry = 0; -#ifdef NEWMIKMOD -#define m_nDefaultTempo of->inittempo -#else - MIDHANDLE *h; - MMFILE mm; -#endif - int ch, dmulti, maxtempo, panlow, panhigh, numchans, numtracks; - MIDTRACK *ttp; - uint32_t t, numpats; - char buf[256]; - long miditracklen; - BYTE runningstatus; - BYTE cmd; - BYTE midibyte[2]; - long metalen, delta; - BYTE *p; - while( avoid_reentry ) sleep(1); - avoid_reentry = 1; -#ifdef NEWMIKMOD - h->mmf = mmfile; -#else - if( !TestMID(lpStream, dwMemLength) ) { - avoid_reentry = 0; - return FALSE; - } - h = MID_Init(); - if( !h ) { - avoid_reentry = 0; - return FALSE; - } - h->mmf = &mm; - mm.mm = (char *)lpStream; - mm.sz = dwMemLength; - mm.pos = 0; -#endif - h->debug = getenv(ENV_MMMID_DEBUG); - h->verbose = getenv(ENV_MMMID_VERBOSE); - pat_resetsmp(); - pat_init_patnames(); - mmfseek(h->mmf,8,SEEK_SET); - h->midiformat = mid_read_short(h); - h->miditracks = mid_read_short(h); - h->resolution = mid_read_short(h); - // at this point the h->mmf is positioned at first miditrack - if( h->midiformat == 0 ) h->miditracks = 1; - if( h->resolution & 0x8000 ) - h->divider = ((h->resolution & 0x7f00)>>8)*(h->resolution & 0xff); - else - h->divider = h->resolution; - h->divider <<= 2; // ticks per quartnote ==> ticks per note - h->tempo = 122; - m_nDefaultTempo = 0; - h->tracktime = 0; - h->speed = 6; - p = (BYTE *)getenv(ENV_MMMID_SPEED); - if( p && isdigit(*p) && p[0] != '0' && p[1] == '\0' ) { - // transform speed - t = *p - '0'; - h->speed *= t; - h->divider *= t; - h->speed /= 6; - h->divider /= 6; - } - // calculate optimal delta multiplier dmulti keeping tempo adjustments - // from 10 to 255 in mind (hoping there will be no midi's with tempo's - // lower than 10, that is sooo sick...) - // this is necessary for the tracks to patterns routine - dmulti = 1; - maxtempo = h->divider; - while( (h->midispeed = miditicks(h, h->speed)) * 10 < 255 * h->speed ) { - ++dmulti; - h->divider = maxtempo * dmulti; - } - h->tp = NULL; - memset(buf,0,sizeof(buf)); -#ifdef NEWMIKMOD - of->songname = NULL; -#else - strcpy(m_szNames[0], ""); -#endif - maxtempo = 0; - panlow = 64; - panhigh = 64; - if( h->verbose ) { - printf("Scanning MIDI with format: %d resolution: %d tracks: %d\n", - h->midiformat, - h->resolution, - h->miditracks); - } - if( h->verbose && dmulti > 1 ) { - printf("Multiplying resolution and deltatimes by %d to get %d miditicks per patternrow\n", - dmulti, h->midispeed); - } - for( t=0; t<(uint32_t)h->miditracks; t++ ) { - if( h->verbose ) printf("Parsing track %d\n", t+1); - mmreadSBYTES(buf,4,h->mmf); - buf[4] = '\0'; - if( strcmp(buf,"MTrk") ) { - mid_message("invalid track-chunk '%s' is not 'MTrk'",buf); - avoid_reentry = 0; - return FALSE; - } - miditracklen = mid_read_long(h); - runningstatus = 0; - if( t && h->midiformat == 1 ) mid_rewind_tracks(h); // tracks sound simultaneously - while( miditracklen > 0 ) { - miditracklen -= mid_read_delta(h); - midibyte[0] = mid_read_byte(h); - miditracklen--; - if( midibyte[0] & 0x80 ) { - runningstatus = midibyte[0]; - switch( runningstatus ) { - case 0xf1: - case 0xf4: - case 0xf5: - case 0xf6: - case 0xf7: - case 0xf8: - case 0xf9: - case 0xfa: - case 0xfb: - case 0xfc: - case 0xfd: - case 0xfe: - break; - default: - midibyte[0] = mid_read_byte(h); - miditracklen--; - break; - } - } - h->tracktime += dmulti * h->deltatime; - ch = runningstatus & 0x0f; - cmd = runningstatus & 0xf0; - switch( cmd ) { - case 0x80: // note off - midibyte[1] = mid_read_byte(h); - miditracklen--; - ttp = mid_find_track(h, ch, midibyte[0]); - if( ttp ) mid_add_noteoff(h, ttp); - if( h->debug ) - printf("%2d %08ld Note off: ch %d 0x%02x 0x%02x\n", - t, (long)(h->tracktime), - ch + 1, midibyte[0], midibyte[1]); - break; - case 0x90: // note on - midibyte[1] = mid_read_byte(h); - miditracklen--; - if( midibyte[1] ) { - ttp = mid_locate_track(h, ch, midibyte[0]); - mid_add_noteon(h, ttp, midibyte[0], midibyte[1]); - if( h->debug ) - printf("%2d %08ld Note on: ch %d 0x%02x 0x%02x\n", - t, (long)(h->tracktime), - ch + 1, midibyte[0], midibyte[1]); - } - else { - ttp = mid_find_track(h, ch, midibyte[0]); - if( ttp ) mid_add_noteoff(h, ttp); - if( h->debug ) - printf("%2d %08ld note off: ch %d 0x%02x\n", - t, (long)(h->tracktime), - ch + 1, midibyte[0]); - } - break; - case 0xa0: // polyphonic key pressure - midibyte[1] = mid_read_byte(h); - miditracklen--; - if( h->debug ) - printf("%2d %08ld polyphonic key pressure: ch %d 0x%02x 0x%02x\n", t, (long)(h->tracktime), ch + 1, midibyte[0], midibyte[1]); - break; - case 0xb0: // control change - midibyte[1] = mid_read_byte(h); - miditracklen--; - switch(midibyte[0]) { - case 0x01: // mod wheel - mid_mod_wheel(h, ch, midibyte[1]); - break; - case 0x07: // main volume - mid_main_volume(h, ch, midibyte[1]); - break; - case 0x0a: // pan - if( midibyte[1] < panlow ) panlow = midibyte[1]; - if( midibyte[1] > panhigh ) panhigh = midibyte[1]; - mid_pan(h, ch, midibyte[1]); - break; - case 0x0b: // expression - break; - case 0x7b: - if( midibyte[1] == 0x00 ) // all notes off - mid_all_notes_off(h, ch); - break; - default: - break; - } - if( h->debug ) - printf("%2d %08ld control change: ch %d 0x%02x 0x%02x\n", - t, (long)(h->tracktime), ch + 1, midibyte[0], midibyte[1]); - break; - case 0xc0: // program change - mid_add_program(h, ch, midibyte[0]); - if( h->debug ) - printf("%2d %08ld program change: ch %d %d\n", - t, (long)(h->tracktime), ch + 1, midibyte[0]); - break; - case 0xd0: // channel pressure - if( h->debug ) - printf("%2d %08ld channel pressure: ch %d 0x%02x\n", t, (long)(h->tracktime), ch + 1, midibyte[0]); - break; - case 0xe0: // pitch wheel change - midibyte[1] = mid_read_byte(h); - miditracklen--; - if( h->debug ) - printf("%2d %08ld pitch wheel change: ch %d %d\n", - t, (long)(h->tracktime), ch + 1, midishort(midibyte)); - mid_add_pitchwheel(h, ch, midishort(midibyte)); - break; - case 0xf0: // system & realtime - switch( runningstatus ) { - case 0xf0: // sysex - if( h->debug ) printf("%2d %08ld sysex: 0x%02x", - t, (long)(h->tracktime), midibyte[0]); - while( midibyte[0] != 0xf7 ) { - midibyte[0] = mid_read_byte(h); - miditracklen--; - if( h->debug ) printf(" %02X", midibyte[0]); - } - if( h->debug ) printf("\n"); - break; - case 0xf2: // song position pointer - midibyte[1] = mid_read_byte(h); - miditracklen--; - if( h->debug ) - printf("%2d %08ld song position pointer: %d", - t, (long)(h->tracktime), midishort(midibyte)); - break; - case 0xf7: - delta = h->deltatime; - miditracklen -= mid_read_delta(h); - metalen = h->deltatime; - if( h->debug ) - printf("%2d %08ld sysex continued: %ld", - t, (long)(h->tracktime), metalen); - while( metalen > 0 ) { - midibyte[1] = mid_read_byte(h); - metalen--; - miditracklen--; - if( h->debug ) printf(" %02X", midibyte[1]); - } - h->deltatime = delta; - break; - case 0xff: // meta event - delta = h->deltatime; - miditracklen -= mid_read_delta(h); - metalen = h->deltatime; - if( metalen > 31 ) metalen = 31; - if( metalen ) { - mmreadSBYTES(buf, metalen, h->mmf); - miditracklen -= metalen; - } - buf[metalen] = '\0'; - metalen = h->deltatime - metalen; - while( metalen > 0 ) { - midibyte[1] = mid_read_byte(h); - metalen--; - miditracklen--; - } - h->deltatime = delta; - switch( midibyte[0] ) { - case 0x03: // type: track name - if( h->debug ) - printf("%2d %08ld META trackname:%s\n", t, (long)(h->tracktime), buf); -#ifdef NEWMIKMOD - if( !of->songname ) - of->songname = DupStr(of->allochandle, buf, strlen(buf)); -#else - if( m_szNames[0][0] == '\0' ) - strcpy(m_szNames[0], buf); -#endif - break; - case 0x51: // type: tempo - p=(BYTE *)buf; - delta = (p[0]<<16)|(p[1]<<8)|p[2]; - if( delta ) - h->tempo = 60000000 / delta; - if( h->debug ) printf("%2d %08ld META tempo:%d\n", t, (long)(h->tracktime), h->tempo); - if( m_nDefaultTempo == 0 ) m_nDefaultTempo = h->tempo; - else { - ttp = h->track; - if( !ttp ) ttp = mid_locate_track(h, 0, 0xff); - mid_add_tempo_event(h,h->tempo); - } - if( h->tempo > maxtempo ) maxtempo = h->tempo; - break; - case 0x2f: // type: end of track - if( h->debug ) printf("%2d %08ld META end of track\n", t, (long)(h->tracktime)); - if( miditracklen > 0 ) { - sprintf(buf, "%ld", miditracklen); - mid_message("Meta event not at end of track, %s bytes left in track", buf); - miditracklen = 0; - } - break; - default: - if( h->debug ) printf("%2d %08ld META type 0x%02x\n", t, (long)(h->tracktime), midibyte[0]); - break; - } - break; - default: - if( h->debug ) printf("%2d %08ld System type 0x%02x\n", t, (long)(h->tracktime), midibyte[0]); - break; - } - break; - default: // no running status, just skip it... - if( h->debug ) printf("%2d %08ld unknown runningstatus: 0x%02x skipped:0x%02x\n", t, (long)(h->tracktime), runningstatus, midibyte[0]); - break; - } - if( miditracklen < 1 && (runningstatus != 0xff || midibyte[0] != 0x2f) ) { - delta = mmftell(h->mmf); - mmreadSBYTES(buf,4,h->mmf); - buf[4] = '\0'; - if( strcmp(buf,"MTrk") ) { - miditracklen = 0x7fffffff; - mid_message("Meta event not at end of track, %s bytes left in track", "superfluous"); - } - else - mid_message("Meta event not at end of track, %s bytes left in track", "no"); - mmfseek(h->mmf,delta,SEEK_SET); - } - } - } - if( h->verbose ) printf("Determining percussion channel\n"); - // get the lowest event time and the used channels - delta = 0x7fffffff; - metalen = 0; // use as bit bucket for used channels - for( ttp=h->track; ttp; ttp=ttp->next ) { - metalen |= (1<<ttp->chan); - if( ttp->head ) { - ULONG tt; - tt = mid_first_noteonevent_tick(ttp->head); - if( tt < (ULONG)delta ) - delta = tt; - } - } - if( metalen & 0x03ff ) { - if( (metalen & 0x0f00) == 0x0400 ) - h->percussion = 10; // buggy sng2mid uses channel 10 - else - h->percussion = 9; - } - else h->percussion = 15; - if( h->verbose ) - printf("Percussion channel is %d\nStripping off silences and other optimalisations\n", h->percussion + 1); - // last but not least shut off all pending events, transform drumnotes when appropriate - // strip off silences at begin and end and get the greatest tracktime - h->tracktime = 0; - metalen = h->midispeed; - for( ttp=h->track; ttp; ttp=ttp->next ) { - if( ttp->chan == h->percussion ) - mid_notes_to_percussion(ttp, delta, metalen); - else - mid_prog_to_notes(ttp, delta, metalen); - if( ttp->tail && ttp->tail->tracktick > h->tracktime ) - h->tracktime = ttp->tail->tracktick; - } - h->tracktime += h->divider >> 2; // add one quartnote to the song for silence - mid_add_partbreak(h); - if( h->debug ) - mid_dump_tracks(h); - numchans = mid_numchans(h); - if( panlow > 48 || panhigh < 80 ) { - for( ttp=h->track; ttp; ttp=ttp->next ) { - ttp->balance = ((0x40*numchans+0x80*mid_ordchan(h, ttp->chan))/numchans)&0x7f; - } - } - // set module variables - numtracks = mid_numtracks(h); - if( m_nDefaultTempo == 0 ) m_nDefaultTempo = h->tempo; - if( maxtempo == 0 ) maxtempo = h->tempo; - if( maxtempo != 255 ) { - if( h->verbose ) printf("Adjusting tempo %d to 255\n", maxtempo); - mid_adjust_for_optimal_tempo(h, maxtempo); - } - if( maxtempo > 0 ) m_nDefaultTempo = (255 * m_nDefaultTempo) / maxtempo; - numpats = 1 + (modticks(h, h->tracktime) / h->speed / 64 ); - if( h->verbose ) printf("Generating %d patterns with speed %d\n", numpats, h->speed); -#ifdef NEWMIKMOD - if( !of->songname ) of->songname = DupStr(of->allochandle, "Untitled", 8); - of->memsize = STMEM_LAST; // Number of memory slots to reserve! - of->modtype = _mm_strdup(of->allochandle, MID_Version); - of->numpat = numpats; - of->numpos = of->numpat; - of->reppos = 0; - of->initspeed = h->speed; - of->numchn = numtracks; - of->numtrk = of->numpat * of->numchn; - of->initvolume = 64; - of->pansep = 128; - // orderlist - if(!AllocPositions(of, of->numpos)) { - avoid_reentry = 0; - return FALSE; - } - for(t=0; t<of->numpos; t++) - of->positions[t] = t; - if( !PAT_Load_Instruments(of) ) { - avoid_reentry = 0; - return FALSE; - } - // ============================== - // Load the pattern info now! - if(!AllocTracks(of)) { - avoid_reentry = 0; - return FALSE; - } - if(!AllocPatterns(of)) { - avoid_reentry = 0; - return FALSE; - } - of->ut = utrk_init(of->numchn, h->allochandle); - utrk_memory_reset(of->ut); - utrk_local_memflag(of->ut, PTMEM_PORTAMENTO, TRUE, FALSE); - MID_ReadPatterns(of, h, numpats); - // ============================================================ - // set panning positions - t = 0; - for( ttp=h->track; ttp; ttp=ttp->next ) { - of->panning[t] = modpan(ttp->balance, numchans / 2); - t++; - } -#else - m_nType = MOD_TYPE_MID; - m_nDefaultSpeed = h->speed; - m_nChannels = numtracks; - m_dwSongFlags = SONG_LINEARSLIDES; - m_nMinPeriod = 28 << 2; - m_nMaxPeriod = 1712 << 3; - // orderlist - for(t=0; t < numpats; t++) - Order[t] = t; - if( !PAT_Load_Instruments(this) ) { - avoid_reentry = 0; - return FALSE; - } - // ============================== - // Load the pattern info now! - if( MID_ReadPatterns(Patterns, PatternSize, h, numpats, m_nChannels) ) { - // :^( need one more channel to handle the global events ;^b - m_nChannels++; - h->tp = mid_new_track(h, h->track->chan, 0xff); - for( ttp=h->track; ttp->next; ttp=ttp->next ) ; - ttp->next = h->tp; - mid_add_sync(h, h->tp); - for( t=0; t<numpats; t++ ) { - FreePattern(Patterns[t]); - Patterns[t] = NULL; - } - MID_ReadPatterns(Patterns, PatternSize, h, numpats, m_nChannels); - } - // ============================================================ - // set panning positions - t = 0; - for( ttp=h->track; ttp; ttp=ttp->next ) { - ChnSettings[t].nPan = modpan(ttp->balance, numchans / 2); - ChnSettings[t].nVolume = 64; - t++; - } - MID_Cleanup(h); // we dont need it anymore -#endif - if( h->verbose ) printf("Done\n"); - avoid_reentry = 0; // it is safe now, I'm finished - return TRUE; -} - -#ifdef NEWMIKMOD -// ===================================================================================== -CHAR *MID_LoadTitle(MMSTREAM *mmfile) -// ===================================================================================== -{ - int t; - char buf[24]; - long miditracklen; - BYTE runningstatus; - BYTE cmd; - BYTE midibyte[2]; - long metalen; - MIDHANDLE hh, *h; - h = &hh; - h->mmf = mmfile; - mmfseek(h->mmf,8,SEEK_SET); - h->midiformat = mid_read_short(h); - h->miditracks = mid_read_short(h); - h->resolution = mid_read_short(h); - // at this point the h->mmf is positioned at first miditrack - if( h->midiformat == 0 ) h->miditracks = 1; - h->tracktime = 0; - for( t=0; t<h->miditracks; t++ ) { - mmreadSBYTES(buf,4,h->mmf); - miditracklen = mid_read_long(h); - runningstatus = 0; - while( miditracklen > 0 ) { - miditracklen -= mid_read_delta(h); - midibyte[0] = mid_read_byte(h); - miditracklen--; - if( midibyte[0] & 0x80 ) { - runningstatus = midibyte[0]; - switch( runningstatus ) { - case 0xf1: - case 0xf4: - case 0xf5: - case 0xf6: - case 0xf7: - case 0xf8: - case 0xf9: - case 0xfa: - case 0xfb: - case 0xfc: - case 0xfd: - case 0xfe: - break; - default: - midibyte[0] = mid_read_byte(h); - miditracklen--; - break; - } - } - cmd = runningstatus & 0xf0; - switch( cmd ) { - case 0x80: // note off - case 0x90: // note on - case 0xa0: // polyphonic key pressure - case 0xb0: // control change - case 0xe0: // pitch wheel change - midibyte[1] = mid_read_byte(h); - miditracklen--; - case 0xc0: // program change - case 0xd0: // channel pressure - break; - case 0xf0: // system & realtime - switch( runningstatus ) { - case 0xf0: // sysex - while( midibyte[0] != 0xf7 ) { - midibyte[0] = mid_read_byte(h); - miditracklen--; - } - break; - case 0xf2: // song position pointer - midibyte[1] = mid_read_byte(h); - miditracklen--; - break; - case 0xf7: - miditracklen -= mid_read_delta(h); - metalen = h->deltatime; - while( metalen > 0 ) { - midibyte[1] = mid_read_byte(h); - metalen--; - miditracklen--; - } - break; - case 0xff: // meta event - miditracklen -= mid_read_delta(h); - metalen = h->deltatime; - if( metalen > 21 ) metalen = 21; - if( metalen ) { - mmreadSBYTES(buf, metalen, h->mmf); - miditracklen -= metalen; - } - buf[metalen] = '\0'; - metalen = h->deltatime - metalen; - while( metalen > 0 ) { - midibyte[1] = mid_read_byte(h); - metalen--; - miditracklen--; - } - switch( midibyte[0] ) { - case 0x03: // type: track name - return DupStr(NULL, buf, strlen(buf)); - break; - case 0x2f: // type: end of track - miditracklen = 0; - break; - default: - break; - } - break; - default: - break; - } - break; - default: // no running status, just skip it... - break; - } - if( miditracklen < 1 && (runningstatus != 0xff || midibyte[0] != 0x2f) ) { - metalen = mmftell(h->mmf); - mmreadSBYTES(buf,4,h->mmf); - buf[4] = '\0'; - if( strcmp(buf,"MTrk") ) miditracklen = 0x7fffffff; - mmfseek(h->mmf,metalen,SEEK_SET); - } - } - } - return DupStr(NULL, "Untitled" ,8); -} - -MLOADER load_mid = -{ - "MID", - "Musical Instrument Digital Interface", - 0x30, - NULL, - MID_Test, - (void *(*)(void))MID_Init, - (void (*)(ML_HANDLE *))MID_Cleanup, - /* Every single loader seems to need one of these! */ - (BOOL (*)(ML_HANDLE *, UNIMOD *, MMSTREAM *))MID_Load, - MID_LoadTitle -}; -#endif diff --git a/lib/libmodplug/src/load_mod.cpp b/lib/libmodplug/src/load_mod.cpp deleted file mode 100644 index 57304ac51e..0000000000 --- a/lib/libmodplug/src/load_mod.cpp +++ /dev/null @@ -1,505 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque <olivierl@jps.net>, - * Adam Goode <adam@evdebs.org> (endian and char fixes for PPC) -*/ - -#include "stdafx.h" -#include "sndfile.h" -#include "tables.h" - -#ifdef _MSC_VER -//#pragma warning(disable:4244) -#endif - -////////////////////////////////////////////////////////// -// ProTracker / NoiseTracker MOD/NST file support - -void CSoundFile::ConvertModCommand(MODCOMMAND *m) const -//----------------------------------------------------- -{ - UINT command = m->command, param = m->param; - - switch(command) - { - case 0x00: if (param) command = CMD_ARPEGGIO; break; - case 0x01: command = CMD_PORTAMENTOUP; break; - case 0x02: command = CMD_PORTAMENTODOWN; break; - case 0x03: command = CMD_TONEPORTAMENTO; break; - case 0x04: command = CMD_VIBRATO; break; - case 0x05: command = CMD_TONEPORTAVOL; if (param & 0xF0) param &= 0xF0; break; - case 0x06: command = CMD_VIBRATOVOL; if (param & 0xF0) param &= 0xF0; break; - case 0x07: command = CMD_TREMOLO; break; - case 0x08: command = CMD_PANNING8; break; - case 0x09: command = CMD_OFFSET; break; - case 0x0A: command = CMD_VOLUMESLIDE; if (param & 0xF0) param &= 0xF0; break; - case 0x0B: command = CMD_POSITIONJUMP; break; - case 0x0C: command = CMD_VOLUME; break; - case 0x0D: command = CMD_PATTERNBREAK; param = ((param >> 4) * 10) + (param & 0x0F); break; - case 0x0E: command = CMD_MODCMDEX; break; - case 0x0F: command = (param <= (UINT)((m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) ? 0x1F : 0x20)) ? CMD_SPEED : CMD_TEMPO; - if ((param == 0xFF) && (m_nSamples == 15)) command = 0; break; - // Extension for XM extended effects - case 'G' - 55: command = CMD_GLOBALVOLUME; break; - case 'H' - 55: command = CMD_GLOBALVOLSLIDE; if (param & 0xF0) param &= 0xF0; break; - case 'K' - 55: command = CMD_KEYOFF; break; - case 'L' - 55: command = CMD_SETENVPOSITION; break; - case 'M' - 55: command = CMD_CHANNELVOLUME; break; - case 'N' - 55: command = CMD_CHANNELVOLSLIDE; break; - case 'P' - 55: command = CMD_PANNINGSLIDE; if (param & 0xF0) param &= 0xF0; break; - case 'R' - 55: command = CMD_RETRIG; break; - case 'T' - 55: command = CMD_TREMOR; break; - case 'X' - 55: command = CMD_XFINEPORTAUPDOWN; break; - case 'Y' - 55: command = CMD_PANBRELLO; break; - case 'Z' - 55: command = CMD_MIDI; break; - default: command = 0; - } - m->command = command; - m->param = param; -} - - -WORD CSoundFile::ModSaveCommand(const MODCOMMAND *m, BOOL bXM) const -//------------------------------------------------------------------ -{ - UINT command = m->command & 0x3F, param = m->param; - - switch(command) - { - case 0: command = param = 0; break; - case CMD_ARPEGGIO: command = 0; break; - case CMD_PORTAMENTOUP: - if (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_STM)) - { - if ((param & 0xF0) == 0xE0) { command=0x0E; param=((param & 0x0F) >> 2)|0x10; break; } - else if ((param & 0xF0) == 0xF0) { command=0x0E; param &= 0x0F; param|=0x10; break; } - } - command = 0x01; - break; - case CMD_PORTAMENTODOWN: - if (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_STM)) - { - if ((param & 0xF0) == 0xE0) { command=0x0E; param=((param & 0x0F) >> 2)|0x20; break; } - else if ((param & 0xF0) == 0xF0) { command=0x0E; param &= 0x0F; param|=0x20; break; } - } - command = 0x02; - break; - case CMD_TONEPORTAMENTO: command = 0x03; break; - case CMD_VIBRATO: command = 0x04; break; - case CMD_TONEPORTAVOL: command = 0x05; break; - case CMD_VIBRATOVOL: command = 0x06; break; - case CMD_TREMOLO: command = 0x07; break; - case CMD_PANNING8: - command = 0x08; - if (bXM) - { - if ((m_nType != MOD_TYPE_IT) && (m_nType != MOD_TYPE_XM) && (param <= 0x80)) - { - param <<= 1; - if (param > 255) param = 255; - } - } else - { - if ((m_nType == MOD_TYPE_IT) || (m_nType == MOD_TYPE_XM)) param >>= 1; - } - break; - case CMD_OFFSET: command = 0x09; break; - case CMD_VOLUMESLIDE: command = 0x0A; break; - case CMD_POSITIONJUMP: command = 0x0B; break; - case CMD_VOLUME: command = 0x0C; break; - case CMD_PATTERNBREAK: command = 0x0D; param = ((param / 10) << 4) | (param % 10); break; - case CMD_MODCMDEX: command = 0x0E; break; - case CMD_SPEED: command = 0x0F; if (param > 0x20) param = 0x20; break; - case CMD_TEMPO: if (param > 0x20) { command = 0x0F; break; } - case CMD_GLOBALVOLUME: command = 'G' - 55; break; - case CMD_GLOBALVOLSLIDE: command = 'H' - 55; break; - case CMD_KEYOFF: command = 'K' - 55; break; - case CMD_SETENVPOSITION: command = 'L' - 55; break; - case CMD_CHANNELVOLUME: command = 'M' - 55; break; - case CMD_CHANNELVOLSLIDE: command = 'N' - 55; break; - case CMD_PANNINGSLIDE: command = 'P' - 55; break; - case CMD_RETRIG: command = 'R' - 55; break; - case CMD_TREMOR: command = 'T' - 55; break; - case CMD_XFINEPORTAUPDOWN: command = 'X' - 55; break; - case CMD_PANBRELLO: command = 'Y' - 55; break; - case CMD_MIDI: command = 'Z' - 55; break; - case CMD_S3MCMDEX: - switch(param & 0xF0) - { - case 0x10: command = 0x0E; param = (param & 0x0F) | 0x30; break; - case 0x20: command = 0x0E; param = (param & 0x0F) | 0x50; break; - case 0x30: command = 0x0E; param = (param & 0x0F) | 0x40; break; - case 0x40: command = 0x0E; param = (param & 0x0F) | 0x70; break; - case 0x90: command = 'X' - 55; break; - case 0xB0: command = 0x0E; param = (param & 0x0F) | 0x60; break; - case 0xA0: - case 0x50: - case 0x70: - case 0x60: command = param = 0; break; - default: command = 0x0E; break; - } - break; - default: command = param = 0; - } - return (WORD)((command << 8) | (param)); -} - - -#pragma pack(1) - -typedef struct _MODSAMPLE -{ - CHAR name[22]; - WORD length; - BYTE finetune; - BYTE volume; - WORD loopstart; - WORD looplen; -} MODSAMPLE, *PMODSAMPLE; - -typedef struct _MODMAGIC -{ - BYTE nOrders; - BYTE nRestartPos; - BYTE Orders[128]; - char Magic[4]; // changed from CHAR -} MODMAGIC, *PMODMAGIC; - -#pragma pack() - -BOOL IsMagic(LPCSTR s1, LPCSTR s2) -{ - return ((*(DWORD *)s1) == (*(DWORD *)s2)) ? TRUE : FALSE; -} - - -BOOL CSoundFile::ReadMod(const BYTE *lpStream, DWORD dwMemLength) -//--------------------------------------------------------------- -{ - char s[1024]; // changed from CHAR - DWORD dwMemPos, dwTotalSampleLen; - PMODMAGIC pMagic; - UINT nErr; - - if ((!lpStream) || (dwMemLength < 0x600)) return FALSE; - dwMemPos = 20; - m_nSamples = 31; - m_nChannels = 4; - pMagic = (PMODMAGIC)(lpStream+dwMemPos+sizeof(MODSAMPLE)*31); - // Check Mod Magic - memcpy(s, pMagic->Magic, 4); - if ((IsMagic(s, "M.K.")) || (IsMagic(s, "M!K!")) - || (IsMagic(s, "M&K!")) || (IsMagic(s, "N.T."))) m_nChannels = 4; else - if ((IsMagic(s, "CD81")) || (IsMagic(s, "OKTA"))) m_nChannels = 8; else - if ((s[0]=='F') && (s[1]=='L') && (s[2]=='T') && (s[3]>='4') && (s[3]<='9')) m_nChannels = s[3] - '0'; else - if ((s[0]>='2') && (s[0]<='9') && (s[1]=='C') && (s[2]=='H') && (s[3]=='N')) m_nChannels = s[0] - '0'; else - if ((s[0]=='1') && (s[1]>='0') && (s[1]<='9') && (s[2]=='C') && (s[3]=='H')) m_nChannels = s[1] - '0' + 10; else - if ((s[0]=='2') && (s[1]>='0') && (s[1]<='9') && (s[2]=='C') && (s[3]=='H')) m_nChannels = s[1] - '0' + 20; else - if ((s[0]=='3') && (s[1]>='0') && (s[1]<='2') && (s[2]=='C') && (s[3]=='H')) m_nChannels = s[1] - '0' + 30; else - if ((s[0]=='T') && (s[1]=='D') && (s[2]=='Z') && (s[3]>='4') && (s[3]<='9')) m_nChannels = s[3] - '0'; else - if (IsMagic(s,"16CN")) m_nChannels = 16; else - if (IsMagic(s,"32CN")) m_nChannels = 32; else m_nSamples = 15; - // Load Samples - nErr = 0; - dwTotalSampleLen = 0; - for (UINT i=1; i<=m_nSamples; i++) - { - PMODSAMPLE pms = (PMODSAMPLE)(lpStream+dwMemPos); - MODINSTRUMENT *psmp = &Ins[i]; - UINT loopstart, looplen; - - memcpy(m_szNames[i], pms->name, 22); - m_szNames[i][22] = 0; - psmp->uFlags = 0; - psmp->nLength = bswapBE16(pms->length)*2; - dwTotalSampleLen += psmp->nLength; - psmp->nFineTune = MOD2XMFineTune(pms->finetune & 0x0F); - psmp->nVolume = 4*pms->volume; - if (psmp->nVolume > 256) { psmp->nVolume = 256; nErr++; } - psmp->nGlobalVol = 64; - psmp->nPan = 128; - loopstart = bswapBE16(pms->loopstart)*2; - looplen = bswapBE16(pms->looplen)*2; - // Fix loops - if ((looplen > 2) && (loopstart+looplen > psmp->nLength) - && (loopstart/2+looplen <= psmp->nLength)) - { - loopstart /= 2; - } - psmp->nLoopStart = loopstart; - psmp->nLoopEnd = loopstart + looplen; - if (psmp->nLength < 4) psmp->nLength = 0; - if (psmp->nLength) - { - UINT derr = 0; - if (psmp->nLoopStart >= psmp->nLength) { psmp->nLoopStart = psmp->nLength-1; derr|=1; } - if (psmp->nLoopEnd > psmp->nLength) { psmp->nLoopEnd = psmp->nLength; derr |= 1; } - if (psmp->nLoopStart > psmp->nLoopEnd) derr |= 1; - if ((psmp->nLoopStart > psmp->nLoopEnd) || (psmp->nLoopEnd <= 8) - || (psmp->nLoopEnd - psmp->nLoopStart <= 4)) - { - psmp->nLoopStart = 0; - psmp->nLoopEnd = 0; - } - if (psmp->nLoopEnd > psmp->nLoopStart) - { - psmp->uFlags |= CHN_LOOP; - } - } - dwMemPos += sizeof(MODSAMPLE); - } - if ((m_nSamples == 15) && (dwTotalSampleLen > dwMemLength * 4)) return FALSE; - pMagic = (PMODMAGIC)(lpStream+dwMemPos); - dwMemPos += sizeof(MODMAGIC); - if (m_nSamples == 15) dwMemPos -= 4; - memset(Order, 0,sizeof(Order)); - memcpy(Order, pMagic->Orders, 128); - - UINT nbp, nbpbuggy, nbpbuggy2, norders; - - norders = pMagic->nOrders; - if ((!norders) || (norders > 0x80)) - { - norders = 0x80; - while ((norders > 1) && (!Order[norders-1])) norders--; - } - nbpbuggy = 0; - nbpbuggy2 = 0; - nbp = 0; - for (UINT iord=0; iord<128; iord++) - { - UINT i = Order[iord]; - if ((i < 0x80) && (nbp <= i)) - { - nbp = i+1; - if (iord<norders) nbpbuggy = nbp; - } - if (i >= nbpbuggy2) nbpbuggy2 = i+1; - } - for (UINT iend=norders; iend<MAX_ORDERS; iend++) Order[iend] = 0xFF; - norders--; - m_nRestartPos = pMagic->nRestartPos; - if (m_nRestartPos >= 0x78) m_nRestartPos = 0; - if (m_nRestartPos + 1 >= (UINT)norders) m_nRestartPos = 0; - if (!nbp) return FALSE; - DWORD dwWowTest = dwTotalSampleLen+dwMemPos; - if ((IsMagic(pMagic->Magic, "M.K.")) && (dwWowTest + nbp*8*256 == dwMemLength)) m_nChannels = 8; - if ((nbp != nbpbuggy) && (dwWowTest + nbp*m_nChannels*256 != dwMemLength)) - { - if (dwWowTest + nbpbuggy*m_nChannels*256 == dwMemLength) nbp = nbpbuggy; - else nErr += 8; - } else - if ((nbpbuggy2 > nbp) && (dwWowTest + nbpbuggy2*m_nChannels*256 == dwMemLength)) - { - nbp = nbpbuggy2; - } - if ((dwWowTest < 0x600) || (dwWowTest > dwMemLength)) nErr += 8; - if ((m_nSamples == 15) && (nErr >= 16)) return FALSE; - // Default settings - m_nType = MOD_TYPE_MOD; - m_nDefaultSpeed = 6; - m_nDefaultTempo = 125; - m_nMinPeriod = 14 << 2; - m_nMaxPeriod = 3424 << 2; - memcpy(m_szNames, lpStream, 20); - // Setting channels pan - for (UINT ich=0; ich<m_nChannels; ich++) - { - ChnSettings[ich].nVolume = 64; - if (gdwSoundSetup & SNDMIX_MAXDEFAULTPAN) - ChnSettings[ich].nPan = (((ich&3)==1) || ((ich&3)==2)) ? 256 : 0; - else - ChnSettings[ich].nPan = (((ich&3)==1) || ((ich&3)==2)) ? 0xC0 : 0x40; - } - // Reading channels - for (UINT ipat=0; ipat<nbp; ipat++) - { - if (ipat < MAX_PATTERNS) - { - if ((Patterns[ipat] = AllocatePattern(64, m_nChannels)) == NULL) break; - PatternSize[ipat] = 64; - if (dwMemPos + m_nChannels*256 >= dwMemLength) break; - MODCOMMAND *m = Patterns[ipat]; - LPCBYTE p = lpStream + dwMemPos; - for (UINT j=m_nChannels*64; j; m++,p+=4,j--) - { - BYTE A0=p[0], A1=p[1], A2=p[2], A3=p[3]; - UINT n = ((((UINT)A0 & 0x0F) << 8) | (A1)); - if ((n) && (n != 0xFFF)) m->note = GetNoteFromPeriod(n << 2); - m->instr = ((UINT)A2 >> 4) | (A0 & 0x10); - m->command = A2 & 0x0F; - m->param = A3; - if ((m->command) || (m->param)) ConvertModCommand(m); - } - } - dwMemPos += m_nChannels*256; - } - // Reading instruments - DWORD dwErrCheck = 0; - for (UINT ismp=1; ismp<=m_nSamples; ismp++) if (Ins[ismp].nLength) - { - LPSTR p = (LPSTR)(lpStream+dwMemPos); - UINT flags = 0; - if (dwMemPos + 5 >= dwMemLength) break; - if (!strnicmp(p, "ADPCM", 5)) - { - flags = 3; - p += 5; - dwMemPos += 5; - } - DWORD dwSize = ReadSample(&Ins[ismp], flags, p, dwMemLength - dwMemPos); - if (dwSize) - { - dwMemPos += dwSize; - dwErrCheck++; - } - } -#ifdef MODPLUG_TRACKER - return TRUE; -#else - return (dwErrCheck) ? TRUE : FALSE; -#endif -} - - -#ifndef MODPLUG_NO_FILESAVE - -#ifdef _MSC_VER -#pragma warning(disable:4100) -#endif - -BOOL CSoundFile::SaveMod(LPCSTR lpszFileName, UINT nPacking) -//---------------------------------------------------------- -{ - BYTE insmap[32]; - UINT inslen[32]; - BYTE bTab[32]; - BYTE ord[128]; - FILE *f; - - if ((!m_nChannels) || (!lpszFileName)) return FALSE; - if ((f = fopen(lpszFileName, "wb")) == NULL) return FALSE; - memset(ord, 0, sizeof(ord)); - memset(inslen, 0, sizeof(inslen)); - if (m_nInstruments) - { - memset(insmap, 0, sizeof(insmap)); - for (UINT i=1; i<32; i++) if (Headers[i]) - { - for (UINT j=0; j<128; j++) if (Headers[i]->Keyboard[j]) - { - insmap[i] = Headers[i]->Keyboard[j]; - break; - } - } - } else - { - for (UINT i=0; i<32; i++) insmap[i] = (BYTE)i; - } - // Writing song name - fwrite(m_szNames, 20, 1, f); - // Writing instrument definition - for (UINT iins=1; iins<=31; iins++) - { - MODINSTRUMENT *pins = &Ins[insmap[iins]]; - memcpy(bTab, m_szNames[iins],22); - inslen[iins] = pins->nLength; - if (inslen[iins] > 0x1fff0) inslen[iins] = 0x1fff0; - bTab[22] = inslen[iins] >> 9; - bTab[23] = inslen[iins] >> 1; - if (pins->RelativeTone < 0) bTab[24] = 0x08; else - if (pins->RelativeTone > 0) bTab[24] = 0x07; else - bTab[24] = (BYTE)XM2MODFineTune(pins->nFineTune); - bTab[25] = pins->nVolume >> 2; - bTab[26] = pins->nLoopStart >> 9; - bTab[27] = pins->nLoopStart >> 1; - bTab[28] = (pins->nLoopEnd - pins->nLoopStart) >> 9; - bTab[29] = (pins->nLoopEnd - pins->nLoopStart) >> 1; - fwrite(bTab, 30, 1, f); - } - // Writing number of patterns - UINT nbp=0, norders=128; - for (UINT iord=0; iord<128; iord++) - { - if (Order[iord] == 0xFF) - { - norders = iord; - break; - } - if ((Order[iord] < 0x80) && (nbp<=Order[iord])) nbp = Order[iord]+1; - } - bTab[0] = norders; - bTab[1] = m_nRestartPos; - fwrite(bTab, 2, 1, f); - // Writing pattern list - if (norders) memcpy(ord, Order, norders); - fwrite(ord, 128, 1, f); - // Writing signature - if (m_nChannels == 4) - lstrcpy((LPSTR)&bTab, "M.K."); - else - wsprintf((LPSTR)&bTab, "%luCHN", m_nChannels); - fwrite(bTab, 4, 1, f); - // Writing patterns - for (UINT ipat=0; ipat<nbp; ipat++) if (Patterns[ipat]) - { - BYTE s[64*4]; - MODCOMMAND *m = Patterns[ipat]; - for (UINT i=0; i<64; i++) if (i < PatternSize[ipat]) - { - LPBYTE p=s; - for (UINT c=0; c<m_nChannels; c++,p+=4,m++) - { - UINT param = ModSaveCommand(m, FALSE); - UINT command = param >> 8; - param &= 0xFF; - if (command > 0x0F) command = param = 0; - if ((m->vol >= 0x10) && (m->vol <= 0x50) && (!command) && (!param)) { command = 0x0C; param = m->vol - 0x10; } - UINT period = m->note; - if (period) - { - if (period < 37) period = 37; - period -= 37; - if (period >= 6*12) period = 6*12-1; - period = ProTrackerPeriodTable[period]; - } - UINT instr = (m->instr > 31) ? 0 : m->instr; - p[0] = ((period >> 8) & 0x0F) | (instr & 0x10); - p[1] = period & 0xFF; - p[2] = ((instr & 0x0F) << 4) | (command & 0x0F); - p[3] = param; - } - fwrite(s, m_nChannels, 4, f); - } else - { - memset(s, 0, m_nChannels*4); - fwrite(s, m_nChannels, 4, f); - } - } - // Writing instruments - for (UINT ismpd=1; ismpd<=31; ismpd++) if (inslen[ismpd]) - { - MODINSTRUMENT *pins = &Ins[insmap[ismpd]]; - UINT flags = RS_PCM8S; -#ifndef NO_PACKING - if (!(pins->uFlags & (CHN_16BIT|CHN_STEREO))) - { - if ((nPacking) && (CanPackSample((char *)pins->pSample, inslen[ismpd], nPacking))) - { - fwrite("ADPCM", 1, 5, f); - flags = RS_ADPCM4; - } - } -#endif - WriteSample(f, pins, flags, inslen[ismpd]); - } - fclose(f); - return TRUE; -} - -#ifdef _MSC_VER -#pragma warning(default:4100) -#endif - -#endif // MODPLUG_NO_FILESAVE diff --git a/lib/libmodplug/src/load_mt2.cpp b/lib/libmodplug/src/load_mt2.cpp deleted file mode 100644 index 208154f6e8..0000000000 --- a/lib/libmodplug/src/load_mt2.cpp +++ /dev/null @@ -1,635 +0,0 @@ -#include "stdafx.h" -#include "sndfile.h" - -//#define MT2DEBUG - -#pragma pack(1) - -typedef struct _MT2FILEHEADER -{ - DWORD dwMT20; // 0x3032544D "MT20" - DWORD dwSpecial; - WORD wVersion; - CHAR szTrackerName[32]; // "MadTracker 2.0" - CHAR szSongName[64]; - WORD nOrders; - WORD wRestart; - WORD wPatterns; - WORD wChannels; - WORD wSamplesPerTick; - BYTE bTicksPerLine; - BYTE bLinesPerBeat; - DWORD fulFlags; // b0=packed patterns - WORD wInstruments; - WORD wSamples; - BYTE Orders[256]; -} MT2FILEHEADER; - -typedef struct _MT2PATTERN -{ - WORD wLines; - DWORD wDataLen; -} MT2PATTERN; - -typedef struct _MT2COMMAND -{ - BYTE note; // 0=nothing, 97=note off - BYTE instr; - BYTE vol; - BYTE pan; - BYTE fxcmd; - BYTE fxparam1; - BYTE fxparam2; -} MT2COMMAND; - -typedef struct _MT2DRUMSDATA -{ - WORD wDrumPatterns; - WORD wDrumSamples[8]; - BYTE DrumPatternOrder[256]; -} MT2DRUMSDATA; - -typedef struct _MT2AUTOMATION -{ - DWORD dwFlags; - DWORD dwEffectId; - DWORD nEnvPoints; -} MT2AUTOMATION; - -typedef struct _MT2INSTRUMENT -{ - CHAR szName[32]; - DWORD dwDataLen; - WORD wSamples; - BYTE GroupsMapping[96]; - BYTE bVibType; - BYTE bVibSweep; - BYTE bVibDepth; - BYTE bVibRate; - WORD wFadeOut; - WORD wNNA; - WORD wInstrFlags; - WORD wEnvFlags1; - WORD wEnvFlags2; -} MT2INSTRUMENT; - -typedef struct _MT2ENVELOPE -{ - BYTE nFlags; - BYTE nPoints; - BYTE nSustainPos; - BYTE nLoopStart; - BYTE nLoopEnd; - BYTE bReserved[3]; - BYTE EnvData[64]; -} MT2ENVELOPE; - -typedef struct _MT2SYNTH -{ - BYTE nSynthId; - BYTE nFxId; - WORD wCutOff; - BYTE nResonance; - BYTE nAttack; - BYTE nDecay; - BYTE bReserved[25]; -} MT2SYNTH; - -typedef struct _MT2SAMPLE -{ - CHAR szName[32]; - DWORD dwDataLen; - DWORD dwLength; - DWORD dwFrequency; - BYTE nQuality; - BYTE nChannels; - BYTE nFlags; - BYTE nLoop; - DWORD dwLoopStart; - DWORD dwLoopEnd; - WORD wVolume; - BYTE nPan; - BYTE nBaseNote; - WORD wSamplesPerBeat; -} MT2SAMPLE; - -typedef struct _MT2GROUP -{ - BYTE nSmpNo; - BYTE nVolume; // 0-128 - BYTE nFinePitch; - BYTE Reserved[5]; -} MT2GROUP; - -#pragma pack() - - -static VOID ConvertMT2Command(CSoundFile *that, MODCOMMAND *m, MT2COMMAND *p) -//--------------------------------------------------------------------------- -{ - // Note - m->note = 0; - if (p->note) m->note = (p->note > 96) ? 0xFF : p->note+12; - // Instrument - m->instr = p->instr; - // Volume Column - if ((p->vol >= 0x10) && (p->vol <= 0x90)) - { - m->volcmd = VOLCMD_VOLUME; - m->vol = (p->vol - 0x10) >> 1; - } else - if ((p->vol >= 0xA0) && (p->vol <= 0xAF)) - { - m->volcmd = VOLCMD_VOLSLIDEDOWN; - m->vol = (p->vol & 0x0f); - } else - if ((p->vol >= 0xB0) && (p->vol <= 0xBF)) - { - m->volcmd = VOLCMD_VOLSLIDEUP; - m->vol = (p->vol & 0x0f); - } else - if ((p->vol >= 0xC0) && (p->vol <= 0xCF)) - { - m->volcmd = VOLCMD_FINEVOLDOWN; - m->vol = (p->vol & 0x0f); - } else - if ((p->vol >= 0xD0) && (p->vol <= 0xDF)) - { - m->volcmd = VOLCMD_FINEVOLUP; - m->vol = (p->vol & 0x0f); - } else - { - m->volcmd = 0; - m->vol = 0; - } - // Effects - m->command = 0; - m->param = 0; - if ((p->fxcmd) || (p->fxparam1) || (p->fxparam2)) - { - if (!p->fxcmd) - { - m->command = p->fxparam2; - m->param = p->fxparam1; - that->ConvertModCommand(m); - } else - { - // TODO: MT2 Effects - } - } -} - - -BOOL CSoundFile::ReadMT2(LPCBYTE lpStream, DWORD dwMemLength) -//----------------------------------------------------------- -{ - MT2FILEHEADER *pfh = (MT2FILEHEADER *)lpStream; - DWORD dwMemPos, dwDrumDataPos, dwExtraDataPos; - UINT nDrumDataLen, nExtraDataLen; - MT2DRUMSDATA *pdd; - MT2INSTRUMENT *InstrMap[255]; - MT2SAMPLE *SampleMap[256]; - - if ((!lpStream) || (dwMemLength < sizeof(MT2FILEHEADER)) - || (pfh->dwMT20 != 0x3032544D) - || (pfh->wVersion < 0x0200) || (pfh->wVersion >= 0x0300) - || (pfh->wChannels < 4) || (pfh->wChannels > 64)) return FALSE; - pdd = NULL; - m_nType = MOD_TYPE_MT2; - m_nChannels = pfh->wChannels; - m_nRestartPos = pfh->wRestart; - m_nDefaultSpeed = pfh->bTicksPerLine; - m_nDefaultTempo = 125; - if ((pfh->wSamplesPerTick > 100) && (pfh->wSamplesPerTick < 5000)) - { - m_nDefaultTempo = 110250 / pfh->wSamplesPerTick; - } - for (UINT iOrd=0; iOrd<MAX_ORDERS; iOrd++) - { - Order[iOrd] = (BYTE)((iOrd < pfh->nOrders) ? pfh->Orders[iOrd] : 0xFF); - } - memcpy(m_szNames[0], pfh->szSongName, 32); - m_szNames[0][31] = 0; - dwMemPos = sizeof(MT2FILEHEADER); - nDrumDataLen = *(WORD *)(lpStream + dwMemPos); - dwDrumDataPos = dwMemPos + 2; - if (nDrumDataLen >= 2) pdd = (MT2DRUMSDATA *)(lpStream+dwDrumDataPos); - dwMemPos += 2 + nDrumDataLen; -#ifdef MT2DEBUG - - Log("MT2 v%03X: \"%s\" (flags=%04X)\n", pfh->wVersion, m_szNames[0], pfh->fulFlags); - Log("%d Channels, %d Patterns, %d Instruments, %d Samples\n", pfh->wChannels, pfh->wPatterns, pfh->wInstruments, pfh->wSamples); - Log("Drum Data: %d bytes @%04X\n", nDrumDataLen, dwDrumDataPos); -#endif - if (dwMemPos >= dwMemLength-12) return TRUE; - if (!*(DWORD *)(lpStream+dwMemPos)) dwMemPos += 4; - if (!*(DWORD *)(lpStream+dwMemPos)) dwMemPos += 4; - nExtraDataLen = *(DWORD *)(lpStream+dwMemPos); - dwExtraDataPos = dwMemPos + 4; - dwMemPos += 4; -#ifdef MT2DEBUG - Log("Extra Data: %d bytes @%04X\n", nExtraDataLen, dwExtraDataPos); -#endif - if (dwMemPos + nExtraDataLen >= dwMemLength) return TRUE; - while (dwMemPos+8 < dwExtraDataPos + nExtraDataLen) - { - DWORD dwId = *(DWORD *)(lpStream+dwMemPos); - DWORD dwLen = *(DWORD *)(lpStream+dwMemPos+4); - dwMemPos += 8; - if (dwMemPos + dwLen > dwMemLength) return TRUE; -#ifdef MT2DEBUG - CHAR s[5]; - memcpy(s, &dwId, 4); - s[4] = 0; - Log("pos=0x%04X: %s: %d bytes\n", dwMemPos-8, s, dwLen); -#endif - switch(dwId) - { - // MSG - case 0x0047534D: - if ((dwLen > 3) && (!m_lpszSongComments)) - { - DWORD nTxtLen = dwLen; - if (nTxtLen > 32000) nTxtLen = 32000; - m_lpszSongComments = new char[nTxtLen]; // changed from CHAR - if (m_lpszSongComments) - { - memcpy(m_lpszSongComments, lpStream+dwMemPos+1, nTxtLen-1); - m_lpszSongComments[nTxtLen-1] = 0; - } - } - break; - // SUM -> author name (or "Unregistered") - // TMAP - // TRKS - case 0x534b5254: - break; - } - dwMemPos += dwLen; - } - // Load Patterns - dwMemPos = dwExtraDataPos + nExtraDataLen; - for (UINT iPat=0; iPat<pfh->wPatterns; iPat++) if (dwMemPos < dwMemLength-6) - { - MT2PATTERN *pmp = (MT2PATTERN *)(lpStream+dwMemPos); - UINT wDataLen = (pmp->wDataLen + 1) & ~1; - dwMemPos += 6; - if (dwMemPos + wDataLen > dwMemLength) break; - UINT nLines = pmp->wLines; - if ((iPat < MAX_PATTERNS) && (nLines > 0) && (nLines <= 256)) - { - #ifdef MT2DEBUG - Log("Pattern #%d @%04X: %d lines, %d bytes\n", iPat, dwMemPos-6, nLines, pmp->wDataLen); - #endif - PatternSize[iPat] = nLines; - Patterns[iPat] = AllocatePattern(nLines, m_nChannels); - if (!Patterns[iPat]) return TRUE; - MODCOMMAND *m = Patterns[iPat]; - UINT len = wDataLen; - if (pfh->fulFlags & 1) // Packed Patterns - { - BYTE *p = (BYTE *)(lpStream+dwMemPos); - UINT pos = 0, row=0, ch=0; - while (pos < len) - { - MT2COMMAND cmd; - UINT infobyte = p[pos++]; - UINT rptcount = 0; - if (infobyte == 0xff) - { - rptcount = p[pos++]; - infobyte = p[pos++]; - #if 0 - Log("(%d.%d) FF(%02X).%02X\n", row, ch, rptcount, infobyte); - } else - { - Log("(%d.%d) %02X\n", row, ch, infobyte); - #endif - } - if (infobyte & 0x7f) - { - UINT patpos = row*m_nChannels+ch; - cmd.note = cmd.instr = cmd.vol = cmd.pan = cmd.fxcmd = cmd.fxparam1 = cmd.fxparam2 = 0; - if (infobyte & 1) cmd.note = p[pos++]; - if (infobyte & 2) cmd.instr = p[pos++]; - if (infobyte & 4) cmd.vol = p[pos++]; - if (infobyte & 8) cmd.pan = p[pos++]; - if (infobyte & 16) cmd.fxcmd = p[pos++]; - if (infobyte & 32) cmd.fxparam1 = p[pos++]; - if (infobyte & 64) cmd.fxparam2 = p[pos++]; - #ifdef MT2DEBUG - if (cmd.fxcmd) - { - Log("(%d.%d) MT2 FX=%02X.%02X.%02X\n", row, ch, cmd.fxcmd, cmd.fxparam1, cmd.fxparam2); - } - #endif - ConvertMT2Command(this, &m[patpos], &cmd); - } - row += rptcount+1; - while (row >= nLines) { row-=nLines; ch++; } - if (ch >= m_nChannels) break; - } - } else - { - MT2COMMAND *p = (MT2COMMAND *)(lpStream+dwMemPos); - UINT n = 0; - while ((len > sizeof(MT2COMMAND)) && (n < m_nChannels*nLines)) - { - ConvertMT2Command(this, m, p); - len -= sizeof(MT2COMMAND); - n++; - p++; - m++; - } - } - } - dwMemPos += wDataLen; - } - // Skip Drum Patterns - if (pdd) - { - #ifdef MT2DEBUG - Log("%d Drum Patterns at offset 0x%08X\n", pdd->wDrumPatterns, dwMemPos); - #endif - for (UINT iDrm=0; iDrm<pdd->wDrumPatterns; iDrm++) - { - if (dwMemPos > dwMemLength-2) return TRUE; - UINT nLines = *(WORD *)(lpStream+dwMemPos); - #ifdef MT2DEBUG - if (nLines != 64) Log("Drum Pattern %d: %d Lines @%04X\n", iDrm, nLines, dwMemPos); - #endif - dwMemPos += 2 + nLines * 32; - } - } - // Automation - if (pfh->fulFlags & 2) - { - #ifdef MT2DEBUG - Log("Automation at offset 0x%08X\n", dwMemPos); - #endif - UINT nAutoCount = m_nChannels; - if (pfh->fulFlags & 0x10) nAutoCount++; // Master Automation - if ((pfh->fulFlags & 0x08) && (pdd)) nAutoCount += 8; // Drums Automation - nAutoCount *= pfh->wPatterns; - for (UINT iAuto=0; iAuto<nAutoCount; iAuto++) - { - if (dwMemPos+12 >= dwMemLength) return TRUE; - MT2AUTOMATION *pma = (MT2AUTOMATION *)(lpStream+dwMemPos); - dwMemPos += (pfh->wVersion <= 0x201) ? 4 : 8; - for (UINT iEnv=0; iEnv<14; iEnv++) - { - if (pma->dwFlags & (1 << iEnv)) - { - #ifdef MT2DEBUG - UINT nPoints = *(DWORD *)(lpStream+dwMemPos); - Log(" Env[%d/%d] %04X @%04X: %d points\n", iAuto, nAutoCount, 1 << iEnv, dwMemPos-8, nPoints); - #endif - dwMemPos += 260; - } - } - } - } - // Load Instruments -#ifdef MT2DEBUG - Log("Loading instruments at offset 0x%08X\n", dwMemPos); -#endif - memset(InstrMap, 0, sizeof(InstrMap)); - m_nInstruments = (pfh->wInstruments < MAX_INSTRUMENTS) ? pfh->wInstruments : MAX_INSTRUMENTS-1; - for (UINT iIns=1; iIns<=255; iIns++) - { - if (dwMemPos+36 > dwMemLength) return TRUE; - MT2INSTRUMENT *pmi = (MT2INSTRUMENT *)(lpStream+dwMemPos); - INSTRUMENTHEADER *penv = NULL; - if (iIns <= m_nInstruments) - { - penv = new INSTRUMENTHEADER; - Headers[iIns] = penv; - if (penv) - { - memset(penv, 0, sizeof(INSTRUMENTHEADER)); - memcpy(penv->name, pmi->szName, 32); - penv->nGlobalVol = 64; - penv->nPan = 128; - for (UINT i=0; i<NOTE_MAX; i++) - { - penv->NoteMap[i] = i+1; - } - } - } - #ifdef MT2DEBUG - if (iIns <= pfh->wInstruments) Log(" Instrument #%d at offset %04X: %d bytes\n", iIns, dwMemPos, pmi->dwDataLen); - #endif - if (((LONG)pmi->dwDataLen > 0) && (dwMemPos + pmi->dwDataLen + 40 <= dwMemLength)) - { - InstrMap[iIns-1] = pmi; - if (penv) - { - penv->nFadeOut = pmi->wFadeOut; - penv->nNNA = pmi->wNNA & 3; - penv->nDCT = (pmi->wNNA>>8) & 3; - penv->nDNA = (pmi->wNNA>>12) & 3; - MT2ENVELOPE *pehdr[4]; - WORD *pedata[4]; - if (pfh->wVersion <= 0x201) - { - DWORD dwEnvPos = dwMemPos + sizeof(MT2INSTRUMENT) - 4; - pehdr[0] = (MT2ENVELOPE *)(lpStream+dwEnvPos); - pehdr[1] = (MT2ENVELOPE *)(lpStream+dwEnvPos+8); - pehdr[2] = pehdr[3] = NULL; - pedata[0] = (WORD *)(lpStream+dwEnvPos+16); - pedata[1] = (WORD *)(lpStream+dwEnvPos+16+64); - pedata[2] = pedata[3] = NULL; - } else - { - DWORD dwEnvPos = dwMemPos + sizeof(MT2INSTRUMENT); - for (UINT i=0; i<4; i++) - { - if (pmi->wEnvFlags1 & (1<<i)) - { - pehdr[i] = (MT2ENVELOPE *)(lpStream+dwEnvPos); - pedata[i] = (WORD *)pehdr[i]->EnvData; - dwEnvPos += sizeof(MT2ENVELOPE); - } else - { - pehdr[i] = NULL; - pedata[i] = NULL; - } - } - } - // Load envelopes - for (UINT iEnv=0; iEnv<4; iEnv++) if (pehdr[iEnv]) - { - MT2ENVELOPE *pme = pehdr[iEnv]; - WORD *pEnvPoints = NULL; - BYTE *pEnvData = NULL; - #ifdef MT2DEBUG - Log(" Env %d.%d @%04X: %d points\n", iIns, iEnv, (UINT)(((BYTE *)pme)-lpStream), pme->nPoints); - #endif - switch(iEnv) - { - // Volume Envelope - case 0: - if (pme->nFlags & 1) penv->dwFlags |= ENV_VOLUME; - if (pme->nFlags & 2) penv->dwFlags |= ENV_VOLSUSTAIN; - if (pme->nFlags & 4) penv->dwFlags |= ENV_VOLLOOP; - penv->nVolEnv = (pme->nPoints > 16) ? 16 : pme->nPoints; - penv->nVolSustainBegin = penv->nVolSustainEnd = pme->nSustainPos; - penv->nVolLoopStart = pme->nLoopStart; - penv->nVolLoopEnd = pme->nLoopEnd; - pEnvPoints = penv->VolPoints; - pEnvData = penv->VolEnv; - break; - - // Panning Envelope - case 1: - if (pme->nFlags & 1) penv->dwFlags |= ENV_PANNING; - if (pme->nFlags & 2) penv->dwFlags |= ENV_PANSUSTAIN; - if (pme->nFlags & 4) penv->dwFlags |= ENV_PANLOOP; - penv->nPanEnv = (pme->nPoints > 16) ? 16 : pme->nPoints; - penv->nPanSustainBegin = penv->nPanSustainEnd = pme->nSustainPos; - penv->nPanLoopStart = pme->nLoopStart; - penv->nPanLoopEnd = pme->nLoopEnd; - pEnvPoints = penv->PanPoints; - pEnvData = penv->PanEnv; - break; - - // Pitch/Filter envelope - default: - if (pme->nFlags & 1) penv->dwFlags |= (iEnv==3) ? (ENV_PITCH|ENV_FILTER) : ENV_PITCH; - if (pme->nFlags & 2) penv->dwFlags |= ENV_PITCHSUSTAIN; - if (pme->nFlags & 4) penv->dwFlags |= ENV_PITCHLOOP; - penv->nPitchEnv = (pme->nPoints > 16) ? 16 : pme->nPoints; - penv->nPitchSustainBegin = penv->nPitchSustainEnd = pme->nSustainPos; - penv->nPitchLoopStart = pme->nLoopStart; - penv->nPitchLoopEnd = pme->nLoopEnd; - pEnvPoints = penv->PitchPoints; - pEnvData = penv->PitchEnv; - } - // Envelope data - if ((pEnvPoints) && (pEnvData) && (pedata[iEnv])) - { - WORD *psrc = pedata[iEnv]; - for (UINT i=0; i<16; i++) - { - pEnvPoints[i] = psrc[i*2]; - pEnvData[i] = (BYTE)psrc[i*2+1]; - } - } - } - } - dwMemPos += pmi->dwDataLen + 36; - if (pfh->wVersion > 0x201) dwMemPos += 4; // ? - } else - { - dwMemPos += 36; - } - } -#ifdef MT2DEBUG - Log("Loading samples at offset 0x%08X\n", dwMemPos); -#endif - memset(SampleMap, 0, sizeof(SampleMap)); - m_nSamples = (pfh->wSamples < MAX_SAMPLES) ? pfh->wSamples : MAX_SAMPLES-1; - for (UINT iSmp=1; iSmp<=256; iSmp++) - { - if (dwMemPos+36 > dwMemLength) return TRUE; - MT2SAMPLE *pms = (MT2SAMPLE *)(lpStream+dwMemPos); - #ifdef MT2DEBUG - if (iSmp <= m_nSamples) Log(" Sample #%d at offset %04X: %d bytes\n", iSmp, dwMemPos, pms->dwDataLen); - #endif - if (iSmp < MAX_SAMPLES) - { - memcpy(m_szNames[iSmp], pms->szName, 32); - } - if (pms->dwDataLen > 0) - { - SampleMap[iSmp-1] = pms; - if (iSmp < MAX_SAMPLES) - { - MODINSTRUMENT *psmp = &Ins[iSmp]; - psmp->nGlobalVol = 64; - psmp->nVolume = (pms->wVolume >> 7); - psmp->nPan = (pms->nPan == 0x80) ? 128 : (pms->nPan^0x80); - psmp->nLength = pms->dwLength; - psmp->nC4Speed = pms->dwFrequency; - psmp->nLoopStart = pms->dwLoopStart; - psmp->nLoopEnd = pms->dwLoopEnd; - FrequencyToTranspose(psmp); - psmp->RelativeTone -= pms->nBaseNote - 49; - psmp->nC4Speed = TransposeToFrequency(psmp->RelativeTone, psmp->nFineTune); - if (pms->nQuality == 2) { psmp->uFlags |= CHN_16BIT; psmp->nLength >>= 1; } - if (pms->nChannels == 2) { psmp->nLength >>= 1; } - if (pms->nLoop == 1) psmp->uFlags |= CHN_LOOP; - if (pms->nLoop == 2) psmp->uFlags |= CHN_LOOP|CHN_PINGPONGLOOP; - } - dwMemPos += pms->dwDataLen + 36; - } else - { - dwMemPos += 36; - } - } -#ifdef MT2DEBUG - Log("Loading groups at offset 0x%08X\n", dwMemPos); -#endif - for (UINT iMap=0; iMap<255; iMap++) if (InstrMap[iMap]) - { - if (dwMemPos+8 > dwMemLength) return TRUE; - MT2INSTRUMENT *pmi = InstrMap[iMap]; - INSTRUMENTHEADER *penv = NULL; - if (iMap<m_nInstruments) penv = Headers[iMap+1]; - for (UINT iGrp=0; iGrp<pmi->wSamples; iGrp++) - { - if (penv) - { - MT2GROUP *pmg = (MT2GROUP *)(lpStream+dwMemPos); - for (UINT i=0; i<96; i++) - { - if (pmi->GroupsMapping[i] == iGrp) - { - UINT nSmp = pmg->nSmpNo+1; - penv->Keyboard[i+12] = (BYTE)nSmp; - if (nSmp <= m_nSamples) - { - Ins[nSmp].nVibType = pmi->bVibType; - Ins[nSmp].nVibSweep = pmi->bVibSweep; - Ins[nSmp].nVibDepth = pmi->bVibDepth; - Ins[nSmp].nVibRate = pmi->bVibRate; - } - } - } - } - dwMemPos += 8; - } - } -#ifdef MT2DEBUG - Log("Loading sample data at offset 0x%08X\n", dwMemPos); -#endif - for (UINT iData=0; iData<256; iData++) if ((iData < m_nSamples) && (SampleMap[iData])) - { - MT2SAMPLE *pms = SampleMap[iData]; - MODINSTRUMENT *psmp = &Ins[iData+1]; - if (!(pms->nFlags & 5)) - { - if (psmp->nLength > 0) - { - #ifdef MT2DEBUG - Log(" Reading sample #%d at offset 0x%04X (len=%d)\n", iData+1, dwMemPos, psmp->nLength); - #endif - UINT rsflags; - - if (pms->nChannels == 2) - rsflags = (psmp->uFlags & CHN_16BIT) ? RS_STPCM16D : RS_STPCM8D; - else - rsflags = (psmp->uFlags & CHN_16BIT) ? RS_PCM16D : RS_PCM8D; - - dwMemPos += ReadSample(psmp, rsflags, (LPCSTR)(lpStream+dwMemPos), dwMemLength-dwMemPos); - } - } else - if (dwMemPos+4 < dwMemLength) - { - UINT nNameLen = *(DWORD *)(lpStream+dwMemPos); - dwMemPos += nNameLen + 16; - } - if (dwMemPos+4 >= dwMemLength) break; - } - return TRUE; -} diff --git a/lib/libmodplug/src/load_mtm.cpp b/lib/libmodplug/src/load_mtm.cpp deleted file mode 100644 index f5f0299e23..0000000000 --- a/lib/libmodplug/src/load_mtm.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque <olivierl@jps.net> -*/ - -#include "stdafx.h" -#include "sndfile.h" - -//#pragma warning(disable:4244) - -////////////////////////////////////////////////////////// -// MTM file support (import only) - -#pragma pack(1) - - -typedef struct tagMTMSAMPLE -{ - char samplename[22]; // changed from CHAR - DWORD length; - DWORD reppos; - DWORD repend; - CHAR finetune; - BYTE volume; - BYTE attribute; -} MTMSAMPLE; - - -typedef struct tagMTMHEADER -{ - char id[4]; // MTM file marker + version // changed from CHAR - char songname[20]; // ASCIIZ songname // changed from CHAR - WORD numtracks; // number of tracks saved - BYTE lastpattern; // last pattern number saved - BYTE lastorder; // last order number to play (songlength-1) - WORD commentsize; // length of comment field - BYTE numsamples; // number of samples saved - BYTE attribute; // attribute byte (unused) - BYTE beatspertrack; - BYTE numchannels; // number of channels used - BYTE panpos[32]; // voice pan positions -} MTMHEADER; - - -#pragma pack() - - -BOOL CSoundFile::ReadMTM(LPCBYTE lpStream, DWORD dwMemLength) -//----------------------------------------------------------- -{ - MTMHEADER *pmh = (MTMHEADER *)lpStream; - DWORD dwMemPos = 66; - - if ((!lpStream) || (dwMemLength < 0x100)) return FALSE; - if ((strncmp(pmh->id, "MTM", 3)) || (pmh->numchannels > 32) - || (pmh->numsamples >= MAX_SAMPLES) || (!pmh->numsamples) - || (!pmh->numtracks) || (!pmh->numchannels) - || (!pmh->lastpattern) || (pmh->lastpattern > MAX_PATTERNS)) - return FALSE; - strncpy(m_szNames[0], pmh->songname, 20); - m_szNames[0][20] = 0; - if (dwMemPos + 37*pmh->numsamples + 128 + 192*pmh->numtracks - + 64 * (pmh->lastpattern+1) + pmh->commentsize >= dwMemLength) - return FALSE; - m_nType = MOD_TYPE_MTM; - m_nSamples = pmh->numsamples; - m_nChannels = pmh->numchannels; - // Reading instruments - for (UINT i=1; i<=m_nSamples; i++) - { - MTMSAMPLE *pms = (MTMSAMPLE *)(lpStream + dwMemPos); - strncpy(m_szNames[i], pms->samplename, 22); - m_szNames[i][22] = 0; - Ins[i].nVolume = pms->volume << 2; - Ins[i].nGlobalVol = 64; - DWORD len = pms->length; - if ((len > 4) && (len <= MAX_SAMPLE_LENGTH)) - { - Ins[i].nLength = len; - Ins[i].nLoopStart = pms->reppos; - Ins[i].nLoopEnd = pms->repend; - if (Ins[i].nLoopEnd > Ins[i].nLength) - Ins[i].nLoopEnd = Ins[i].nLength; - if (Ins[i].nLoopStart + 4 >= Ins[i].nLoopEnd) - Ins[i].nLoopStart = Ins[i].nLoopEnd = 0; - if (Ins[i].nLoopEnd) Ins[i].uFlags |= CHN_LOOP; - Ins[i].nFineTune = MOD2XMFineTune(pms->finetune); - if (pms->attribute & 0x01) - { - Ins[i].uFlags |= CHN_16BIT; - Ins[i].nLength >>= 1; - Ins[i].nLoopStart >>= 1; - Ins[i].nLoopEnd >>= 1; - } - Ins[i].nPan = 128; - } - dwMemPos += 37; - } - // Setting Channel Pan Position - for (UINT ich=0; ich<m_nChannels; ich++) - { - ChnSettings[ich].nPan = ((pmh->panpos[ich] & 0x0F) << 4) + 8; - ChnSettings[ich].nVolume = 64; - } - // Reading pattern order - memcpy(Order, lpStream + dwMemPos, pmh->lastorder+1); - dwMemPos += 128; - // Reading Patterns - LPCBYTE pTracks = lpStream + dwMemPos; - dwMemPos += 192 * pmh->numtracks; - LPWORD pSeq = (LPWORD)(lpStream + dwMemPos); - for (UINT pat=0; pat<=pmh->lastpattern; pat++) - { - PatternSize[pat] = 64; - if ((Patterns[pat] = AllocatePattern(64, m_nChannels)) == NULL) break; - for (UINT n=0; n<32; n++) if ((pSeq[n]) && (pSeq[n] <= pmh->numtracks) && (n < m_nChannels)) - { - LPCBYTE p = pTracks + 192 * (pSeq[n]-1); - MODCOMMAND *m = Patterns[pat] + n; - for (UINT i=0; i<64; i++, m+=m_nChannels, p+=3) - { - if (p[0] & 0xFC) m->note = (p[0] >> 2) + 37; - m->instr = ((p[0] & 0x03) << 4) | (p[1] >> 4); - UINT cmd = p[1] & 0x0F; - UINT param = p[2]; - if (cmd == 0x0A) - { - if (param & 0xF0) param &= 0xF0; else param &= 0x0F; - } - m->command = cmd; - m->param = param; - if ((cmd) || (param)) ConvertModCommand(m); - } - } - pSeq += 32; - } - dwMemPos += 64*(pmh->lastpattern+1); - if ((pmh->commentsize) && (dwMemPos + pmh->commentsize < dwMemLength)) - { - UINT n = pmh->commentsize; - m_lpszSongComments = new char[n+1]; - if (m_lpszSongComments) - { - memcpy(m_lpszSongComments, lpStream+dwMemPos, n); - m_lpszSongComments[n] = 0; - for (UINT i=0; i<n; i++) - { - if (!m_lpszSongComments[i]) - { - m_lpszSongComments[i] = ((i+1) % 40) ? 0x20 : 0x0D; - } - } - } - } - dwMemPos += pmh->commentsize; - // Reading Samples - for (UINT ismp=1; ismp<=m_nSamples; ismp++) - { - if (dwMemPos >= dwMemLength) break; - dwMemPos += ReadSample(&Ins[ismp], (Ins[ismp].uFlags & CHN_16BIT) ? RS_PCM16U : RS_PCM8U, - (LPSTR)(lpStream + dwMemPos), dwMemLength - dwMemPos); - } - m_nMinPeriod = 64; - m_nMaxPeriod = 32767; - return TRUE; -} - diff --git a/lib/libmodplug/src/load_okt.cpp b/lib/libmodplug/src/load_okt.cpp deleted file mode 100644 index 4c4e08a1fb..0000000000 --- a/lib/libmodplug/src/load_okt.cpp +++ /dev/null @@ -1,197 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque <olivierl@jps.net>, - * Adam Goode <adam@evdebs.org> (endian and char fixes for PPC) -*/ - -////////////////////////////////////////////// -// Oktalyzer (OKT) module loader // -////////////////////////////////////////////// -#include "stdafx.h" -#include "sndfile.h" - -//#pragma warning(disable:4244) - -typedef struct OKTFILEHEADER -{ - DWORD okta; // "OKTA" - DWORD song; // "SONG" - DWORD cmod; // "CMOD" - DWORD fixed8; - BYTE chnsetup[8]; - DWORD samp; // "SAMP" - DWORD samplen; -} OKTFILEHEADER; - - -typedef struct OKTSAMPLE -{ - CHAR name[20]; - DWORD length; - WORD loopstart; - WORD looplen; - BYTE pad1; - BYTE volume; - BYTE pad2; - BYTE pad3; -} OKTSAMPLE; - - -BOOL CSoundFile::ReadOKT(const BYTE *lpStream, DWORD dwMemLength) -//--------------------------------------------------------------- -{ - OKTFILEHEADER *pfh = (OKTFILEHEADER *)lpStream; - DWORD dwMemPos = sizeof(OKTFILEHEADER); - UINT nsamples = 0, npatterns = 0, norders = 0; - - if ((!lpStream) || (dwMemLength < 1024)) return FALSE; - if ((pfh->okta != 0x41544B4F) || (pfh->song != 0x474E4F53) - || (pfh->cmod != 0x444F4D43) || (pfh->chnsetup[0]) || (pfh->chnsetup[2]) - || (pfh->chnsetup[4]) || (pfh->chnsetup[6]) || (pfh->fixed8 != 0x08000000) - || (pfh->samp != 0x504D4153)) return FALSE; - m_nType = MOD_TYPE_OKT; - m_nChannels = 4 + pfh->chnsetup[1] + pfh->chnsetup[3] + pfh->chnsetup[5] + pfh->chnsetup[7]; - if (m_nChannels > MAX_CHANNELS) m_nChannels = MAX_CHANNELS; - nsamples = bswapBE32(pfh->samplen) >> 5; - m_nSamples = nsamples; - if (m_nSamples >= MAX_SAMPLES) m_nSamples = MAX_SAMPLES-1; - // Reading samples - for (UINT smp=1; smp <= nsamples; smp++) - { - if (dwMemPos >= dwMemLength) return TRUE; - if (smp < MAX_SAMPLES) - { - OKTSAMPLE *psmp = (OKTSAMPLE *)(lpStream + dwMemPos); - MODINSTRUMENT *pins = &Ins[smp]; - - memcpy(m_szNames[smp], psmp->name, 20); - pins->uFlags = 0; - pins->nLength = bswapBE32(psmp->length) & ~1; - pins->nLoopStart = bswapBE16(psmp->loopstart); - pins->nLoopEnd = pins->nLoopStart + bswapBE16(psmp->looplen); - if (pins->nLoopStart + 2 < pins->nLoopEnd) pins->uFlags |= CHN_LOOP; - pins->nGlobalVol = 64; - pins->nVolume = psmp->volume << 2; - pins->nC4Speed = 8363; - } - dwMemPos += sizeof(OKTSAMPLE); - } - // SPEE - if (dwMemPos >= dwMemLength) return TRUE; - if (*((DWORD *)(lpStream + dwMemPos)) == 0x45455053) - { - m_nDefaultSpeed = lpStream[dwMemPos+9]; - dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8; - } - // SLEN - if (dwMemPos >= dwMemLength) return TRUE; - if (*((DWORD *)(lpStream + dwMemPos)) == 0x4E454C53) - { - npatterns = lpStream[dwMemPos+9]; - dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8; - } - // PLEN - if (dwMemPos >= dwMemLength) return TRUE; - if (*((DWORD *)(lpStream + dwMemPos)) == 0x4E454C50) - { - norders = lpStream[dwMemPos+9]; - dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8; - } - // PATT - if (dwMemPos >= dwMemLength) return TRUE; - if (*((DWORD *)(lpStream + dwMemPos)) == 0x54544150) - { - UINT orderlen = norders; - if (orderlen >= MAX_ORDERS) orderlen = MAX_ORDERS-1; - for (UINT i=0; i<orderlen; i++) Order[i] = lpStream[dwMemPos+10+i]; - for (UINT j=orderlen; j>1; j--) { if (Order[j-1]) break; Order[j-1] = 0xFF; } - dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8; - } - // PBOD - UINT npat = 0; - while ((dwMemPos+10 < dwMemLength) && (*((DWORD *)(lpStream + dwMemPos)) == 0x444F4250)) - { - DWORD dwPos = dwMemPos + 10; - UINT rows = lpStream[dwMemPos+9]; - if (!rows) rows = 64; - if (npat < MAX_PATTERNS) - { - if ((Patterns[npat] = AllocatePattern(rows, m_nChannels)) == NULL) return TRUE; - MODCOMMAND *m = Patterns[npat]; - PatternSize[npat] = rows; - UINT imax = m_nChannels*rows; - for (UINT i=0; i<imax; i++, m++, dwPos+=4) - { - if (dwPos+4 > dwMemLength) break; - const BYTE *p = lpStream+dwPos; - UINT note = p[0]; - if (note) - { - m->note = note + 48; - m->instr = p[1] + 1; - } - UINT command = p[2]; - UINT param = p[3]; - m->param = param; - switch(command) - { - // 0: no effect - case 0: - break; - // 1: Portamento Up - case 1: - case 17: - case 30: - if (param) m->command = CMD_PORTAMENTOUP; - break; - // 2: Portamento Down - case 2: - case 13: - case 21: - if (param) m->command = CMD_PORTAMENTODOWN; - break; - // 10: Arpeggio - case 10: - case 11: - case 12: - m->command = CMD_ARPEGGIO; - break; - // 15: Filter - case 15: - m->command = CMD_MODCMDEX; - m->param = param & 0x0F; - break; - // 25: Position Jump - case 25: - m->command = CMD_POSITIONJUMP; - break; - // 28: Set Speed - case 28: - m->command = CMD_SPEED; - break; - // 31: Volume Control - case 31: - if (param <= 0x40) m->command = CMD_VOLUME; else - if (param <= 0x50) { m->command = CMD_VOLUMESLIDE; m->param &= 0x0F; if (!m->param) m->param = 0x0F; } else - if (param <= 0x60) { m->command = CMD_VOLUMESLIDE; m->param = (param & 0x0F) << 4; if (!m->param) m->param = 0xF0; } else - if (param <= 0x70) { m->command = CMD_MODCMDEX; m->param = 0xB0 | (param & 0x0F); if (!(param & 0x0F)) m->param = 0xBF; } else - if (param <= 0x80) { m->command = CMD_MODCMDEX; m->param = 0xA0 | (param & 0x0F); if (!(param & 0x0F)) m->param = 0xAF; } - break; - } - } - } - npat++; - dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8; - } - // SBOD - UINT nsmp = 1; - while ((dwMemPos+10 < dwMemLength) && (*((DWORD *)(lpStream + dwMemPos)) == 0x444F4253)) - { - if (nsmp < MAX_SAMPLES) ReadSample(&Ins[nsmp], RS_PCM8S, (LPSTR)(lpStream+dwMemPos+8), dwMemLength-dwMemPos-8); - dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8; - nsmp++; - } - return TRUE; -} - diff --git a/lib/libmodplug/src/load_pat.cpp b/lib/libmodplug/src/load_pat.cpp deleted file mode 100644 index 032f95e341..0000000000 --- a/lib/libmodplug/src/load_pat.cpp +++ /dev/null @@ -1,1577 +0,0 @@ -/* - - MikMod Sound System - - By Jake Stine of Divine Entertainment (1996-2000) - - Support: - If you find problems with this code, send mail to: - air@divent.org - - Distribution / Code rights: - Use this source code in any fashion you see fit. Giving me credit where - credit is due is optional, depending on your own levels of integrity and - honesty. - - ----------------------------------------- - Module: LOAD_PAT - - PAT sample loader. - by Peter Grootswagers (2006) - <email:pgrootswagers@planet.nl> - - It's primary purpose is loading samples for the .abc and .mid modules - Can also be used stand alone, in that case a tune (frere Jacques) - is generated using al samples available in the .pat file - - Portability: - All systems - all compilers (hopefully) -*/ - -#include <stdlib.h> -#include <time.h> -#include <string.h> -#include <math.h> -#include <ctype.h> -#include "stdafx.h" - -#ifdef NEWMIKMOD -#include "mikmod.h" -#include "uniform.h" -typedef UBYTE BYTE; -typedef UWORD WORD; -#else -#include "stdafx.h" -#include "sndfile.h" -#endif - -#include "load_pat.h" - -#ifdef MSC_VER -#define DIRDELIM '\\' -#define TIMIDITYCFG "C:\\TIMIDITY\\TIMIDITY.CFG" -#define PATHFORPAT "C:\\TIMIDITY\\INSTRUMENTS" -#else -#define DIRDELIM '/' -#define TIMIDITYCFG "/usr/local/share/timidity/timidity.cfg" -#define PATHFORPAT "/usr/local/share/timidity/instruments" -#endif - -#define PAT_ENV_PATH2CFG "MMPAT_PATH_TO_CFG" - -// 128 gm and 63 drum -#define MAXSMP 191 -static char midipat[MAXSMP][40]; -static char pathforpat[128]; -static char timiditycfg[128]; - -#pragma pack(1) - -typedef struct { - char header[12]; // ascizz GF1PATCH110 - char gravis_id[10]; // allways ID#000002 - char description[60]; - BYTE instruments; - BYTE voices; - BYTE channels; - WORD waveforms; - WORD master_volume; - DWORD data_size; - char reserved[36]; -} PatchHeader; - -typedef struct { - WORD instrument_id; - char instrument_name[16]; - DWORD instrument_size; - BYTE layers; - char reserved[40]; -} InstrumentHeader; - -typedef struct { - BYTE layer_dup; - BYTE layer_id; - DWORD layer_size; - BYTE samples; - char reserved[40]; -} LayerHeader; - -typedef struct { - char wave_name[7]; - BYTE fractions; - DWORD wave_size; - DWORD start_loop; - DWORD end_loop; - WORD sample_rate; - DWORD low_frequency ; - DWORD high_frequency; - DWORD root_frequency; - short int tune; - BYTE balance; - BYTE envelope_rate[6]; - BYTE envelope_offset[6]; - BYTE tremolo_sweep; - BYTE tremolo_rate; - BYTE tremolo_depth; - BYTE vibrato_sweep; - BYTE vibrato_rate; - BYTE vibrato_depth; - BYTE modes; - DWORD scale_frequency; - DWORD scale_factor; - char reserved[32]; -} WaveHeader; - -// WaveHeader.modes bits -#define PAT_16BIT 1 -#define PAT_UNSIGNED 2 -#define PAT_LOOP 4 -#define PAT_PINGPONG 8 -#define PAT_BACKWARD 16 -#define PAT_SUSTAIN 32 -#define PAT_ENVELOPE 64 -#define PAT_CLAMPED 128 - -#define C4SPD 8363 -#define C4mHz 523251 -#define C4 523.251f -#define PI 3.141592653589793f -#define OMEGA ((2.0f * PI * C4)/(float)C4SPD) - -/************************************************************************** -**************************************************************************/ -#ifdef NEWMIKMOD -static char PAT_Version[] = "Timidity GUS Patch v1.0"; -#endif -static BYTE pat_gm_used[MAXSMP]; -static BYTE pat_loops[MAXSMP]; - -/************************************************************************** -**************************************************************************/ - -typedef struct _PATHANDLE -{ -#ifdef NEWMIKMOD - MM_ALLOC *allochandle; -#endif - char patname[16]; - int samples; -} PATHANDLE; - -// local prototypes -static int pat_getopt(const char *s, const char *o, int dflt); - -static void pat_message(const char *s1, const char *s2) -{ - char txt[256]; - if( strlen(s1) + strlen(s2) > 255 ) return; - sprintf(txt, s1, s2); -#ifdef NEWMIKMOD - _mmlog(txt); -#else - fprintf(stderr, "load_pat > %s\n", txt); -#endif -} - -void pat_resetsmp(void) -{ - int i; - for( i=0; i<MAXSMP; i++ ) { - pat_loops[i] = 0; - pat_gm_used[i] = 0; - } -} - -int pat_numsmp() -{ - return strlen((const char *)pat_gm_used); -} - -int pat_numinstr(void) -{ - return strlen((const char *)pat_gm_used); -} - -int pat_smptogm(int smp) -{ - if( smp < MAXSMP ) - return pat_gm_used[smp - 1]; - return 1; -} - -int pat_gmtosmp(int gm) -{ - int smp; - for( smp=0; pat_gm_used[smp]; smp++ ) - if( pat_gm_used[smp] == gm ) - return smp+1; - if( smp < MAXSMP ) { - pat_gm_used[smp] = gm; - return smp+1; - } - return 1; -} - -int pat_smplooped(int smp) -{ - if( smp < MAXSMP ) return pat_loops[smp - 1]; - return 1; -} - -const char *pat_gm_name(int gm) -{ - static char buf[40]; - if( gm < 1 || gm > MAXSMP ) { - sprintf(buf, "invalid gm %d", gm); - return buf; - } - return midipat[gm - 1]; -} - -int pat_gm_drumnr(int n) -{ - if( n < 25 ) return 129; - if( n+129-25 < MAXSMP ) - return 129+n-25; // timidity.cfg drum patches start at 25 - return MAXSMP; -} - -int pat_gm_drumnote(int n) -{ - char *p; - p = strchr(midipat[pat_gm_drumnr(n)-1], ':'); - if( p ) return pat_getopt(p+1, "note", n); - return n; -} - -static float pat_sinus(int i) -{ - float res = sinf(OMEGA * (float)i); - return res; -} - -static float pat_square(int i) -{ - float res = 30.0f * sinf(OMEGA * (float)i); - if( res > 0.99f ) return 0.99f; - if( res < -0.99f ) return -0.99f; - return res; -} - -static float pat_sawtooth(int i) -{ - float res = OMEGA * (float)i; - while( res > 2 * PI ) - res -= 2 * PI; - i = 2; - if( res > PI ) { - res = PI - res; - i = -2; - } - res = (float)i * res / PI; - if( res > 0.9f ) return 1.0f - res; - if( res < -0.9f ) return 1.0f + res; - return res; -} - -typedef float (*PAT_SAMPLE_FUN)(int); - -static PAT_SAMPLE_FUN pat_fun[] = { pat_sinus, pat_square, pat_sawtooth }; - -#ifdef NEWMIKMOD - -#define MMFILE MMSTREAM -#define mmftell(x) _mm_ftell(x) -#define mmfseek(f,p,w) _mm_fseek(f,p,w) -#define mmreadUBYTES(buf,sz,f) _mm_read_UBYTES(buf,sz,f) - -#else - -#define MMSTREAM FILE -#define _mm_fopen(name,mode) fopen(name,mode) -#define _mm_fgets(f,buf,sz) fgets(buf,sz,f) -#define _mm_fseek(f,pos,whence) fseek(f,pos,whence) -#define _mm_ftell(f) ftell(f) -#define _mm_read_UBYTES(buf,sz,f) fread(buf,sz,1,f) -#define _mm_read_SBYTES(buf,sz,f) fread(buf,sz,1,f) -#define _mm_feof(f) feof(f) -#define _mm_fclose(f) fclose(f) -#define DupStr(h,buf,sz) strdup(buf) -#define _mm_calloc(h,n,sz) calloc(n,sz) -#define _mm_recalloc(h,buf,sz,elsz) realloc(buf,sz) -#undef _mm_free -#define _mm_free(h,p) free(p) - -typedef struct { - char *mm; - int sz; - int pos; -} MMFILE; - -static long mmftell(MMFILE *mmfile) -{ - return mmfile->pos; -} - -static void mmfseek(MMFILE *mmfile, long p, int whence) -{ - switch(whence) { - case SEEK_SET: - mmfile->pos = p; - break; - case SEEK_CUR: - mmfile->pos += p; - break; - case SEEK_END: - mmfile->pos = mmfile->sz + p; - break; - } -} - -static void mmreadUBYTES(BYTE *buf, long sz, MMFILE *mmfile) -{ - memcpy(buf, &mmfile->mm[mmfile->pos], sz); - mmfile->pos += sz; -} - -static void mmreadSBYTES(char *buf, long sz, MMFILE *mmfile) -{ - memcpy(buf, &mmfile->mm[mmfile->pos], sz); - mmfile->pos += sz; -} - -#endif - -void pat_init_patnames(void) -{ - int i,j; - char *p, *q; - char line[80]; - MMSTREAM *mmcfg; - strcpy(pathforpat, PATHFORPAT); - strcpy(timiditycfg, TIMIDITYCFG); - p = getenv(PAT_ENV_PATH2CFG); - if( p ) { - strcpy(timiditycfg,p); - strcpy(pathforpat,p); - strcat(timiditycfg,"/timidity.cfg"); - strcat(pathforpat,"/instruments"); - } - mmcfg = _mm_fopen(timiditycfg,"r"); - for( i=0; i<MAXSMP; i++ ) midipat[i][0] = '\0'; - if( !mmcfg ) { - pat_message("can not open %s, use environment variable " PAT_ENV_PATH2CFG " for the directory", timiditycfg); - } - else { - // read in bank 0 and drum patches - j = 0; - _mm_fgets(mmcfg, line, 80); - while( !_mm_feof(mmcfg) ) { - if( isdigit(line[0]) ) { - i = atoi(line); - if( i < MAXSMP && i >= 0 ) { - p = strchr(line,'/')+1; - if(j) - q = midipat[pat_gm_drumnr(i)-1]; - else - q = midipat[i]; - while( *p && !isspace(*p) ) *q++ = *p++; - if( isspace(*p) ) { - *q++ = ':'; - while( isspace(*p) ) { - while( isspace(*p) ) p++; - while( *p && !isspace(*p) ) *q++ = *p++; - if( isspace(*p) ) *q++ = ' '; - } - } - *q++ = '\0'; - } - } - if( !strncmp(line,"drumset",7) ) j = 1; - _mm_fgets(mmcfg, line, 80); - } - _mm_fclose(mmcfg); - } - q = midipat[0]; - j = 0; - for( i=0; i<MAXSMP; i++ ) { - if( midipat[i][0] ) q = midipat[i]; - else { - strcpy(midipat[i],q); - if( midipat[i][0] == '\0' ) j++; - } - } - if( j ) { - for( i=MAXSMP; i-- > 0; ) { - if( midipat[i][0] ) q = midipat[i]; - else strcpy(midipat[i],q); - } - } -} - -static char *pat_build_path(char *fname, int pat) -{ - char *ps; - ps = strrchr(midipat[pat], ':'); - if( ps ) { - sprintf(fname, "%s%c%s", pathforpat, DIRDELIM, midipat[pat]); - strcpy(strrchr(fname, ':'), ".pat"); - return ps; - } - sprintf(fname, "%s%c%s.pat", pathforpat, DIRDELIM, midipat[pat]); - return 0; -} - -static void pat_read_patname(PATHANDLE *h, MMFILE *mmpat) { - InstrumentHeader ih; - mmfseek(mmpat,sizeof(PatchHeader), SEEK_SET); - mmreadUBYTES((BYTE *)&ih, sizeof(InstrumentHeader), mmpat); - strncpy(h->patname, ih.instrument_name, 16); - h->patname[15] = '\0'; -} - -static void pat_read_layerheader(MMSTREAM *mmpat, LayerHeader *hl) -{ - _mm_fseek(mmpat,sizeof(PatchHeader)+sizeof(InstrumentHeader), SEEK_SET); - _mm_read_UBYTES((BYTE *)hl, sizeof(LayerHeader), mmpat); -} - -static void pat_get_layerheader(MMFILE *mmpat, LayerHeader *hl) -{ - InstrumentHeader ih; - mmfseek(mmpat,sizeof(PatchHeader), SEEK_SET); - mmreadUBYTES((BYTE *)&ih, sizeof(InstrumentHeader), mmpat); - mmreadUBYTES((BYTE *)hl, sizeof(LayerHeader), mmpat); - strncpy(hl->reserved, ih.instrument_name, 40); -} - -static int pat_read_numsmp(MMFILE *mmpat) { - LayerHeader hl; - pat_get_layerheader(mmpat, &hl); - return hl.samples; -} - -static void pat_read_waveheader(MMSTREAM *mmpat, WaveHeader *hw, int layer) -{ - long int pos, bestpos=0; - LayerHeader hl; - ULONG bestfreq, freqdist; - int i; - // read the very first and maybe only sample - pat_read_layerheader(mmpat, &hl); - if( hl.samples > 1 ) { - if( layer ) { - if( layer > hl.samples ) layer = hl.samples; // you don't fool me.... - for( i=1; i<layer; i++ ) { - _mm_read_UBYTES((BYTE *)hw, sizeof(WaveHeader), mmpat); - _mm_fseek(mmpat, hw->wave_size, SEEK_CUR); - } - } - else { - bestfreq = C4mHz * 1000; // big enough - for( i=0; i<hl.samples; i++ ) { - pos = _mm_ftell(mmpat); - _mm_read_UBYTES((BYTE *)hw, sizeof(WaveHeader), mmpat); - if( hw->root_frequency > C4mHz ) - freqdist = hw->root_frequency - C4mHz; - else - freqdist = 2 * (C4mHz - hw->root_frequency); - if( freqdist < bestfreq ) { - bestfreq = freqdist; - bestpos = pos; - } - _mm_fseek(mmpat, hw->wave_size, SEEK_CUR); - } - _mm_fseek(mmpat, bestpos, SEEK_SET); - } - } - _mm_read_UBYTES((BYTE *)hw, sizeof(WaveHeader), mmpat); - strncpy(hw->reserved, hl.reserved, 36); - if( hw->start_loop >= hw->wave_size ) { - hw->start_loop = 0; - hw->end_loop = 0; - hw->modes &= ~PAT_LOOP; // mask off loop indicator - } - if( hw->end_loop > hw->wave_size ) - hw->end_loop = hw->wave_size; -} - -#ifndef NEWMIKMOD -static void pat_get_waveheader(MMFILE *mmpat, WaveHeader *hw, int layer) -{ - long int pos, bestpos=0; - LayerHeader hl; - ULONG bestfreq, freqdist; - int i; - // read the very first and maybe only sample - pat_get_layerheader(mmpat, &hl); - if( hl.samples > 1 ) { - if( layer ) { - if( layer > hl.samples ) layer = hl.samples; // you don't fool me.... - for( i=1; i<layer; i++ ) { - mmreadUBYTES((BYTE *)hw, sizeof(WaveHeader), mmpat); - mmfseek(mmpat, hw->wave_size, SEEK_CUR); - } - } - else { - bestfreq = C4mHz * 1000; // big enough - for( i=0; i<hl.samples; i++ ) { - pos = mmftell(mmpat); - mmreadUBYTES((BYTE *)hw, sizeof(WaveHeader), mmpat); - if( hw->root_frequency > C4mHz ) - freqdist = hw->root_frequency - C4mHz; - else - freqdist = 2 * (C4mHz - hw->root_frequency); - if( freqdist < bestfreq ) { - bestfreq = freqdist; - bestpos = pos; - } - mmfseek(mmpat, hw->wave_size, SEEK_CUR); - } - mmfseek(mmpat, bestpos, SEEK_SET); - } - } - mmreadUBYTES((BYTE *)hw, sizeof(WaveHeader), mmpat); - if( hw->start_loop >= hw->wave_size ) { - hw->start_loop = 0; - hw->end_loop = 0; - hw->modes &= ~PAT_LOOP; // mask off loop indicator - } - if( hw->end_loop > hw->wave_size ) - hw->end_loop = hw->wave_size; -} -#endif - -static int pat_readpat_attr(int pat, WaveHeader *hw, int layer) -{ - char fname[128]; - MMSTREAM *mmpat; - pat_build_path(fname, pat); - mmpat = _mm_fopen(fname, "r"); - if( !mmpat ) - return 0; - pat_read_waveheader(mmpat, hw, layer); - _mm_fclose(mmpat); - return 1; -} - -static void pat_amplify(char *b, int num, int amp, int m) -{ - char *pb; - BYTE *pu; - short int *pi; - WORD *pw; - int i,n,v; - n = num; - if( m & PAT_16BIT ) { // 16 bit - n >>= 1; - if( m & 2 ) { // unsigned - pw = (WORD *)b; - for( i=0; i<n; i++ ) { - v = (((int)(*pw) - 0x8000) * amp) / 100; - if( v < -0x8000 ) v = -0x8000; - if( v > 0x7fff ) v = 0x7fff; - *pw++ = v + 0x8000; - } - } - else { - pi = (short int *)b; - for( i=0; i<n; i++ ) { - v = ((*pi) * amp) / 100; - if( v < -0x8000 ) v = -0x8000; - if( v > 0x7fff ) v = 0x7fff; - *pi++ = v; - } - } - } - else { - if( m & 2 ) { // unsigned - pu = (BYTE *)b; - for( i=0; i<n; i++ ) { - v = (((int)(*pu) - 0x80) * amp) / 100; - if( v < -0x80 ) v = -0x80; - if( v > 0x7f ) v = 0x7f; - *pu++ = v + 0x80; - } - } - else { - pb = (char *)b; - for( i=0; i<n; i++ ) { - v = ((*pb) * amp) / 100; - if( v < -0x80 ) v = -0x80; - if( v > 0x7f ) v = 0x7f; - *pb++ = v; - } - } - } -} - -static int pat_getopt(const char *s, const char *o, int dflt) -{ - const char *p; - if( !s ) return dflt; - p = strstr(s,o); - if( !p ) return dflt; - return atoi(strchr(p,'=')+1); -} - -static void pat_readpat(int pat, char *dest, int num) -{ - static int readlasttime = 0, wavesize = 0; - static MMSTREAM *mmpat = 0; - static char *opt = 0; - int amp; - char fname[128]; - WaveHeader hw; -#ifdef NEWMIKMOD - static int patlast = MAXSMP; - if( !dest ) { // reset - if( mmpat ) _mm_fclose(mmpat); - readlasttime = 0; - wavesize = 0; - mmpat = 0; - patlast = MAXSMP; - return; - } - if( pat != patlast ) { // reset for other instrument - if( mmpat ) _mm_fclose(mmpat); - readlasttime = 0; - patlast = pat; - } -#endif - if( !readlasttime ) { - opt=pat_build_path(fname, pat); - mmpat = _mm_fopen(fname, "r"); - if( !mmpat ) - return; - pat_read_waveheader(mmpat, &hw, 0); - wavesize = hw.wave_size; - } - _mm_read_SBYTES(dest, num, mmpat); - amp = pat_getopt(opt,"amp",100); - if( amp != 100 ) pat_amplify(dest, num, amp, hw.modes); - readlasttime += num; - if( readlasttime < wavesize ) return; - readlasttime = 0; - _mm_fclose(mmpat); - mmpat = 0; -} - -#ifdef NEWMIKMOD -// next code pinched from dec_raw.c and rebuild to load bytes from different places -// ===================================================================================== -static void *dec_pat_Init(MMSTREAM *mmfp) -{ - pat_readpat(0,0,0); // initialize pat loader - return (void *)mmfp; -} - -static void dec_pat_Cleanup(void *raw) -{ -} - -static BOOL dec_pat_Decompress16Bit(void *raw, short int *dest, int cbcount, MMSTREAM *mmfp) -{ - long samplenum = _mm_ftell(mmfp) - 1; -#else -static BOOL dec_pat_Decompress16Bit(short int *dest, int cbcount, int samplenum) -{ -#endif - int i; - PAT_SAMPLE_FUN f; - if( samplenum < MAXSMP ) pat_readpat(samplenum, (char *)dest, cbcount*2); - else { - f = pat_fun[(samplenum - MAXSMP) % 3]; - for( i=0; i<cbcount; i++ ) - dest[i] = (short int)(32000.0*f(i)); - } - return cbcount; -} - -// convert 8 bit data to 16 bit! -// We do the conversion in reverse so that the data we're converting isn't overwritten -// by the result. -static void pat_blowup_to16bit(short int *dest, int cbcount) { - char *s; - short int *d; - int t; - s = (char *)dest; - d = dest; - s += cbcount; - d += cbcount; - for(t=0; t<cbcount; t++) - { s--; - d--; - *d = (*s) << 8; - } -} - -#ifdef NEWMIKMOD -static BOOL dec_pat_Decompress8Bit(void *raw, short int *dest, int cbcount, MMSTREAM *mmfp) -{ - long samplenum = _mm_ftell(mmfp) - 1; -#else -static BOOL dec_pat_Decompress8Bit(short int *dest, int cbcount, int samplenum) -{ -#endif - int i; - PAT_SAMPLE_FUN f; - if( samplenum < MAXSMP ) pat_readpat(samplenum, (char *)dest, cbcount); - else { - f = pat_fun[(samplenum - MAXSMP) % 3]; - for( i=0; i<cbcount; i++ ) - dest[i] = (char)(120.0*f(i)); - } - pat_blowup_to16bit(dest, cbcount); - return cbcount; -} - -#ifdef NEWMIKMOD -SL_DECOMPRESS_API dec_pat = -{ - NULL, - SL_COMPRESS_RAW, - dec_pat_Init, - dec_pat_Cleanup, - dec_pat_Decompress16Bit, - dec_pat_Decompress8Bit, -}; -#endif - -// ===================================================================================== -#ifdef NEWMIKMOD -BOOL PAT_Test(MMSTREAM *mmfile) -#else -BOOL CSoundFile::TestPAT(const BYTE *lpStream, DWORD dwMemLength) -#endif -// ===================================================================================== -{ - PatchHeader ph; -#ifdef NEWMIKMOD - _mm_fseek(mmfile,0,SEEK_SET); - _mm_read_UBYTES((BYTE *)&ph, sizeof(PatchHeader), mmfile); -#else - if( dwMemLength < sizeof(PatchHeader) ) return 0; - memcpy((BYTE *)&ph, lpStream, sizeof(PatchHeader)); -#endif - if( !strcmp(ph.header,"GF1PATCH110") && !strcmp(ph.gravis_id,"ID#000002") ) return 1; - return 0; -} - -// ===================================================================================== -static PATHANDLE *PAT_Init(void) -{ - PATHANDLE *retval; -#ifdef NEWMIKMOD - MM_ALLOC *allochandle; - - allochandle = _mmalloc_create("Load_PAT", NULL); - retval = (PATHANDLE *)_mm_calloc(allochandle, 1,sizeof(PATHANDLE)); - if( !retval ) return NULL; - SL_RegisterDecompressor(&dec_raw); // we can not get the samples out of our own routines...! -#else - retval = (PATHANDLE *)calloc(1,sizeof(PATHANDLE)); - if( !retval ) return NULL; -#endif - return retval; -} - -// ===================================================================================== -static void PAT_Cleanup(PATHANDLE *handle) -// ===================================================================================== -{ -#ifdef NEWMIKMOD - if(handle && handle->allochandle) { - _mmalloc_close(handle->allochandle); - handle->allochandle = 0; - } -#else - if(handle) { - free(handle); - } -#endif -} - -static char tune[] = "c d e c|c d e c|e f g..|e f g..|gagfe c|gagfe c|c G c..|c G c..|"; -static int pat_note(int abc) -{ - switch( abc ) { - case 'C': return 48; - case 'D': return 50; - case 'E': return 52; - case 'F': return 53; - case 'G': return 55; - case 'A': return 57; - case 'B': return 59; - case 'c': return 60; - case 'd': return 62; - case 'e': return 64; - case 'f': return 65; - case 'g': return 67; - case 'a': return 69; - case 'b': return 71; - default: - break; - } - return 0; -} - -int pat_modnote(int midinote) -{ - int n; - n = midinote; -#ifdef NEWMIKMOD - if( n < 12 ) n++; - else n-=11; -#else - n += 13; -#endif - return n; -} - -// ===================================================================================== -#ifdef NEWMIKMOD -static void PAT_ReadPatterns(UNIMOD *of, PATHANDLE *h, int numpat) -// ===================================================================================== -{ - int pat,row,i,ch; - BYTE n,ins,vol; - int t; - int tt1, tt2; - UNITRK_EFFECT eff; - - tt2 = (h->samples - 1) * 16 + 128; - for( pat = 0; pat < numpat; pat++ ) { - utrk_reset(of->ut); - for( row = 0; row < 64; row++ ) { - tt1 = (pat * 64 + row); - for( ch = 0; ch < h->samples; ch++ ) { - t = tt1 - ch * 16; - if( t >= 0 ) { - i = tt2 - 16 * ((h->samples - 1 - ch) & 3); - if( tt1 < i ) { - t = t % 64; - if( isalpha(tune[t]) ) { - utrk_settrack(of->ut, ch); - n = pat_modnote(pat_note(tune[t])); - ins = ch; - vol = 100; - if( (t % 16) == 0 ) { - vol += vol / 10; - if( vol > 127 ) vol = 127; - } - utrk_write_inst(of->ut, ins); - utrk_write_note(of->ut, n); // <- normal note - pt_write_effect(of->ut, 0xc, vol); - } - if( tt1 == i - 1 && ch == 0 && row < 63 ) { - eff.effect = UNI_GLOB_PATBREAK; - eff.param.u = 0; - eff.framedly = UFD_RUNONCE; - utrk_write_global(of->ut, &eff, UNIMEM_NONE); - } - } - else { - if( tt1 == i ) { - eff.param.u = 0; - eff.effect = UNI_NOTEKILL; - utrk_write_local(of->ut, &eff, UNIMEM_NONE); - } - } - } - } - utrk_newline(of->ut); - } - if(!utrk_dup_pattern(of->ut,of)) return; - } -} - -#else - -static void PAT_ReadPatterns(MODCOMMAND *pattern[], WORD psize[], PATHANDLE *h, int numpat) -// ===================================================================================== -{ - int pat,row,i,ch; - BYTE n,ins,vol; - int t; - int tt1, tt2; - MODCOMMAND *m; - if( numpat > MAX_PATTERNS ) numpat = MAX_PATTERNS; - - tt2 = (h->samples - 1) * 16 + 128; - for( pat = 0; pat < numpat; pat++ ) { - pattern[pat] = CSoundFile::AllocatePattern(64, h->samples); - if( !pattern[pat] ) return; - psize[pat] = 64; - for( row = 0; row < 64; row++ ) { - tt1 = (pat * 64 + row); - for( ch = 0; ch < h->samples; ch++ ) { - t = tt1 - ch * 16; - m = &pattern[pat][row * h->samples + ch]; - m->param = 0; - m->command = CMD_NONE; - if( t >= 0 ) { - i = tt2 - 16 * ((h->samples - 1 - ch) & 3); - if( tt1 < i ) { - t = t % 64; - if( isalpha(tune[t]) ) { - n = pat_modnote(pat_note(tune[t])); - ins = ch + 1; - vol = 40; - if( (t % 16) == 0 ) { - vol += vol / 10; - if( vol > 64 ) vol = 64; - } - m->instr = ins; - m->note = n; // <- normal note - m->volcmd = VOLCMD_VOLUME; - m->vol = vol; - } - if( tt1 == i - 1 && ch == 0 && row < 63 ) { - m->command = CMD_PATTERNBREAK; - } - } - else { - if( tt1 == i ) { - m->param = 0; - m->command = CMD_KEYOFF; - m->volcmd = VOLCMD_VOLUME; - m->vol = 0; - } - } - } - } - } - } -} - -#endif - -// calculate the best speed that approximates the pat root frequency as a C note -static ULONG pat_patrate_to_C4SPD(ULONG patRate , ULONG patMilliHz) -{ - ULONG u; - double x, y; - u = patMilliHz; - x = 0.1 * patRate; - x = x * C4mHz; - y = u * 0.4; - x = x / y; - u = (ULONG)(x+0.5); - return u; -} - -// return relative position in samples for the rate starting with offset start ending with offset end -static int pat_envelope_rpos(int rate, int start, int end) -{ - int r, p, t, s; - // rate byte is 3 bits exponent and 6 bits increment size - // eeiiiiii - // every 8 to the power ee the volume is incremented/decremented by iiiiii - // Thank you Gravis for this weirdness... - r = 3 - ((rate >> 6) & 3) * 3; - p = rate & 0x3f; - if( !p ) return 0; - t = end - start; - if( !t ) return 0; - if (t < 0) t = -t; - s = (t << r)/ p; - return s; -} - -static void pat_modenv(WaveHeader *hw, int mpos[6], int mvol[6]) -{ - int i, sum, s; - BYTE *prate = hw->envelope_rate, *poffset = hw->envelope_offset; - for( i=0; i<6; i++ ) { - mpos[i] = 0; - mvol[i] = 64; - } - if( !memcmp(prate, "??????", 6) || poffset[5] >= 100 ) return; // weird rates or high env end volume - if( !(hw->modes & PAT_SUSTAIN) ) return; // no sustain thus no need for envelope - s = hw->wave_size; - if (s == 0) return; - if( hw->modes & PAT_16BIT ) - s >>= 1; - // offsets 0 1 2 3 4 5 are distributed over 0 2 4 6 8 10, the odd numbers are set in between - sum = 0; - for( i=0; i<6; i++ ) { - mvol[i] = poffset[i]; - mpos[i] = pat_envelope_rpos(prate[i], i? poffset[i-1]: 0, poffset[i]); - sum += mpos[i]; - } - if( sum == 0 ) return; - if( sum > s ) { - for( i=0; i<6; i++ ) - mpos[i] = (s * mpos[i]) / sum; - } - for( i=1; i<6; i++ ) - mpos[i] += mpos[i-1]; - for( i=0; i<6 ; i++ ) { - mpos[i] = (256 * mpos[i]) / s; - mpos[i]++; - if( i > 0 && mpos[i] <= mpos[i-1] ) { - if( mvol[i] == mvol[i-1] ) mpos[i] = mpos[i-1]; - else mpos[i] = mpos[i-1] + 1; - } - if( mpos[i] > 256 ) mpos[i] = 256; - } - mvol[5] = 0; // kill Bill.... -} - -#ifdef NEWMIKMOD -static void pat_setpat_inst(WaveHeader *hw, INSTRUMENT *d, int smp) -{ - int u, inuse; - int envpoint[6], envvolume[6]; - for(u=0; u<120; u++) { - d->samplenumber[u] = smp; - d->samplenote[u] = smp; - } - d->globvol = 64; - d->volfade = 0; - d->volflg = EF_CARRY; - d->panflg = EF_CARRY; - if( hw->modes & PAT_ENVELOPE ) d->volflg |= EF_ON; - if( hw->modes & PAT_SUSTAIN ) d->volflg |= EF_SUSTAIN; - if( (hw->modes & PAT_LOOP) && (hw->start_loop != hw->end_loop) ) d->volflg |= EF_LOOP; - d->volsusbeg = 1; - d->volsusend = 1; - d->volbeg = 1; - d->volend = 2; - d->volpts = 6; - // scale volume envelope: - inuse = 0; - pat_modenv(hw, envpoint, envvolume); - for(u=0; u<6; u++) - { - if( envvolume[u] != 64 ) inuse = 1; - d->volenv[u].val = envvolume[u]<<2; - d->volenv[u].pos = envpoint[u]; - } - if(!inuse) d->volpts = 0; - d->pansusbeg = 0; - d->pansusend = 0; - d->panbeg = 0; - d->panend = 0; - d->panpts = 0; - // scale panning envelope: - for(u=0; u<12; u++) - { - d->panenv[u].val = 0; - d->panenv[u].pos = 0; - } - d->panpts = 0; -} -#else -static void pat_setpat_inst(WaveHeader *hw, INSTRUMENTHEADER *d, int smp) -{ - int u, inuse; - int envpoint[6], envvolume[6]; - d->nMidiProgram = 0; - d->nFadeOut = 0; - d->nPan = 128; - d->nPPC = 5*12; - d->dwFlags = 0; - if( hw->modes & PAT_ENVELOPE ) d->dwFlags |= ENV_VOLUME; - if( hw->modes & PAT_SUSTAIN ) d->dwFlags |= ENV_VOLSUSTAIN; - if( (hw->modes & PAT_LOOP) && (hw->start_loop != hw->end_loop) ) d->dwFlags |= ENV_VOLLOOP; - d->nVolEnv = 6; - //if (!d->nVolEnv) d->dwFlags &= ~ENV_VOLUME; - d->nPanEnv = 0; - d->nVolSustainBegin = 1; - d->nVolSustainEnd = 1; - d->nVolLoopStart = 1; - d->nVolLoopEnd = 2; - d->nPanSustainBegin = 0; - d->nPanSustainEnd = 0; - d->nPanLoopStart = 0; - d->nPanLoopEnd = 0; - d->nGlobalVol = 64; - pat_modenv(hw, envpoint, envvolume); - inuse = 0; - for( u=0; u<6; u++) - { - if( envvolume[u] != 64 ) inuse = 1; - d->VolPoints[u] = envpoint[u]; - d->VolEnv[u] = envvolume[u]; - d->PanPoints[u] = 0; - d->PanEnv[u] = 0; - if (u) - { - if (d->VolPoints[u] < d->VolPoints[u-1]) - { - d->VolPoints[u] &= 0xFF; - d->VolPoints[u] += d->VolPoints[u-1] & 0xFF00; - if (d->VolPoints[u] < d->VolPoints[u-1]) d->VolPoints[u] += 0x100; - } - } - } - if( !inuse ) d->nVolEnv = 0; - for( u=0; u<128; u++) - { - d->NoteMap[u] = u+1; - d->Keyboard[u] = smp; - } -} -#endif -#ifdef NEWMIKMOD -static void PATinst(UNIMOD *of, INSTRUMENT *d, int smp, int gm) -#else -static void PATinst(INSTRUMENTHEADER *d, int smp, int gm) -#endif -{ - WaveHeader hw; - char s[32]; - memset(s,0,32); - if( pat_readpat_attr(gm-1, &hw, 0) ) { - pat_setpat_inst(&hw, d, smp); - } - else { - hw.modes = PAT_16BIT|PAT_ENVELOPE|PAT_SUSTAIN|PAT_LOOP; - hw.start_loop = 0; - hw.end_loop = 30000; - hw.wave_size = 30000; -// envelope rates and offsets pinched from timidity's acpiano.pat sample no 1 - hw.envelope_rate[0] = 0x3f; - hw.envelope_rate[1] = 0x3f; - hw.envelope_rate[2] = 0x3f; - hw.envelope_rate[3] = 0x08|(3<<6); - hw.envelope_rate[4] = 0x3f; - hw.envelope_rate[5] = 0x3f; - hw.envelope_offset[0] = 246; - hw.envelope_offset[1] = 246; - hw.envelope_offset[2] = 246; - hw.envelope_offset[3] = 0; - hw.envelope_offset[4] = 0; - hw.envelope_offset[5] = 0; - strncpy(hw.reserved, midipat[gm-1], sizeof(hw.reserved)); - pat_setpat_inst(&hw, d, smp); - } - if( hw.reserved[0] ) - strncpy(s, hw.reserved, 32); - else - strncpy(s, midipat[gm-1], 32); -#ifdef NEWMIKMOD - d->insname = DupStr(of->allochandle, s,28); -#else - s[31] = '\0'; - memset(d->name, 0, 32); - strcpy((char *)d->name, s); - strncpy(s, midipat[gm-1], 12); - s[11] = '\0'; - memset(d->filename, 0, 12); - strcpy((char *)d->filename, s); -#endif -} - -#ifdef NEWMIKMOD -static void pat_setpat_attr(WaveHeader *hw, UNISAMPLE *q, int gm) -{ - q->seekpos = gm; // dec_pat expects the midi samplenumber in this - q->speed = pat_patrate_to_C4SPD(hw->sample_rate , hw->root_frequency); - q->length = hw->wave_size; - q->loopstart = hw->start_loop; - q->loopend = hw->end_loop; - q->volume = 0x40; - if( hw->modes & PAT_16BIT ) { - q->format |= SF_16BITS; - q->length >>= 1; - q->loopstart >>= 1; - q->loopend >>= 1; - q->speed <<= 1; - } - if( (hw->modes & PAT_UNSIGNED)==0 ) q->format |= SF_SIGNED; - if( hw->modes & PAT_LOOP ) { - q->flags |= SL_LOOP; - if( hw->modes & PAT_PINGPONG ) q->flags |= SL_SUSTAIN_BIDI; - if( hw->modes & PAT_SUSTAIN ) q->flags |= SL_SUSTAIN_LOOP; - } -} -#else -static void pat_setpat_attr(WaveHeader *hw, MODINSTRUMENT *q) -{ - q->nC4Speed = pat_patrate_to_C4SPD(hw->sample_rate , hw->root_frequency); - q->nLength = hw->wave_size; - q->nLoopStart = hw->start_loop; - q->nLoopEnd = hw->end_loop; - q->nVolume = 256; - if( hw->modes & PAT_16BIT ) { - q->nLength >>= 1; - q->nLoopStart >>= 1; - q->nLoopEnd >>= 1; - } - if( hw->modes & PAT_LOOP ) { - q->uFlags |= CHN_LOOP; - if( hw->modes & PAT_PINGPONG ) q->uFlags |= CHN_PINGPONGSUSTAIN; - if( hw->modes & PAT_SUSTAIN ) q->uFlags |= CHN_SUSTAINLOOP; - } -} -#endif - -// ========================== -// Load those darned Samples! -#ifdef NEWMIKMOD -static void PATsample(UNIMOD *of, UNISAMPLE *q, int smp, int gm) -#else -static void PATsample(CSoundFile *cs, MODINSTRUMENT *q, int smp, int gm) -#endif -{ - WaveHeader hw; - char s[32]; - sprintf(s, "%d:%s", smp-1, midipat[gm-1]); -#ifdef NEWMIKMOD - q->samplename = DupStr(of->allochandle, s,28); - if( pat_readpat_attr(gm-1, &hw, 0) ) { - pat_setpat_attr(&hw, q, gm); - pat_loops[smp-1] = (q->flags & (SL_LOOP | SL_SUSTAIN_LOOP))? 1: 0; - } - else { - q->seekpos = smp + MAXSMP + 1; // dec_pat expects the samplenumber in this - q->speed = C4SPD; - q->length = 30000; - q->loopstart = 0; - q->loopend = 30000; - q->volume = 0x40; - - // Enable aggressive declicking for songs that do not loop and that - // are long enough that they won't be adversely affected. - - q->flags |= SL_LOOP; - q->format |= SF_16BITS; - q->format |= SF_SIGNED; - } - if(!(q->flags & (SL_LOOP | SL_SUSTAIN_LOOP)) && (q->length > 5000)) - q->flags |= SL_DECLICK; -#else - s[31] = '\0'; - memset(cs->m_szNames[smp], 0, 32); - strcpy(cs->m_szNames[smp], s); - q->nGlobalVol = 64; - q->nPan = 128; - q->uFlags = CHN_16BIT; - if( pat_readpat_attr(gm-1, &hw, 0) ) { - char *p; - pat_setpat_attr(&hw, q); - pat_loops[smp-1] = (q->uFlags & CHN_LOOP)? 1: 0; - if( hw.modes & PAT_16BIT ) p = (char *)malloc(hw.wave_size); - else p = (char *)malloc(hw.wave_size * sizeof(short int)); - if( p ) { - if( hw.modes & PAT_16BIT ) { - dec_pat_Decompress16Bit((short int *)p, hw.wave_size>>1, gm - 1); - cs->ReadSample(q, (hw.modes&PAT_UNSIGNED)?RS_PCM16U:RS_PCM16S, (LPSTR)p, hw.wave_size); - } - else { - dec_pat_Decompress8Bit((short int *)p, hw.wave_size, gm - 1); - cs->ReadSample(q, (hw.modes&PAT_UNSIGNED)?RS_PCM16U:RS_PCM16S, (LPSTR)p, hw.wave_size * sizeof(short int)); - } - free(p); - } - } - else { - char *p; - q->nC4Speed = C4SPD; - q->nLength = 30000; - q->nLoopStart = 0; - q->nLoopEnd = 30000; - q->nVolume = 256; - q->uFlags |= CHN_LOOP; - q->uFlags |= CHN_16BIT; - p = (char *)malloc(q->nLength*sizeof(short int)); - if( p ) { - dec_pat_Decompress8Bit((short int *)p, q->nLength, smp + MAXSMP - 1); - cs->ReadSample(q, RS_PCM16S, (LPSTR)p, q->nLength*2); - free(p); - } - } -#endif -} - -// ===================================================================================== -BOOL PAT_Load_Instruments(void *c) -{ - uint32_t t; -#ifdef NEWMIKMOD - UNIMOD *of = (UNIMOD *)c; - INSTRUMENT *d; - UNISAMPLE *q; - if( !pat_numsmp() ) pat_gmtosmp(1); // make sure there is a sample - of->numsmp = pat_numsmp(); - of->numins = pat_numinstr(); - if(!AllocInstruments(of)) return FALSE; - if(!AllocSamples(of, 0)) return FALSE; - d = of->instruments; - for(t=1; t<=of->numins; t++) { - PATinst(of, d, t, pat_smptogm(t)); - d++; - } - q = of->samples; - for(t=1; t<=of->numsmp; t++) { - PATsample(of, q, t, pat_smptogm(t)); - q++; - } - SL_RegisterDecompressor(&dec_pat); // fool him to generate samples -#else - CSoundFile *of=(CSoundFile *)c; - if( !pat_numsmp() ) pat_gmtosmp(1); // make sure there is a sample - of->m_nSamples = pat_numsmp() + 1; // xmms modplug does not use slot zero - of->m_nInstruments = pat_numinstr() + 1; - for(t=1; t<of->m_nInstruments; t++) { // xmms modplug doesn't use slot zero - if( (of->Headers[t] = new INSTRUMENTHEADER) == NULL ) return FALSE; - memset(of->Headers[t], 0, sizeof(INSTRUMENTHEADER)); - PATinst(of->Headers[t], t, pat_smptogm(t)); - } - for(t=1; t<of->m_nSamples; t++) { // xmms modplug doesn't use slot zero - PATsample(of, &of->Ins[t], t, pat_smptogm(t)); - } - // copy last of the mohicans to entry 0 for XMMS modinfo to work.... - t = of->m_nInstruments - 1; - if( (of->Headers[0] = new INSTRUMENTHEADER) == NULL ) return FALSE; - memcpy(of->Headers[0], of->Headers[t], sizeof(INSTRUMENTHEADER)); - memset(of->Headers[0]->name, 0, 32); - strncpy((char *)of->Headers[0]->name, "Timidity GM patches", 32); - t = of->m_nSamples - 1; - memcpy(&of->Ins[0], &of->Ins[t], sizeof(MODINSTRUMENT)); -#endif - return TRUE; -} -// ===================================================================================== -#ifdef NEWMIKMOD -BOOL PAT_Load(PATHANDLE *h, UNIMOD *of, MMSTREAM *mmfile) -#else -BOOL CSoundFile::ReadPAT(const BYTE *lpStream, DWORD dwMemLength) -#endif -{ - static int avoid_reentry = 0; - char buf[60]; - int t; -#ifdef NEWMIKMOD - UNISAMPLE *q; - INSTRUMENT *d; -#define m_nDefaultTempo of->inittempo -#else - PATHANDLE *h; - int numpat; - MMFILE mm, *mmfile; - MODINSTRUMENT *q; - INSTRUMENTHEADER *d; - if( !TestPAT(lpStream, dwMemLength) ) return FALSE; - h = PAT_Init(); - if( !h ) return FALSE; - mmfile = &mm; - mm.mm = (char *)lpStream; - mm.sz = dwMemLength; - mm.pos = 0; -#endif - while( avoid_reentry ) sleep(1); - avoid_reentry = 1; - pat_read_patname(h, mmfile); - h->samples = pat_read_numsmp(mmfile); - if( strlen(h->patname) ) - sprintf(buf,"%s canon %d-v (Fr. Jacques)", h->patname, h->samples); - else - sprintf(buf,"%d-voice canon (Fr. Jacques)", h->samples); -#ifdef NEWMIKMOD - of->songname = DupStr(of->allochandle, buf, strlen(buf)); -#else - if( strlen(buf) > 31 ) buf[31] = '\0'; // chop it of - strcpy(m_szNames[0], buf); -#endif - m_nDefaultTempo = 60; // 120 / 2 - t = (h->samples - 1) * 16 + 128; - if( t % 64 ) t += 64; - t = t / 64; -#ifdef NEWMIKMOD - of->memsize = PTMEM_LAST; // Number of memory slots to reserve! - of->modtype = _mm_strdup(of->allochandle, PAT_Version); - of->reppos = 0; - of->numins = h->samples; - of->numsmp = h->samples; - of->initspeed = 6; - of->numchn = h->samples; - of->numpat = t; - of->numpos = of->numpat; // one repeating pattern - of->numtrk = of->numpat * of->numchn; - of->initvolume = 64; - of->pansep=128; - // allocate resources - if(!AllocPositions(of, of->numpos)) { - avoid_reentry = 0; - return FALSE; - } - if(!AllocInstruments(of)) { - avoid_reentry = 0; - return FALSE; - } - if(!AllocSamples(of, 0)) { - avoid_reentry = 0; - return FALSE; - } - // orderlist - for(t=0; t<of->numpos; t++) - of->positions[t] = t; - d = of->instruments; - for(t=1; t<=of->numins; t++) { - WaveHeader hw; - char s[32]; - sprintf(s, "%s", h->patname); - d->insname = DupStr(of->allochandle, s,28); - pat_read_waveheader(mmfile, &hw, t); - pat_setpat_inst(&hw, d, t); - } - q = of->samples; - for(t=1; t<=of->numsmp; t++) { - WaveHeader hw; - char s[28]; - pat_read_waveheader(mmfile, &hw, t); - pat_setpat_attr(&hw, q, _mm_ftell(mmfile)); - memset(s,0,28); - if( hw.wave_name[0] ) - sprintf(s, "%d:%s", t, hw.wave_name); - else - sprintf(s, "%d:%s", t, h->patname); - q->samplename = DupStr(of->allochandle, s,28); - if(!(q->flags & (SL_LOOP | SL_SUSTAIN_LOOP)) && (q->length > 5000)) - q->flags |= SL_DECLICK; - q++; - } -#else - m_nType = MOD_TYPE_PAT; - m_nInstruments = h->samples + 1; // we know better but use each sample in the pat... - m_nSamples = h->samples + 1; // xmms modplug does not use slot zero - m_nDefaultSpeed = 6; - m_nChannels = h->samples; - numpat = t; - - m_dwSongFlags = SONG_LINEARSLIDES; - m_nMinPeriod = 28 << 2; - m_nMaxPeriod = 1712 << 3; - // orderlist - for(t=0; t < numpat; t++) - Order[t] = t; - for(t=1; t<(int)m_nInstruments; t++) { // xmms modplug doesn't use slot zero - WaveHeader hw; - char s[32]; - if( (d = new INSTRUMENTHEADER) == NULL ) { - avoid_reentry = 0; - return FALSE; - } - memset(d, 0, sizeof(INSTRUMENTHEADER)); - Headers[t] = d; - sprintf(s, "%s", h->patname); - s[31] = '\0'; - memset(d->name, 0, 32); - strcpy((char *)d->name, s); - s[11] = '\0'; - memset(d->filename, 0, 12); - strcpy((char *)d->filename, s); - pat_get_waveheader(mmfile, &hw, t); - pat_setpat_inst(&hw, d, t); - } - for(t=1; t<(int)m_nSamples; t++) { // xmms modplug doesn't use slot zero - WaveHeader hw; - char s[32]; - char *p; - q = &Ins[t]; // we do not use slot zero - q->nGlobalVol = 64; - q->nPan = 128; - q->uFlags = CHN_16BIT; - pat_get_waveheader(mmfile, &hw, t); - pat_setpat_attr(&hw, q); - memset(s,0,32); - if( hw.wave_name[0] ) - sprintf(s, "%d:%s", t, hw.wave_name); - else { - if( h->patname[0] ) - sprintf(s, "%d:%s", t, h->patname); - else - sprintf(s, "%d:Untitled GM patch", t); - } - s[31] = '\0'; - memset(m_szNames[t], 0, 32); - strcpy(m_szNames[t], s); - if( hw.modes & PAT_16BIT ) p = (char *)malloc(hw.wave_size); - else p = (char *)malloc(hw.wave_size * sizeof(short int)); - if( p ) { - mmreadSBYTES(p, hw.wave_size, mmfile); - if( hw.modes & PAT_16BIT ) { - ReadSample(q, (hw.modes&PAT_UNSIGNED)?RS_PCM16U:RS_PCM16S, (LPSTR)p, hw.wave_size); - } - else { - pat_blowup_to16bit((short int *)p, hw.wave_size); - ReadSample(q, (hw.modes&PAT_UNSIGNED)?RS_PCM16U:RS_PCM16S, (LPSTR)p, hw.wave_size * sizeof(short int)); - } - free(p); - } - } - // copy last of the mohicans to entry 0 for XMMS modinfo to work.... - t = m_nInstruments - 1; - if( (Headers[0] = new INSTRUMENTHEADER) == NULL ) { - avoid_reentry = 0; - return FALSE; - } - memcpy(Headers[0], Headers[t], sizeof(INSTRUMENTHEADER)); - memset(Headers[0]->name, 0, 32); - if( h->patname[0] ) - strncpy((char *)Headers[0]->name, h->patname, 32); - else - strncpy((char *)Headers[0]->name, "Timidity GM patch", 32); - t = m_nSamples - 1; - memcpy(&Ins[0], &Ins[t], sizeof(MODINSTRUMENT)); -#endif -#ifdef NEWMIKMOD - // ============================== - // Load the pattern info now! - if(!AllocTracks(of)) return 0; - if(!AllocPatterns(of)) return 0; - of->ut = utrk_init(of->numchn, h->allochandle); - utrk_memory_reset(of->ut); - utrk_local_memflag(of->ut, PTMEM_PORTAMENTO, TRUE, FALSE); - PAT_ReadPatterns(of, h, of->numpat); - // ============================================================ - // set panning positions - for(t=0; t<of->numchn; t++) { - of->panning[t] = PAN_LEFT+((t+2)%5)*((PAN_RIGHT - PAN_LEFT)/5); // 0x30 = std s3m val - } -#else - // ============================== - // Load the pattern info now! - PAT_ReadPatterns(Patterns, PatternSize, h, numpat); - // ============================================================ - // set panning positions - for(t=0; t<(int)m_nChannels; t++) { - ChnSettings[t].nPan = 0x30+((t+2)%5)*((0xD0 - 0x30)/5); // 0x30 = std s3m val - ChnSettings[t].nVolume = 64; - } -#endif - avoid_reentry = 0; // it is safe now, I'm finished -#ifndef NEWMIKMOD - PAT_Cleanup(h); // we dont need it anymore -#endif - return 1; -} - -#ifdef NEWMIKMOD -// ===================================================================================== -CHAR *PAT_LoadTitle(MMSTREAM *mmfile) -// ===================================================================================== -{ - PATHANDLE dummy; - pat_read_patname(&dummy, mmfile); - return(DupStr(NULL, dummy.patname,strlen(dummy.patname))); -} - -MLOADER load_pat = -{ - "PAT", - "PAT loader 1.0", - 0x30, - NULL, - PAT_Test, - (void *(*)(void))PAT_Init, - (void (*)(ML_HANDLE *))PAT_Cleanup, - /* Every single loader seems to need one of these! */ - (BOOL (*)(ML_HANDLE *, UNIMOD *, MMSTREAM *))PAT_Load, - PAT_LoadTitle -}; -#endif diff --git a/lib/libmodplug/src/load_pat.h b/lib/libmodplug/src/load_pat.h deleted file mode 100644 index 21db1f7ba8..0000000000 --- a/lib/libmodplug/src/load_pat.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef LOAD_PAT_H -#define LOAD_PAT_H - -#ifdef __cplusplus -extern "C" { -#endif - -void pat_init_patnames(void); -void pat_resetsmp(void); -int pat_numinstr(void); -int pat_numsmp(void); -int pat_smptogm(int smp); -int pat_gmtosmp(int gm); -int pat_gm_drumnr(int n); -int pat_gm_drumnote(int n); -const char *pat_gm_name(int gm); -int pat_modnote(int midinote); -int pat_smplooped(int smp); -//#ifdef NEWMIKMOD -BOOL PAT_Load_Instruments(void *c); -//#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/libmodplug/src/load_psm.cpp b/lib/libmodplug/src/load_psm.cpp deleted file mode 100644 index 19966a680a..0000000000 --- a/lib/libmodplug/src/load_psm.cpp +++ /dev/null @@ -1,839 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque <olivierl@jps.net> -*/ - - -/////////////////////////////////////////////////// -// -// PSM module loader -// -/////////////////////////////////////////////////// -#include "stdafx.h" -#include "sndfile.h" - -//#define PSM_LOG - -#define PSM_ID_NEW 0x204d5350 -#define PSM_ID_OLD 0xfe4d5350 -#define IFFID_FILE 0x454c4946 -#define IFFID_TITL 0x4c544954 -#define IFFID_SDFT 0x54464453 -#define IFFID_PBOD 0x444f4250 -#define IFFID_SONG 0x474e4f53 -#define IFFID_PATT 0x54544150 -#define IFFID_DSMP 0x504d5344 -#define IFFID_OPLH 0x484c504f - -#pragma pack(1) - -typedef struct _PSMCHUNK -{ - DWORD id; - DWORD len; - DWORD listid; -} PSMCHUNK; - -typedef struct _PSMSONGHDR -{ - CHAR songname[8]; // "MAINSONG" - BYTE reserved1; - BYTE reserved2; - BYTE channels; -} PSMSONGHDR; - -typedef struct _PSMPATTERN -{ - DWORD size; - DWORD name; - WORD rows; - WORD reserved1; - BYTE data[4]; -} PSMPATTERN; - -typedef struct _PSMSAMPLE -{ - BYTE flags; - CHAR songname[8]; - DWORD smpid; - CHAR samplename[34]; - DWORD reserved1; - BYTE reserved2; - BYTE insno; - BYTE reserved3; - DWORD length; - DWORD loopstart; - DWORD loopend; - WORD reserved4; - BYTE defvol; - DWORD reserved5; - DWORD samplerate; - BYTE reserved6[19]; -} PSMSAMPLE; - -#pragma pack() - - -BOOL CSoundFile::ReadPSM(LPCBYTE lpStream, DWORD dwMemLength) -//----------------------------------------------------------- -{ - PSMCHUNK *pfh = (PSMCHUNK *)lpStream; - DWORD dwMemPos, dwSongPos; - DWORD smpnames[MAX_SAMPLES]; - DWORD patptrs[MAX_PATTERNS]; - BYTE samplemap[MAX_SAMPLES]; - UINT nPatterns; - - // Chunk0: "PSM ",filesize,"FILE" - if (dwMemLength < 256) return FALSE; - if (pfh->id == PSM_ID_OLD) - { - #ifdef PSM_LOG - Log("Old PSM format not supported\n"); - #endif - return FALSE; - } - if ((pfh->id != PSM_ID_NEW) || (pfh->len+12 > dwMemLength) || (pfh->listid != IFFID_FILE)) return FALSE; - m_nType = MOD_TYPE_PSM; - m_nChannels = 16; - m_nSamples = 0; - nPatterns = 0; - dwMemPos = 12; - dwSongPos = 0; - for (UINT iChPan=0; iChPan<16; iChPan++) - { - UINT pan = (((iChPan & 3) == 1) || ((iChPan&3)==2)) ? 0xC0 : 0x40; - ChnSettings[iChPan].nPan = pan; - } - while (dwMemPos+8 < dwMemLength) - { - PSMCHUNK *pchunk = (PSMCHUNK *)(lpStream+dwMemPos); - if ((pchunk->len >= dwMemLength - 8) || (dwMemPos + pchunk->len + 8 > dwMemLength)) break; - dwMemPos += 8; - PUCHAR pdata = (PUCHAR)(lpStream+dwMemPos); - ULONG len = pchunk->len; - if (len) switch(pchunk->id) - { - // "TITL": Song title - case IFFID_TITL: - if (!pdata[0]) { pdata++; len--; } - memcpy(m_szNames[0], pdata, (len>31) ? 31 : len); - m_szNames[0][31] = 0; - break; - // "PBOD": Pattern - case IFFID_PBOD: - if ((len >= 12) && (nPatterns < MAX_PATTERNS)) - { - patptrs[nPatterns++] = dwMemPos-8; - } - break; - // "SONG": Song description - case IFFID_SONG: - if ((len >= sizeof(PSMSONGHDR)+8) && (!dwSongPos)) - { - dwSongPos = dwMemPos - 8; - } - break; - // "DSMP": Sample Data - case IFFID_DSMP: - if ((len >= sizeof(PSMSAMPLE)) && (m_nSamples+1 < MAX_SAMPLES)) - { - m_nSamples++; - MODINSTRUMENT *pins = &Ins[m_nSamples]; - PSMSAMPLE *psmp = (PSMSAMPLE *)pdata; - smpnames[m_nSamples] = psmp->smpid; - memcpy(m_szNames[m_nSamples], psmp->samplename, 31); - m_szNames[m_nSamples][31] = 0; - samplemap[m_nSamples-1] = (BYTE)m_nSamples; - // Init sample - pins->nGlobalVol = 0x40; - pins->nC4Speed = psmp->samplerate; - pins->nLength = psmp->length; - pins->nLoopStart = psmp->loopstart; - pins->nLoopEnd = psmp->loopend; - pins->nPan = 128; - pins->nVolume = (psmp->defvol+1) * 2; - pins->uFlags = (psmp->flags & 0x80) ? CHN_LOOP : 0; - if (pins->nLoopStart > 0) pins->nLoopStart--; - // Point to sample data - pdata += 0x60; - len -= 0x60; - // Load sample data - if ((pins->nLength > 3) && (len > 3)) - { - ReadSample(pins, RS_PCM8D, (LPCSTR)pdata, len); - } else - { - pins->nLength = 0; - } - } - break; - #if 0 - default: - { - CHAR s[8], s2[64]; - *(DWORD *)s = pchunk->id; - s[4] = 0; - wsprintf(s2, "%s: %4d bytes @ %4d\n", s, pchunk->len, dwMemPos); - OutputDebugString(s2); - } - #endif - } - dwMemPos += pchunk->len; - } - // Step #1: convert song structure - PSMSONGHDR *pSong = (PSMSONGHDR *)(lpStream+dwSongPos+8); - if ((!dwSongPos) || (pSong->channels < 2) || (pSong->channels > 32)) return TRUE; - m_nChannels = pSong->channels; - // Valid song header -> convert attached chunks - { - DWORD dwSongEnd = dwSongPos + 8 + *(DWORD *)(lpStream+dwSongPos+4); - dwMemPos = dwSongPos + 8 + 11; // sizeof(PSMCHUNK)+sizeof(PSMSONGHDR) - while (dwMemPos + 8 < dwSongEnd) - { - PSMCHUNK *pchunk = (PSMCHUNK *)(lpStream+dwMemPos); - dwMemPos += 8; - if ((pchunk->len > dwSongEnd) || (dwMemPos + pchunk->len > dwSongEnd)) break; - PUCHAR pdata = (PUCHAR)(lpStream+dwMemPos); - ULONG len = pchunk->len; - switch(pchunk->id) - { - case IFFID_OPLH: - if (len >= 0x20) - { - UINT pos = len - 3; - while (pos > 5) - { - BOOL bFound = FALSE; - pos -= 5; - DWORD dwName = *(DWORD *)(pdata+pos); - for (UINT i=0; i<nPatterns; i++) - { - DWORD dwPatName = ((PSMPATTERN *)(lpStream+patptrs[i]+8))->name; - if (dwName == dwPatName) - { - bFound = TRUE; - break; - } - } - if ((!bFound) && (pdata[pos+1] > 0) && (pdata[pos+1] <= 0x10) - && (pdata[pos+3] > 0x40) && (pdata[pos+3] < 0xC0)) - { - m_nDefaultSpeed = pdata[pos+1]; - m_nDefaultTempo = pdata[pos+3]; - break; - } - } - UINT iOrd = 0; - while ((pos+5<len) && (iOrd < MAX_ORDERS)) - { - DWORD dwName = *(DWORD *)(pdata+pos); - for (UINT i=0; i<nPatterns; i++) - { - DWORD dwPatName = ((PSMPATTERN *)(lpStream+patptrs[i]+8))->name; - if (dwName == dwPatName) - { - Order[iOrd++] = i; - break; - } - } - pos += 5; - } - } - break; - } - dwMemPos += pchunk->len; - } - } - - // Step #2: convert patterns - for (UINT nPat=0; nPat<nPatterns; nPat++) - { - PSMPATTERN *pPsmPat = (PSMPATTERN *)(lpStream+patptrs[nPat]+8); - ULONG len = *(DWORD *)(lpStream+patptrs[nPat]+4) - 12; - UINT nRows = pPsmPat->rows; - if (len > pPsmPat->size) len = pPsmPat->size; - if ((nRows < 64) || (nRows > 256)) nRows = 64; - PatternSize[nPat] = nRows; - if ((Patterns[nPat] = AllocatePattern(nRows, m_nChannels)) == NULL) break; - MODCOMMAND *m = Patterns[nPat]; - BYTE *p = pPsmPat->data; - UINT pos = 0; - UINT row = 0; - UINT oldch = 0; - BOOL bNewRow = FALSE; - #ifdef PSM_LOG - Log("Pattern %d at offset 0x%04X\n", nPat, (DWORD)(p - (BYTE *)lpStream)); - #endif - while ((row < nRows) && (pos+1 < len)) - { - UINT flags = p[pos++]; - UINT ch = p[pos++]; - - #ifdef PSM_LOG - //Log("flags+ch: %02X.%02X\n", flags, ch); - #endif - if (((flags & 0xf0) == 0x10) && (ch <= oldch) /*&& (!bNewRow)*/) - { - if ((pos+1<len) && (!(p[pos] & 0x0f)) && (p[pos+1] < m_nChannels)) - { - #ifdef PSM_LOG - //if (!nPat) Log("Continuing on new row\n"); - #endif - row++; - m += m_nChannels; - oldch = ch; - continue; - } - } - if ((pos >= len) || (row >= nRows)) break; - if (!(flags & 0xf0)) - { - #ifdef PSM_LOG - //if (!nPat) Log("EOR(%d): %02X.%02X\n", row, p[pos], p[pos+1]); - #endif - row++; - m += m_nChannels; - bNewRow = TRUE; - oldch = ch; - continue; - } - bNewRow = FALSE; - if (ch >= m_nChannels) - { - #ifdef PSM_LOG - if (!nPat) Log("Invalid channel row=%d (0x%02X.0x%02X)\n", row, flags, ch); - #endif - ch = 0; - } - // Note + Instr - if ((flags & 0x40) && (pos+1 < len)) - { - UINT note = p[pos++]; - UINT nins = p[pos++]; - #ifdef PSM_LOG - //if (!nPat) Log("note+ins: %02X.%02X\n", note, nins); - if ((!nPat) && (nins >= m_nSamples)) Log("WARNING: invalid instrument number (%d)\n", nins); - #endif - if ((note) && (note < 0x80)) note = (note>>4)*12+(note&0x0f)+12+1; - m[ch].instr = samplemap[nins]; - m[ch].note = note; - } - // Volume - if ((flags & 0x20) && (pos < len)) - { - m[ch].volcmd = VOLCMD_VOLUME; - m[ch].vol = p[pos++] / 2; - } - // Effect - if ((flags & 0x10) && (pos+1 < len)) - { - UINT command = p[pos++]; - UINT param = p[pos++]; - // Convert effects - switch(command) - { - // 01: fine volslide up - case 0x01: command = CMD_VOLUMESLIDE; param |= 0x0f; break; - // 04: fine volslide down - case 0x04: command = CMD_VOLUMESLIDE; param>>=4; param |= 0xf0; break; - // 0C: portamento up - case 0x0C: command = CMD_PORTAMENTOUP; param = (param+1)/2; break; - // 0E: portamento down - case 0x0E: command = CMD_PORTAMENTODOWN; param = (param+1)/2; break; - // 33: Position Jump - case 0x33: command = CMD_POSITIONJUMP; break; - // 34: Pattern break - case 0x34: command = CMD_PATTERNBREAK; break; - // 3D: speed - case 0x3D: command = CMD_SPEED; break; - // 3E: tempo - case 0x3E: command = CMD_TEMPO; break; - // Unknown - default: - #ifdef PSM_LOG - Log("Unknown PSM effect pat=%d row=%d ch=%d: %02X.%02X\n", nPat, row, ch, command, param); - #endif - command = param = 0; - } - m[ch].command = (BYTE)command; - m[ch].param = (BYTE)param; - } - oldch = ch; - } - #ifdef PSM_LOG - if (pos < len) - { - Log("Pattern %d: %d/%d[%d] rows (%d bytes) -> %d bytes left\n", nPat, row, nRows, pPsmPat->rows, pPsmPat->size, len-pos); - } - #endif - } - - // Done (finally!) - return TRUE; -} - - -////////////////////////////////////////////////////////////// -// -// PSM Old Format -// - -/* - -CONST - c_PSM_MaxOrder = $FF; - c_PSM_MaxSample = $FF; - c_PSM_MaxChannel = $0F; - - TYPE - PPSM_Header = ^TPSM_Header; - TPSM_Header = RECORD - PSM_Sign : ARRAY[01..04] OF CHAR; { PSM + #254 } - PSM_SongName : ARRAY[01..58] OF CHAR; - PSM_Byte00 : BYTE; - PSM_Byte1A : BYTE; - PSM_Unknown00 : BYTE; - PSM_Unknown01 : BYTE; - PSM_Unknown02 : BYTE; - PSM_Speed : BYTE; - PSM_Tempo : BYTE; - PSM_Unknown03 : BYTE; - PSM_Unknown04 : WORD; - PSM_OrderLength : WORD; - PSM_PatternNumber : WORD; - PSM_SampleNumber : WORD; - PSM_ChannelNumber : WORD; - PSM_ChannelUsed : WORD; - PSM_OrderPosition : LONGINT; - PSM_ChannelSettingPosition : LONGINT; - PSM_PatternPosition : LONGINT; - PSM_SamplePosition : LONGINT; - { *** perhaps there are some more infos in a larger header, - but i have not decoded it and so it apears here NOT } - END; - - PPSM_Sample = ^TPSM_Sample; - TPSM_Sample = RECORD - PSM_SampleFileName : ARRAY[01..12] OF CHAR; - PSM_SampleByte00 : BYTE; - PSM_SampleName : ARRAY[01..22] OF CHAR; - PSM_SampleUnknown00 : ARRAY[01..02] OF BYTE; - PSM_SamplePosition : LONGINT; - PSM_SampleUnknown01 : ARRAY[01..04] OF BYTE; - PSM_SampleNumber : BYTE; - PSM_SampleFlags : WORD; - PSM_SampleLength : LONGINT; - PSM_SampleLoopBegin : LONGINT; - PSM_SampleLoopEnd : LONGINT; - PSM_Unknown03 : BYTE; - PSM_SampleVolume : BYTE; - PSM_SampleC5Speed : WORD; - END; - - PPSM_SampleList = ^TPSM_SampleList; - TPSM_SampleList = ARRAY[01..c_PSM_MaxSample] OF TPSM_Sample; - - PPSM_Order = ^TPSM_Order; - TPSM_Order = ARRAY[00..c_PSM_MaxOrder] OF BYTE; - - PPSM_ChannelSettings = ^TPSM_ChannelSettings; - TPSM_ChannelSettings = ARRAY[00..c_PSM_MaxChannel] OF BYTE; - - CONST - PSM_NotesInPattern : BYTE = $00; - PSM_ChannelInPattern : BYTE = $00; - - CONST - c_PSM_SetSpeed = 60; - - FUNCTION PSM_Size(FileName : STRING;FilePosition : LONGINT) : LONGINT; - BEGIN - END; - - PROCEDURE PSM_UnpackPattern(VAR Source,Destination;PatternLength : WORD); - VAR - Witz : ARRAY[00..04] OF WORD; - I1,I2 : WORD; - I3,I4 : WORD; - TopicalByte : ^BYTE; - Pattern : PUnpackedPattern; - ChannelP : BYTE; - NoteP : BYTE; - InfoByte : BYTE; - CodeByte : BYTE; - InfoWord : WORD; - Effect : BYTE; - Opperand : BYTE; - Panning : BYTE; - Volume : BYTE; - PrevInfo : BYTE; - InfoIndex : BYTE; - BEGIN - Pattern := @Destination; - TopicalByte := @Source; - { *** Initialize patttern } - FOR I2 := 0 TO c_Maximum_NoteIndex DO - FOR I3 := 0 TO c_Maximum_ChannelIndex DO - BEGIN - Pattern^[I2,I3,c_Pattern_NoteIndex] := $FF; - Pattern^[I2,I3,c_Pattern_SampleIndex] := $00; - Pattern^[I2,I3,c_Pattern_VolumeIndex] := $FF; - Pattern^[I2,I3,c_Pattern_PanningIndex] := $FF; - Pattern^[I2,I3,c_Pattern_EffectIndex] := $00; - Pattern^[I2,I3,c_Pattern_OpperandIndex] := $00; - END; - { *** Byte-pointer on first pattern-entry } - ChannelP := $00; - NoteP := $00; - InfoByte := $00; - PrevInfo := $00; - InfoIndex := $02; - { *** read notes in pattern } - PSM_NotesInPattern := TopicalByte^; INC(TopicalByte); DEC(PatternLength); INC(InfoIndex); - PSM_ChannelInPattern := TopicalByte^; INC(TopicalByte); DEC(PatternLength); INC(InfoIndex); - { *** unpack pattern } - WHILE (INTEGER(PatternLength) > 0) AND (NoteP < c_Maximum_NoteIndex) DO - BEGIN - { *** Read info-byte } - InfoByte := TopicalByte^; INC(TopicalByte); DEC(PatternLength); INC(InfoIndex); - IF InfoByte <> $00 THEN - BEGIN - ChannelP := InfoByte AND $0F; - IF InfoByte AND 128 = 128 THEN { note and sample } - BEGIN - { *** read note } - CodeByte := TopicalByte^; INC(TopicalByte); DEC(PatternLength); - DEC(CodeByte); - CodeByte := CodeByte MOD 12 * 16 + CodeByte DIV 12 + 2; - Pattern^[NoteP,ChannelP,c_Pattern_NoteIndex] := CodeByte; - { *** read sample } - CodeByte := TopicalByte^; INC(TopicalByte); DEC(PatternLength); - Pattern^[NoteP,ChannelP,c_Pattern_SampleIndex] := CodeByte; - END; - IF InfoByte AND 64 = 64 THEN { Volume } - BEGIN - CodeByte := TopicalByte^; INC(TopicalByte); DEC(PatternLength); - Pattern^[NoteP,ChannelP,c_Pattern_VolumeIndex] := CodeByte; - END; - IF InfoByte AND 32 = 32 THEN { effect AND opperand } - BEGIN - Effect := TopicalByte^; INC(TopicalByte); DEC(PatternLength); - Opperand := TopicalByte^; INC(TopicalByte); DEC(PatternLength); - CASE Effect OF - c_PSM_SetSpeed: - BEGIN - Effect := c_I_Set_Speed; - END; - ELSE - BEGIN - Effect := c_I_NoEffect; - Opperand := $00; - END; - END; - Pattern^[NoteP,ChannelP,c_Pattern_EffectIndex] := Effect; - Pattern^[NoteP,ChannelP,c_Pattern_OpperandIndex] := Opperand; - END; - END ELSE INC(NoteP); - END; - END; - - PROCEDURE PSM_Load(FileName : STRING;FilePosition : LONGINT;VAR Module : PModule;VAR ErrorCode : WORD); - { *** caution : Module has to be inited before!!!! } - VAR - Header : PPSM_Header; - Sample : PPSM_SampleList; - Order : PPSM_Order; - ChannelSettings : PPSM_ChannelSettings; - MultiPurposeBuffer : PByteArray; - PatternBuffer : PUnpackedPattern; - TopicalParaPointer : WORD; - - InFile : FILE; - I1,I2 : WORD; - I3,I4 : WORD; - TempW : WORD; - TempB : BYTE; - TempP : PByteArray; - TempI : INTEGER; - { *** copy-vars for loop-extension } - CopySource : LONGINT; - CopyDestination : LONGINT; - CopyLength : LONGINT; - BEGIN - { *** try to open file } - ASSIGN(InFile,FileName); -{$I-} - RESET(InFile,1); -{$I+} - IF IORESULT <> $00 THEN - BEGIN - EXIT; - END; -{$I-} - { *** seek start of module } - IF FILESIZE(InFile) < FilePosition THEN - BEGIN - EXIT; - END; - SEEK(InFile,FilePosition); - { *** look for enough memory for temporary variables } - IF MEMAVAIL < SIZEOF(TPSM_Header) + SIZEOF(TPSM_SampleList) + - SIZEOF(TPSM_Order) + SIZEOF(TPSM_ChannelSettings) + - SIZEOF(TByteArray) + SIZEOF(TUnpackedPattern) - THEN - BEGIN - EXIT; - END; - { *** init dynamic variables } - NEW(Header); - NEW(Sample); - NEW(Order); - NEW(ChannelSettings); - NEW(MultiPurposeBuffer); - NEW(PatternBuffer); - { *** read header } - BLOCKREAD(InFile,Header^,SIZEOF(TPSM_Header)); - { *** test if this is a DSM-file } - IF NOT ((Header^.PSM_Sign[1] = 'P') AND (Header^.PSM_Sign[2] = 'S') AND - (Header^.PSM_Sign[3] = 'M') AND (Header^.PSM_Sign[4] = #254)) THEN - BEGIN - ErrorCode := c_NoValidFileFormat; - CLOSE(InFile); - EXIT; - END; - { *** read order } - SEEK(InFile,FilePosition + Header^.PSM_OrderPosition); - BLOCKREAD(InFile,Order^,Header^.PSM_OrderLength); - { *** read channelsettings } - SEEK(InFile,FilePosition + Header^.PSM_ChannelSettingPosition); - BLOCKREAD(InFile,ChannelSettings^,SIZEOF(TPSM_ChannelSettings)); - { *** read samplelist } - SEEK(InFile,FilePosition + Header^.PSM_SamplePosition); - BLOCKREAD(InFile,Sample^,Header^.PSM_SampleNumber * SIZEOF(TPSM_Sample)); - { *** copy header to intern NTMIK-structure } - Module^.Module_Sign := 'MF'; - Module^.Module_FileFormatVersion := $0100; - Module^.Module_SampleNumber := Header^.PSM_SampleNumber; - Module^.Module_PatternNumber := Header^.PSM_PatternNumber; - Module^.Module_OrderLength := Header^.PSM_OrderLength; - Module^.Module_ChannelNumber := Header^.PSM_ChannelNumber+1; - Module^.Module_Initial_GlobalVolume := 64; - Module^.Module_Initial_MasterVolume := $C0; - Module^.Module_Initial_Speed := Header^.PSM_Speed; - Module^.Module_Initial_Tempo := Header^.PSM_Tempo; -{ *** paragraph 01 start } - Module^.Module_Flags := c_Module_Flags_ZeroVolume * BYTE(1) + - c_Module_Flags_Stereo * BYTE(1) + - c_Module_Flags_ForceAmigaLimits * BYTE(0) + - c_Module_Flags_Panning * BYTE(1) + - c_Module_Flags_Surround * BYTE(1) + - c_Module_Flags_QualityMixing * BYTE(1) + - c_Module_Flags_FastVolumeSlides * BYTE(0) + - c_Module_Flags_SpecialCustomData * BYTE(0) + - c_Module_Flags_SongName * BYTE(1); - I1 := $01; - WHILE (Header^.PSM_SongName[I1] > #00) AND (I1 < c_Module_SongNameLength) DO - BEGIN - Module^.Module_Name[I1] := Header^.PSM_SongName[I1]; - INC(I1); - END; - Module^.Module_Name[c_Module_SongNameLength] := #00; - { *** Init channelsettings } - FOR I1 := 0 TO c_Maximum_ChannelIndex DO - BEGIN - IF I1 < Header^.PSM_ChannelUsed THEN - BEGIN - { *** channel enabled } - Module^.Module_ChannelSettingPointer^[I1].ChannelSettings_GlobalVolume := 64; - Module^.Module_ChannelSettingPointer^[I1].ChannelSettings_Panning := (ChannelSettings^[I1]) * $08; - Module^.Module_ChannelSettingPointer^[I1].ChannelSettings_Code := I1 + $10 * BYTE(ChannelSettings^[I1] > $08) + - c_ChannelSettings_Code_ChannelEnabled * BYTE(1) + - c_ChannelSettings_Code_ChannelDigital * BYTE(1); - Module^.Module_ChannelSettingPointer^[I1].ChannelSettings_Controls := - c_ChannelSettings_Controls_EnhancedMode * BYTE(1) + - c_ChannelSettings_Controls_SurroundMode * BYTE(0); - END - ELSE - BEGIN - { *** channel disabled } - Module^.Module_ChannelSettingPointer^[I1].ChannelSettings_GlobalVolume := $00; - Module^.Module_ChannelSettingPointer^[I1].ChannelSettings_Panning := $00; - Module^.Module_ChannelSettingPointer^[I1].ChannelSettings_Code := $00; - Module^.Module_ChannelSettingPointer^[I1].ChannelSettings_Controls := $00; - END; - END; - { *** init and copy order } - FILLCHAR(Module^.Module_OrderPointer^,c_Maximum_OrderIndex+1,$FF); - MOVE(Order^,Module^.Module_OrderPointer^,Header^.PSM_OrderLength); - { *** read pattern } - SEEK(InFile,FilePosition + Header^.PSM_PatternPosition); - NTMIK_LoaderPatternNumber := Header^.PSM_PatternNumber-1; - FOR I1 := 0 TO Header^.PSM_PatternNumber-1 DO - BEGIN - NTMIK_LoadPatternProcedure; - { *** read length } - BLOCKREAD(InFile,TempW,2); - { *** read pattern } - BLOCKREAD(InFile,MultiPurposeBuffer^,TempW-2); - { *** unpack pattern and set notes per channel to 64 } - PSM_UnpackPattern(MultiPurposeBuffer^,PatternBuffer^,TempW); - NTMIK_PackPattern(MultiPurposeBuffer^,PatternBuffer^,PSM_NotesInPattern); - TempW := WORD(256) * MultiPurposeBuffer^[01] + MultiPurposeBuffer^[00]; - GETMEM(Module^.Module_PatternPointer^[I1],TempW); - MOVE(MultiPurposeBuffer^,Module^.Module_PatternPointer^[I1]^,TempW); - { *** next pattern } - END; - { *** read samples } - NTMIK_LoaderSampleNumber := Header^.PSM_SampleNumber; - FOR I1 := 1 TO Header^.PSM_SampleNumber DO - BEGIN - NTMIK_LoadSampleProcedure; - { *** get index for sample } - I3 := Sample^[I1].PSM_SampleNumber; - { *** clip PSM-sample } - IF Sample^[I1].PSM_SampleLoopEnd > Sample^[I1].PSM_SampleLength - THEN Sample^[I1].PSM_SampleLoopEnd := Sample^[I1].PSM_SampleLength; - { *** init intern sample } - NEW(Module^.Module_SamplePointer^[I3]); - FILLCHAR(Module^.Module_SamplePointer^[I3]^,SIZEOF(TSample),$00); - FILLCHAR(Module^.Module_SamplePointer^[I3]^.Sample_SampleName,c_Sample_SampleNameLength,#32); - FILLCHAR(Module^.Module_SamplePointer^[I3]^.Sample_FileName,c_Sample_FileNameLength,#32); - { *** copy informations to intern sample } - I2 := $01; - WHILE (Sample^[I1].PSM_SampleName[I2] > #00) AND (I2 < c_Sample_SampleNameLength) DO - BEGIN - Module^.Module_SamplePointer^[I3]^.Sample_SampleName[I2] := Sample^[I1].PSM_SampleName[I2]; - INC(I2); - END; - Module^.Module_SamplePointer^[I3]^.Sample_Sign := 'DF'; - Module^.Module_SamplePointer^[I3]^.Sample_FileFormatVersion := $00100; - Module^.Module_SamplePointer^[I3]^.Sample_Position := $00000000; - Module^.Module_SamplePointer^[I3]^.Sample_Selector := $0000; - Module^.Module_SamplePointer^[I3]^.Sample_Volume := Sample^[I1].PSM_SampleVolume; - Module^.Module_SamplePointer^[I3]^.Sample_LoopCounter := $00; - Module^.Module_SamplePointer^[I3]^.Sample_C5Speed := Sample^[I1].PSM_SampleC5Speed; - Module^.Module_SamplePointer^[I3]^.Sample_Length := Sample^[I1].PSM_SampleLength; - Module^.Module_SamplePointer^[I3]^.Sample_LoopBegin := Sample^[I1].PSM_SampleLoopBegin; - Module^.Module_SamplePointer^[I3]^.Sample_LoopEnd := Sample^[I1].PSM_SampleLoopEnd; - { *** now it's time for the flags } - Module^.Module_SamplePointer^[I3]^.Sample_Flags := - c_Sample_Flags_DigitalSample * BYTE(1) + - c_Sample_Flags_8BitSample * BYTE(1) + - c_Sample_Flags_UnsignedSampleData * BYTE(1) + - c_Sample_Flags_Packed * BYTE(0) + - c_Sample_Flags_LoopCounter * BYTE(0) + - c_Sample_Flags_SampleName * BYTE(1) + - c_Sample_Flags_LoopActive * - BYTE(Sample^[I1].PSM_SampleFlags AND (LONGINT(1) SHL 15) = (LONGINT(1) SHL 15)); - { *** alloc memory for sample-data } - E_Getmem(Module^.Module_SamplePointer^[I3]^.Sample_Selector, - Module^.Module_SamplePointer^[I3]^.Sample_Position, - Module^.Module_SamplePointer^[I3]^.Sample_Length + c_LoopExtensionSize); - { *** read out data } - EPT(TempP).p_Selector := Module^.Module_SamplePointer^[I3]^.Sample_Selector; - EPT(TempP).p_Offset := $0000; - SEEK(InFile,Sample^[I1].PSM_SamplePosition); - E_BLOCKREAD(InFile,TempP^,Module^.Module_SamplePointer^[I3]^.Sample_Length); - { *** 'coz the samples are signed in a DSM-file -> PC-fy them } - IF Module^.Module_SamplePointer^[I3]^.Sample_Length > 4 THEN - BEGIN - CopyLength := Module^.Module_SamplePointer^[I3]^.Sample_Length; - { *** decode sample } - ASM - DB 066h; MOV CX,WORD PTR CopyLength - { *** load sample selector } - MOV ES,WORD PTR TempP[00002h] - DB 066h; XOR SI,SI - DB 066h; XOR DI,DI - XOR AH,AH - { *** conert all bytes } - @@MainLoop: - DB 026h; DB 067h; LODSB - ADD AL,AH - MOV AH,AL - DB 067h; STOSB - DB 066h; LOOP @@MainLoop - END; - { *** make samples unsigned } - ASM - DB 066h; MOV CX,WORD PTR CopyLength - { *** load sample selector } - MOV ES,WORD PTR TempP[00002h] - DB 066h; XOR SI,SI - DB 066h; XOR DI,DI - { *** conert all bytes } - @@MainLoop: - DB 026h; DB 067h; LODSB - SUB AL,080h - DB 067h; STOSB - DB 066h; LOOP @@MainLoop - END; - { *** Create Loop-Extension } - IF Module^.Module_SamplePointer^[I3]^.Sample_Flags AND c_Sample_Flags_LoopActive = c_Sample_Flags_LoopActive THEN - BEGIN - CopySource := Module^.Module_SamplePointer^[I3]^.Sample_LoopBegin; - CopyDestination := Module^.Module_SamplePointer^[I3]^.Sample_LoopEnd; - CopyLength := CopyDestination - CopySource; - ASM - { *** load sample-selector } - MOV ES,WORD PTR TempP[00002h] - DB 066h; MOV DI,WORD PTR CopyDestination - { *** calculate number of full sample-loops to copy } - XOR DX,DX - MOV AX,c_LoopExtensionSize - MOV BX,WORD PTR CopyLength - DIV BX - OR AX,AX - JE @@NoFullLoop - { *** copy some full-loops (size=bx) } - MOV CX,AX - @@InnerLoop: - PUSH CX - DB 066h; MOV SI,WORD PTR CopySource - MOV CX,BX - DB 0F3h; DB 026h,067h,0A4h { REP MOVS BYTE PTR ES:[EDI],ES:[ESI] } - POP CX - LOOP @@InnerLoop - @@NoFullLoop: - { *** calculate number of rest-bytes to copy } - DB 066h; MOV SI,WORD PTR CopySource - MOV CX,DX - DB 0F3h; DB 026h,067h,0A4h { REP MOVS BYTE PTR ES:[EDI],ES:[ESI] } - END; - END - ELSE - BEGIN - CopyDestination := Module^.Module_SamplePointer^[I3]^.Sample_Length; - ASM - { *** load sample-selector } - MOV ES,WORD PTR TempP[00002h] - DB 066h; MOV DI,WORD PTR CopyDestination - { *** clear extension } - MOV CX,c_LoopExtensionSize - MOV AL,080h - DB 0F3h; DB 067h,0AAh { REP STOS BYTE PTR ES:[EDI] } - END; - END; - END; - { *** next sample } - END; - { *** init period-ranges } - NTMIK_MaximumPeriod := $0000D600 SHR 1; - NTMIK_MinimumPeriod := $0000D600 SHR 8; - { *** close file } - CLOSE(InFile); - { *** dispose all dynamic variables } - DISPOSE(Header); - DISPOSE(Sample); - DISPOSE(Order); - DISPOSE(ChannelSettings); - DISPOSE(MultiPurposeBuffer); - DISPOSE(PatternBuffer); - { *** set errorcode to noerror } - ErrorCode := c_NoError; - END; - -*/ - diff --git a/lib/libmodplug/src/load_ptm.cpp b/lib/libmodplug/src/load_ptm.cpp deleted file mode 100644 index 83df89d29f..0000000000 --- a/lib/libmodplug/src/load_ptm.cpp +++ /dev/null @@ -1,208 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque <olivierl@jps.net>, - * Adam Goode <adam@evdebs.org> (endian and char fixes for PPC) -*/ - -////////////////////////////////////////////// -// PTM PolyTracker module loader // -////////////////////////////////////////////// -#include "stdafx.h" -#include "sndfile.h" - -//#pragma warning(disable:4244) - -#pragma pack(1) - -typedef struct PTMFILEHEADER -{ - CHAR songname[28]; // name of song, asciiz string - CHAR eof; // 26 - BYTE version_lo; // 03 version of file, currently 0203h - BYTE version_hi; // 02 - BYTE reserved1; // reserved, set to 0 - WORD norders; // number of orders (0..256) - WORD nsamples; // number of instruments (1..255) - WORD npatterns; // number of patterns (1..128) - WORD nchannels; // number of channels (voices) used (1..32) - WORD fileflags; // set to 0 - WORD reserved2; // reserved, set to 0 - DWORD ptmf_id; // song identification, 'PTMF' or 0x464d5450 - BYTE reserved3[16]; // reserved, set to 0 - BYTE chnpan[32]; // channel panning settings, 0..15, 0 = left, 7 = middle, 15 = right - BYTE orders[256]; // order list, valid entries 0..nOrders-1 - WORD patseg[128]; // pattern offsets (*16) -} PTMFILEHEADER, *LPPTMFILEHEADER; - -#define SIZEOF_PTMFILEHEADER 608 - - -typedef struct PTMSAMPLE -{ - BYTE sampletype; // sample type (bit array) - CHAR filename[12]; // name of external sample file - BYTE volume; // default volume - WORD nC4Spd; // C4 speed - WORD sampleseg; // sample segment (used internally) - WORD fileofs[2]; // offset of sample data - WORD length[2]; // sample size (in bytes) - WORD loopbeg[2]; // start of loop - WORD loopend[2]; // end of loop - WORD gusdata[8]; - char samplename[28]; // name of sample, asciiz // changed from CHAR - DWORD ptms_id; // sample identification, 'PTMS' or 0x534d5450 -} PTMSAMPLE; - -#define SIZEOF_PTMSAMPLE 80 - -#pragma pack() - - -BOOL CSoundFile::ReadPTM(const BYTE *lpStream, DWORD dwMemLength) -//--------------------------------------------------------------- -{ - PTMFILEHEADER pfh = *(LPPTMFILEHEADER)lpStream; - DWORD dwMemPos; - UINT nOrders; - - pfh.norders = bswapLE16(pfh.norders); - pfh.nsamples = bswapLE16(pfh.nsamples); - pfh.npatterns = bswapLE16(pfh.npatterns); - pfh.nchannels = bswapLE16(pfh.nchannels); - pfh.fileflags = bswapLE16(pfh.fileflags); - pfh.reserved2 = bswapLE16(pfh.reserved2); - pfh.ptmf_id = bswapLE32(pfh.ptmf_id); - for (UINT j=0; j<128; j++) - { - pfh.patseg[j] = bswapLE16(pfh.patseg[j]); - } - - if ((!lpStream) || (dwMemLength < 1024)) return FALSE; - if ((pfh.ptmf_id != 0x464d5450) || (!pfh.nchannels) - || (pfh.nchannels > 32) - || (pfh.norders > 256) || (!pfh.norders) - || (!pfh.nsamples) || (pfh.nsamples > 255) - || (!pfh.npatterns) || (pfh.npatterns > 128) - || (SIZEOF_PTMFILEHEADER+pfh.nsamples*SIZEOF_PTMSAMPLE >= (int)dwMemLength)) return FALSE; - memcpy(m_szNames[0], pfh.songname, 28); - m_szNames[0][28] = 0; - m_nType = MOD_TYPE_PTM; - m_nChannels = pfh.nchannels; - m_nSamples = (pfh.nsamples < MAX_SAMPLES) ? pfh.nsamples : MAX_SAMPLES-1; - dwMemPos = SIZEOF_PTMFILEHEADER; - nOrders = (pfh.norders < MAX_ORDERS) ? pfh.norders : MAX_ORDERS-1; - memcpy(Order, pfh.orders, nOrders); - for (UINT ipan=0; ipan<m_nChannels; ipan++) - { - ChnSettings[ipan].nVolume = 64; - ChnSettings[ipan].nPan = ((pfh.chnpan[ipan] & 0x0F) << 4) + 4; - } - for (UINT ismp=0; ismp<m_nSamples; ismp++, dwMemPos += SIZEOF_PTMSAMPLE) - { - MODINSTRUMENT *pins = &Ins[ismp+1]; - PTMSAMPLE *psmp = (PTMSAMPLE *)(lpStream+dwMemPos); - - lstrcpyn(m_szNames[ismp+1], psmp->samplename, 28); - memcpy(pins->name, psmp->filename, 12); - pins->name[12] = 0; - pins->nGlobalVol = 64; - pins->nPan = 128; - pins->nVolume = psmp->volume << 2; - pins->nC4Speed = bswapLE16(psmp->nC4Spd) << 1; - pins->uFlags = 0; - if ((psmp->sampletype & 3) == 1) - { - UINT smpflg = RS_PCM8D; - DWORD samplepos = (psmp->fileofs[1] << 16) + - psmp->fileofs[0]; - pins->nLength = bswapLE32(*(LPDWORD)(psmp->length)); - pins->nLoopStart = bswapLE32(*(LPDWORD)(psmp->loopbeg)); - pins->nLoopEnd = bswapLE32(*(LPDWORD)(psmp->loopend)); - samplepos = bswapLE32(samplepos); - if (psmp->sampletype & 4) pins->uFlags |= CHN_LOOP; - if (psmp->sampletype & 8) pins->uFlags |= CHN_PINGPONGLOOP; - if (psmp->sampletype & 16) - { - pins->uFlags |= CHN_16BIT; - pins->nLength >>= 1; - pins->nLoopStart >>= 1; - pins->nLoopEnd >>= 1; - smpflg = RS_PTM8DTO16; - } - if ((pins->nLength) && (samplepos) && (samplepos < dwMemLength)) - { - ReadSample(pins, smpflg, (LPSTR)(lpStream+samplepos), dwMemLength-samplepos); - } - } - } - // Reading Patterns - for (UINT ipat=0; ipat<pfh.npatterns; ipat++) - { - dwMemPos = ((UINT)pfh.patseg[ipat]) << 4; - if ((!dwMemPos) || (dwMemPos >= dwMemLength)) continue; - PatternSize[ipat] = 64; - if ((Patterns[ipat] = AllocatePattern(64, m_nChannels)) == NULL) break; - // - MODCOMMAND *m = Patterns[ipat]; - for (UINT row=0; ((row < 64) && (dwMemPos < dwMemLength)); ) - { - UINT b = lpStream[dwMemPos++]; - - if (dwMemPos >= dwMemLength) break; - if (b) - { - UINT nChn = b & 0x1F; - - if (b & 0x20) - { - if (dwMemPos + 2 > dwMemLength) break; - m[nChn].note = lpStream[dwMemPos++]; - m[nChn].instr = lpStream[dwMemPos++]; - } - if (b & 0x40) - { - if (dwMemPos + 2 > dwMemLength) break; - m[nChn].command = lpStream[dwMemPos++]; - m[nChn].param = lpStream[dwMemPos++]; - if ((m[nChn].command == 0x0E) && ((m[nChn].param & 0xF0) == 0x80)) - { - m[nChn].command = CMD_S3MCMDEX; - } else - if (m[nChn].command < 0x10) - { - ConvertModCommand(&m[nChn]); - } else - { - switch(m[nChn].command) - { - case 16: - m[nChn].command = CMD_GLOBALVOLUME; - break; - case 17: - m[nChn].command = CMD_RETRIG; - break; - case 18: - m[nChn].command = CMD_FINEVIBRATO; - break; - default: - m[nChn].command = 0; - } - } - } - if (b & 0x80) - { - if (dwMemPos >= dwMemLength) break; - m[nChn].volcmd = VOLCMD_VOLUME; - m[nChn].vol = lpStream[dwMemPos++]; - } - } else - { - row++; - m += m_nChannels; - } - } - } - return TRUE; -} - diff --git a/lib/libmodplug/src/load_s3m.cpp b/lib/libmodplug/src/load_s3m.cpp deleted file mode 100644 index f994f90923..0000000000 --- a/lib/libmodplug/src/load_s3m.cpp +++ /dev/null @@ -1,657 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque <olivierl@jps.net>, - * Adam Goode <adam@evdebs.org> (endian and char fixes for PPC) -*/ - -#include "stdafx.h" -#include "sndfile.h" -#include "tables.h" - -#ifdef _MSC_VER -//#pragma warning(disable:4244) -#endif - -////////////////////////////////////////////////////// -// ScreamTracker S3M file support - -typedef struct tagS3MSAMPLESTRUCT -{ - BYTE type; - CHAR dosname[12]; - BYTE hmem; - WORD memseg; - DWORD length; - DWORD loopbegin; - DWORD loopend; - BYTE vol; - BYTE bReserved; - BYTE pack; - BYTE flags; - DWORD finetune; - DWORD dwReserved; - WORD intgp; - WORD int512; - DWORD lastused; - CHAR name[28]; - CHAR scrs[4]; -} S3MSAMPLESTRUCT; - - -typedef struct tagS3MFILEHEADER -{ - CHAR name[28]; - BYTE b1A; - BYTE type; - WORD reserved1; - WORD ordnum; - WORD insnum; - WORD patnum; - WORD flags; - WORD cwtv; - WORD version; - DWORD scrm; // "SCRM" = 0x4D524353 - BYTE globalvol; - BYTE speed; - BYTE tempo; - BYTE mastervol; - BYTE ultraclicks; - BYTE panning_present; - BYTE reserved2[8]; - WORD special; - BYTE channels[32]; -} S3MFILEHEADER; - - -void CSoundFile::S3MConvert(MODCOMMAND *m, BOOL bIT) const -//-------------------------------------------------------- -{ - UINT command = m->command; - UINT param = m->param; - switch (command + 0x40) - { - case 'A': command = CMD_SPEED; break; - case 'B': command = CMD_POSITIONJUMP; break; - case 'C': command = CMD_PATTERNBREAK; if (!bIT) param = (param >> 4) * 10 + (param & 0x0F); break; - case 'D': command = CMD_VOLUMESLIDE; break; - case 'E': command = CMD_PORTAMENTODOWN; break; - case 'F': command = CMD_PORTAMENTOUP; break; - case 'G': command = CMD_TONEPORTAMENTO; break; - case 'H': command = CMD_VIBRATO; break; - case 'I': command = CMD_TREMOR; break; - case 'J': command = CMD_ARPEGGIO; break; - case 'K': command = CMD_VIBRATOVOL; break; - case 'L': command = CMD_TONEPORTAVOL; break; - case 'M': command = CMD_CHANNELVOLUME; break; - case 'N': command = CMD_CHANNELVOLSLIDE; break; - case 'O': command = CMD_OFFSET; break; - case 'P': command = CMD_PANNINGSLIDE; break; - case 'Q': command = CMD_RETRIG; break; - case 'R': command = CMD_TREMOLO; break; - case 'S': command = CMD_S3MCMDEX; break; - case 'T': command = CMD_TEMPO; break; - case 'U': command = CMD_FINEVIBRATO; break; - case 'V': command = CMD_GLOBALVOLUME; break; - case 'W': command = CMD_GLOBALVOLSLIDE; break; - case 'X': command = CMD_PANNING8; break; - case 'Y': command = CMD_PANBRELLO; break; - case 'Z': command = CMD_MIDI; break; - default: command = 0; - } - m->command = command; - m->param = param; -} - - -void CSoundFile::S3MSaveConvert(UINT *pcmd, UINT *pprm, BOOL bIT) const -//--------------------------------------------------------------------- -{ - UINT command = *pcmd; - UINT param = *pprm; - switch(command) - { - case CMD_SPEED: command = 'A'; break; - case CMD_POSITIONJUMP: command = 'B'; break; - case CMD_PATTERNBREAK: command = 'C'; if (!bIT) param = ((param / 10) << 4) + (param % 10); break; - case CMD_VOLUMESLIDE: command = 'D'; break; - case CMD_PORTAMENTODOWN: command = 'E'; if ((param >= 0xE0) && (m_nType & (MOD_TYPE_MOD|MOD_TYPE_XM))) param = 0xDF; break; - case CMD_PORTAMENTOUP: command = 'F'; if ((param >= 0xE0) && (m_nType & (MOD_TYPE_MOD|MOD_TYPE_XM))) param = 0xDF; break; - case CMD_TONEPORTAMENTO: command = 'G'; break; - case CMD_VIBRATO: command = 'H'; break; - case CMD_TREMOR: command = 'I'; break; - case CMD_ARPEGGIO: command = 'J'; break; - case CMD_VIBRATOVOL: command = 'K'; break; - case CMD_TONEPORTAVOL: command = 'L'; break; - case CMD_CHANNELVOLUME: command = 'M'; break; - case CMD_CHANNELVOLSLIDE: command = 'N'; break; - case CMD_OFFSET: command = 'O'; break; - case CMD_PANNINGSLIDE: command = 'P'; break; - case CMD_RETRIG: command = 'Q'; break; - case CMD_TREMOLO: command = 'R'; break; - case CMD_S3MCMDEX: command = 'S'; break; - case CMD_TEMPO: command = 'T'; break; - case CMD_FINEVIBRATO: command = 'U'; break; - case CMD_GLOBALVOLUME: command = 'V'; break; - case CMD_GLOBALVOLSLIDE: command = 'W'; break; - case CMD_PANNING8: - command = 'X'; - if ((bIT) && (m_nType != MOD_TYPE_IT) && (m_nType != MOD_TYPE_XM)) - { - if (param == 0xA4) { command = 'S'; param = 0x91; } else - if (param <= 0x80) { param <<= 1; if (param > 255) param = 255; } else - command = param = 0; - } else - if ((!bIT) && ((m_nType == MOD_TYPE_IT) || (m_nType == MOD_TYPE_XM))) - { - param >>= 1; - } - break; - case CMD_PANBRELLO: command = 'Y'; break; - case CMD_MIDI: command = 'Z'; break; - case CMD_XFINEPORTAUPDOWN: - if (param & 0x0F) switch(param & 0xF0) - { - case 0x10: command = 'F'; param = (param & 0x0F) | 0xE0; break; - case 0x20: command = 'E'; param = (param & 0x0F) | 0xE0; break; - case 0x90: command = 'S'; break; - default: command = param = 0; - } else command = param = 0; - break; - case CMD_MODCMDEX: - command = 'S'; - switch(param & 0xF0) - { - case 0x00: command = param = 0; break; - case 0x10: command = 'F'; param |= 0xF0; break; - case 0x20: command = 'E'; param |= 0xF0; break; - case 0x30: param = (param & 0x0F) | 0x10; break; - case 0x40: param = (param & 0x0F) | 0x30; break; - case 0x50: param = (param & 0x0F) | 0x20; break; - case 0x60: param = (param & 0x0F) | 0xB0; break; - case 0x70: param = (param & 0x0F) | 0x40; break; - case 0x90: command = 'Q'; param &= 0x0F; break; - case 0xA0: if (param & 0x0F) { command = 'D'; param = (param << 4) | 0x0F; } else command=param=0; break; - case 0xB0: if (param & 0x0F) { command = 'D'; param |= 0xF0; } else command=param=0; break; - } - break; - default: command = param = 0; - } - command &= ~0x40; - *pcmd = command; - *pprm = param; -} - - -BOOL CSoundFile::ReadS3M(const BYTE *lpStream, DWORD dwMemLength) -//--------------------------------------------------------------- -{ - UINT insnum,patnum,nins,npat; - DWORD insfile[128]; - WORD ptr[256]; - BYTE s[1024]; - DWORD dwMemPos; - BYTE insflags[128], inspack[128]; - S3MFILEHEADER psfh = *(S3MFILEHEADER *)lpStream; - - psfh.reserved1 = bswapLE16(psfh.reserved1); - psfh.ordnum = bswapLE16(psfh.ordnum); - psfh.insnum = bswapLE16(psfh.insnum); - psfh.patnum = bswapLE16(psfh.patnum); - psfh.flags = bswapLE16(psfh.flags); - psfh.cwtv = bswapLE16(psfh.cwtv); - psfh.version = bswapLE16(psfh.version); - psfh.scrm = bswapLE32(psfh.scrm); - psfh.special = bswapLE16(psfh.special); - - if ((!lpStream) || (dwMemLength <= sizeof(S3MFILEHEADER)+sizeof(S3MSAMPLESTRUCT)+64)) return FALSE; - if (psfh.scrm != 0x4D524353) return FALSE; - dwMemPos = 0x60; - m_nType = MOD_TYPE_S3M; - memset(m_szNames,0,sizeof(m_szNames)); - memcpy(m_szNames[0], psfh.name, 28); - // Speed - m_nDefaultSpeed = psfh.speed; - if (m_nDefaultSpeed < 1) m_nDefaultSpeed = 6; - if (m_nDefaultSpeed > 0x1F) m_nDefaultSpeed = 0x1F; - // Tempo - m_nDefaultTempo = psfh.tempo; - if (m_nDefaultTempo < 40) m_nDefaultTempo = 40; - if (m_nDefaultTempo > 240) m_nDefaultTempo = 240; - // Global Volume - m_nDefaultGlobalVolume = psfh.globalvol << 2; - if ((!m_nDefaultGlobalVolume) || (m_nDefaultGlobalVolume > 256)) m_nDefaultGlobalVolume = 256; - m_nSongPreAmp = psfh.mastervol & 0x7F; - // Channels - m_nChannels = 4; - for (UINT ich=0; ich<32; ich++) - { - ChnSettings[ich].nPan = 128; - ChnSettings[ich].nVolume = 64; - - ChnSettings[ich].dwFlags = CHN_MUTE; - if (psfh.channels[ich] != 0xFF) - { - m_nChannels = ich+1; - UINT b = psfh.channels[ich] & 0x0F; - ChnSettings[ich].nPan = (b & 8) ? 0xC0 : 0x40; - ChnSettings[ich].dwFlags = 0; - } - } - if (m_nChannels < 4) m_nChannels = 4; - if ((psfh.cwtv < 0x1320) || (psfh.flags & 0x40)) m_dwSongFlags |= SONG_FASTVOLSLIDES; - // Reading pattern order - UINT iord = psfh.ordnum; - if (iord<1) iord = 1; - if (iord > MAX_ORDERS) iord = MAX_ORDERS; - if (iord) - { - memcpy(Order, lpStream+dwMemPos, iord); - dwMemPos += iord; - } - if ((iord & 1) && (lpStream[dwMemPos] == 0xFF)) dwMemPos++; - // Reading file pointers - insnum = nins = psfh.insnum; - if (insnum >= MAX_SAMPLES) insnum = MAX_SAMPLES-1; - m_nSamples = insnum; - patnum = npat = psfh.patnum; - if (patnum > MAX_PATTERNS) patnum = MAX_PATTERNS; - memset(ptr, 0, sizeof(ptr)); - if (nins+npat) - { - memcpy(ptr, lpStream+dwMemPos, 2*(nins+npat)); - dwMemPos += 2*(nins+npat); - for (UINT j = 0; j < (nins+npat); ++j) { - ptr[j] = bswapLE16(ptr[j]); - } - if (psfh.panning_present == 252) - { - const BYTE *chnpan = lpStream+dwMemPos; - for (UINT i=0; i<32; i++) if (chnpan[i] & 0x20) - { - ChnSettings[i].nPan = ((chnpan[i] & 0x0F) << 4) + 8; - } - } - } - if (!m_nChannels) return TRUE; - // Reading instrument headers - memset(insfile, 0, sizeof(insfile)); - for (UINT iSmp=1; iSmp<=insnum; iSmp++) - { - UINT nInd = ((DWORD)ptr[iSmp-1])*16; - if ((!nInd) || (nInd + 0x50 > dwMemLength)) continue; - memcpy(s, lpStream+nInd, 0x50); - memcpy(Ins[iSmp].name, s+1, 12); - insflags[iSmp-1] = s[0x1F]; - inspack[iSmp-1] = s[0x1E]; - s[0x4C] = 0; - lstrcpy(m_szNames[iSmp], (LPCSTR)&s[0x30]); - if ((s[0]==1) && (s[0x4E]=='R') && (s[0x4F]=='S')) - { - UINT j = bswapLE32(*((LPDWORD)(s+0x10))); - if (j > MAX_SAMPLE_LENGTH) j = MAX_SAMPLE_LENGTH; - if (j < 4) j = 0; - Ins[iSmp].nLength = j; - j = bswapLE32(*((LPDWORD)(s+0x14))); - if (j >= Ins[iSmp].nLength) j = Ins[iSmp].nLength - 1; - Ins[iSmp].nLoopStart = j; - j = bswapLE32(*((LPDWORD)(s+0x18))); - if (j > MAX_SAMPLE_LENGTH) j = MAX_SAMPLE_LENGTH; - if (j < 4) j = 0; - if (j > Ins[iSmp].nLength) j = Ins[iSmp].nLength; - Ins[iSmp].nLoopEnd = j; - j = s[0x1C]; - if (j > 64) j = 64; - Ins[iSmp].nVolume = j << 2; - Ins[iSmp].nGlobalVol = 64; - if (s[0x1F]&1) Ins[iSmp].uFlags |= CHN_LOOP; - j = bswapLE32(*((LPDWORD)(s+0x20))); - if (!j) j = 8363; - if (j < 1024) j = 1024; - Ins[iSmp].nC4Speed = j; - insfile[iSmp] = ((DWORD)bswapLE16(*((LPWORD)(s+0x0E)))) << 4; - insfile[iSmp] += ((DWORD)(BYTE)s[0x0D]) << 20; - if (insfile[iSmp] > dwMemLength) insfile[iSmp] &= 0xFFFF; - if ((Ins[iSmp].nLoopStart >= Ins[iSmp].nLoopEnd) || (Ins[iSmp].nLoopEnd - Ins[iSmp].nLoopStart < 8)) - Ins[iSmp].nLoopStart = Ins[iSmp].nLoopEnd = 0; - Ins[iSmp].nPan = 0x80; - } - } - // Reading patterns - for (UINT iPat=0; iPat<patnum; iPat++) - { - UINT nInd = ((DWORD)ptr[nins+iPat]) << 4; - if (nInd + 0x40 > dwMemLength) continue; - WORD len = bswapLE16(*((WORD *)(lpStream+nInd))); - nInd += 2; - PatternSize[iPat] = 64; - if ((!len) || (nInd + len > dwMemLength - 6) - || ((Patterns[iPat] = AllocatePattern(64, m_nChannels)) == NULL)) continue; - LPBYTE src = (LPBYTE)(lpStream+nInd); - // Unpacking pattern - MODCOMMAND *p = Patterns[iPat]; - UINT row = 0; - UINT j = 0; - while (j < len) - { - BYTE b = src[j++]; - if (!b) - { - if (++row >= 64) break; - } else - { - UINT chn = b & 0x1F; - if (chn < m_nChannels) - { - MODCOMMAND *m = &p[row*m_nChannels+chn]; - if (b & 0x20) - { - m->note = src[j++]; - if (m->note < 0xF0) m->note = (m->note & 0x0F) + 12*(m->note >> 4) + 13; - else if (m->note == 0xFF) m->note = 0; - m->instr = src[j++]; - } - if (b & 0x40) - { - UINT vol = src[j++]; - if ((vol >= 128) && (vol <= 192)) - { - vol -= 128; - m->volcmd = VOLCMD_PANNING; - } else - { - if (vol > 64) vol = 64; - m->volcmd = VOLCMD_VOLUME; - } - m->vol = vol; - } - if (b & 0x80) - { - m->command = src[j++]; - m->param = src[j++]; - if (m->command) S3MConvert(m, FALSE); - } - } else - { - if (b & 0x20) j += 2; - if (b & 0x40) j++; - if (b & 0x80) j += 2; - } - if (j >= len) break; - } - } - } - // Reading samples - for (UINT iRaw=1; iRaw<=insnum; iRaw++) if ((Ins[iRaw].nLength) && (insfile[iRaw])) - { - UINT flags = (psfh.version == 1) ? RS_PCM8S : RS_PCM8U; - if (insflags[iRaw-1] & 4) flags += 5; - if (insflags[iRaw-1] & 2) flags |= RSF_STEREO; - if (inspack[iRaw-1] == 4) flags = RS_ADPCM4; - dwMemPos = insfile[iRaw]; - dwMemPos += ReadSample(&Ins[iRaw], flags, (LPSTR)(lpStream + dwMemPos), dwMemLength - dwMemPos); - } - m_nMinPeriod = 64; - m_nMaxPeriod = 32767; - if (psfh.flags & 0x10) m_dwSongFlags |= SONG_AMIGALIMITS; - return TRUE; -} - - -#ifndef MODPLUG_NO_FILESAVE - -#ifdef _MSC_VER -#pragma warning(disable:4100) -#endif - -static BYTE S3MFiller[16] = -{ - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 -}; - - -BOOL CSoundFile::SaveS3M(LPCSTR lpszFileName, UINT nPacking) -//---------------------------------------------------------- -{ - FILE *f; - BYTE header[0x60]; - UINT nbo,nbi,nbp,i; - WORD patptr[128]; - WORD insptr[128]; - BYTE buffer[5*1024]; - S3MSAMPLESTRUCT insex[128]; - - if ((!m_nChannels) || (!lpszFileName)) return FALSE; - if ((f = fopen(lpszFileName, "wb")) == NULL) return FALSE; - // Writing S3M header - memset(header, 0, sizeof(header)); - memset(insex, 0, sizeof(insex)); - memcpy(header, m_szNames[0], 0x1C); - header[0x1B] = 0; - header[0x1C] = 0x1A; - header[0x1D] = 0x10; - nbo = (GetNumPatterns() + 15) & 0xF0; - if (!nbo) nbo = 16; - header[0x20] = nbo & 0xFF; - header[0x21] = nbo >> 8; - nbi = m_nInstruments; - if (!nbi) nbi = m_nSamples; - if (nbi > 99) nbi = 99; - header[0x22] = nbi & 0xFF; - header[0x23] = nbi >> 8; - nbp = 0; - for (i=0; Patterns[i]; i++) { nbp = i+1; if (nbp >= MAX_PATTERNS) break; } - for (i=0; i<MAX_ORDERS; i++) if ((Order[i] < MAX_PATTERNS) && (Order[i] >= nbp)) nbp = Order[i] + 1; - header[0x24] = nbp & 0xFF; - header[0x25] = nbp >> 8; - if (m_dwSongFlags & SONG_FASTVOLSLIDES) header[0x26] |= 0x40; - if ((m_nMaxPeriod < 20000) || (m_dwSongFlags & SONG_AMIGALIMITS)) header[0x26] |= 0x10; - header[0x28] = 0x20; - header[0x29] = 0x13; - header[0x2A] = 0x02; // Version = 1 => Signed samples - header[0x2B] = 0x00; - header[0x2C] = 'S'; - header[0x2D] = 'C'; - header[0x2E] = 'R'; - header[0x2F] = 'M'; - header[0x30] = m_nDefaultGlobalVolume >> 2; - header[0x31] = m_nDefaultSpeed; - header[0x32] = m_nDefaultTempo; - header[0x33] = ((m_nSongPreAmp < 0x20) ? 0x20 : m_nSongPreAmp) | 0x80; // Stereo - header[0x35] = 0xFC; - for (i=0; i<32; i++) - { - if (i < m_nChannels) - { - UINT tmp = (i & 0x0F) >> 1; - header[0x40+i] = (i & 0x10) | ((i & 1) ? 8+tmp : tmp); - } else header[0x40+i] = 0xFF; - } - fwrite(header, 0x60, 1, f); - fwrite(Order, nbo, 1, f); - memset(patptr, 0, sizeof(patptr)); - memset(insptr, 0, sizeof(insptr)); - UINT ofs0 = 0x60 + nbo; - UINT ofs1 = ((0x60 + nbo + nbi*2 + nbp*2 + 15) & 0xFFF0) + 0x20; - UINT ofs = ofs1; - - for (i=0; i<nbi; i++) insptr[i] = (WORD)((ofs + i*0x50) / 16); - for (i=0; i<nbp; i++) patptr[i] = (WORD)((ofs + nbi*0x50) / 16); - fwrite(insptr, nbi, 2, f); - fwrite(patptr, nbp, 2, f); - if (header[0x35] == 0xFC) - { - BYTE chnpan[32]; - for (i=0; i<32; i++) - { - chnpan[i] = 0x20 | (ChnSettings[i].nPan >> 4); - } - fwrite(chnpan, 0x20, 1, f); - } - if ((nbi*2+nbp*2) & 0x0F) - { - fwrite(S3MFiller, 0x10 - ((nbi*2+nbp*2) & 0x0F), 1, f); - } - ofs1 = ftell(f); - fwrite(insex, nbi, 0x50, f); - // Packing patterns - ofs += nbi*0x50; - for (i=0; i<nbp; i++) - { - WORD len = 64; - memset(buffer, 0, sizeof(buffer)); - patptr[i] = ofs / 16; - if (Patterns[i]) - { - len = 2; - MODCOMMAND *p = Patterns[i]; - for (int row=0; row<64; row++) if (row < PatternSize[i]) - { - for (UINT j=0; j<m_nChannels; j++) - { - UINT b = j; - MODCOMMAND *m = &p[row*m_nChannels+j]; - UINT note = m->note; - UINT volcmd = m->volcmd; - UINT vol = m->vol; - UINT command = m->command; - UINT param = m->param; - - if ((note) || (m->instr)) b |= 0x20; - if (!note) note = 0xFF; else - if (note >= 0xFE) note = 0xFE; else - if (note < 13) note = 0; else note -= 13; - if (note < 0xFE) note = (note % 12) + ((note / 12) << 4); - if (command == CMD_VOLUME) - { - command = 0; - if (param > 64) param = 64; - volcmd = VOLCMD_VOLUME; - vol = param; - } - if (volcmd == VOLCMD_VOLUME) b |= 0x40; else - if (volcmd == VOLCMD_PANNING) { vol |= 0x80; b |= 0x40; } - if (command) - { - S3MSaveConvert(&command, ¶m, FALSE); - if (command) b |= 0x80; - } - if (b & 0xE0) - { - buffer[len++] = b; - if (b & 0x20) - { - buffer[len++] = note; - buffer[len++] = m->instr; - } - if (b & 0x40) - { - buffer[len++] = vol; - } - if (b & 0x80) - { - buffer[len++] = command; - buffer[len++] = param; - } - if (len > sizeof(buffer) - 20) break; - } - } - buffer[len++] = 0; - if (len > sizeof(buffer) - 20) break; - } - } - buffer[0] = (len - 2) & 0xFF; - buffer[1] = (len - 2) >> 8; - len = (len+15) & (~0x0F); - fwrite(buffer, len, 1, f); - ofs += len; - } - // Writing samples - for (i=1; i<=nbi; i++) - { - MODINSTRUMENT *pins = &Ins[i]; - if (m_nInstruments) - { - pins = Ins; - if (Headers[i]) - { - for (UINT j=0; j<128; j++) - { - UINT n = Headers[i]->Keyboard[j]; - if ((n) && (n < MAX_INSTRUMENTS)) - { - pins = &Ins[n]; - break; - } - } - } - } - memcpy(insex[i-1].dosname, pins->name, 12); - memcpy(insex[i-1].name, m_szNames[i], 28); - memcpy(insex[i-1].scrs, "SCRS", 4); - insex[i-1].hmem = (BYTE)((DWORD)ofs >> 20); - insex[i-1].memseg = (WORD)((DWORD)ofs >> 4); - if (pins->pSample) - { - insex[i-1].type = 1; - insex[i-1].length = pins->nLength; - insex[i-1].loopbegin = pins->nLoopStart; - insex[i-1].loopend = pins->nLoopEnd; - insex[i-1].vol = pins->nVolume / 4; - insex[i-1].flags = (pins->uFlags & CHN_LOOP) ? 1 : 0; - if (pins->nC4Speed) - insex[i-1].finetune = pins->nC4Speed; - else - insex[i-1].finetune = TransposeToFrequency(pins->RelativeTone, pins->nFineTune); - UINT flags = RS_PCM8U; -#ifndef NO_PACKING - if (nPacking) - { - if ((!(pins->uFlags & (CHN_16BIT|CHN_STEREO))) - && (CanPackSample((char *)pins->pSample, pins->nLength, nPacking))) - { - insex[i-1].pack = 4; - flags = RS_ADPCM4; - } - } else -#endif // NO_PACKING - { - if (pins->uFlags & CHN_16BIT) - { - insex[i-1].flags |= 4; - flags = RS_PCM16U; - } - if (pins->uFlags & CHN_STEREO) - { - insex[i-1].flags |= 2; - flags = (pins->uFlags & CHN_16BIT) ? RS_STPCM16U : RS_STPCM8U; - } - } - DWORD len = WriteSample(f, pins, flags); - if (len & 0x0F) - { - fwrite(S3MFiller, 0x10 - (len & 0x0F), 1, f); - } - ofs += (len + 15) & (~0x0F); - } else - { - insex[i-1].length = 0; - } - } - // Updating parapointers - fseek(f, ofs0, SEEK_SET); - fwrite(insptr, nbi, 2, f); - fwrite(patptr, nbp, 2, f); - fseek(f, ofs1, SEEK_SET); - fwrite(insex, 0x50, nbi, f); - fclose(f); - return TRUE; -} - -#ifdef _MSC_VER -#pragma warning(default:4100) -#endif - -#endif // MODPLUG_NO_FILESAVE - diff --git a/lib/libmodplug/src/load_stm.cpp b/lib/libmodplug/src/load_stm.cpp deleted file mode 100644 index 294ecd8f4f..0000000000 --- a/lib/libmodplug/src/load_stm.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque <olivierl@jps.net> -*/ - -#include "stdafx.h" -#include "sndfile.h" - -//#pragma warning(disable:4244) - -#pragma pack(1) - -typedef struct tagSTMNOTE -{ - BYTE note; - BYTE insvol; - BYTE volcmd; - BYTE cmdinf; -} STMNOTE; - - -// Raw STM sampleinfo struct: -typedef struct tagSTMSAMPLE -{ - CHAR filename[14]; // Can't have long comments - just filename comments :) - WORD reserved; // ISA in memory when in ST 2 - WORD length; // Sample length - WORD loopbeg; // Loop start point - WORD loopend; // Loop end point - BYTE volume; // Volume - BYTE reserved2; // More reserved crap - WORD c2spd; // Good old c2spd - BYTE reserved3[6]; // Yet more of PSi's reserved crap -} STMSAMPLE; - - -// Raw STM header struct: -typedef struct tagSTMHEADER -{ - char songname[20]; // changed from CHAR - char trackername[8]; // !SCREAM! for ST 2.xx // changed from CHAR - CHAR unused; // 0x1A - CHAR filetype; // 1=song, 2=module (only 2 is supported, of course) :) - CHAR ver_major; // Like 2 - CHAR ver_minor; // "ditto" - BYTE inittempo; // initspeed= stm inittempo>>4 - BYTE numpat; // number of patterns - BYTE globalvol; // <- WoW! a RiGHT TRiANGLE =8*) - BYTE reserved[13]; // More of PSi's internal crap - STMSAMPLE sample[31]; // STM sample data - BYTE patorder[128]; // Docs say 64 - actually 128 -} STMHEADER; - -#pragma pack() - - - -BOOL CSoundFile::ReadSTM(const BYTE *lpStream, DWORD dwMemLength) -//--------------------------------------------------------------- -{ - STMHEADER *phdr = (STMHEADER *)lpStream; - DWORD dwMemPos = 0; - - if ((!lpStream) || (dwMemLength < sizeof(STMHEADER))) return FALSE; - if ((phdr->filetype != 2) || (phdr->unused != 0x1A) - || ((strnicmp(phdr->trackername, "!SCREAM!", 8)) - && (strnicmp(phdr->trackername, "BMOD2STM", 8)))) return FALSE; - memcpy(m_szNames[0], phdr->songname, 20); - // Read STM header - m_nType = MOD_TYPE_STM; - m_nSamples = 31; - m_nChannels = 4; - m_nInstruments = 0; - m_nMinPeriod = 64; - m_nMaxPeriod = 0x7FFF; - m_nDefaultSpeed = phdr->inittempo >> 4; - if (m_nDefaultSpeed < 1) m_nDefaultSpeed = 1; - m_nDefaultTempo = 125; - m_nDefaultGlobalVolume = phdr->globalvol << 2; - if (m_nDefaultGlobalVolume > 256) m_nDefaultGlobalVolume = 256; - memcpy(Order, phdr->patorder, 128); - // Setting up channels - for (UINT nSet=0; nSet<4; nSet++) - { - ChnSettings[nSet].dwFlags = 0; - ChnSettings[nSet].nVolume = 64; - ChnSettings[nSet].nPan = (nSet & 1) ? 0x40 : 0xC0; - } - // Reading samples - for (UINT nIns=0; nIns<31; nIns++) - { - MODINSTRUMENT *pIns = &Ins[nIns+1]; - STMSAMPLE *pStm = &phdr->sample[nIns]; // STM sample data - memcpy(pIns->name, pStm->filename, 13); - memcpy(m_szNames[nIns+1], pStm->filename, 12); - pIns->nC4Speed = bswapLE16(pStm->c2spd); - pIns->nGlobalVol = 64; - pIns->nVolume = pStm->volume << 2; - if (pIns->nVolume > 256) pIns->nVolume = 256; - pIns->nLength = bswapLE16(pStm->length); - if ((pIns->nLength < 4) || (!pIns->nVolume)) pIns->nLength = 0; - pIns->nLoopStart = bswapLE16(pStm->loopbeg); - pIns->nLoopEnd = bswapLE16(pStm->loopend); - if ((pIns->nLoopEnd > pIns->nLoopStart) && (pIns->nLoopEnd != 0xFFFF)) pIns->uFlags |= CHN_LOOP; - } - dwMemPos = sizeof(STMHEADER); - for (UINT nOrd=0; nOrd<MAX_ORDERS; nOrd++) if (Order[nOrd] >= 99) Order[nOrd] = 0xFF; - UINT nPatterns = phdr->numpat; - for (UINT nPat=0; nPat<nPatterns; nPat++) - { - if (dwMemPos + 64*4*4 > dwMemLength) return TRUE; - PatternSize[nPat] = 64; - if ((Patterns[nPat] = AllocatePattern(64, m_nChannels)) == NULL) return TRUE; - MODCOMMAND *m = Patterns[nPat]; - STMNOTE *p = (STMNOTE *)(lpStream + dwMemPos); - for (UINT n=0; n<64*4; n++, p++, m++) - { - UINT note,ins,vol,cmd; - // extract the various information from the 4 bytes that - // make up a single note - note = p->note; - ins = p->insvol >> 3; - vol = (p->insvol & 0x07) + (p->volcmd >> 1); - cmd = p->volcmd & 0x0F; - if ((ins) && (ins < 32)) m->instr = ins; - // special values of [SBYTE0] are handled here -> - // we have no idea if these strange values will ever be encountered - // but it appears as though stms sound correct. - if ((note == 0xFE) || (note == 0xFC)) m->note = 0xFE; else - // if note < 251, then all three bytes are stored in the file - if (note < 0xFC) m->note = (note >> 4)*12 + (note&0xf) + 37; - if (vol <= 64) { m->volcmd = VOLCMD_VOLUME; m->vol = vol; } - m->param = p->cmdinf; - switch(cmd) - { - // Axx set speed to xx - case 1: m->command = CMD_SPEED; m->param >>= 4; break; - // Bxx position jump - case 2: m->command = CMD_POSITIONJUMP; break; - // Cxx patternbreak to row xx - case 3: m->command = CMD_PATTERNBREAK; m->param = (m->param & 0xF0) * 10 + (m->param & 0x0F); break; - // Dxy volumeslide - case 4: m->command = CMD_VOLUMESLIDE; break; - // Exy toneslide down - case 5: m->command = CMD_PORTAMENTODOWN; break; - // Fxy toneslide up - case 6: m->command = CMD_PORTAMENTOUP; break; - // Gxx Tone portamento,speed xx - case 7: m->command = CMD_TONEPORTAMENTO; break; - // Hxy vibrato - case 8: m->command = CMD_VIBRATO; break; - // Ixy tremor, ontime x, offtime y - case 9: m->command = CMD_TREMOR; break; - // Jxy arpeggio - case 10: m->command = CMD_ARPEGGIO; break; - // Kxy Dual command H00 & Dxy - case 11: m->command = CMD_VIBRATOVOL; break; - // Lxy Dual command G00 & Dxy - case 12: m->command = CMD_TONEPORTAVOL; break; - // Xxx amiga command 8xx - case 0x18: m->command = CMD_PANNING8; break; - default: - m->command = m->param = 0; - } - } - dwMemPos += 64*4*4; - } - // Reading Samples - for (UINT nSmp=1; nSmp<=31; nSmp++) - { - MODINSTRUMENT *pIns = &Ins[nSmp]; - dwMemPos = (dwMemPos + 15) & (~15); - if (pIns->nLength) - { - UINT nPos = ((UINT)phdr->sample[nSmp-1].reserved) << 4; - if ((nPos >= sizeof(STMHEADER)) && (nPos+pIns->nLength <= dwMemLength)) dwMemPos = nPos; - if (dwMemPos < dwMemLength) - { - dwMemPos += ReadSample(pIns, RS_PCM8S, (LPSTR)(lpStream+dwMemPos),dwMemLength-dwMemPos); - } - } - } - return TRUE; -} - diff --git a/lib/libmodplug/src/load_ult.cpp b/lib/libmodplug/src/load_ult.cpp deleted file mode 100644 index 91e1b30402..0000000000 --- a/lib/libmodplug/src/load_ult.cpp +++ /dev/null @@ -1,222 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque <olivierl@jps.net> -*/ - -#include "stdafx.h" -#include "sndfile.h" - -//#pragma warning(disable:4244) - -#define ULT_16BIT 0x04 -#define ULT_LOOP 0x08 -#define ULT_BIDI 0x10 - -#pragma pack(1) - -// Raw ULT header struct: -typedef struct tagULTHEADER -{ - char id[15]; // changed from CHAR - char songtitle[32]; // changed from CHAR - BYTE reserved; -} ULTHEADER; - - -// Raw ULT sampleinfo struct: -typedef struct tagULTSAMPLE -{ - CHAR samplename[32]; - CHAR dosname[12]; - LONG loopstart; - LONG loopend; - LONG sizestart; - LONG sizeend; - BYTE volume; - BYTE flags; - WORD finetune; -} ULTSAMPLE; - -#pragma pack() - - -BOOL CSoundFile::ReadUlt(const BYTE *lpStream, DWORD dwMemLength) -//--------------------------------------------------------------- -{ - ULTHEADER *pmh = (ULTHEADER *)lpStream; - ULTSAMPLE *pus; - UINT nos, nop; - DWORD dwMemPos = 0; - - // try to read module header - if ((!lpStream) || (dwMemLength < 0x100)) return FALSE; - if (strncmp(pmh->id,"MAS_UTrack_V00",14)) return FALSE; - // Warning! Not supported ULT format, trying anyway - // if ((pmh->id[14] < '1') || (pmh->id[14] > '4')) return FALSE; - m_nType = MOD_TYPE_ULT; - m_nDefaultSpeed = 6; - m_nDefaultTempo = 125; - memcpy(m_szNames[0], pmh->songtitle, 32); - // read songtext - dwMemPos = sizeof(ULTHEADER); - if ((pmh->reserved) && (dwMemPos + pmh->reserved * 32 < dwMemLength)) - { - UINT len = pmh->reserved * 32; - m_lpszSongComments = new char[len + 1 + pmh->reserved]; - if (m_lpszSongComments) - { - for (UINT l=0; l<pmh->reserved; l++) - { - memcpy(m_lpszSongComments+l*33, lpStream+dwMemPos+l*32, 32); - m_lpszSongComments[l*33+32] = 0x0D; - } - m_lpszSongComments[len] = 0; - } - dwMemPos += len; - } - if (dwMemPos >= dwMemLength) return TRUE; - nos = lpStream[dwMemPos++]; - m_nSamples = nos; - if (m_nSamples >= MAX_SAMPLES) m_nSamples = MAX_SAMPLES-1; - UINT smpsize = 64; - if (pmh->id[14] >= '4') smpsize += 2; - if (dwMemPos + nos*smpsize + 256 + 2 > dwMemLength) return TRUE; - for (UINT ins=1; ins<=nos; ins++, dwMemPos+=smpsize) if (ins<=m_nSamples) - { - pus = (ULTSAMPLE *)(lpStream+dwMemPos); - MODINSTRUMENT *pins = &Ins[ins]; - memcpy(m_szNames[ins], pus->samplename, 32); - memcpy(pins->name, pus->dosname, 12); - pins->nLoopStart = pus->loopstart; - pins->nLoopEnd = pus->loopend; - pins->nLength = pus->sizeend - pus->sizestart; - pins->nVolume = pus->volume; - pins->nGlobalVol = 64; - pins->nC4Speed = 8363; - if (pmh->id[14] >= '4') - { - pins->nC4Speed = pus->finetune; - } - if (pus->flags & ULT_LOOP) pins->uFlags |= CHN_LOOP; - if (pus->flags & ULT_BIDI) pins->uFlags |= CHN_PINGPONGLOOP; - if (pus->flags & ULT_16BIT) - { - pins->uFlags |= CHN_16BIT; - pins->nLoopStart >>= 1; - pins->nLoopEnd >>= 1; - } - } - memcpy(Order, lpStream+dwMemPos, 256); - dwMemPos += 256; - m_nChannels = lpStream[dwMemPos] + 1; - nop = lpStream[dwMemPos+1] + 1; - dwMemPos += 2; - if (m_nChannels > 32) m_nChannels = 32; - // Default channel settings - for (UINT nSet=0; nSet<m_nChannels; nSet++) - { - ChnSettings[nSet].nVolume = 64; - ChnSettings[nSet].nPan = (nSet & 1) ? 0x40 : 0xC0; - } - // read pan position table for v1.5 and higher - if(pmh->id[14]>='3') - { - if (dwMemPos + m_nChannels > dwMemLength) return TRUE; - for(UINT t=0; t<m_nChannels; t++) - { - ChnSettings[t].nPan = (lpStream[dwMemPos++] << 4) + 8; - if (ChnSettings[t].nPan > 256) ChnSettings[t].nPan = 256; - } - } - // Allocating Patterns - for (UINT nAllocPat=0; nAllocPat<nop; nAllocPat++) - { - if (nAllocPat < MAX_PATTERNS) - { - PatternSize[nAllocPat] = 64; - Patterns[nAllocPat] = AllocatePattern(64, m_nChannels); - } - } - // Reading Patterns - for (UINT nChn=0; nChn<m_nChannels; nChn++) - { - for (UINT nPat=0; nPat<nop; nPat++) - { - MODCOMMAND *pat = NULL; - - if (nPat < MAX_PATTERNS) - { - pat = Patterns[nPat]; - if (pat) pat += nChn; - } - UINT row = 0; - while (row < 64) - { - if (dwMemPos + 6 > dwMemLength) return TRUE; - UINT rep = 1; - UINT note = lpStream[dwMemPos++]; - if (note == 0xFC) - { - rep = lpStream[dwMemPos]; - note = lpStream[dwMemPos+1]; - dwMemPos += 2; - } - UINT instr = lpStream[dwMemPos++]; - UINT eff = lpStream[dwMemPos++]; - UINT dat1 = lpStream[dwMemPos++]; - UINT dat2 = lpStream[dwMemPos++]; - UINT cmd1 = eff & 0x0F; - UINT cmd2 = eff >> 4; - if (cmd1 == 0x0C) dat1 >>= 2; else - if (cmd1 == 0x0B) { cmd1 = dat1 = 0; } - if (cmd2 == 0x0C) dat2 >>= 2; else - if (cmd2 == 0x0B) { cmd2 = dat2 = 0; } - while ((rep != 0) && (row < 64)) - { - if (pat) - { - pat->instr = instr; - if (note) pat->note = note + 36; - if (cmd1 | dat1) - { - if (cmd1 == 0x0C) - { - pat->volcmd = VOLCMD_VOLUME; - pat->vol = dat1; - } else - { - pat->command = cmd1; - pat->param = dat1; - ConvertModCommand(pat); - } - } - if (cmd2 == 0x0C) - { - pat->volcmd = VOLCMD_VOLUME; - pat->vol = dat2; - } else - if ((cmd2 | dat2) && (!pat->command)) - { - pat->command = cmd2; - pat->param = dat2; - ConvertModCommand(pat); - } - pat += m_nChannels; - } - row++; - rep--; - } - } - } - } - // Reading Instruments - for (UINT smp=1; smp<=m_nSamples; smp++) if (Ins[smp].nLength) - { - if (dwMemPos >= dwMemLength) return TRUE; - UINT flags = (Ins[smp].uFlags & CHN_16BIT) ? RS_PCM16S : RS_PCM8S; - dwMemPos += ReadSample(&Ins[smp], flags, (LPSTR)(lpStream+dwMemPos), dwMemLength - dwMemPos); - } - return TRUE; -} - diff --git a/lib/libmodplug/src/load_umx.cpp b/lib/libmodplug/src/load_umx.cpp deleted file mode 100644 index 8913c740ff..0000000000 --- a/lib/libmodplug/src/load_umx.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque <olivierl@jps.net> -*/ - -#include "stdafx.h" -#include "sndfile.h" - -#define MODMAGIC_OFFSET (20+31*30+130) - - -BOOL CSoundFile::ReadUMX(const BYTE *lpStream, DWORD dwMemLength) -//--------------------------------------------------------------- -{ - if ((!lpStream) || (dwMemLength < 0x800)) return FALSE; - // Rip Mods from UMX - if ((bswapLE32(*((DWORD *)(lpStream+0x20))) < dwMemLength) - && (bswapLE32(*((DWORD *)(lpStream+0x18))) <= dwMemLength - 0x10) - && (bswapLE32(*((DWORD *)(lpStream+0x18))) >= dwMemLength - 0x200)) - { - for (UINT uscan=0x40; uscan<0x500; uscan++) - { - DWORD dwScan = bswapLE32(*((DWORD *)(lpStream+uscan))); - // IT - if (dwScan == 0x4D504D49) - { - DWORD dwRipOfs = uscan; - return ReadIT(lpStream + dwRipOfs, dwMemLength - dwRipOfs); - } - // S3M - if (dwScan == 0x4D524353) - { - DWORD dwRipOfs = uscan - 44; - return ReadS3M(lpStream + dwRipOfs, dwMemLength - dwRipOfs); - } - // XM - if (!strnicmp((LPCSTR)(lpStream+uscan), "Extended Module", 15)) - { - DWORD dwRipOfs = uscan; - return ReadXM(lpStream + dwRipOfs, dwMemLength - dwRipOfs); - } - // MOD - if ((uscan > MODMAGIC_OFFSET) && (dwScan == 0x2e4b2e4d)) - { - DWORD dwRipOfs = uscan - MODMAGIC_OFFSET; - return ReadMod(lpStream+dwRipOfs, dwMemLength-dwRipOfs); - } - } - } - return FALSE; -} - diff --git a/lib/libmodplug/src/load_wav.cpp b/lib/libmodplug/src/load_wav.cpp deleted file mode 100644 index 3bcd132865..0000000000 --- a/lib/libmodplug/src/load_wav.cpp +++ /dev/null @@ -1,220 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque <olivierl@jps.net> -*/ - -#include "stdafx.h" -#include "sndfile.h" - -#ifndef WAVE_FORMAT_EXTENSIBLE -#define WAVE_FORMAT_EXTENSIBLE 0xFFFE -#endif - -///////////////////////////////////////////////////////////// -// WAV file support - -BOOL CSoundFile::ReadWav(const BYTE *lpStream, DWORD dwMemLength) -//--------------------------------------------------------------- -{ - DWORD dwMemPos = 0; - WAVEFILEHEADER *phdr = (WAVEFILEHEADER *)lpStream; - WAVEFORMATHEADER *pfmt = (WAVEFORMATHEADER *)(lpStream + sizeof(WAVEFILEHEADER)); - if ((!lpStream) || (dwMemLength < (DWORD)sizeof(WAVEFILEHEADER))) return FALSE; - if ((phdr->id_RIFF != IFFID_RIFF) || (phdr->id_WAVE != IFFID_WAVE) - || (pfmt->id_fmt != IFFID_fmt)) return FALSE; - dwMemPos = sizeof(WAVEFILEHEADER) + 8 + pfmt->hdrlen; - if ((dwMemPos + 8 >= dwMemLength) - || ((pfmt->format != WAVE_FORMAT_PCM) && (pfmt->format != WAVE_FORMAT_EXTENSIBLE)) - || (pfmt->channels > 4) - || (!pfmt->channels) - || (!pfmt->freqHz) - || (pfmt->bitspersample & 7) - || (pfmt->bitspersample < 8) - || (pfmt->bitspersample > 32)) return FALSE; - WAVEDATAHEADER *pdata; - for (;;) - { - pdata = (WAVEDATAHEADER *)(lpStream + dwMemPos); - if (pdata->id_data == IFFID_data) break; - dwMemPos += pdata->length + 8; - if (dwMemPos + 8 >= dwMemLength) return FALSE; - } - m_nType = MOD_TYPE_WAV; - m_nSamples = 0; - m_nInstruments = 0; - m_nChannels = 4; - m_nDefaultSpeed = 8; - m_nDefaultTempo = 125; - m_dwSongFlags |= SONG_LINEARSLIDES; // For no resampling - Order[0] = 0; - Order[1] = 0xFF; - PatternSize[0] = PatternSize[1] = 64; - if ((Patterns[0] = AllocatePattern(64, 4)) == NULL) return TRUE; - if ((Patterns[1] = AllocatePattern(64, 4)) == NULL) return TRUE; - UINT samplesize = (pfmt->channels * pfmt->bitspersample) >> 3; - UINT len = pdata->length, bytelen; - if (dwMemPos + len > dwMemLength - 8) len = dwMemLength - dwMemPos - 8; - len /= samplesize; - bytelen = len; - if (pfmt->bitspersample >= 16) bytelen *= 2; - if (len > MAX_SAMPLE_LENGTH) len = MAX_SAMPLE_LENGTH; - if (!len) return TRUE; - // Setting up module length - DWORD dwTime = ((len * 50) / pfmt->freqHz) + 1; - DWORD framesperrow = (dwTime + 63) / 63; - if (framesperrow < 4) framesperrow = 4; - UINT norders = 1; - while (framesperrow >= 0x20) - { - Order[norders++] = 1; - Order[norders] = 0xFF; - framesperrow = (dwTime + (64 * norders - 1)) / (64 * norders); - if (norders >= MAX_ORDERS-1) break; - } - m_nDefaultSpeed = framesperrow; - for (UINT iChn=0; iChn<4; iChn++) - { - ChnSettings[iChn].nPan = (iChn & 1) ? 256 : 0; - ChnSettings[iChn].nVolume = 64; - ChnSettings[iChn].dwFlags = 0; - } - // Setting up speed command - MODCOMMAND *pcmd = Patterns[0]; - pcmd[0].command = CMD_SPEED; - pcmd[0].param = (BYTE)m_nDefaultSpeed; - pcmd[0].note = 5*12+1; - pcmd[0].instr = 1; - pcmd[1].note = pcmd[0].note; - pcmd[1].instr = pcmd[0].instr; - m_nSamples = pfmt->channels; - // Support for Multichannel Wave - for (UINT nChn=0; nChn<m_nSamples; nChn++) - { - MODINSTRUMENT *pins = &Ins[nChn+1]; - pcmd[nChn].note = pcmd[0].note; - pcmd[nChn].instr = (BYTE)(nChn+1); - pins->nLength = len; - pins->nC4Speed = pfmt->freqHz; - pins->nVolume = 256; - pins->nPan = 128; - pins->nGlobalVol = 64; - pins->uFlags = (WORD)((pfmt->bitspersample >= 16) ? CHN_16BIT : 0); - pins->uFlags |= CHN_PANNING; - if (m_nSamples > 1) - { - switch(nChn) - { - case 0: pins->nPan = 0; break; - case 1: pins->nPan = 256; break; - case 2: pins->nPan = (WORD)((m_nSamples == 3) ? 128 : 64); pcmd[nChn].command = CMD_S3MCMDEX; pcmd[nChn].param = 0x91; break; - case 3: pins->nPan = 192; pcmd[nChn].command = CMD_S3MCMDEX; pcmd[nChn].param = 0x91; break; - default: pins->nPan = 128; break; - } - } - if ((pins->pSample = AllocateSample(bytelen+8)) == NULL) return TRUE; - if (pfmt->bitspersample >= 16) - { - int slsize = pfmt->bitspersample >> 3; - signed short *p = (signed short *)pins->pSample; - signed char *psrc = (signed char *)(lpStream+dwMemPos+8+nChn*slsize+slsize-2); - for (UINT i=0; i<len; i++) - { - p[i] = *((signed short *)psrc); - psrc += samplesize; - } - p[len+1] = p[len] = p[len-1]; - } else - { - signed char *p = (signed char *)pins->pSample; - signed char *psrc = (signed char *)(lpStream+dwMemPos+8+nChn); - for (UINT i=0; i<len; i++) - { - p[i] = (signed char)((*psrc) + 0x80); - psrc += samplesize; - } - p[len+1] = p[len] = p[len-1]; - } - } - return TRUE; -} - - -//////////////////////////////////////////////////////////////////////// -// IMA ADPCM Support - -#pragma pack(1) - -typedef struct IMAADPCMBLOCK -{ - WORD sample; - BYTE index; - BYTE Reserved; -} DVI_ADPCMBLOCKHEADER; - -#pragma pack() - -static const int gIMAUnpackTable[90] = -{ - 7, 8, 9, 10, 11, 12, 13, 14, - 16, 17, 19, 21, 23, 25, 28, 31, - 34, 37, 41, 45, 50, 55, 60, 66, - 73, 80, 88, 97, 107, 118, 130, 143, - 157, 173, 190, 209, 230, 253, 279, 307, - 337, 371, 408, 449, 494, 544, 598, 658, - 724, 796, 876, 963, 1060, 1166, 1282, 1411, - 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, - 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, - 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, - 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, - 32767, 0 -}; - - -BOOL IMAADPCMUnpack16(signed short *pdest, UINT nLen, LPBYTE psrc, DWORD dwBytes, UINT pkBlkAlign) -//------------------------------------------------------------------------------------------------ -{ - static const int gIMAIndexTab[8] = { -1, -1, -1, -1, 2, 4, 6, 8 }; - UINT nPos; - int value; - - if ((nLen < 4) || (!pdest) || (!psrc) - || (pkBlkAlign < 5) || (pkBlkAlign > dwBytes)) return FALSE; - nPos = 0; - while ((nPos < nLen) && (dwBytes > 4)) - { - int nIndex; - value = *((short int *)psrc); - nIndex = psrc[2]; - psrc += 4; - dwBytes -= 4; - pdest[nPos++] = (short int)value; - for (UINT i=0; ((i<(pkBlkAlign-4)*2) && (nPos < nLen) && (dwBytes)); i++) - { - BYTE delta; - if (i & 1) - { - delta = (BYTE)(((*(psrc++)) >> 4) & 0x0F); - dwBytes--; - } else - { - delta = (BYTE)((*psrc) & 0x0F); - } - int v = gIMAUnpackTable[nIndex] >> 3; - if (delta & 1) v += gIMAUnpackTable[nIndex] >> 2; - if (delta & 2) v += gIMAUnpackTable[nIndex] >> 1; - if (delta & 4) v += gIMAUnpackTable[nIndex]; - if (delta & 8) value -= v; else value += v; - nIndex += gIMAIndexTab[delta & 7]; - if (nIndex < 0) nIndex = 0; else - if (nIndex > 88) nIndex = 88; - if (value > 32767) value = 32767; else - if (value < -32768) value = -32768; - pdest[nPos++] = (short int)value; - } - } - return TRUE; -} - - - diff --git a/lib/libmodplug/src/load_xm.cpp b/lib/libmodplug/src/load_xm.cpp deleted file mode 100644 index ee71b79265..0000000000 --- a/lib/libmodplug/src/load_xm.cpp +++ /dev/null @@ -1,892 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque <olivierl@jps.net>, - * Adam Goode <adam@evdebs.org> (endian and char fixes for PPC) -*/ - -#include "stdafx.h" -#include "sndfile.h" - -//////////////////////////////////////////////////////// -// FastTracker II XM file support - -#ifdef MSC_VER -#pragma warning(disable:4244) -#endif - -#pragma pack(1) -typedef struct tagXMFILEHEADER -{ - DWORD size; - WORD norder; - WORD restartpos; - WORD channels; - WORD patterns; - WORD instruments; - WORD flags; - WORD speed; - WORD tempo; - BYTE order[256]; -} XMFILEHEADER; - - -typedef struct tagXMINSTRUMENTHEADER -{ - DWORD size; - CHAR name[22]; - BYTE type; - BYTE samples; - BYTE samplesh; -} XMINSTRUMENTHEADER; - - -typedef struct tagXMSAMPLEHEADER -{ - DWORD shsize; - BYTE snum[96]; - WORD venv[24]; - WORD penv[24]; - BYTE vnum, pnum; - BYTE vsustain, vloops, vloope, psustain, ploops, ploope; - BYTE vtype, ptype; - BYTE vibtype, vibsweep, vibdepth, vibrate; - WORD volfade; - WORD res; - BYTE reserved1[20]; -} XMSAMPLEHEADER; - -typedef struct tagXMSAMPLESTRUCT -{ - DWORD samplen; - DWORD loopstart; - DWORD looplen; - BYTE vol; - signed char finetune; - BYTE type; - BYTE pan; - signed char relnote; - BYTE res; - char name[22]; -} XMSAMPLESTRUCT; -#pragma pack() - - -BOOL CSoundFile::ReadXM(const BYTE *lpStream, DWORD dwMemLength) -//-------------------------------------------------------------- -{ - XMSAMPLEHEADER xmsh; - XMSAMPLESTRUCT xmss; - DWORD dwMemPos, dwHdrSize; - WORD norders=0, restartpos=0, channels=0, patterns=0, instruments=0; - WORD xmflags=0, deftempo=125, defspeed=6; - BOOL InstUsed[256]; - BYTE channels_used[MAX_CHANNELS]; - BYTE pattern_map[256]; - BOOL samples_used[MAX_SAMPLES]; - UINT unused_samples; - - m_nChannels = 0; - if ((!lpStream) || (dwMemLength < 0x200)) return FALSE; - if (strnicmp((LPCSTR)lpStream, "Extended Module", 15)) return FALSE; - - memcpy(m_szNames[0], lpStream+17, 20); - dwHdrSize = bswapLE32(*((DWORD *)(lpStream+60))); - norders = bswapLE16(*((WORD *)(lpStream+64))); - if ((!norders) || (norders > MAX_ORDERS)) return FALSE; - restartpos = bswapLE16(*((WORD *)(lpStream+66))); - channels = bswapLE16(*((WORD *)(lpStream+68))); - if ((!channels) || (channels > 64)) return FALSE; - m_nType = MOD_TYPE_XM; - m_nMinPeriod = 27; - m_nMaxPeriod = 54784; - m_nChannels = channels; - if (restartpos < norders) m_nRestartPos = restartpos; - patterns = bswapLE16(*((WORD *)(lpStream+70))); - if (patterns > 256) patterns = 256; - instruments = bswapLE16(*((WORD *)(lpStream+72))); - if (instruments >= MAX_INSTRUMENTS) instruments = MAX_INSTRUMENTS-1; - m_nInstruments = instruments; - m_nSamples = 0; - memcpy(&xmflags, lpStream+74, 2); - xmflags = bswapLE16(xmflags); - if (xmflags & 1) m_dwSongFlags |= SONG_LINEARSLIDES; - if (xmflags & 0x1000) m_dwSongFlags |= SONG_EXFILTERRANGE; - defspeed = bswapLE16(*((WORD *)(lpStream+76))); - deftempo = bswapLE16(*((WORD *)(lpStream+78))); - if ((deftempo >= 32) && (deftempo < 256)) m_nDefaultTempo = deftempo; - if ((defspeed > 0) && (defspeed < 40)) m_nDefaultSpeed = defspeed; - memcpy(Order, lpStream+80, norders); - memset(InstUsed, 0, sizeof(InstUsed)); - if (patterns > MAX_PATTERNS) - { - UINT i, j; - for (i=0; i<norders; i++) - { - if (Order[i] < patterns) InstUsed[Order[i]] = TRUE; - } - j = 0; - for (i=0; i<256; i++) - { - if (InstUsed[i]) pattern_map[i] = j++; - } - for (i=0; i<256; i++) - { - if (!InstUsed[i]) - { - pattern_map[i] = (j < MAX_PATTERNS) ? j : 0xFE; - j++; - } - } - for (i=0; i<norders; i++) - { - Order[i] = pattern_map[Order[i]]; - } - } else - { - for (UINT i=0; i<256; i++) pattern_map[i] = i; - } - memset(InstUsed, 0, sizeof(InstUsed)); - dwMemPos = dwHdrSize + 60; - if (dwMemPos + 8 >= dwMemLength) return TRUE; - // Reading patterns - memset(channels_used, 0, sizeof(channels_used)); - for (UINT ipat=0; ipat<patterns; ipat++) - { - UINT ipatmap = pattern_map[ipat]; - DWORD dwSize = 0; - WORD rows=64, packsize=0; - dwSize = bswapLE32(*((DWORD *)(lpStream+dwMemPos))); - while ((dwMemPos + dwSize >= dwMemLength) || (dwSize & 0xFFFFFF00)) - { - if (dwMemPos + 4 >= dwMemLength) break; - dwMemPos++; - dwSize = bswapLE32(*((DWORD *)(lpStream+dwMemPos))); - } - rows = bswapLE16(*((WORD *)(lpStream+dwMemPos+5))); - if ((!rows) || (rows > 256)) rows = 64; - packsize = bswapLE16(*((WORD *)(lpStream+dwMemPos+7))); - if (dwMemPos + dwSize + 4 > dwMemLength) return TRUE; - dwMemPos += dwSize; - if (dwMemPos + packsize + 4 > dwMemLength) return TRUE; - MODCOMMAND *p; - if (ipatmap < MAX_PATTERNS) - { - PatternSize[ipatmap] = rows; - if ((Patterns[ipatmap] = AllocatePattern(rows, m_nChannels)) == NULL) return TRUE; - if (!packsize) continue; - p = Patterns[ipatmap]; - } else p = NULL; - const BYTE *src = lpStream+dwMemPos; - UINT j=0; - for (UINT row=0; row<rows; row++) - { - for (UINT chn=0; chn<m_nChannels; chn++) - { - if ((p) && (j < packsize)) - { - BYTE b = src[j++]; - UINT vol = 0; - if (b & 0x80) - { - if (b & 1) p->note = src[j++]; - if (b & 2) p->instr = src[j++]; - if (b & 4) vol = src[j++]; - if (b & 8) p->command = src[j++]; - if (b & 16) p->param = src[j++]; - } else - { - p->note = b; - p->instr = src[j++]; - vol = src[j++]; - p->command = src[j++]; - p->param = src[j++]; - } - if (p->note == 97) p->note = 0xFF; else - if ((p->note) && (p->note < 97)) p->note += 12; - if (p->note) channels_used[chn] = 1; - if (p->command | p->param) ConvertModCommand(p); - if (p->instr == 0xff) p->instr = 0; - if (p->instr) InstUsed[p->instr] = TRUE; - if ((vol >= 0x10) && (vol <= 0x50)) - { - p->volcmd = VOLCMD_VOLUME; - p->vol = vol - 0x10; - } else - if (vol >= 0x60) - { - UINT v = vol & 0xF0; - vol &= 0x0F; - p->vol = vol; - switch(v) - { - // 60-6F: Volume Slide Down - case 0x60: p->volcmd = VOLCMD_VOLSLIDEDOWN; break; - // 70-7F: Volume Slide Up: - case 0x70: p->volcmd = VOLCMD_VOLSLIDEUP; break; - // 80-8F: Fine Volume Slide Down - case 0x80: p->volcmd = VOLCMD_FINEVOLDOWN; break; - // 90-9F: Fine Volume Slide Up - case 0x90: p->volcmd = VOLCMD_FINEVOLUP; break; - // A0-AF: Set Vibrato Speed - case 0xA0: p->volcmd = VOLCMD_VIBRATOSPEED; break; - // B0-BF: Vibrato - case 0xB0: p->volcmd = VOLCMD_VIBRATO; break; - // C0-CF: Set Panning - case 0xC0: p->volcmd = VOLCMD_PANNING; p->vol = (vol << 2) + 2; break; - // D0-DF: Panning Slide Left - case 0xD0: p->volcmd = VOLCMD_PANSLIDELEFT; break; - // E0-EF: Panning Slide Right - case 0xE0: p->volcmd = VOLCMD_PANSLIDERIGHT; break; - // F0-FF: Tone Portamento - case 0xF0: p->volcmd = VOLCMD_TONEPORTAMENTO; break; - } - } - p++; - } else - if (j < packsize) - { - BYTE b = src[j++]; - if (b & 0x80) - { - if (b & 1) j++; - if (b & 2) j++; - if (b & 4) j++; - if (b & 8) j++; - if (b & 16) j++; - } else j += 4; - } else break; - } - } - dwMemPos += packsize; - } - // Wrong offset check - while (dwMemPos + 4 < dwMemLength) - { - DWORD d = bswapLE32(*((DWORD *)(lpStream+dwMemPos))); - if (d < 0x300) break; - dwMemPos++; - } - memset(samples_used, 0, sizeof(samples_used)); - unused_samples = 0; - // Reading instruments - for (UINT iIns=1; iIns<=instruments; iIns++) - { - XMINSTRUMENTHEADER *pih; - BYTE flags[32]; - DWORD samplesize[32]; - UINT samplemap[32]; - WORD nsamples; - - if (dwMemPos + sizeof(XMINSTRUMENTHEADER) >= dwMemLength) return TRUE; - pih = (XMINSTRUMENTHEADER *)(lpStream+dwMemPos); - if (dwMemPos + bswapLE32(pih->size) > dwMemLength) return TRUE; - if ((Headers[iIns] = new INSTRUMENTHEADER) == NULL) continue; - memset(Headers[iIns], 0, sizeof(INSTRUMENTHEADER)); - memcpy(Headers[iIns]->name, pih->name, 22); - if ((nsamples = pih->samples) > 0) - { - if (dwMemPos + sizeof(XMSAMPLEHEADER) > dwMemLength) return TRUE; - memcpy(&xmsh, lpStream+dwMemPos+sizeof(XMINSTRUMENTHEADER), sizeof(XMSAMPLEHEADER)); - xmsh.shsize = bswapLE32(xmsh.shsize); - for (int i = 0; i < 24; ++i) { - xmsh.venv[i] = bswapLE16(xmsh.venv[i]); - xmsh.penv[i] = bswapLE16(xmsh.penv[i]); - } - xmsh.volfade = bswapLE16(xmsh.volfade); - xmsh.res = bswapLE16(xmsh.res); - dwMemPos += bswapLE32(pih->size); - } else - { - if (bswapLE32(pih->size)) dwMemPos += bswapLE32(pih->size); - else dwMemPos += sizeof(XMINSTRUMENTHEADER); - continue; - } - memset(samplemap, 0, sizeof(samplemap)); - if (nsamples > 32) return TRUE; - UINT newsamples = m_nSamples; - for (UINT nmap=0; nmap<nsamples; nmap++) - { - UINT n = m_nSamples+nmap+1; - if (n >= MAX_SAMPLES) - { - n = m_nSamples; - while (n > 0) - { - if (!Ins[n].pSample) - { - for (UINT xmapchk=0; xmapchk < nmap; xmapchk++) - { - if (samplemap[xmapchk] == n) goto alreadymapped; - } - for (UINT clrs=1; clrs<iIns; clrs++) if (Headers[clrs]) - { - INSTRUMENTHEADER *pks = Headers[clrs]; - for (UINT ks=0; ks<128; ks++) - { - if (pks->Keyboard[ks] == n) pks->Keyboard[ks] = 0; - } - } - break; - } - alreadymapped: - n--; - } -#ifndef MODPLUG_FASTSOUNDLIB - // Damn! more than 200 samples: look for duplicates - if (!n) - { - if (!unused_samples) - { - unused_samples = DetectUnusedSamples(samples_used); - if (!unused_samples) unused_samples = 0xFFFF; - } - if ((unused_samples) && (unused_samples != 0xFFFF)) - { - for (UINT iext=m_nSamples; iext>=1; iext--) if (!samples_used[iext]) - { - unused_samples--; - samples_used[iext] = TRUE; - DestroySample(iext); - n = iext; - for (UINT mapchk=0; mapchk<nmap; mapchk++) - { - if (samplemap[mapchk] == n) samplemap[mapchk] = 0; - } - for (UINT clrs=1; clrs<iIns; clrs++) if (Headers[clrs]) - { - INSTRUMENTHEADER *pks = Headers[clrs]; - for (UINT ks=0; ks<128; ks++) - { - if (pks->Keyboard[ks] == n) pks->Keyboard[ks] = 0; - } - } - memset(&Ins[n], 0, sizeof(Ins[0])); - break; - } - } - } -#endif // MODPLUG_FASTSOUNDLIB - } - if (newsamples < n) newsamples = n; - samplemap[nmap] = n; - } - m_nSamples = newsamples; - // Reading Volume Envelope - INSTRUMENTHEADER *penv = Headers[iIns]; - penv->nMidiProgram = pih->type; - penv->nFadeOut = xmsh.volfade; - penv->nPan = 128; - penv->nPPC = 5*12; - if (xmsh.vtype & 1) penv->dwFlags |= ENV_VOLUME; - if (xmsh.vtype & 2) penv->dwFlags |= ENV_VOLSUSTAIN; - if (xmsh.vtype & 4) penv->dwFlags |= ENV_VOLLOOP; - if (xmsh.ptype & 1) penv->dwFlags |= ENV_PANNING; - if (xmsh.ptype & 2) penv->dwFlags |= ENV_PANSUSTAIN; - if (xmsh.ptype & 4) penv->dwFlags |= ENV_PANLOOP; - if (xmsh.vnum > 12) xmsh.vnum = 12; - if (xmsh.pnum > 12) xmsh.pnum = 12; - penv->nVolEnv = xmsh.vnum; - if (!xmsh.vnum) penv->dwFlags &= ~ENV_VOLUME; - if (!xmsh.pnum) penv->dwFlags &= ~ENV_PANNING; - penv->nPanEnv = xmsh.pnum; - penv->nVolSustainBegin = penv->nVolSustainEnd = xmsh.vsustain; - if (xmsh.vsustain >= 12) penv->dwFlags &= ~ENV_VOLSUSTAIN; - penv->nVolLoopStart = xmsh.vloops; - penv->nVolLoopEnd = xmsh.vloope; - if (penv->nVolLoopEnd >= 12) penv->nVolLoopEnd = 0; - if (penv->nVolLoopStart >= penv->nVolLoopEnd) penv->dwFlags &= ~ENV_VOLLOOP; - penv->nPanSustainBegin = penv->nPanSustainEnd = xmsh.psustain; - if (xmsh.psustain >= 12) penv->dwFlags &= ~ENV_PANSUSTAIN; - penv->nPanLoopStart = xmsh.ploops; - penv->nPanLoopEnd = xmsh.ploope; - if (penv->nPanLoopEnd >= 12) penv->nPanLoopEnd = 0; - if (penv->nPanLoopStart >= penv->nPanLoopEnd) penv->dwFlags &= ~ENV_PANLOOP; - penv->nGlobalVol = 64; - for (UINT ienv=0; ienv<12; ienv++) - { - penv->VolPoints[ienv] = (WORD)xmsh.venv[ienv*2]; - penv->VolEnv[ienv] = (BYTE)xmsh.venv[ienv*2+1]; - penv->PanPoints[ienv] = (WORD)xmsh.penv[ienv*2]; - penv->PanEnv[ienv] = (BYTE)xmsh.penv[ienv*2+1]; - if (ienv) - { - if (penv->VolPoints[ienv] < penv->VolPoints[ienv-1]) - { - penv->VolPoints[ienv] &= 0xFF; - penv->VolPoints[ienv] += penv->VolPoints[ienv-1] & 0xFF00; - if (penv->VolPoints[ienv] < penv->VolPoints[ienv-1]) penv->VolPoints[ienv] += 0x100; - } - if (penv->PanPoints[ienv] < penv->PanPoints[ienv-1]) - { - penv->PanPoints[ienv] &= 0xFF; - penv->PanPoints[ienv] += penv->PanPoints[ienv-1] & 0xFF00; - if (penv->PanPoints[ienv] < penv->PanPoints[ienv-1]) penv->PanPoints[ienv] += 0x100; - } - } - } - for (UINT j=0; j<96; j++) - { - penv->NoteMap[j+12] = j+1+12; - if (xmsh.snum[j] < nsamples) - penv->Keyboard[j+12] = samplemap[xmsh.snum[j]]; - } - // Reading samples - for (UINT ins=0; ins<nsamples; ins++) - { - if ((dwMemPos + sizeof(xmss) > dwMemLength) - || (dwMemPos + xmsh.shsize > dwMemLength)) return TRUE; - memcpy(&xmss, lpStream+dwMemPos, sizeof(xmss)); - xmss.samplen = bswapLE32(xmss.samplen); - xmss.loopstart = bswapLE32(xmss.loopstart); - xmss.looplen = bswapLE32(xmss.looplen); - dwMemPos += xmsh.shsize; - flags[ins] = (xmss.type & 0x10) ? RS_PCM16D : RS_PCM8D; - if (xmss.type & 0x20) flags[ins] = (xmss.type & 0x10) ? RS_STPCM16D : RS_STPCM8D; - samplesize[ins] = xmss.samplen; - if (!samplemap[ins]) continue; - if (xmss.type & 0x10) - { - xmss.looplen >>= 1; - xmss.loopstart >>= 1; - xmss.samplen >>= 1; - } - if (xmss.type & 0x20) - { - xmss.looplen >>= 1; - xmss.loopstart >>= 1; - xmss.samplen >>= 1; - } - if (xmss.samplen > MAX_SAMPLE_LENGTH) xmss.samplen = MAX_SAMPLE_LENGTH; - if (xmss.loopstart >= xmss.samplen) xmss.type &= ~3; - xmss.looplen += xmss.loopstart; - if (xmss.looplen > xmss.samplen) xmss.looplen = xmss.samplen; - if (!xmss.looplen) xmss.type &= ~3; - UINT imapsmp = samplemap[ins]; - memcpy(m_szNames[imapsmp], xmss.name, 22); - m_szNames[imapsmp][22] = 0; - MODINSTRUMENT *pins = &Ins[imapsmp]; - pins->nLength = (xmss.samplen > MAX_SAMPLE_LENGTH) ? MAX_SAMPLE_LENGTH : xmss.samplen; - pins->nLoopStart = xmss.loopstart; - pins->nLoopEnd = xmss.looplen; - if (pins->nLoopEnd > pins->nLength) pins->nLoopEnd = pins->nLength; - if (pins->nLoopStart >= pins->nLoopEnd) - { - pins->nLoopStart = pins->nLoopEnd = 0; - } - if (xmss.type & 3) pins->uFlags |= CHN_LOOP; - if (xmss.type & 2) pins->uFlags |= CHN_PINGPONGLOOP; - pins->nVolume = xmss.vol << 2; - if (pins->nVolume > 256) pins->nVolume = 256; - pins->nGlobalVol = 64; - if ((xmss.res == 0xAD) && (!(xmss.type & 0x30))) - { - flags[ins] = RS_ADPCM4; - samplesize[ins] = (samplesize[ins]+1)/2 + 16; - } - pins->nFineTune = xmss.finetune; - pins->RelativeTone = (int)xmss.relnote; - pins->nPan = xmss.pan; - pins->uFlags |= CHN_PANNING; - pins->nVibType = xmsh.vibtype; - pins->nVibSweep = xmsh.vibsweep; - pins->nVibDepth = xmsh.vibdepth; - pins->nVibRate = xmsh.vibrate; - memcpy(pins->name, xmss.name, 22); - pins->name[21] = 0; - } -#if 0 - if ((xmsh.reserved2 > nsamples) && (xmsh.reserved2 <= 16)) - { - dwMemPos += (((UINT)xmsh.reserved2) - nsamples) * xmsh.shsize; - } -#endif - for (UINT ismpd=0; ismpd<nsamples; ismpd++) - { - if ((samplemap[ismpd]) && (samplesize[ismpd]) && (dwMemPos < dwMemLength)) - { - ReadSample(&Ins[samplemap[ismpd]], flags[ismpd], (LPSTR)(lpStream + dwMemPos), dwMemLength - dwMemPos); - } - dwMemPos += samplesize[ismpd]; - if (dwMemPos >= dwMemLength) break; - } - } - // Read song comments: "TEXT" - if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x74786574)) - { - UINT len = *((DWORD *)(lpStream+dwMemPos+4)); - dwMemPos += 8; - if ((dwMemPos + len <= dwMemLength) && (len < 16384)) - { - m_lpszSongComments = new char[len+1]; - if (m_lpszSongComments) - { - memcpy(m_lpszSongComments, lpStream+dwMemPos, len); - m_lpszSongComments[len] = 0; - } - dwMemPos += len; - } - } - // Read midi config: "MIDI" - if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x4944494D)) - { - UINT len = *((DWORD *)(lpStream+dwMemPos+4)); - dwMemPos += 8; - if (len == sizeof(MODMIDICFG)) - { - memcpy(&m_MidiCfg, lpStream+dwMemPos, len); - m_dwSongFlags |= SONG_EMBEDMIDICFG; - } - } - // Read pattern names: "PNAM" - if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x4d414e50)) - { - UINT len = *((DWORD *)(lpStream+dwMemPos+4)); - dwMemPos += 8; - if ((dwMemPos + len <= dwMemLength) && (len <= MAX_PATTERNS*MAX_PATTERNNAME) && (len >= MAX_PATTERNNAME)) - { - m_lpszPatternNames = new char[len]; - - if (m_lpszPatternNames) - { - m_nPatternNames = len / MAX_PATTERNNAME; - memcpy(m_lpszPatternNames, lpStream+dwMemPos, len); - } - dwMemPos += len; - } - } - // Read channel names: "CNAM" - if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x4d414e43)) - { - UINT len = *((DWORD *)(lpStream+dwMemPos+4)); - dwMemPos += 8; - if ((dwMemPos + len <= dwMemLength) && (len <= MAX_BASECHANNELS*MAX_CHANNELNAME)) - { - UINT n = len / MAX_CHANNELNAME; - for (UINT i=0; i<n; i++) - { - memcpy(ChnSettings[i].szName, (lpStream+dwMemPos+i*MAX_CHANNELNAME), MAX_CHANNELNAME); - ChnSettings[i].szName[MAX_CHANNELNAME-1] = 0; - } - dwMemPos += len; - } - } - // Read mix plugins information - if (dwMemPos + 8 < dwMemLength) - { - dwMemPos += LoadMixPlugins(lpStream+dwMemPos, dwMemLength-dwMemPos); - } - return TRUE; -} - - -#ifndef MODPLUG_NO_FILESAVE - -BOOL CSoundFile::SaveXM(LPCSTR lpszFileName, UINT nPacking) -//--------------------------------------------------------- -{ - BYTE s[64*64*5]; - XMFILEHEADER header; - XMINSTRUMENTHEADER xmih; - XMSAMPLEHEADER xmsh; - XMSAMPLESTRUCT xmss; - BYTE smptable[32]; - BYTE xmph[9]; - FILE *f; - int i; - - if ((!m_nChannels) || (!lpszFileName)) return FALSE; - if ((f = fopen(lpszFileName, "wb")) == NULL) return FALSE; - fwrite("Extended Module: ", 17, 1, f); - fwrite(m_szNames[0], 20, 1, f); - s[0] = 0x1A; - lstrcpy((LPSTR)&s[1], (nPacking) ? "MOD Plugin packed " : "FastTracker v2.00 "); - s[21] = 0x04; - s[22] = 0x01; - fwrite(s, 23, 1, f); - // Writing song header - memset(&header, 0, sizeof(header)); - header.size = sizeof(XMFILEHEADER); - header.norder = 0; - header.restartpos = m_nRestartPos; - header.channels = m_nChannels; - header.patterns = 0; - for (i=0; i<MAX_ORDERS; i++) - { - if (Order[i] == 0xFF) break; - header.norder++; - if ((Order[i] >= header.patterns) && (Order[i] < MAX_PATTERNS)) header.patterns = Order[i]+1; - } - header.instruments = m_nInstruments; - if (!header.instruments) header.instruments = m_nSamples; - header.flags = (m_dwSongFlags & SONG_LINEARSLIDES) ? 0x01 : 0x00; - if (m_dwSongFlags & SONG_EXFILTERRANGE) header.flags |= 0x1000; - header.tempo = m_nDefaultTempo; - header.speed = m_nDefaultSpeed; - memcpy(header.order, Order, header.norder); - fwrite(&header, 1, sizeof(header), f); - // Writing patterns - for (i=0; i<header.patterns; i++) if (Patterns[i]) - { - MODCOMMAND *p = Patterns[i]; - UINT len = 0; - - memset(&xmph, 0, sizeof(xmph)); - xmph[0] = 9; - xmph[5] = (BYTE)(PatternSize[i] & 0xFF); - xmph[6] = (BYTE)(PatternSize[i] >> 8); - for (UINT j=m_nChannels*PatternSize[i]; j; j--,p++) - { - UINT note = p->note; - UINT param = ModSaveCommand(p, TRUE); - UINT command = param >> 8; - param &= 0xFF; - if (note >= 0xFE) note = 97; else - if ((note <= 12) || (note > 96+12)) note = 0; else - note -= 12; - UINT vol = 0; - if (p->volcmd) - { - UINT volcmd = p->volcmd; - switch(volcmd) - { - case VOLCMD_VOLUME: vol = 0x10 + p->vol; break; - case VOLCMD_VOLSLIDEDOWN: vol = 0x60 + (p->vol & 0x0F); break; - case VOLCMD_VOLSLIDEUP: vol = 0x70 + (p->vol & 0x0F); break; - case VOLCMD_FINEVOLDOWN: vol = 0x80 + (p->vol & 0x0F); break; - case VOLCMD_FINEVOLUP: vol = 0x90 + (p->vol & 0x0F); break; - case VOLCMD_VIBRATOSPEED: vol = 0xA0 + (p->vol & 0x0F); break; - case VOLCMD_VIBRATO: vol = 0xB0 + (p->vol & 0x0F); break; - case VOLCMD_PANNING: vol = 0xC0 + (p->vol >> 2); if (vol > 0xCF) vol = 0xCF; break; - case VOLCMD_PANSLIDELEFT: vol = 0xD0 + (p->vol & 0x0F); break; - case VOLCMD_PANSLIDERIGHT: vol = 0xE0 + (p->vol & 0x0F); break; - case VOLCMD_TONEPORTAMENTO: vol = 0xF0 + (p->vol & 0x0F); break; - } - } - if ((note) && (p->instr) && (vol > 0x0F) && (command) && (param)) - { - s[len++] = note; - s[len++] = p->instr; - s[len++] = vol; - s[len++] = command; - s[len++] = param; - } else - { - BYTE b = 0x80; - if (note) b |= 0x01; - if (p->instr) b |= 0x02; - if (vol >= 0x10) b |= 0x04; - if (command) b |= 0x08; - if (param) b |= 0x10; - s[len++] = b; - if (b & 1) s[len++] = note; - if (b & 2) s[len++] = p->instr; - if (b & 4) s[len++] = vol; - if (b & 8) s[len++] = command; - if (b & 16) s[len++] = param; - } - if (len > sizeof(s) - 5) break; - } - xmph[7] = (BYTE)(len & 0xFF); - xmph[8] = (BYTE)(len >> 8); - fwrite(xmph, 1, 9, f); - fwrite(s, 1, len, f); - } else - { - memset(&xmph, 0, sizeof(xmph)); - xmph[0] = 9; - xmph[5] = (BYTE)(PatternSize[i] & 0xFF); - xmph[6] = (BYTE)(PatternSize[i] >> 8); - fwrite(xmph, 1, 9, f); - } - // Writing instruments - for (i=1; i<=header.instruments; i++) - { - MODINSTRUMENT *pins; - BYTE flags[32]; - - memset(&xmih, 0, sizeof(xmih)); - memset(&xmsh, 0, sizeof(xmsh)); - xmih.size = sizeof(xmih) + sizeof(xmsh); - memcpy(xmih.name, m_szNames[i], 22); - xmih.type = 0; - xmih.samples = 0; - if (m_nInstruments) - { - INSTRUMENTHEADER *penv = Headers[i]; - if (penv) - { - memcpy(xmih.name, penv->name, 22); - xmih.type = penv->nMidiProgram; - xmsh.volfade = penv->nFadeOut; - xmsh.vnum = (BYTE)penv->nVolEnv; - xmsh.pnum = (BYTE)penv->nPanEnv; - if (xmsh.vnum > 12) xmsh.vnum = 12; - if (xmsh.pnum > 12) xmsh.pnum = 12; - for (UINT ienv=0; ienv<12; ienv++) - { - xmsh.venv[ienv*2] = penv->VolPoints[ienv]; - xmsh.venv[ienv*2+1] = penv->VolEnv[ienv]; - xmsh.penv[ienv*2] = penv->PanPoints[ienv]; - xmsh.penv[ienv*2+1] = penv->PanEnv[ienv]; - } - if (penv->dwFlags & ENV_VOLUME) xmsh.vtype |= 1; - if (penv->dwFlags & ENV_VOLSUSTAIN) xmsh.vtype |= 2; - if (penv->dwFlags & ENV_VOLLOOP) xmsh.vtype |= 4; - if (penv->dwFlags & ENV_PANNING) xmsh.ptype |= 1; - if (penv->dwFlags & ENV_PANSUSTAIN) xmsh.ptype |= 2; - if (penv->dwFlags & ENV_PANLOOP) xmsh.ptype |= 4; - xmsh.vsustain = (BYTE)penv->nVolSustainBegin; - xmsh.vloops = (BYTE)penv->nVolLoopStart; - xmsh.vloope = (BYTE)penv->nVolLoopEnd; - xmsh.psustain = (BYTE)penv->nPanSustainBegin; - xmsh.ploops = (BYTE)penv->nPanLoopStart; - xmsh.ploope = (BYTE)penv->nPanLoopEnd; - for (UINT j=0; j<96; j++) if (penv->Keyboard[j+12]) - { - UINT k; - for (k=0; k<xmih.samples; k++) if (smptable[k] == penv->Keyboard[j+12]) break; - if (k == xmih.samples) - { - smptable[xmih.samples++] = penv->Keyboard[j+12]; - } - if (xmih.samples >= 32) break; - xmsh.snum[j] = k; - } -// xmsh.reserved2 = xmih.samples; - } - } else - { - xmih.samples = 1; -// xmsh.reserved2 = 1; - smptable[0] = i; - } - xmsh.shsize = (xmih.samples) ? 40 : 0; - fwrite(&xmih, 1, sizeof(xmih), f); - if (smptable[0]) - { - MODINSTRUMENT *pvib = &Ins[smptable[0]]; - xmsh.vibtype = pvib->nVibType; - xmsh.vibsweep = pvib->nVibSweep; - xmsh.vibdepth = pvib->nVibDepth; - xmsh.vibrate = pvib->nVibRate; - } - fwrite(&xmsh, 1, xmih.size - sizeof(xmih), f); - if (!xmih.samples) continue; - for (UINT ins=0; ins<xmih.samples; ins++) - { - memset(&xmss, 0, sizeof(xmss)); - if (smptable[ins]) memcpy(xmss.name, m_szNames[smptable[ins]], 22); - pins = &Ins[smptable[ins]]; - xmss.samplen = pins->nLength; - xmss.loopstart = pins->nLoopStart; - xmss.looplen = pins->nLoopEnd - pins->nLoopStart; - xmss.vol = pins->nVolume / 4; - xmss.finetune = (char)pins->nFineTune; - xmss.type = 0; - if (pins->uFlags & CHN_LOOP) xmss.type = (pins->uFlags & CHN_PINGPONGLOOP) ? 2 : 1; - flags[ins] = RS_PCM8D; -#ifndef NO_PACKING - if (nPacking) - { - if ((!(pins->uFlags & (CHN_16BIT|CHN_STEREO))) - && (CanPackSample((char *)pins->pSample, pins->nLength, nPacking))) - { - flags[ins] = RS_ADPCM4; - xmss.res = 0xAD; - } - } else -#endif - { - if (pins->uFlags & CHN_16BIT) - { - flags[ins] = RS_PCM16D; - xmss.type |= 0x10; - xmss.looplen *= 2; - xmss.loopstart *= 2; - xmss.samplen *= 2; - } - if (pins->uFlags & CHN_STEREO) - { - flags[ins] = (pins->uFlags & CHN_16BIT) ? RS_STPCM16D : RS_STPCM8D; - xmss.type |= 0x20; - xmss.looplen *= 2; - xmss.loopstart *= 2; - xmss.samplen *= 2; - } - } - xmss.pan = 255; - if (pins->nPan < 256) xmss.pan = (BYTE)pins->nPan; - xmss.relnote = (signed char)pins->RelativeTone; - fwrite(&xmss, 1, xmsh.shsize, f); - } - for (UINT ismpd=0; ismpd<xmih.samples; ismpd++) - { - pins = &Ins[smptable[ismpd]]; - if (pins->pSample) - { -#ifndef NO_PACKING - if ((flags[ismpd] == RS_ADPCM4) && (xmih.samples>1)) CanPackSample((char *)pins->pSample, pins->nLength, nPacking); -#endif // NO_PACKING - WriteSample(f, pins, flags[ismpd]); - } - } - } - // Writing song comments - if ((m_lpszSongComments) && (m_lpszSongComments[0])) - { - DWORD d = 0x74786574; - fwrite(&d, 1, 4, f); - d = strlen(m_lpszSongComments); - fwrite(&d, 1, 4, f); - fwrite(m_lpszSongComments, 1, d, f); - } - // Writing midi cfg - if (m_dwSongFlags & SONG_EMBEDMIDICFG) - { - DWORD d = 0x4944494D; - fwrite(&d, 1, 4, f); - d = sizeof(MODMIDICFG); - fwrite(&d, 1, 4, f); - fwrite(&m_MidiCfg, 1, sizeof(MODMIDICFG), f); - } - // Writing Pattern Names - if ((m_nPatternNames) && (m_lpszPatternNames)) - { - DWORD dwLen = m_nPatternNames * MAX_PATTERNNAME; - while ((dwLen >= MAX_PATTERNNAME) && (!m_lpszPatternNames[dwLen-MAX_PATTERNNAME])) dwLen -= MAX_PATTERNNAME; - if (dwLen >= MAX_PATTERNNAME) - { - DWORD d = 0x4d414e50; - fwrite(&d, 1, 4, f); - fwrite(&dwLen, 1, 4, f); - fwrite(m_lpszPatternNames, 1, dwLen, f); - } - } - // Writing Channel Names - { - UINT nChnNames = 0; - for (UINT inam=0; inam<m_nChannels; inam++) - { - if (ChnSettings[inam].szName[0]) nChnNames = inam+1; - } - // Do it! - if (nChnNames) - { - DWORD dwLen = nChnNames * MAX_CHANNELNAME; - DWORD d = 0x4d414e43; - fwrite(&d, 1, 4, f); - fwrite(&dwLen, 1, 4, f); - for (UINT inam=0; inam<nChnNames; inam++) - { - fwrite(ChnSettings[inam].szName, 1, MAX_CHANNELNAME, f); - } - } - } - // Save mix plugins information - SaveMixPlugins(f); - fclose(f); - return TRUE; -} - -#endif // MODPLUG_NO_FILESAVE diff --git a/lib/libmodplug/src/mmcmp.cpp b/lib/libmodplug/src/mmcmp.cpp deleted file mode 100644 index 200ee3b93d..0000000000 --- a/lib/libmodplug/src/mmcmp.cpp +++ /dev/null @@ -1,406 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque <olivierl@jps.net> -*/ - -#include "stdafx.h" -#include "sndfile.h" - -BOOL PP20_Unpack(LPCBYTE *ppMemFile, LPDWORD pdwMemLength); - -typedef struct MMCMPFILEHEADER -{ - DWORD id_ziRC; // "ziRC" - DWORD id_ONia; // "ONia" - WORD hdrsize; -} MMCMPFILEHEADER, *LPMMCMPFILEHEADER; - -typedef struct MMCMPHEADER -{ - WORD version; - WORD nblocks; - DWORD filesize; - DWORD blktable; - BYTE glb_comp; - BYTE fmt_comp; -} MMCMPHEADER, *LPMMCMPHEADER; - -typedef struct MMCMPBLOCK -{ - DWORD unpk_size; - DWORD pk_size; - DWORD xor_chk; - WORD sub_blk; - WORD flags; - WORD tt_entries; - WORD num_bits; -} MMCMPBLOCK, *LPMMCMPBLOCK; - -typedef struct MMCMPSUBBLOCK -{ - DWORD unpk_pos; - DWORD unpk_size; -} MMCMPSUBBLOCK, *LPMMCMPSUBBLOCK; - -#define MMCMP_COMP 0x0001 -#define MMCMP_DELTA 0x0002 -#define MMCMP_16BIT 0x0004 -#define MMCMP_STEREO 0x0100 -#define MMCMP_ABS16 0x0200 -#define MMCMP_ENDIAN 0x0400 - -typedef struct MMCMPBITBUFFER -{ - UINT bitcount; - DWORD bitbuffer; - LPCBYTE pSrc; - LPCBYTE pEnd; - - DWORD GetBits(UINT nBits); -} MMCMPBITBUFFER; - - -DWORD MMCMPBITBUFFER::GetBits(UINT nBits) -//--------------------------------------- -{ - DWORD d; - if (!nBits) return 0; - while (bitcount < 24) - { - bitbuffer |= ((pSrc < pEnd) ? *pSrc++ : 0) << bitcount; - bitcount += 8; - } - d = bitbuffer & ((1 << nBits) - 1); - bitbuffer >>= nBits; - bitcount -= nBits; - return d; -} - -//#define MMCMP_LOG - -#ifdef MMCMP_LOG -extern void Log(LPCSTR s, ...); -#endif - -const DWORD MMCMP8BitCommands[8] = -{ - 0x01, 0x03, 0x07, 0x0F, 0x1E, 0x3C, 0x78, 0xF8 -}; - -const UINT MMCMP8BitFetch[8] = -{ - 3, 3, 3, 3, 2, 1, 0, 0 -}; - -const DWORD MMCMP16BitCommands[16] = -{ - 0x01, 0x03, 0x07, 0x0F, 0x1E, 0x3C, 0x78, 0xF0, - 0x1F0, 0x3F0, 0x7F0, 0xFF0, 0x1FF0, 0x3FF0, 0x7FF0, 0xFFF0 -}; - -const UINT MMCMP16BitFetch[16] = -{ - 4, 4, 4, 4, 3, 2, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0 -}; - - -BOOL MMCMP_Unpack(LPCBYTE *ppMemFile, LPDWORD pdwMemLength) -//--------------------------------------------------------- -{ - DWORD dwMemLength = *pdwMemLength; - LPCBYTE lpMemFile = *ppMemFile; - LPBYTE pBuffer; - LPMMCMPFILEHEADER pmfh = (LPMMCMPFILEHEADER)(lpMemFile); - LPMMCMPHEADER pmmh = (LPMMCMPHEADER)(lpMemFile+10); - LPDWORD pblk_table; - DWORD dwFileSize; - - if (PP20_Unpack(ppMemFile, pdwMemLength)) - { - return TRUE; - } - if ((dwMemLength < 256) || (!pmfh) || (pmfh->id_ziRC != 0x4352697A) || (pmfh->id_ONia != 0x61694e4f) || (pmfh->hdrsize < 14) - || (!pmmh->nblocks) || (pmmh->filesize < 16) || (pmmh->filesize > 0x8000000) - || (pmmh->blktable >= dwMemLength) || (pmmh->blktable + 4*pmmh->nblocks > dwMemLength)) return FALSE; - dwFileSize = pmmh->filesize; - if ((pBuffer = (LPBYTE)GlobalAllocPtr(GHND, (dwFileSize + 31) & ~15)) == NULL) return FALSE; - pblk_table = (LPDWORD)(lpMemFile+pmmh->blktable); - for (UINT nBlock=0; nBlock<pmmh->nblocks; nBlock++) - { - DWORD dwMemPos = pblk_table[nBlock]; - LPMMCMPBLOCK pblk = (LPMMCMPBLOCK)(lpMemFile+dwMemPos); - LPMMCMPSUBBLOCK psubblk = (LPMMCMPSUBBLOCK)(lpMemFile+dwMemPos+20); - - if ((dwMemPos + 20 >= dwMemLength) || (dwMemPos + 20 + pblk->sub_blk*8 >= dwMemLength)) break; - dwMemPos += 20 + pblk->sub_blk*8; -#ifdef MMCMP_LOG - Log("block %d: flags=%04X sub_blocks=%d", nBlock, (UINT)pblk->flags, (UINT)pblk->sub_blk); - Log(" pksize=%d unpksize=%d", pblk->pk_size, pblk->unpk_size); - Log(" tt_entries=%d num_bits=%d\n", pblk->tt_entries, pblk->num_bits); -#endif - // Data is not packed - if (!(pblk->flags & MMCMP_COMP)) - { - for (UINT i=0; i<pblk->sub_blk; i++) - { - if ((psubblk->unpk_pos > dwFileSize) || (psubblk->unpk_pos + psubblk->unpk_size > dwFileSize)) break; -#ifdef MMCMP_LOG - Log(" Unpacked sub-block %d: offset %d, size=%d\n", i, psubblk->unpk_pos, psubblk->unpk_size); -#endif - memcpy(pBuffer+psubblk->unpk_pos, lpMemFile+dwMemPos, psubblk->unpk_size); - dwMemPos += psubblk->unpk_size; - psubblk++; - } - } else - // Data is 16-bit packed - if (pblk->flags & MMCMP_16BIT) - { - MMCMPBITBUFFER bb; - LPWORD pDest = (LPWORD)(pBuffer + psubblk->unpk_pos); - DWORD dwSize = psubblk->unpk_size >> 1; - DWORD dwPos = 0; - UINT numbits = pblk->num_bits; - UINT subblk = 0, oldval = 0; - -#ifdef MMCMP_LOG - Log(" 16-bit block: pos=%d size=%d ", psubblk->unpk_pos, psubblk->unpk_size); - if (pblk->flags & MMCMP_DELTA) Log("DELTA "); - if (pblk->flags & MMCMP_ABS16) Log("ABS16 "); - Log("\n"); -#endif - bb.bitcount = 0; - bb.bitbuffer = 0; - bb.pSrc = lpMemFile+dwMemPos+pblk->tt_entries; - bb.pEnd = lpMemFile+dwMemPos+pblk->pk_size; - while (subblk < pblk->sub_blk) - { - UINT newval = 0x10000; - DWORD d = bb.GetBits(numbits+1); - - if (d >= MMCMP16BitCommands[numbits]) - { - UINT nFetch = MMCMP16BitFetch[numbits]; - UINT newbits = bb.GetBits(nFetch) + ((d - MMCMP16BitCommands[numbits]) << nFetch); - if (newbits != numbits) - { - numbits = newbits & 0x0F; - } else - { - if ((d = bb.GetBits(4)) == 0x0F) - { - if (bb.GetBits(1)) break; - newval = 0xFFFF; - } else - { - newval = 0xFFF0 + d; - } - } - } else - { - newval = d; - } - if (newval < 0x10000) - { - newval = (newval & 1) ? (UINT)(-(LONG)((newval+1) >> 1)) : (UINT)(newval >> 1); - if (pblk->flags & MMCMP_DELTA) - { - newval += oldval; - oldval = newval; - } else - if (!(pblk->flags & MMCMP_ABS16)) - { - newval ^= 0x8000; - } - pDest[dwPos++] = (WORD)newval; - } - if (dwPos >= dwSize) - { - subblk++; - dwPos = 0; - dwSize = psubblk[subblk].unpk_size >> 1; - pDest = (LPWORD)(pBuffer + psubblk[subblk].unpk_pos); - } - } - } else - // Data is 8-bit packed - { - MMCMPBITBUFFER bb; - LPBYTE pDest = pBuffer + psubblk->unpk_pos; - DWORD dwSize = psubblk->unpk_size; - DWORD dwPos = 0; - UINT numbits = pblk->num_bits; - UINT subblk = 0, oldval = 0; - LPCBYTE ptable = lpMemFile+dwMemPos; - - bb.bitcount = 0; - bb.bitbuffer = 0; - bb.pSrc = lpMemFile+dwMemPos+pblk->tt_entries; - bb.pEnd = lpMemFile+dwMemPos+pblk->pk_size; - while (subblk < pblk->sub_blk) - { - UINT newval = 0x100; - DWORD d = bb.GetBits(numbits+1); - - if (d >= MMCMP8BitCommands[numbits]) - { - UINT nFetch = MMCMP8BitFetch[numbits]; - UINT newbits = bb.GetBits(nFetch) + ((d - MMCMP8BitCommands[numbits]) << nFetch); - if (newbits != numbits) - { - numbits = newbits & 0x07; - } else - { - if ((d = bb.GetBits(3)) == 7) - { - if (bb.GetBits(1)) break; - newval = 0xFF; - } else - { - newval = 0xF8 + d; - } - } - } else - { - newval = d; - } - if (newval < 0x100) - { - int n = ptable[newval]; - if (pblk->flags & MMCMP_DELTA) - { - n += oldval; - oldval = n; - } - pDest[dwPos++] = (BYTE)n; - } - if (dwPos >= dwSize) - { - subblk++; - dwPos = 0; - dwSize = psubblk[subblk].unpk_size; - pDest = pBuffer + psubblk[subblk].unpk_pos; - } - } - } - } - *ppMemFile = pBuffer; - *pdwMemLength = dwFileSize; - return TRUE; -} - - -////////////////////////////////////////////////////////////////////////////// -// -// PowerPack PP20 Unpacker -// - -typedef struct _PPBITBUFFER -{ - UINT bitcount; - ULONG bitbuffer; - LPCBYTE pStart; - LPCBYTE pSrc; - - ULONG GetBits(UINT n); -} PPBITBUFFER; - - -ULONG PPBITBUFFER::GetBits(UINT n) -{ - ULONG result = 0; - - for (UINT i=0; i<n; i++) - { - if (!bitcount) - { - bitcount = 8; - if (pSrc != pStart) pSrc--; - bitbuffer = *pSrc; - } - result = (result<<1) | (bitbuffer&1); - bitbuffer >>= 1; - bitcount--; - } - return result; -} - - -VOID PP20_DoUnpack(const BYTE *pSrc, UINT nSrcLen, BYTE *pDst, UINT nDstLen) -{ - PPBITBUFFER BitBuffer; - ULONG nBytesLeft; - - BitBuffer.pStart = pSrc; - BitBuffer.pSrc = pSrc + nSrcLen - 4; - BitBuffer.bitbuffer = 0; - BitBuffer.bitcount = 0; - BitBuffer.GetBits(pSrc[nSrcLen-1]); - nBytesLeft = nDstLen; - while (nBytesLeft > 0) - { - if (!BitBuffer.GetBits(1)) - { - UINT n = 1; - while (n < nBytesLeft) - { - UINT code = BitBuffer.GetBits(2); - n += code; - if (code != 3) break; - } - for (UINT i=0; i<n; i++) - { - pDst[--nBytesLeft] = (BYTE)BitBuffer.GetBits(8); - } - if (!nBytesLeft) break; - } - { - UINT n = BitBuffer.GetBits(2)+1; - UINT nbits = pSrc[n-1]; - UINT nofs; - if (n==4) - { - nofs = BitBuffer.GetBits( (BitBuffer.GetBits(1)) ? nbits : 7 ); - while (n < nBytesLeft) - { - UINT code = BitBuffer.GetBits(3); - n += code; - if (code != 7) break; - } - } else - { - nofs = BitBuffer.GetBits(nbits); - } - for (UINT i=0; i<=n; i++) - { - pDst[nBytesLeft-1] = (nBytesLeft+nofs < nDstLen) ? pDst[nBytesLeft+nofs] : 0; - if (!--nBytesLeft) break; - } - } - } -} - - -BOOL PP20_Unpack(LPCBYTE *ppMemFile, LPDWORD pdwMemLength) -{ - DWORD dwMemLength = *pdwMemLength; - LPCBYTE lpMemFile = *ppMemFile; - DWORD dwDstLen; - LPBYTE pBuffer; - - if ((!lpMemFile) || (dwMemLength < 256) || (*(DWORD *)lpMemFile != 0x30325050)) return FALSE; - dwDstLen = (lpMemFile[dwMemLength-4]<<16) | (lpMemFile[dwMemLength-3]<<8) | (lpMemFile[dwMemLength-2]); - //Log("PP20 detected: Packed length=%d, Unpacked length=%d\n", dwMemLength, dwDstLen); - if ((dwDstLen < 512) || (dwDstLen > 0x400000) || (dwDstLen > 16*dwMemLength)) return FALSE; - if ((pBuffer = (LPBYTE)GlobalAllocPtr(GHND, (dwDstLen + 31) & ~15)) == NULL) return FALSE; - PP20_DoUnpack(lpMemFile+4, dwMemLength-4, pBuffer, dwDstLen); - *ppMemFile = pBuffer; - *pdwMemLength = dwDstLen; - return TRUE; -} - - - - - diff --git a/lib/libmodplug/src/modplug.cpp b/lib/libmodplug/src/modplug.cpp deleted file mode 100644 index b53de00b41..0000000000 --- a/lib/libmodplug/src/modplug.cpp +++ /dev/null @@ -1,271 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Kenton Varda <temporal@gauge3d.org> (C interface wrapper) - */ - -#include "modplug.h" -#include "stdafx.h" -#include "sndfile.h" - -struct _ModPlugFile -{ - CSoundFile mSoundFile; -}; - -namespace ModPlug -{ - ModPlug_Settings gSettings = - { - MODPLUG_ENABLE_OVERSAMPLING | MODPLUG_ENABLE_NOISE_REDUCTION, - - 2, - 16, - 44100, - MODPLUG_RESAMPLE_LINEAR, - - 0, - 0, - 0, - 0, - 0, - 0, - 0 - }; - - int gSampleSize; - - void UpdateSettings(bool updateBasicConfig) - { - if(gSettings.mFlags & MODPLUG_ENABLE_REVERB) - { - CSoundFile::SetReverbParameters(gSettings.mReverbDepth, - gSettings.mReverbDelay); - } - - if(gSettings.mFlags & MODPLUG_ENABLE_MEGABASS) - { - CSoundFile::SetXBassParameters(gSettings.mBassAmount, - gSettings.mBassRange); - } - else // modplug seems to ignore the SetWaveConfigEx() setting for bass boost - CSoundFile::SetXBassParameters(0, 0); - - if(gSettings.mFlags & MODPLUG_ENABLE_SURROUND) - { - CSoundFile::SetSurroundParameters(gSettings.mSurroundDepth, - gSettings.mSurroundDelay); - } - - if(updateBasicConfig) - { - CSoundFile::SetWaveConfig(gSettings.mFrequency, - gSettings.mBits, - gSettings.mChannels); - - gSampleSize = gSettings.mBits / 8 * gSettings.mChannels; - } - - CSoundFile::SetWaveConfigEx(gSettings.mFlags & MODPLUG_ENABLE_SURROUND, - !(gSettings.mFlags & MODPLUG_ENABLE_OVERSAMPLING), - gSettings.mFlags & MODPLUG_ENABLE_REVERB, - true, - gSettings.mFlags & MODPLUG_ENABLE_MEGABASS, - gSettings.mFlags & MODPLUG_ENABLE_NOISE_REDUCTION, - false); - CSoundFile::SetResamplingMode(gSettings.mResamplingMode); - } -} - -ModPlugFile* ModPlug_Load(const void* data, int size) -{ - ModPlugFile* result = new ModPlugFile; - ModPlug::UpdateSettings(true); - if(result->mSoundFile.Create((const BYTE*)data, size)) - { - result->mSoundFile.SetRepeatCount(ModPlug::gSettings.mLoopCount); - return result; - } - else - { - delete result; - return NULL; - } -} - -void ModPlug_Unload(ModPlugFile* file) -{ - file->mSoundFile.Destroy(); - delete file; -} - -int ModPlug_Read(ModPlugFile* file, void* buffer, int size) -{ - return file->mSoundFile.Read(buffer, size) * ModPlug::gSampleSize; -} - -const char* ModPlug_GetName(ModPlugFile* file) -{ - return file->mSoundFile.GetTitle(); -} - -int ModPlug_GetLength(ModPlugFile* file) -{ - return file->mSoundFile.GetSongTime() * 1000; -} - -void ModPlug_InitMixerCallback(ModPlugFile* file,ModPlugMixerProc proc) -{ - file->mSoundFile.gpSndMixHook = (LPSNDMIXHOOKPROC)proc ; - return; -} - -void ModPlug_UnloadMixerCallback(ModPlugFile* file) -{ - file->mSoundFile.gpSndMixHook = NULL; - return ; -} - -unsigned int ModPlug_GetMasterVolume(ModPlugFile* file) -{ - return (unsigned int)file->mSoundFile.m_nMasterVolume; -} - -void ModPlug_SetMasterVolume(ModPlugFile* file,unsigned int cvol) -{ - (void)file->mSoundFile.SetMasterVolume( (UINT)cvol, - FALSE ); - return ; -} - -int ModPlug_GetCurrentSpeed(ModPlugFile* file) -{ - return file->mSoundFile.m_nMusicSpeed; -} - -int ModPlug_GetCurrentTempo(ModPlugFile* file) -{ - return file->mSoundFile.m_nMusicTempo; -} - -int ModPlug_GetCurrentOrder(ModPlugFile* file) -{ - return file->mSoundFile.GetCurrentOrder(); -} - -int ModPlug_GetCurrentPattern(ModPlugFile* file) -{ - return file->mSoundFile.GetCurrentPattern(); -} - -int ModPlug_GetCurrentRow(ModPlugFile* file) -{ - return file->mSoundFile.m_nRow; -} - -int ModPlug_GetPlayingChannels(ModPlugFile* file) -{ - return ( file->mSoundFile.m_nMixChannels < file->mSoundFile.m_nMaxMixChannels ? file->mSoundFile.m_nMixChannels : file->mSoundFile.m_nMaxMixChannels ); -} - -void ModPlug_SeekOrder(ModPlugFile* file,int order) -{ - file->mSoundFile.SetCurrentOrder(order); -} - -int ModPlug_GetModuleType(ModPlugFile* file) -{ - return file->mSoundFile.m_nType; -} - -char* ModPlug_GetMessage(ModPlugFile* file) -{ - return file->mSoundFile.m_lpszSongComments; -} - -#ifndef MODPLUG_NO_FILESAVE -char ModPlug_ExportS3M(ModPlugFile* file,const char* filepath) -{ - return (char)file->mSoundFile.SaveS3M(filepath,0); -} - -char ModPlug_ExportXM(ModPlugFile* file,const char* filepath) -{ - return (char)file->mSoundFile.SaveXM(filepath,0); -} - -char ModPlug_ExportMOD(ModPlugFile* file,const char* filepath) -{ - return (char)file->mSoundFile.SaveMod(filepath,0); -} - -char ModPlug_ExportIT(ModPlugFile* file,const char* filepath) -{ - return (char)file->mSoundFile.SaveIT(filepath,0); -} -#endif // MODPLUG_NO_FILESAVE - -unsigned int ModPlug_NumInstruments(ModPlugFile* file) -{ - return file->mSoundFile.m_nInstruments; -} - -unsigned int ModPlug_NumSamples(ModPlugFile* file) -{ - return file->mSoundFile.m_nSamples; -} - -unsigned int ModPlug_NumPatterns(ModPlugFile* file) -{ - return file->mSoundFile.GetNumPatterns(); -} - -unsigned int ModPlug_NumChannels(ModPlugFile* file) -{ - return file->mSoundFile.GetNumChannels(); -} - -unsigned int ModPlug_SampleName(ModPlugFile* file,unsigned int qual,char* buff) -{ - return file->mSoundFile.GetSampleName(qual,buff); -} - -unsigned int ModPlug_InstrumentName(ModPlugFile* file,unsigned int qual,char* buff) -{ - return file->mSoundFile.GetInstrumentName(qual,buff); -} - -ModPlugNote* ModPlug_GetPattern(ModPlugFile* file,int pattern,unsigned int* numrows) { - if ( pattern<MAX_PATTERNS ) { - if (file->mSoundFile.Patterns[pattern]) { - if (numrows) *numrows=(unsigned int)file->mSoundFile.PatternSize[pattern]; - return (ModPlugNote*)file->mSoundFile.Patterns[pattern]; - } - } - return NULL; -} - -void ModPlug_Seek(ModPlugFile* file, int millisecond) -{ - int maxpos; - int maxtime = file->mSoundFile.GetSongTime() * 1000; - float postime; - - if(millisecond > maxtime) - millisecond = maxtime; - maxpos = file->mSoundFile.GetMaxPosition(); - postime = (float)maxpos / (float)maxtime; - - file->mSoundFile.SetCurrentPos((int)(millisecond * postime)); -} - -void ModPlug_GetSettings(ModPlug_Settings* settings) -{ - memcpy(settings, &ModPlug::gSettings, sizeof(ModPlug_Settings)); -} - -void ModPlug_SetSettings(const ModPlug_Settings* settings) -{ - memcpy(&ModPlug::gSettings, settings, sizeof(ModPlug_Settings)); - ModPlug::UpdateSettings(false); // do not update basic config. -} diff --git a/lib/libmodplug/src/modplug.h b/lib/libmodplug/src/modplug.h deleted file mode 100644 index 8e02ad8a86..0000000000 --- a/lib/libmodplug/src/modplug.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Kenton Varda <temporal@gauge3d.org> (C interface wrapper) - */ - -#ifndef MODPLUG_H__INCLUDED -#define MODPLUG_H__INCLUDED - -#ifdef __cplusplus -extern "C" { -#endif - -struct _ModPlugFile; -typedef struct _ModPlugFile ModPlugFile; - -struct _ModPlugNote { - unsigned char Note; - unsigned char Instrument; - unsigned char VolumeEffect; - unsigned char Effect; - unsigned char Volume; - unsigned char Parameter; -}; -typedef struct _ModPlugNote ModPlugNote; - -typedef void (*ModPlugMixerProc)(int*, unsigned long, unsigned long); - -/* Load a mod file. [data] should point to a block of memory containing the complete - * file, and [size] should be the size of that block. - * Return the loaded mod file on success, or NULL on failure. */ -ModPlugFile* ModPlug_Load(const void* data, int size); -/* Unload a mod file. */ -void ModPlug_Unload(ModPlugFile* file); - -/* Read sample data into the buffer. Returns the number of bytes read. If the end - * of the mod has been reached, zero is returned. */ -int ModPlug_Read(ModPlugFile* file, void* buffer, int size); - -/* Get the name of the mod. The returned buffer is stored within the ModPlugFile - * structure and will remain valid until you unload the file. */ -const char* ModPlug_GetName(ModPlugFile* file); - -/* Get the length of the mod, in milliseconds. Note that this result is not always - * accurate, especially in the case of mods with loops. */ -int ModPlug_GetLength(ModPlugFile* file); - -/* Seek to a particular position in the song. Note that seeking and MODs don't mix very - * well. Some mods will be missing instruments for a short time after a seek, as ModPlug - * does not scan the sequence backwards to find out which instruments were supposed to be - * playing at that time. (Doing so would be difficult and not very reliable.) Also, - * note that seeking is not very exact in some mods -- especially those for which - * ModPlug_GetLength() does not report the full length. */ -void ModPlug_Seek(ModPlugFile* file, int millisecond); - -enum _ModPlug_Flags -{ - MODPLUG_ENABLE_OVERSAMPLING = 1 << 0, /* Enable oversampling (*highly* recommended) */ - MODPLUG_ENABLE_NOISE_REDUCTION = 1 << 1, /* Enable noise reduction */ - MODPLUG_ENABLE_REVERB = 1 << 2, /* Enable reverb */ - MODPLUG_ENABLE_MEGABASS = 1 << 3, /* Enable megabass */ - MODPLUG_ENABLE_SURROUND = 1 << 4 /* Enable surround sound. */ -}; - -enum _ModPlug_ResamplingMode -{ - MODPLUG_RESAMPLE_NEAREST = 0, /* No interpolation (very fast, extremely bad sound quality) */ - MODPLUG_RESAMPLE_LINEAR = 1, /* Linear interpolation (fast, good quality) */ - MODPLUG_RESAMPLE_SPLINE = 2, /* Cubic spline interpolation (high quality) */ - MODPLUG_RESAMPLE_FIR = 3 /* 8-tap fir filter (extremely high quality) */ -}; - -typedef struct _ModPlug_Settings -{ - int mFlags; /* One or more of the MODPLUG_ENABLE_* flags above, bitwise-OR'ed */ - - /* Note that ModPlug always decodes sound at 44100kHz, 32 bit, stereo and then - * down-mixes to the settings you choose. */ - int mChannels; /* Number of channels - 1 for mono or 2 for stereo */ - int mBits; /* Bits per sample - 8, 16, or 32 */ - int mFrequency; /* Sampling rate - 11025, 22050, or 44100 */ - int mResamplingMode; /* One of MODPLUG_RESAMPLE_*, above */ - - int mReverbDepth; /* Reverb level 0(quiet)-100(loud) */ - int mReverbDelay; /* Reverb delay in ms, usually 40-200ms */ - int mBassAmount; /* XBass level 0(quiet)-100(loud) */ - int mBassRange; /* XBass cutoff in Hz 10-100 */ - int mSurroundDepth; /* Surround level 0(quiet)-100(heavy) */ - int mSurroundDelay; /* Surround delay in ms, usually 5-40ms */ - int mLoopCount; /* Number of times to loop. Zero prevents looping. - -1 loops forever. */ -} ModPlug_Settings; - -/* Get and set the mod decoder settings. All options, except for channels, bits-per-sample, - * sampling rate, and loop count, will take effect immediately. Those options which don't - * take effect immediately will take effect the next time you load a mod. */ -void ModPlug_GetSettings(ModPlug_Settings* settings); -void ModPlug_SetSettings(const ModPlug_Settings* settings); - -/* New ModPlug API Functions */ -/* NOTE: Master Volume (1-512) */ -unsigned int ModPlug_GetMasterVolume(ModPlugFile* file) ; -void ModPlug_SetMasterVolume(ModPlugFile* file,unsigned int cvol) ; - -int ModPlug_GetCurrentSpeed(ModPlugFile* file); -int ModPlug_GetCurrentTempo(ModPlugFile* file); -int ModPlug_GetCurrentOrder(ModPlugFile* file); -int ModPlug_GetCurrentPattern(ModPlugFile* file); -int ModPlug_GetCurrentRow(ModPlugFile* file); -int ModPlug_GetPlayingChannels(ModPlugFile* file); - -void ModPlug_SeekOrder(ModPlugFile* file,int order); -int ModPlug_GetModuleType(ModPlugFile* file); -char* ModPlug_GetMessage(ModPlugFile* file); - - -#ifndef MODPLUG_NO_FILESAVE -/* - * EXPERIMENTAL Export Functions - */ -/*Export to a Scream Tracker 3 S3M module. EXPERIMENTAL (only works on Little-Endian platforms)*/ -char ModPlug_ExportS3M(ModPlugFile* file, const char* filepath); - -/*Export to a Extended Module (XM). EXPERIMENTAL (only works on Little-Endian platforms)*/ -char ModPlug_ExportXM(ModPlugFile* file, const char* filepath); - -/*Export to a Amiga MOD file. EXPERIMENTAL.*/ -char ModPlug_ExportMOD(ModPlugFile* file, const char* filepath); - -/*Export to a Impulse Tracker IT file. Should work OK in Little-Endian & Big-Endian platforms :-) */ -char ModPlug_ExportIT(ModPlugFile* file, const char* filepath); -#endif // MODPLUG_NO_FILESAVE - -unsigned int ModPlug_NumInstruments(ModPlugFile* file); -unsigned int ModPlug_NumSamples(ModPlugFile* file); -unsigned int ModPlug_NumPatterns(ModPlugFile* file); -unsigned int ModPlug_NumChannels(ModPlugFile* file); -unsigned int ModPlug_SampleName(ModPlugFile* file, unsigned int qual, char* buff); -unsigned int ModPlug_InstrumentName(ModPlugFile* file, unsigned int qual, char* buff); - -/* - * Retrieve pattern note-data - */ -ModPlugNote* ModPlug_GetPattern(ModPlugFile* file, int pattern, unsigned int* numrows); - -/* - * ================= - * Mixer callback - * ================= - * - * Use this callback if you want to 'modify' the mixed data of LibModPlug. - * - * void proc(int* buffer,unsigned long channels,unsigned long nsamples) ; - * - * 'buffer': A buffer of mixed samples - * 'channels': N. of channels in the buffer - * 'nsamples': N. of samples in the buffeer (without taking care of n.channels) - * - * (Samples are signed 32-bit integers) - */ -void ModPlug_InitMixerCallback(ModPlugFile* file,ModPlugMixerProc proc) ; -void ModPlug_UnloadMixerCallback(ModPlugFile* file) ; - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif diff --git a/lib/libmodplug/src/snd_dsp.cpp b/lib/libmodplug/src/snd_dsp.cpp deleted file mode 100644 index ab5a30584a..0000000000 --- a/lib/libmodplug/src/snd_dsp.cpp +++ /dev/null @@ -1,485 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque <olivierl@jps.net> -*/ - -#include "stdafx.h" -#include "sndfile.h" - -#ifdef MODPLUG_FASTSOUNDLIB -#define MODPLUG_NO_REVERB -#endif - - -// Delayed Surround Filters -#ifndef MODPLUG_FASTSOUNDLIB -#define nDolbyHiFltAttn 6 -#define nDolbyHiFltMask 3 -#define DOLBYATTNROUNDUP 31 -#else -#define nDolbyHiFltAttn 3 -#define nDolbyHiFltMask 3 -#define DOLBYATTNROUNDUP 3 -#endif - -// Bass Expansion -#define XBASS_DELAY 14 // 2.5 ms - -// Buffer Sizes -#define XBASSBUFFERSIZE 64 // 2 ms at 50KHz -#define FILTERBUFFERSIZE 64 // 1.25 ms -#define SURROUNDBUFFERSIZE ((MAX_SAMPLE_RATE * 50) / 1000) -#define REVERBBUFFERSIZE ((MAX_SAMPLE_RATE * 200) / 1000) -#define REVERBBUFFERSIZE2 ((REVERBBUFFERSIZE*13) / 17) -#define REVERBBUFFERSIZE3 ((REVERBBUFFERSIZE*7) / 13) -#define REVERBBUFFERSIZE4 ((REVERBBUFFERSIZE*7) / 19) - - -// DSP Effects: PUBLIC members -UINT CSoundFile::m_nXBassDepth = 6; -UINT CSoundFile::m_nXBassRange = XBASS_DELAY; -UINT CSoundFile::m_nReverbDepth = 1; -UINT CSoundFile::m_nReverbDelay = 100; -UINT CSoundFile::m_nProLogicDepth = 12; -UINT CSoundFile::m_nProLogicDelay = 20; - -//////////////////////////////////////////////////////////////////// -// DSP Effects internal state - -// Bass Expansion: low-pass filter -static LONG nXBassSum = 0; -static LONG nXBassBufferPos = 0; -static LONG nXBassDlyPos = 0; -static LONG nXBassMask = 0; - -// Noise Reduction: simple low-pass filter -static LONG nLeftNR = 0; -static LONG nRightNR = 0; - -// Surround Encoding: 1 delay line + low-pass filter + high-pass filter -static LONG nSurroundSize = 0; -static LONG nSurroundPos = 0; -static LONG nDolbyDepth = 0; -static LONG nDolbyLoDlyPos = 0; -static LONG nDolbyLoFltPos = 0; -static LONG nDolbyLoFltSum = 0; -static LONG nDolbyHiFltPos = 0; -static LONG nDolbyHiFltSum = 0; - -// Reverb: 4 delay lines + high-pass filter + low-pass filter -#ifndef MODPLUG_NO_REVERB -static LONG nReverbSize = 0; -static LONG nReverbBufferPos = 0; -static LONG nReverbSize2 = 0; -static LONG nReverbBufferPos2 = 0; -static LONG nReverbSize3 = 0; -static LONG nReverbBufferPos3 = 0; -static LONG nReverbSize4 = 0; -static LONG nReverbBufferPos4 = 0; -static LONG nReverbLoFltSum = 0; -static LONG nReverbLoFltPos = 0; -static LONG nReverbLoDlyPos = 0; -static LONG nFilterAttn = 0; -static LONG gRvbLowPass[8]; -static LONG gRvbLPPos = 0; -static LONG gRvbLPSum = 0; -static LONG ReverbLoFilterBuffer[XBASSBUFFERSIZE]; -static LONG ReverbLoFilterDelay[XBASSBUFFERSIZE]; -static LONG ReverbBuffer[REVERBBUFFERSIZE]; -static LONG ReverbBuffer2[REVERBBUFFERSIZE2]; -static LONG ReverbBuffer3[REVERBBUFFERSIZE3]; -static LONG ReverbBuffer4[REVERBBUFFERSIZE4]; -#endif -static LONG XBassBuffer[XBASSBUFFERSIZE]; -static LONG XBassDelay[XBASSBUFFERSIZE]; -static LONG DolbyLoFilterBuffer[XBASSBUFFERSIZE]; -static LONG DolbyLoFilterDelay[XBASSBUFFERSIZE]; -static LONG DolbyHiFilterBuffer[FILTERBUFFERSIZE]; -static LONG SurroundBuffer[SURROUNDBUFFERSIZE]; - -// Access the main temporary mix buffer directly: avoids an extra pointer -extern int MixSoundBuffer[MIXBUFFERSIZE*2]; -//cextern int MixReverbBuffer[MIXBUFFERSIZE*2]; -extern int MixReverbBuffer[MIXBUFFERSIZE*2]; - -static UINT GetMaskFromSize(UINT len) -//----------------------------------- -{ - UINT n = 2; - while (n <= len) n <<= 1; - return ((n >> 1) - 1); -} - - -void CSoundFile::InitializeDSP(BOOL bReset) -//----------------------------------------- -{ - if (!m_nReverbDelay) m_nReverbDelay = 100; - if (!m_nXBassRange) m_nXBassRange = XBASS_DELAY; - if (!m_nProLogicDelay) m_nProLogicDelay = 20; - if (m_nXBassDepth > 8) m_nXBassDepth = 8; - if (m_nXBassDepth < 2) m_nXBassDepth = 2; - if (bReset) - { - // Noise Reduction - nLeftNR = nRightNR = 0; - } - // Pro-Logic Surround - nSurroundPos = nSurroundSize = 0; - nDolbyLoFltPos = nDolbyLoFltSum = nDolbyLoDlyPos = 0; - nDolbyHiFltPos = nDolbyHiFltSum = 0; - if (gdwSoundSetup & SNDMIX_SURROUND) - { - memset(DolbyLoFilterBuffer, 0, sizeof(DolbyLoFilterBuffer)); - memset(DolbyHiFilterBuffer, 0, sizeof(DolbyHiFilterBuffer)); - memset(DolbyLoFilterDelay, 0, sizeof(DolbyLoFilterDelay)); - memset(SurroundBuffer, 0, sizeof(SurroundBuffer)); - nSurroundSize = (gdwMixingFreq * m_nProLogicDelay) / 1000; - if (nSurroundSize > SURROUNDBUFFERSIZE) nSurroundSize = SURROUNDBUFFERSIZE; - if (m_nProLogicDepth < 8) nDolbyDepth = (32 >> m_nProLogicDepth) + 32; - else nDolbyDepth = (m_nProLogicDepth < 16) ? (8 + (m_nProLogicDepth - 8) * 7) : 64; - nDolbyDepth >>= 2; - } - // Reverb Setup -#ifndef MODPLUG_NO_REVERB - if (gdwSoundSetup & SNDMIX_REVERB) - { - UINT nrs = (gdwMixingFreq * m_nReverbDelay) / 1000; - UINT nfa = m_nReverbDepth+1; - if (nrs > REVERBBUFFERSIZE) nrs = REVERBBUFFERSIZE; - if ((bReset) || (nrs != (UINT)nReverbSize) || (nfa != (UINT)nFilterAttn)) - { - nFilterAttn = nfa; - nReverbSize = nrs; - nReverbBufferPos = nReverbBufferPos2 = nReverbBufferPos3 = nReverbBufferPos4 = 0; - nReverbLoFltSum = nReverbLoFltPos = nReverbLoDlyPos = 0; - gRvbLPSum = gRvbLPPos = 0; - nReverbSize2 = (nReverbSize * 13) / 17; - if (nReverbSize2 > REVERBBUFFERSIZE2) nReverbSize2 = REVERBBUFFERSIZE2; - nReverbSize3 = (nReverbSize * 7) / 13; - if (nReverbSize3 > REVERBBUFFERSIZE3) nReverbSize3 = REVERBBUFFERSIZE3; - nReverbSize4 = (nReverbSize * 7) / 19; - if (nReverbSize4 > REVERBBUFFERSIZE4) nReverbSize4 = REVERBBUFFERSIZE4; - memset(ReverbLoFilterBuffer, 0, sizeof(ReverbLoFilterBuffer)); - memset(ReverbLoFilterDelay, 0, sizeof(ReverbLoFilterDelay)); - memset(ReverbBuffer, 0, sizeof(ReverbBuffer)); - memset(ReverbBuffer2, 0, sizeof(ReverbBuffer2)); - memset(ReverbBuffer3, 0, sizeof(ReverbBuffer3)); - memset(ReverbBuffer4, 0, sizeof(ReverbBuffer4)); - memset(gRvbLowPass, 0, sizeof(gRvbLowPass)); - } - } else nReverbSize = 0; -#endif - BOOL bResetBass = FALSE; - // Bass Expansion Reset - if (gdwSoundSetup & SNDMIX_MEGABASS) - { - UINT nXBassSamples = (gdwMixingFreq * m_nXBassRange) / 10000; - if (nXBassSamples > XBASSBUFFERSIZE) nXBassSamples = XBASSBUFFERSIZE; - UINT mask = GetMaskFromSize(nXBassSamples); - if ((bReset) || (mask != (UINT)nXBassMask)) - { - nXBassMask = mask; - bResetBass = TRUE; - } - } else - { - nXBassMask = 0; - bResetBass = TRUE; - } - if (bResetBass) - { - nXBassSum = nXBassBufferPos = nXBassDlyPos = 0; - memset(XBassBuffer, 0, sizeof(XBassBuffer)); - memset(XBassDelay, 0, sizeof(XBassDelay)); - } -} - - -void CSoundFile::ProcessStereoDSP(int count) -//------------------------------------------ -{ -#ifndef MODPLUG_NO_REVERB - // Reverb - if (gdwSoundSetup & SNDMIX_REVERB) - { - int *pr = MixSoundBuffer, *pin = MixReverbBuffer, rvbcount = count; - do - { - int echo = ReverbBuffer[nReverbBufferPos] + ReverbBuffer2[nReverbBufferPos2] - + ReverbBuffer3[nReverbBufferPos3] + ReverbBuffer4[nReverbBufferPos4]; // echo = reverb signal - // Delay line and remove Low Frequencies // v = original signal - int echodly = ReverbLoFilterDelay[nReverbLoDlyPos]; // echodly = delayed signal - ReverbLoFilterDelay[nReverbLoDlyPos] = echo >> 1; - nReverbLoDlyPos++; - nReverbLoDlyPos &= 0x1F; - int n = nReverbLoFltPos; - nReverbLoFltSum -= ReverbLoFilterBuffer[n]; - int tmp = echo / 128; - ReverbLoFilterBuffer[n] = tmp; - nReverbLoFltSum += tmp; - echodly -= nReverbLoFltSum; - nReverbLoFltPos = (n + 1) & 0x3F; - // Reverb - int v = (pin[0]+pin[1]) >> nFilterAttn; - pr[0] += pin[0] + echodly; - pr[1] += pin[1] + echodly; - v += echodly >> 2; - ReverbBuffer3[nReverbBufferPos3] = v; - ReverbBuffer4[nReverbBufferPos4] = v; - v += echodly >> 4; - v >>= 1; - gRvbLPSum -= gRvbLowPass[gRvbLPPos]; - gRvbLPSum += v; - gRvbLowPass[gRvbLPPos] = v; - gRvbLPPos++; - gRvbLPPos &= 7; - int vlp = gRvbLPSum >> 2; - ReverbBuffer[nReverbBufferPos] = vlp; - ReverbBuffer2[nReverbBufferPos2] = vlp; - if (++nReverbBufferPos >= nReverbSize) nReverbBufferPos = 0; - if (++nReverbBufferPos2 >= nReverbSize2) nReverbBufferPos2 = 0; - if (++nReverbBufferPos3 >= nReverbSize3) nReverbBufferPos3 = 0; - if (++nReverbBufferPos4 >= nReverbSize4) nReverbBufferPos4 = 0; - pr += 2; - pin += 2; - } while (--rvbcount); - } -#endif - // Dolby Pro-Logic Surround - if (gdwSoundSetup & SNDMIX_SURROUND) - { - int *pr = MixSoundBuffer, n = nDolbyLoFltPos; - for (int r=count; r; r--) - { - int v = (pr[0]+pr[1]+DOLBYATTNROUNDUP) >> (nDolbyHiFltAttn+1); -#ifndef MODPLUG_FASTSOUNDLIB - v *= (int)nDolbyDepth; -#endif - // Low-Pass Filter - nDolbyHiFltSum -= DolbyHiFilterBuffer[nDolbyHiFltPos]; - DolbyHiFilterBuffer[nDolbyHiFltPos] = v; - nDolbyHiFltSum += v; - v = nDolbyHiFltSum; - nDolbyHiFltPos++; - nDolbyHiFltPos &= nDolbyHiFltMask; - // Surround - int secho = SurroundBuffer[nSurroundPos]; - SurroundBuffer[nSurroundPos] = v; - // Delay line and remove low frequencies - v = DolbyLoFilterDelay[nDolbyLoDlyPos]; // v = delayed signal - DolbyLoFilterDelay[nDolbyLoDlyPos] = secho; // secho = signal - nDolbyLoDlyPos++; - nDolbyLoDlyPos &= 0x1F; - nDolbyLoFltSum -= DolbyLoFilterBuffer[n]; - int tmp = secho / 64; - DolbyLoFilterBuffer[n] = tmp; - nDolbyLoFltSum += tmp; - v -= nDolbyLoFltSum; - n++; - n &= 0x3F; - // Add echo - pr[0] += v; - pr[1] -= v; - if (++nSurroundPos >= nSurroundSize) nSurroundPos = 0; - pr += 2; - } - nDolbyLoFltPos = n; - } - // Bass Expansion - if (gdwSoundSetup & SNDMIX_MEGABASS) - { - int *px = MixSoundBuffer; - int xba = m_nXBassDepth+1, xbamask = (1 << xba) - 1; - int n = nXBassBufferPos; - for (int x=count; x; x--) - { - nXBassSum -= XBassBuffer[n]; - int tmp0 = px[0] + px[1]; - int tmp = (tmp0 + ((tmp0 >> 31) & xbamask)) >> xba; - XBassBuffer[n] = tmp; - nXBassSum += tmp; - int v = XBassDelay[nXBassDlyPos]; - XBassDelay[nXBassDlyPos] = px[0]; - px[0] = v + nXBassSum; - v = XBassDelay[nXBassDlyPos+1]; - XBassDelay[nXBassDlyPos+1] = px[1]; - px[1] = v + nXBassSum; - nXBassDlyPos = (nXBassDlyPos + 2) & nXBassMask; - px += 2; - n++; - n &= nXBassMask; - } - nXBassBufferPos = n; - } - // Noise Reduction - if (gdwSoundSetup & SNDMIX_NOISEREDUCTION) - { - int n1 = nLeftNR, n2 = nRightNR; - int *pnr = MixSoundBuffer; - for (int nr=count; nr; nr--) - { - int vnr = pnr[0] >> 1; - pnr[0] = vnr + n1; - n1 = vnr; - vnr = pnr[1] >> 1; - pnr[1] = vnr + n2; - n2 = vnr; - pnr += 2; - } - nLeftNR = n1; - nRightNR = n2; - } -} - - -void CSoundFile::ProcessMonoDSP(int count) -//---------------------------------------- -{ -#ifndef MODPLUG_NO_REVERB - // Reverb - if (gdwSoundSetup & SNDMIX_REVERB) - { - int *pr = MixSoundBuffer, rvbcount = count, *pin = MixReverbBuffer; - do - { - int echo = ReverbBuffer[nReverbBufferPos] + ReverbBuffer2[nReverbBufferPos2] - + ReverbBuffer3[nReverbBufferPos3] + ReverbBuffer4[nReverbBufferPos4]; // echo = reverb signal - // Delay line and remove Low Frequencies // v = original signal - int echodly = ReverbLoFilterDelay[nReverbLoDlyPos]; // echodly = delayed signal - ReverbLoFilterDelay[nReverbLoDlyPos] = echo >> 1; - nReverbLoDlyPos++; - nReverbLoDlyPos &= 0x1F; - int n = nReverbLoFltPos; - nReverbLoFltSum -= ReverbLoFilterBuffer[n]; - int tmp = echo / 128; - ReverbLoFilterBuffer[n] = tmp; - nReverbLoFltSum += tmp; - echodly -= nReverbLoFltSum; - nReverbLoFltPos = (n + 1) & 0x3F; - // Reverb - int v = pin[0] >> (nFilterAttn-1); - *pr++ += pin[0] + echodly; - pin++; - v += echodly >> 2; - ReverbBuffer3[nReverbBufferPos3] = v; - ReverbBuffer4[nReverbBufferPos4] = v; - v += echodly >> 4; - v >>= 1; - gRvbLPSum -= gRvbLowPass[gRvbLPPos]; - gRvbLPSum += v; - gRvbLowPass[gRvbLPPos] = v; - gRvbLPPos++; - gRvbLPPos &= 7; - int vlp = gRvbLPSum >> 2; - ReverbBuffer[nReverbBufferPos] = vlp; - ReverbBuffer2[nReverbBufferPos2] = vlp; - if (++nReverbBufferPos >= nReverbSize) nReverbBufferPos = 0; - if (++nReverbBufferPos2 >= nReverbSize2) nReverbBufferPos2 = 0; - if (++nReverbBufferPos3 >= nReverbSize3) nReverbBufferPos3 = 0; - if (++nReverbBufferPos4 >= nReverbSize4) nReverbBufferPos4 = 0; - } while (--rvbcount); - } -#endif - // Bass Expansion - if (gdwSoundSetup & SNDMIX_MEGABASS) - { - int *px = MixSoundBuffer; - int xba = m_nXBassDepth, xbamask = (1 << xba)-1; - int n = nXBassBufferPos; - for (int x=count; x; x--) - { - nXBassSum -= XBassBuffer[n]; - int tmp0 = *px; - int tmp = (tmp0 + ((tmp0 >> 31) & xbamask)) >> xba; - XBassBuffer[n] = tmp; - nXBassSum += tmp; - int v = XBassDelay[nXBassDlyPos]; - XBassDelay[nXBassDlyPos] = *px; - *px++ = v + nXBassSum; - nXBassDlyPos = (nXBassDlyPos + 2) & nXBassMask; - n++; - n &= nXBassMask; - } - nXBassBufferPos = n; - } - // Noise Reduction - if (gdwSoundSetup & SNDMIX_NOISEREDUCTION) - { - int n = nLeftNR; - int *pnr = MixSoundBuffer; - for (int nr=count; nr; pnr++, nr--) - { - int vnr = *pnr >> 1; - *pnr = vnr + n; - n = vnr; - } - nLeftNR = n; - } -} - - -///////////////////////////////////////////////////////////////// -// Clean DSP Effects interface - -// [Reverb level 0(quiet)-100(loud)], [delay in ms, usually 40-200ms] -BOOL CSoundFile::SetReverbParameters(UINT nDepth, UINT nDelay) -//------------------------------------------------------------ -{ - if (nDepth > 100) nDepth = 100; - UINT gain = nDepth / 20; - if (gain > 4) gain = 4; - m_nReverbDepth = 4 - gain; - if (nDelay < 40) nDelay = 40; - if (nDelay > 250) nDelay = 250; - m_nReverbDelay = nDelay; - return TRUE; -} - - -// [XBass level 0(quiet)-100(loud)], [cutoff in Hz 20-100] -BOOL CSoundFile::SetXBassParameters(UINT nDepth, UINT nRange) -//----------------------------------------------------------- -{ - if (nDepth > 100) nDepth = 100; - UINT gain = nDepth / 20; - if (gain > 4) gain = 4; - m_nXBassDepth = 8 - gain; // filter attenuation 1/256 .. 1/16 - UINT range = nRange / 5; - if (range > 5) range -= 5; else range = 0; - if (nRange > 16) nRange = 16; - m_nXBassRange = 21 - range; // filter average on 0.5-1.6ms - return TRUE; -} - - -// [Surround level 0(quiet)-100(heavy)] [delay in ms, usually 5-50ms] -BOOL CSoundFile::SetSurroundParameters(UINT nDepth, UINT nDelay) -//-------------------------------------------------------------- -{ - UINT gain = (nDepth * 16) / 100; - if (gain > 16) gain = 16; - if (gain < 1) gain = 1; - m_nProLogicDepth = gain; - if (nDelay < 4) nDelay = 4; - if (nDelay > 50) nDelay = 50; - m_nProLogicDelay = nDelay; - return TRUE; -} - -BOOL CSoundFile::SetWaveConfigEx(BOOL bSurround,BOOL bNoOverSampling,BOOL bReverb,BOOL hqido,BOOL bMegaBass,BOOL bNR,BOOL bEQ) -//---------------------------------------------------------------------------------------------------------------------------- -{ - DWORD d = gdwSoundSetup & ~(SNDMIX_SURROUND | SNDMIX_NORESAMPLING | SNDMIX_REVERB | SNDMIX_HQRESAMPLER | SNDMIX_MEGABASS | SNDMIX_NOISEREDUCTION | SNDMIX_EQ); - if (bSurround) d |= SNDMIX_SURROUND; - if (bNoOverSampling) d |= SNDMIX_NORESAMPLING; - if (bReverb) d |= SNDMIX_REVERB; - if (hqido) d |= SNDMIX_HQRESAMPLER; - if (bMegaBass) d |= SNDMIX_MEGABASS; - if (bNR) d |= SNDMIX_NOISEREDUCTION; - if (bEQ) d |= SNDMIX_EQ; - gdwSoundSetup = d; - InitPlayer(FALSE); - return TRUE; -} diff --git a/lib/libmodplug/src/snd_flt.cpp b/lib/libmodplug/src/snd_flt.cpp deleted file mode 100644 index f8a573cbe6..0000000000 --- a/lib/libmodplug/src/snd_flt.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque <olivierl@jps.net> -*/ - -#include "stdafx.h" -#include "sndfile.h" - -// AWE32: cutoff = reg[0-255] * 31.25 + 100 -> [100Hz-8060Hz] -// EMU10K1 docs: cutoff = reg[0-127]*62+100 -#define FILTER_PRECISION 8192 - -#ifndef NO_FILTER - -#ifdef MSC_VER -#define _ASM_MATH -#endif - -#ifdef _ASM_MATH - -// pow(a,b) returns a^^b -> 2^^(b.log2(a)) -static float pow(float a, float b) -{ - long tmpint; - float result; - _asm { - fld b // Load b - fld a // Load a - fyl2x // ST(0) = b.log2(a) - fist tmpint // Store integer exponent - fisub tmpint // ST(0) = -1 <= (b*log2(a)) <= 1 - f2xm1 // ST(0) = 2^(x)-1 - fild tmpint // load integer exponent - fld1 // Load 1 - fscale // ST(0) = 2^ST(1) - fstp ST(1) // Remove the integer from the stack - fmul ST(1), ST(0) // multiply with fractional part - faddp ST(1), ST(0) // add integer_part - fstp result // Store the result - } - return result; -} - - -#else - -#include <math.h> - -#endif // _ASM_MATH - - -DWORD CSoundFile::CutOffToFrequency(UINT nCutOff, int flt_modifier) const -//----------------------------------------------------------------------- -{ - float Fc; - - if (m_dwSongFlags & SONG_EXFILTERRANGE) - Fc = 110.0f * pow(2.0f, 0.25f + ((float)(nCutOff*(flt_modifier+256)))/(21.0f*512.0f)); - else - Fc = 110.0f * pow(2.0f, 0.25f + ((float)(nCutOff*(flt_modifier+256)))/(24.0f*512.0f)); - LONG freq = (LONG)Fc; - if (freq < 120) return 120; - if (freq > 10000) return 10000; - if (freq*2 > (LONG)gdwMixingFreq) freq = gdwMixingFreq>>1; - return (DWORD)freq; -} - - -// Simple 2-poles resonant filter -void CSoundFile::SetupChannelFilter(MODCHANNEL *pChn, BOOL bReset, int flt_modifier) const -//---------------------------------------------------------------------------------------- -{ - float fc = (float)CutOffToFrequency(pChn->nCutOff, flt_modifier); - float fs = (float)gdwMixingFreq; - float fg, fb0, fb1; - - fc *= (float)(2.0*3.14159265358/fs); - float dmpfac = pow(10.0f, -((24.0f / 128.0f)*(float)pChn->nResonance) / 20.0f); - float d = (1.0f-2.0f*dmpfac)* fc; - if (d>2.0) d = 2.0; - d = (2.0f*dmpfac - d)/fc; - float e = pow(1.0f/fc,2.0f); - - fg=1/(1+d+e); - fb0=(d+e+e)/(1+d+e); - fb1=-e/(1+d+e); - - pChn->nFilter_A0 = (int)(fg * FILTER_PRECISION); - pChn->nFilter_B0 = (int)(fb0 * FILTER_PRECISION); - pChn->nFilter_B1 = (int)(fb1 * FILTER_PRECISION); - - if (bReset) - { - pChn->nFilter_Y1 = pChn->nFilter_Y2 = 0; - pChn->nFilter_Y3 = pChn->nFilter_Y4 = 0; - } - pChn->dwFlags |= CHN_FILTER; -} - -#endif // NO_FILTER diff --git a/lib/libmodplug/src/snd_fx.cpp b/lib/libmodplug/src/snd_fx.cpp deleted file mode 100644 index dcc875d292..0000000000 --- a/lib/libmodplug/src/snd_fx.cpp +++ /dev/null @@ -1,2379 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque <olivierl@jps.net> -*/ - -#include "stdafx.h" -#include "sndfile.h" -#include "tables.h" -#include <stdlib.h> - -#ifdef MSC_VER -#pragma warning(disable:4244) -#endif - -//////////////////////////////////////////////////////////// -// Length - -DWORD CSoundFile::GetLength(BOOL bAdjust, BOOL bTotal) -//---------------------------------------------------- -{ - UINT dwElapsedTime=0, nRow=0, nCurrentPattern=0, nNextPattern=0, nPattern=Order[0]; - UINT nMusicSpeed=m_nDefaultSpeed, nMusicTempo=m_nDefaultTempo, nNextRow=0; - UINT nMaxRow = 0, nMaxPattern = 0; - LONG nGlbVol = m_nDefaultGlobalVolume, nOldGlbVolSlide = 0; - BYTE samples[MAX_CHANNELS]; - BYTE instr[MAX_CHANNELS]; - BYTE notes[MAX_CHANNELS]; - BYTE vols[MAX_CHANNELS]; - BYTE oldparam[MAX_CHANNELS]; - BYTE chnvols[MAX_CHANNELS]; - DWORD patloop[MAX_CHANNELS]; - - memset(instr, 0, sizeof(instr)); - memset(notes, 0, sizeof(notes)); - memset(vols, 0xFF, sizeof(vols)); - memset(patloop, 0, sizeof(patloop)); - memset(oldparam, 0, sizeof(oldparam)); - memset(chnvols, 64, sizeof(chnvols)); - memset(samples, 0, sizeof(samples)); - for (UINT icv=0; icv<m_nChannels; icv++) chnvols[icv] = ChnSettings[icv].nVolume; - nMaxRow = m_nNextRow; - nMaxPattern = m_nNextPattern; - nCurrentPattern = nNextPattern = 0; - nPattern = Order[0]; - nRow = nNextRow = 0; - for (;;) - { - UINT nSpeedCount = 0; - nRow = nNextRow; - nCurrentPattern = nNextPattern; - // Check if pattern is valid - nPattern = Order[nCurrentPattern]; - while (nPattern >= MAX_PATTERNS) - { - // End of song ? - if ((nPattern == 0xFF) || (nCurrentPattern >= MAX_ORDERS)) - { - goto EndMod; - } else - { - nCurrentPattern++; - nPattern = (nCurrentPattern < MAX_ORDERS) ? Order[nCurrentPattern] : 0xFF; - } - nNextPattern = nCurrentPattern; - } - // Weird stuff? - if ((nPattern >= MAX_PATTERNS) || (!Patterns[nPattern])) break; - // Should never happen - if (nRow >= PatternSize[nPattern]) nRow = 0; - // Update next position - nNextRow = nRow + 1; - if (nNextRow >= PatternSize[nPattern]) - { - nNextPattern = nCurrentPattern + 1; - nNextRow = 0; - } - if (!nRow) - { - for (UINT ipck=0; ipck<m_nChannels; ipck++) patloop[ipck] = dwElapsedTime; - } - if (!bTotal) - { - if ((nCurrentPattern > nMaxPattern) || ((nCurrentPattern == nMaxPattern) && (nRow >= nMaxRow))) - { - if (bAdjust) - { - m_nMusicSpeed = nMusicSpeed; - m_nMusicTempo = nMusicTempo; - } - break; - } - } - MODCHANNEL *pChn = Chn; - MODCOMMAND *p = Patterns[nPattern] + nRow * m_nChannels; - for (UINT nChn=0; nChn<m_nChannels; p++,pChn++, nChn++) if (*((DWORD *)p)) - { - UINT command = p->command; - UINT param = p->param; - UINT note = p->note; - if (p->instr) { instr[nChn] = p->instr; notes[nChn] = 0; vols[nChn] = 0xFF; } - if ((note) && (note <= NOTE_MAX)) notes[nChn] = note; - if (p->volcmd == VOLCMD_VOLUME) { vols[nChn] = p->vol; } - if (command) switch (command) - { - // Position Jump - case CMD_POSITIONJUMP: - if (param <= nCurrentPattern) goto EndMod; - nNextPattern = param; - nNextRow = 0; - if (bAdjust) - { - pChn->nPatternLoopCount = 0; - pChn->nPatternLoop = 0; - } - break; - // Pattern Break - case CMD_PATTERNBREAK: - nNextRow = param; - nNextPattern = nCurrentPattern + 1; - if (bAdjust) - { - pChn->nPatternLoopCount = 0; - pChn->nPatternLoop = 0; - } - break; - // Set Speed - case CMD_SPEED: - if (!param) break; - if ((param <= 0x20) || (m_nType != MOD_TYPE_MOD)) - { - if (param < 128) nMusicSpeed = param; - } - break; - // Set Tempo - case CMD_TEMPO: - if ((bAdjust) && (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT))) - { - if (param) pChn->nOldTempo = param; else param = pChn->nOldTempo; - } - if (param >= 0x20) nMusicTempo = param; else - // Tempo Slide - if ((param & 0xF0) == 0x10) - { - nMusicTempo += param & 0x0F; - if (nMusicTempo > 255) nMusicTempo = 255; - } else - { - nMusicTempo -= param & 0x0F; - if (nMusicTempo < 32) nMusicTempo = 32; - } - break; - // Pattern Delay - case CMD_S3MCMDEX: - if ((param & 0xF0) == 0x60) { nSpeedCount = param & 0x0F; break; } else - if ((param & 0xF0) == 0xB0) { param &= 0x0F; param |= 0x60; } - case CMD_MODCMDEX: - if ((param & 0xF0) == 0xE0) nSpeedCount = (param & 0x0F) * nMusicSpeed; else - if ((param & 0xF0) == 0x60) - { - if (param & 0x0F) dwElapsedTime += (dwElapsedTime - patloop[nChn]) * (param & 0x0F); - else patloop[nChn] = dwElapsedTime; - } - break; - } - if (!bAdjust) continue; - switch(command) - { - // Portamento Up/Down - case CMD_PORTAMENTOUP: - case CMD_PORTAMENTODOWN: - if (param) pChn->nOldPortaUpDown = param; - break; - // Tone-Portamento - case CMD_TONEPORTAMENTO: - if (param) pChn->nPortamentoSlide = param << 2; - break; - // Offset - case CMD_OFFSET: - if (param) pChn->nOldOffset = param; - break; - // Volume Slide - case CMD_VOLUMESLIDE: - case CMD_TONEPORTAVOL: - case CMD_VIBRATOVOL: - if (param) pChn->nOldVolumeSlide = param; - break; - // Set Volume - case CMD_VOLUME: - vols[nChn] = param; - break; - // Global Volume - case CMD_GLOBALVOLUME: - if (!(m_nType & (MOD_TYPE_IT))) param <<= 1; - if (param > 128) param = 128; - nGlbVol = param << 1; - break; - // Global Volume Slide - case CMD_GLOBALVOLSLIDE: - if (param) nOldGlbVolSlide = param; else param = nOldGlbVolSlide; - if (((param & 0x0F) == 0x0F) && (param & 0xF0)) - { - param >>= 4; - if (m_nType != MOD_TYPE_IT) param <<= 1; - nGlbVol += param << 1; - } else - if (((param & 0xF0) == 0xF0) && (param & 0x0F)) - { - param = (param & 0x0F) << 1; - if (m_nType != MOD_TYPE_IT) param <<= 1; - nGlbVol -= param; - } else - if (param & 0xF0) - { - param >>= 4; - param <<= 1; - if (m_nType != MOD_TYPE_IT) param <<= 1; - nGlbVol += param * nMusicSpeed; - } else - { - param = (param & 0x0F) << 1; - if (m_nType != MOD_TYPE_IT) param <<= 1; - nGlbVol -= param * nMusicSpeed; - } - if (nGlbVol < 0) nGlbVol = 0; - if (nGlbVol > 256) nGlbVol = 256; - break; - case CMD_CHANNELVOLUME: - if (param <= 64) chnvols[nChn] = param; - break; - case CMD_CHANNELVOLSLIDE: - if (param) oldparam[nChn] = param; else param = oldparam[nChn]; - pChn->nOldChnVolSlide = param; - if (((param & 0x0F) == 0x0F) && (param & 0xF0)) - { - param = (param >> 4) + chnvols[nChn]; - } else - if (((param & 0xF0) == 0xF0) && (param & 0x0F)) - { - if (chnvols[nChn] > (int)(param & 0x0F)) param = chnvols[nChn] - (param & 0x0F); - else param = 0; - } else - if (param & 0x0F) - { - param = (param & 0x0F) * nMusicSpeed; - param = (chnvols[nChn] > param) ? chnvols[nChn] - param : 0; - } else param = ((param & 0xF0) >> 4) * nMusicSpeed + chnvols[nChn]; - if (param > 64) param = 64; - chnvols[nChn] = param; - break; - } - } - nSpeedCount += nMusicSpeed; - dwElapsedTime += (2500 * nSpeedCount) / nMusicTempo; - } -EndMod: - if ((bAdjust) && (!bTotal)) - { - m_nGlobalVolume = nGlbVol; - m_nOldGlbVolSlide = nOldGlbVolSlide; - for (UINT n=0; n<m_nChannels; n++) - { - Chn[n].nGlobalVol = chnvols[n]; - if (notes[n]) Chn[n].nNewNote = notes[n]; - if (instr[n]) Chn[n].nNewIns = instr[n]; - if (vols[n] != 0xFF) - { - if (vols[n] > 64) vols[n] = 64; - Chn[n].nVolume = vols[n] << 2; - } - } - } - return (dwElapsedTime+500) / 1000; -} - - -////////////////////////////////////////////////////////////////////////////////////////////////// -// Effects - -void CSoundFile::InstrumentChange(MODCHANNEL *pChn, UINT instr, BOOL bPorta, BOOL bUpdVol, BOOL bResetEnv) -//-------------------------------------------------------------------------------------------------------- -{ - BOOL bInstrumentChanged = FALSE; - - if (instr >= MAX_INSTRUMENTS) return; - INSTRUMENTHEADER *penv = Headers[instr]; - MODINSTRUMENT *psmp = &Ins[instr]; - UINT note = pChn->nNewNote; - if ((penv) && (note) && (note <= 128)) - { - if (penv->NoteMap[note-1] >= 0xFE) return; - UINT n = penv->Keyboard[note-1]; - psmp = ((n) && (n < MAX_SAMPLES)) ? &Ins[n] : NULL; - } else - if (m_nInstruments) - { - if (note >= 0xFE) return; - psmp = NULL; - } - // Update Volume - if (bUpdVol) pChn->nVolume = (psmp) ? psmp->nVolume : 0; - // bInstrumentChanged is used for IT carry-on env option - if (penv != pChn->pHeader) - { - bInstrumentChanged = TRUE; - pChn->pHeader = penv; - } else - { - // Special XM hack - if ((bPorta) && (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) && (penv) - && (pChn->pInstrument) && (psmp != pChn->pInstrument)) - { - // FT2 doesn't change the sample in this case, - // but still uses the sample info from the old one (bug?) - return; - } - } - // Instrument adjust - pChn->nNewIns = 0; - if (psmp) - { - if (penv) - { - pChn->nInsVol = (psmp->nGlobalVol * penv->nGlobalVol) >> 6; - if (penv->dwFlags & ENV_SETPANNING) pChn->nPan = penv->nPan; - pChn->nNNA = penv->nNNA; - } else - { - pChn->nInsVol = psmp->nGlobalVol; - } - if (psmp->uFlags & CHN_PANNING) pChn->nPan = psmp->nPan; - } - // Reset envelopes - if (bResetEnv) - { - if ((!bPorta) || (!(m_nType & MOD_TYPE_IT)) || (m_dwSongFlags & SONG_ITCOMPATMODE) - || (!pChn->nLength) || ((pChn->dwFlags & CHN_NOTEFADE) && (!pChn->nFadeOutVol))) - { - pChn->dwFlags |= CHN_FASTVOLRAMP; - if ((m_nType & MOD_TYPE_IT) && (!bInstrumentChanged) && (penv) && (!(pChn->dwFlags & (CHN_KEYOFF|CHN_NOTEFADE)))) - { - if (!(penv->dwFlags & ENV_VOLCARRY)) pChn->nVolEnvPosition = 0; - if (!(penv->dwFlags & ENV_PANCARRY)) pChn->nPanEnvPosition = 0; - if (!(penv->dwFlags & ENV_PITCHCARRY)) pChn->nPitchEnvPosition = 0; - } else - { - pChn->nVolEnvPosition = 0; - pChn->nPanEnvPosition = 0; - pChn->nPitchEnvPosition = 0; - } - pChn->nAutoVibDepth = 0; - pChn->nAutoVibPos = 0; - } else - if ((penv) && (!(penv->dwFlags & ENV_VOLUME))) - { - pChn->nVolEnvPosition = 0; - pChn->nAutoVibDepth = 0; - pChn->nAutoVibPos = 0; - } - } - // Invalid sample ? - if (!psmp) - { - pChn->pInstrument = NULL; - pChn->nInsVol = 0; - return; - } - // Tone-Portamento doesn't reset the pingpong direction flag - if ((bPorta) && (psmp == pChn->pInstrument)) - { - if (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT)) return; - pChn->dwFlags &= ~(CHN_KEYOFF|CHN_NOTEFADE); - pChn->dwFlags = (pChn->dwFlags & (0xFFFFFF00 | CHN_PINGPONGFLAG)) | (psmp->uFlags); - } else - { - pChn->dwFlags &= ~(CHN_KEYOFF|CHN_NOTEFADE|CHN_VOLENV|CHN_PANENV|CHN_PITCHENV); - pChn->dwFlags = (pChn->dwFlags & 0xFFFFFF00) | (psmp->uFlags); - if (penv) - { - if (penv->dwFlags & ENV_VOLUME) pChn->dwFlags |= CHN_VOLENV; - if (penv->dwFlags & ENV_PANNING) pChn->dwFlags |= CHN_PANENV; - if (penv->dwFlags & ENV_PITCH) pChn->dwFlags |= CHN_PITCHENV; - if ((penv->dwFlags & ENV_PITCH) && (penv->dwFlags & ENV_FILTER)) - { - if (!pChn->nCutOff) pChn->nCutOff = 0x7F; - } - if (penv->nIFC & 0x80) pChn->nCutOff = penv->nIFC & 0x7F; - if (penv->nIFR & 0x80) pChn->nResonance = penv->nIFR & 0x7F; - } - pChn->nVolSwing = pChn->nPanSwing = 0; - } - pChn->pInstrument = psmp; - pChn->nLength = psmp->nLength; - pChn->nLoopStart = psmp->nLoopStart; - pChn->nLoopEnd = psmp->nLoopEnd; - pChn->nC4Speed = psmp->nC4Speed; - pChn->pSample = psmp->pSample; - pChn->nTranspose = psmp->RelativeTone; - pChn->nFineTune = psmp->nFineTune; - if (pChn->dwFlags & CHN_SUSTAINLOOP) - { - pChn->nLoopStart = psmp->nSustainStart; - pChn->nLoopEnd = psmp->nSustainEnd; - pChn->dwFlags |= CHN_LOOP; - if (pChn->dwFlags & CHN_PINGPONGSUSTAIN) pChn->dwFlags |= CHN_PINGPONGLOOP; - } - if ((pChn->dwFlags & CHN_LOOP) && (pChn->nLoopEnd < pChn->nLength)) pChn->nLength = pChn->nLoopEnd; -} - - -void CSoundFile::NoteChange(UINT nChn, int note, BOOL bPorta, BOOL bResetEnv) -//--------------------------------------------------------------------------- -{ - if (note < 1) return; - MODCHANNEL * const pChn = &Chn[nChn]; - MODINSTRUMENT *pins = pChn->pInstrument; - INSTRUMENTHEADER *penv = pChn->pHeader; - if ((penv) && (note <= 0x80)) - { - UINT n = penv->Keyboard[note - 1]; - if ((n) && (n < MAX_SAMPLES)) pins = &Ins[n]; - note = penv->NoteMap[note-1]; - } - // Key Off - if (note >= 0x80) // 0xFE or invalid note => key off - { - // Key Off - KeyOff(nChn); - // Note Cut - if (note == 0xFE) - { - pChn->dwFlags |= (CHN_NOTEFADE|CHN_FASTVOLRAMP); - if ((!(m_nType & MOD_TYPE_IT)) || (m_nInstruments)) pChn->nVolume = 0; - pChn->nFadeOutVol = 0; - } - return; - } - if (!pins) return; - if ((!bPorta) && (m_nType & (MOD_TYPE_XM|MOD_TYPE_MED|MOD_TYPE_MT2))) - { - pChn->nTranspose = pins->RelativeTone; - pChn->nFineTune = pins->nFineTune; - } - if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2|MOD_TYPE_MED)) note += pChn->nTranspose; - if (note < 1) note = 1; - if (note > 132) note = 132; - pChn->nNote = note; - if ((!bPorta) || (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT))) pChn->nNewIns = 0; - UINT period = GetPeriodFromNote(note, pChn->nFineTune, pChn->nC4Speed); - if (period) - { - if ((!bPorta) || (!pChn->nPeriod)) pChn->nPeriod = period; - pChn->nPortamentoDest = period; - if ((!bPorta) || ((!pChn->nLength) && (!(m_nType & MOD_TYPE_S3M)))) - { - pChn->pInstrument = pins; - pChn->pSample = pins->pSample; - pChn->nLength = pins->nLength; - pChn->nLoopEnd = pins->nLength; - pChn->nLoopStart = 0; - pChn->dwFlags = (pChn->dwFlags & 0xFFFFFF00) | (pins->uFlags); - if (pChn->dwFlags & CHN_SUSTAINLOOP) - { - pChn->nLoopStart = pins->nSustainStart; - pChn->nLoopEnd = pins->nSustainEnd; - pChn->dwFlags &= ~CHN_PINGPONGLOOP; - pChn->dwFlags |= CHN_LOOP; - if (pChn->dwFlags & CHN_PINGPONGSUSTAIN) pChn->dwFlags |= CHN_PINGPONGLOOP; - if (pChn->nLength > pChn->nLoopEnd) pChn->nLength = pChn->nLoopEnd; - } else - if (pChn->dwFlags & CHN_LOOP) - { - pChn->nLoopStart = pins->nLoopStart; - pChn->nLoopEnd = pins->nLoopEnd; - if (pChn->nLength > pChn->nLoopEnd) pChn->nLength = pChn->nLoopEnd; - } - pChn->nPos = 0; - pChn->nPosLo = 0; - if (pChn->nVibratoType < 4) pChn->nVibratoPos = ((m_nType & MOD_TYPE_IT) && (!(m_dwSongFlags & SONG_ITOLDEFFECTS))) ? 0x10 : 0; - if (pChn->nTremoloType < 4) pChn->nTremoloPos = 0; - } - if (pChn->nPos >= pChn->nLength) pChn->nPos = pChn->nLoopStart; - } else bPorta = FALSE; - if ((!bPorta) || (!(m_nType & MOD_TYPE_IT)) - || ((pChn->dwFlags & CHN_NOTEFADE) && (!pChn->nFadeOutVol)) - || ((m_dwSongFlags & SONG_ITCOMPATMODE) && (pChn->nRowInstr))) - { - if ((m_nType & MOD_TYPE_IT) && (pChn->dwFlags & CHN_NOTEFADE) && (!pChn->nFadeOutVol)) - { - pChn->nVolEnvPosition = 0; - pChn->nPanEnvPosition = 0; - pChn->nPitchEnvPosition = 0; - pChn->nAutoVibDepth = 0; - pChn->nAutoVibPos = 0; - pChn->dwFlags &= ~CHN_NOTEFADE; - pChn->nFadeOutVol = 65536; - } - if ((!bPorta) || (!(m_dwSongFlags & SONG_ITCOMPATMODE)) || (pChn->nRowInstr)) - { - if ((!(m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))) || (pChn->nRowInstr)) - { - pChn->dwFlags &= ~CHN_NOTEFADE; - pChn->nFadeOutVol = 65536; - } - } - } - pChn->dwFlags &= ~(CHN_EXTRALOUD|CHN_KEYOFF); - // Enable Ramping - if (!bPorta) - { - pChn->nVUMeter = 0x100; - pChn->nLeftVU = pChn->nRightVU = 0xFF; - pChn->dwFlags &= ~CHN_FILTER; - pChn->dwFlags |= CHN_FASTVOLRAMP; - pChn->nRetrigCount = 0; - pChn->nTremorCount = 0; - if (bResetEnv) - { - pChn->nVolSwing = pChn->nPanSwing = 0; - if (penv) - { - if (!(penv->dwFlags & ENV_VOLCARRY)) pChn->nVolEnvPosition = 0; - if (!(penv->dwFlags & ENV_PANCARRY)) pChn->nPanEnvPosition = 0; - if (!(penv->dwFlags & ENV_PITCHCARRY)) pChn->nPitchEnvPosition = 0; - if (m_nType & MOD_TYPE_IT) - { - // Volume Swing - if (penv->nVolSwing) - { - int d = ((LONG)penv->nVolSwing*(LONG)((rand() & 0xFF) - 0x7F)) / 128; - pChn->nVolSwing = (signed short)((d * pChn->nVolume + 1)/128); - } - // Pan Swing - if (penv->nPanSwing) - { - int d = ((LONG)penv->nPanSwing*(LONG)((rand() & 0xFF) - 0x7F)) / 128; - pChn->nPanSwing = (signed short)d; - } - } - } - pChn->nAutoVibDepth = 0; - pChn->nAutoVibPos = 0; - } - pChn->nLeftVol = pChn->nRightVol = 0; - BOOL bFlt = (m_dwSongFlags & SONG_MPTFILTERMODE) ? FALSE : TRUE; - // Setup Initial Filter for this note - if (penv) - { - if (penv->nIFR & 0x80) { pChn->nResonance = penv->nIFR & 0x7F; bFlt = TRUE; } - if (penv->nIFC & 0x80) { pChn->nCutOff = penv->nIFC & 0x7F; bFlt = TRUE; } - } else - { - pChn->nVolSwing = pChn->nPanSwing = 0; - } -#ifndef NO_FILTER - if ((pChn->nCutOff < 0x7F) && (bFlt)) SetupChannelFilter(pChn, TRUE); -#endif // NO_FILTER - } -} - - -UINT CSoundFile::GetNNAChannel(UINT nChn) const -//--------------------------------------------- -{ - const MODCHANNEL *pChn = &Chn[nChn]; - // Check for empty channel - const MODCHANNEL *pi = &Chn[m_nChannels]; - for (UINT i=m_nChannels; i<MAX_CHANNELS; i++, pi++) if (!pi->nLength) return i; - if (!pChn->nFadeOutVol) return 0; - // All channels are used: check for lowest volume - UINT result = 0; - DWORD vol = 64*65536; // 25% - DWORD envpos = 0xFFFFFF; - const MODCHANNEL *pj = &Chn[m_nChannels]; - for (UINT j=m_nChannels; j<MAX_CHANNELS; j++, pj++) - { - if (!pj->nFadeOutVol) return j; - DWORD v = pj->nVolume; - if (pj->dwFlags & CHN_NOTEFADE) - v = v * pj->nFadeOutVol; - else - v <<= 16; - if (pj->dwFlags & CHN_LOOP) v >>= 1; - if ((v < vol) || ((v == vol) && (pj->nVolEnvPosition > envpos))) - { - envpos = pj->nVolEnvPosition; - vol = v; - result = j; - } - } - return result; -} - - -void CSoundFile::CheckNNA(UINT nChn, UINT instr, int note, BOOL bForceCut) -//------------------------------------------------------------------------ -{ - MODCHANNEL *pChn = &Chn[nChn]; - INSTRUMENTHEADER *penv = pChn->pHeader, *pHeader = 0; - signed char *pSample; - if (note > 0x80) note = 0; - if (note < 1) return; - // Always NNA cut - using - if ((!(m_nType & (MOD_TYPE_IT|MOD_TYPE_MT2))) || (!m_nInstruments) || (bForceCut)) - { - if ((m_dwSongFlags & SONG_CPUVERYHIGH) - || (!pChn->nLength) || (pChn->dwFlags & CHN_MUTE) - || ((!pChn->nLeftVol) && (!pChn->nRightVol))) return; - UINT n = GetNNAChannel(nChn); - if (!n) return; - MODCHANNEL *p = &Chn[n]; - // Copy Channel - *p = *pChn; - p->dwFlags &= ~(CHN_VIBRATO|CHN_TREMOLO|CHN_PANBRELLO|CHN_MUTE|CHN_PORTAMENTO); - p->nMasterChn = nChn+1; - p->nCommand = 0; - // Cut the note - p->nFadeOutVol = 0; - p->dwFlags |= (CHN_NOTEFADE|CHN_FASTVOLRAMP); - // Stop this channel - pChn->nLength = pChn->nPos = pChn->nPosLo = 0; - pChn->nROfs = pChn->nLOfs = 0; - pChn->nLeftVol = pChn->nRightVol = 0; - return; - } - if (instr >= MAX_INSTRUMENTS) instr = 0; - pSample = pChn->pSample; - pHeader = pChn->pHeader; - if ((instr) && (note)) - { - pHeader = Headers[instr]; - if (pHeader) - { - UINT n = 0; - if (note <= 0x80) - { - n = pHeader->Keyboard[note-1]; - note = pHeader->NoteMap[note-1]; - if ((n) && (n < MAX_SAMPLES)) pSample = Ins[n].pSample; - } - } else pSample = NULL; - } - if (!penv) return; - MODCHANNEL *p = pChn; - for (UINT i=nChn; i<MAX_CHANNELS; p++, i++) - if ((i >= m_nChannels) || (p == pChn)) - { - if (((p->nMasterChn == nChn+1) || (p == pChn)) && (p->pHeader)) - { - BOOL bOk = FALSE; - // Duplicate Check Type - switch(p->pHeader->nDCT) - { - // Note - case DCT_NOTE: - if ((note) && (p->nNote == note) && (pHeader == p->pHeader)) bOk = TRUE; - break; - // Sample - case DCT_SAMPLE: - if ((pSample) && (pSample == p->pSample)) bOk = TRUE; - break; - // Instrument - case DCT_INSTRUMENT: - if (pHeader == p->pHeader) bOk = TRUE; - break; - } - // Duplicate Note Action - if (bOk) - { - switch(p->pHeader->nDNA) - { - // Cut - case DNA_NOTECUT: - KeyOff(i); - p->nVolume = 0; - break; - // Note Off - case DNA_NOTEOFF: - KeyOff(i); - break; - // Note Fade - case DNA_NOTEFADE: - p->dwFlags |= CHN_NOTEFADE; - break; - } - if (!p->nVolume) - { - p->nFadeOutVol = 0; - p->dwFlags |= (CHN_NOTEFADE|CHN_FASTVOLRAMP); - } - } - } - } - if (pChn->dwFlags & CHN_MUTE) return; - // New Note Action - if ((pChn->nVolume) && (pChn->nLength)) - { - UINT n = GetNNAChannel(nChn); - if (n) - { - MODCHANNEL *p = &Chn[n]; - // Copy Channel - *p = *pChn; - p->dwFlags &= ~(CHN_VIBRATO|CHN_TREMOLO|CHN_PANBRELLO|CHN_MUTE|CHN_PORTAMENTO); - p->nMasterChn = nChn+1; - p->nCommand = 0; - // Key Off the note - switch(pChn->nNNA) - { - case NNA_NOTEOFF: KeyOff(n); break; - case NNA_NOTECUT: - p->nFadeOutVol = 0; - case NNA_NOTEFADE: p->dwFlags |= CHN_NOTEFADE; break; - } - if (!p->nVolume) - { - p->nFadeOutVol = 0; - p->dwFlags |= (CHN_NOTEFADE|CHN_FASTVOLRAMP); - } - // Stop this channel - pChn->nLength = pChn->nPos = pChn->nPosLo = 0; - pChn->nROfs = pChn->nLOfs = 0; - } - } -} - - -BOOL CSoundFile::ProcessEffects() -//------------------------------- -{ - MODCHANNEL *pChn = Chn; - int nBreakRow = -1, nPosJump = -1, nPatLoopRow = -1; - - for (UINT nChn=0; nChn<m_nChannels; nChn++, pChn++) - { - UINT instr = pChn->nRowInstr; - UINT volcmd = pChn->nRowVolCmd; - UINT vol = pChn->nRowVolume; - UINT cmd = pChn->nRowCommand; - UINT param = pChn->nRowParam; - bool bPorta = ((cmd != CMD_TONEPORTAMENTO) && (cmd != CMD_TONEPORTAVOL) && (volcmd != VOLCMD_TONEPORTAMENTO)) ? FALSE : TRUE; - UINT nStartTick = 0; - - pChn->dwFlags &= ~CHN_FASTVOLRAMP; - // Process special effects (note delay, pattern delay, pattern loop) - if ((cmd == CMD_MODCMDEX) || (cmd == CMD_S3MCMDEX)) - { - if ((!param) && (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT))) param = pChn->nOldCmdEx; else pChn->nOldCmdEx = param; - // Note Delay ? - if ((param & 0xF0) == 0xD0) - { - nStartTick = param & 0x0F; - } else - if (!m_nTickCount) - { - // Pattern Loop ? - if ((((param & 0xF0) == 0x60) && (cmd == CMD_MODCMDEX)) - || (((param & 0xF0) == 0xB0) && (cmd == CMD_S3MCMDEX))) - { - int nloop = PatternLoop(pChn, param & 0x0F); - if (nloop >= 0) nPatLoopRow = nloop; - } else - // Pattern Delay - if ((param & 0xF0) == 0xE0) - { - m_nPatternDelay = param & 0x0F; - } - } - } - - // Handles note/instrument/volume changes - if (m_nTickCount == nStartTick) // can be delayed by a note delay effect - { - UINT note = pChn->nRowNote; - if (instr) pChn->nNewIns = instr; - // XM: Key-Off + Sample == Note Cut - if (m_nType & (MOD_TYPE_MOD|MOD_TYPE_XM|MOD_TYPE_MT2)) - { - if ((note == 0xFF) && ((!pChn->pHeader) || (!(pChn->pHeader->dwFlags & ENV_VOLUME)))) - { - pChn->dwFlags |= CHN_FASTVOLRAMP; - pChn->nVolume = 0; - note = instr = 0; - } - } - if ((!note) && (instr)) - { - if (m_nInstruments) - { - if (pChn->pInstrument) pChn->nVolume = pChn->pInstrument->nVolume; - if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) - { - pChn->dwFlags |= CHN_FASTVOLRAMP; - pChn->nVolEnvPosition = 0; - pChn->nPanEnvPosition = 0; - pChn->nPitchEnvPosition = 0; - pChn->nAutoVibDepth = 0; - pChn->nAutoVibPos = 0; - pChn->dwFlags &= ~CHN_NOTEFADE; - pChn->nFadeOutVol = 65536; - } - } else - { - if (instr < MAX_SAMPLES) pChn->nVolume = Ins[instr].nVolume; - } - if (!(m_nType & MOD_TYPE_IT)) instr = 0; - } - // Invalid Instrument ? - if (instr >= MAX_INSTRUMENTS) instr = 0; - // Note Cut/Off => ignore instrument - if (note >= 0xFE) instr = 0; - if ((note) && (note <= 128)) pChn->nNewNote = note; - // New Note Action ? - if ((note) && (note <= 128) && (!bPorta)) - { - CheckNNA(nChn, instr, note, FALSE); - } - // Instrument Change ? - if (instr) - { - MODINSTRUMENT *psmp = pChn->pInstrument; - InstrumentChange(pChn, instr, bPorta, TRUE); - pChn->nNewIns = 0; - // Special IT case: portamento+note causes sample change -> ignore portamento - if ((m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT)) - && (psmp != pChn->pInstrument) && (note) && (note < 0x80)) - { - bPorta = FALSE; - } - } - // New Note ? - if (note) - { - if ((!instr) && (pChn->nNewIns) && (note < 0x80)) - { - InstrumentChange(pChn, pChn->nNewIns, bPorta, FALSE, (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) ? FALSE : TRUE); - pChn->nNewIns = 0; - } - NoteChange(nChn, note, bPorta, (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) ? FALSE : TRUE); - if ((bPorta) && (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) && (instr)) - { - pChn->dwFlags |= CHN_FASTVOLRAMP; - pChn->nVolEnvPosition = 0; - pChn->nPanEnvPosition = 0; - pChn->nPitchEnvPosition = 0; - pChn->nAutoVibDepth = 0; - pChn->nAutoVibPos = 0; - } - } - // Tick-0 only volume commands - if (volcmd == VOLCMD_VOLUME) - { - if (vol > 64) vol = 64; - pChn->nVolume = vol << 2; - pChn->dwFlags |= CHN_FASTVOLRAMP; - } else - if (volcmd == VOLCMD_PANNING) - { - if (vol > 64) vol = 64; - pChn->nPan = vol << 2; - pChn->dwFlags |= CHN_FASTVOLRAMP; - } - } - - // Volume Column Effect (except volume & panning) - if ((volcmd > VOLCMD_PANNING) && (m_nTickCount >= nStartTick)) - { - if (volcmd == VOLCMD_TONEPORTAMENTO) - { - if (m_nType & MOD_TYPE_IT) - TonePortamento(pChn, ImpulseTrackerPortaVolCmd[vol & 0x0F]); - else - TonePortamento(pChn, vol * 16); - } else - { - if (vol) pChn->nOldVolParam = vol; else vol = pChn->nOldVolParam; - switch(volcmd) - { - case VOLCMD_VOLSLIDEUP: - VolumeSlide(pChn, vol << 4); - break; - - case VOLCMD_VOLSLIDEDOWN: - VolumeSlide(pChn, vol); - break; - - case VOLCMD_FINEVOLUP: - if (m_nType & MOD_TYPE_IT) - { - if (m_nTickCount == nStartTick) VolumeSlide(pChn, (vol << 4) | 0x0F); - } else - FineVolumeUp(pChn, vol); - break; - - case VOLCMD_FINEVOLDOWN: - if (m_nType & MOD_TYPE_IT) - { - if (m_nTickCount == nStartTick) VolumeSlide(pChn, 0xF0 | vol); - } else - FineVolumeDown(pChn, vol); - break; - - case VOLCMD_VIBRATOSPEED: - Vibrato(pChn, vol << 4); - break; - - case VOLCMD_VIBRATO: - Vibrato(pChn, vol); - break; - - case VOLCMD_PANSLIDELEFT: - PanningSlide(pChn, vol); - break; - - case VOLCMD_PANSLIDERIGHT: - PanningSlide(pChn, vol << 4); - break; - - case VOLCMD_PORTAUP: - PortamentoUp(pChn, vol << 2); - break; - - case VOLCMD_PORTADOWN: - PortamentoDown(pChn, vol << 2); - break; - } - } - } - - // Effects - if (cmd) switch (cmd) - { - // Set Volume - case CMD_VOLUME: - if (!m_nTickCount) - { - pChn->nVolume = (param < 64) ? param*4 : 256; - pChn->dwFlags |= CHN_FASTVOLRAMP; - } - break; - - // Portamento Up - case CMD_PORTAMENTOUP: - if ((!param) && (m_nType & MOD_TYPE_MOD)) break; - PortamentoUp(pChn, param); - break; - - // Portamento Down - case CMD_PORTAMENTODOWN: - if ((!param) && (m_nType & MOD_TYPE_MOD)) break; - PortamentoDown(pChn, param); - break; - - // Volume Slide - case CMD_VOLUMESLIDE: - if ((param) || (m_nType != MOD_TYPE_MOD)) VolumeSlide(pChn, param); - break; - - // Tone-Portamento - case CMD_TONEPORTAMENTO: - TonePortamento(pChn, param); - break; - - // Tone-Portamento + Volume Slide - case CMD_TONEPORTAVOL: - if ((param) || (m_nType != MOD_TYPE_MOD)) VolumeSlide(pChn, param); - TonePortamento(pChn, 0); - break; - - // Vibrato - case CMD_VIBRATO: - Vibrato(pChn, param); - break; - - // Vibrato + Volume Slide - case CMD_VIBRATOVOL: - if ((param) || (m_nType != MOD_TYPE_MOD)) VolumeSlide(pChn, param); - Vibrato(pChn, 0); - break; - - // Set Speed - case CMD_SPEED: - if (!m_nTickCount) SetSpeed(param); - break; - - // Set Tempo - case CMD_TEMPO: - if (!m_nTickCount) - { - if (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT)) - { - if (param) pChn->nOldTempo = param; else param = pChn->nOldTempo; - } - SetTempo(param); - } - break; - - // Set Offset - case CMD_OFFSET: - if (m_nTickCount) break; - if (param) pChn->nOldOffset = param; else param = pChn->nOldOffset; - param <<= 8; - param |= (UINT)(pChn->nOldHiOffset) << 16; - if ((pChn->nRowNote) && (pChn->nRowNote < 0x80)) - { - if (bPorta) - pChn->nPos = param; - else - pChn->nPos += param; - if (pChn->nPos >= pChn->nLength) - { - if (!(m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))) - { - pChn->nPos = pChn->nLoopStart; - if ((m_dwSongFlags & SONG_ITOLDEFFECTS) && (pChn->nLength > 4)) - { - pChn->nPos = pChn->nLength - 2; - } - } - } - } else - if ((param < pChn->nLength) && (m_nType & (MOD_TYPE_MTM|MOD_TYPE_DMF))) - { - pChn->nPos = param; - } - break; - - // Arpeggio - case CMD_ARPEGGIO: - if ((m_nTickCount) || (!pChn->nPeriod) || (!pChn->nNote)) break; - if ((!param) && (!(m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT)))) break; - pChn->nCommand = CMD_ARPEGGIO; - if (param) pChn->nArpeggio = param; - break; - - // Retrig - case CMD_RETRIG: - if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) - { - if (!(param & 0xF0)) param |= pChn->nRetrigParam & 0xF0; - if (!(param & 0x0F)) param |= pChn->nRetrigParam & 0x0F; - param |= 0x100; // increment retrig count on first row - } - if (param) pChn->nRetrigParam = (BYTE)(param & 0xFF); else param = pChn->nRetrigParam; - RetrigNote(nChn, param); - break; - - // Tremor - case CMD_TREMOR: - if (m_nTickCount) break; - pChn->nCommand = CMD_TREMOR; - if (param) pChn->nTremorParam = param; - break; - - // Set Global Volume - case CMD_GLOBALVOLUME: - if (m_nTickCount) break; - if (m_nType != MOD_TYPE_IT) param <<= 1; - if (param > 128) param = 128; - m_nGlobalVolume = param << 1; - break; - - // Global Volume Slide - case CMD_GLOBALVOLSLIDE: - GlobalVolSlide(param); - break; - - // Set 8-bit Panning - case CMD_PANNING8: - if (m_nTickCount) break; - if (!(m_dwSongFlags & SONG_SURROUNDPAN)) pChn->dwFlags &= ~CHN_SURROUND; - if (m_nType & (MOD_TYPE_IT|MOD_TYPE_XM|MOD_TYPE_MT2)) - { - pChn->nPan = param; - } else - if (param <= 0x80) - { - pChn->nPan = param << 1; - } else - if (param == 0xA4) - { - pChn->dwFlags |= CHN_SURROUND; - pChn->nPan = 0x80; - } - pChn->dwFlags |= CHN_FASTVOLRAMP; - break; - - // Panning Slide - case CMD_PANNINGSLIDE: - PanningSlide(pChn, param); - break; - - // Tremolo - case CMD_TREMOLO: - Tremolo(pChn, param); - break; - - // Fine Vibrato - case CMD_FINEVIBRATO: - FineVibrato(pChn, param); - break; - - // MOD/XM Exx Extended Commands - case CMD_MODCMDEX: - ExtendedMODCommands(nChn, param); - break; - - // S3M/IT Sxx Extended Commands - case CMD_S3MCMDEX: - ExtendedS3MCommands(nChn, param); - break; - - // Key Off - case CMD_KEYOFF: - if (!m_nTickCount) KeyOff(nChn); - break; - - // Extra-fine porta up/down - case CMD_XFINEPORTAUPDOWN: - switch(param & 0xF0) - { - case 0x10: ExtraFinePortamentoUp(pChn, param & 0x0F); break; - case 0x20: ExtraFinePortamentoDown(pChn, param & 0x0F); break; - // Modplug XM Extensions - case 0x50: - case 0x60: - case 0x70: - case 0x90: - case 0xA0: ExtendedS3MCommands(nChn, param); break; - } - break; - - // Set Channel Global Volume - case CMD_CHANNELVOLUME: - if (m_nTickCount) break; - if (param <= 64) - { - pChn->nGlobalVol = param; - pChn->dwFlags |= CHN_FASTVOLRAMP; - } - break; - - // Channel volume slide - case CMD_CHANNELVOLSLIDE: - ChannelVolSlide(pChn, param); - break; - - // Panbrello (IT) - case CMD_PANBRELLO: - Panbrello(pChn, param); - break; - - // Set Envelope Position - case CMD_SETENVPOSITION: - if (!m_nTickCount) - { - pChn->nVolEnvPosition = param; - pChn->nPanEnvPosition = param; - pChn->nPitchEnvPosition = param; - if (pChn->pHeader) - { - INSTRUMENTHEADER *penv = pChn->pHeader; - if ((pChn->dwFlags & CHN_PANENV) && (penv->nPanEnv) && (param > penv->PanPoints[penv->nPanEnv-1])) - { - pChn->dwFlags &= ~CHN_PANENV; - } - } - } - break; - - // Position Jump - case CMD_POSITIONJUMP: - nPosJump = param; - break; - - // Pattern Break - case CMD_PATTERNBREAK: - nBreakRow = param; - break; - - // Midi Controller - case CMD_MIDI: - if (m_nTickCount) break; - if (param < 0x80){ - ProcessMidiMacro(nChn, &m_MidiCfg.szMidiSFXExt[pChn->nActiveMacro << 5], param); - } else { - ProcessMidiMacro(nChn, &m_MidiCfg.szMidiZXXExt[(param & 0x7F) << 5], 0); - } - break; - } - } - - // Navigation Effects - if (!m_nTickCount) - { - // Pattern Loop - if (nPatLoopRow >= 0) - { - m_nNextPattern = m_nCurrentPattern; - m_nNextRow = nPatLoopRow; - if (m_nPatternDelay) m_nNextRow++; - } else - // Pattern Break / Position Jump only if no loop running - if ((nBreakRow >= 0) || (nPosJump >= 0)) - { - BOOL bNoLoop = FALSE; - if (nPosJump < 0) nPosJump = m_nCurrentPattern+1; - if (nBreakRow < 0) nBreakRow = 0; - // Modplug Tracker & ModPlugin allow backward jumps - #ifndef MODPLUG_FASTSOUNDLIB - if ((nPosJump < (int)m_nCurrentPattern) - || ((nPosJump == (int)m_nCurrentPattern) && (nBreakRow <= (int)m_nRow))) - { - if (!IsValidBackwardJump(m_nCurrentPattern, m_nRow, nPosJump, nBreakRow)) - { - if (m_nRepeatCount) - { - if (m_nRepeatCount > 0) m_nRepeatCount--; - } else - { - #ifdef MODPLUG_TRACKER - if (gdwSoundSetup & SNDMIX_NOBACKWARDJUMPS) - #endif - // Backward jump disabled - bNoLoop = TRUE; - //reset repeat count incase there are multiple loops. - //(i.e. Unreal tracks) - m_nRepeatCount = m_nInitialRepeatCount; - } - } - } - #endif // MODPLUG_FASTSOUNDLIB - if (((!bNoLoop) && (nPosJump < MAX_ORDERS)) - && ((nPosJump != (int)m_nCurrentPattern) || (nBreakRow != (int)m_nRow))) - { - if (nPosJump != (int)m_nCurrentPattern) - { - for (UINT i=0; i<m_nChannels; i++) Chn[i].nPatternLoopCount = 0; - } - m_nNextPattern = nPosJump; - m_nNextRow = (UINT)nBreakRow; - } - } - } - return TRUE; -} - - -//////////////////////////////////////////////////////////// -// Channels effects - -void CSoundFile::PortamentoUp(MODCHANNEL *pChn, UINT param) -//--------------------------------------------------------- -{ - if (param) pChn->nOldPortaUpDown = param; else param = pChn->nOldPortaUpDown; - if ((m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_STM)) && ((param & 0xF0) >= 0xE0)) - { - if (param & 0x0F) - { - if ((param & 0xF0) == 0xF0) - { - FinePortamentoUp(pChn, param & 0x0F); - } else - if ((param & 0xF0) == 0xE0) - { - ExtraFinePortamentoUp(pChn, param & 0x0F); - } - } - return; - } - // Regular Slide - if (!(m_dwSongFlags & SONG_FIRSTTICK) || (m_nMusicSpeed == 1)) //rewbs.PortaA01fix - { - DoFreqSlide(pChn, -(int)(param * 4)); - } -} - - -void CSoundFile::PortamentoDown(MODCHANNEL *pChn, UINT param) -//----------------------------------------------------------- -{ - if (param) pChn->nOldPortaUpDown = param; else param = pChn->nOldPortaUpDown; - if ((m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_STM)) && ((param & 0xF0) >= 0xE0)) - { - if (param & 0x0F) - { - if ((param & 0xF0) == 0xF0) - { - FinePortamentoDown(pChn, param & 0x0F); - } else - if ((param & 0xF0) == 0xE0) - { - ExtraFinePortamentoDown(pChn, param & 0x0F); - } - } - return; - } - if (!(m_dwSongFlags & SONG_FIRSTTICK) || (m_nMusicSpeed == 1)) { //rewbs.PortaA01fix - DoFreqSlide(pChn, (int)(param << 2)); - } -} - - -void CSoundFile::FinePortamentoUp(MODCHANNEL *pChn, UINT param) -//------------------------------------------------------------- -{ - if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) - { - if (param) pChn->nOldFinePortaUpDown = param; else param = pChn->nOldFinePortaUpDown; - } - if (m_dwSongFlags & SONG_FIRSTTICK) - { - if ((pChn->nPeriod) && (param)) - { - if ((m_dwSongFlags & SONG_LINEARSLIDES) && (!(m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)))) - { - pChn->nPeriod = _muldivr(pChn->nPeriod, LinearSlideDownTable[param & 0x0F], 65536); - } else - { - pChn->nPeriod -= (int)(param * 4); - } - if (pChn->nPeriod < 1) pChn->nPeriod = 1; - } - } -} - - -void CSoundFile::FinePortamentoDown(MODCHANNEL *pChn, UINT param) -//--------------------------------------------------------------- -{ - if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) - { - if (param) pChn->nOldFinePortaUpDown = param; else param = pChn->nOldFinePortaUpDown; - } - if (m_dwSongFlags & SONG_FIRSTTICK) - { - if ((pChn->nPeriod) && (param)) - { - if ((m_dwSongFlags & SONG_LINEARSLIDES) && (!(m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)))) - { - pChn->nPeriod = _muldivr(pChn->nPeriod, LinearSlideUpTable[param & 0x0F], 65536); - } else - { - pChn->nPeriod += (int)(param * 4); - } - if (pChn->nPeriod > 0xFFFF) pChn->nPeriod = 0xFFFF; - } - } -} - - -void CSoundFile::ExtraFinePortamentoUp(MODCHANNEL *pChn, UINT param) -//------------------------------------------------------------------ -{ - if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) - { - if (param) pChn->nOldFinePortaUpDown = param; else param = pChn->nOldFinePortaUpDown; - } - if (m_dwSongFlags & SONG_FIRSTTICK) - { - if ((pChn->nPeriod) && (param)) - { - if ((m_dwSongFlags & SONG_LINEARSLIDES) && (!(m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)))) - { - pChn->nPeriod = _muldivr(pChn->nPeriod, FineLinearSlideDownTable[param & 0x0F], 65536); - } else - { - pChn->nPeriod -= (int)(param); - } - if (pChn->nPeriod < 1) pChn->nPeriod = 1; - } - } -} - - -void CSoundFile::ExtraFinePortamentoDown(MODCHANNEL *pChn, UINT param) -//-------------------------------------------------------------------- -{ - if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) - { - if (param) pChn->nOldFinePortaUpDown = param; else param = pChn->nOldFinePortaUpDown; - } - if (m_dwSongFlags & SONG_FIRSTTICK) - { - if ((pChn->nPeriod) && (param)) - { - if ((m_dwSongFlags & SONG_LINEARSLIDES) && (!(m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)))) - { - pChn->nPeriod = _muldivr(pChn->nPeriod, FineLinearSlideUpTable[param & 0x0F], 65536); - } else - { - pChn->nPeriod += (int)(param); - } - if (pChn->nPeriod > 0xFFFF) pChn->nPeriod = 0xFFFF; - } - } -} - - -// Portamento Slide -void CSoundFile::TonePortamento(MODCHANNEL *pChn, UINT param) -//----------------------------------------------------------- -{ - if (param) pChn->nPortamentoSlide = param * 4; - pChn->dwFlags |= CHN_PORTAMENTO; - if ((pChn->nPeriod) && (pChn->nPortamentoDest) && (!(m_dwSongFlags & SONG_FIRSTTICK))) - { - if (pChn->nPeriod < pChn->nPortamentoDest) - { - LONG delta = (int)pChn->nPortamentoSlide; - if ((m_dwSongFlags & SONG_LINEARSLIDES) && (!(m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)))) - { - UINT n = pChn->nPortamentoSlide >> 2; - if (n > 255) n = 255; - delta = _muldivr(pChn->nPeriod, LinearSlideUpTable[n], 65536) - pChn->nPeriod; - if (delta < 1) delta = 1; - } - pChn->nPeriod += delta; - if (pChn->nPeriod > pChn->nPortamentoDest) pChn->nPeriod = pChn->nPortamentoDest; - } else - if (pChn->nPeriod > pChn->nPortamentoDest) - { - LONG delta = - (int)pChn->nPortamentoSlide; - if ((m_dwSongFlags & SONG_LINEARSLIDES) && (!(m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)))) - { - UINT n = pChn->nPortamentoSlide >> 2; - if (n > 255) n = 255; - delta = _muldivr(pChn->nPeriod, LinearSlideDownTable[n], 65536) - pChn->nPeriod; - if (delta > -1) delta = -1; - } - pChn->nPeriod += delta; - if (pChn->nPeriod < pChn->nPortamentoDest) pChn->nPeriod = pChn->nPortamentoDest; - } - } -} - - -void CSoundFile::Vibrato(MODCHANNEL *p, UINT param) -//------------------------------------------------- -{ - if (param & 0x0F) p->nVibratoDepth = (param & 0x0F) * 4; - if (param & 0xF0) p->nVibratoSpeed = (param >> 4) & 0x0F; - p->dwFlags |= CHN_VIBRATO; -} - - -void CSoundFile::FineVibrato(MODCHANNEL *p, UINT param) -//----------------------------------------------------- -{ - if (param & 0x0F) p->nVibratoDepth = param & 0x0F; - if (param & 0xF0) p->nVibratoSpeed = (param >> 4) & 0x0F; - p->dwFlags |= CHN_VIBRATO; -} - - -void CSoundFile::Panbrello(MODCHANNEL *p, UINT param) -//--------------------------------------------------- -{ - if (param & 0x0F) p->nPanbrelloDepth = param & 0x0F; - if (param & 0xF0) p->nPanbrelloSpeed = (param >> 4) & 0x0F; - p->dwFlags |= CHN_PANBRELLO; -} - - -void CSoundFile::VolumeSlide(MODCHANNEL *pChn, UINT param) -//-------------------------------------------------------- -{ - if (param) pChn->nOldVolumeSlide = param; else param = pChn->nOldVolumeSlide; - LONG newvolume = pChn->nVolume; - if (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_STM|MOD_TYPE_AMF)) - { - if ((param & 0x0F) == 0x0F) - { - if (param & 0xF0) - { - FineVolumeUp(pChn, (param >> 4)); - return; - } else - { - if ((m_dwSongFlags & SONG_FIRSTTICK) && (!(m_dwSongFlags & SONG_FASTVOLSLIDES))) - { - newvolume -= 0x0F * 4; - } - } - } else - if ((param & 0xF0) == 0xF0) - { - if (param & 0x0F) - { - FineVolumeDown(pChn, (param & 0x0F)); - return; - } else - { - if ((m_dwSongFlags & SONG_FIRSTTICK) && (!(m_dwSongFlags & SONG_FASTVOLSLIDES))) - { - newvolume += 0x0F * 4; - } - } - } - } - if ((!(m_dwSongFlags & SONG_FIRSTTICK)) || (m_dwSongFlags & SONG_FASTVOLSLIDES)) - { - if (param & 0x0F) newvolume -= (int)((param & 0x0F) * 4); - else newvolume += (int)((param & 0xF0) >> 2); - if (m_nType & MOD_TYPE_MOD) pChn->dwFlags |= CHN_FASTVOLRAMP; - } - if (newvolume < 0) newvolume = 0; - if (newvolume > 256) newvolume = 256; - pChn->nVolume = newvolume; -} - - -void CSoundFile::PanningSlide(MODCHANNEL *pChn, UINT param) -//--------------------------------------------------------- -{ - LONG nPanSlide = 0; - if (param) pChn->nOldPanSlide = param; else param = pChn->nOldPanSlide; - if (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_STM)) - { - if (((param & 0x0F) == 0x0F) && (param & 0xF0)) - { - if (m_dwSongFlags & SONG_FIRSTTICK) - { - param = (param & 0xF0) >> 2; - nPanSlide = - (int)param; - } - } else - if (((param & 0xF0) == 0xF0) && (param & 0x0F)) - { - if (m_dwSongFlags & SONG_FIRSTTICK) - { - nPanSlide = (param & 0x0F) << 2; - } - } else - { - if (!(m_dwSongFlags & SONG_FIRSTTICK)) - { - if (param & 0x0F) nPanSlide = (int)((param & 0x0F) << 2); - else nPanSlide = -(int)((param & 0xF0) >> 2); - } - } - } else - { - if (!(m_dwSongFlags & SONG_FIRSTTICK)) - { - if (param & 0x0F) nPanSlide = -(int)((param & 0x0F) << 2); - else nPanSlide = (int)((param & 0xF0) >> 2); - } - } - if (nPanSlide) - { - nPanSlide += pChn->nPan; - if (nPanSlide < 0) nPanSlide = 0; - if (nPanSlide > 256) nPanSlide = 256; - pChn->nPan = nPanSlide; - } -} - - -void CSoundFile::FineVolumeUp(MODCHANNEL *pChn, UINT param) -//--------------------------------------------------------- -{ - if (param) pChn->nOldFineVolUpDown = param; else param = pChn->nOldFineVolUpDown; - if (m_dwSongFlags & SONG_FIRSTTICK) - { - pChn->nVolume += param * 4; - if (pChn->nVolume > 256) pChn->nVolume = 256; - if (m_nType & MOD_TYPE_MOD) pChn->dwFlags |= CHN_FASTVOLRAMP; - } -} - - -void CSoundFile::FineVolumeDown(MODCHANNEL *pChn, UINT param) -//----------------------------------------------------------- -{ - if (param) pChn->nOldFineVolUpDown = param; else param = pChn->nOldFineVolUpDown; - if (m_dwSongFlags & SONG_FIRSTTICK) - { - pChn->nVolume -= param * 4; - if (pChn->nVolume < 0) pChn->nVolume = 0; - if (m_nType & MOD_TYPE_MOD) pChn->dwFlags |= CHN_FASTVOLRAMP; - } -} - - -void CSoundFile::Tremolo(MODCHANNEL *p, UINT param) -//------------------------------------------------- -{ - if (param & 0x0F) p->nTremoloDepth = (param & 0x0F) << 2; - if (param & 0xF0) p->nTremoloSpeed = (param >> 4) & 0x0F; - p->dwFlags |= CHN_TREMOLO; -} - - -void CSoundFile::ChannelVolSlide(MODCHANNEL *pChn, UINT param) -//------------------------------------------------------------ -{ - LONG nChnSlide = 0; - if (param) pChn->nOldChnVolSlide = param; else param = pChn->nOldChnVolSlide; - if (((param & 0x0F) == 0x0F) && (param & 0xF0)) - { - if (m_dwSongFlags & SONG_FIRSTTICK) nChnSlide = param >> 4; - } else - if (((param & 0xF0) == 0xF0) && (param & 0x0F)) - { - if (m_dwSongFlags & SONG_FIRSTTICK) nChnSlide = - (int)(param & 0x0F); - } else - { - if (!(m_dwSongFlags & SONG_FIRSTTICK)) - { - if (param & 0x0F) nChnSlide = -(int)(param & 0x0F); - else nChnSlide = (int)((param & 0xF0) >> 4); - } - } - if (nChnSlide) - { - nChnSlide += pChn->nGlobalVol; - if (nChnSlide < 0) nChnSlide = 0; - if (nChnSlide > 64) nChnSlide = 64; - pChn->nGlobalVol = nChnSlide; - } -} - - -void CSoundFile::ExtendedMODCommands(UINT nChn, UINT param) -//--------------------------------------------------------- -{ - MODCHANNEL *pChn = &Chn[nChn]; - UINT command = param & 0xF0; - param &= 0x0F; - switch(command) - { - // E0x: Set Filter - // E1x: Fine Portamento Up - case 0x10: if ((param) || (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))) FinePortamentoUp(pChn, param); break; - // E2x: Fine Portamento Down - case 0x20: if ((param) || (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))) FinePortamentoDown(pChn, param); break; - // E3x: Set Glissando Control - case 0x30: pChn->dwFlags &= ~CHN_GLISSANDO; if (param) pChn->dwFlags |= CHN_GLISSANDO; break; - // E4x: Set Vibrato WaveForm - case 0x40: pChn->nVibratoType = param & 0x07; break; - // E5x: Set FineTune - case 0x50: if (m_nTickCount) break; - pChn->nC4Speed = S3MFineTuneTable[param]; - if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) - pChn->nFineTune = param*2; - else - pChn->nFineTune = MOD2XMFineTune(param); - if (pChn->nPeriod) pChn->nPeriod = GetPeriodFromNote(pChn->nNote, pChn->nFineTune, pChn->nC4Speed); - break; - // E6x: Pattern Loop - // E7x: Set Tremolo WaveForm - case 0x70: pChn->nTremoloType = param & 0x07; break; - // E8x: Set 4-bit Panning - case 0x80: if (!m_nTickCount) { pChn->nPan = (param << 4) + 8; pChn->dwFlags |= CHN_FASTVOLRAMP; } break; - // E9x: Retrig - case 0x90: RetrigNote(nChn, param); break; - // EAx: Fine Volume Up - case 0xA0: if ((param) || (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))) FineVolumeUp(pChn, param); break; - // EBx: Fine Volume Down - case 0xB0: if ((param) || (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))) FineVolumeDown(pChn, param); break; - // ECx: Note Cut - case 0xC0: NoteCut(nChn, param); break; - // EDx: Note Delay - // EEx: Pattern Delay - // EFx: MOD: Invert Loop, XM: Set Active Midi Macro - case 0xF0: pChn->nActiveMacro = param; break; - } -} - - -void CSoundFile::ExtendedS3MCommands(UINT nChn, UINT param) -//--------------------------------------------------------- -{ - MODCHANNEL *pChn = &Chn[nChn]; - UINT command = param & 0xF0; - param &= 0x0F; - switch(command) - { - // S0x: Set Filter - // S1x: Set Glissando Control - case 0x10: pChn->dwFlags &= ~CHN_GLISSANDO; if (param) pChn->dwFlags |= CHN_GLISSANDO; break; - // S2x: Set FineTune - case 0x20: if (m_nTickCount) break; - pChn->nC4Speed = S3MFineTuneTable[param & 0x0F]; - pChn->nFineTune = MOD2XMFineTune(param); - if (pChn->nPeriod) pChn->nPeriod = GetPeriodFromNote(pChn->nNote, pChn->nFineTune, pChn->nC4Speed); - break; - // S3x: Set Vibrato WaveForm - case 0x30: pChn->nVibratoType = param & 0x07; break; - // S4x: Set Tremolo WaveForm - case 0x40: pChn->nTremoloType = param & 0x07; break; - // S5x: Set Panbrello WaveForm - case 0x50: pChn->nPanbrelloType = param & 0x07; break; - // S6x: Pattern Delay for x frames - case 0x60: m_nFrameDelay = param; break; - // S7x: Envelope Control - case 0x70: if (m_nTickCount) break; - switch(param) - { - case 0: - case 1: - case 2: - { - MODCHANNEL *bkp = &Chn[m_nChannels]; - for (UINT i=m_nChannels; i<MAX_CHANNELS; i++, bkp++) - { - if (bkp->nMasterChn == nChn+1) - { - if (param == 1) KeyOff(i); else - if (param == 2) bkp->dwFlags |= CHN_NOTEFADE; else - { bkp->dwFlags |= CHN_NOTEFADE; bkp->nFadeOutVol = 0; } - } - } - } - break; - case 3: pChn->nNNA = NNA_NOTECUT; break; - case 4: pChn->nNNA = NNA_CONTINUE; break; - case 5: pChn->nNNA = NNA_NOTEOFF; break; - case 6: pChn->nNNA = NNA_NOTEFADE; break; - case 7: pChn->dwFlags &= ~CHN_VOLENV; break; - case 8: pChn->dwFlags |= CHN_VOLENV; break; - case 9: pChn->dwFlags &= ~CHN_PANENV; break; - case 10: pChn->dwFlags |= CHN_PANENV; break; - case 11: pChn->dwFlags &= ~CHN_PITCHENV; break; - case 12: pChn->dwFlags |= CHN_PITCHENV; break; - } - break; - // S8x: Set 4-bit Panning - case 0x80: if (!m_nTickCount) { pChn->nPan = (param << 4) + 8; pChn->dwFlags |= CHN_FASTVOLRAMP; } break; - // S9x: Set Surround - case 0x90: ExtendedChannelEffect(pChn, param & 0x0F); break; - // SAx: Set 64k Offset - case 0xA0: if (!m_nTickCount) - { - pChn->nOldHiOffset = param; - if ((pChn->nRowNote) && (pChn->nRowNote < 0x80)) - { - DWORD pos = param << 16; - if (pos < pChn->nLength) pChn->nPos = pos; - } - } - break; - // SBx: Pattern Loop - // SCx: Note Cut - case 0xC0: NoteCut(nChn, param); break; - // SDx: Note Delay - // case 0xD0: break; - // SEx: Pattern Delay for x rows - // SFx: S3M: Funk Repeat, IT: Set Active Midi Macro - case 0xF0: pChn->nActiveMacro = param; break; - } -} - - -void CSoundFile::ExtendedChannelEffect(MODCHANNEL *pChn, UINT param) -//------------------------------------------------------------------ -{ - // S9x and X9x commands (S3M/XM/IT only) - if (m_nTickCount) return; - switch(param & 0x0F) - { - // S90: Surround Off - case 0x00: pChn->dwFlags &= ~CHN_SURROUND; break; - // S91: Surround On - case 0x01: pChn->dwFlags |= CHN_SURROUND; pChn->nPan = 128; break; - //////////////////////////////////////////////////////////// - // Modplug Extensions - // S98: Reverb Off - case 0x08: - pChn->dwFlags &= ~CHN_REVERB; - pChn->dwFlags |= CHN_NOREVERB; - break; - // S99: Reverb On - case 0x09: - pChn->dwFlags &= ~CHN_NOREVERB; - pChn->dwFlags |= CHN_REVERB; - break; - // S9A: 2-Channels surround mode - case 0x0A: - m_dwSongFlags &= ~SONG_SURROUNDPAN; - break; - // S9B: 4-Channels surround mode - case 0x0B: - m_dwSongFlags |= SONG_SURROUNDPAN; - break; - // S9C: IT Filter Mode - case 0x0C: - m_dwSongFlags &= ~SONG_MPTFILTERMODE; - break; - // S9D: MPT Filter Mode - case 0x0D: - m_dwSongFlags |= SONG_MPTFILTERMODE; - break; - // S9E: Go forward - case 0x0E: - pChn->dwFlags &= ~(CHN_PINGPONGFLAG); - break; - // S9F: Go backward (set position at the end for non-looping samples) - case 0x0F: - if ((!(pChn->dwFlags & CHN_LOOP)) && (!pChn->nPos) && (pChn->nLength)) - { - pChn->nPos = pChn->nLength - 1; - pChn->nPosLo = 0xFFFF; - } - pChn->dwFlags |= CHN_PINGPONGFLAG; - break; - } -} - - -void CSoundFile::ProcessMidiMacro(UINT nChn, LPCSTR pszMidiMacro, UINT param) -//--------------------------------------------------------------------------- -{ - MODCHANNEL *pChn = &Chn[nChn]; - DWORD dwMacro = (*((LPDWORD)pszMidiMacro)) & 0x7F5F7F5F; - // Not Internal Device ? - if (dwMacro != 0x30463046 && dwMacro != 0x31463046) - { - UINT pos = 0, nNib = 0, nBytes = 0; - DWORD dwMidiCode = 0, dwByteCode = 0; - while (pos+6 <= 32) - { - CHAR cData = pszMidiMacro[pos++]; - if (!cData) break; - if ((cData >= '0') && (cData <= '9')) { dwByteCode = (dwByteCode<<4) | (cData-'0'); nNib++; } else - if ((cData >= 'A') && (cData <= 'F')) { dwByteCode = (dwByteCode<<4) | (cData-'A'+10); nNib++; } else - if ((cData >= 'a') && (cData <= 'f')) { dwByteCode = (dwByteCode<<4) | (cData-'a'+10); nNib++; } else - if ((cData == 'z') || (cData == 'Z')) { dwByteCode = param & 0x7f; nNib = 2; } else - if ((cData == 'x') || (cData == 'X')) { dwByteCode = param & 0x70; nNib = 2; } else - if ((cData == 'y') || (cData == 'Y')) { dwByteCode = (param & 0x0f)<<3; nNib = 2; } else - if (nNib >= 2) - { - nNib = 0; - dwMidiCode |= dwByteCode << (nBytes*8); - dwByteCode = 0; - nBytes++; - if (nBytes >= 3) - { - UINT nMasterCh = (nChn < m_nChannels) ? nChn+1 : pChn->nMasterChn; - if ((nMasterCh) && (nMasterCh <= m_nChannels)) - { - UINT nPlug = ChnSettings[nMasterCh-1].nMixPlugin; - if ((nPlug) && (nPlug <= MAX_MIXPLUGINS)) - { - IMixPlugin *pPlugin = m_MixPlugins[nPlug-1].pMixPlugin; - if ((pPlugin) && (m_MixPlugins[nPlug-1].pMixState)) - { - pPlugin->MidiSend(dwMidiCode); - } - } - } - nBytes = 0; - dwMidiCode = 0; - } - } - - } - return; - } - // Internal device - pszMidiMacro += 4; - // Filter ? - if (pszMidiMacro[0] == '0') - { - CHAR cData1 = pszMidiMacro[2]; - DWORD dwParam = 0; - if ((cData1 == 'z') || (cData1 == 'Z')) - { - dwParam = param; - } else - { - CHAR cData2 = pszMidiMacro[3]; - if ((cData1 >= '0') && (cData1 <= '9')) dwParam += (cData1 - '0') << 4; else - if ((cData1 >= 'A') && (cData1 <= 'F')) dwParam += (cData1 - 'A' + 0x0A) << 4; - if ((cData2 >= '0') && (cData2 <= '9')) dwParam += (cData2 - '0'); else - if ((cData2 >= 'A') && (cData2 <= 'F')) dwParam += (cData2 - 'A' + 0x0A); - } - switch(pszMidiMacro[1]) - { - // F0.F0.00.xx: Set CutOff - case '0': - { - int oldcutoff = pChn->nCutOff; - if (dwParam < 0x80) pChn->nCutOff = dwParam; -#ifndef NO_FILTER - oldcutoff -= pChn->nCutOff; - - if (oldcutoff < 0) oldcutoff = -oldcutoff; - if ((pChn->nVolume > 0) || (oldcutoff < 0x10) - || (!(pChn->dwFlags & CHN_FILTER)) || (!(pChn->nLeftVol|pChn->nRightVol))) - SetupChannelFilter(pChn, (pChn->dwFlags & CHN_FILTER) ? FALSE : TRUE); -#endif // NO_FILTER - } - break; - - // F0.F0.01.xx: Set Resonance - case '1': - if (dwParam < 0x80) pChn->nResonance = dwParam; -#ifndef NO_FILTER - SetupChannelFilter(pChn, (pChn->dwFlags & CHN_FILTER) ? FALSE : TRUE); -#endif // NO_FILTER - - break; - } - - } -} - - -void CSoundFile::RetrigNote(UINT nChn, UINT param) -//------------------------------------------------ -{ - // Retrig: bit 8 is set if it's the new XM retrig - MODCHANNEL *pChn = &Chn[nChn]; - UINT nRetrigSpeed = param & 0x0F; - UINT nRetrigCount = pChn->nRetrigCount; - BOOL bDoRetrig = FALSE; - - if (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT)) - { - if (!nRetrigSpeed) nRetrigSpeed = 1; - if ((nRetrigCount) && (!(nRetrigCount % nRetrigSpeed))) bDoRetrig = TRUE; - nRetrigCount++; - } else - { - UINT realspeed = nRetrigSpeed; - if ((param & 0x100) && (pChn->nRowVolCmd == VOLCMD_VOLUME) && (pChn->nRowParam & 0xF0)) realspeed++; - if ((m_nTickCount) || (param & 0x100)) - { - if (!realspeed) realspeed = 1; - if ((!(param & 0x100)) && (m_nMusicSpeed) && (!(m_nTickCount % realspeed))) bDoRetrig = TRUE; - nRetrigCount++; - } else if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) nRetrigCount = 0; - if (nRetrigCount >= realspeed) - { - if ((m_nTickCount) || ((param & 0x100) && (!pChn->nRowNote))) bDoRetrig = TRUE; - } - } - if (bDoRetrig) - { - UINT dv = (param >> 4) & 0x0F; - if (dv) - { - int vol = pChn->nVolume; - if (retrigTable1[dv]) - vol = (vol * retrigTable1[dv]) >> 4; - else - vol += ((int)retrigTable2[dv]) << 2; - if (vol < 0) vol = 0; - if (vol > 256) vol = 256; - pChn->nVolume = vol; - pChn->dwFlags |= CHN_FASTVOLRAMP; - } - UINT nNote = pChn->nNewNote; - LONG nOldPeriod = pChn->nPeriod; - if ((nNote) && (nNote <= NOTE_MAX) && (pChn->nLength)) CheckNNA(nChn, 0, nNote, TRUE); - BOOL bResetEnv = FALSE; - if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) - { - if ((pChn->nRowInstr) && (param < 0x100)) { InstrumentChange(pChn, pChn->nRowInstr, FALSE, FALSE); bResetEnv = TRUE; } - if (param < 0x100) bResetEnv = TRUE; - } - NoteChange(nChn, nNote, FALSE, bResetEnv); - if ((m_nType & MOD_TYPE_IT) && (!pChn->nRowNote) && (nOldPeriod)) pChn->nPeriod = nOldPeriod; - if (!(m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT))) nRetrigCount = 0; - } - pChn->nRetrigCount = (BYTE)nRetrigCount; -} - - -void CSoundFile::DoFreqSlide(MODCHANNEL *pChn, LONG nFreqSlide) -//------------------------------------------------------------- -{ - // IT Linear slides - if (!pChn->nPeriod) return; - if ((m_dwSongFlags & SONG_LINEARSLIDES) && (!(m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)))) - { - if (nFreqSlide < 0) - { - UINT n = (- nFreqSlide) >> 2; - if (n > 255) n = 255; - pChn->nPeriod = _muldivr(pChn->nPeriod, LinearSlideDownTable[n], 65536); - } else - { - UINT n = (nFreqSlide) >> 2; - - if (n > 255) n = 255; - pChn->nPeriod = _muldivr(pChn->nPeriod, LinearSlideUpTable[n], 65536); - } - } else - { - pChn->nPeriod += nFreqSlide; - } - if (pChn->nPeriod < 1) - { - pChn->nPeriod = 1; - if (m_nType & MOD_TYPE_IT) - { - pChn->dwFlags |= CHN_NOTEFADE; - pChn->nFadeOutVol = 0; - } - } -} - - -void CSoundFile::NoteCut(UINT nChn, UINT nTick) -//--------------------------------------------- -{ - if (m_nTickCount == nTick) - { - MODCHANNEL *pChn = &Chn[nChn]; - // if (m_nInstruments) KeyOff(pChn); ? - pChn->nVolume = 0; - pChn->dwFlags |= CHN_FASTVOLRAMP; - } -} - - -void CSoundFile::KeyOff(UINT nChn) -//-------------------------------- -{ - MODCHANNEL *pChn = &Chn[nChn]; - BOOL bKeyOn = (pChn->dwFlags & CHN_KEYOFF) ? FALSE : TRUE; - pChn->dwFlags |= CHN_KEYOFF; - //if ((!pChn->pHeader) || (!(pChn->dwFlags & CHN_VOLENV))) - if ((pChn->pHeader) && (!(pChn->dwFlags & CHN_VOLENV))) - { - pChn->dwFlags |= CHN_NOTEFADE; - } - if (!pChn->nLength) return; - if ((pChn->dwFlags & CHN_SUSTAINLOOP) && (pChn->pInstrument) && (bKeyOn)) - { - MODINSTRUMENT *psmp = pChn->pInstrument; - if (psmp->uFlags & CHN_LOOP) - { - if (psmp->uFlags & CHN_PINGPONGLOOP) - pChn->dwFlags |= CHN_PINGPONGLOOP; - else - pChn->dwFlags &= ~(CHN_PINGPONGLOOP|CHN_PINGPONGFLAG); - pChn->dwFlags |= CHN_LOOP; - pChn->nLength = psmp->nLength; - pChn->nLoopStart = psmp->nLoopStart; - pChn->nLoopEnd = psmp->nLoopEnd; - if (pChn->nLength > pChn->nLoopEnd) pChn->nLength = pChn->nLoopEnd; - } else - { - pChn->dwFlags &= ~(CHN_LOOP|CHN_PINGPONGLOOP|CHN_PINGPONGFLAG); - pChn->nLength = psmp->nLength; - } - } - if (pChn->pHeader) - { - INSTRUMENTHEADER *penv = pChn->pHeader; - if (((penv->dwFlags & ENV_VOLLOOP) || (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))) && (penv->nFadeOut)) - pChn->dwFlags |= CHN_NOTEFADE; - } -} - - -////////////////////////////////////////////////////////// -// CSoundFile: Global Effects - - -void CSoundFile::SetSpeed(UINT param) -//----------------------------------- -{ - UINT max = (m_nType == MOD_TYPE_IT) ? 256 : 128; - // Modplug Tracker and Mod-Plugin don't do this check -#ifndef MODPLUG_TRACKER -#ifndef MODPLUG_FASTSOUNDLIB - // Big Hack!!! - if ((!param) || (param >= 0x80) || ((m_nType & (MOD_TYPE_MOD|MOD_TYPE_XM|MOD_TYPE_MT2)) && (param >= 0x1E))) - { - if (IsSongFinished(m_nCurrentPattern, m_nRow+1)) - { - GlobalFadeSong(1000); - } - } -#endif // MODPLUG_FASTSOUNDLIB -#endif // MODPLUG_TRACKER - if ((m_nType & MOD_TYPE_S3M) && (param > 0x80)) param -= 0x80; - if ((param) && (param <= max)) m_nMusicSpeed = param; -} - - -void CSoundFile::SetTempo(UINT param) -//----------------------------------- -{ - if (param < 0x20) - { - // Tempo Slide - if ((param & 0xF0) == 0x10) - { - m_nMusicTempo += (param & 0x0F) * 2; - if (m_nMusicTempo > 255) m_nMusicTempo = 255; - } else - { - m_nMusicTempo -= (param & 0x0F) * 2; - if ((LONG)m_nMusicTempo < 32) m_nMusicTempo = 32; - } - } else - { - m_nMusicTempo = param; - } -} - - -int CSoundFile::PatternLoop(MODCHANNEL *pChn, UINT param) -//------------------------------------------------------- -{ - if (param) - { - if (pChn->nPatternLoopCount) - { - pChn->nPatternLoopCount--; - if (!pChn->nPatternLoopCount) return -1; - } else - { - MODCHANNEL *p = Chn; - for (UINT i=0; i<m_nChannels; i++, p++) if (p != pChn) - { - // Loop already done - if (p->nPatternLoopCount) return -1; - } - pChn->nPatternLoopCount = param; - } - return pChn->nPatternLoop; - } else - { - pChn->nPatternLoop = m_nRow; - } - return -1; -} - - -void CSoundFile::GlobalVolSlide(UINT param) -//----------------------------------------- -{ - LONG nGlbSlide = 0; - if (param) m_nOldGlbVolSlide = param; else param = m_nOldGlbVolSlide; - if (((param & 0x0F) == 0x0F) && (param & 0xF0)) - { - if (m_dwSongFlags & SONG_FIRSTTICK) nGlbSlide = (param >> 4) * 2; - } else - if (((param & 0xF0) == 0xF0) && (param & 0x0F)) - { - if (m_dwSongFlags & SONG_FIRSTTICK) nGlbSlide = - (int)((param & 0x0F) * 2); - } else - { - if (!(m_dwSongFlags & SONG_FIRSTTICK)) - { - if (param & 0xF0) nGlbSlide = (int)((param & 0xF0) >> 4) * 2; - else nGlbSlide = -(int)((param & 0x0F) * 2); - } - } - if (nGlbSlide) - { - if (m_nType != MOD_TYPE_IT) nGlbSlide *= 2; - nGlbSlide += m_nGlobalVolume; - if (nGlbSlide < 0) nGlbSlide = 0; - if (nGlbSlide > 256) nGlbSlide = 256; - m_nGlobalVolume = nGlbSlide; - } -} - - -DWORD CSoundFile::IsSongFinished(UINT nStartOrder, UINT nStartRow) const -//---------------------------------------------------------------------- -{ - UINT nOrd; - - for (nOrd=nStartOrder; nOrd<MAX_ORDERS; nOrd++) - { - UINT nPat = Order[nOrd]; - if (nPat != 0xFE) - { - MODCOMMAND *p; - - if (nPat >= MAX_PATTERNS) break; - p = Patterns[nPat]; - if (p) - { - UINT len = PatternSize[nPat] * m_nChannels; - UINT pos = (nOrd == nStartOrder) ? nStartRow : 0; - pos *= m_nChannels; - while (pos < len) - { - UINT cmd; - if ((p[pos].note) || (p[pos].volcmd)) return 0; - cmd = p[pos].command; - if (cmd == CMD_MODCMDEX) - { - UINT cmdex = p[pos].param & 0xF0; - if ((!cmdex) || (cmdex == 0x60) || (cmdex == 0xE0) || (cmdex == 0xF0)) cmd = 0; - } - if ((cmd) && (cmd != CMD_SPEED) && (cmd != CMD_TEMPO)) return 0; - pos++; - } - } - } - } - return (nOrd < MAX_ORDERS) ? nOrd : MAX_ORDERS-1; -} - - -BOOL CSoundFile::IsValidBackwardJump(UINT nStartOrder, UINT nStartRow, UINT nJumpOrder, UINT nJumpRow) const -//---------------------------------------------------------------------------------------------------------- -{ - while ((nJumpOrder < MAX_PATTERNS) && (Order[nJumpOrder] == 0xFE)) nJumpOrder++; - if ((nStartOrder >= MAX_PATTERNS) || (nJumpOrder >= MAX_PATTERNS)) return FALSE; - // Treat only case with jumps in the same pattern - if (nJumpOrder > nStartOrder) return TRUE; - if ((nJumpOrder < nStartOrder) || (nJumpRow >= PatternSize[nStartOrder]) - || (!Patterns[nStartOrder]) || (nStartRow >= 256) || (nJumpRow >= 256)) return FALSE; - // See if the pattern is being played backward - BYTE row_hist[256]; - memset(row_hist, 0, sizeof(row_hist)); - UINT nRows = PatternSize[nStartOrder], row = nJumpRow; - if (nRows > 256) nRows = 256; - row_hist[nStartRow] = TRUE; - while ((row < 256) && (!row_hist[row])) - { - if (row >= nRows) return TRUE; - row_hist[row] = TRUE; - MODCOMMAND *p = Patterns[nStartOrder] + row * m_nChannels; - row++; - int breakrow = -1, posjump = 0; - for (UINT i=0; i<m_nChannels; i++, p++) - { - if (p->command == CMD_POSITIONJUMP) - { - if (p->param < nStartOrder) return FALSE; - if (p->param > nStartOrder) return TRUE; - posjump = TRUE; - } else - if (p->command == CMD_PATTERNBREAK) - { - breakrow = p->param; - } - } - if (breakrow >= 0) - { - if (!posjump) return TRUE; - row = breakrow; - } - if (row >= nRows) return TRUE; - } - return FALSE; -} - - -////////////////////////////////////////////////////// -// Note/Period/Frequency functions - -UINT CSoundFile::GetNoteFromPeriod(UINT period) const -//--------------------------------------------------- -{ - if (!period) return 0; - if (m_nType & (MOD_TYPE_MED|MOD_TYPE_MOD|MOD_TYPE_MTM|MOD_TYPE_669|MOD_TYPE_OKT|MOD_TYPE_AMF0)) - { - period >>= 2; - for (UINT i=0; i<6*12; i++) - { - if (period >= ProTrackerPeriodTable[i]) - { - if ((period != ProTrackerPeriodTable[i]) && (i)) - { - UINT p1 = ProTrackerPeriodTable[i-1]; - UINT p2 = ProTrackerPeriodTable[i]; - if (p1 - period < (period - p2)) return i+36; - } - return i+1+36; - } - } - return 6*12+36; - } else - { - for (UINT i=1; i<NOTE_MAX; i++) - { - LONG n = GetPeriodFromNote(i, 0, 0); - if ((n > 0) && (n <= (LONG)period)) return i; - } - return NOTE_MAX; - } -} - - - -UINT CSoundFile::GetPeriodFromNote(UINT note, int nFineTune, UINT nC4Speed) const -//------------------------------------------------------------------------------- -{ - if ((!note) || (note > 0xF0)) return 0; - if (m_nType & (MOD_TYPE_IT|MOD_TYPE_S3M|MOD_TYPE_STM|MOD_TYPE_MDL|MOD_TYPE_ULT|MOD_TYPE_WAV - |MOD_TYPE_FAR|MOD_TYPE_DMF|MOD_TYPE_PTM|MOD_TYPE_AMS|MOD_TYPE_DBM|MOD_TYPE_AMF|MOD_TYPE_PSM)) - { - note--; - if (m_dwSongFlags & SONG_LINEARSLIDES) - { - return (FreqS3MTable[note % 12] << 5) >> (note / 12); - } else - { - if (!nC4Speed) nC4Speed = 8363; - return _muldiv(8363, (FreqS3MTable[note % 12] << 5), nC4Speed << (note / 12)); - } - } else - if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) - { - if (note < 13) note = 13; - note -= 13; - if (m_dwSongFlags & SONG_LINEARSLIDES) - { - LONG l = ((NOTE_MAX - note) << 6) - (nFineTune / 2); - if (l < 1) l = 1; - return (UINT)l; - } else - { - int finetune = nFineTune; - UINT rnote = (note % 12) << 3; - UINT roct = note / 12; - int rfine = finetune / 16; - int i = rnote + rfine + 8; - if (i < 0) i = 0; - if (i >= 104) i = 103; - UINT per1 = XMPeriodTable[i]; - if ( finetune < 0 ) - { - rfine--; - finetune = -finetune; - } else rfine++; - i = rnote+rfine+8; - if (i < 0) i = 0; - if (i >= 104) i = 103; - UINT per2 = XMPeriodTable[i]; - rfine = finetune & 0x0F; - per1 *= 16-rfine; - per2 *= rfine; - return ((per1 + per2) << 1) >> roct; - } - } else - { - note--; - nFineTune = XM2MODFineTune(nFineTune); - if ((nFineTune) || (note < 36) || (note >= 36+6*12)) - return (ProTrackerTunedPeriods[nFineTune*12 + note % 12] << 5) >> (note / 12); - else - return (ProTrackerPeriodTable[note-36] << 2); - } -} - - -UINT CSoundFile::GetFreqFromPeriod(UINT period, UINT nC4Speed, int nPeriodFrac) const -//----------------------------------------------------------------------------------- -{ - if (!period) return 0; - if (m_nType & (MOD_TYPE_MED|MOD_TYPE_MOD|MOD_TYPE_MTM|MOD_TYPE_669|MOD_TYPE_OKT|MOD_TYPE_AMF0)) - { - return (3546895L*4) / period; - } else - if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) - { - if (m_dwSongFlags & SONG_LINEARSLIDES) - return XMLinearTable[period % 768] >> (period / 768); - else - return 8363 * 1712L / period; - } else - { - if (m_dwSongFlags & SONG_LINEARSLIDES) - { - if (!nC4Speed) nC4Speed = 8363; - return _muldiv(nC4Speed, 1712L << 8, (period << 8)+nPeriodFrac); - } else - { - return _muldiv(8363, 1712L << 8, (period << 8)+nPeriodFrac); - } - } -} - - diff --git a/lib/libmodplug/src/sndfile.cpp b/lib/libmodplug/src/sndfile.cpp deleted file mode 100644 index 66defb2983..0000000000 --- a/lib/libmodplug/src/sndfile.cpp +++ /dev/null @@ -1,1885 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque <olivierl@jps.net>, - * Adam Goode <adam@evdebs.org> (endian and char fixes for PPC) -*/ - -#include <math.h> //for GCCFIX -#include "libmodplug/stdafx.h" -#include "libmodplug/sndfile.h" - -#define MMCMP_SUPPORT - -#ifdef MMCMP_SUPPORT -extern BOOL MMCMP_Unpack(LPCBYTE *ppMemFile, LPDWORD pdwMemLength); -#endif - -// External decompressors -extern void AMSUnpack(const char *psrc, UINT inputlen, char *pdest, UINT dmax, char packcharacter); -extern WORD MDLReadBits(DWORD &bitbuf, UINT &bitnum, LPBYTE &ibuf, CHAR n); -extern int DMFUnpack(LPBYTE psample, LPBYTE ibuf, LPBYTE ibufmax, UINT maxlen); -extern DWORD ITReadBits(DWORD &bitbuf, UINT &bitnum, LPBYTE &ibuf, CHAR n); -extern void ITUnpack8Bit(signed char *pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dwMemLength, BOOL b215); -extern void ITUnpack16Bit(signed char *pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dwMemLength, BOOL b215); - - -#define MAX_PACK_TABLES 3 - - -// Compression table -static const signed char UnpackTable[MAX_PACK_TABLES][16] = -//-------------------------------------------- -{ - // CPU-generated dynamic table - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - // u-Law table - {0, 1, 2, 4, 8, 16, 32, 64, - -1, -2, -4, -8, -16, -32, -48, -64}, - // Linear table - {0, 1, 2, 3, 5, 7, 12, 19, - -1, -2, -3, -5, -7, -12, -19, -31} -}; - - -////////////////////////////////////////////////////////// -// CSoundFile - -CSoundFile::CSoundFile() -//---------------------- -{ - m_nType = MOD_TYPE_NONE; - m_dwSongFlags = 0; - m_nChannels = 0; - m_nMixChannels = 0; - m_nSamples = 0; - m_nInstruments = 0; - m_nPatternNames = 0; - m_lpszPatternNames = NULL; - m_lpszSongComments = NULL; - m_nFreqFactor = m_nTempoFactor = 128; - m_nMasterVolume = 128; - m_nMinPeriod = 0x20; - m_nMaxPeriod = 0x7FFF; - m_nRepeatCount = 0; - memset(Chn, 0, sizeof(Chn)); - memset(ChnMix, 0, sizeof(ChnMix)); - memset(Ins, 0, sizeof(Ins)); - memset(ChnSettings, 0, sizeof(ChnSettings)); - memset(Headers, 0, sizeof(Headers)); - memset(Order, 0xFF, sizeof(Order)); - memset(Patterns, 0, sizeof(Patterns)); - memset(m_szNames, 0, sizeof(m_szNames)); - memset(m_MixPlugins, 0, sizeof(m_MixPlugins)); -} - - -CSoundFile::~CSoundFile() -//----------------------- -{ - Destroy(); -} - - -BOOL CSoundFile::Create(LPCBYTE lpStream, DWORD dwMemLength) -//---------------------------------------------------------- -{ - int i; - - m_nType = MOD_TYPE_NONE; - m_dwSongFlags = 0; - m_nChannels = 0; - m_nMixChannels = 0; - m_nSamples = 0; - m_nInstruments = 0; - m_nFreqFactor = m_nTempoFactor = 128; - m_nMasterVolume = 128; - m_nDefaultGlobalVolume = 256; - m_nGlobalVolume = 256; - m_nOldGlbVolSlide = 0; - m_nDefaultSpeed = 6; - m_nDefaultTempo = 125; - m_nPatternDelay = 0; - m_nFrameDelay = 0; - m_nNextRow = 0; - m_nRow = 0; - m_nPattern = 0; - m_nCurrentPattern = 0; - m_nNextPattern = 0; - m_nRestartPos = 0; - m_nMinPeriod = 16; - m_nMaxPeriod = 32767; - m_nSongPreAmp = 0x30; - m_nPatternNames = 0; - m_nMaxOrderPosition = 0; - m_lpszPatternNames = NULL; - m_lpszSongComments = NULL; - memset(Ins, 0, sizeof(Ins)); - memset(ChnMix, 0, sizeof(ChnMix)); - memset(Chn, 0, sizeof(Chn)); - memset(Headers, 0, sizeof(Headers)); - memset(Order, 0xFF, sizeof(Order)); - memset(Patterns, 0, sizeof(Patterns)); - memset(m_szNames, 0, sizeof(m_szNames)); - memset(m_MixPlugins, 0, sizeof(m_MixPlugins)); - ResetMidiCfg(); - for (UINT npt=0; npt<MAX_PATTERNS; npt++) PatternSize[npt] = 64; - for (UINT nch=0; nch<MAX_BASECHANNELS; nch++) - { - ChnSettings[nch].nPan = 128; - ChnSettings[nch].nVolume = 64; - ChnSettings[nch].dwFlags = 0; - ChnSettings[nch].szName[0] = 0; - } - if (lpStream) - { -#ifdef MMCMP_SUPPORT - BOOL bMMCmp = MMCMP_Unpack(&lpStream, &dwMemLength); -#endif - if ((!ReadXM(lpStream, dwMemLength)) - && (!ReadS3M(lpStream, dwMemLength)) - && (!ReadIT(lpStream, dwMemLength)) - && (!ReadWav(lpStream, dwMemLength)) -#ifndef MODPLUG_BASIC_SUPPORT -/* Sequencer File Format Support */ - && (!ReadABC(lpStream, dwMemLength)) - && (!ReadMID(lpStream, dwMemLength)) - && (!ReadPAT(lpStream, dwMemLength)) - && (!ReadSTM(lpStream, dwMemLength)) - && (!ReadMed(lpStream, dwMemLength)) - && (!ReadMTM(lpStream, dwMemLength)) - && (!ReadMDL(lpStream, dwMemLength)) - && (!ReadDBM(lpStream, dwMemLength)) - && (!Read669(lpStream, dwMemLength)) - && (!ReadFAR(lpStream, dwMemLength)) - && (!ReadAMS(lpStream, dwMemLength)) - && (!ReadOKT(lpStream, dwMemLength)) - && (!ReadPTM(lpStream, dwMemLength)) - && (!ReadUlt(lpStream, dwMemLength)) - && (!ReadDMF(lpStream, dwMemLength)) - && (!ReadDSM(lpStream, dwMemLength)) - && (!ReadUMX(lpStream, dwMemLength)) - && (!ReadAMF(lpStream, dwMemLength)) - && (!ReadPSM(lpStream, dwMemLength)) - && (!ReadMT2(lpStream, dwMemLength)) -#endif // MODPLUG_BASIC_SUPPORT - && (!ReadMod(lpStream, dwMemLength))) m_nType = MOD_TYPE_NONE; -#ifdef MMCMP_SUPPORT - if (bMMCmp) - { - GlobalFreePtr(lpStream); - lpStream = NULL; - } -#endif - } - // Adjust song names - for (i=0; i<MAX_SAMPLES; i++) - { - LPSTR p = m_szNames[i]; - int j = 31; - p[j] = 0; - while ((j>=0) && (p[j]<=' ')) p[j--] = 0; - while (j>=0) - { - if (((BYTE)p[j]) < ' ') p[j] = ' '; - j--; - } - } - // Adjust channels - for (i=0; i<MAX_BASECHANNELS; i++) - { - if (ChnSettings[i].nVolume > 64) ChnSettings[i].nVolume = 64; - if (ChnSettings[i].nPan > 256) ChnSettings[i].nPan = 128; - Chn[i].nPan = ChnSettings[i].nPan; - Chn[i].nGlobalVol = ChnSettings[i].nVolume; - Chn[i].dwFlags = ChnSettings[i].dwFlags; - Chn[i].nVolume = 256; - Chn[i].nCutOff = 0x7F; - } - // Checking instruments - MODINSTRUMENT *pins = Ins; - - for (i=0; i<MAX_INSTRUMENTS; i++, pins++) - { - if (pins->pSample) - { - if (pins->nLoopEnd > pins->nLength) pins->nLoopEnd = pins->nLength; - if (pins->nLoopStart + 3 >= pins->nLoopEnd) - { - pins->nLoopStart = 0; - pins->nLoopEnd = 0; - } - if (pins->nSustainEnd > pins->nLength) pins->nSustainEnd = pins->nLength; - if (pins->nSustainStart + 3 >= pins->nSustainEnd) - { - pins->nSustainStart = 0; - pins->nSustainEnd = 0; - } - } else - { - pins->nLength = 0; - pins->nLoopStart = 0; - pins->nLoopEnd = 0; - pins->nSustainStart = 0; - pins->nSustainEnd = 0; - } - if (!pins->nLoopEnd) pins->uFlags &= ~CHN_LOOP; - if (!pins->nSustainEnd) pins->uFlags &= ~CHN_SUSTAINLOOP; - if (pins->nGlobalVol > 64) pins->nGlobalVol = 64; - } - // Check invalid instruments - while ((m_nInstruments > 0) && (!Headers[m_nInstruments])) - m_nInstruments--; - // Set default values - if (m_nSongPreAmp < 0x20) m_nSongPreAmp = 0x20; - if (m_nDefaultTempo < 32) m_nDefaultTempo = 125; - if (!m_nDefaultSpeed) m_nDefaultSpeed = 6; - m_nMusicSpeed = m_nDefaultSpeed; - m_nMusicTempo = m_nDefaultTempo; - m_nGlobalVolume = m_nDefaultGlobalVolume; - m_nNextPattern = 0; - m_nCurrentPattern = 0; - m_nPattern = 0; - m_nBufferCount = 0; - m_nTickCount = m_nMusicSpeed; - m_nNextRow = 0; - m_nRow = 0; - if ((m_nRestartPos >= MAX_ORDERS) || (Order[m_nRestartPos] >= MAX_PATTERNS)) m_nRestartPos = 0; - // Load plugins - if (gpMixPluginCreateProc) - { - for (UINT iPlug=0; iPlug<MAX_MIXPLUGINS; iPlug++) - { - if ((m_MixPlugins[iPlug].Info.dwPluginId1) - || (m_MixPlugins[iPlug].Info.dwPluginId2)) - { - gpMixPluginCreateProc(&m_MixPlugins[iPlug]); - if (m_MixPlugins[iPlug].pMixPlugin) - { - m_MixPlugins[iPlug].pMixPlugin->RestoreAllParameters(); - } - } - } - } - if (m_nType) - { - UINT maxpreamp = 0x10+(m_nChannels*8); - if (maxpreamp > 100) maxpreamp = 100; - if (m_nSongPreAmp > maxpreamp) m_nSongPreAmp = maxpreamp; - return TRUE; - } - return FALSE; -} - - -BOOL CSoundFile::Destroy() - -//------------------------ -{ - int i; - for (i=0; i<MAX_PATTERNS; i++) if (Patterns[i]) - { - FreePattern(Patterns[i]); - Patterns[i] = NULL; - } - m_nPatternNames = 0; - if (m_lpszPatternNames) - { - delete m_lpszPatternNames; - m_lpszPatternNames = NULL; - } - if (m_lpszSongComments) - { - delete m_lpszSongComments; - m_lpszSongComments = NULL; - } - for (i=1; i<MAX_SAMPLES; i++) - { - MODINSTRUMENT *pins = &Ins[i]; - if (pins->pSample) - { - FreeSample(pins->pSample); - pins->pSample = NULL; - } - } - for (i=0; i<MAX_INSTRUMENTS; i++) - { - if (Headers[i]) - { - delete Headers[i]; - Headers[i] = NULL; - } - } - for (i=0; i<MAX_MIXPLUGINS; i++) - { - if ((m_MixPlugins[i].nPluginDataSize) && (m_MixPlugins[i].pPluginData)) - { - m_MixPlugins[i].nPluginDataSize = 0; - delete [] (signed char*)m_MixPlugins[i].pPluginData; - m_MixPlugins[i].pPluginData = NULL; - } - m_MixPlugins[i].pMixState = NULL; - if (m_MixPlugins[i].pMixPlugin) - { - m_MixPlugins[i].pMixPlugin->Release(); - m_MixPlugins[i].pMixPlugin = NULL; - } - } - m_nType = MOD_TYPE_NONE; - m_nChannels = m_nSamples = m_nInstruments = 0; - return TRUE; -} - - -////////////////////////////////////////////////////////////////////////// -// Memory Allocation - -MODCOMMAND *CSoundFile::AllocatePattern(UINT rows, UINT nchns) -//------------------------------------------------------------ -{ - MODCOMMAND *p = new MODCOMMAND[rows*nchns]; - if (p) memset(p, 0, rows*nchns*sizeof(MODCOMMAND)); - return p; -} - - -void CSoundFile::FreePattern(LPVOID pat) -//-------------------------------------- -{ - if (pat) delete [] (signed char*)pat; -} - - -signed char* CSoundFile::AllocateSample(UINT nbytes) -//------------------------------------------- -{ - signed char * p = (signed char *)GlobalAllocPtr(GHND, (nbytes+39) & ~7); - if (p) p += 16; - return p; -} - - -void CSoundFile::FreeSample(LPVOID p) -//----------------------------------- -{ - if (p) - { - GlobalFreePtr(((LPSTR)p)-16); - } -} - - -////////////////////////////////////////////////////////////////////////// -// Misc functions - -void CSoundFile::ResetMidiCfg() -//----------------------------- -{ - memset(&m_MidiCfg, 0, sizeof(m_MidiCfg)); - lstrcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_START*32], "FF"); - lstrcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_STOP*32], "FC"); - lstrcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_NOTEON*32], "9c n v"); - lstrcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_NOTEOFF*32], "9c n 0"); - lstrcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_PROGRAM*32], "Cc p"); - lstrcpy(&m_MidiCfg.szMidiSFXExt[0], "F0F000z"); - for (int iz=0; iz<16; iz++) wsprintf(&m_MidiCfg.szMidiZXXExt[iz*32], "F0F001%02X", iz*8); -} - - -UINT CSoundFile::GetNumChannels() const -//------------------------------------- -{ - UINT n = 0; - for (UINT i=0; i<m_nChannels; i++) if (ChnSettings[i].nVolume) n++; - return n; -} - - -UINT CSoundFile::GetSongComments(LPSTR s, UINT len, UINT linesize) -//---------------------------------------------------------------- -{ - LPCSTR p = m_lpszSongComments; - if (!p) return 0; - UINT i = 2, ln=0; - if ((len) && (s)) s[0] = '\x0D'; - if ((len > 1) && (s)) s[1] = '\x0A'; - while ((*p) && (i+2 < len)) - { - BYTE c = (BYTE)*p++; - if ((c == 0x0D) || ((c == ' ') && (ln >= linesize))) - { if (s) { s[i++] = '\x0D'; s[i++] = '\x0A'; } else i+= 2; ln=0; } - else - if (c >= 0x20) { if (s) s[i++] = c; else i++; ln++; } - } - if (s) s[i] = 0; - return i; -} - - -UINT CSoundFile::GetRawSongComments(LPSTR s, UINT len, UINT linesize) -//------------------------------------------------------------------- -{ - LPCSTR p = m_lpszSongComments; - if (!p) return 0; - UINT i = 0, ln=0; - while ((*p) && (i < len-1)) - { - BYTE c = (BYTE)*p++; - if ((c == 0x0D) || (c == 0x0A)) - { - if (ln) - { - while (ln < linesize) { if (s) s[i] = ' '; i++; ln++; } - ln = 0; - } - } else - if ((c == ' ') && (!ln)) - { - UINT k=0; - while ((p[k]) && (p[k] >= ' ')) k++; - if (k <= linesize) - { - if (s) s[i] = ' '; - i++; - ln++; - } - } else - { - if (s) s[i] = c; - i++; - ln++; - if (ln == linesize) ln = 0; - } - } - if (ln) - { - while ((ln < linesize) && (i < len)) - { - if (s) s[i] = ' '; - i++; - ln++; - } - } - if (s) s[i] = 0; - return i; -} - - -BOOL CSoundFile::SetWaveConfig(UINT nRate,UINT nBits,UINT nChannels,BOOL bMMX) -//---------------------------------------------------------------------------- -{ - BOOL bReset = FALSE; - DWORD d = gdwSoundSetup & ~SNDMIX_ENABLEMMX; - if (bMMX) d |= SNDMIX_ENABLEMMX; - if ((gdwMixingFreq != nRate) || (gnBitsPerSample != nBits) || (gnChannels != nChannels) || (d != gdwSoundSetup)) bReset = TRUE; - gnChannels = nChannels; - gdwSoundSetup = d; - gdwMixingFreq = nRate; - gnBitsPerSample = nBits; - InitPlayer(bReset); - return TRUE; -} - - -BOOL CSoundFile::SetResamplingMode(UINT nMode) -//-------------------------------------------- -{ - DWORD d = gdwSoundSetup & ~(SNDMIX_NORESAMPLING|SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE); - switch(nMode) - { - case SRCMODE_NEAREST: d |= SNDMIX_NORESAMPLING; break; - case SRCMODE_LINEAR: break; - case SRCMODE_SPLINE: d |= SNDMIX_HQRESAMPLER; break; - case SRCMODE_POLYPHASE: d |= (SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE); break; - default: - return FALSE; - } - gdwSoundSetup = d; - return TRUE; -} - - -BOOL CSoundFile::SetMasterVolume(UINT nVol, BOOL bAdjustAGC) -//---------------------------------------------------------- -{ - if (nVol < 1) nVol = 1; - if (nVol > 0x200) nVol = 0x200; // x4 maximum - if ((nVol < m_nMasterVolume) && (nVol) && (gdwSoundSetup & SNDMIX_AGC) && (bAdjustAGC)) - { - gnAGC = gnAGC * m_nMasterVolume / nVol; - if (gnAGC > AGC_UNITY) gnAGC = AGC_UNITY; - } - m_nMasterVolume = nVol; - return TRUE; -} - - -void CSoundFile::SetAGC(BOOL b) -//----------------------------- -{ - if (b) - { - if (!(gdwSoundSetup & SNDMIX_AGC)) - { - gdwSoundSetup |= SNDMIX_AGC; - gnAGC = AGC_UNITY; - } - } else gdwSoundSetup &= ~SNDMIX_AGC; -} - - -UINT CSoundFile::GetNumPatterns() const -//------------------------------------- -{ - UINT i = 0; - while ((i < MAX_ORDERS) && (Order[i] < 0xFF)) i++; - return i; -} - - -UINT CSoundFile::GetNumInstruments() const -//---------------------------------------- -{ - UINT n=0; - for (UINT i=0; i<MAX_INSTRUMENTS; i++) if (Ins[i].pSample) n++; - return n; -} - - -UINT CSoundFile::GetMaxPosition() const -//------------------------------------- -{ - UINT max = 0; - UINT i = 0; - - while ((i < MAX_ORDERS) && (Order[i] != 0xFF)) - { - if (Order[i] < MAX_PATTERNS) max += PatternSize[Order[i]]; - i++; - } - return max; -} - - -UINT CSoundFile::GetCurrentPos() const -//------------------------------------ -{ - UINT pos = 0; - - for (UINT i=0; i<m_nCurrentPattern; i++) if (Order[i] < MAX_PATTERNS) - pos += PatternSize[Order[i]]; - return pos + m_nRow; -} - - -void CSoundFile::SetCurrentPos(UINT nPos) -//--------------------------------------- -{ - UINT i, nPattern; - - for (i=0; i<MAX_CHANNELS; i++) - { - Chn[i].nNote = Chn[i].nNewNote = Chn[i].nNewIns = 0; - Chn[i].pInstrument = NULL; - Chn[i].pHeader = NULL; - Chn[i].nPortamentoDest = 0; - Chn[i].nCommand = 0; - Chn[i].nPatternLoopCount = 0; - Chn[i].nPatternLoop = 0; - Chn[i].nFadeOutVol = 0; - Chn[i].dwFlags |= CHN_KEYOFF|CHN_NOTEFADE; - Chn[i].nTremorCount = 0; - } - if (!nPos) - { - for (i=0; i<MAX_CHANNELS; i++) - { - Chn[i].nPeriod = 0; - Chn[i].nPos = Chn[i].nLength = 0; - Chn[i].nLoopStart = 0; - Chn[i].nLoopEnd = 0; - Chn[i].nROfs = Chn[i].nLOfs = 0; - Chn[i].pSample = NULL; - Chn[i].pInstrument = NULL; - Chn[i].pHeader = NULL; - Chn[i].nCutOff = 0x7F; - Chn[i].nResonance = 0; - Chn[i].nLeftVol = Chn[i].nRightVol = 0; - Chn[i].nNewLeftVol = Chn[i].nNewRightVol = 0; - Chn[i].nLeftRamp = Chn[i].nRightRamp = 0; - Chn[i].nVolume = 256; - if (i < MAX_BASECHANNELS) - { - Chn[i].dwFlags = ChnSettings[i].dwFlags; - Chn[i].nPan = ChnSettings[i].nPan; - Chn[i].nGlobalVol = ChnSettings[i].nVolume; - } else - { - Chn[i].dwFlags = 0; - Chn[i].nPan = 128; - Chn[i].nGlobalVol = 64; - } - } - m_nGlobalVolume = m_nDefaultGlobalVolume; - m_nMusicSpeed = m_nDefaultSpeed; - m_nMusicTempo = m_nDefaultTempo; - } - m_dwSongFlags &= ~(SONG_PATTERNLOOP|SONG_CPUVERYHIGH|SONG_FADINGSONG|SONG_ENDREACHED|SONG_GLOBALFADE); - for (nPattern = 0; nPattern < MAX_ORDERS; nPattern++) - { - UINT ord = Order[nPattern]; - if (ord == 0xFE) continue; - if (ord == 0xFF) break; - if (ord < MAX_PATTERNS) - { - if (nPos < (UINT)PatternSize[ord]) break; - nPos -= PatternSize[ord]; - } - } - // Buggy position ? - if ((nPattern >= MAX_ORDERS) - || (Order[nPattern] >= MAX_PATTERNS) - || (nPos >= PatternSize[Order[nPattern]])) - { - nPos = 0; - nPattern = 0; - } - UINT nRow = nPos; - if ((nRow) && (Order[nPattern] < MAX_PATTERNS)) - { - MODCOMMAND *p = Patterns[Order[nPattern]]; - if ((p) && (nRow < PatternSize[Order[nPattern]])) - { - BOOL bOk = FALSE; - while ((!bOk) && (nRow > 0)) - { - UINT n = nRow * m_nChannels; - for (UINT k=0; k<m_nChannels; k++, n++) - { - if (p[n].note) - { - bOk = TRUE; - break; - } - } - if (!bOk) nRow--; - } - } - } - m_nNextPattern = nPattern; - m_nNextRow = nRow; - m_nTickCount = m_nMusicSpeed; - m_nBufferCount = 0; - m_nPatternDelay = 0; - m_nFrameDelay = 0; -} - - -void CSoundFile::SetCurrentOrder(UINT nPos) -//----------------------------------------- -{ - while ((nPos < MAX_ORDERS) && (Order[nPos] == 0xFE)) nPos++; - if ((nPos >= MAX_ORDERS) || (Order[nPos] >= MAX_PATTERNS)) return; - for (UINT j=0; j<MAX_CHANNELS; j++) - { - Chn[j].nPeriod = 0; - Chn[j].nNote = 0; - Chn[j].nPortamentoDest = 0; - Chn[j].nCommand = 0; - Chn[j].nPatternLoopCount = 0; - Chn[j].nPatternLoop = 0; - Chn[j].nTremorCount = 0; - } - if (!nPos) - { - SetCurrentPos(0); - } else - { - m_nNextPattern = nPos; - m_nRow = m_nNextRow = 0; - m_nPattern = 0; - m_nTickCount = m_nMusicSpeed; - m_nBufferCount = 0; - m_nTotalCount = 0; - m_nPatternDelay = 0; - m_nFrameDelay = 0; - } - m_dwSongFlags &= ~(SONG_PATTERNLOOP|SONG_CPUVERYHIGH|SONG_FADINGSONG|SONG_ENDREACHED|SONG_GLOBALFADE); -} - - -void CSoundFile::ResetChannels() -//------------------------------ -{ - m_dwSongFlags &= ~(SONG_CPUVERYHIGH|SONG_FADINGSONG|SONG_ENDREACHED|SONG_GLOBALFADE); - m_nBufferCount = 0; - for (UINT i=0; i<MAX_CHANNELS; i++) - { - Chn[i].nROfs = Chn[i].nLOfs = 0; - } -} - - -void CSoundFile::LoopPattern(int nPat, int nRow) -//---------------------------------------------- -{ - if ((nPat < 0) || (nPat >= MAX_PATTERNS) || (!Patterns[nPat])) - { - m_dwSongFlags &= ~SONG_PATTERNLOOP; - } else - { - if ((nRow < 0) || (nRow >= PatternSize[nPat])) nRow = 0; - m_nPattern = nPat; - m_nRow = m_nNextRow = nRow; - m_nTickCount = m_nMusicSpeed; - m_nPatternDelay = 0; - m_nFrameDelay = 0; - m_nBufferCount = 0; - m_dwSongFlags |= SONG_PATTERNLOOP; - } -} - - -UINT CSoundFile::GetBestSaveFormat() const -//---------------------------------------- -{ - if ((!m_nSamples) || (!m_nChannels)) return MOD_TYPE_NONE; - if (!m_nType) return MOD_TYPE_NONE; - if (m_nType & (MOD_TYPE_MOD|MOD_TYPE_OKT)) - return MOD_TYPE_MOD; - if (m_nType & (MOD_TYPE_S3M|MOD_TYPE_STM|MOD_TYPE_ULT|MOD_TYPE_FAR|MOD_TYPE_PTM)) - return MOD_TYPE_S3M; - if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MED|MOD_TYPE_MTM|MOD_TYPE_MT2)) - return MOD_TYPE_XM; - return MOD_TYPE_IT; -} - - -UINT CSoundFile::GetSaveFormats() const -//------------------------------------- -{ - UINT n = 0; - if ((!m_nSamples) || (!m_nChannels) || (m_nType == MOD_TYPE_NONE)) return 0; - switch(m_nType) - { - case MOD_TYPE_MOD: n = MOD_TYPE_MOD; - case MOD_TYPE_S3M: n = MOD_TYPE_S3M; - } - n |= MOD_TYPE_XM | MOD_TYPE_IT; - if (!m_nInstruments) - { - if (m_nSamples < 32) n |= MOD_TYPE_MOD; - n |= MOD_TYPE_S3M; - } - return n; -} - - -UINT CSoundFile::GetSampleName(UINT nSample,LPSTR s) const -//-------------------------------------------------------- -{ - char sztmp[40] = ""; // changed from CHAR - memcpy(sztmp, m_szNames[nSample],32); - sztmp[31] = 0; - if (s) strcpy(s, sztmp); - return strlen(sztmp); -} - - -UINT CSoundFile::GetInstrumentName(UINT nInstr,LPSTR s) const -//----------------------------------------------------------- -{ - char sztmp[40] = ""; // changed from CHAR - if ((nInstr >= MAX_INSTRUMENTS) || (!Headers[nInstr])) - { - if (s) *s = 0; - return 0; - } - INSTRUMENTHEADER *penv = Headers[nInstr]; - memcpy(sztmp, penv->name, 32); - sztmp[31] = 0; - if (s) strcpy(s, sztmp); - return strlen(sztmp); -} - - -#ifndef NO_PACKING -UINT CSoundFile::PackSample(int &sample, int next) -//------------------------------------------------ -{ - UINT i = 0; - int delta = next - sample; - if (delta >= 0) - { - for (i=0; i<7; i++) if (delta <= (int)CompressionTable[i+1]) break; - } else - { - for (i=8; i<15; i++) if (delta >= (int)CompressionTable[i+1]) break; - } - sample += (int)CompressionTable[i]; - return i; -} - - -BOOL CSoundFile::CanPackSample(LPSTR pSample, UINT nLen, UINT nPacking, BYTE *result) -//----------------------------------------------------------------------------------- -{ - int pos, old, oldpos, besttable = 0; - DWORD dwErr, dwTotal, dwResult; - int i,j; - - if (result) *result = 0; - if ((!pSample) || (nLen < 1024)) return FALSE; - // Try packing with different tables - dwResult = 0; - for (j=1; j<MAX_PACK_TABLES; j++) - { - memcpy(CompressionTable, UnpackTable[j], 16); - dwErr = 0; - dwTotal = 1; - old = pos = oldpos = 0; - for (i=0; i<(int)nLen; i++) - { - int s = (int)pSample[i]; - PackSample(pos, s); - dwErr += abs(pos - oldpos); - dwTotal += abs(s - old); - old = s; - oldpos = pos; - } - dwErr = _muldiv(dwErr, 100, dwTotal); - if (dwErr >= dwResult) - { - dwResult = dwErr; - besttable = j; - } - } - memcpy(CompressionTable, UnpackTable[besttable], 16); - if (result) - { - if (dwResult > 100) *result = 100; else *result = (BYTE)dwResult; - } - return (dwResult >= nPacking) ? TRUE : FALSE; -} -#endif // NO_PACKING - -#ifndef MODPLUG_NO_FILESAVE - -UINT CSoundFile::WriteSample(FILE *f, MODINSTRUMENT *pins, UINT nFlags, UINT nMaxLen) -//----------------------------------------------------------------------------------- -{ - UINT len = 0, bufcount; - signed char buffer[4096]; - signed char *pSample = (signed char *)pins->pSample; - UINT nLen = pins->nLength; - - if ((nMaxLen) && (nLen > nMaxLen)) nLen = nMaxLen; - if ((!pSample) || (f == NULL) || (!nLen)) return 0; - switch(nFlags) - { -#ifndef NO_PACKING - // 3: 4-bit ADPCM data - case RS_ADPCM4: - { - int pos; - len = (nLen + 1) / 2; - fwrite(CompressionTable, 16, 1, f); - bufcount = 0; - pos = 0; - for (UINT j=0; j<len; j++) - { - BYTE b; - // Sample #1 - b = PackSample(pos, (int)pSample[j*2]); - // Sample #2 - b |= PackSample(pos, (int)pSample[j*2+1]) << 4; - buffer[bufcount++] = (signed char)b; - if (bufcount >= sizeof(buffer)) - { - fwrite(buffer, 1, bufcount, f); - bufcount = 0; - } - } - if (bufcount) fwrite(buffer, 1, bufcount, f); - len += 16; - } - break; -#endif // NO_PACKING - - // 16-bit samples - case RS_PCM16U: - case RS_PCM16D: - case RS_PCM16S: - { - int16_t *p = (int16_t *)pSample; - int s_old = 0, s_ofs; - len = nLen * 2; - bufcount = 0; - s_ofs = (nFlags == RS_PCM16U) ? 0x8000 : 0; - for (UINT j=0; j<nLen; j++) - { - int s_new = *p; - p++; - if (pins->uFlags & CHN_STEREO) - { - s_new = (s_new + (*p) + 1) >> 1; - p++; - } - if (nFlags == RS_PCM16D) - { - int16_t temp = bswapLE16((int16_t)(s_new - s_old)); - *((int16_t*)(&buffer[bufcount])) = temp; - s_old = s_new; - } else - { - int16_t temp = bswapLE16((int16_t)(s_new + s_ofs)); - *((int16_t *)(&buffer[bufcount])) = temp; - } - bufcount += 2; - if (bufcount >= sizeof(buffer) - 1) - { - fwrite(buffer, 1, bufcount, f); - bufcount = 0; - } - } - if (bufcount) fwrite(buffer, 1, bufcount, f); - } - break; - - - // 8-bit Stereo samples (not interleaved) - case RS_STPCM8S: - case RS_STPCM8U: - case RS_STPCM8D: - { - int s_ofs = (nFlags == RS_STPCM8U) ? 0x80 : 0; - for (UINT iCh=0; iCh<2; iCh++) - { - signed char *p = pSample + iCh; - int s_old = 0; - - bufcount = 0; - for (UINT j=0; j<nLen; j++) - { - int s_new = *p; - p += 2; - if (nFlags == RS_STPCM8D) - { - buffer[bufcount++] = (signed char)(s_new - s_old); - s_old = s_new; - } else - { - buffer[bufcount++] = (signed char)(s_new + s_ofs); - } - if (bufcount >= sizeof(buffer)) - { - fwrite(buffer, 1, bufcount, f); - bufcount = 0; - } - } - if (bufcount) fwrite(buffer, 1, bufcount, f); - } - } - len = nLen * 2; - break; - - // 16-bit Stereo samples (not interleaved) - case RS_STPCM16S: - case RS_STPCM16U: - case RS_STPCM16D: - { - int s_ofs = (nFlags == RS_STPCM16U) ? 0x8000 : 0; - for (UINT iCh=0; iCh<2; iCh++) - { - int16_t *p = ((int16_t *)pSample) + iCh; - int s_old = 0; - - bufcount = 0; - for (UINT j=0; j<nLen; j++) - { - int s_new = *p; - p += 2; - if (nFlags == RS_STPCM16D) - { - int16_t temp = bswapLE16((int16_t)(s_new - s_old)); - *((int16_t *)(&buffer[bufcount])) = temp; - s_old = s_new; - } else - { - int16_t temp = bswapLE16((int16_t)(s_new - s_ofs)); - *((int16_t*)(&buffer[bufcount])) = temp; - } - bufcount += 2; - if (bufcount >= sizeof(buffer)) - { - fwrite(buffer, 1, bufcount, f); - bufcount = 0; - } - } - if (bufcount) fwrite(buffer, 1, bufcount, f); - } - } - len = nLen*4; - break; - - // Stereo signed interleaved - case RS_STIPCM8S: - case RS_STIPCM16S: - len = nLen * 2; - if (nFlags == RS_STIPCM16S) len *= 2; - fwrite(pSample, 1, len, f); - break; - - // Default: assume 8-bit PCM data - default: - len = nLen; - bufcount = 0; - { - signed char *p = pSample; - int sinc = (pins->uFlags & CHN_16BIT) ? 2 : 1; - int s_old = 0, s_ofs = (nFlags == RS_PCM8U) ? 0x80 : 0; - if (pins->uFlags & CHN_16BIT) p++; - for (UINT j=0; j<len; j++) - { - int s_new = (signed char)(*p); - p += sinc; - if (pins->uFlags & CHN_STEREO) - { - s_new = (s_new + ((int)*p) + 1) >> 1; - p += sinc; - } - if (nFlags == RS_PCM8D) - { - buffer[bufcount++] = (signed char)(s_new - s_old); - s_old = s_new; - } else - { - buffer[bufcount++] = (signed char)(s_new + s_ofs); - } - if (bufcount >= sizeof(buffer)) - { - fwrite(buffer, 1, bufcount, f); - bufcount = 0; - } - } - if (bufcount) fwrite(buffer, 1, bufcount, f); - } - } - return len; -} - -#endif // MODPLUG_NO_FILESAVE - - -// Flags: -// 0 = signed 8-bit PCM data (default) -// 1 = unsigned 8-bit PCM data -// 2 = 8-bit ADPCM data with linear table -// 3 = 4-bit ADPCM data -// 4 = 16-bit ADPCM data with linear table -// 5 = signed 16-bit PCM data -// 6 = unsigned 16-bit PCM data - - -UINT CSoundFile::ReadSample(MODINSTRUMENT *pIns, UINT nFlags, LPCSTR lpMemFile, DWORD dwMemLength) -//------------------------------------------------------------------------------ -{ - UINT len = 0, mem = pIns->nLength+6; - - // Disable >2Gb samples,(preventing buffer overflow in AllocateSample) - if ((!pIns) || ((int)pIns->nLength < 4) || (!lpMemFile)) return 0; - if (pIns->nLength > MAX_SAMPLE_LENGTH) pIns->nLength = MAX_SAMPLE_LENGTH; - pIns->uFlags &= ~(CHN_16BIT|CHN_STEREO); - if (nFlags & RSF_16BIT) - { - mem *= 2; - pIns->uFlags |= CHN_16BIT; - } - if (nFlags & RSF_STEREO) - { - mem *= 2; - pIns->uFlags |= CHN_STEREO; - } - if ((pIns->pSample = AllocateSample(mem)) == NULL) - { - pIns->nLength = 0; - return 0; - } - switch(nFlags) - { - // 1: 8-bit unsigned PCM data - case RS_PCM8U: - { - len = pIns->nLength; - if (len > dwMemLength) len = pIns->nLength = dwMemLength; - signed char *pSample = pIns->pSample; - for (UINT j=0; j<len; j++) pSample[j] = (signed char)(lpMemFile[j] - 0x80); - } - break; - - // 2: 8-bit ADPCM data with linear table - case RS_PCM8D: - { - len = pIns->nLength; - if (len > dwMemLength) break; - signed char *pSample = pIns->pSample; - const signed char *p = (const signed char *)lpMemFile; - int delta = 0; - - for (UINT j=0; j<len; j++) - { - delta += p[j]; - *pSample++ = (signed char)delta; - } - } - break; - - // 3: 4-bit ADPCM data - case RS_ADPCM4: - { - len = (pIns->nLength + 1) / 2; - if (len > dwMemLength - 16) break; - memcpy(CompressionTable, lpMemFile, 16); - lpMemFile += 16; - signed char *pSample = pIns->pSample; - signed char delta = 0; - for (UINT j=0; j<len; j++) - { - BYTE b0 = (BYTE)lpMemFile[j]; - BYTE b1 = (BYTE)(lpMemFile[j] >> 4); - delta = (signed char)GetDeltaValue((int)delta, b0); - pSample[0] = delta; - delta = (signed char)GetDeltaValue((int)delta, b1); - pSample[1] = delta; - pSample += 2; - } - len += 16; - } - break; - - // 4: 16-bit ADPCM data with linear table - case RS_PCM16D: - { - len = pIns->nLength * 2; - if (len > dwMemLength) break; - int16_t *pSample = (int16_t *)pIns->pSample; - int16_t *p = (int16_t *)lpMemFile; - int delta16 = 0; - for (UINT j=0; j<len; j+=2) - { - delta16 += bswapLE16(*p++); - *pSample++ = (int16_t )delta16; - } - } - break; - - // 5: 16-bit signed PCM data - case RS_PCM16S: - { - len = pIns->nLength * 2; - if (len <= dwMemLength) memcpy(pIns->pSample, lpMemFile, len); - int16_t *pSample = (int16_t *)pIns->pSample; - for (UINT j=0; j<len; j+=2) - { - int16_t rawSample = *pSample; - *pSample++ = bswapLE16(rawSample); - } - } - break; - - // 16-bit signed mono PCM motorola byte order - case RS_PCM16M: - len = pIns->nLength * 2; - if (len > dwMemLength) len = dwMemLength & ~1; - if (len > 1) - { - signed char *pSample = (signed char *)pIns->pSample; - signed char *pSrc = (signed char *)lpMemFile; - for (UINT j=0; j<len; j+=2) - { - // pSample[j] = pSrc[j+1]; - // pSample[j+1] = pSrc[j]; - *((uint16_t *)(pSample+j)) = bswapBE16(*((uint16_t *)(pSrc+j))); - } - } - break; - - // 6: 16-bit unsigned PCM data - case RS_PCM16U: - { - len = pIns->nLength * 2; - if (len > dwMemLength) break; - int16_t *pSample = (int16_t *)pIns->pSample; - int16_t *pSrc = (int16_t *)lpMemFile; - for (UINT j=0; j<len; j+=2) *pSample++ = bswapLE16(*(pSrc++)) - 0x8000; - } - break; - - // 16-bit signed stereo big endian - case RS_STPCM16M: - len = pIns->nLength * 2; - if (len*2 <= dwMemLength) - { - signed char *pSample = (signed char *)pIns->pSample; - signed char *pSrc = (signed char *)lpMemFile; - for (UINT j=0; j<len; j+=2) - { - // pSample[j*2] = pSrc[j+1]; - // pSample[j*2+1] = pSrc[j]; - // pSample[j*2+2] = pSrc[j+1+len]; - // pSample[j*2+3] = pSrc[j+len]; - *((uint16_t *)(pSample+j*2)) = bswapBE16(*((uint16_t *)(pSrc+j))); - *((uint16_t *)(pSample+j*2+2)) = bswapBE16(*((uint16_t *)(pSrc+j+len))); - } - len *= 2; - } - break; - - // 8-bit stereo samples - case RS_STPCM8S: - case RS_STPCM8U: - case RS_STPCM8D: - { - int iadd_l = 0, iadd_r = 0; - if (nFlags == RS_STPCM8U) { iadd_l = iadd_r = -128; } - len = pIns->nLength; - signed char *psrc = (signed char *)lpMemFile; - signed char *pSample = (signed char *)pIns->pSample; - if (len*2 > dwMemLength) break; - for (UINT j=0; j<len; j++) - { - pSample[j*2] = (signed char)(psrc[0] + iadd_l); - pSample[j*2+1] = (signed char)(psrc[len] + iadd_r); - psrc++; - if (nFlags == RS_STPCM8D) - { - iadd_l = pSample[j*2]; - iadd_r = pSample[j*2+1]; - } - } - len *= 2; - } - break; - - // 16-bit stereo samples - case RS_STPCM16S: - case RS_STPCM16U: - case RS_STPCM16D: - { - int iadd_l = 0, iadd_r = 0; - if (nFlags == RS_STPCM16U) { iadd_l = iadd_r = -0x8000; } - len = pIns->nLength; - int16_t *psrc = (int16_t *)lpMemFile; - int16_t *pSample = (int16_t *)pIns->pSample; - if (len*4 > dwMemLength) break; - for (UINT j=0; j<len; j++) - { - pSample[j*2] = (int16_t) (bswapLE16(psrc[0]) + iadd_l); - pSample[j*2+1] = (int16_t) (bswapLE16(psrc[len]) + iadd_r); - psrc++; - if (nFlags == RS_STPCM16D) - { - iadd_l = pSample[j*2]; - iadd_r = pSample[j*2+1]; - } - } - len *= 4; - } - break; - - // IT 2.14 compressed samples - case RS_IT2148: - case RS_IT21416: - case RS_IT2158: - case RS_IT21516: - len = dwMemLength; - if (len < 4) break; - if ((nFlags == RS_IT2148) || (nFlags == RS_IT2158)) - ITUnpack8Bit(pIns->pSample, pIns->nLength, (LPBYTE)lpMemFile, dwMemLength, (nFlags == RS_IT2158)); - else - ITUnpack16Bit(pIns->pSample, pIns->nLength, (LPBYTE)lpMemFile, dwMemLength, (nFlags == RS_IT21516)); - break; - -#ifndef MODPLUG_BASIC_SUPPORT -#ifndef MODPLUG_FASTSOUNDLIB - // 8-bit interleaved stereo samples - case RS_STIPCM8S: - case RS_STIPCM8U: - { - int iadd = 0; - if (nFlags == RS_STIPCM8U) { iadd = -0x80; } - len = pIns->nLength; - if (len*2 > dwMemLength) len = dwMemLength >> 1; - LPBYTE psrc = (LPBYTE)lpMemFile; - LPBYTE pSample = (LPBYTE)pIns->pSample; - for (UINT j=0; j<len; j++) - { - pSample[j*2] = (signed char)(psrc[0] + iadd); - pSample[j*2+1] = (signed char)(psrc[1] + iadd); - psrc+=2; - } - len *= 2; - } - break; - - // 16-bit interleaved stereo samples - case RS_STIPCM16S: - case RS_STIPCM16U: - { - int iadd = 0; - if (nFlags == RS_STIPCM16U) iadd = -32768; - len = pIns->nLength; - if (len*4 > dwMemLength) len = dwMemLength >> 2; - int16_t *psrc = (int16_t *)lpMemFile; - int16_t *pSample = (int16_t *)pIns->pSample; - for (UINT j=0; j<len; j++) - { - pSample[j*2] = (int16_t)(bswapLE16(psrc[0]) + iadd); - pSample[j*2+1] = (int16_t)(bswapLE16(psrc[1]) + iadd); - psrc += 2; - } - len *= 4; - } - break; - - // AMS compressed samples - case RS_AMS8: - case RS_AMS16: - len = 9; - if (dwMemLength > 9) - { - const char *psrc = lpMemFile; - char packcharacter = lpMemFile[8], *pdest = (char *)pIns->pSample; - len += bswapLE32(*((LPDWORD)(lpMemFile+4))); - if (len > dwMemLength) len = dwMemLength; - UINT dmax = pIns->nLength; - if (pIns->uFlags & CHN_16BIT) dmax <<= 1; - AMSUnpack(psrc+9, len-9, pdest, dmax, packcharacter); - } - break; - - // PTM 8bit delta to 16-bit sample - case RS_PTM8DTO16: - { - len = pIns->nLength * 2; - if (len > dwMemLength) break; - int8_t *pSample = (int8_t *)pIns->pSample; - int8_t delta8 = 0; - for (UINT j=0; j<len; j++) - { - delta8 += lpMemFile[j]; - *pSample++ = delta8; - } - uint16_t *pSampleW = (uint16_t *)pIns->pSample; - for (UINT j=0; j<len; j+=2) // swaparoni! - { - uint16_t rawSample = *pSampleW; - *pSampleW++ = bswapLE16(rawSample); - } - } - break; - - // Huffman MDL compressed samples - case RS_MDL8: - case RS_MDL16: - len = dwMemLength; - if (len >= 4) - { - LPBYTE pSample = (LPBYTE)pIns->pSample; - LPBYTE ibuf = (LPBYTE)lpMemFile; - DWORD bitbuf = bswapLE32(*((DWORD *)ibuf)); - UINT bitnum = 32; - BYTE dlt = 0, lowbyte = 0; - ibuf += 4; - for (UINT j=0; j<pIns->nLength; j++) - { - BYTE hibyte; - BYTE sign; - if (nFlags == RS_MDL16) lowbyte = (BYTE)MDLReadBits(bitbuf, bitnum, ibuf, 8); - sign = (BYTE)MDLReadBits(bitbuf, bitnum, ibuf, 1); - if (MDLReadBits(bitbuf, bitnum, ibuf, 1)) - { - hibyte = (BYTE)MDLReadBits(bitbuf, bitnum, ibuf, 3); - } else - { - hibyte = 8; - while (!MDLReadBits(bitbuf, bitnum, ibuf, 1)) hibyte += 0x10; - hibyte += MDLReadBits(bitbuf, bitnum, ibuf, 4); - } - if (sign) hibyte = ~hibyte; - dlt += hibyte; - if (nFlags != RS_MDL16) - pSample[j] = dlt; - else - { - pSample[j<<1] = lowbyte; - pSample[(j<<1)+1] = dlt; - } - } - } - break; - - case RS_DMF8: - case RS_DMF16: - len = dwMemLength; - if (len >= 4) - { - UINT maxlen = pIns->nLength; - if (pIns->uFlags & CHN_16BIT) maxlen <<= 1; - LPBYTE ibuf = (LPBYTE)lpMemFile, ibufmax = (LPBYTE)(lpMemFile+dwMemLength); - len = DMFUnpack((LPBYTE)pIns->pSample, ibuf, ibufmax, maxlen); - } - break; - -#ifdef MODPLUG_TRACKER - // PCM 24-bit signed -> load sample, and normalize it to 16-bit - case RS_PCM24S: - case RS_PCM32S: - len = pIns->nLength * 3; - if (nFlags == RS_PCM32S) len += pIns->nLength; - if (len > dwMemLength) break; - if (len > 4*8) - { - UINT slsize = (nFlags == RS_PCM32S) ? 4 : 3; - LPBYTE pSrc = (LPBYTE)lpMemFile; - LONG max = 255; - if (nFlags == RS_PCM32S) pSrc++; - for (UINT j=0; j<len; j+=slsize) - { - LONG l = ((((pSrc[j+2] << 8) + pSrc[j+1]) << 8) + pSrc[j]) << 8; - l /= 256; - if (l > max) max = l; - if (-l > max) max = -l; - } - max = (max / 128) + 1; - int16_t *pDest = (int16_t *)pIns->pSample; - for (UINT k=0; k<len; k+=slsize) - { - LONG l = ((((pSrc[k+2] << 8) + pSrc[k+1]) << 8) + pSrc[k]) << 8; - *pDest++ = (uint16_t)(l / max); - } - } - break; - - // Stereo PCM 24-bit signed -> load sample, and normalize it to 16-bit - case RS_STIPCM24S: - case RS_STIPCM32S: - len = pIns->nLength * 6; - if (nFlags == RS_STIPCM32S) len += pIns->nLength * 2; - if (len > dwMemLength) break; - if (len > 8*8) - { - UINT slsize = (nFlags == RS_STIPCM32S) ? 4 : 3; - LPBYTE pSrc = (LPBYTE)lpMemFile; - LONG max = 255; - if (nFlags == RS_STIPCM32S) pSrc++; - for (UINT j=0; j<len; j+=slsize) - { - LONG l = ((((pSrc[j+2] << 8) + pSrc[j+1]) << 8) + pSrc[j]) << 8; - l /= 256; - if (l > max) max = l; - if (-l > max) max = -l; - } - max = (max / 128) + 1; - int16_t *pDest = (int16_t *)pIns->pSample; - for (UINT k=0; k<len; k+=slsize) - { - LONG lr = ((((pSrc[k+2] << 8) + pSrc[k+1]) << 8) + pSrc[k]) << 8; - k += slsize; - LONG ll = ((((pSrc[k+2] << 8) + pSrc[k+1]) << 8) + pSrc[k]) << 8; - pDest[0] = (int16_t)ll; - pDest[1] = (int16_t)lr; - pDest += 2; - } - } - break; - - // 16-bit signed big endian interleaved stereo - case RS_STIPCM16M: - { - len = pIns->nLength; - if (len*4 > dwMemLength) len = dwMemLength >> 2; - LPCBYTE psrc = (LPCBYTE)lpMemFile; - int16_t *pSample = (int16_t *)pIns->pSample; - for (UINT j=0; j<len; j++) - { - pSample[j*2] = (int16_t)(((UINT)psrc[0] << 8) | (psrc[1])); - pSample[j*2+1] = (int16_t)(((UINT)psrc[2] << 8) | (psrc[3])); - psrc += 4; - } - len *= 4; - } - break; - -#endif // MODPLUG_TRACKER -#endif // !MODPLUG_FASTSOUNDLIB -#endif // !MODPLUG_BASIC_SUPPORT - - // Default: 8-bit signed PCM data - default: - len = pIns->nLength; - if (len > dwMemLength) len = pIns->nLength = dwMemLength; - memcpy(pIns->pSample, lpMemFile, len); - } - if (len > dwMemLength) - { - if (pIns->pSample) - { - pIns->nLength = 0; - FreeSample(pIns->pSample); - pIns->pSample = NULL; - } - return 0; - } - AdjustSampleLoop(pIns); - return len; -} - - -void CSoundFile::AdjustSampleLoop(MODINSTRUMENT *pIns) -//---------------------------------------------------- -{ - if (!pIns->pSample) return; - if (pIns->nLoopEnd > pIns->nLength) pIns->nLoopEnd = pIns->nLength; - if (pIns->nLoopStart+2 >= pIns->nLoopEnd) - { - pIns->nLoopStart = pIns->nLoopEnd = 0; - pIns->uFlags &= ~CHN_LOOP; - } - UINT len = pIns->nLength; - if (pIns->uFlags & CHN_16BIT) - { - int16_t *pSample = (int16_t *)pIns->pSample; - // Adjust end of sample - if (pIns->uFlags & CHN_STEREO) - { - pSample[len*2+6] = pSample[len*2+4] = pSample[len*2+2] = pSample[len*2] = 0; - pSample[len*2+7] = pSample[len*2+5] = pSample[len*2+3] = pSample[len*2+1] = 0; - } else - { - pSample[len+4] = pSample[len+3] = pSample[len+2] = pSample[len+1] = pSample[len] = 0; - } - if ((pIns->uFlags & (CHN_LOOP|CHN_PINGPONGLOOP|CHN_STEREO)) == CHN_LOOP) - { - // Fix bad loops - if ((pIns->nLoopEnd+3 >= pIns->nLength) || (m_nType & MOD_TYPE_S3M)) - { - pSample[pIns->nLoopEnd] = pSample[pIns->nLoopStart]; - pSample[pIns->nLoopEnd+1] = pSample[pIns->nLoopStart+1]; - pSample[pIns->nLoopEnd+2] = pSample[pIns->nLoopStart+2]; - pSample[pIns->nLoopEnd+3] = pSample[pIns->nLoopStart+3]; - pSample[pIns->nLoopEnd+4] = pSample[pIns->nLoopStart+4]; - } - } - } else - { - signed char *pSample = pIns->pSample; -#ifndef MODPLUG_FASTSOUNDLIB - // Crappy samples (except chiptunes) ? - if ((pIns->nLength > 0x100) && (m_nType & (MOD_TYPE_MOD|MOD_TYPE_S3M)) - && (!(pIns->uFlags & CHN_STEREO))) - { - int smpend = pSample[pIns->nLength-1], smpfix = 0, kscan; - for (kscan=pIns->nLength-1; kscan>0; kscan--) - { - smpfix = pSample[kscan-1]; - if (smpfix != smpend) break; - } - int delta = smpfix - smpend; - if (((!(pIns->uFlags & CHN_LOOP)) || (kscan > (int)pIns->nLoopEnd)) - && ((delta < -8) || (delta > 8))) - { - while (kscan<(int)pIns->nLength) - { - if (!(kscan & 7)) - { - if (smpfix > 0) smpfix--; - if (smpfix < 0) smpfix++; - } - pSample[kscan] = (signed char)smpfix; - kscan++; - } - } - } -#endif - // Adjust end of sample - if (pIns->uFlags & CHN_STEREO) - { - pSample[len*2+6] = pSample[len*2+4] = pSample[len*2+2] = pSample[len*2] = 0; - pSample[len*2+7] = pSample[len*2+5] = pSample[len*2+3] = pSample[len*2+1] = 0; - - } else - { - pSample[len+4] = pSample[len+3] = pSample[len+2] = pSample[len+1] = pSample[len] = 0; - } - if ((pIns->uFlags & (CHN_LOOP|CHN_PINGPONGLOOP|CHN_STEREO)) == CHN_LOOP) - { - if ((pIns->nLoopEnd+3 >= pIns->nLength) || (m_nType & (MOD_TYPE_MOD|MOD_TYPE_S3M))) - { - pSample[pIns->nLoopEnd] = pSample[pIns->nLoopStart]; - pSample[pIns->nLoopEnd+1] = pSample[pIns->nLoopStart+1]; - pSample[pIns->nLoopEnd+2] = pSample[pIns->nLoopStart+2]; - pSample[pIns->nLoopEnd+3] = pSample[pIns->nLoopStart+3]; - pSample[pIns->nLoopEnd+4] = pSample[pIns->nLoopStart+4]; - } - } - } -} - - -///////////////////////////////////////////////////////////// -// Transpose <-> Frequency conversions - -// returns 8363*2^((transp*128+ftune)/(12*128)) -DWORD CSoundFile::TransposeToFrequency(int transp, int ftune) -//----------------------------------------------------------- -{ -#ifdef MSC_VER - const float _fbase = 8363; - const float _factor = 1.0f/(12.0f*128.0f); - int result; - DWORD freq; - - transp = (transp << 7) + ftune; - _asm { - fild transp - fld _factor - fmulp st(1), st(0) - fist result - fisub result - f2xm1 - fild result - fld _fbase - fscale - fstp st(1) - fmul st(1), st(0) - faddp st(1), st(0) - fistp freq - } - UINT derr = freq % 11025; - if (derr <= 8) freq -= derr; - if (derr >= 11015) freq += 11025-derr; - derr = freq % 1000; - if (derr <= 5) freq -= derr; - if (derr >= 995) freq += 1000-derr; - return freq; -#else - //---GCCFIX: Removed assembly. - return (DWORD)(8363*pow(2, (transp*128+ftune)/(1536))); -#endif -} - - -// returns 12*128*log2(freq/8363) -int CSoundFile::FrequencyToTranspose(DWORD freq) -//---------------------------------------------- -{ -#ifdef MSC_VER - const float _f1_8363 = 1.0f / 8363.0f; - const float _factor = 128 * 12; - LONG result; - - if (!freq) return 0; - _asm { - fld _factor - fild freq - fld _f1_8363 - fmulp st(1), st(0) - fyl2x - fistp result - } - return result; -#else - //---GCCFIX: Removed assembly. - return int(1536*(log(freq/8363)/log(2))); -#endif -} - - -void CSoundFile::FrequencyToTranspose(MODINSTRUMENT *psmp) -//-------------------------------------------------------- -{ - int f2t = FrequencyToTranspose(psmp->nC4Speed); - int transp = f2t >> 7; - int ftune = f2t & 0x7F; - if (ftune > 80) - { - transp++; - ftune -= 128; - } - if (transp > 127) transp = 127; - if (transp < -127) transp = -127; - psmp->RelativeTone = transp; - psmp->nFineTune = ftune; -} - - -void CSoundFile::CheckCPUUsage(UINT nCPU) -//--------------------------------------- -{ - if (nCPU > 100) nCPU = 100; - gnCPUUsage = nCPU; - if (nCPU < 90) - { - m_dwSongFlags &= ~SONG_CPUVERYHIGH; - } else - if ((m_dwSongFlags & SONG_CPUVERYHIGH) && (nCPU >= 94)) - { - UINT i=MAX_CHANNELS; - while (i >= 8) - { - i--; - if (Chn[i].nLength) - { - Chn[i].nLength = Chn[i].nPos = 0; - nCPU -= 2; - if (nCPU < 94) break; - } - } - } else - if (nCPU > 90) - { - m_dwSongFlags |= SONG_CPUVERYHIGH; - } -} - - -BOOL CSoundFile::SetPatternName(UINT nPat, LPCSTR lpszName) -//--------------------------------------------------------- -{ - char szName[MAX_PATTERNNAME] = ""; // changed from CHAR - if (nPat >= MAX_PATTERNS) return FALSE; - if (lpszName) lstrcpyn(szName, lpszName, MAX_PATTERNNAME); - szName[MAX_PATTERNNAME-1] = 0; - if (!m_lpszPatternNames) m_nPatternNames = 0; - if (nPat >= m_nPatternNames) - { - if (!lpszName[0]) return TRUE; - UINT len = (nPat+1)*MAX_PATTERNNAME; - char *p = new char[len]; // changed from CHAR - if (!p) return FALSE; - memset(p, 0, len); - if (m_lpszPatternNames) - { - memcpy(p, m_lpszPatternNames, m_nPatternNames * MAX_PATTERNNAME); - delete m_lpszPatternNames; - m_lpszPatternNames = NULL; - } - m_lpszPatternNames = p; - m_nPatternNames = nPat + 1; - } - memcpy(m_lpszPatternNames + nPat * MAX_PATTERNNAME, szName, MAX_PATTERNNAME); - return TRUE; -} - - -BOOL CSoundFile::GetPatternName(UINT nPat, LPSTR lpszName, UINT cbSize) const -//--------------------------------------------------------------------------- -{ - if ((!lpszName) || (!cbSize)) return FALSE; - lpszName[0] = 0; - if (cbSize > MAX_PATTERNNAME) cbSize = MAX_PATTERNNAME; - if ((m_lpszPatternNames) && (nPat < m_nPatternNames)) - { - memcpy(lpszName, m_lpszPatternNames + nPat * MAX_PATTERNNAME, cbSize); - lpszName[cbSize-1] = 0; - return TRUE; - } - return FALSE; -} - - -#ifndef MODPLUG_FASTSOUNDLIB - -UINT CSoundFile::DetectUnusedSamples(BOOL *pbIns) -//----------------------------------------------- -{ - UINT nExt = 0; - - if (!pbIns) return 0; - if (m_nInstruments) - { - memset(pbIns, 0, MAX_SAMPLES * sizeof(BOOL)); - for (UINT ipat=0; ipat<MAX_PATTERNS; ipat++) - { - MODCOMMAND *p = Patterns[ipat]; - if (p) - { - UINT jmax = PatternSize[ipat] * m_nChannels; - for (UINT j=0; j<jmax; j++, p++) - { - if ((p->note) && (p->note <= NOTE_MAX)) - { - if ((p->instr) && (p->instr < MAX_INSTRUMENTS)) - { - INSTRUMENTHEADER *penv = Headers[p->instr]; - if (penv) - { - UINT n = penv->Keyboard[p->note-1]; - if (n < MAX_SAMPLES) pbIns[n] = TRUE; - } - } else - { - for (UINT k=1; k<=m_nInstruments; k++) - { - INSTRUMENTHEADER *penv = Headers[k]; - if (penv) - { - UINT n = penv->Keyboard[p->note-1]; - if (n < MAX_SAMPLES) pbIns[n] = TRUE; - } - } - } - } - } - } - } - for (UINT ichk=1; ichk<=m_nSamples; ichk++) - { - if ((!pbIns[ichk]) && (Ins[ichk].pSample)) nExt++; - } - } - return nExt; -} - - -BOOL CSoundFile::RemoveSelectedSamples(BOOL *pbIns) -//------------------------------------------------- -{ - if (!pbIns) return FALSE; - for (UINT j=1; j<MAX_SAMPLES; j++) - { - if ((!pbIns[j]) && (Ins[j].pSample)) - { - DestroySample(j); - if ((j == m_nSamples) && (j > 1)) m_nSamples--; - } - } - return TRUE; -} - - -BOOL CSoundFile::DestroySample(UINT nSample) -//------------------------------------------ -{ - if ((!nSample) || (nSample >= MAX_SAMPLES)) return FALSE; - if (!Ins[nSample].pSample) return TRUE; - MODINSTRUMENT *pins = &Ins[nSample]; - signed char *pSample = pins->pSample; - pins->pSample = NULL; - pins->nLength = 0; - pins->uFlags &= ~(CHN_16BIT); - for (UINT i=0; i<MAX_CHANNELS; i++) - { - if (Chn[i].pSample == pSample) - { - Chn[i].nPos = Chn[i].nLength = 0; - Chn[i].pSample = Chn[i].pCurrentSample = NULL; - } - } - FreeSample(pSample); - return TRUE; -} - -#endif // MODPLUG_FASTSOUNDLIB - diff --git a/lib/libmodplug/src/sndmix.cpp b/lib/libmodplug/src/sndmix.cpp deleted file mode 100644 index 4be1c4e298..0000000000 --- a/lib/libmodplug/src/sndmix.cpp +++ /dev/null @@ -1,1237 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque <olivierl@jps.net> -*/ - -#include "libmodplug/stdafx.h" -#include "libmodplug/sndfile.h" -#include "tables.h" - -#ifdef MODPLUG_TRACKER -#define ENABLE_STEREOVU -#endif - -// Volume ramp length, in 1/10 ms -#define VOLUMERAMPLEN 146 // 1.46ms = 64 samples at 44.1kHz - -// VU-Meter -#define VUMETER_DECAY 4 - -// SNDMIX: These are global flags for playback control -UINT CSoundFile::m_nStereoSeparation = 128; -LONG CSoundFile::m_nStreamVolume = 0x8000; -UINT CSoundFile::m_nMaxMixChannels = 32; -// Mixing Configuration (SetWaveConfig) -DWORD CSoundFile::gdwSysInfo = 0; -DWORD CSoundFile::gnChannels = 1; -DWORD CSoundFile::gdwSoundSetup = 0; -DWORD CSoundFile::gdwMixingFreq = 44100; -DWORD CSoundFile::gnBitsPerSample = 16; -// Mixing data initialized in -UINT CSoundFile::gnAGC = AGC_UNITY; -UINT CSoundFile::gnVolumeRampSamples = 64; -UINT CSoundFile::gnVUMeter = 0; -UINT CSoundFile::gnCPUUsage = 0; -LPSNDMIXHOOKPROC CSoundFile::gpSndMixHook = NULL; -PMIXPLUGINCREATEPROC CSoundFile::gpMixPluginCreateProc = NULL; -LONG gnDryROfsVol = 0; -LONG gnDryLOfsVol = 0; -LONG gnRvbROfsVol = 0; -LONG gnRvbLOfsVol = 0; -int gbInitPlugins = 0; - -typedef DWORD (MPPASMCALL * LPCONVERTPROC)(LPVOID, int *, DWORD, LPLONG, LPLONG); - -extern DWORD MPPASMCALL X86_Convert32To8(LPVOID lpBuffer, int *, DWORD nSamples, LPLONG, LPLONG); -extern DWORD MPPASMCALL X86_Convert32To16(LPVOID lpBuffer, int *, DWORD nSamples, LPLONG, LPLONG); -extern DWORD MPPASMCALL X86_Convert32To24(LPVOID lpBuffer, int *, DWORD nSamples, LPLONG, LPLONG); -extern DWORD MPPASMCALL X86_Convert32To32(LPVOID lpBuffer, int *, DWORD nSamples, LPLONG, LPLONG); -extern UINT MPPASMCALL X86_AGC(int *pBuffer, UINT nSamples, UINT nAGC); -extern VOID MPPASMCALL X86_Dither(int *pBuffer, UINT nSamples, UINT nBits); -extern VOID MPPASMCALL X86_InterleaveFrontRear(int *pFrontBuf, int *pRearBuf, DWORD nSamples); -extern VOID MPPASMCALL X86_StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs); -extern VOID MPPASMCALL X86_MonoFromStereo(int *pMixBuf, UINT nSamples); - -extern int MixSoundBuffer[MIXBUFFERSIZE*4]; -extern int MixRearBuffer[MIXBUFFERSIZE*2]; -UINT gnReverbSend; - - -// Log tables for pre-amp -// We don't want the tracker to get too loud -const UINT PreAmpTable[16] = -{ - 0x60, 0x60, 0x60, 0x70, // 0-7 - 0x80, 0x88, 0x90, 0x98, // 8-15 - 0xA0, 0xA4, 0xA8, 0xB0, // 16-23 - 0xB4, 0xB8, 0xBC, 0xC0, // 24-31 -}; - -const UINT PreAmpAGCTable[16] = -{ - 0x60, 0x60, 0x60, 0x60, - 0x68, 0x70, 0x78, 0x80, - 0x84, 0x88, 0x8C, 0x90, - 0x94, 0x98, 0x9C, 0xA0, -}; - - -// Return (a*b)/c - no divide error -int _muldiv(long a, long b, long c) -{ -#ifdef MSC_VER - int sign, result; - _asm { - mov eax, a - mov ebx, b - or eax, eax - mov edx, eax - jge aneg - neg eax -aneg: - xor edx, ebx - or ebx, ebx - mov ecx, c - jge bneg - neg ebx -bneg: - xor edx, ecx - or ecx, ecx - mov sign, edx - jge cneg - neg ecx -cneg: - mul ebx - cmp edx, ecx - jae diverr - div ecx - jmp ok -diverr: - mov eax, 0x7fffffff -ok: - mov edx, sign - or edx, edx - jge rneg - neg eax -rneg: - mov result, eax - } - return result; -#else - return ((unsigned long long) a * (unsigned long long) b ) / c; -#endif -} - - -// Return (a*b+c/2)/c - no divide error -int _muldivr(long a, long b, long c) -{ -#ifdef MSC_VER - int sign, result; - _asm { - mov eax, a - mov ebx, b - or eax, eax - mov edx, eax - jge aneg - neg eax -aneg: - xor edx, ebx - or ebx, ebx - mov ecx, c - jge bneg - neg ebx -bneg: - xor edx, ecx - or ecx, ecx - mov sign, edx - jge cneg - neg ecx -cneg: - mul ebx - mov ebx, ecx - shr ebx, 1 - add eax, ebx - adc edx, 0 - cmp edx, ecx - jae diverr - div ecx - jmp ok -diverr: - mov eax, 0x7fffffff -ok: - mov edx, sign - or edx, edx - jge rneg - neg eax -rneg: - mov result, eax - } - return result; -#else - return ((unsigned long long) a * (unsigned long long) b + (c >> 1)) / c; -#endif -} - - -BOOL CSoundFile::InitPlayer(BOOL bReset) -//-------------------------------------- -{ - if (m_nMaxMixChannels > MAX_CHANNELS) m_nMaxMixChannels = MAX_CHANNELS; - if (gdwMixingFreq < 4000) gdwMixingFreq = 4000; - if (gdwMixingFreq > MAX_SAMPLE_RATE) gdwMixingFreq = MAX_SAMPLE_RATE; - gnVolumeRampSamples = (gdwMixingFreq * VOLUMERAMPLEN) / 100000; - if (gnVolumeRampSamples < 8) gnVolumeRampSamples = 8; - gnDryROfsVol = gnDryLOfsVol = 0; - gnRvbROfsVol = gnRvbLOfsVol = 0; - if (bReset) - { - gnVUMeter = 0; - gnCPUUsage = 0; - } - gbInitPlugins = (bReset) ? 3 : 1; - InitializeDSP(bReset); - return TRUE; -} - - -BOOL CSoundFile::FadeSong(UINT msec) -//---------------------------------- -{ - LONG nsamples = _muldiv(msec, gdwMixingFreq, 1000); - if (nsamples <= 0) return FALSE; - if (nsamples > 0x100000) nsamples = 0x100000; - m_nBufferCount = nsamples; - LONG nRampLength = m_nBufferCount; - // Ramp everything down - for (UINT noff=0; noff < m_nMixChannels; noff++) - { - MODCHANNEL *pramp = &Chn[ChnMix[noff]]; - if (!pramp) continue; - pramp->nNewLeftVol = pramp->nNewRightVol = 0; - pramp->nRightRamp = (-pramp->nRightVol << VOLUMERAMPPRECISION) / nRampLength; - pramp->nLeftRamp = (-pramp->nLeftVol << VOLUMERAMPPRECISION) / nRampLength; - pramp->nRampRightVol = pramp->nRightVol << VOLUMERAMPPRECISION; - pramp->nRampLeftVol = pramp->nLeftVol << VOLUMERAMPPRECISION; - pramp->nRampLength = nRampLength; - pramp->dwFlags |= CHN_VOLUMERAMP; - } - m_dwSongFlags |= SONG_FADINGSONG; - return TRUE; -} - - -BOOL CSoundFile::GlobalFadeSong(UINT msec) -//---------------------------------------- -{ - if (m_dwSongFlags & SONG_GLOBALFADE) return FALSE; - m_nGlobalFadeMaxSamples = _muldiv(msec, gdwMixingFreq, 1000); - m_nGlobalFadeSamples = m_nGlobalFadeMaxSamples; - m_dwSongFlags |= SONG_GLOBALFADE; - return TRUE; -} - - -UINT CSoundFile::Read(LPVOID lpDestBuffer, UINT cbBuffer) -//------------------------------------------------------- -{ - LPBYTE lpBuffer = (LPBYTE)lpDestBuffer; - LPCONVERTPROC pCvt = X86_Convert32To8; - UINT lRead, lMax, lSampleSize, lCount, lSampleCount, nStat=0; - LONG nVUMeterMin = 0x7FFFFFFF, nVUMeterMax = -0x7FFFFFFF; - UINT nMaxPlugins; - - { - nMaxPlugins = MAX_MIXPLUGINS; - while ((nMaxPlugins > 0) && (!m_MixPlugins[nMaxPlugins-1].pMixPlugin)) nMaxPlugins--; - } - m_nMixStat = 0; - lSampleSize = gnChannels; - if (gnBitsPerSample == 16) { lSampleSize *= 2; pCvt = X86_Convert32To16; } -#ifndef MODPLUG_FASTSOUNDLIB - else if (gnBitsPerSample == 24) { lSampleSize *= 3; pCvt = X86_Convert32To24; } - else if (gnBitsPerSample == 32) { lSampleSize *= 4; pCvt = X86_Convert32To32; } -#endif - lMax = cbBuffer / lSampleSize; - if ((!lMax) || (!lpBuffer) || (!m_nChannels)) return 0; - lRead = lMax; - if (m_dwSongFlags & SONG_ENDREACHED) goto MixDone; - while (lRead > 0) - { - // Update Channel Data - if (!m_nBufferCount) - { -#ifndef MODPLUG_FASTSOUNDLIB - if (m_dwSongFlags & SONG_FADINGSONG) - { - m_dwSongFlags |= SONG_ENDREACHED; - m_nBufferCount = lRead; - } else -#endif - if (!ReadNote()) - { -#ifndef MODPLUG_FASTSOUNDLIB - if (!FadeSong(FADESONGDELAY)) -#endif - { - m_dwSongFlags |= SONG_ENDREACHED; - if (lRead == lMax) goto MixDone; - m_nBufferCount = lRead; - } - } - } - lCount = m_nBufferCount; - if (lCount > MIXBUFFERSIZE) lCount = MIXBUFFERSIZE; - if (lCount > lRead) lCount = lRead; - if (!lCount) break; - lSampleCount = lCount; -#ifndef MODPLUG_NO_REVERB - gnReverbSend = 0; -#endif - // Resetting sound buffer - X86_StereoFill(MixSoundBuffer, lSampleCount, &gnDryROfsVol, &gnDryLOfsVol); - if (gnChannels >= 2) - { - lSampleCount *= 2; - m_nMixStat += CreateStereoMix(lCount); - ProcessStereoDSP(lCount); - } else - { - m_nMixStat += CreateStereoMix(lCount); - if (nMaxPlugins) ProcessPlugins(lCount); - ProcessStereoDSP(lCount); - X86_MonoFromStereo(MixSoundBuffer, lCount); - } - nStat++; -#ifndef NO_AGC - // Automatic Gain Control - if (gdwSoundSetup & SNDMIX_AGC) ProcessAGC(lSampleCount); -#endif - UINT lTotalSampleCount = lSampleCount; -#ifndef MODPLUG_FASTSOUNDLIB - // Multichannel - if (gnChannels > 2) - { - X86_InterleaveFrontRear(MixSoundBuffer, MixRearBuffer, lSampleCount); - lTotalSampleCount *= 2; - } - // Hook Function - if (gpSndMixHook) - { - gpSndMixHook(MixSoundBuffer, lTotalSampleCount, gnChannels); - } -#endif - // Perform clipping + VU-Meter - lpBuffer += pCvt(lpBuffer, MixSoundBuffer, lTotalSampleCount, &nVUMeterMin, &nVUMeterMax); - // Buffer ready - lRead -= lCount; - m_nBufferCount -= lCount; - } -MixDone: - if (lRead) memset(lpBuffer, (gnBitsPerSample == 8) ? 0x80 : 0, lRead * lSampleSize); - // VU-Meter - nVUMeterMin >>= (24-MIXING_ATTENUATION); - nVUMeterMax >>= (24-MIXING_ATTENUATION); - if (nVUMeterMax < nVUMeterMin) nVUMeterMax = nVUMeterMin; - if ((gnVUMeter = (UINT)(nVUMeterMax - nVUMeterMin)) > 0xFF) gnVUMeter = 0xFF; - if (nStat) { m_nMixStat += nStat-1; m_nMixStat /= nStat; } - return lMax - lRead; -} - - - -///////////////////////////////////////////////////////////////////////////// -// Handles navigation/effects - -BOOL CSoundFile::ProcessRow() -//--------------------------- -{ - if (++m_nTickCount >= m_nMusicSpeed * (m_nPatternDelay+1) + m_nFrameDelay) - { - m_nPatternDelay = 0; - m_nFrameDelay = 0; - m_nTickCount = 0; - m_nRow = m_nNextRow; - // Reset Pattern Loop Effect - if (m_nCurrentPattern != m_nNextPattern) m_nCurrentPattern = m_nNextPattern; - // Check if pattern is valid - if (!(m_dwSongFlags & SONG_PATTERNLOOP)) - { - m_nPattern = (m_nCurrentPattern < MAX_ORDERS) ? Order[m_nCurrentPattern] : 0xFF; - if ((m_nPattern < MAX_PATTERNS) && (!Patterns[m_nPattern])) m_nPattern = 0xFE; - while (m_nPattern >= MAX_PATTERNS) - { - // End of song ? - if ((m_nPattern == 0xFF) || (m_nCurrentPattern >= MAX_ORDERS)) - { - //if (!m_nRepeatCount) - return FALSE; //never repeat entire song - if (!m_nRestartPos) - { - m_nMusicSpeed = m_nDefaultSpeed; - m_nMusicTempo = m_nDefaultTempo; - m_nGlobalVolume = m_nDefaultGlobalVolume; - for (UINT i=0; i<MAX_CHANNELS; i++) - { - Chn[i].dwFlags |= CHN_NOTEFADE | CHN_KEYOFF; - Chn[i].nFadeOutVol = 0; - if (i < m_nChannels) - { - Chn[i].nGlobalVol = ChnSettings[i].nVolume; - Chn[i].nVolume = ChnSettings[i].nVolume; - Chn[i].nPan = ChnSettings[i].nPan; - Chn[i].nPanSwing = Chn[i].nVolSwing = 0; - Chn[i].nOldVolParam = 0; - Chn[i].nOldOffset = 0; - Chn[i].nOldHiOffset = 0; - Chn[i].nPortamentoDest = 0; - if (!Chn[i].nLength) - { - Chn[i].dwFlags = ChnSettings[i].dwFlags; - Chn[i].nLoopStart = 0; - Chn[i].nLoopEnd = 0; - Chn[i].pHeader = NULL; - Chn[i].pSample = NULL; - Chn[i].pInstrument = NULL; - } - } - } - } -// if (m_nRepeatCount > 0) m_nRepeatCount--; - m_nCurrentPattern = m_nRestartPos; - m_nRow = 0; - if ((Order[m_nCurrentPattern] >= MAX_PATTERNS) || (!Patterns[Order[m_nCurrentPattern]])) return FALSE; - } else - { - m_nCurrentPattern++; - } - m_nPattern = (m_nCurrentPattern < MAX_ORDERS) ? Order[m_nCurrentPattern] : 0xFF; - if ((m_nPattern < MAX_PATTERNS) && (!Patterns[m_nPattern])) m_nPattern = 0xFE; - } - m_nNextPattern = m_nCurrentPattern; - } - // Weird stuff? - if ((m_nPattern >= MAX_PATTERNS) || (!Patterns[m_nPattern])) return FALSE; - // Should never happen - if (m_nRow >= PatternSize[m_nPattern]) m_nRow = 0; - m_nNextRow = m_nRow + 1; - if (m_nNextRow >= PatternSize[m_nPattern]) - { - if (!(m_dwSongFlags & SONG_PATTERNLOOP)) m_nNextPattern = m_nCurrentPattern + 1; - m_nNextRow = 0; - } - // Reset channel values - MODCHANNEL *pChn = Chn; - MODCOMMAND *m = Patterns[m_nPattern] + m_nRow * m_nChannels; - for (UINT nChn=0; nChn<m_nChannels; pChn++, nChn++, m++) - { - pChn->nRowNote = m->note; - pChn->nRowInstr = m->instr; - pChn->nRowVolCmd = m->volcmd; - pChn->nRowVolume = m->vol; - pChn->nRowCommand = m->command; - pChn->nRowParam = m->param; - - pChn->nLeftVol = pChn->nNewLeftVol; - pChn->nRightVol = pChn->nNewRightVol; - pChn->dwFlags &= ~(CHN_PORTAMENTO | CHN_VIBRATO | CHN_TREMOLO | CHN_PANBRELLO); - pChn->nCommand = 0; - } - } - // Should we process tick0 effects? - if (!m_nMusicSpeed) m_nMusicSpeed = 1; - m_dwSongFlags |= SONG_FIRSTTICK; - if (m_nTickCount) - { - m_dwSongFlags &= ~SONG_FIRSTTICK; - if ((!(m_nType & MOD_TYPE_XM)) && (m_nTickCount < m_nMusicSpeed * (1 + m_nPatternDelay))) - { - if (!(m_nTickCount % m_nMusicSpeed)) m_dwSongFlags |= SONG_FIRSTTICK; - } - - } - // Update Effects - return ProcessEffects(); -} - - -//////////////////////////////////////////////////////////////////////////////////////////// -// Handles envelopes & mixer setup - -BOOL CSoundFile::ReadNote() -//------------------------- -{ - if (!ProcessRow()) return FALSE; - //////////////////////////////////////////////////////////////////////////////////// - m_nTotalCount++; - if (!m_nMusicTempo) return FALSE; - m_nBufferCount = (gdwMixingFreq * 5 * m_nTempoFactor) / (m_nMusicTempo << 8); - // Master Volume + Pre-Amplification / Attenuation setup - DWORD nMasterVol; - { - int nchn32 = (m_nChannels < 32) ? m_nChannels : 31; - if ((m_nType & MOD_TYPE_IT) && (m_nInstruments) && (nchn32 < 6)) nchn32 = 6; - int realmastervol = m_nMasterVolume; - if (realmastervol > 0x80) - { - realmastervol = 0x80 + ((realmastervol - 0x80) * (nchn32+4)) / 16; - } - UINT attenuation = (gdwSoundSetup & SNDMIX_AGC) ? PreAmpAGCTable[nchn32>>1] : PreAmpTable[nchn32>>1]; - DWORD mastervol = (realmastervol * (m_nSongPreAmp + 0x10)) >> 6; - if (mastervol > 0x200) mastervol = 0x200; - if ((m_dwSongFlags & SONG_GLOBALFADE) && (m_nGlobalFadeMaxSamples)) - { - mastervol = _muldiv(mastervol, m_nGlobalFadeSamples, m_nGlobalFadeMaxSamples); - } - nMasterVol = (mastervol << 7) / attenuation; - if (nMasterVol > 0x180) nMasterVol = 0x180; - } - //////////////////////////////////////////////////////////////////////////////////// - // Update channels data - m_nMixChannels = 0; - MODCHANNEL *pChn = Chn; - for (UINT nChn=0; nChn<MAX_CHANNELS; nChn++,pChn++) - { - if ((pChn->dwFlags & CHN_NOTEFADE) && (!(pChn->nFadeOutVol|pChn->nRightVol|pChn->nLeftVol))) - { - pChn->nLength = 0; - pChn->nROfs = pChn->nLOfs = 0; - } - // Check for unused channel - if ((pChn->dwFlags & CHN_MUTE) || ((nChn >= m_nChannels) && (!pChn->nLength))) - { - pChn->nVUMeter = 0; -#ifdef ENABLE_STEREOVU - pChn->nLeftVU = pChn->nRightVU = 0; -#endif - continue; - } - // Reset channel data - pChn->nInc = 0; - pChn->nRealVolume = 0; - pChn->nRealPan = pChn->nPan + pChn->nPanSwing; - if (pChn->nRealPan < 0) pChn->nRealPan = 0; - if (pChn->nRealPan > 256) pChn->nRealPan = 256; - pChn->nRampLength = 0; - // Calc Frequency - if ((pChn->nPeriod) && (pChn->nLength)) - { - int vol = pChn->nVolume + pChn->nVolSwing; - - if (vol < 0) vol = 0; - if (vol > 256) vol = 256; - // Tremolo - if (pChn->dwFlags & CHN_TREMOLO) - { - UINT trempos = pChn->nTremoloPos & 0x3F; - if (vol > 0) - { - int tremattn = (m_nType & MOD_TYPE_XM) ? 5 : 6; - switch (pChn->nTremoloType & 0x03) - { - case 1: - vol += (ModRampDownTable[trempos] * (int)pChn->nTremoloDepth) >> tremattn; - break; - case 2: - vol += (ModSquareTable[trempos] * (int)pChn->nTremoloDepth) >> tremattn; - break; - case 3: - vol += (ModRandomTable[trempos] * (int)pChn->nTremoloDepth) >> tremattn; - break; - default: - vol += (ModSinusTable[trempos] * (int)pChn->nTremoloDepth) >> tremattn; - } - } - if ((m_nTickCount) || ((m_nType & (MOD_TYPE_STM|MOD_TYPE_S3M|MOD_TYPE_IT)) && (!(m_dwSongFlags & SONG_ITOLDEFFECTS)))) - { - pChn->nTremoloPos = (trempos + pChn->nTremoloSpeed) & 0x3F; - } - } - // Tremor - if (pChn->nCommand == CMD_TREMOR) - { - UINT n = (pChn->nTremorParam >> 4) + (pChn->nTremorParam & 0x0F); - UINT ontime = pChn->nTremorParam >> 4; - if ((!(m_nType & MOD_TYPE_IT)) || (m_dwSongFlags & SONG_ITOLDEFFECTS)) { n += 2; ontime++; } - UINT tremcount = (UINT)pChn->nTremorCount; - if (tremcount >= n) tremcount = 0; - if ((m_nTickCount) || (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT))) - { - if (tremcount >= ontime) vol = 0; - pChn->nTremorCount = (BYTE)(tremcount + 1); - } - pChn->dwFlags |= CHN_FASTVOLRAMP; - } - // Clip volume - if (vol < 0) vol = 0; - if (vol > 0x100) vol = 0x100; - vol <<= 6; - // Process Envelopes - if (pChn->pHeader) - { - INSTRUMENTHEADER *penv = pChn->pHeader; - // Volume Envelope - if ((pChn->dwFlags & CHN_VOLENV) && (penv->nVolEnv)) - { - int envpos = pChn->nVolEnvPosition; - UINT pt = penv->nVolEnv - 1; - for (UINT i=0; i<(UINT)(penv->nVolEnv-1); i++) - { - if (envpos <= penv->VolPoints[i]) - { - pt = i; - break; - } - } - int x2 = penv->VolPoints[pt]; - int x1, envvol; - if (envpos >= x2) - { - envvol = penv->VolEnv[pt] << 2; - x1 = x2; - } else - if (pt) - { - envvol = penv->VolEnv[pt-1] << 2; - x1 = penv->VolPoints[pt-1]; - } else - { - envvol = 0; - x1 = 0; - } - if (envpos > x2) envpos = x2; - if ((x2 > x1) && (envpos > x1)) - { - envvol += ((envpos - x1) * (((int)penv->VolEnv[pt]<<2) - envvol)) / (x2 - x1); - } - if (envvol < 0) envvol = 0; - if (envvol > 256) envvol = 256; - vol = (vol * envvol) >> 8; - } - // Panning Envelope - if ((pChn->dwFlags & CHN_PANENV) && (penv->nPanEnv)) - { - int envpos = pChn->nPanEnvPosition; - UINT pt = penv->nPanEnv - 1; - for (UINT i=0; i<(UINT)(penv->nPanEnv-1); i++) - { - if (envpos <= penv->PanPoints[i]) - { - pt = i; - break; - } - } - int x2 = penv->PanPoints[pt], y2 = penv->PanEnv[pt]; - int x1, envpan; - if (envpos >= x2) - { - envpan = y2; - x1 = x2; - } else - if (pt) - { - envpan = penv->PanEnv[pt-1]; - x1 = penv->PanPoints[pt-1]; - } else - { - envpan = 128; - x1 = 0; - } - if ((x2 > x1) && (envpos > x1)) - { - envpan += ((envpos - x1) * (y2 - envpan)) / (x2 - x1); - } - if (envpan < 0) envpan = 0; - if (envpan > 64) envpan = 64; - int pan = pChn->nPan; - if (pan >= 128) - { - pan += ((envpan - 32) * (256 - pan)) / 32; - } else - { - pan += ((envpan - 32) * (pan)) / 32; - } - if (pan < 0) pan = 0; - if (pan > 256) pan = 256; - pChn->nRealPan = pan; - } - // FadeOut volume - if (pChn->dwFlags & CHN_NOTEFADE) - { - UINT fadeout = penv->nFadeOut; - if (fadeout) - { - pChn->nFadeOutVol -= fadeout << 1; - if (pChn->nFadeOutVol <= 0) pChn->nFadeOutVol = 0; - vol = (vol * pChn->nFadeOutVol) >> 16; - } else - if (!pChn->nFadeOutVol) - { - vol = 0; - } - } - // Pitch/Pan separation - if ((penv->nPPS) && (pChn->nRealPan) && (pChn->nNote)) - { - int pandelta = (int)pChn->nRealPan + (int)((int)(pChn->nNote - penv->nPPC - 1) * (int)penv->nPPS) / (int)8; - if (pandelta < 0) pandelta = 0; - if (pandelta > 256) pandelta = 256; - pChn->nRealPan = pandelta; - } - } else - { - // No Envelope: key off => note cut - if (pChn->dwFlags & CHN_NOTEFADE) // 1.41-: CHN_KEYOFF|CHN_NOTEFADE - { - pChn->nFadeOutVol = 0; - vol = 0; - } - } - // vol is 14-bits - if (vol) - { - // IMPORTANT: pChn->nRealVolume is 14 bits !!! - // -> _muldiv( 14+8, 6+6, 18); => RealVolume: 14-bit result (22+12-20) - pChn->nRealVolume = _muldiv(vol * m_nGlobalVolume, pChn->nGlobalVol * pChn->nInsVol, 1 << 20); - } - if (pChn->nPeriod < m_nMinPeriod) pChn->nPeriod = m_nMinPeriod; - int period = pChn->nPeriod; - if ((pChn->dwFlags & (CHN_GLISSANDO|CHN_PORTAMENTO)) == (CHN_GLISSANDO|CHN_PORTAMENTO)) - { - period = GetPeriodFromNote(GetNoteFromPeriod(period), pChn->nFineTune, pChn->nC4Speed); - } - - // Arpeggio ? - if (pChn->nCommand == CMD_ARPEGGIO) - { - switch(m_nTickCount % 3) - { - case 1: period = GetPeriodFromNote(pChn->nNote + (pChn->nArpeggio >> 4), pChn->nFineTune, pChn->nC4Speed); break; - case 2: period = GetPeriodFromNote(pChn->nNote + (pChn->nArpeggio & 0x0F), pChn->nFineTune, pChn->nC4Speed); break; - } - } - - if (m_dwSongFlags & SONG_AMIGALIMITS) - { - if (period < 113*4) period = 113*4; - if (period > 856*4) period = 856*4; - } - - // Pitch/Filter Envelope - if ((pChn->pHeader) && (pChn->dwFlags & CHN_PITCHENV) && (pChn->pHeader->nPitchEnv)) - { - INSTRUMENTHEADER *penv = pChn->pHeader; - int envpos = pChn->nPitchEnvPosition; - UINT pt = penv->nPitchEnv - 1; - for (UINT i=0; i<(UINT)(penv->nPitchEnv-1); i++) - { - if (envpos <= penv->PitchPoints[i]) - { - pt = i; - break; - } - } - int x2 = penv->PitchPoints[pt]; - int x1, envpitch; - if (envpos >= x2) - { - envpitch = (((int)penv->PitchEnv[pt]) - 32) * 8; - x1 = x2; - } else - if (pt) - { - envpitch = (((int)penv->PitchEnv[pt-1]) - 32) * 8; - x1 = penv->PitchPoints[pt-1]; - } else - { - envpitch = 0; - x1 = 0; - } - if (envpos > x2) envpos = x2; - if ((x2 > x1) && (envpos > x1)) - { - int envpitchdest = (((int)penv->PitchEnv[pt]) - 32) * 8; - envpitch += ((envpos - x1) * (envpitchdest - envpitch)) / (x2 - x1); - } - if (envpitch < -256) envpitch = -256; - if (envpitch > 256) envpitch = 256; - // Filter Envelope: controls cutoff frequency - if (penv->dwFlags & ENV_FILTER) - { -#ifndef NO_FILTER - SetupChannelFilter(pChn, (pChn->dwFlags & CHN_FILTER) ? FALSE : TRUE, envpitch); -#endif // NO_FILTER - } else - // Pitch Envelope - { - int l = envpitch; - if (l < 0) - { - l = -l; - if (l > 255) l = 255; - period = _muldiv(period, LinearSlideUpTable[l], 0x10000); - } else - { - if (l > 255) l = 255; - period = _muldiv(period, LinearSlideDownTable[l], 0x10000); - } - } - } - - // Vibrato - if (pChn->dwFlags & CHN_VIBRATO) - { - UINT vibpos = pChn->nVibratoPos; - LONG vdelta; - switch (pChn->nVibratoType & 0x03) - { - case 1: - vdelta = ModRampDownTable[vibpos]; - break; - case 2: - vdelta = ModSquareTable[vibpos]; - break; - case 3: - vdelta = ModRandomTable[vibpos]; - break; - default: - vdelta = ModSinusTable[vibpos]; - } - UINT vdepth = ((m_nType != MOD_TYPE_IT) || (m_dwSongFlags & SONG_ITOLDEFFECTS)) ? 6 : 7; - vdelta = (vdelta * (int)pChn->nVibratoDepth) >> vdepth; - if ((m_dwSongFlags & SONG_LINEARSLIDES) && (m_nType & MOD_TYPE_IT)) - { - LONG l = vdelta; - if (l < 0) - { - l = -l; - vdelta = _muldiv(period, LinearSlideDownTable[l >> 2], 0x10000) - period; - if (l & 0x03) vdelta += _muldiv(period, FineLinearSlideDownTable[l & 0x03], 0x10000) - period; - - } else - { - vdelta = _muldiv(period, LinearSlideUpTable[l >> 2], 0x10000) - period; - if (l & 0x03) vdelta += _muldiv(period, FineLinearSlideUpTable[l & 0x03], 0x10000) - period; - - } - } - period += vdelta; - if ((m_nTickCount) || ((m_nType & MOD_TYPE_IT) && (!(m_dwSongFlags & SONG_ITOLDEFFECTS)))) - { - pChn->nVibratoPos = (vibpos + pChn->nVibratoSpeed) & 0x3F; - } - } - // Panbrello - if (pChn->dwFlags & CHN_PANBRELLO) - { - UINT panpos = ((pChn->nPanbrelloPos+0x10) >> 2) & 0x3F; - LONG pdelta; - switch (pChn->nPanbrelloType & 0x03) - { - case 1: - pdelta = ModRampDownTable[panpos]; - break; - case 2: - pdelta = ModSquareTable[panpos]; - break; - case 3: - pdelta = ModRandomTable[panpos]; - break; - default: - pdelta = ModSinusTable[panpos]; - } - pChn->nPanbrelloPos += pChn->nPanbrelloSpeed; - pdelta = ((pdelta * (int)pChn->nPanbrelloDepth) + 2) >> 3; - pdelta += pChn->nRealPan; - if (pdelta < 0) pdelta = 0; - if (pdelta > 256) pdelta = 256; - pChn->nRealPan = pdelta; - } - int nPeriodFrac = 0; - // Instrument Auto-Vibrato - if ((pChn->pInstrument) && (pChn->pInstrument->nVibDepth)) - { - MODINSTRUMENT *pins = pChn->pInstrument; - if (pins->nVibSweep == 0) - { - pChn->nAutoVibDepth = pins->nVibDepth << 8; - } else - { - if (m_nType & MOD_TYPE_IT) - { - pChn->nAutoVibDepth += pins->nVibSweep << 3; - } else - if (!(pChn->dwFlags & CHN_KEYOFF)) - { - pChn->nAutoVibDepth += (pins->nVibDepth << 8) / pins->nVibSweep; - } - if ((pChn->nAutoVibDepth >> 8) > pins->nVibDepth) - pChn->nAutoVibDepth = pins->nVibDepth << 8; - } - pChn->nAutoVibPos += pins->nVibRate; - int val; - switch(pins->nVibType) - { - case 4: // Random - val = ModRandomTable[pChn->nAutoVibPos & 0x3F]; - pChn->nAutoVibPos++; - break; - case 3: // Ramp Down - val = ((0x40 - (pChn->nAutoVibPos >> 1)) & 0x7F) - 0x40; - break; - case 2: // Ramp Up - val = ((0x40 + (pChn->nAutoVibPos >> 1)) & 0x7f) - 0x40; - break; - case 1: // Square - val = (pChn->nAutoVibPos & 128) ? +64 : -64; - break; - default: // Sine - val = ft2VibratoTable[pChn->nAutoVibPos & 255]; - } - int n = ((val * pChn->nAutoVibDepth) >> 8); - if (m_nType & MOD_TYPE_IT) - { - int df1, df2; - if (n < 0) - { - n = -n; - UINT n1 = n >> 8; - df1 = LinearSlideUpTable[n1]; - df2 = LinearSlideUpTable[n1+1]; - } else - { - UINT n1 = n >> 8; - df1 = LinearSlideDownTable[n1]; - df2 = LinearSlideDownTable[n1+1]; - } - n >>= 2; - period = _muldiv(period, df1 + ((df2-df1)*(n&0x3F)>>6), 256); - nPeriodFrac = period & 0xFF; - period >>= 8; - } else - { - period += (n >> 6); - } - } - // Final Period - if (period <= m_nMinPeriod) - { - if (m_nType & MOD_TYPE_S3M) pChn->nLength = 0; - period = m_nMinPeriod; - } - if (period > m_nMaxPeriod) - { - if ((m_nType & MOD_TYPE_IT) || (period >= 0x100000)) - { - pChn->nFadeOutVol = 0; - pChn->dwFlags |= CHN_NOTEFADE; - pChn->nRealVolume = 0; - } - period = m_nMaxPeriod; - nPeriodFrac = 0; - } - UINT freq = GetFreqFromPeriod(period, pChn->nC4Speed, nPeriodFrac); - if ((m_nType & MOD_TYPE_IT) && (freq < 256)) - { - pChn->nFadeOutVol = 0; - pChn->dwFlags |= CHN_NOTEFADE; - pChn->nRealVolume = 0; - } - UINT ninc = _muldiv(freq, 0x10000, gdwMixingFreq); - if ((ninc >= 0xFFB0) && (ninc <= 0x10090)) ninc = 0x10000; - if (m_nFreqFactor != 128) ninc = (ninc * m_nFreqFactor) >> 7; - if (ninc > 0xFF0000) ninc = 0xFF0000; - pChn->nInc = (ninc+1) & ~3; - } - - // Increment envelope position - if (pChn->pHeader) - { - INSTRUMENTHEADER *penv = pChn->pHeader; - // Volume Envelope - if (pChn->dwFlags & CHN_VOLENV) - { - // Increase position - pChn->nVolEnvPosition++; - // Volume Loop ? - if (penv->dwFlags & ENV_VOLLOOP) - { - UINT volloopend = penv->VolPoints[penv->nVolLoopEnd]; - if (m_nType != MOD_TYPE_XM) volloopend++; - if (pChn->nVolEnvPosition == volloopend) - { - pChn->nVolEnvPosition = penv->VolPoints[penv->nVolLoopStart]; - if ((penv->nVolLoopEnd == penv->nVolLoopStart) && (!penv->VolEnv[penv->nVolLoopStart]) - && ((!(m_nType & MOD_TYPE_XM)) || (penv->nVolLoopEnd+1 == penv->nVolEnv))) - { - pChn->dwFlags |= CHN_NOTEFADE; - pChn->nFadeOutVol = 0; - } - } - } - // Volume Sustain ? - if ((penv->dwFlags & ENV_VOLSUSTAIN) && (!(pChn->dwFlags & CHN_KEYOFF))) - { - if (pChn->nVolEnvPosition == (UINT)penv->VolPoints[penv->nVolSustainEnd]+1) - pChn->nVolEnvPosition = penv->VolPoints[penv->nVolSustainBegin]; - } else - // End of Envelope ? - if (pChn->nVolEnvPosition > penv->VolPoints[penv->nVolEnv - 1]) - { - if ((m_nType & MOD_TYPE_IT) || (pChn->dwFlags & CHN_KEYOFF)) pChn->dwFlags |= CHN_NOTEFADE; - pChn->nVolEnvPosition = penv->VolPoints[penv->nVolEnv - 1]; - if ((!penv->VolEnv[penv->nVolEnv-1]) && ((nChn >= m_nChannels) || (m_nType & MOD_TYPE_IT))) - { - pChn->dwFlags |= CHN_NOTEFADE; - pChn->nFadeOutVol = 0; - - pChn->nRealVolume = 0; - } - } - } - // Panning Envelope - if (pChn->dwFlags & CHN_PANENV) - { - pChn->nPanEnvPosition++; - if (penv->dwFlags & ENV_PANLOOP) - { - UINT panloopend = penv->PanPoints[penv->nPanLoopEnd]; - if (m_nType != MOD_TYPE_XM) panloopend++; - if (pChn->nPanEnvPosition == panloopend) - pChn->nPanEnvPosition = penv->PanPoints[penv->nPanLoopStart]; - } - // Panning Sustain ? - if ((penv->dwFlags & ENV_PANSUSTAIN) && (pChn->nPanEnvPosition == (UINT)penv->PanPoints[penv->nPanSustainEnd]+1) - && (!(pChn->dwFlags & CHN_KEYOFF))) - { - // Panning sustained - pChn->nPanEnvPosition = penv->PanPoints[penv->nPanSustainBegin]; - } else - { - if (pChn->nPanEnvPosition > penv->PanPoints[penv->nPanEnv - 1]) - pChn->nPanEnvPosition = penv->PanPoints[penv->nPanEnv - 1]; - } - } - // Pitch Envelope - if (pChn->dwFlags & CHN_PITCHENV) - { - // Increase position - pChn->nPitchEnvPosition++; - // Pitch Loop ? - if (penv->dwFlags & ENV_PITCHLOOP) - { - if (pChn->nPitchEnvPosition >= penv->PitchPoints[penv->nPitchLoopEnd]) - pChn->nPitchEnvPosition = penv->PitchPoints[penv->nPitchLoopStart]; - } - // Pitch Sustain ? - if ((penv->dwFlags & ENV_PITCHSUSTAIN) && (!(pChn->dwFlags & CHN_KEYOFF))) - { - if (pChn->nPitchEnvPosition == (UINT)penv->PitchPoints[penv->nPitchSustainEnd]+1) - pChn->nPitchEnvPosition = penv->PitchPoints[penv->nPitchSustainBegin]; - } else - { - if (pChn->nPitchEnvPosition > penv->PitchPoints[penv->nPitchEnv - 1]) - pChn->nPitchEnvPosition = penv->PitchPoints[penv->nPitchEnv - 1]; - } - } - } -#ifdef MODPLUG_PLAYER - // Limit CPU -> > 80% -> don't ramp - if ((gnCPUUsage >= 80) && (!pChn->nRealVolume)) - { - pChn->nLeftVol = pChn->nRightVol = 0; - } -#endif // MODPLUG_PLAYER - // Volume ramping - pChn->dwFlags &= ~CHN_VOLUMERAMP; - if ((pChn->nRealVolume) || (pChn->nLeftVol) || (pChn->nRightVol)) - pChn->dwFlags |= CHN_VOLUMERAMP; -#ifdef MODPLUG_PLAYER - // Decrease VU-Meter - if (pChn->nVUMeter > VUMETER_DECAY) pChn->nVUMeter -= VUMETER_DECAY; else pChn->nVUMeter = 0; -#endif // MODPLUG_PLAYER -#ifdef ENABLE_STEREOVU - if (pChn->nLeftVU > VUMETER_DECAY) pChn->nLeftVU -= VUMETER_DECAY; else pChn->nLeftVU = 0; - if (pChn->nRightVU > VUMETER_DECAY) pChn->nRightVU -= VUMETER_DECAY; else pChn->nRightVU = 0; -#endif - // Check for too big nInc - if (((pChn->nInc >> 16) + 1) >= (LONG)(pChn->nLoopEnd - pChn->nLoopStart)) pChn->dwFlags &= ~CHN_LOOP; - pChn->nNewRightVol = pChn->nNewLeftVol = 0; - pChn->pCurrentSample = ((pChn->pSample) && (pChn->nLength) && (pChn->nInc)) ? pChn->pSample : NULL; - if (pChn->pCurrentSample) - { - // Update VU-Meter (nRealVolume is 14-bit) -#ifdef MODPLUG_PLAYER - UINT vutmp = pChn->nRealVolume >> (14 - 8); - if (vutmp > 0xFF) vutmp = 0xFF; - if (pChn->nVUMeter >= 0x100) pChn->nVUMeter = vutmp; - vutmp >>= 1; - if (pChn->nVUMeter < vutmp) pChn->nVUMeter = vutmp; -#endif // MODPLUG_PLAYER -#ifdef ENABLE_STEREOVU - UINT vul = (pChn->nRealVolume * pChn->nRealPan) >> 14; - if (vul > 127) vul = 127; - if (pChn->nLeftVU > 127) pChn->nLeftVU = (BYTE)vul; - vul >>= 1; - if (pChn->nLeftVU < vul) pChn->nLeftVU = (BYTE)vul; - UINT vur = (pChn->nRealVolume * (256-pChn->nRealPan)) >> 14; - if (vur > 127) vur = 127; - if (pChn->nRightVU > 127) pChn->nRightVU = (BYTE)vur; - vur >>= 1; - if (pChn->nRightVU < vur) pChn->nRightVU = (BYTE)vur; -#endif -#ifdef MODPLUG_TRACKER - UINT kChnMasterVol = (pChn->dwFlags & CHN_EXTRALOUD) ? 0x100 : nMasterVol; -#else -#define kChnMasterVol nMasterVol -#endif // MODPLUG_TRACKER - // Adjusting volumes - if (gnChannels >= 2) - { - int pan = ((int)pChn->nRealPan) - 128; - pan *= (int)m_nStereoSeparation; - pan /= 128; - pan += 128; - - if (pan < 0) pan = 0; - if (pan > 256) pan = 256; -#ifndef MODPLUG_FASTSOUNDLIB - if (gdwSoundSetup & SNDMIX_REVERSESTEREO) pan = 256 - pan; -#endif - LONG realvol = (pChn->nRealVolume * kChnMasterVol) >> (8-1); - if (gdwSoundSetup & SNDMIX_SOFTPANNING) - { - if (pan < 128) - { - pChn->nNewLeftVol = (realvol * pan) >> 8; - pChn->nNewRightVol = (realvol * 128) >> 8; - } else - { - pChn->nNewLeftVol = (realvol * 128) >> 8; - pChn->nNewRightVol = (realvol * (256 - pan)) >> 8; - } - } else - { - pChn->nNewLeftVol = (realvol * pan) >> 8; - pChn->nNewRightVol = (realvol * (256 - pan)) >> 8; - } - } else - { - pChn->nNewRightVol = (pChn->nRealVolume * kChnMasterVol) >> 8; - pChn->nNewLeftVol = pChn->nNewRightVol; - } - // Clipping volumes - if (pChn->nNewRightVol > 0xFFFF) pChn->nNewRightVol = 0xFFFF; - if (pChn->nNewLeftVol > 0xFFFF) pChn->nNewLeftVol = 0xFFFF; - // Check IDO - if (gdwSoundSetup & SNDMIX_NORESAMPLING) - { - pChn->dwFlags |= CHN_NOIDO; - } else - { - pChn->dwFlags &= ~(CHN_NOIDO|CHN_HQSRC); - if( pChn->nInc == 0x10000 ) - { pChn->dwFlags |= CHN_NOIDO; - } - else - { if( ((gdwSoundSetup & SNDMIX_HQRESAMPLER) == 0) && ((gdwSoundSetup & SNDMIX_ULTRAHQSRCMODE) == 0) ) - { if (pChn->nInc >= 0xFF00) pChn->dwFlags |= CHN_NOIDO; - } - } - } - pChn->nNewRightVol >>= MIXING_ATTENUATION; - pChn->nNewLeftVol >>= MIXING_ATTENUATION; - pChn->nRightRamp = pChn->nLeftRamp = 0; - // Dolby Pro-Logic Surround - if ((pChn->dwFlags & CHN_SURROUND) && (gnChannels <= 2)) pChn->nNewLeftVol = - pChn->nNewLeftVol; - // Checking Ping-Pong Loops - if (pChn->dwFlags & CHN_PINGPONGFLAG) pChn->nInc = -pChn->nInc; - // Setting up volume ramp - if ((pChn->dwFlags & CHN_VOLUMERAMP) - && ((pChn->nRightVol != pChn->nNewRightVol) - || (pChn->nLeftVol != pChn->nNewLeftVol))) - { - LONG nRampLength = gnVolumeRampSamples; - LONG nRightDelta = ((pChn->nNewRightVol - pChn->nRightVol) << VOLUMERAMPPRECISION); - LONG nLeftDelta = ((pChn->nNewLeftVol - pChn->nLeftVol) << VOLUMERAMPPRECISION); -#ifndef MODPLUG_FASTSOUNDLIB - if ((gdwSoundSetup & SNDMIX_DIRECTTODISK) - || ((gdwSysInfo & (SYSMIX_ENABLEMMX|SYSMIX_FASTCPU)) - && (gdwSoundSetup & SNDMIX_HQRESAMPLER) && (gnCPUUsage <= 20))) - { - if ((pChn->nRightVol|pChn->nLeftVol) && (pChn->nNewRightVol|pChn->nNewLeftVol) && (!(pChn->dwFlags & CHN_FASTVOLRAMP))) - { - nRampLength = m_nBufferCount; - if (nRampLength > (1 << (VOLUMERAMPPRECISION-1))) nRampLength = (1 << (VOLUMERAMPPRECISION-1)); - if (nRampLength < (LONG)gnVolumeRampSamples) nRampLength = gnVolumeRampSamples; - } - } -#endif - pChn->nRightRamp = nRightDelta / nRampLength; - pChn->nLeftRamp = nLeftDelta / nRampLength; - pChn->nRightVol = pChn->nNewRightVol - ((pChn->nRightRamp * nRampLength) >> VOLUMERAMPPRECISION); - pChn->nLeftVol = pChn->nNewLeftVol - ((pChn->nLeftRamp * nRampLength) >> VOLUMERAMPPRECISION); - if (pChn->nRightRamp|pChn->nLeftRamp) - { - pChn->nRampLength = nRampLength; - } else - { - pChn->dwFlags &= ~CHN_VOLUMERAMP; - pChn->nRightVol = pChn->nNewRightVol; - pChn->nLeftVol = pChn->nNewLeftVol; - } - } else - { - pChn->dwFlags &= ~CHN_VOLUMERAMP; - pChn->nRightVol = pChn->nNewRightVol; - pChn->nLeftVol = pChn->nNewLeftVol; - } - pChn->nRampRightVol = pChn->nRightVol << VOLUMERAMPPRECISION; - pChn->nRampLeftVol = pChn->nLeftVol << VOLUMERAMPPRECISION; - // Adding the channel in the channel list - ChnMix[m_nMixChannels++] = nChn; - if (m_nMixChannels >= MAX_CHANNELS) break; - } else - { -#ifdef ENABLE_STEREOVU - // Note change but no sample - if (pChn->nLeftVU > 128) pChn->nLeftVU = 0; - if (pChn->nRightVU > 128) pChn->nRightVU = 0; -#endif - if (pChn->nVUMeter > 0xFF) pChn->nVUMeter = 0; - pChn->nLeftVol = pChn->nRightVol = 0; - pChn->nLength = 0; - } - } - // Checking Max Mix Channels reached: ordering by volume - if ((m_nMixChannels >= m_nMaxMixChannels) && (!(gdwSoundSetup & SNDMIX_DIRECTTODISK))) - { - for (UINT i=0; i<m_nMixChannels; i++) - { - UINT j=i; - while ((j+1<m_nMixChannels) && (Chn[ChnMix[j]].nRealVolume < Chn[ChnMix[j+1]].nRealVolume)) - { - UINT n = ChnMix[j]; - ChnMix[j] = ChnMix[j+1]; - ChnMix[j+1] = n; - j++; - } - } - } - if (m_dwSongFlags & SONG_GLOBALFADE) - { - if (!m_nGlobalFadeSamples) - { - m_dwSongFlags |= SONG_ENDREACHED; - return FALSE; - } - if (m_nGlobalFadeSamples > m_nBufferCount) - m_nGlobalFadeSamples -= m_nBufferCount; - else - m_nGlobalFadeSamples = 0; - } - return TRUE; -} - - diff --git a/lib/libmodplug/src/tables.h b/lib/libmodplug/src/tables.h deleted file mode 100755 index a572caef86..0000000000 --- a/lib/libmodplug/src/tables.h +++ /dev/null @@ -1,376 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque <olivierl@jps.net> - */ - -#include "libmodplug/stdafx.h" -#include "libmodplug/sndfile.h" - -#ifndef MODPLUG_FASTSOUNDLIB -//#pragma data_seg(".tables") -#endif - -static const BYTE ImpulseTrackerPortaVolCmd[16] = -{ - 0x00, 0x01, 0x04, 0x08, 0x10, 0x20, 0x40, 0x60, - 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - -// Period table for Protracker octaves 0-5: -static const WORD ProTrackerPeriodTable[6*12] = -{ - 1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,907, - 856,808,762,720,678,640,604,570,538,508,480,453, - 428,404,381,360,339,320,302,285,269,254,240,226, - 214,202,190,180,170,160,151,143,135,127,120,113, - 107,101,95,90,85,80,75,71,67,63,60,56, - 53,50,47,45,42,40,37,35,33,31,30,28 -}; - - -static const WORD ProTrackerTunedPeriods[16*12] = -{ - 1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,907, - 1700,1604,1514,1430,1348,1274,1202,1134,1070,1010,954,900, - 1688,1592,1504,1418,1340,1264,1194,1126,1064,1004,948,894, - 1676,1582,1492,1408,1330,1256,1184,1118,1056,996,940,888, - 1664,1570,1482,1398,1320,1246,1176,1110,1048,990,934,882, - 1652,1558,1472,1388,1310,1238,1168,1102,1040,982,926,874, - 1640,1548,1460,1378,1302,1228,1160,1094,1032,974,920,868, - 1628,1536,1450,1368,1292,1220,1150,1086,1026,968,914,862, - 1814,1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960, - 1800,1700,1604,1514,1430,1350,1272,1202,1134,1070,1010,954, - 1788,1688,1592,1504,1418,1340,1264,1194,1126,1064,1004,948, - 1774,1676,1582,1492,1408,1330,1256,1184,1118,1056,996,940, - 1762,1664,1570,1482,1398,1320,1246,1176,1110,1048,988,934, - 1750,1652,1558,1472,1388,1310,1238,1168,1102,1040,982,926, - 1736,1640,1548,1460,1378,1302,1228,1160,1094,1032,974,920, - 1724,1628,1536,1450,1368,1292,1220,1150,1086,1026,968,914 -}; - - -// S3M C-4 periods -static const WORD FreqS3MTable[16] = -{ - 1712,1616,1524,1440,1356,1280, - 1208,1140,1076,1016,960,907, - 0,0,0,0 -}; - - -// S3M FineTune frequencies -static const WORD S3MFineTuneTable[16] = -{ - 7895,7941,7985,8046,8107,8169,8232,8280, - 8363,8413,8463,8529,8581,8651,8723,8757, // 8363*2^((i-8)/(12*8)) -}; - - -// Sinus table -static const int16_t ModSinusTable[64] = -{ - 0,12,25,37,49,60,71,81,90,98,106,112,117,122,125,126, - 127,126,125,122,117,112,106,98,90,81,71,60,49,37,25,12, - 0,-12,-25,-37,-49,-60,-71,-81,-90,-98,-106,-112,-117,-122,-125,-126, - -127,-126,-125,-122,-117,-112,-106,-98,-90,-81,-71,-60,-49,-37,-25,-12 -}; - -// Triangle wave table (ramp down) -static const int16_t ModRampDownTable[64] = -{ - 0,-4,-8,-12,-16,-20,-24,-28,-32,-36,-40,-44,-48,-52,-56,-60, - -64,-68,-72,-76,-80,-84,-88,-92,-96,-100,-104,-108,-112,-116,-120,-124, - 127,123,119,115,111,107,103,99,95,91,87,83,79,75,71,67, - 63,59,55,51,47,43,39,35,31,27,23,19,15,11,7,3 -}; - -// Square wave table -static const int16_t ModSquareTable[64] = -{ - 127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127, - 127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127, - -127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127, - -127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127 -}; - -// Random wave table -static const int16_t ModRandomTable[64] = -{ - 98,-127,-43,88,102,41,-65,-94,125,20,-71,-86,-70,-32,-16,-96, - 17,72,107,-5,116,-69,-62,-40,10,-61,65,109,-18,-38,-13,-76, - -23,88,21,-94,8,106,21,-112,6,109,20,-88,-30,9,-127,118, - 42,-34,89,-4,-51,-72,21,-29,112,123,84,-101,-92,98,-54,-95 -}; - - -// volume fade tables for Retrig Note: -static const int8_t retrigTable1[16] = -{ 0, 0, 0, 0, 0, 0, 10, 8, 0, 0, 0, 0, 0, 0, 24, 32 }; - -static const int8_t retrigTable2[16] = -{ 0, -1, -2, -4, -8, -16, 0, 0, 0, 1, 2, 4, 8, 16, 0, 0 }; - - - -static const WORD XMPeriodTable[104] = -{ - 907,900,894,887,881,875,868,862,856,850,844,838,832,826,820,814, - 808,802,796,791,785,779,774,768,762,757,752,746,741,736,730,725, - 720,715,709,704,699,694,689,684,678,675,670,665,660,655,651,646, - 640,636,632,628,623,619,614,610,604,601,597,592,588,584,580,575, - 570,567,563,559,555,551,547,543,538,535,532,528,524,520,516,513, - 508,505,502,498,494,491,487,484,480,477,474,470,467,463,460,457, - 453,450,447,443,440,437,434,431 -}; - - -static const uint32_t XMLinearTable[768] = -{ - 535232,534749,534266,533784,533303,532822,532341,531861, - 531381,530902,530423,529944,529466,528988,528511,528034, - 527558,527082,526607,526131,525657,525183,524709,524236, - 523763,523290,522818,522346,521875,521404,520934,520464, - 519994,519525,519057,518588,518121,517653,517186,516720, - 516253,515788,515322,514858,514393,513929,513465,513002, - 512539,512077,511615,511154,510692,510232,509771,509312, - 508852,508393,507934,507476,507018,506561,506104,505647, - 505191,504735,504280,503825,503371,502917,502463,502010, - 501557,501104,500652,500201,499749,499298,498848,498398, - 497948,497499,497050,496602,496154,495706,495259,494812, - 494366,493920,493474,493029,492585,492140,491696,491253, - 490809,490367,489924,489482,489041,488600,488159,487718, - 487278,486839,486400,485961,485522,485084,484647,484210, - 483773,483336,482900,482465,482029,481595,481160,480726, - 480292,479859,479426,478994,478562,478130,477699,477268, - 476837,476407,475977,475548,475119,474690,474262,473834, - 473407,472979,472553,472126,471701,471275,470850,470425, - 470001,469577,469153,468730,468307,467884,467462,467041, - 466619,466198,465778,465358,464938,464518,464099,463681, - 463262,462844,462427,462010,461593,461177,460760,460345, - 459930,459515,459100,458686,458272,457859,457446,457033, - 456621,456209,455797,455386,454975,454565,454155,453745, - 453336,452927,452518,452110,451702,451294,450887,450481, - 450074,449668,449262,448857,448452,448048,447644,447240, - 446836,446433,446030,445628,445226,444824,444423,444022, - 443622,443221,442821,442422,442023,441624,441226,440828, - 440430,440033,439636,439239,438843,438447,438051,437656, - 437261,436867,436473,436079,435686,435293,434900,434508, - 434116,433724,433333,432942,432551,432161,431771,431382, - 430992,430604,430215,429827,429439,429052,428665,428278, - 427892,427506,427120,426735,426350,425965,425581,425197, - 424813,424430,424047,423665,423283,422901,422519,422138, - 421757,421377,420997,420617,420237,419858,419479,419101, - 418723,418345,417968,417591,417214,416838,416462,416086, - 415711,415336,414961,414586,414212,413839,413465,413092, - 412720,412347,411975,411604,411232,410862,410491,410121, - 409751,409381,409012,408643,408274,407906,407538,407170, - 406803,406436,406069,405703,405337,404971,404606,404241, - 403876,403512,403148,402784,402421,402058,401695,401333, - 400970,400609,400247,399886,399525,399165,398805,398445, - 398086,397727,397368,397009,396651,396293,395936,395579, - 395222,394865,394509,394153,393798,393442,393087,392733, - 392378,392024,391671,391317,390964,390612,390259,389907, - 389556,389204,388853,388502,388152,387802,387452,387102, - 386753,386404,386056,385707,385359,385012,384664,384317, - 383971,383624,383278,382932,382587,382242,381897,381552, - 381208,380864,380521,380177,379834,379492,379149,378807, - - 378466,378124,377783,377442,377102,376762,376422,376082, - 375743,375404,375065,374727,374389,374051,373714,373377, - 373040,372703,372367,372031,371695,371360,371025,370690, - 370356,370022,369688,369355,369021,368688,368356,368023, - 367691,367360,367028,366697,366366,366036,365706,365376, - 365046,364717,364388,364059,363731,363403,363075,362747, - 362420,362093,361766,361440,361114,360788,360463,360137, - 359813,359488,359164,358840,358516,358193,357869,357547, - 357224,356902,356580,356258,355937,355616,355295,354974, - 354654,354334,354014,353695,353376,353057,352739,352420, - 352103,351785,351468,351150,350834,350517,350201,349885, - 349569,349254,348939,348624,348310,347995,347682,347368, - 347055,346741,346429,346116,345804,345492,345180,344869, - 344558,344247,343936,343626,343316,343006,342697,342388, - 342079,341770,341462,341154,340846,340539,340231,339924, - 339618,339311,339005,338700,338394,338089,337784,337479, - 337175,336870,336566,336263,335959,335656,335354,335051, - 334749,334447,334145,333844,333542,333242,332941,332641, - 332341,332041,331741,331442,331143,330844,330546,330247, - 329950,329652,329355,329057,328761,328464,328168,327872, - 327576,327280,326985,326690,326395,326101,325807,325513, - 325219,324926,324633,324340,324047,323755,323463,323171, - 322879,322588,322297,322006,321716,321426,321136,320846, - 320557,320267,319978,319690,319401,319113,318825,318538, - 318250,317963,317676,317390,317103,316817,316532,316246, - 315961,315676,315391,315106,314822,314538,314254,313971, - 313688,313405,313122,312839,312557,312275,311994,311712, - 311431,311150,310869,310589,310309,310029,309749,309470, - 309190,308911,308633,308354,308076,307798,307521,307243, - 306966,306689,306412,306136,305860,305584,305308,305033, - 304758,304483,304208,303934,303659,303385,303112,302838, - 302565,302292,302019,301747,301475,301203,300931,300660, - 300388,300117,299847,299576,299306,299036,298766,298497, - 298227,297958,297689,297421,297153,296884,296617,296349, - 296082,295815,295548,295281,295015,294749,294483,294217, - 293952,293686,293421,293157,292892,292628,292364,292100, - 291837,291574,291311,291048,290785,290523,290261,289999, - 289737,289476,289215,288954,288693,288433,288173,287913, - 287653,287393,287134,286875,286616,286358,286099,285841, - 285583,285326,285068,284811,284554,284298,284041,283785, - 283529,283273,283017,282762,282507,282252,281998,281743, - 281489,281235,280981,280728,280475,280222,279969,279716, - 279464,279212,278960,278708,278457,278206,277955,277704, - 277453,277203,276953,276703,276453,276204,275955,275706, - 275457,275209,274960,274712,274465,274217,273970,273722, - 273476,273229,272982,272736,272490,272244,271999,271753, - 271508,271263,271018,270774,270530,270286,270042,269798, - 269555,269312,269069,268826,268583,268341,268099,267857 -}; - - -static const int8_t ft2VibratoTable[256] = -{ - 0,-2,-3,-5,-6,-8,-9,-11,-12,-14,-16,-17,-19,-20,-22,-23, - -24,-26,-27,-29,-30,-32,-33,-34,-36,-37,-38,-39,-41,-42, - -43,-44,-45,-46,-47,-48,-49,-50,-51,-52,-53,-54,-55,-56, - -56,-57,-58,-59,-59,-60,-60,-61,-61,-62,-62,-62,-63,-63, - -63,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-63,-63, - -63,-62,-62,-62,-61,-61,-60,-60,-59,-59,-58,-57,-56,-56, - -55,-54,-53,-52,-51,-50,-49,-48,-47,-46,-45,-44,-43,-42, - -41,-39,-38,-37,-36,-34,-33,-32,-30,-29,-27,-26,-24,-23, - -22,-20,-19,-17,-16,-14,-12,-11,-9,-8,-6,-5,-3,-2,0, - 2,3,5,6,8,9,11,12,14,16,17,19,20,22,23,24,26,27,29,30, - 32,33,34,36,37,38,39,41,42,43,44,45,46,47,48,49,50,51, - 52,53,54,55,56,56,57,58,59,59,60,60,61,61,62,62,62,63, - 63,63,64,64,64,64,64,64,64,64,64,64,64,63,63,63,62,62, - 62,61,61,60,60,59,59,58,57,56,56,55,54,53,52,51,50,49, - 48,47,46,45,44,43,42,41,39,38,37,36,34,33,32,30,29,27, - 26,24,23,22,20,19,17,16,14,12,11,9,8,6,5,3,2 -}; - - - -static const DWORD FineLinearSlideUpTable[16] = -{ - 65536, 65595, 65654, 65714, 65773, 65832, 65892, 65951, - 66011, 66071, 66130, 66190, 66250, 66309, 66369, 66429 -}; - - -static const DWORD FineLinearSlideDownTable[16] = -{ - 65535, 65477, 65418, 65359, 65300, 65241, 65182, 65123, - 65065, 65006, 64947, 64888, 64830, 64772, 64713, 64645 -}; - - -static const DWORD LinearSlideUpTable[256] = -{ - 65536, 65773, 66010, 66249, 66489, 66729, 66971, 67213, - 67456, 67700, 67945, 68190, 68437, 68685, 68933, 69182, - 69432, 69684, 69936, 70189, 70442, 70697, 70953, 71209, - 71467, 71725, 71985, 72245, 72507, 72769, 73032, 73296, - 73561, 73827, 74094, 74362, 74631, 74901, 75172, 75444, - 75717, 75991, 76265, 76541, 76818, 77096, 77375, 77655, - 77935, 78217, 78500, 78784, 79069, 79355, 79642, 79930, - 80219, 80509, 80800, 81093, 81386, 81680, 81976, 82272, - 82570, 82868, 83168, 83469, 83771, 84074, 84378, 84683, - 84989, 85297, 85605, 85915, 86225, 86537, 86850, 87164, - 87480, 87796, 88113, 88432, 88752, 89073, 89395, 89718, - 90043, 90369, 90695, 91023, 91353, 91683, 92015, 92347, - 92681, 93017, 93353, 93691, 94029, 94370, 94711, 95053, - 95397, 95742, 96088, 96436, 96785, 97135, 97486, 97839, - 98193, 98548, 98904, 99262, 99621, 99981, 100343, 100706, - 101070, 101435, 101802, 102170, 102540, 102911, 103283, 103657, - 104031, 104408, 104785, 105164, 105545, 105926, 106309, 106694, - 107080, 107467, 107856, 108246, 108637, 109030, 109425, 109820, - 110217, 110616, 111016, 111418, 111821, 112225, 112631, 113038, - 113447, 113857, 114269, 114682, 115097, 115514, 115931, 116351, - 116771, 117194, 117618, 118043, 118470, 118898, 119328, 119760, - 120193, 120628, 121064, 121502, 121941, 122382, 122825, 123269, - 123715, 124162, 124611, 125062, 125514, 125968, 126424, 126881, - 127340, 127801, 128263, 128727, 129192, 129660, 130129, 130599, - 131072, 131546, 132021, 132499, 132978, 133459, 133942, 134426, - 134912, 135400, 135890, 136381, 136875, 137370, 137866, 138365, - 138865, 139368, 139872, 140378, 140885, 141395, 141906, 142419, - 142935, 143451, 143970, 144491, 145014, 145538, 146064, 146593, - 147123, 147655, 148189, 148725, 149263, 149803, 150344, 150888, - 151434, 151982, 152531, 153083, 153637, 154192, 154750, 155310, - 155871, 156435, 157001, 157569, 158138, 158710, 159284, 159860, - 160439, 161019, 161601, 162186, 162772, 163361, 163952, 164545, -}; - - -static const DWORD LinearSlideDownTable[256] = -{ - 65536, 65299, 65064, 64830, 64596, 64363, 64131, 63900, - 63670, 63440, 63212, 62984, 62757, 62531, 62305, 62081, - 61857, 61634, 61412, 61191, 60970, 60751, 60532, 60314, - 60096, 59880, 59664, 59449, 59235, 59021, 58809, 58597, - 58385, 58175, 57965, 57757, 57548, 57341, 57134, 56928, - 56723, 56519, 56315, 56112, 55910, 55709, 55508, 55308, - 55108, 54910, 54712, 54515, 54318, 54123, 53928, 53733, - - 53540, 53347, 53154, 52963, 52772, 52582, 52392, 52204, - 52015, 51828, 51641, 51455, 51270, 51085, 50901, 50717, - 50535, 50353, 50171, 49990, 49810, 49631, 49452, 49274, - 49096, 48919, 48743, 48567, 48392, 48218, 48044, 47871, - 47698, 47526, 47355, 47185, 47014, 46845, 46676, 46508, - 46340, 46173, 46007, 45841, 45676, 45511, 45347, 45184, - 45021, 44859, 44697, 44536, 44376, 44216, 44056, 43898, - 43740, 43582, 43425, 43268, 43112, 42957, 42802, 42648, - 42494, 42341, 42189, 42037, 41885, 41734, 41584, 41434, - 41285, 41136, 40988, 40840, 40693, 40546, 40400, 40254, - 40109, 39965, 39821, 39677, 39534, 39392, 39250, 39108, - 38967, 38827, 38687, 38548, 38409, 38270, 38132, 37995, - 37858, 37722, 37586, 37450, 37315, 37181, 37047, 36913, - 36780, 36648, 36516, 36384, 36253, 36122, 35992, 35862, - 35733, 35604, 35476, 35348, 35221, 35094, 34968, 34842, - 34716, 34591, 34466, 34342, 34218, 34095, 33972, 33850, - 33728, 33606, 33485, 33364, 33244, 33124, 33005, 32886, - 32768, 32649, 32532, 32415, 32298, 32181, 32065, 31950, - 31835, 31720, 31606, 31492, 31378, 31265, 31152, 31040, - 30928, 30817, 30706, 30595, 30485, 30375, 30266, 30157, - 30048, 29940, 29832, 29724, 29617, 29510, 29404, 29298, - 29192, 29087, 28982, 28878, 28774, 28670, 28567, 28464, - 28361, 28259, 28157, 28056, 27955, 27854, 27754, 27654, - 27554, 27455, 27356, 27257, 27159, 27061, 26964, 26866, - 26770, 26673, 26577, 26481, 26386, 26291, 26196, 26102, -}; - - -static const int SpectrumSinusTable[256*2] = -{ - 0, 1, 1, 2, 3, 3, 4, 5, 6, 7, 7, 8, 9, 10, 10, 11, - 12, 13, 14, 14, 15, 16, 17, 17, 18, 19, 20, 20, 21, 22, 22, 23, - 24, 25, 25, 26, 27, 28, 28, 29, 30, 30, 31, 32, 32, 33, 34, 34, - 35, 36, 36, 37, 38, 38, 39, 39, 40, 41, 41, 42, 42, 43, 44, 44, - 45, 45, 46, 46, 47, 47, 48, 48, 49, 49, 50, 50, 51, 51, 52, 52, - 53, 53, 53, 54, 54, 55, 55, 55, 56, 56, 57, 57, 57, 58, 58, 58, - 59, 59, 59, 59, 60, 60, 60, 60, 61, 61, 61, 61, 61, 62, 62, 62, - 62, 62, 62, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 62, 62, - 62, 62, 62, 62, 61, 61, 61, 61, 61, 60, 60, 60, 60, 59, 59, 59, - 59, 58, 58, 58, 57, 57, 57, 56, 56, 55, 55, 55, 54, 54, 53, 53, - 53, 52, 52, 51, 51, 50, 50, 49, 49, 48, 48, 47, 47, 46, 46, 45, - 45, 44, 44, 43, 42, 42, 41, 41, 40, 39, 39, 38, 38, 37, 36, 36, - 35, 34, 34, 33, 32, 32, 31, 30, 30, 29, 28, 28, 27, 26, 25, 25, - 24, 23, 22, 22, 21, 20, 20, 19, 18, 17, 17, 16, 15, 14, 14, 13, - 12, 11, 10, 10, 9, 8, 7, 7, 6, 5, 4, 3, 3, 2, 1, 0, - 0, -1, -1, -2, -3, -3, -4, -5, -6, -7, -7, -8, -9, -10, -10, -11, - -12, -13, -14, -14, -15, -16, -17, -17, -18, -19, -20, -20, -21, -22, -22, -23, - -24, -25, -25, -26, -27, -28, -28, -29, -30, -30, -31, -32, -32, -33, -34, -34, - -35, -36, -36, -37, -38, -38, -39, -39, -40, -41, -41, -42, -42, -43, -44, -44, - -45, -45, -46, -46, -47, -47, -48, -48, -49, -49, -50, -50, -51, -51, -52, -52, - -53, -53, -53, -54, -54, -55, -55, -55, -56, -56, -57, -57, -57, -58, -58, -58, - -59, -59, -59, -59, -60, -60, -60, -60, -61, -61, -61, -61, -61, -62, -62, -62, - -62, -62, -62, -63, -63, -63, -63, -63, -63, -63, -63, -63, -63, -63, -63, -63, - -63, -63, -63, -63, -63, -63, -63, -63, -63, -63, -63, -63, -63, -63, -62, -62, - -62, -62, -62, -62, -61, -61, -61, -61, -61, -60, -60, -60, -60, -59, -59, -59, - -59, -58, -58, -58, -57, -57, -57, -56, -56, -55, -55, -55, -54, -54, -53, -53, - -53, -52, -52, -51, -51, -50, -50, -49, -49, -48, -48, -47, -47, -46, -46, -45, - -45, -44, -44, -43, -42, -42, -41, -41, -40, -39, -39, -38, -38, -37, -36, -36, - -35, -34, -34, -33, -32, -32, -31, -30, -30, -29, -28, -28, -27, -26, -25, -25, - -24, -23, -22, -22, -21, -20, -20, -19, -18, -17, -17, -16, -15, -14, -14, -13, - -12, -11, -10, -10, -9, -8, -7, -7, -6, -5, -4, -3, -3, -2, -1, 0, -}; - |