Initial Commit

This commit is contained in:
Godzil
2019-09-01 21:43:40 +01:00
commit 56b69d2281
176 changed files with 41262 additions and 0 deletions

View File

@@ -0,0 +1,36 @@
# Makefile for BeOS Release 4 operating systems
CC = gcc
AR = ar
AS = nasm
CFLAGS = -c -O3 -Wall -Wno-multichar -D__ASM__ -D__FLAT__
ARFLAGS = cr
LIBS = -L../lib/BeOS/ -laudio -lroot -lbe -lmedia
OBJS = audio.o wavfile.o xmfile.o s3mfile.o modfile.o mtmfile.o \
iofile.o modeng.o nondrv.o mixdrv.o _mixdrv.o be3drv.o bedrv.o
LIB = ../lib/BeOS/libaudio.a
all : mp clean
@echo done.
mp : mp.o $(LIB)
$(CC) -o mp mp.o $(LIBS)
$(LIB) : $(OBJS)
$(AR) $(ARFLAGS) $(LIB) $(OBJS)
.SUFFIXES: .c .cpp .h .obj
.c.o:
$(CC) $(CFLAGS) $<
.cpp.o:
$(CC) $(CFLAGS) $<
.asm.o:
$(AS) $<
clean :
@rm -rf *.o

View File

@@ -0,0 +1,45 @@
/* audio_driver.h */
/* Jon Watte 19971223 */
/* Interface to drivers found in /dev/audio */
/* Devices found in /dev/old follow a different API! */
#if !defined(_AUDIO_DRIVER_H)
#define _AUDIO_DRIVER_H
#if !defined(_SUPPORT_DEFS_H)
#include <SupportDefs.h>
#endif /* _SUPPORT_DEFS_H */
#if !defined(_DRIVERS_H)
#include <Drivers.h>
#endif /* _DRIVERS_H */
enum {
/* arg = ptr to struct audio_format */
B_AUDIO_GET_AUDIO_FORMAT = B_AUDIO_DRIVER_BASE,
B_AUDIO_SET_AUDIO_FORMAT,
/* arg = ptr to float[4] */
B_AUDIO_GET_PREFERRED_SAMPLE_RATES
};
/* this is the definition of what the audio driver can do for you */
typedef struct audio_format {
float sample_rate; /* ~4000 - ~48000, maybe more */
int32 channels; /* 1 or 2 */
int32 format; /* 0x11 (uchar), 0x2 (short) or 0x24 (float) */
int32 big_endian; /* 0 for little endian, 1 for big endian */
size_t buf_header; /* typically 0 or 16 */
size_t play_buf_size; /* size of playback buffer (latency) */
size_t rec_buf_size; /* size of record buffer (latency) */
} audio_format;
/* when buffer header is in effect, this is what gets read before data */
typedef struct audio_buf_header {
bigtime_t capture_time;
uint32 capture_size;
float sample_rate;
} audio_buf_header;
#endif /* _AUDIO_DRIVER_H */

View File

@@ -0,0 +1,86 @@
/* audio_driver.h - BeOS Release 3 interface to sound drivers */
#ifndef _AUDIO_DRIVER_H_
#define _AUDIO_DRIVER_H_
#include <Drivers.h>
enum {
B_AUDIO_GET_PARAMS = B_DEVICE_OP_CODES_END,
B_AUDIO_SET_PARAMS,
B_AUDIO_SET_PLAYBACK_COMPLETION_SEM,
B_AUDIO_SET_CAPTURE_COMPLETION_SEM,
B_AUDIO_RESERVED_1, /* unused */
B_AUDIO_RESERVED_2, /* unused */
B_AUDIO_DEBUG_ON, /* unused */
B_AUDIO_DEBUG_OFF, /* unused */
B_AUDIO_WRITE_BUFFER,
B_AUDIO_READ_BUFFER,
B_AUDIO_LOCK_FOR_DMA
};
enum {
B_AUDIO_ADC_SOURCE_LINE = 0,
B_AUDIO_ADC_SOURCE_CDROM,
B_AUDIO_ADC_SOURCE_MIC,
B_AUDIO_ADC_SOURCE_LOOPBACK
};
enum {
B_AUDIO_SAMPLE_RATE_8000 = 0,
B_AUDIO_SAMPLE_RATE_5510 = 1,
B_AUDIO_SAMPLE_RATE_16000 = 2,
B_AUDIO_SAMPLE_RATE_11025 = 3,
B_AUDIO_SAMPLE_RATE_27420 = 4,
B_AUDIO_SAMPLE_RATE_18900 = 5,
B_AUDIO_SAMPLE_RATE_32000 = 6,
B_AUDIO_SAMPLE_RATE_22050 = 7,
B_AUDIO_SAMPLE_RATE_37800 = 9,
B_AUDIO_SAMPLE_RATE_44100 = 11,
B_AUDIO_SAMPLE_RATE_48000 = 12,
B_AUDIO_SAMPLE_RATE_33075 = 13,
B_AUDIO_SAMPLE_RATE_9600 = 14,
B_AUDIO_SAMPLE_RATE_6620 = 15
};
struct audio_channel {
uint32 adc_source; /* adc input source */
char adc_gain; /* 0-15 adc gain, in 1.5 dB steps */
char mic_gain_enable; /* non-zero enables 20 dB MIC input gain */
char cd_mix_gain; /* 0-31 cd mix to output gain in -1.5dB steps */
char cd_mix_mute; /* non-zero mutes cd mix */
char aux2_mix_gain; /* unused */
char aux2_mix_mute; /* unused */
char line_mix_gain; /* 0-31 line mix to out gain in -1.5dB steps */
char line_mix_mute; /* non-zero mutes line mix */
char dac_attn; /* 0-61 dac attenuation, in -1.5 dB steps */
char dac_mute; /* non-zero mutes dac output */
char reserved_1;
char reserved_2;
};
typedef struct audio_params {
struct audio_channel left; /* left channel setup */
struct audio_channel right; /* right channel setup */
uint32 sample_rate; /* sample rate */
uint32 playback_format; /* ignore (always 16bit-linear) */
uint32 capture_format; /* ignore (always 16bit-linear) */
char dither_enable; /* non-zero enables dither on 16 => 8 bit */
char mic_attn; /* 0..64 mic input level */
char mic_enable; /* non-zero enables mic input */
char output_boost; /* ignore (always on) */
char highpass_enable; /* ignore (always on) */
char mono_gain; /* 0..64 mono speaker gain */
char mono_mute; /* non-zero mutes speaker */
} audio_params;
typedef struct audio_buffer_header {
int32 buffer_number;
int32 subscriber_count;
bigtime_t time;
int32 reserved_1;
int32 reserved_2;
bigtime_t sample_clock;
} audio_buffer_header;
#endif

View File

@@ -0,0 +1,33 @@
# Makefile for Borland C++ 4.5 (DPMI16 protected mode, large memory model)
CC = bcc
AS = tasm
AR = tlib
CFLAGS = -ml -WX -c -w9 -3 -O2 -D__DPMI__ -D__16BIT__
AFLAGS = -t -m -q -zi
LFLAGS = -ml -WX
OBJS = audio.obj wavfile.obj xmfile.obj s3mfile.obj modfile.obj mtmfile.obj \
iofile.obj modeng.obj nondrv.obj mixdrv.obj msdos.obj \
sbdrv.obj awedrv.obj pasdrv.obj wssdrv.obj gusdrv.obj ariadrv.obj
LIB = ..\lib\DOS\audiobcx.lib
all : mp.exe $(LIB) clean
@echo done.
mp.exe : mp.obj $(LIB)
$(CC) $(LFLAGS) mp.obj $(LIB)
$(LIB) : $(OBJS)
@if exist $(LIB) del $(LIB) > nul
$(AR) $(LIB) @DOS\DPMI16\Borland\audiobcx.lnk
.c.obj :
$(CC) $(CFLAGS) $<
.asm.obj :
$(AS) $(AFLAGS) $<
clean :
@if exist *.obj del *.obj > nul

View File

@@ -0,0 +1 @@
+audio.obj +wavfile.obj +xmfile.obj +s3mfile.obj +modfile.obj +iofile.obj +modeng.obj +nondrv.obj +mixdrv.obj +msdos.obj +sbdrv.obj +awedrv.obj +pasdrv.obj +wssdrv.obj +gusdrv.obj +ariadrv.obj

View File

@@ -0,0 +1,33 @@
# Makefile for Borland C++ 4.5 (DPMI32 protected mode, flat memory model)
CC = bcc32a
AS = tasm
AR = tlib
CFLAGS = -WX -c -w9 -5 -O2 -D__DPMI__ -D__ASM__
AFLAGS = -t -m -q -ml -zi
LFLAGS = -WX
OBJS = audio.obj wavfile.obj xmfile.obj s3mfile.obj modfile.obj mtmfile.obj \
iofile.obj modeng.obj nondrv.obj mixdrv.obj _mixdrv.obj msdos.obj \
sbdrv.obj awedrv.obj pasdrv.obj wssdrv.obj gusdrv.obj ariadrv.obj
LIB = ..\lib\DOS\audiobcf.lib
all : mp.exe $(LIB) clean
@echo done.
mp.exe : mp.obj $(LIB)
$(CC) $(LFLAGS) mp.obj $(LIB)
$(LIB) : $(OBJS)
@if exist $(LIB) del $(LIB) > nul
$(AR) $(LIB) @DOS\DPMI32\Borland\audiobcf.lnk
.c.obj :
$(CC) $(CFLAGS) $<
.asm.obj :
$(AS) $(AFLAGS) $<
clean :
@if exist *.obj del *.obj > nul

View File

@@ -0,0 +1 @@
+audio.obj +wavfile.obj +xmfile.obj +s3mfile.obj +modfile.obj +iofile.obj +modeng.obj +nondrv.obj +mixdrv.obj +_mixdrv.obj +msdos.obj +sbdrv.obj +awedrv.obj +pasdrv.obj +wssdrv.obj +gusdrv.obj +ariadrv.obj

View File

@@ -0,0 +1,39 @@
# Makefile for DJGPP V2.0 (GO32/DPMI32 protected mode, flat memory model)
CC = gcc
AR = ar
RANLIB = ranlib
STRIP = strip
COFF2EXE = stubify
CFLAGS = -c -Wall -mpentium -O2 -D__DPMI__ -D__ASM__
LFLAGS =
#OBJS = audio.o wavfile.o xmfile.o s3mfile.o modfile.o mtmfile.o \
# iofile.o modeng.o nondrv.o mixdrv.o _mixdrv.o msdos.o \
# sbdrv.o awedrv.o pasdrv.o wssdrv.o gusdrv.o ariadrv.o
OBJS = audiodj.o _mixdrv.o
LIB = ../lib/DOS/libaudio.a
all : mp.exe $(LIB) clean
@echo done.
mp.exe : mp.o $(LIB)
$(CC) -o mp mp.o $(LIB) $(LFLAGS)
$(STRIP) mp
$(COFF2EXE) mp
@del mp > nul
$(LIB) : $(OBJS)
@$(AR) rc $(LIB) $(OBJS)
$(RANLIB) $(LIB)
.c.o :
$(CC) $(CFLAGS) $<
.s.o :
$(CC) $(CFLAGS) $*.S
clean :
@if exist *.o del *.o > nul

View File

@@ -0,0 +1,40 @@
# Makefile for WATCOM C/C++32 10.0 (DOS4GW protected mode, flat memory model)
CC = wcc386
LD = wcl386
AS = tasm
AR = wlib -s -t -q -n
CFLAGS = -zq -zu -w9 -we -5r -s -oxt -D__DPMI__ -D__ASM__
AFLAGS = -t -m -q -ml -zi
LFLAGS = -l=dos4g -zq
#AS = wasm
#AFLAGS = -zq -w9 -we -5r
OBJS = audio.obj wavfile.obj xmfile.obj s3mfile.obj modfile.obj mtmfile.obj \
iofile.obj modeng.obj nondrv.obj mixdrv.obj _mixdrv.obj msdos.obj \
sbdrv.obj awedrv.obj pasdrv.obj wssdrv.obj gusdrv.obj ariadrv.obj
LIB = "..\lib\DOS\audiowcf.lib"
all : mp.exe $(LIB) clean .SYMBOLIC
@echo done.
mp.exe : mp.obj $(LIB)
$(LD) mp.obj $(LIB) $(LFLAGS)
$(LIB) : $(OBJS)
@echo $(OBJS) > audiowcf.lnk
$(AR) $(LIB) @audiowcf.lnk
@del audiowcf.lnk
.SUFFIXES: .c .asm .obj
.c.obj :
$(CC) $(CFLAGS) $<
.asm.obj :
$(AS) $(AFLAGS) $<
clean : .SYMBOLIC
@if exist *.obj del *.obj > nul

View File

@@ -0,0 +1,33 @@
# Makefile for Borland C++ 4.5 (DOS real mode, large memory model)
CC = bcc
AS = tasm
AR = tlib
CFLAGS = -ml -c -w9 -3 -O2 -D__DOS16__ -D__16BIT__
AFLAGS = -t -m -q -zi
LFLAGS = -ml
OBJS = audio.obj wavfile.obj xmfile.obj s3mfile.obj modfile.obj mtmfile.obj \
iofile.obj modeng.obj nondrv.obj mixdrv.obj msdos.obj \
sbdrv.obj awedrv.obj pasdrv.obj wssdrv.obj gusdrv.obj ariadrv.obj
LIB = ..\lib\DOS\audiobcl.lib
all : mp.exe $(LIB) clean
@echo done.
mp.exe : mp.obj $(LIB)
$(CC) $(LFLAGS) mp.obj $(LIB)
$(LIB) : $(OBJS)
@if exist $(LIB) del $(LIB) > nul
$(AR) $(LIB) @DOS\Large\Borland\audiobcl.lnk
.c.obj :
$(CC) $(CFLAGS) $<
.asm.obj :
$(AS) $(AFLAGS) $<
clean :
@if exist *.obj del *.obj > nul

View File

@@ -0,0 +1 @@
+audio.obj +wavfile.obj +xmfile.obj +s3mfile.obj +modfile.obj +iofile.obj +modeng.obj +nondrv.obj +mixdrv.obj +msdos.obj +sbdrv.obj +awedrv.obj +pasdrv.obj +wssdrv.obj +gusdrv.obj +ariadrv.obj

View File

@@ -0,0 +1,32 @@
# Makefile for Watcom C/C++16 (DOS real mode, large memory model)
CC = wcl
AS = tasm
AR = wlib -n -b -q
CFLAGS = -zq -zu -ml -c -w9 -we -5 -s -oxt -D__DOS16__ -D__16BIT__
AFLAGS = -t -m -q -zi
LFLAGS = -zq -ml
OBJS = audio.obj wavfile.obj xmfile.obj s3mfile.obj modfile.obj mtmfile.obj &
iofile.obj modeng.obj nondrv.obj mixdrv.obj msdos.obj &
sbdrv.obj awedrv.obj pasdrv.obj wssdrv.obj gusdrv.obj ariadrv.obj
LIB = ..\lib\DOS\audiowcl.lib
all : mp.exe $(LIB) clean .SYMBOLIC
@echo done.
mp.exe : mp.obj $(LIB)
$(CC) $(LFLAGS) mp.obj $(LIB)
$(LIB) : $(OBJS)
*$(AR) $(LIB) $(OBJS)
.c.obj :
$(CC) $(CFLAGS) $<
.asm.obj :
$(AS) $(AFLAGS) $<
clean : .SYMBOLIC
@if exist *.obj del *.obj > nul

View File

@@ -0,0 +1,30 @@
# Makefile for FreeBSD/386 and VoxWare 2.90 or later
CC = gcc
AR = ar
RANLIB = ranlib
STRIP = strip
CFLAGS = -c -Wall -O2 -fomit-frame-pointer -D__FREEBSD__ -D__ASM__
LFLAGS = -L../lib/FreeBSD -laudio
OBJS = audio.o wavfile.o xmfile.o s3mfile.o modfile.o mtmfile.o \
iofile.o modeng.o nondrv.o mixdrv.o _mixdrv.o lnxdrv.o
LIB = ../lib/FreeBSD/libaudio.a
all : mp $(LIB) clean
@echo done.
mp : mp.o $(LIB)
$(CC) -o mp mp.o $(LFLAGS)
$(STRIP) mp
$(LIB) : $(OBJS)
$(AR) rc $(LIB) $(OBJS)
$(RANLIB) $(LIB)
.c.o .s.o .S.o :
$(CC) $(CFLAGS) $<
clean :
@for f in *.o; do rm -f $$f; done

View File

@@ -0,0 +1,30 @@
# Makefile for Silicon Graphics Indigo IRIX 4.x with audio ports
CC = gcc
AR = ar
RANLIB = ranlib
STRIP = strip
CFLAGS = -c -Wall -O2 -D__SILICON__ -D__BIGENDIAN__
LFLAGS = -laudio -L../lib/Indigo -laudio
OBJS = audio.o wavfile.o xmfile.o s3mfile.o modfile.o mtmfile.o \
iofile.o modeng.o nondrv.o mixdrv.o sgidrv.o
LIB = ../lib/Indigo/libaudio.a
all : mp $(LIB) clean
@echo done.
mp : mp.o $(LIB)
$(CC) -o mp mp.o $(LFLAGS)
$(STRIP) mp
$(LIB) : $(OBJS)
$(AR) rc $(LIB) $(OBJS)
$(RANLIB) $(LIB)
.c.o .s.o .S.o :
$(CC) $(CFLAGS) $<
clean :
@for f in *.o; do rm -f $$f; done

View File

@@ -0,0 +1,34 @@
# Makefile for MacOS X using SDL
CC = clang
AR = ar
RANLIB = ranlib
STRIP = strip
CFLAGS = -c -Wall -O2 -fomit-frame-pointer -D__OSX__ `allegro-config --cflags` -arch i386
LFLAGS = -L../lib/MacOSX -laudio `allegro-config --libs` -arch i386
OBJS = audio.o wavfile.o xmfile.o s3mfile.o modfile.o mtmfile.o \
iofile.o modeng.o nondrv.o mixdrv.o allegdrv.o
#osxdrv.c
# Not supported on x86_64 platforms
#_mixdrv.o
LIB = ../lib/MacOSX/libaudio.a
all : mp $(LIB) clean
@echo done.
mp : mp.o $(LIB)
$(CC) -o mp mp.o $(LFLAGS)
$(STRIP) mp
$(LIB) : $(OBJS)
$(AR) rc $(LIB) $(OBJS)
$(RANLIB) $(LIB)
.c.o .s.o .S.o :
@echo CC $<
@$(CC) $(CFLAGS) $<
clean :
@for f in *.o; do rm -f $$f; done

34
seal-hack/src/Makefile Normal file
View File

@@ -0,0 +1,34 @@
# Makefile for Linux and SDL wrapper driver...
CC = clang
AR = ar
RANLIB = ranlib
STRIP = strip
CFLAGS = -g -c -Wall -O2 -D__SDL__ `sdl-config --cflags` -arch i386
LFLAGS = -L../lib/SDL -laudio `sdl-config --libs` -arch i386
OBJS = audio.o wavfile.o xmfile.o s3mfile.o modfile.o mtmfile.o \
iofile.o modeng.o nondrv.o mixdrv.o sdldrv.o
#_mixdrv.o
LIB = ../lib/SDL/libaudio.a
all: mp $(LIB)
@echo done.
mp : mp.o $(LIB)
$(CC) -o mp mp.o $(LFLAGS)
$(LIB) : $(OBJS)
$(AR) rc $(LIB) $(OBJS)
$(RANLIB) $(LIB)
.c.o:
$(CC) $(CFLAGS) $<
.s.o .S.o :
$(CC) $(CFLAGS) $< -D__LINUX__
clean:
-rm -rf *.o
-rm mp

View File

@@ -0,0 +1,53 @@
# Makefile for OS/2 MMPM with EMX and GCC
#
# To build an OS/2 DLL and the ModPlayer executable,
# just set the MMBASE environment variable to point to
# your MMOS2 base directory, change to the src directory
# and type make -f os2/Makefile. That's all there is
# to it!
MMBASE=f:\mmos2
CC = gcc
CPP = cpp
IMPLIB = implib
CFLAGS = -c -Wall -O3 -Zsys -Zmts -fomit-frame-pointer -D__OS2__ -D__ASM__ -D __32BIT__ -D __FLAT__
DLL = audio.dll
LIB = ../lib/OS2/audio.lib
OBJS = audio.o wavfile.o xmfile.o s3mfile.o modfile.o mtmfile.o \
iofile.o modeng.o nondrv.o _mixdrv.o mixdrv.o os2drv.o
OMFOBJS = audio.obj wavfile.obj xmfile.obj s3mfile.obj modfile.obj \
mtmfile.obj iofile.obj modeng.obj nondrv.obj _mixdrv.obj \
mixdrv.obj os2drv.obj
all : mp.exe
@echo done.
$(DLL) : $(OBJS) mdm.lib
$(CC) -Zsys -Zomf -Zmts -Zso -Zdll -o $(DLL) os2/audio.def -L. -lmdm $(OMFOBJS)
mdm.lib: $(MMBASE)/dll/mdm.dll
$(IMPLIB) mdm.lib $(MMBASE)/dll/mdm.dll
$(LIB): $(DLL)
$(IMPLIB) $(LIB) $(DLL)
mp.exe : $(OBJS) mp.o $(LIB)
emxomf mp.o
$(CC) -Zsys -Zomf -Zmts -Zlinker /STACK:32768 -Zlinker /PMTYPE:VIO -o mp mp.obj -L../lib/OS2 -laudio -lmdm
.c.o:
$(CC) $(CFLAGS) $<
emxomf $*.o
_mixdrv.o: _mixdrv.S
$(CPP) _mixdrv.S | $(AS) -o _mixdrv.o
emxomf _mixdrv.o
clean :
@rm -rf *.obj *.o


View File

@@ -0,0 +1,52 @@
LIBRARY audio INITINSTANCE TERMINSTANCE
DESCRIPTION 'SEAL Audio Library 1.07 for OS/2'
EXPORTS AInitialize
AGetVersion
AGetAudioNumDevs
AGetAudioDevCaps
AGetErrorText
APingAudio
AOpenAudio
ACloseAudio
AUpdateAudio
AOpenVoices
ACloseVoices
ASetAudioCallback
ASetAudioTimerProc
ASetAudioTimerRate
AGetAudioDataAvail
ACreateAudioData
ADestroyAudioData
AWriteAudioData
ACreateAudioVoice
ADestroyAudioVoice
APlayVoice
APrimeVoice
AStartVoice
AStopVoice
ASetVoicePosition
ASetVoiceFrequency
ASetVoiceVolume
ASetVoicePanning
AGetVoicePosition
AGetVoiceFrequency
AGetVoiceVolume
AGetVoicePanning
AGetVoiceStatus
APlayModule
AStopModule
APauseModule
AResumeModule
ASetModuleVolume
ASetModulePosition
AGetModuleVolume
AGetModulePosition
AGetModuleStatus
ASetModuleCallback
ALoadModuleFile
AFreeModuleFile
ALoadWaveFile
AFreeWaveFile
AGetModuleTrack
ASetAudioMixerValue
AUpdateAudioEx

View File

@@ -0,0 +1,30 @@
# Makefile for SPARC 10 Solaris 2.x with dbri or AMD ulaw audio device
CC = gcc
AR = ar
RANLIB = ranlib
STRIP = strip
CFLAGS = -c -Wall -O2 -D__SOLARIS__ -D__BIGENDIAN__
LFLAGS = -L../lib/Solaris -laudio
OBJS = audio.o wavfile.o xmfile.o s3mfile.o modfile.o mtmfile.o \
iofile.o modeng.o nondrv.o mixdrv.o sundrv.o
LIB = ../lib/Solaris/libaudio.a
all : mp $(LIB) clean
@echo done.
mp : mp.o $(LIB)
$(CC) -o mp mp.o $(LFLAGS)
$(STRIP) mp
$(LIB) : $(OBJS)
$(AR) rc $(LIB) $(OBJS)
$(RANLIB) $(LIB)
.c.o .s.o .S.o :
$(CC) $(CFLAGS) $<
clean :
@rm -rf *.o

View File

@@ -0,0 +1,30 @@
# Makefile for SPARC 1/2/IPX/... SunOS 4.1.x with AMD ulaw audio device
CC = gcc
AR = ar
RANLIB = ranlib
STRIP = strip
CFLAGS = -c -Wall -O2 -D__SPARC__ -D__BIGENDIAN__
LFLAGS = -L../lib/SunOS -laudio
OBJS = audio.o wavfile.o xmfile.o s3mfile.o modfile.o mtmfile.o \
iofile.o modeng.o nondrv.o mixdrv.o sundrv.o
LIB = ../lib/SunOS/libaudio.a
all : mp $(LIB) clean
@echo done.
mp : mp.o $(LIB)
$(CC) -o mp mp.o $(LFLAGS)
$(STRIP) mp
$(LIB) : $(OBJS)
$(AR) rc $(LIB) $(OBJS)
$(RANLIB) $(LIB)
.c.o .s.o .S.o :
$(CC) $(CFLAGS) $<
clean :
@rm -rf *.o

View File

@@ -0,0 +1,32 @@
# Makefile for Borland C++ 4.5 (Win16 protected mode, large memory model)
CC = bcc
AS = tasm
AR = tlib
CFLAGS = -ml -W -c -w9 -3 -O2 -D__WINDOWS__ -D__16BIT__
AFLAGS = -t -m -q -zi
LFLAGS = -ml -W
OBJS = audio.obj wavfile.obj xmfile.obj s3mfile.obj modfile.obj mtmfile.obj \
iofile.obj modeng.obj nondrv.obj mixdrv.obj windrv.obj
LIB = ..\lib\Win16\audw16bc.lib
all : mp.exe $(LIB) clean
@echo done.
mp.exe : mp.obj $(LIB)
$(CC) $(LFLAGS) mp.obj $(LIB)
$(LIB) : $(OBJS)
@if exist $(LIB) del $(LIB) > nul
$(AR) $(LIB) @Windows\Win16\Borland\audw16bc.lnk
.c.obj :
$(CC) $(CFLAGS) $<
.asm.obj :
$(AS) $(AFLAGS) $<
clean :
@if exist *.obj del *.obj > nul

View File

@@ -0,0 +1 @@
+audio.obj +wavfile.obj +xmfile.obj +s3mfile.obj +modfile.obj +iofile.obj +modeng.obj +nondrv.obj +mixdrv.obj +windrv.obj

View File

@@ -0,0 +1,31 @@
# Makefile for WATCOM C/C++16 10.0 (Win16 protected mode, large memory model)
CC = wcl
AS = tasm
AR = wlib -b -n -q
CFLAGS = -zq -zw -ml -c -w9 -we -5 -s -oxt -D__WINDOWS__ -D__16BIT__
AFLAGS = -t -m -q -ml -zi
LFLAGS = -zq -zw -ml
OBJS = audio.obj wavfile.obj xmfile.obj s3mfile.obj modfile.obj mtmfile.obj &
iofile.obj modeng.obj nondrv.obj mixdrv.obj windrv.obj
LIB = ..\lib\Win16\audw16wc.lib
all : mp.exe $(LIB) clean .SYMBOLIC
@echo done.
mp.exe : mp.obj $(LIB)
$(CC) $(LFLAGS) mp.obj $(LIB) mmsystem.lib
$(LIB) : $(OBJS)
*$(AR) $(LIB) $(OBJS)
.c.obj :
$(CC) $(CFLAGS) $<
.asm.obj :
$(AS) $(AFLAGS) $<
clean : .SYMBOLIC
@if exist *.obj del *.obj > nul

View File

@@ -0,0 +1,37 @@
# Makefile for Borland C++ 4.5 (Win32 protected mode, flat memory model)
CC = bcc32a
LD = tlink32
IMPLIB = implib
AS = tasm
AR = tlib
CFLAGS = -WC -c -w9 -5 -O2 -DWIN32 -D__WINDOWS__ -D__ASM__
AFLAGS = -t -m -q -ml -zi
LFLAGS = -WD
LDFLAGS = -x -Tpd
OBJS = audio.obj wavfile.obj xmfile.obj s3mfile.obj modfile.obj mtmfile.obj \
iofile.obj modeng.obj nondrv.obj mixdrv.obj _mixdrv.obj windrv.obj \
drdrv.obj audiow32.obj
DLL = audiow32.dll
LIB = ..\lib\Win32\audw32bc.lib
all : mp.exe $(DLL) $(LIB) clean
mp.exe : mp.obj $(LIB)
$(CC) -WC mp.obj $(LIB)
$(DLL): $(OBJS)
$(LD) $(LDFLAGS) @Windows\Win32\Borland\audiow32.lnk
$(LIB) : $(DLL)
$(IMPLIB) $(LIB) $(DLL)
.c.obj :
$(CC) $(CFLAGS) $<
.asm.obj :
$(AS) $(AFLAGS) $<
clean :
@if exist *.obj del *.obj > nul

View File

@@ -0,0 +1,54 @@
LIBRARY audiow32
DESCRIPTION 'Audio Library 1.07 for Win32'
CODE PRELOAD MOVEABLE DISCARDABLE
DATA PRELOAD MOVEABLE
EXPORTS AInitialize @100
AGetVersion @101
AGetAudioNumDevs @102
AGetAudioDevCaps @103
AGetErrorText @104
APingAudio @105
AOpenAudio @106
ACloseAudio @107
AUpdateAudio @108
AOpenVoices @109
ACloseVoices @110
ASetAudioCallback @111
ASetAudioTimerProc @112
ASetAudioTimerRate @113
AGetAudioDataAvail @114
ACreateAudioData @115
ADestroyAudioData @116
AWriteAudioData @117
ACreateAudioVoice @118
ADestroyAudioVoice @119
APlayVoice @120
APrimeVoice @121
AStartVoice @122
AStopVoice @123
ASetVoicePosition @124
ASetVoiceFrequency @125
ASetVoiceVolume @126
ASetVoicePanning @127
AGetVoicePosition @128
AGetVoiceFrequency @129
AGetVoiceVolume @130
AGetVoicePanning @131
AGetVoiceStatus @132
APlayModule @133
AStopModule @134
APauseModule @135
AResumeModule @136
ASetModuleVolume @137
ASetModulePosition @138
AGetModuleVolume @139
AGetModulePosition @140
AGetModuleStatus @141
ASetModuleCallback @146
ALoadModuleFile @142
AFreeModuleFile @143
ALoadWaveFile @144
AFreeWaveFile @145
AGetModuleTrack @147
ASetAudioMixerValue @148
AUpdateAudioEx @149

View File

@@ -0,0 +1,7 @@
c0d32.obj +
audio.obj wavfile.obj xmfile.obj s3mfile.obj modfile.obj iofile.obj +
modeng.obj nondrv.obj mixdrv.obj _mixdrv.obj windrv.obj audiow32.obj
audiow32.dll
audiow32.map
cw32.lib import32.lib
Windows\Win32\Borland\audiow32.def

View File

@@ -0,0 +1,48 @@
# Makefile for Visual C++ 4.1 - 5.2 (Win32 protected mode, flat memory model)
!if "$(MSVCDIR)"==""
MSVCDIR = C:\VC
!endif
!if "$(DXSDKROOT)"==""
DXSDKROOT = $(MSVCDIR)
!endif
CC = cl
LD = link
AS = tasm
AR = lib
CFLAGS = -nologo -G5 -Gr -MD -LD -W2 -GD -Ox -Zp4 -c -DWIN32 -D__WINDOWS__ -D__FLAT__ -D__ASM__ -D__MSC__ -I"$(DXSDKROOT)\INCLUDE" -I"$(MSVCDIR)\INCLUDE"
AFLAGS = -t -m -q -ml -zi
OBJS = audiow32.obj audio.obj wavfile.obj xmfile.obj s3mfile.obj mtmfile.obj \
modfile.obj iofile.obj modeng.obj nondrv.obj mixdrv.obj \
_mixdrv.obj windrv.obj dsdrv.obj dsdrv2.obj
DLL = audiow32.dll
LIB = ..\lib\Win32\audw32vc.lib
LIBS = "$(MSVCDIR)\LIB\msvcrt.lib" \
"$(MSVCDIR)\LIB\kernel32.lib" "$(MSVCDIR)\LIB\winmm.lib" \
"$(MSVCDIR)\LIB\ole32.lib" "$(MSVCDIR)\LIB\user32.lib" \
"$(DXSDKROOT)\LIB\dsound.lib"
LFLAGS = -NOLOGO -DLL -MACHINE:I386 -VERSION:1.07 \
-DEF:Windows\Win32\VisualC\audiow32.def -OUT:$(DLL) -IMPLIB:$(LIB)
all : mp.exe $(DLL) $(LIB) clean
mp.exe : mp.obj $(LIB)
@$(LD) $(LIBS) -NOLOGO -SUBSYSTEM:CONSOLE -MACHINE:I386 -OUT:mp.exe mp.obj $(LIB)
$(DLL) $(LIB) : $(OBJS)
$(LD) $(LIBS) $(LFLAGS) $(OBJS)
.c.obj :
$(CC) $(CFLAGS) $<
.asm.obj :
$(AS) $(AFLAGS) $<
clean :
@if exist *.obj del *.obj > nul
@if exist *.exp del *.exp > nul

View File

@@ -0,0 +1,54 @@
LIBRARY audiow32
DESCRIPTION 'Audio Library 1.07 for Win32'
CODE PRELOAD MOVEABLE DISCARDABLE
DATA PRELOAD MOVEABLE
EXPORTS AInitialize @100
AGetVersion @101
AGetAudioNumDevs @102
AGetAudioDevCaps @103
AGetErrorText @104
APingAudio @105
AOpenAudio @106
ACloseAudio @107
AUpdateAudio @108
AOpenVoices @109
ACloseVoices @110
ASetAudioCallback @111
ASetAudioTimerProc @112
ASetAudioTimerRate @113
AGetAudioDataAvail @114
ACreateAudioData @115
ADestroyAudioData @116
AWriteAudioData @117
ACreateAudioVoice @118
ADestroyAudioVoice @119
APlayVoice @120
APrimeVoice @121
AStartVoice @122
AStopVoice @123
ASetVoicePosition @124
ASetVoiceFrequency @125
ASetVoiceVolume @126
ASetVoicePanning @127
AGetVoicePosition @128
AGetVoiceFrequency @129
AGetVoiceVolume @130
AGetVoicePanning @131
AGetVoiceStatus @132
APlayModule @133
AStopModule @134
APauseModule @135
AResumeModule @136
ASetModuleVolume @137
ASetModulePosition @138
AGetModuleVolume @139
AGetModulePosition @140
AGetModuleStatus @141
ASetModuleCallback @146
ALoadModuleFile @142
AFreeModuleFile @143
ALoadWaveFile @144
AFreeWaveFile @145
AGetModuleTrack @147
ASetAudioMixerValue @148
AUpdateAudioEx @149

View File

@@ -0,0 +1,39 @@
# Makefile for WATCOM C/C++32 10.0 (Win32 protected mode, flat memory model)
CC = wcl386
LD = wlink
AS = tasm
AR = wlib -b -n -q
CFLAGS = -zq -c -w9 -5r -s -oxt -DWIN32 -D__WINDOWS__ -D__ASM__
AFLAGS = -q -t -m -ml -zi
LFLAGS = -zq -l=nt
#AS = wasm
#AFLAGS = -zq -w9 -we -5r
OBJS = audio.obj wavfile.obj xmfile.obj s3mfile.obj modfile.obj mtmfile.obj &
iofile.obj modeng.obj nondrv.obj mixdrv.obj _mixdrv.obj windrv.obj dsdrv.obj
DLL = audiow32.dll
LIB = ..\lib\Win32\audw32wc.lib
all : mp.exe $(DLL) clean .SYMBOLIC
@echo done.
mp.exe : mp.obj $(LIB)
$(CC) mp.obj $(LIB) $(LFLAGS)
$(LIB) : $(DLL)
$(AR) $(LIB) @Windows\Win32\Watcom\audiow32.lbc
$(DLL) : $(OBJS)
$(LD) @Windows\Win32\Watcom\audiow32.lnk
.c.obj :
$(CC) $(CFLAGS) $<
.asm.obj :
$(AS) $(AFLAGS) $<
clean : .SYMBOLIC
@if exist *.obj del *.obj > nul

View File

@@ -0,0 +1,49 @@
++'_AInitialize@0'.'AUDIOW32.DLL'..AInitialize
++'_AGetVersion@0'.'AUDIOW32.DLL'..AGetVersion
++'_AGetAudioNumDevs@0'.'AUDIOW32.DLL'..AGetAudioNumDevs
++'_AGetAudioDevCaps@8'.'AUDIOW32.DLL'..AGetAudioDevCaps
++'_AGetErrorText@12'.'AUDIOW32.DLL'..AGetErrorText
++'_APingAudio@4'.'AUDIOW32.DLL'..APingAudio
++'_AOpenAudio@4'.'AUDIOW32.DLL'..AOpenAudio
++'_ACloseAudio@0'.'AUDIOW32.DLL'..ACloseAudio
++'_AUpdateAudio@0'.'AUDIOW32.DLL'..AUpdateAudio
++'_AOpenVoices@4'.'AUDIOW32.DLL'..AOpenVoices
++'_ACloseVoices@0'.'AUDIOW32.DLL'..ACloseVoices
++'_ASetAudioCallback@4'.'AUDIOW32.DLL'..ASetAudioCallback
++'_ASetAudioTimerProc@4'.'AUDIOW32.DLL'..ASetAudioTimerProc
++'_ASetAudioTimerRate@4'.'AUDIOW32.DLL'..ASetAudioTimerRate
++'_AGetAudioDataAvail@0'.'AUDIOW32.DLL'..AGetAudioDataAvail
++'_ACreateAudioData@4'.'AUDIOW32.DLL'..ACreateAudioData
++'_ADestroyAudioData@4'.'AUDIOW32.DLL'..ADestroyAudioData
++'_AWriteAudioData@12'.'AUDIOW32.DLL'..AWriteAudioData
++'_ACreateAudioVoice@4'.'AUDIOW32.DLL'..ACreateAudioVoice
++'_ADestroyAudioVoice@4'.'AUDIOW32.DLL'..ADestroyAudioVoice
++'_APlayVoice@8'.'AUDIOW32.DLL'..APlayVoice
++'_APrimeVoice@8'.'AUDIOW32.DLL'..APrimeVoice
++'_AStartVoice@4'.'AUDIOW32.DLL'..AStartVoice
++'_AStopVoice@4'.'AUDIOW32.DLL'..AStopVoice
++'_ASetVoicePosition@8'.'AUDIOW32.DLL'..ASetVoicePosition
++'_ASetVoiceFrequency@8'.'AUDIOW32.DLL'..ASetVoiceFrequency
++'_ASetVoiceVolume@8'.'AUDIOW32.DLL'..ASetVoiceVolume
++'_ASetVoicePanning@8'.'AUDIOW32.DLL'..ASetVoicePanning
++'_AGetVoicePosition@8'.'AUDIOW32.DLL'..AGetVoicePosition
++'_AGetVoiceFrequency@8'.'AUDIOW32.DLL'..AGetVoiceFrequency
++'_AGetVoiceVolume@8'.'AUDIOW32.DLL'..AGetVoiceVolume
++'_AGetVoicePanning@8'.'AUDIOW32.DLL'..AGetVoicePanning
++'_AGetVoiceStatus@8'.'AUDIOW32.DLL'..AGetVoiceStatus
++'_APlayModule@4'.'AUDIOW32.DLL'..APlayModule
++'_AStopModule@0'.'AUDIOW32.DLL'..AStopModule
++'_APauseModule@0'.'AUDIOW32.DLL'..APauseModule
++'_AResumeModule@0'.'AUDIOW32.DLL'..AResumeModule
++'_ASetModuleVolume@4'.'AUDIOW32.DLL'..ASetModuleVolume
++'_ASetModulePosition@8'.'AUDIOW32.DLL'..ASetModulePosition
++'_AGetModuleVolume@4'.'AUDIOW32.DLL'..AGetModuleVolume
++'_AGetModulePosition@8'.'AUDIOW32.DLL'..AGetModulePosition
++'_AGetModuleStatus@4'.'AUDIOW32.DLL'..AGetModuleStatus
++'_ASetModuleCallback@4'.'AUDIOW32.DLL'..ASetModuleCallback
++'_ALoadModuleFile@12'.'AUDIOW32.DLL'..ALoadModuleFile
++'_AFreeModuleFile@4'.'AUDIOW32.DLL'..AFreeModuleFile
++'_ALoadWaveFile@12'.'AUDIOW32.DLL'..ALoadWaveFile
++'_AFreeWaveFile@4'.'AUDIOW32.DLL'..AFreeWaveFile
++'_ASetAudioMixerValue@8'.'AUDIOW32.DLL'..ASetAudioMixerValue
++'_AUpdateAudioEx@4".'AUDIOW32.DLL'..AUpdateAudioEx

View File

@@ -0,0 +1,57 @@
NAME AUDIOW32.DLL
SYSTEM nt_dll
OPTION MODNAME='AudioW32', VERSION=1.07
OPTION DESCRIPTION 'Audio Library 1.07 for Win32'
FILE AUDIO.OBJ, WAVFILE.OBJ, XMFILE.OBJ, S3MFILE.OBJ,
MODFILE.OBJ, IOFILE.OBJ, MODENG.OBJ, NONDRV.OBJ,
MIXDRV.OBJ, _MIXDRV.OBJ, WINDRV.OBJ
EXPORT AInitialize.100,
AGetVersion.101,
AGetAudioNumDevs.102,
AGetAudioDevCaps.103,
AGetErrorText.104,
APingAudio.105,
AOpenAudio.106,
ACloseAudio.107,
AUpdateAudio.108,
AOpenVoices.109,
ACloseVoices.110,
ASetAudioCallback.111,
ASetAudioTimerProc.112,
ASetAudioTimerRate.113,
AGetAudioDataAvail.114,
ACreateAudioData.115,
ADestroyAudioData.116,
AWriteAudioData.117,
ACreateAudioVoice.118,
ADestroyAudioVoice.119,
APlayVoice.120,
APrimeVoice.121,
AStartVoice.122,
AStopVoice.123,
ASetVoicePosition.124,
ASetVoiceFrequency.125,
ASetVoiceVolume.126,
ASetVoicePanning.127,
AGetVoicePosition.128,
AGetVoiceFrequency.129,
AGetVoiceVolume.130,
AGetVoicePanning.131,
AGetVoiceStatus.132,
APlayModule.133,
AStopModule.134,
APauseModule.135,
AResumeModule.136,
ASetModuleVolume.137,
ASetModulePosition.138,
AGetModuleVolume.139,
AGetModulePosition.140,
AGetModuleStatus.141,
ASetModuleCallback.146,
ALoadModuleFile.142,
AFreeModuleFile.143,
ALoadWaveFile.144,
AFreeWaveFile.145,
AGetModuleTrack.147
ASetAudioMixerValue.148
AUpdateAudioEx.149

2202
seal-hack/src/_mixdrv.S Normal file

File diff suppressed because it is too large Load Diff

2269
seal-hack/src/_mixdrv.asm Normal file

File diff suppressed because it is too large Load Diff

172
seal-hack/src/allegdrv.c Normal file
View File

@@ -0,0 +1,172 @@
/*
* $Id: lnxdrv.c 1.5 1996/08/05 18:51:19 chasan released $
*
* SDL audio driver. Turns SEAL into a mixer on top of SDL.
*
* Copyright 2002 Greg Velichansky (hmaon@bumba.net)
*
* Based in part on the Linux Voxware driver,
* Copyright (C) 1995-1999 Carlos Hasan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#ifdef __APPLE__
#define USE_CONSOLE
#include <Allegro/allegro.h>
#else
#define USE_CONSOLE
#include <allegro.h>
#endif
#include "audio.h"
#include "drivers.h"
/*
* fragments defines
*/
#define NUMFRAGS 16
#define FRAGSIZE 11
#define BUFFERSIZE (1 << FRAGSIZE)
/*
* configuration structure
*/
static struct AudioStruct {
AUDIOSTREAM *stream;
BYTE aBuffer[BUFFERSIZE*4];
LPFNAUDIOWAVE lpfnAudioWave;
WORD wFormat;
} Audio;
/*
* Linux driver API interface
*/
static UINT AIAPI GetAudioCaps(LPAUDIOCAPS lpCaps)
{
static AUDIOCAPS Caps =
{
AUDIO_PRODUCT_LINUX, "Allegro",
AUDIO_FORMAT_1M08 | AUDIO_FORMAT_1S08 |
AUDIO_FORMAT_1M16 | AUDIO_FORMAT_1S16 |
AUDIO_FORMAT_2M08 | AUDIO_FORMAT_2S08 |
AUDIO_FORMAT_2M16 | AUDIO_FORMAT_2S16 |
AUDIO_FORMAT_4M08 | AUDIO_FORMAT_4S08 |
AUDIO_FORMAT_4M16 | AUDIO_FORMAT_4S16
};
memcpy(lpCaps, &Caps, sizeof(AUDIOCAPS));
return AUDIO_ERROR_NONE;
}
static UINT AIAPI PingAudio(VOID)
{
return 0;
/* return (SDL_INIT_AUDIO == SDL_WasInit(SDL_INIT_AUDIO)); */
}
static UINT AIAPI OpenAudio(LPAUDIOINFO lpInfo)
{
int nBitsPerSample, nStereoOn, nSampleRate, nFrags;
memset(&Audio, 0, sizeof(Audio));
allegro_init();
if (install_sound(DIGI_AUTODETECT, MIDI_NONE, "") != 0)
return AUDIO_ERROR_NODEVICE;
//nBitsPerSample = lpInfo->wFormat & AUDIO_FORMAT_16BITS ? 16 : 8;
//nStereoOn = lpInfo->wFormat & AUDIO_FORMAT_STEREO ? 1 : 0;
/*nSampleRate = lpInfo->nSampleRate;*/
/* Audio.desired.freq = lpInfo->nSampleRate;
Audio.desired.samples = 512;
Audio.desired.channels = nStereoOn ? 2 : 1;
Audio.desired.format = (lpInfo->wFormat & AUDIO_FORMAT_16BITS) ? AUDIO_U16SYS : AUDIO_U8;
Audio.desired.userdata = (void*)&Audio;
Audio.desired.callback = updatecallback;*/
//SDL_OpenAudio(&(Audio.desired), &(Audio.spec));
Audio.stream = play_audio_stream(BUFFERSIZE, 16, TRUE, lpInfo->nSampleRate, 255, 128);
voice_start(Audio.stream->voice);
/* we should probably do something here... blah... whatever :/ */
/* setup number and size of buffer fragments */
/*nFrags = (NUMFRAGS << 16) + (FRAGSIZE);
ioctl(Audio.nHandle, SNDCTL_DSP_SETFRAGMENT, &nFrags);*/
/* setup audio playback encoding format and sampling frequency */
/*if (ioctl(Audio.nHandle, SNDCTL_DSP_SAMPLESIZE, &nBitsPerSample) < 0 ||
ioctl(Audio.nHandle, SNDCTL_DSP_STEREO, &nStereoOn) < 0 ||
ioctl(Audio.nHandle, SNDCTL_DSP_SPEED, &nSampleRate) < 0) {
close(Audio.nHandle);
return AUDIO_ERROR_BADFORMAT;
}*/
/*Audio.wFormat = lpInfo->wFormat;*/
return AUDIO_ERROR_NONE;
}
static UINT AIAPI CloseAudio(VOID)
{
//SDL_CloseAudio();
voice_stop(Audio.stream);
return AUDIO_ERROR_NONE;
}
static UINT AIAPI UpdateAudio(UINT nFrames)
{
unsigned char *Buf;
Buf = get_audio_stream_buffer(Audio.stream);
/* compute frame size */
if (Audio.wFormat & AUDIO_FORMAT_16BITS) nFrames <<= 1;
if (Audio.wFormat & AUDIO_FORMAT_STEREO) nFrames <<= 1;
if (nFrames <= 0 || nFrames > sizeof(Audio.aBuffer))
nFrames = sizeof(Audio.aBuffer);
/* send PCM samples to the DSP audio device */
if (Audio.lpfnAudioWave != NULL) {
Audio.lpfnAudioWave(Buf, nFrames);
}
return AUDIO_ERROR_NONE;
}
static UINT AIAPI SetAudioCallback(LPFNAUDIOWAVE lpfnAudioWave)
{
/* set up DSP audio device user's callback function */
Audio.lpfnAudioWave = lpfnAudioWave;
return AUDIO_ERROR_NONE;
}
/*
* Linux driver public interface
*/
AUDIOWAVEDRIVER AllegWaveDriver =
{
GetAudioCaps, PingAudio, OpenAudio, CloseAudio,
UpdateAudio, SetAudioCallback
};
AUDIODRIVER AllegDriver =
{
&AllegWaveDriver, NULL
};

370
seal-hack/src/ariadrv.c Normal file
View File

@@ -0,0 +1,370 @@
/*
* $Id: ariadrv.c 1.6 1996/08/05 18:51:19 chasan released $
*
* Sierra Semiconductors' Aria soundcard audio driver.
*
* Copyright (C) 1995-1999 Carlos Hasan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <string.h>
#include <malloc.h>
#include "audio.h"
#include "drivers.h"
#include "msdos.h"
/*
* Aria DSP chip register offsets
*/
#define ARIA_CMD 0x000 /* Aria DSP command port */
#define ARIA_STAT 0x002 /* Aria DSP write status */
#define ARIA_ADDR 0x004 /* Aria DSP memory address */
#define ARIA_DATA 0x006 /* Aria DSP indexed memory data */
/*
* Aria DSP playback mode defines
*/
#define ARIA_MODE_0 0x0000 /* 4 mono or 2 stereo PCM channels */
#define ARIA_MODE_1 0x0001 /* 2 mono or 1 stereo PCM channels */
#define ARIA_MODE_2 0x0002 /* 2 mono or 1 stereo PCM channels */
/*
* Aria DSP playback format defines
*/
#define ARIA_FMT_11025 0x0000 /* select 11025 Hz sampling rate */
#define ARIA_FMT_22050 0x0010 /* select 22050 Hz sampling rate */
#define ARIA_FMT_44100 0x0020 /* select 44100 Hz sampling rate */
#define ARIA_FMT_MONO 0x0000 /* select mono output */
#define ARIA_FMT_STEREO 0x0001 /* select stereo output */
#define ARIA_FMT_8BIT 0x0000 /* select 8-bit PCM encoding */
#define ARIA_FMT_16BIT 0x0002 /* select 16-bit PCM encoding */
#define ARIA_FMT_ADPCM 0x0004 /* select ADPCM encoding */
#define BUFFERSIZE 50 /* buffer length in milliseconds */
#define PACKETSIZE 1024 /* packet size in bytes */
#define TIMEOUT 60000 /* timeout counter for DSP writes */
/*
* Aria DSP configuration structure
*/
static struct {
WORD wFormat; /* playback encoding format */
WORD nSampleRate; /* sampling frequency */
WORD wFmt; /* Aria DSP format command */
WORD wPort; /* base I/O port address */
BYTE nIrqLine; /* interrupt request line */
BYTE nDmaChannel; /* direct memory access channel */
LPBYTE lpBuffer; /* DMA buffer address */
UINT nBufferSize; /* DMA buffer length in bytes */
UINT nPosition; /* DMA buffer playing position */
UINT nWritePosition; /* DMA buffer DSP write position */
LPFNAUDIOWAVE lpfnAudioWave; /* user wave callback function */
} Aria;
/*
* Aria DSP low level programming routines
*/
static VOID ARPortW(WORD wCmd)
{
UINT n;
/* wait until the Aria DSP is ready to receive a command */
for (n = 0; n < TIMEOUT; n++) {
if (!(INW(Aria.wPort + ARIA_STAT) & 0x8000))
break;
}
/* send the command to the Aria DSP chip */
OUTW(Aria.wPort + ARIA_CMD, wCmd);
}
static VOID ARPokeW(WORD nIndex, WORD wData)
{
OUTB(Aria.wPort + ARIA_ADDR, nIndex);
OUTB(Aria.wPort + ARIA_DATA, wData);
}
static WORD ARPeekW(WORD nIndex)
{
OUTW(Aria.wPort + ARIA_ADDR, nIndex);
return INW(Aria.wPort + ARIA_DATA);
}
static VOID ARSetPlaybackMode(WORD nMode)
{
/*
* Setup Aria's playback mode to one of the following:
*
* ARIA_MODE_0 4 mono or 2 stereo PCM channels, no synth operators
* ARIA_MODE_1 2 mono or 1 stereo PCM channels, 20 synth operators
* ARIA_MODE_2 2 mono or 1 stereo PCM channels, 32 synth operators
*
*/
ARPortW(0x0006);
ARPortW(nMode);
ARPortW(0xFFFF);
}
static VOID ARStartPlayback(VOID)
{
ARPortW(0x0011);
ARPortW(0x0000);
ARPortW(0xFFFF);
}
static VOID ARStopPlayback(VOID)
{
ARPortW(0x0012);
ARPortW(0x0000);
ARPortW(0xFFFF);
}
static VOID ARSetFormat(WORD wFmt)
{
/* we have to set some parameters to play at 44100 Hz */
if (wFmt & ARIA_FMT_44100) {
ARSetPlaybackMode(ARIA_MODE_0);
OUTW(Aria.wPort + ARIA_STAT, 0x008A);
}
ARPortW(0x0003);
ARPortW(wFmt);
ARPortW(0xFFFF);
}
static VOID ARInit(VOID)
{
UINT n;
/*
* Set up Aria in native mode (disable SB emulation mode),
* first initialize the chip and then clear the init flag.
*/
OUTW(Aria.wPort + ARIA_STAT, 0x00C8);
ARPokeW(0x6102, 0x0000);
/* Aria DSP initialization */
ARPortW(0x0000);
ARPortW(0x0000);
ARPortW(0x0000);
ARPortW(0x0000);
ARPortW(0xFFFF);
/* wait until Aria DSP initialization finishes */
for (n = 0; n < TIMEOUT; n++) {
if (ARPeekW(0x6102) == 1)
break;
}
/* complete Aria initialization */
OUTW(Aria.wPort + ARIA_CMD, 0x00CA);
}
static VOID ARReset(WORD wFmt)
{
/*
* We need to reset the Aria chip back to 22050 Hz
* when it was programmed to play at 44100 Hz.
*/
if (wFmt & ARIA_FMT_44100) {
ARSetPlaybackMode(ARIA_MODE_2);
OUTW(Aria.wPort + ARIA_STAT, 0x00CA);
}
/* switch back to SB emulation mode */
OUTW(Aria.wPort + ARIA_STAT, 0x0040);
}
static VOID AIAPI ARInterruptHandler(VOID)
{
LPWORD lpPacket;
WORD wAddress;
UINT n;
/* check interrupt type and exit if not generated by Aria */
if (INW(Aria.wPort + ARIA_CMD) == 1) {
/* play a packet of samples from our buffer */
wAddress = 0x8000 - PACKETSIZE + ARPeekW(0x6100);
OUTW(Aria.wPort + ARIA_ADDR, wAddress);
lpPacket = (LPWORD) (Aria.lpBuffer + Aria.nWritePosition);
for (n = 0; n < PACKETSIZE/2; n++) {
OUTW(Aria.wPort + ARIA_DATA, *lpPacket++);
}
if ((Aria.nWritePosition += PACKETSIZE) >= Aria.nBufferSize)
Aria.nWritePosition -= Aria.nBufferSize;
ARPortW(0x0010);
ARPortW(0xFFFF);
}
}
/*
* Aria audio driver API interface
*/
static UINT AIAPI PingAudio(VOID)
{
LPSTR lpszAria;
UINT nChar;
if ((lpszAria = DosGetEnvironment("ARIA")) != NULL) {
Aria.wPort = 0x290;
Aria.nIrqLine = 10;
Aria.nDmaChannel = 5;
nChar = DosParseString(lpszAria, TOKEN_CHAR);
while (nChar != 0) {
switch (nChar) {
case 'A':
case 'a':
Aria.wPort = DosParseString(NULL, TOKEN_HEX);
break;
case 'I':
case 'i':
Aria.nIrqLine = DosParseString(NULL, TOKEN_DEC);
break;
case 'D':
case 'd':
Aria.nDmaChannel = DosParseString(NULL, TOKEN_DEC);
break;
}
nChar = DosParseString(NULL, TOKEN_CHAR);
}
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_NODEVICE;
}
static UINT AIAPI GetAudioCaps(LPAUDIOCAPS lpCaps)
{
static AUDIOCAPS Caps =
{
AUDIO_PRODUCT_ARIA, "Aria sound card",
AUDIO_FORMAT_1M08 | AUDIO_FORMAT_1S08 |
AUDIO_FORMAT_1M16 | AUDIO_FORMAT_1S16 |
AUDIO_FORMAT_2M08 | AUDIO_FORMAT_2S08 |
AUDIO_FORMAT_2M16 | AUDIO_FORMAT_2S16 |
AUDIO_FORMAT_4M08 | AUDIO_FORMAT_4S08 |
AUDIO_FORMAT_4M16 | AUDIO_FORMAT_4S16
};
memcpy(lpCaps, &Caps, sizeof(AUDIOCAPS));
return AUDIO_ERROR_NONE;
}
static UINT AIAPI OpenAudio(LPAUDIOINFO lpInfo)
{
DWORD dwBytesPerSecond;
memset(&Aria, 0, sizeof(Aria));
/*
* Initialize the Aria DSP configuration parameters
*/
Aria.wFormat = lpInfo->wFormat;
Aria.nSampleRate = lpInfo->nSampleRate < 16357 ? 11025 :
(lpInfo->nSampleRate < 33075 ? 22050 : 44100);
if (PingAudio())
return AUDIO_ERROR_NODEVICE;
/*
* Allocate and clean DMA buffer used for playback
*/
dwBytesPerSecond = Aria.nSampleRate;
if (Aria.wFormat & AUDIO_FORMAT_16BITS)
dwBytesPerSecond <<= 1;
if (Aria.wFormat & AUDIO_FORMAT_STEREO)
dwBytesPerSecond <<= 1;
Aria.nBufferSize = dwBytesPerSecond / (1000 / (BUFFERSIZE >> 1));
Aria.nBufferSize = (Aria.nBufferSize + PACKETSIZE) & -PACKETSIZE;
Aria.nBufferSize <<= 1;
if ((Aria.lpBuffer = malloc(Aria.nBufferSize)) == NULL)
return AUDIO_ERROR_NOMEMORY;
memset(Aria.lpBuffer, Aria.wFormat & AUDIO_FORMAT_16BITS ?
0x00 : 0x80, Aria.nBufferSize);
/*
* Initialize the Aria DSP chip, set playback format,
* sampling frequency and start the DAC transfer.
*/
ARInit();
DosSetVectorHandler(Aria.nIrqLine, ARInterruptHandler);
Aria.wFmt = Aria.wFormat & AUDIO_FORMAT_16BITS ?
ARIA_FMT_16BIT : ARIA_FMT_8BIT;
Aria.wFmt |= Aria.wFormat & AUDIO_FORMAT_STEREO ?
ARIA_FMT_STEREO : ARIA_FMT_MONO;
Aria.wFmt |= (Aria.nSampleRate <= 11025 ? ARIA_FMT_11025 :
(Aria.nSampleRate <= 22050 ? ARIA_FMT_22050 : ARIA_FMT_44100));
ARSetFormat(Aria.wFmt);
ARStartPlayback();
/* refresh caller's format and sampling frequency */
lpInfo->wFormat = Aria.wFormat;
lpInfo->nSampleRate = Aria.nSampleRate;
return AUDIO_ERROR_NONE;
}
static UINT AIAPI CloseAudio(VOID)
{
ARStopPlayback();
ARReset(Aria.wFmt);
DosSetVectorHandler(Aria.nIrqLine, NULL);
if (Aria.lpBuffer != NULL)
free(Aria.lpBuffer);
return AUDIO_ERROR_NONE;
}
static UINT AIAPI UpdateAudio(UINT nFrames)
{
int nBlockSize, nSize;
if (Aria.wFormat & AUDIO_FORMAT_16BITS) nFrames <<= 1;
if (Aria.wFormat & AUDIO_FORMAT_STEREO) nFrames <<= 1;
if (nFrames <= 0 || nFrames > Aria.nBufferSize)
nFrames = Aria.nBufferSize;
if ((nBlockSize = Aria.nWritePosition - Aria.nPosition) < 0)
nBlockSize += Aria.nBufferSize;
if (nBlockSize > nFrames)
nBlockSize = nFrames;
while (nBlockSize != 0) {
if ((nSize = Aria.nBufferSize - Aria.nPosition) > nBlockSize)
nSize = nBlockSize;
if (Aria.lpfnAudioWave != NULL) {
Aria.lpfnAudioWave(&Aria.lpBuffer[Aria.nPosition], nSize);
}
else {
memset(&Aria.lpBuffer[Aria.nPosition],
Aria.wFormat & AUDIO_FORMAT_16BITS ? 0x00 : 0x80, nSize);
}
if ((Aria.nPosition += nSize) >= Aria.nBufferSize)
Aria.nPosition -= Aria.nBufferSize;
nBlockSize -= nSize;
}
return AUDIO_ERROR_NONE;
}
static UINT AIAPI SetAudioCallback(LPFNAUDIOWAVE lpfnAudioWave)
{
Aria.lpfnAudioWave = lpfnAudioWave;
return AUDIO_ERROR_NONE;
}
/*
* Aria DSP audio driver public interface
*/
AUDIOWAVEDRIVER AriaWaveDriver =
{
GetAudioCaps, PingAudio, OpenAudio, CloseAudio,
UpdateAudio, SetAudioCallback
};
AUDIODRIVER AriaDriver =
{
&AriaWaveDriver, NULL
};

559
seal-hack/src/audio.c Normal file
View File

@@ -0,0 +1,559 @@
/*
* $Id: audio.c 1.13 1996/12/12 16:32:06 chasan Exp $
* 1.14 1998/10/18 14:59:21 chasan (BeOS and OS/2 driver)
* 1.15 1998/11/30 18:20:26 chasan (Mixer and UpdateAudioEx API)
*
* Audio device drivers API interface
*
* Copyright (C) 1995-1999 Carlos Hasan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifdef __GNUC__
#include <memory.h>
#endif
#include <stdlib.h>
#include <string.h>
#include "audio.h"
#include "drivers.h"
/*
* Copyright information hard-coded into the library
*/
CHAR szAudioCopyright[] =
"SEAL Synthetic Audio Library 1.07 (Build " __DATE__ ")\n"
"Copyright (C) 1995, 1996, 1997, 1998, 1999 Carlos Hasan\n";
#ifdef __OS2__
CHAR szMartyCopyright[] =
"OS/2 Audio Driver Copyright (C) 1998 by Martin Amodeo";
#endif
/*
* Audio device drivers resource limits
*/
#define MAXDRIVERS 8
#define MAXVOICES 32
/*
* Macros to work with audio channels handles
*/
#define VOICENUM(handle) ((UINT)handle-1)
/*
* Table of registered audio device drivers and channels.
*/
static LPAUDIODRIVER aDriverTable[MAXDRIVERS];
static HAC aVoiceTable[MAXVOICES];
static UINT nNumVoices;
/*
* Currently active audio device driver virtual method tables
*/
static UINT nDriverId = AUDIO_DEVICE_MAPPER;
static AUDIOWAVEDRIVER WaveDriver;
static AUDIOSYNTHDRIVER SynthDriver;
/*
* Audio device drivers API interface
*/
UINT AIAPI AAudioFatalError(UINT nErrorCode)
{
nNumVoices = 0;
nDriverId = AUDIO_DEVICE_MAPPER;
memset(aVoiceTable, 0, sizeof(aVoiceTable));
memcpy(&WaveDriver, &NoneWaveDriver, sizeof(AUDIOWAVEDRIVER));
memcpy(&SynthDriver, &NoneSynthDriver, sizeof(AUDIOSYNTHDRIVER));
return nErrorCode;
}
UINT AIAPI AGetErrorText(UINT nErrorCode, LPSTR lpText, UINT nSize)
{
static LPSTR aErrorTable[] =
{
"Unknown audio system error",
"Bad channel or sample handle",
"Invalid parameter passed",
"Invalid audio system call",
"Bad audio device identifier",
"No audio device found",
"Audio device is busy",
"Bad audio data format",
"Not enough memory",
"Not enough device memory",
"File not found",
"Bad file format"
};
if (lpText != NULL) {
if (nErrorCode <= AUDIO_LAST_ERROR) {
strncpy(lpText, aErrorTable[nErrorCode], nSize);
return AUDIO_ERROR_NONE;
}
strncpy(lpText, aErrorTable[AUDIO_ERROR_NONE], nSize);
}
return AUDIO_ERROR_INVALPARAM;
}
UINT AIAPI ARegisterAudioDriver(LPAUDIODRIVER lpDriver)
{
UINT nDeviceId;
for (nDeviceId = 0; nDeviceId < MAXDRIVERS; nDeviceId++) {
if (aDriverTable[nDeviceId] == NULL ||
aDriverTable[nDeviceId] == lpDriver) {
aDriverTable[nDeviceId] = lpDriver;
return AUDIO_ERROR_NONE;
}
}
return AUDIO_ERROR_NOMEMORY;
}
UINT AIAPI AGetAudioNumDevs(VOID)
{
UINT nDeviceId, nNumDevs;
nNumDevs = 0;
for (nDeviceId = 0; nDeviceId < MAXDRIVERS; nDeviceId++) {
if (aDriverTable[nDeviceId] != NULL)
nNumDevs++;
}
return nNumDevs;
}
UINT AIAPI AGetAudioDevCaps(UINT nDeviceId, LPAUDIOCAPS lpCaps)
{
LPAUDIODRIVER lpDriver;
if (lpCaps != NULL) {
memset(lpCaps, 0, sizeof(AUDIOCAPS));
if (nDeviceId < MAXDRIVERS) {
if ((lpDriver = aDriverTable[nDeviceId]) != NULL) {
if (lpDriver->lpWaveDriver != NULL) {
return lpDriver->lpWaveDriver->GetAudioCaps(lpCaps);
}
else if (lpDriver->lpSynthDriver != NULL) {
return lpDriver->lpSynthDriver->GetAudioCaps(lpCaps);
}
}
}
return AUDIO_ERROR_BADDEVICEID;
}
return AUDIO_ERROR_INVALPARAM;
}
UINT AIAPI APingAudio(LPUINT lpnDeviceId)
{
LPAUDIODRIVER lpDriver;
UINT nDeviceId;
if (lpnDeviceId != NULL) {
*lpnDeviceId = AUDIO_DEVICE_NONE;
if (nDriverId == AUDIO_DEVICE_MAPPER) {
for (nDeviceId = MAXDRIVERS - 1; nDeviceId != 0; nDeviceId--) {
if ((lpDriver = aDriverTable[nDeviceId]) != NULL) {
if (lpDriver->lpWaveDriver != NULL &&
!lpDriver->lpWaveDriver->PingAudio()) {
*lpnDeviceId = nDeviceId;
return AUDIO_ERROR_NONE;
}
else if (lpDriver->lpSynthDriver != NULL &&
!lpDriver->lpSynthDriver->PingAudio()) {
*lpnDeviceId = nDeviceId;
return AUDIO_ERROR_NONE;
}
}
}
return AUDIO_ERROR_NODEVICE;
}
return AUDIO_ERROR_NOTSUPPORTED;
}
return AUDIO_ERROR_INVALPARAM;
}
UINT AIAPI AOpenAudio(LPAUDIOINFO lpInfo)
{
LPAUDIODRIVER lpDriver;
LPAUDIOWAVEDRIVER lpWaveDriver;
LPAUDIOSYNTHDRIVER lpSynthDriver;
UINT nErrorCode;
if (nDriverId == AUDIO_DEVICE_MAPPER) {
if (lpInfo != NULL && lpInfo->nDeviceId == AUDIO_DEVICE_MAPPER) {
nErrorCode = APingAudio(&lpInfo->nDeviceId);
if (nErrorCode != AUDIO_ERROR_NONE)
return AAudioFatalError(nErrorCode);
}
if (lpInfo != NULL && lpInfo->nDeviceId < MAXDRIVERS) {
if ((lpDriver = aDriverTable[lpInfo->nDeviceId]) != NULL) {
if ((lpWaveDriver = lpDriver->lpWaveDriver) == NULL)
lpWaveDriver = &NoneWaveDriver;
if ((lpSynthDriver = lpDriver->lpSynthDriver) == NULL)
lpSynthDriver = &EmuSynthDriver;
memcpy(&WaveDriver, lpWaveDriver, sizeof(AUDIOWAVEDRIVER));
memcpy(&SynthDriver, lpSynthDriver, sizeof(AUDIOSYNTHDRIVER));
nErrorCode = WaveDriver.OpenAudio(lpInfo);
if (nErrorCode != AUDIO_ERROR_NONE)
return AAudioFatalError(nErrorCode);
nErrorCode = SynthDriver.OpenAudio(lpInfo);
if (nErrorCode != AUDIO_ERROR_NONE) {
WaveDriver.CloseAudio();
return AAudioFatalError(nErrorCode);
}
memset(aVoiceTable, 0, sizeof(aVoiceTable));
nNumVoices = 0;
nDriverId = lpInfo->nDeviceId;
return AUDIO_ERROR_NONE;
}
}
return AAudioFatalError(lpInfo != NULL ? AUDIO_ERROR_BADDEVICEID :
AUDIO_ERROR_INVALPARAM);
}
return AUDIO_ERROR_NOTSUPPORTED;
}
UINT AIAPI ACloseAudio(VOID)
{
UINT nErrorCode;
nDriverId = AUDIO_DEVICE_MAPPER;
if ((nErrorCode = SynthDriver.CloseAudio()) != AUDIO_ERROR_NONE)
return AAudioFatalError(nErrorCode);
if ((nErrorCode = WaveDriver.CloseAudio()) != AUDIO_ERROR_NONE)
return AAudioFatalError(nErrorCode);
return AAudioFatalError(AUDIO_ERROR_NONE);
}
UINT AIAPI AUpdateAudio(VOID)
{
return AUpdateAudioEx(0);
}
UINT AIAPI AUpdateAudioEx(UINT nFrames)
{
static UINT nSemalphore = 0;
UINT nErrorCode = AUDIO_ERROR_NONE;
/* TODO: This is not a real semalphore, may fail sometimes. */
if (nDriverId != AUDIO_DEVICE_MAPPER) {
if (!nSemalphore++) nErrorCode = WaveDriver.UpdateAudio(nFrames);
nSemalphore--;
}
return nErrorCode;
}
UINT AIAPI AOpenVoices(UINT nVoices)
{
UINT nErrorCode;
memset(aVoiceTable, 0, sizeof(aVoiceTable));
if ((nErrorCode = SynthDriver.OpenVoices(nVoices)) == AUDIO_ERROR_NONE)
nNumVoices = nVoices;
return nErrorCode;
}
UINT AIAPI ACloseVoices(VOID)
{
UINT nVoice;
for (nVoice = 0; nVoice < nNumVoices; nVoice++) {
if (aVoiceTable[nVoice] != (HAC) NULL)
return AUDIO_ERROR_NOTSUPPORTED;
}
nNumVoices = 0;
memset(aVoiceTable, 0, sizeof(aVoiceTable));
return SynthDriver.CloseVoices();
}
UINT AIAPI ASetAudioCallback(LPFNAUDIOWAVE lpfnAudioWave)
{
return WaveDriver.SetAudioCallback(lpfnAudioWave);
}
UINT AIAPI ASetAudioTimerProc(LPFNAUDIOTIMER lpfnAudioTimer)
{
return SynthDriver.SetAudioTimerProc(lpfnAudioTimer);
}
UINT AIAPI ASetAudioTimerRate(UINT nTimerRate)
{
return SynthDriver.SetAudioTimerRate(nTimerRate);
}
UINT AIAPI ASetAudioMixerValue(UINT nChannel, UINT nValue)
{
return SynthDriver.SetAudioMixerValue(nChannel, nValue);
}
LONG AIAPI AGetAudioDataAvail(VOID)
{
return SynthDriver.GetAudioDataAvail();
}
UINT AIAPI ACreateAudioData(LPAUDIOWAVE lpWave)
{
UINT nErrorCode;
if (lpWave != NULL) {
if ((lpWave->lpData = malloc(lpWave->dwLength + 4)) != NULL) {
nErrorCode = SynthDriver.CreateAudioData(lpWave);
if (nErrorCode != AUDIO_ERROR_NONE) {
free(lpWave->lpData);
lpWave->lpData = NULL;
}
return nErrorCode;
}
return AUDIO_ERROR_NOMEMORY;
}
return AUDIO_ERROR_INVALPARAM;
}
UINT AIAPI ADestroyAudioData(LPAUDIOWAVE lpWave)
{
UINT nErrorCode;
if (lpWave != NULL) {
nErrorCode = SynthDriver.DestroyAudioData(lpWave);
if (lpWave->lpData != NULL)
free(lpWave->lpData);
return nErrorCode;
}
return AUDIO_ERROR_INVALHANDLE;
}
UINT AIAPI AWriteAudioData(LPAUDIOWAVE lpWave, DWORD dwOffset, UINT nCount)
{
if (lpWave != NULL && lpWave->lpData != NULL) {
if (nCount != 0) {
return SynthDriver.WriteAudioData(lpWave, dwOffset, nCount);
}
return AUDIO_ERROR_INVALPARAM;
}
return AUDIO_ERROR_INVALHANDLE;
}
UINT AIAPI ACreateAudioVoice(LPHAC lphVoice)
{
UINT nVoice;
if (lphVoice != NULL) {
for (nVoice = 0; nVoice < nNumVoices; nVoice++) {
if (!aVoiceTable[nVoice]) {
*lphVoice = aVoiceTable[nVoice] = (HAC) (nVoice + 1);
return AUDIO_ERROR_NONE;
}
}
return AUDIO_ERROR_NOMEMORY;
}
return AUDIO_ERROR_INVALPARAM;
}
UINT AIAPI ADestroyAudioVoice(HAC hVoice)
{
UINT nVoice;
if ((nVoice = VOICENUM(hVoice)) < nNumVoices) {
aVoiceTable[nVoice] = (HAC) NULL;
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALHANDLE;
}
UINT AIAPI APlayVoice(HAC hVoice, LPAUDIOWAVE lpWave)
{
UINT nErrorCode;
if (lpWave != NULL) {
if (!(nErrorCode = APrimeVoice(hVoice, lpWave)) &&
!(nErrorCode = ASetVoiceFrequency(hVoice, lpWave->nSampleRate)))
return AStartVoice(hVoice);
return nErrorCode;
}
return AUDIO_ERROR_INVALHANDLE;
}
UINT AIAPI APrimeVoice(HAC hVoice, LPAUDIOWAVE lpWave)
{
return SynthDriver.PrimeVoice(VOICENUM(hVoice), lpWave);
}
UINT AIAPI AStartVoice(HAC hVoice)
{
return SynthDriver.StartVoice(VOICENUM(hVoice));
}
UINT AIAPI AStopVoice(HAC hVoice)
{
return SynthDriver.StopVoice(VOICENUM(hVoice));
}
UINT AIAPI ASetVoicePosition(HAC hVoice, LONG dwPosition)
{
return SynthDriver.SetVoicePosition(VOICENUM(hVoice), dwPosition);
}
UINT AIAPI ASetVoiceFrequency(HAC hVoice, LONG dwFrequency)
{
return SynthDriver.SetVoiceFrequency(VOICENUM(hVoice), dwFrequency);
}
UINT AIAPI ASetVoiceVolume(HAC hVoice, UINT nVolume)
{
return SynthDriver.SetVoiceVolume(VOICENUM(hVoice), nVolume);
}
UINT AIAPI ASetVoicePanning(HAC hVoice, UINT nPanning)
{
return SynthDriver.SetVoicePanning(VOICENUM(hVoice), nPanning);
}
UINT AIAPI AGetVoicePosition(HAC hVoice, LPLONG lpdwPosition)
{
return SynthDriver.GetVoicePosition(VOICENUM(hVoice), lpdwPosition);
}
UINT AIAPI AGetVoiceFrequency(HAC hVoice, LPLONG lpdwFrequency)
{
return SynthDriver.GetVoiceFrequency(VOICENUM(hVoice), lpdwFrequency);
}
UINT AIAPI AGetVoiceVolume(HAC hVoice, LPUINT lpnVolume)
{
return SynthDriver.GetVoiceVolume(VOICENUM(hVoice), lpnVolume);
}
UINT AIAPI AGetVoicePanning(HAC hVoice, LPUINT lpnPanning)
{
return SynthDriver.GetVoicePanning(VOICENUM(hVoice), lpnPanning);
}
UINT AIAPI AGetVoiceStatus(HAC hVoice, LPBOOL lpnStatus)
{
return SynthDriver.GetVoiceStatus(VOICENUM(hVoice), lpnStatus);
}
/*
* External system-dependant audio device drivers
*/
#ifdef __BEOS__
extern AUDIODRIVER BeOSR3Driver;
extern AUDIODRIVER BeOSDriver;
#endif
#ifdef __OS2__
extern AUDIODRIVER OS2MMPMDriver;
#endif
#ifdef __LINUX__
extern AUDIODRIVER LinuxDriver;
#endif
#ifdef __OSX__
//extern AUDIODRIVER MacOSXDriver;
extern AUDIODRIVER AllegDriver;
#endif
#ifdef __FREEBSD__
extern AUDIODRIVER LinuxDriver;
#endif
#ifdef __SPARC__
extern AUDIODRIVER SparcDriver;
#endif
#ifdef __SOLARIS__
extern AUDIODRIVER SparcDriver;
#endif
#ifdef __SILICON__
extern AUDIODRIVER SiliconDriver;
#endif
#ifdef __WINDOWS__
extern AUDIODRIVER WindowsDriver;
extern AUDIODRIVER DirectSoundDriver;
extern AUDIODRIVER DirectSoundAccelDriver;
#endif
#if defined(__DOS16__) || defined(__DPMI__)
extern AUDIODRIVER SoundBlasterDriver;
extern AUDIODRIVER SoundBlaster32Driver;
extern AUDIODRIVER ProAudioSpectrumDriver;
extern AUDIODRIVER UltraSoundDriver;
extern AUDIODRIVER UltraSoundMaxDriver;
extern AUDIODRIVER WinSndSystemDriver;
extern AUDIODRIVER SoundscapeDriver;
extern AUDIODRIVER AriaDriver;
#endif
#ifdef __SDL__
extern AUDIODRIVER SDLDriver;
#endif
UINT AIAPI AGetVersion(VOID)
{
/* return the current hard-coded audio system version */
return AUDIO_SYSTEM_VERSION;
}
UINT AIAPI AInitialize(VOID)
{
#ifdef __DJGPP__
/* 1998/12/20 lock code and data memory */
SEAL_LOCK_MEMORY();
#endif
/*
* Initialize all the audio system state variables,
* and registers all the built-in audio drivers.
*/
if (nDriverId != AUDIO_DEVICE_MAPPER)
return AUDIO_ERROR_NOTSUPPORTED;
ARegisterAudioDriver(&NoneDriver);
#ifdef __BEOS__
ARegisterAudioDriver(&BeOSR3Driver);
ARegisterAudioDriver(&BeOSDriver);
#endif
#ifdef __OS2__
ARegisterAudioDriver(&OS2MMPMDriver);
#endif
#ifdef __LINUX__
ARegisterAudioDriver(&LinuxDriver);
#endif
#ifdef __OSX__
// ARegisterAudioDriver(&MacOSXDriver);
ARegisterAudioDriver(&AllegDriver);
#endif
#ifdef __FREEBSD__
ARegisterAudioDriver(&LinuxDriver);
#endif
#ifdef __SPARC__
ARegisterAudioDriver(&SparcDriver);
#endif
#ifdef __SOLARIS__
ARegisterAudioDriver(&SparcDriver);
#endif
#ifdef __SILICON__
ARegisterAudioDriver(&SiliconDriver);
#endif
#ifdef __WINDOWS__
ARegisterAudioDriver(&WindowsDriver);
ARegisterAudioDriver(&DirectSoundAccelDriver);
ARegisterAudioDriver(&DirectSoundDriver);
#endif
#if defined(__DOS16__) || defined(__DPMI__)
ARegisterAudioDriver(&SoundBlasterDriver);
ARegisterAudioDriver(&SoundBlaster32Driver);
ARegisterAudioDriver(&ProAudioSpectrumDriver);
ARegisterAudioDriver(&UltraSoundMaxDriver);
ARegisterAudioDriver(&UltraSoundDriver);
ARegisterAudioDriver(&WinSndSystemDriver);
ARegisterAudioDriver(&SoundscapeDriver);
ARegisterAudioDriver(&AriaDriver);
#endif
#ifdef __SDL__
ARegisterAudioDriver(&SDLDriver);
#endif
return AAudioFatalError(AUDIO_ERROR_NONE);
}

391
seal-hack/src/audio.h Normal file
View File

@@ -0,0 +1,391 @@
/*
* $Id: audio.h 1.17 1996/09/25 17:13:02 chasan released $
* 1.18 1998/10/12 23:54:08 chasan released
* 1.19 1998/10/24 18:20:52 chasan released
* 1.20 1999/06/27 17:49:49 chasan released
*
* SEAL Synthetic Audio Library API Interface
*
* Copyright (C) 1995, 1996, 1997, 1998, 1999 Carlos Hasan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef __AUDIO_H
#define __AUDIO_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#ifndef WIN32
#define AIAPI
#else
#define AIAPI __stdcall
#endif
#ifndef WINAPI
/* atomic data types definitions */
#if 0
typedef void VOID;
typedef char CHAR;
typedef int INT;
typedef long LONG;
typedef int BOOL;
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned int UINT;
typedef unsigned long DWORD;
#else
typedef void VOID;
typedef int8_t CHAR;
typedef int32_t INT;
typedef int32_t LONG;
typedef int8_t BOOL;
typedef uint8_t BYTE;
typedef uint16_t WORD;
typedef uint32_t UINT;
typedef uint32_t DWORD;
#endif
typedef VOID* LPVOID;
typedef CHAR* LPCHAR;
typedef INT* LPINT;
typedef LONG* LPLONG;
typedef BOOL* LPBOOL;
typedef BYTE* LPBYTE;
typedef WORD* LPWORD;
typedef UINT* LPUINT;
typedef DWORD* LPDWORD;
typedef CHAR* LPSTR;
typedef DWORD HANDLE;
/* helper macros */
#define LOBYTE(s) ((BYTE)(s))
#define HIBYTE(s) ((BYTE)((WORD)(s)>>8))
#define LOWORD(l) ((WORD)(l))
#define HIWORD(l) ((WORD)((DWORD)(l)>>16))
#define MAKEWORD(l,h) ((WORD)(((BYTE)(l))|(((WORD)((BYTE)(h)))<<8)))
#define MAKELONG(l,h) ((DWORD)(((WORD)(l))|(((DWORD)((WORD)(h)))<<16)))
#endif
/* audio system version number */
#define AUDIO_SYSTEM_VERSION 0x0106
/* audio capabilities bit fields definitions */
#define AUDIO_FORMAT_1M08 0x00000001
#define AUDIO_FORMAT_1S08 0x00000002
#define AUDIO_FORMAT_1M16 0x00000004
#define AUDIO_FORMAT_1S16 0x00000008
#define AUDIO_FORMAT_2M08 0x00000010
#define AUDIO_FORMAT_2S08 0x00000020
#define AUDIO_FORMAT_2M16 0x00000040
#define AUDIO_FORMAT_2S16 0x00000080
#define AUDIO_FORMAT_4M08 0x00000100
#define AUDIO_FORMAT_4S08 0x00000200
#define AUDIO_FORMAT_4M16 0x00000400
#define AUDIO_FORMAT_4S16 0x00000800
/* audio format bit fields defines for devices and waveforms */
#define AUDIO_FORMAT_8BITS 0x0000
#define AUDIO_FORMAT_16BITS 0x0001
#define AUDIO_FORMAT_LOOP 0x0010
#define AUDIO_FORMAT_BIDILOOP 0x0020
#define AUDIO_FORMAT_REVERSE 0x0080
#define AUDIO_FORMAT_MONO 0x0000
#define AUDIO_FORMAT_STEREO 0x0100
#define AUDIO_FORMAT_FILTER 0x8000
/* audio resource limits defines */
#define AUDIO_MAX_VOICES 32
#define AUDIO_MAX_SAMPLES 16
#define AUDIO_MAX_PATCHES 128
#define AUDIO_MAX_PATTERNS 256
#define AUDIO_MAX_ORDERS 256
#define AUDIO_MAX_NOTES 96
#define AUDIO_MAX_POINTS 12
#define AUDIO_MIN_PERIOD 1
#define AUDIO_MAX_PERIOD 31999
#define AUDIO_MIN_VOLUME 0x00
#define AUDIO_MAX_VOLUME 0x40
#define AUDIO_MIN_PANNING 0x00
#define AUDIO_MAX_PANNING 0xFF
#define AUDIO_MIN_POSITION 0x00000000L
#define AUDIO_MAX_POSITION 0x00100000L
#define AUDIO_MIN_FREQUENCY 0x00000200L
#define AUDIO_MAX_FREQUENCY 0x00080000L
/* audio error code defines */
#define AUDIO_ERROR_NONE 0x0000
#define AUDIO_ERROR_INVALHANDLE 0x0001
#define AUDIO_ERROR_INVALPARAM 0x0002
#define AUDIO_ERROR_NOTSUPPORTED 0x0003
#define AUDIO_ERROR_BADDEVICEID 0x0004
#define AUDIO_ERROR_NODEVICE 0x0005
#define AUDIO_ERROR_DEVICEBUSY 0x0006
#define AUDIO_ERROR_BADFORMAT 0x0007
#define AUDIO_ERROR_NOMEMORY 0x0008
#define AUDIO_ERROR_NODRAMMEMORY 0x0009
#define AUDIO_ERROR_FILENOTFOUND 0x000A
#define AUDIO_ERROR_BADFILEFORMAT 0x000B
#define AUDIO_LAST_ERROR 0x000B
/* audio device identifiers */
#define AUDIO_DEVICE_NONE 0x0000
#define AUDIO_DEVICE_MAPPER 0xFFFF
/* audio product identifiers */
#define AUDIO_PRODUCT_NONE 0x0000
#define AUDIO_PRODUCT_SB 0x0001
#define AUDIO_PRODUCT_SB15 0x0002
#define AUDIO_PRODUCT_SB20 0x0003
#define AUDIO_PRODUCT_SBPRO 0x0004
#define AUDIO_PRODUCT_SB16 0x0005
#define AUDIO_PRODUCT_AWE32 0x0006
#define AUDIO_PRODUCT_WSS 0x0007
#define AUDIO_PRODUCT_ESS 0x0008
#define AUDIO_PRODUCT_GUS 0x0009
#define AUDIO_PRODUCT_GUSDB 0x000A
#define AUDIO_PRODUCT_GUSMAX 0x000B
#define AUDIO_PRODUCT_IWAVE 0x000C
#define AUDIO_PRODUCT_PAS 0x000D
#define AUDIO_PRODUCT_PAS16 0x000E
#define AUDIO_PRODUCT_ARIA 0x000F
#define AUDIO_PRODUCT_WINDOWS 0x0100
#define AUDIO_PRODUCT_LINUX 0x0101
#define AUDIO_PRODUCT_SPARC 0x0102
#define AUDIO_PRODUCT_SGI 0x0103
#define AUDIO_PRODUCT_DSOUND 0x0104
#define AUDIO_PRODUCT_OS2MMPM 0x0105
#define AUDIO_PRODUCT_OS2DART 0x0106
#define AUDIO_PRODUCT_BEOSR3 0x0107
#define AUDIO_PRODUCT_BEOS 0x0108
#define AUDIO_PRODUCT_QNX 0x0109
/* audio mixer channels */
#define AUDIO_MIXER_MASTER_VOLUME 0x0001
#define AUDIO_MIXER_TREBLE 0x0002
#define AUDIO_MIXER_BASS 0x0003
#define AUDIO_MIXER_CHORUS 0x0004
#define AUDIO_MIXER_REVERB 0x0005
/* audio envelope bit fields */
#define AUDIO_ENVELOPE_ON 0x0001
#define AUDIO_ENVELOPE_SUSTAIN 0x0002
#define AUDIO_ENVELOPE_LOOP 0x0004
/* audio pattern bit fields */
#define AUDIO_PATTERN_PACKED 0x0080
#define AUDIO_PATTERN_NOTE 0x0001
#define AUDIO_PATTERN_SAMPLE 0x0002
#define AUDIO_PATTERN_VOLUME 0x0004
#define AUDIO_PATTERN_COMMAND 0x0008
#define AUDIO_PATTERN_PARAMS 0x0010
/* audio module bit fields */
#define AUDIO_MODULE_AMIGA 0x0000
#define AUDIO_MODULE_LINEAR 0x0001
#define AUDIO_MODULE_PANNING 0x8000
#pragma pack(1)
/* audio capabilities structure */
typedef struct {
WORD wProductId; /* product identifier */
CHAR szProductName[30]; /* product name */
DWORD dwFormats; /* formats supported */
} AUDIOCAPS, *LPAUDIOCAPS;
/* audio format structure */
typedef struct {
UINT nDeviceId; /* device identifier */
WORD wFormat; /* playback format */
WORD nSampleRate; /* sampling frequency */
} AUDIOINFO, *LPAUDIOINFO;
/* audio waveform structure */
typedef struct {
LPBYTE lpData; /* data pointer */
DWORD dwHandle; /* waveform handle */
DWORD dwLength; /* waveform length */
DWORD dwLoopStart; /* loop start point */
DWORD dwLoopEnd; /* loop end point */
WORD nSampleRate; /* sampling rate */
WORD wFormat; /* format bits */
} AUDIOWAVE, *LPAUDIOWAVE;
/* audio envelope point structure */
typedef struct {
WORD nFrame; /* envelope frame */
WORD nValue; /* envelope value */
} AUDIOPOINT, *LPAUDIOPOINT;
/* audio envelope structure */
typedef struct {
AUDIOPOINT aEnvelope[AUDIO_MAX_POINTS]; /* envelope points */
BYTE nPoints; /* number of points */
BYTE nSustain; /* sustain point */
BYTE nLoopStart; /* loop start point */
BYTE nLoopEnd; /* loop end point */
WORD wFlags; /* envelope flags */
WORD nSpeed; /* envelope speed */
} AUDIOENVELOPE, *LPAUDIOENVELOPE;
/* audio sample structure */
typedef struct {
CHAR szSampleName[32]; /* sample name */
BYTE nVolume; /* default volume */
BYTE nPanning; /* default panning */
BYTE nRelativeNote; /* relative note */
BYTE nFinetune; /* finetune */
AUDIOWAVE Wave; /* waveform handle */
} AUDIOSAMPLE, *LPAUDIOSAMPLE;
/* audio patch structure */
typedef struct {
CHAR szPatchName[32]; /* patch name */
BYTE aSampleNumber[AUDIO_MAX_NOTES]; /* multi-sample table */
WORD nSamples; /* number of samples */
BYTE nVibratoType; /* vibrato type */
BYTE nVibratoSweep; /* vibrato sweep */
BYTE nVibratoDepth; /* vibrato depth */
BYTE nVibratoRate; /* vibrato rate */
WORD nVolumeFadeout; /* volume fadeout */
AUDIOENVELOPE Volume; /* volume envelope */
AUDIOENVELOPE Panning; /* panning envelope */
LPAUDIOSAMPLE aSampleTable; /* sample table */
} AUDIOPATCH, *LPAUDIOPATCH;
/* audio pattern structure */
typedef struct {
WORD nPacking; /* packing type */
WORD nTracks; /* number of tracks */
WORD nRows; /* number of rows */
WORD nSize; /* data size */
LPBYTE lpData; /* data pointer */
} AUDIOPATTERN, *LPAUDIOPATTERN;
/* audio module structure */
typedef struct {
CHAR szModuleName[32]; /* module name */
WORD wFlags; /* module flags */
WORD nOrders; /* number of orders */
WORD nRestart; /* restart position */
WORD nTracks; /* number of tracks */
WORD nPatterns; /* number of patterns */
WORD nPatches; /* number of patches */
WORD nTempo; /* initial tempo */
WORD nBPM; /* initial BPM */
BYTE aOrderTable[AUDIO_MAX_ORDERS]; /* order table */
BYTE aPanningTable[AUDIO_MAX_VOICES]; /* panning table */
LPAUDIOPATTERN aPatternTable; /* pattern table */
LPAUDIOPATCH aPatchTable; /* patch table */
} AUDIOMODULE, *LPAUDIOMODULE;
/* audio music track structure */
typedef struct {
BYTE nNote; /* note index */
BYTE nPatch; /* patch number */
BYTE nSample; /* sample number */
BYTE nCommand; /* effect command */
BYTE bParams; /* effect params */
BYTE nVolumeCmd; /* volume command */
BYTE nVolume; /* volume level */
BYTE nPanning; /* stereo panning */
LONG dwFrequency; /* note frequency */
WORD wPeriod; /* note period */
} AUDIOTRACK, *LPAUDIOTRACK;
/* audio callback function defines */
typedef VOID (AIAPI* LPFNAUDIOWAVE)(LPBYTE, UINT);
typedef VOID (AIAPI* LPFNAUDIOTIMER)(VOID);
typedef VOID (AIAPI* LPFNAUDIOCALLBACK)(BYTE, UINT, UINT);
/* audio handle defines */
typedef HANDLE HAC;
typedef HAC* LPHAC;
#pragma pack()
/* audio interface API prototypes */
UINT AIAPI AInitialize(VOID);
UINT AIAPI AGetVersion(VOID);
UINT AIAPI AGetAudioNumDevs(VOID);
UINT AIAPI AGetAudioDevCaps(UINT nDeviceId, LPAUDIOCAPS lpCaps);
UINT AIAPI AGetErrorText(UINT nErrorCode, LPSTR lpText, UINT nSize);
UINT AIAPI APingAudio(LPUINT lpnDeviceId);
UINT AIAPI AOpenAudio(LPAUDIOINFO lpInfo);
UINT AIAPI ACloseAudio(VOID);
UINT AIAPI AUpdateAudio(VOID);
UINT AIAPI AUpdateAudioEx(UINT nFrames);
UINT AIAPI ASetAudioMixerValue(UINT nChannel, UINT nValue);
UINT AIAPI AOpenVoices(UINT nVoices);
UINT AIAPI ACloseVoices(VOID);
UINT AIAPI ASetAudioCallback(LPFNAUDIOWAVE lpfnAudioWave);
UINT AIAPI ASetAudioTimerProc(LPFNAUDIOTIMER lpfnAudioTimer);
UINT AIAPI ASetAudioTimerRate(UINT nTimerRate);
LONG AIAPI AGetAudioDataAvail(VOID);
UINT AIAPI ACreateAudioData(LPAUDIOWAVE lpWave);
UINT AIAPI ADestroyAudioData(LPAUDIOWAVE lpWave);
UINT AIAPI AWriteAudioData(LPAUDIOWAVE lpWave, DWORD dwOffset, UINT nCount);
UINT AIAPI ACreateAudioVoice(LPHAC lphVoice);
UINT AIAPI ADestroyAudioVoice(HAC hVoice);
UINT AIAPI APlayVoice(HAC hVoice, LPAUDIOWAVE lpWave);
UINT AIAPI APrimeVoice(HAC hVoice, LPAUDIOWAVE lpWave);
UINT AIAPI AStartVoice(HAC hVoice);
UINT AIAPI AStopVoice(HAC hVoice);
UINT AIAPI ASetVoicePosition(HAC hVoice, LONG dwPosition);
UINT AIAPI ASetVoiceFrequency(HAC hVoice, LONG dwFrequency);
UINT AIAPI ASetVoiceVolume(HAC hVoice, UINT nVolume);
UINT AIAPI ASetVoicePanning(HAC hVoice, UINT nPanning);
UINT AIAPI AGetVoicePosition(HAC hVoice, LPLONG lpdwPosition);
UINT AIAPI AGetVoiceFrequency(HAC hVoice, LPLONG lpdwFrequency);
UINT AIAPI AGetVoiceVolume(HAC hVoice, LPUINT lpnVolume);
UINT AIAPI AGetVoicePanning(HAC hVoice, LPUINT lpnPanning);
UINT AIAPI AGetVoiceStatus(HAC hVoice, LPBOOL lpnStatus);
UINT AIAPI APlayModule(LPAUDIOMODULE lpModule);
UINT AIAPI AStopModule(VOID);
UINT AIAPI APauseModule(VOID);
UINT AIAPI AResumeModule(VOID);
UINT AIAPI ASetModuleVolume(UINT nVolume);
UINT AIAPI ASetModulePosition(UINT nOrder, UINT nRow);
UINT AIAPI AGetModuleVolume(LPUINT lpnVolume);
UINT AIAPI AGetModulePosition(LPUINT pnOrder, LPUINT lpnRow);
UINT AIAPI AGetModuleStatus(LPBOOL lpnStatus);
UINT AIAPI ASetModuleCallback(LPFNAUDIOCALLBACK lpfnAudioCallback);
UINT AIAPI ALoadModuleFile(LPSTR lpszFileName,
LPAUDIOMODULE* lplpModule, DWORD dwFileOffset);
UINT AIAPI AFreeModuleFile(LPAUDIOMODULE lpModule);
UINT AIAPI ALoadWaveFile(LPSTR lpszFileName,
LPAUDIOWAVE* lplpWave, DWORD dwFileOffset);
UINT AIAPI AFreeWaveFile(LPAUDIOWAVE lpWave);
UINT AIAPI AGetModuleTrack(UINT nTrack, LPAUDIOTRACK lpTrack);
#ifdef __cplusplus
};
#endif
#endif

383
seal-hack/src/audiodj.c Normal file
View File

@@ -0,0 +1,383 @@
/*
* @(#)audiodj.c 0.2 1998/12/20 Carlos Hasan (chasan@dcc.uchile.cl)
*
* Hack for DJGPP 2.01 to lock code and data into a contiguous memory region.
*
* Copyright (C) 1998-1999 Carlos Hasan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <dpmi.h>
#include <sys/nearptr.h>
static int __SEAL_BSS_BEGIN;
static int __SEAL_DATA_BEGIN = 0xCafe;
static int __SEAL_TEXT_BEGIN(void) { return 0; }
static void SEAL_LOCK_MEMORY(void);
#include "audio.c"
#include "wavfile.c"
#include "xmfile.c"
#include "s3mfile.c"
#include "modfile.c"
#include "mtmfile.c"
#include "iofile.c"
#include "modeng.c"
#undef BUFFERSIZE
#undef CLIP
#undef TIMEOUT
#undef DEBUG
#undef GetAudioCaps
#undef PingAudio
#undef OpenAudio
#undef CloseAudio
#undef UpdateAudio
#undef SetAudioCallback
#define GetAudioCaps noneGetAudioCaps
#define PingAudio nonePingAudio
#define OpenAudio noneOpenAudio
#define CloseAudio noneCloseAudio
#define UpdateAudio noneUpdateAudio
#define SetAudioCallback noneSetAudioCallback
#include "nondrv.c"
#undef BUFFERSIZE
#undef CLIP
#undef TIMEOUT
#undef DEBUG
#undef GetAudioCaps
#undef PingAudio
#undef OpenAudio
#undef CloseAudio
#undef UpdateAudio
#undef SetAudioCallback
#define GetAudioCaps sbGetAudioCaps
#define PingAudio sbPingAudio
#define OpenAudio sbOpenAudio
#define CloseAudio sbCloseAudio
#define UpdateAudio sbUpdateAudio
#define SetAudioCallback sbSetAudioCallback
#include "sbdrv.c"
#undef BUFFERSIZE
#undef CLIP
#undef TIMEOUT
#undef DEBUG
#undef GetAudioCaps
#undef PingAudio
#undef OpenAudio
#undef CloseAudio
#undef UpdateAudio
#undef SetAudioCallback
#define GetAudioCaps pasGetAudioCaps
#define PingAudio pasPingAudio
#define OpenAudio pasOpenAudio
#define CloseAudio pasCloseAudio
#define UpdateAudio pasUpdateAudio
#define SetAudioCallback pasSetAudioCallback
#include "pasdrv.c"
#undef BUFFERSIZE
#undef CLIP
#undef TIMEOUT
#undef DEBUG
#undef GetAudioCaps
#undef PingAudio
#undef OpenAudio
#undef CloseAudio
#undef UpdateAudio
#undef SetAudioCallback
#define GetAudioCaps wssGetAudioCaps
#define PingAudio wssPingAudio
#define OpenAudio wssOpenAudio
#define CloseAudio wssCloseAudio
#define UpdateAudio wssUpdateAudio
#define SetAudioCallback wssSetAudioCallback
#include "wssdrv.c"
#undef BUFFERSIZE
#undef CLIP
#undef TIMEOUT
#undef DEBUG
#undef GetAudioCaps
#undef PingAudio
#undef OpenAudio
#undef CloseAudio
#undef UpdateAudio
#undef SetAudioCallback
#define GetAudioCaps ariaGetAudioCaps
#define PingAudio ariaPingAudio
#define OpenAudio ariaOpenAudio
#define CloseAudio ariaCloseAudio
#define UpdateAudio ariaUpdateAudio
#define SetAudioCallback ariaSetAudioCallback
#include "ariadrv.c"
#undef BUFFERSIZE
#undef CLIP
#undef TIMEOUT
#undef DEBUG
#undef VOICE_START
#undef VOICE_STOP
#undef VOICE_LOOP
#undef VOICE_BIDILOOP
#undef aVolumeTable
#undef aFrequencyTable
#define aVolumeTable mixVolumeTable
#define aFrequencyTable mixFrequencyTable
#undef GetAudioCaps
#undef PingAudio
#undef OpenAudio
#undef CloseAudio
#undef UpdateAudio
#undef SetAudioCallback
#undef SetAudioMixerValue
#undef OpenVoices
#undef CloseVoices
#undef GetAudioDataAvail
#undef CreateAudioData
#undef DestroyAudioData
#undef WriteAudioData
#undef PrimeVoice
#undef StartVoice
#undef StopVoice
#undef SetVoicePosition
#undef SetVoiceFrequency
#undef SetVoiceVolume
#undef SetVoicePanning
#undef GetVoicePosition
#undef GetVoiceFrequency
#undef GetVoiceVolume
#undef GetVoicePanning
#undef GetVoiceStatus
#undef SetAudioTimerProc
#undef SetAudioTimerRate
#define GetAudioCaps mixGetAudioCaps
#define PingAudio mixPingAudio
#define OpenAudio mixOpenAudio
#define CloseAudio mixCloseAudio
#define UpdateAudio mixUpdateAudio
#define SetAudioCallback mixSetAudioCallback
#define SetAudioMixerValue mixSetAudioMixerValue
#define OpenVoices mixOpenVoices
#define CloseVoices mixCloseVoices
#define GetAudioDataAvail mixGetAudioDataAvail
#define CreateAudioData mixCreateAudioData
#define DestroyAudioData mixDestroyAudioData
#define WriteAudioData mixWriteAudioData
#define PrimeVoice mixPrimeVoice
#define StartVoice mixStartVoice
#define StopVoice mixStopVoice
#define SetVoicePosition mixSetVoicePosition
#define SetVoiceFrequency mixSetVoiceFrequency
#define SetVoiceVolume mixSetVoiceVolume
#define SetVoicePanning mixSetVoicePanning
#define GetVoicePosition mixGetVoicePosition
#define GetVoiceFrequency mixGetVoiceFrequency
#define GetVoiceVolume mixGetVoiceVolume
#define GetVoicePanning mixGetVoicePanning
#define GetVoiceStatus mixGetVoiceStatus
#define SetAudioTimerProc mixSetAudioTimerProc
#define SetAudioTimerRate mixSetAudioTimerRate
#include "mixdrv.c"
#undef BUFFERSIZE
#undef CLIP
#undef TIMEOUT
#undef DEBUG
#undef VOICE_START
#undef VOICE_STOP
#undef VOICE_LOOP
#undef VOICE_BIDILOOP
#undef aVolumeTable
#undef aFrequencyTable
#define aVolumeTable aweVolumeTable
#define aFrequencyTable aweFrequencyTable
#undef GetAudioCaps
#undef PingAudio
#undef OpenAudio
#undef CloseAudio
#undef UpdateAudio
#undef SetAudioCallback
#undef SetAudioMixerValue
#undef OpenVoices
#undef CloseVoices
#undef GetAudioDataAvail
#undef CreateAudioData
#undef DestroyAudioData
#undef WriteAudioData
#undef PrimeVoice
#undef StartVoice
#undef StopVoice
#undef SetVoicePosition
#undef SetVoiceFrequency
#undef SetVoiceVolume
#undef SetVoicePanning
#undef GetVoicePosition
#undef GetVoiceFrequency
#undef GetVoiceVolume
#undef GetVoicePanning
#undef GetVoiceStatus
#undef SetAudioTimerProc
#undef SetAudioTimerRate
#define GetAudioCaps aweGetAudioCaps
#define PingAudio awePingAudio
#define OpenAudio aweOpenAudio
#define CloseAudio aweCloseAudio
#define UpdateAudio aweUpdateAudio
#define SetAudioCallback aweSetAudioCallback
#define SetAudioMixerValue aweSetAudioMixerValue
#define OpenVoices aweOpenVoices
#define CloseVoices aweCloseVoices
#define GetAudioDataAvail aweGetAudioDataAvail
#define CreateAudioData aweCreateAudioData
#define DestroyAudioData aweDestroyAudioData
#define WriteAudioData aweWriteAudioData
#define PrimeVoice awePrimeVoice
#define StartVoice aweStartVoice
#define StopVoice aweStopVoice
#define SetVoicePosition aweSetVoicePosition
#define SetVoiceFrequency aweSetVoiceFrequency
#define SetVoiceVolume aweSetVoiceVolume
#define SetVoicePanning aweSetVoicePanning
#define GetVoicePosition aweGetVoicePosition
#define GetVoiceFrequency aweGetVoiceFrequency
#define GetVoiceVolume aweGetVoiceVolume
#define GetVoicePanning aweGetVoicePanning
#define GetVoiceStatus aweGetVoiceStatus
#define SetAudioTimerProc aweSetAudioTimerProc
#define SetAudioTimerRate aweSetAudioTimerRate
#include "awedrv.c"
#undef BUFFERSIZE
#undef CLIP
#undef TIMEOUT
#undef DEBUG
#undef VOICE_START
#undef VOICE_STOP
#undef VOICE_LOOP
#undef VOICE_BIDILOOP
#undef aVolumeTable
#undef aFrequencyTable
#define aVolumeTable gusVolumeTable
#define aFrequencyTable gusFrequencyTable
#undef GetAudioCaps
#undef PingAudio
#undef OpenAudio
#undef CloseAudio
#undef UpdateAudio
#undef SetAudioCallback
#undef SetAudioMixerValue
#undef OpenVoices
#undef CloseVoices
#undef GetAudioDataAvail
#undef CreateAudioData
#undef DestroyAudioData
#undef WriteAudioData
#undef PrimeVoice
#undef StartVoice
#undef StopVoice
#undef SetVoicePosition
#undef SetVoiceFrequency
#undef SetVoiceVolume
#undef SetVoicePanning
#undef GetVoicePosition
#undef GetVoiceFrequency
#undef GetVoiceVolume
#undef GetVoicePanning
#undef GetVoiceStatus
#undef SetAudioTimerProc
#undef SetAudioTimerRate
#define GetAudioCaps gusGetAudioCaps
#define PingAudio gusPingAudio
#define OpenAudio gusOpenAudio
#define CloseAudio gusCloseAudio
#define UpdateAudio gusUpdateAudio
#define SetAudioCallback gusSetAudioCallback
#define SetAudioMixerValue gusSetAudioMixerValue
#define OpenVoices gusOpenVoices
#define CloseVoices gusCloseVoices
#define GetAudioDataAvail gusGetAudioDataAvail
#define CreateAudioData gusCreateAudioData
#define DestroyAudioData gusDestroyAudioData
#define WriteAudioData gusWriteAudioData
#define PrimeVoice gusPrimeVoice
#define StartVoice gusStartVoice
#define StopVoice gusStopVoice
#define SetVoicePosition gusSetVoicePosition
#define SetVoiceFrequency gusSetVoiceFrequency
#define SetVoiceVolume gusSetVoiceVolume
#define SetVoicePanning gusSetVoicePanning
#define GetVoicePosition gusGetVoicePosition
#define GetVoiceFrequency gusGetVoiceFrequency
#define GetVoiceVolume gusGetVoiceVolume
#define GetVoicePanning gusGetVoicePanning
#define GetVoiceStatus gusGetVoiceStatus
#define SetAudioTimerProc gusSetAudioTimerProc
#define SetAudioTimerRate gusSetAudioTimerRate
#include "gusdrv.c"
#include "msdos.c"
static int __SEAL_BSS_END;
static int __SEAL_DATA_END = 0xCafe;
static int __SEAL_TEXT_END(void) { return 0; }
static void SEAL_LOCK_MEMORY(void)
{
/* lock in host memory the text, data and bss segments */
_go32_dpmi_lock_code(__SEAL_TEXT_BEGIN,
(long) __SEAL_TEXT_END - (long) __SEAL_TEXT_BEGIN);
_go32_dpmi_lock_data(&__SEAL_DATA_BEGIN,
(long) &__SEAL_DATA_END - (long) &__SEAL_DATA_BEGIN);
_go32_dpmi_lock_data(&__SEAL_BSS_BEGIN,
(long) &__SEAL_BSS_END - (long) &__SEAL_BSS_BEGIN);
/* lock conventional memory used for DMA buffers and IRQ callbacks */
_crt0_startup_flags |= _CRT0_FLAG_NEARPTR;
__djgpp_nearptr_enable();
_go32_dpmi_lock_data((void *) __djgpp_conventional_base, 640 << 10);
}

68
seal-hack/src/audiow32.c Normal file
View File

@@ -0,0 +1,68 @@
/*
* $Id: audiow32.c 1.7 1996/09/20 23:55:38 chasan released $
* 1.8 1998/12/24 15:07:30 chasan released (NT fix)
*
* Win32 dynamic-link library entry point routine
*
* Copyright (C) 1995-1999 Carlos Hasan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <windows.h>
#include "audio.h"
#ifdef WIN32
#define AUDIO_UPDATE_LATENCY 10 /* audio latency in milliseconds */
static HANDLE hThread;
static DWORD nThreadId;
static BOOL bTerminate;
DWORD WINAPI UpdateAudioThread(LPVOID lpThreadParameter)
{
LONG dwAudioTime, dwSleepTime;
dwAudioTime = GetTickCount();
while (!bTerminate) {
AUpdateAudio();
dwAudioTime += AUDIO_UPDATE_LATENCY;
if ((dwSleepTime = dwAudioTime - GetTickCount()) > 0)
Sleep(dwSleepTime);
}
return (lpThreadParameter != NULL);
}
#endif
#ifdef __MSC__
BOOL WINAPI DllMain(HINSTANCE hinstDLL,
DWORD fdwReason, LPVOID lpvReserved)
#else
BOOL WINAPI DllEntryPoint(HINSTANCE hinstDLL,
DWORD fdwReason, LPVOID lpvReserved)
#endif
{
if (fdwReason == DLL_PROCESS_ATTACH) {
AInitialize();
#ifdef WIN32
bTerminate = FALSE;
hThread = CreateThread(NULL, 0, UpdateAudioThread, NULL, 0, &nThreadId);
SetPriorityClass(hThread, HIGH_PRIORITY_CLASS);
SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL);
}
if (fdwReason == DLL_PROCESS_DETACH) {
bTerminate = TRUE;
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
#endif
}
if (hinstDLL != (HINSTANCE)0 && lpvReserved != (LPVOID)0) {
/* avoid compiler warnings */
}
return TRUE;
}

1384
seal-hack/src/awedrv.c Normal file

File diff suppressed because it is too large Load Diff

185
seal-hack/src/be3drv.c Normal file
View File

@@ -0,0 +1,185 @@
/*
* $Id: be3drv.c 1.0 1998/10/12 00:33:08 chasan Exp $
*
* Intel BeOS Release 3 audio driver.
*
* Copyright (C) 1998-1999 Carlos Hasan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <sys/ioctl.h>
#include "BeOS/old_audio_driver.h"
#include "audio.h"
#include "drivers.h"
#define BUFFERSIZE (1 << 12)
/*
* BeOS driver configuration structure
*/
static struct {
int nHandle;
char szDeviceName[MAXNAMLEN];
BYTE aBuffer[sizeof(audio_buffer_header) + BUFFERSIZE];
LPFNAUDIOWAVE lpfnAudioWave;
} Audio;
/*
* BeOS driver API interface
*/
static UINT AIAPI GetAudioCaps(LPAUDIOCAPS lpCaps)
{
static AUDIOCAPS Caps =
{
AUDIO_PRODUCT_BEOSR3, "BeOS R3 Sound Driver",
AUDIO_FORMAT_1M08 | AUDIO_FORMAT_1S08 |
AUDIO_FORMAT_1M16 | AUDIO_FORMAT_1S16 |
AUDIO_FORMAT_2M08 | AUDIO_FORMAT_2S08 |
AUDIO_FORMAT_2M16 | AUDIO_FORMAT_2S16 |
AUDIO_FORMAT_4M08 | AUDIO_FORMAT_4S08 |
AUDIO_FORMAT_4M16 | AUDIO_FORMAT_4S16
};
memcpy(lpCaps, &Caps, sizeof(AUDIOCAPS));
return AUDIO_ERROR_NONE;
}
static UINT AIAPI PingAudio(VOID)
{
DIR *dir;
struct dirent *entry;
/* first try the default sound device */
strcpy(Audio.szDeviceName, "/dev/old/sound");
if (access(Audio.szDeviceName, W_OK) == 0)
return AUDIO_ERROR_NONE;
/* search an old audio device */
if ((dir = opendir("/dev/old")) != 0) {
while ((entry = readdir(dir)) != 0) {
if (strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..")) {
strcat(strcpy(Audio.szDeviceName, "/dev/old/"), entry->d_name);
if (access(Audio.szDeviceName, W_OK) == 0) {
closedir(dir);
return AUDIO_ERROR_NONE;
}
}
}
closedir(dir);
}
return AUDIO_ERROR_NODEVICE;
}
static UINT AIAPI OpenAudio(LPAUDIOINFO lpInfo)
{
static int sample_rates[] = {
5510, B_AUDIO_SAMPLE_RATE_5510,
6620, B_AUDIO_SAMPLE_RATE_6620,
8000, B_AUDIO_SAMPLE_RATE_8000,
9600, B_AUDIO_SAMPLE_RATE_9600,
11025, B_AUDIO_SAMPLE_RATE_11025,
16000, B_AUDIO_SAMPLE_RATE_16000,
18900, B_AUDIO_SAMPLE_RATE_18900,
22050, B_AUDIO_SAMPLE_RATE_22050,
27420, B_AUDIO_SAMPLE_RATE_27420,
32000, B_AUDIO_SAMPLE_RATE_32000,
33075, B_AUDIO_SAMPLE_RATE_33075,
37800, B_AUDIO_SAMPLE_RATE_37800,
44100, B_AUDIO_SAMPLE_RATE_44100,
48000, B_AUDIO_SAMPLE_RATE_48000 };
struct audio_params params;
int index;
memset(&Audio, 0, sizeof(Audio));
/* search an old audio device for playback */
if (PingAudio() != AUDIO_ERROR_NONE)
return AUDIO_ERROR_NODEVICE;
/* try to open audio device for playback */
if ((Audio.nHandle = open(Audio.szDeviceName, O_WRONLY)) < 0)
return AUDIO_ERROR_DEVICEBUSY;
/* setup audio playback encoding format and sampling frequency */
if (ioctl(Audio.nHandle, B_AUDIO_GET_PARAMS, &params) < 0) {
close(Audio.nHandle);
return AUDIO_ERROR_NODEVICE;
}
for (index = 0; index < 2*13; index += 2) {
if (sample_rates[index] >= lpInfo->nSampleRate)
break;
}
lpInfo->nSampleRate = sample_rates[index];
params.sample_rate = sample_rates[index+1];
lpInfo->wFormat |= AUDIO_FORMAT_STEREO | AUDIO_FORMAT_16BITS;
/* params.playback_format = B_AUDIO_FORMAT_16_BIT_STEREO; */
if (ioctl(Audio.nHandle, B_AUDIO_SET_PARAMS, &params) < 0) {
close(Audio.nHandle);
return AUDIO_ERROR_BADFORMAT;
}
return AUDIO_ERROR_NONE;
}
static UINT AIAPI CloseAudio(VOID)
{
/* close DSP audio device */
close(Audio.nHandle);
return AUDIO_ERROR_NONE;
}
static UINT AIAPI UpdateAudio(UINT nFrames)
{
audio_buffer_header *header = (audio_buffer_header *) Audio.aBuffer;
/* compute frame size */
nFrames <<= 2;
if (nFrames <= 0 || nFrames > BUFFERSIZE)
nFrames = BUFFERSIZE;
/* send PCM samples to the DSP audio device */
if (Audio.lpfnAudioWave != NULL) {
Audio.lpfnAudioWave(Audio.aBuffer + sizeof(*header), nFrames);
header->buffer_number = 0;
header->subscriber_count = 0;
header->reserved_1 = sizeof(*header) + nFrames;
ioctl(Audio.nHandle, B_AUDIO_WRITE_BUFFER, header);
}
return AUDIO_ERROR_NONE;
}
static UINT AIAPI SetAudioCallback(LPFNAUDIOWAVE lpfnAudioWave)
{
/* set up DSP audio device user's callback function */
Audio.lpfnAudioWave = lpfnAudioWave;
return AUDIO_ERROR_NONE;
}
/*
* BeOS driver public interface
*/
AUDIOWAVEDRIVER BeOSR3WaveDriver =
{
GetAudioCaps, PingAudio, OpenAudio, CloseAudio,
UpdateAudio, SetAudioCallback
};
AUDIODRIVER BeOSR3Driver =
{
&BeOSR3WaveDriver, NULL
};

185
seal-hack/src/be4drv.c Normal file
View File

@@ -0,0 +1,185 @@
/*
* $Id: bedrv.c 1.1 1998/10/24 18:24:26 chasan Exp $
*
* Intel BeOS Release 4 audio driver.
*
* Copyright (C) 1998-1999 Carlos Hasan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include "BeOS/audio_driver.h"
#include "audio.h"
#include "drivers.h"
#define BUFFERSIZE 200 /* 200 ms */
/*
* BeOS driver configuration structure
*/
static struct {
int nHandle;
char szDeviceName[MAXNAMLEN];
LPBYTE lpBuffer;
int nBufferSize;
LPFNAUDIOWAVE lpfnAudioWave;
WORD wFormat;
} Audio;
/*
* BeOS driver API interface
*/
static UINT AIAPI GetAudioCaps(LPAUDIOCAPS lpCaps)
{
static AUDIOCAPS Caps =
{
AUDIO_PRODUCT_BEOS, "BeOS Sound Driver",
AUDIO_FORMAT_1M08 | AUDIO_FORMAT_1S08 |
AUDIO_FORMAT_1M16 | AUDIO_FORMAT_1S16 |
AUDIO_FORMAT_2M08 | AUDIO_FORMAT_2S08 |
AUDIO_FORMAT_2M16 | AUDIO_FORMAT_2S16 |
AUDIO_FORMAT_4M08 | AUDIO_FORMAT_4S08 |
AUDIO_FORMAT_4M16 | AUDIO_FORMAT_4S16
};
memcpy(lpCaps, &Caps, sizeof(AUDIOCAPS));
return AUDIO_ERROR_NONE;
}
static UINT AIAPI PingAudio(VOID)
{
DIR *dir;
struct dirent *entry;
struct stat st;
/* search an audio device */
if ((dir = opendir("/dev/audio")) != 0) {
while ((entry = readdir(dir)) != 0) {
if (strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..")) {
strcat(strcpy(Audio.szDeviceName, "/dev/audio/"), entry->d_name);
if (stat(Audio.szDeviceName, &st) < 0 || S_ISDIR(st.st_mode))
continue;
if (access(Audio.szDeviceName, W_OK) == 0) {
closedir(dir);
return AUDIO_ERROR_NONE;
}
}
}
closedir(dir);
}
return AUDIO_ERROR_NODEVICE;
}
static UINT AIAPI OpenAudio(LPAUDIOINFO lpInfo)
{
struct audio_format config;
memset(&Audio, 0, sizeof(Audio));
/* search an old audio device for playback */
if (PingAudio() != AUDIO_ERROR_NONE)
return AUDIO_ERROR_NODEVICE;
/* try to open audio device for playback */
if ((Audio.nHandle = open(Audio.szDeviceName, O_WRONLY)) < 0)
return AUDIO_ERROR_DEVICEBUSY;
/* compute 200 ms latency buffer size */
Audio.nBufferSize = lpInfo->nSampleRate;
if (lpInfo->wFormat & AUDIO_FORMAT_16BITS)
Audio.nBufferSize <<= 1;
if (lpInfo->wFormat & AUDIO_FORMAT_STEREO)
Audio.nBufferSize <<= 1;
Audio.nBufferSize /= (1000 / BUFFERSIZE);
Audio.nBufferSize += 15;
Audio.nBufferSize &= ~15;
/* setup audio playback encoding format and sampling frequency */
config.sample_rate = lpInfo->nSampleRate;
config.channels = (lpInfo->wFormat & AUDIO_FORMAT_STEREO ? 2 : 1);
config.format = (lpInfo->wFormat & AUDIO_FORMAT_16BITS ? 0x02 : 0x11);
config.big_endian = 0;
config.buf_header = 0;
config.play_buf_size = Audio.nBufferSize;
config.rec_buf_size = Audio.nBufferSize;
if (ioctl(Audio.nHandle, B_AUDIO_SET_AUDIO_FORMAT, &config) < 0) {
close(Audio.nHandle);
return AUDIO_ERROR_NODEVICE;
}
if (ioctl(Audio.nHandle, B_AUDIO_GET_AUDIO_FORMAT, &config) < 0) {
close(Audio.nHandle);
return AUDIO_ERROR_NODEVICE;
}
lpInfo->nSampleRate = config.sample_rate;
lpInfo->wFormat = AUDIO_FORMAT_8BITS | AUDIO_FORMAT_MONO;
if (config.format == 0x02)
lpInfo->wFormat |= AUDIO_FORMAT_16BITS;
if (config.channels == 2)
lpInfo->wFormat |= AUDIO_FORMAT_STEREO;
/* allocate audio buffer area */
if ((Audio.lpBuffer = (LPBYTE) malloc(Audio.nBufferSize)) == NULL) {
close(Audio.nHandle);
return AUDIO_ERROR_NOMEMORY;
}
Audio.wFormat = lpInfo->wFormat;
return AUDIO_ERROR_NONE;
}
static UINT AIAPI CloseAudio(VOID)
{
/* close DSP audio device */
close(Audio.nHandle);
return AUDIO_ERROR_NONE;
}
static UINT AIAPI UpdateAudio(UINT nFrames)
{
/* compute frame size */
if (Audio.wFormat & AUDIO_FORMAT_16BITS) nFrames <<= 1;
if (Audio.wFormat & AUDIO_FORMAT_STEREO) nFrames <<= 1;
if (nFrames <= 0 || nFrames > Audio.nBufferSize)
nFrames = Audio.nBufferSize;
/* send PCM samples to the DSP audio device */
if (Audio.lpfnAudioWave != NULL) {
Audio.lpfnAudioWave(Audio.lpBuffer, nFrames);
write(Audio.nHandle, Audio.lpBuffer, nFrames);
}
return AUDIO_ERROR_NONE;
}
static UINT AIAPI SetAudioCallback(LPFNAUDIOWAVE lpfnAudioWave)
{
/* set up DSP audio device user's callback function */
Audio.lpfnAudioWave = lpfnAudioWave;
return AUDIO_ERROR_NONE;
}
/*
* BeOS driver public interface
*/
AUDIOWAVEDRIVER BeOSWaveDriver =
{
GetAudioCaps, PingAudio, OpenAudio, CloseAudio,
UpdateAudio, SetAudioCallback
};
AUDIODRIVER BeOSDriver =
{
&BeOSWaveDriver, NULL
};

174
seal-hack/src/bedrv.cpp Normal file
View File

@@ -0,0 +1,174 @@
/*
* $Id: bedrv.c 0.1 1998/12/19 18:24:26 chasan Exp $
*
* Intel BeOS Release 4 audio driver using the New Media Kit.
*
* Copyright (C) 1998 Carlos Hasan. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <MediaDefs.h>
#include <SoundPlayer.h>
#include "audio.h"
#include "drivers.h"
/*
* BeOS driver configuration structure
*/
static struct {
BSoundPlayer *Player;
LPFNAUDIOWAVE lpfnAudioWave;
} Audio;
/*
* BeOS driver API interface
*/
static UINT AIAPI GetAudioCaps(LPAUDIOCAPS lpCaps)
{
static AUDIOCAPS Caps =
{
AUDIO_PRODUCT_BEOS, "BeOS Sound Player",
AUDIO_FORMAT_1M08 | AUDIO_FORMAT_1S08 |
AUDIO_FORMAT_1M16 | AUDIO_FORMAT_1S16 |
AUDIO_FORMAT_2M08 | AUDIO_FORMAT_2S08 |
AUDIO_FORMAT_2M16 | AUDIO_FORMAT_2S16 |
AUDIO_FORMAT_4M08 | AUDIO_FORMAT_4S08 |
AUDIO_FORMAT_4M16 | AUDIO_FORMAT_4S16
};
memcpy(lpCaps, &Caps, sizeof(AUDIOCAPS));
return AUDIO_ERROR_NONE;
}
static void PlayAudio(void *cookie, void *buffer, size_t size,
const media_raw_audio_format& fmt)
{
static float hitable[256], lotable[256];
static float scale = 0.0f;
float *float_buffer = (float *) buffer;
short *short_buffer = (short *) buffer + (size >> 2);
size >>= 2;
/* lazily build the integer to float translation table */
if (scale == 0.0f) {
int i;
scale = 1.0f / 32768.0f;
for (i = -128; i < 128; i++)
hitable[i & 255] = scale * 256.0f * i;
for (i = 0; i < 255; i++)
lotable[i] = scale * i;
}
/* streams of 44100 Hz, stereo, 32bit floats are supported */
if (fmt.format != media_raw_audio_format::B_AUDIO_FLOAT ||
fmt.channel_count != 2 || fmt.frame_rate != 44100 ||
Audio.lpfnAudioWave == NULL) {
memset(buffer, 0, size);
}
else {
/* make 44100 Hz, stereo, 16-bit signed integer samples */
Audio.lpfnAudioWave((LPBYTE) short_buffer, size << 1);
/* convert to 32-bit float samples using lookup table */
while (size >= 8) {
int *sample = (int *) short_buffer;
int s;
/* TODO: channels will be swapped in big-endian machines */
s = sample[0];
float_buffer[0] = hitable[(s >> 8) & 255] + lotable[s & 255];
float_buffer[1] = hitable[(s >> 24) & 255] + lotable[(s >> 16)&255];
s = sample[1];
float_buffer[2] = hitable[(s >> 8) & 255] + lotable[s & 255];
float_buffer[3] = hitable[(s >> 24) & 255] + lotable[(s >> 16)&255];
s = sample[2];
float_buffer[4] = hitable[(s >> 8) & 255] + lotable[s & 255];
float_buffer[5] = hitable[(s >> 24) & 255] + lotable[(s >> 16)&255];
s = sample[3];
float_buffer[6] = hitable[(s >> 8) & 255] + lotable[s & 255];
float_buffer[7] = hitable[(s >> 24) & 255] + lotable[(s >> 16)&255];
short_buffer += 8;
float_buffer += 8;
size -= 8;
}
while (size-- > 0) {
short s = *short_buffer++;
*float_buffer++ = hitable[(s >> 8) & 255] + lotable[s & 255];
}
}
}
static UINT AIAPI PingAudio(VOID)
{
return AUDIO_ERROR_NONE;
}
static UINT AIAPI OpenAudio(LPAUDIOINFO lpInfo)
{
/* clean up local state structure */
memset(&Audio, 0, sizeof(Audio));
/* create sound player */
if ((Audio.Player = new BSoundPlayer("SEAL Player", PlayAudio)) == NULL)
return AUDIO_ERROR_NODEVICE;
/* force default settings */
lpInfo->nSampleRate = 44100;
lpInfo->wFormat = AUDIO_FORMAT_16BITS | AUDIO_FORMAT_STEREO;
/* start sound player */
Audio.Player->SetHasData(true);
Audio.Player->Start();
return AUDIO_ERROR_NONE;
}
static UINT AIAPI CloseAudio(VOID)
{
if (Audio.Player != NULL) {
/* stop sound player */
Audio.Player->Stop();
/* release sound player */
delete Audio.Player;
Audio.Player = NULL;
}
return AUDIO_ERROR_NONE;
}
static UINT AIAPI UpdateAudio(UINT nFrames)
{
return AUDIO_ERROR_NONE;
}
static UINT AIAPI SetAudioCallback(LPFNAUDIOWAVE lpfnAudioWave)
{
/* set up audio device user's callback function */
Audio.lpfnAudioWave = lpfnAudioWave;
return AUDIO_ERROR_NONE;
}
/*
* BeOS driver public interface
*/
AUDIOWAVEDRIVER BeOSWaveDriver =
{
GetAudioCaps, PingAudio, OpenAudio, CloseAudio,
UpdateAudio, SetAudioCallback
};
AUDIODRIVER BeOSDriver =
{
&BeOSWaveDriver, NULL
};

83
seal-hack/src/drivers.h Normal file
View File

@@ -0,0 +1,83 @@
/*
* $Id: drivers.h 1.4 1996/08/05 18:51:19 chasan released $
*
* Audio device drivers interface
*
* Copyright (C) 1995-1999 Carlos Hasan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef __DRIVERS_H
#define __DRIVERS_H
#ifndef __AUDIO_H
#include "audio.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*
* Audio device driver structures
*/
typedef struct {
UINT (AIAPI* GetAudioCaps)(LPAUDIOCAPS);
UINT (AIAPI* PingAudio)(VOID);
UINT (AIAPI* OpenAudio)(LPAUDIOINFO);
UINT (AIAPI* CloseAudio)(VOID);
UINT (AIAPI* UpdateAudio)(UINT);
UINT (AIAPI* SetAudioCallback)(LPFNAUDIOWAVE);
} AUDIOWAVEDRIVER, *LPAUDIOWAVEDRIVER;
typedef struct {
UINT (AIAPI* GetAudioCaps)(LPAUDIOCAPS);
UINT (AIAPI* PingAudio)(VOID);
UINT (AIAPI* OpenAudio)(LPAUDIOINFO);
UINT (AIAPI* CloseAudio)(VOID);
UINT (AIAPI* UpdateAudio)(VOID);
UINT (AIAPI* OpenVoices)(UINT);
UINT (AIAPI* CloseVoices)(VOID);
UINT (AIAPI* SetAudioTimerProc)(LPFNAUDIOTIMER);
UINT (AIAPI* SetAudioTimerRate)(UINT);
UINT (AIAPI* SetAudioMixerValue)(UINT, UINT); /*NEW:1998/10/24*/
LONG (AIAPI* GetAudioDataAvail)(VOID);
UINT (AIAPI* CreateAudioData)(LPAUDIOWAVE);
UINT (AIAPI* DestroyAudioData)(LPAUDIOWAVE);
UINT (AIAPI* WriteAudioData)(LPAUDIOWAVE, DWORD, UINT);
UINT (AIAPI* PrimeVoice)(UINT, LPAUDIOWAVE);
UINT (AIAPI* StartVoice)(UINT);
UINT (AIAPI* StopVoice)(UINT);
UINT (AIAPI* SetVoicePosition)(UINT, LONG);
UINT (AIAPI* SetVoiceFrequency)(UINT, LONG);
UINT (AIAPI* SetVoiceVolume)(UINT, UINT);
UINT (AIAPI* SetVoicePanning)(UINT, UINT);
UINT (AIAPI* GetVoicePosition)(UINT, LPLONG);
UINT (AIAPI* GetVoiceFrequency)(UINT, LPLONG);
UINT (AIAPI* GetVoiceVolume)(UINT, LPUINT);
UINT (AIAPI* GetVoicePanning)(UINT, LPUINT);
UINT (AIAPI* GetVoiceStatus)(UINT, LPBOOL);
} AUDIOSYNTHDRIVER, *LPAUDIOSYNTHDRIVER;
typedef struct {
LPAUDIOWAVEDRIVER lpWaveDriver;
LPAUDIOSYNTHDRIVER lpSynthDriver;
} AUDIODRIVER, *LPAUDIODRIVER;
/*
* External device-independant software drivers
*/
extern AUDIODRIVER NoneDriver;
extern AUDIOWAVEDRIVER NoneWaveDriver;
extern AUDIOSYNTHDRIVER NoneSynthDriver;
extern AUDIOSYNTHDRIVER EmuSynthDriver;
#ifdef __cplusplus
};
#endif
#endif

313
seal-hack/src/dsdrv.c Normal file
View File

@@ -0,0 +1,313 @@
/*
* $Id: dsdrv.c 1.5 1997/01/05 16:23:47 chasan Exp $
*
* Microsoft DirectSound audio driver interface
*
* Copyright (c) 1996-1999 Carlos Hasan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#define MSGBOX(text)
#define INITGUID
#include <windows.h>
#include <objbase.h>
#include <dsound.h>
#include "audio.h"
#include "drivers.h"
static struct {
LPDIRECTSOUND lpDirectSound;
LPDIRECTSOUNDBUFFER lpPrimaryBuffer;
LPDIRECTSOUNDBUFFER lpSoundBuffer;
LPFNAUDIOWAVE lpfnAudioWave;
DWORD dwBufferOffset;
DWORD dwBufferSize;
WORD nSampleRate;
WORD wFormat;
} DS;
static HRESULT _DirectSoundCreate(GUID FAR * lpGuid,
LPDIRECTSOUND *lplpDirectSound, IUnknown FAR * lpUnkOuter)
{
HRESULT hresult;
CoInitialize(NULL);
hresult = CoCreateInstance(&CLSID_DirectSound, lpUnkOuter,
CLSCTX_ALL, &IID_IDirectSound, lplpDirectSound);
if (!FAILED(hresult))
hresult = IDirectSound_Initialize(*lplpDirectSound, NULL);
return hresult;
}
static HRESULT _DirectSoundDestroy(LPDIRECTSOUND lpDirectSound)
{
HRESULT hresult;
hresult = IDirectSound_Release(lpDirectSound);
CoUninitialize();
return hresult;
}
static UINT AIAPI GetAudioCaps(LPAUDIOCAPS lpCaps)
{
strncpy(lpCaps->szProductName, "DirectSound",
sizeof(lpCaps->szProductName));
lpCaps->wProductId = AUDIO_PRODUCT_DSOUND;
lpCaps->dwFormats =
AUDIO_FORMAT_1M08 | AUDIO_FORMAT_1S08 |
AUDIO_FORMAT_1M16 | AUDIO_FORMAT_1S16 |
AUDIO_FORMAT_2M08 | AUDIO_FORMAT_2S08 |
AUDIO_FORMAT_2M16 | AUDIO_FORMAT_2S16 |
AUDIO_FORMAT_4M08 | AUDIO_FORMAT_4S08 |
AUDIO_FORMAT_4M16 | AUDIO_FORMAT_4S16 ;
return AUDIO_ERROR_NONE;
}
static UINT AIAPI PingAudio(VOID)
{
LPDIRECTSOUND lpDirectSound;
if (_DirectSoundCreate(NULL, &lpDirectSound, NULL) != DS_OK)
return AUDIO_ERROR_NODEVICE;
_DirectSoundDestroy(lpDirectSound);
return AUDIO_ERROR_NONE;
}
static UINT AIAPI OpenAudio(LPAUDIOINFO lpInfo)
{
DSBUFFERDESC dsbd;
DSBCAPS dsbc;
DSCAPS dsc;
WAVEFORMATEX wfx;
memset(&DS, 0, sizeof(DS));
/* create the direct sound object */
if (_DirectSoundCreate(NULL, &DS.lpDirectSound, NULL) != DS_OK) {
MSGBOX("Failed to create DirectSound COM object");
return AUDIO_ERROR_NODEVICE;
}
/* set direct sound cooperative level */
if (DS.lpDirectSound->lpVtbl->SetCooperativeLevel(
DS.lpDirectSound, GetForegroundWindow(), DSSCL_PRIORITY) != DS_OK) {
MSGBOX("DirectSound SetCooperativeLevel failed");
_DirectSoundDestroy(DS.lpDirectSound);
return AUDIO_ERROR_NODEVICE;
}
/* get DirectSound capabilities */
dsc.dwSize = sizeof(dsc);
if (DS.lpDirectSound->lpVtbl->GetCaps(DS.lpDirectSound, &dsc) != DS_OK) {
MSGBOX("Cannot get DirectSound capabilities");
_DirectSoundDestroy(DS.lpDirectSound);
return AUDIO_ERROR_NODEVICE;
}
if (!(dsc.dwFlags & DSCAPS_PRIMARYSTEREO))
lpInfo->wFormat &= ~AUDIO_FORMAT_STEREO;
if (!(dsc.dwFlags & DSCAPS_SECONDARY16BIT))
lpInfo->wFormat &= ~AUDIO_FORMAT_16BITS;
/* set up wave format structure */
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nChannels = lpInfo->wFormat & AUDIO_FORMAT_STEREO ? 2 : 1;
wfx.wBitsPerSample = lpInfo->wFormat & AUDIO_FORMAT_16BITS ? 16 : 8;
wfx.nSamplesPerSec = lpInfo->nSampleRate;
wfx.nAvgBytesPerSec = lpInfo->nSampleRate;
wfx.nBlockAlign = 1;
wfx.cbSize = 0;
if (lpInfo->wFormat & AUDIO_FORMAT_STEREO) {
wfx.nAvgBytesPerSec <<= 1;
wfx.nBlockAlign <<= 1;
}
if (lpInfo->wFormat & AUDIO_FORMAT_16BITS) {
wfx.nAvgBytesPerSec <<= 1;
wfx.nBlockAlign <<= 1;
}
/* create primary sound buffer */
memset(&dsbd, 0, sizeof(dsbd));
dsbd.dwSize = sizeof(dsbd);
dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER;
dsbd.dwBufferBytes = 0;
dsbd.lpwfxFormat = NULL;
if (DS.lpDirectSound->lpVtbl->CreateSoundBuffer(
DS.lpDirectSound, &dsbd, &DS.lpPrimaryBuffer, NULL) != DS_OK) {
MSGBOX("Cannot create primary buffer");
_DirectSoundDestroy(DS.lpDirectSound);
return AUDIO_ERROR_NODEVICE;
}
/* set up primary buffer format */
while (DS.lpPrimaryBuffer->lpVtbl->SetFormat(DS.lpPrimaryBuffer, &wfx) != DS_OK) {
if (lpInfo->nSampleRate <= 11025) {
MSGBOX("Can't change primary buffer format");
DS.lpPrimaryBuffer->lpVtbl->Release(DS.lpPrimaryBuffer);
_DirectSoundDestroy(DS.lpDirectSound);
return AUDIO_ERROR_NODEVICE;
}
wfx.nSamplesPerSec >>= 1;
wfx.nAvgBytesPerSec >>= 1;
wfx.nBlockAlign >>= 1;
lpInfo->nSampleRate >>= 1;
}
/* get primary buffer length */
dsbc.dwSize = sizeof(dsbc);
if (DS.lpPrimaryBuffer->lpVtbl->GetCaps(DS.lpPrimaryBuffer, &dsbc) != DS_OK) {
MSGBOX("Can't get primary buffer capabilities");
DS.lpPrimaryBuffer->lpVtbl->Release(DS.lpPrimaryBuffer);
_DirectSoundDestroy(DS.lpDirectSound);
return AUDIO_ERROR_NODEVICE;
}
/* the secondary buffer size should be between 20 ms and 100 ms */
if (dsbc.dwBufferBytes > (100L * wfx.nAvgBytesPerSec) / 1000) {
dsbc.dwBufferBytes = (100L * wfx.nAvgBytesPerSec) / 1000;
}
if (dsbc.dwBufferBytes < (20L * wfx.nAvgBytesPerSec) / 1000) {
dsbc.dwBufferBytes = (20L * wfx.nAvgBytesPerSec) / 1000;
}
/* [1998/12/24] in emulation mode use at least 150 ms buffers */
if (dsc.dwFlags & DSCAPS_EMULDRIVER) {
if (dsbc.dwBufferBytes < (150L * wfx.nAvgBytesPerSec) / 1000)
dsbc.dwBufferBytes = (150L * wfx.nAvgBytesPerSec) / 1000;
}
dsbc.dwBufferBytes >>= 2;
dsbc.dwBufferBytes <<= 2;
/* set up secondary buffer description */
memset(&dsbd, 0, sizeof(dsbd));
dsbd.dwSize = sizeof(dsbd);
dsbd.dwFlags = DSBCAPS_STICKYFOCUS | DSBCAPS_GETCURRENTPOSITION2;
dsbd.dwBufferBytes = dsbc.dwBufferBytes;
dsbd.lpwfxFormat = &wfx;
/* create secondary sound buffer */
if (DS.lpDirectSound->lpVtbl->CreateSoundBuffer(
DS.lpDirectSound, &dsbd, &DS.lpSoundBuffer, NULL) != DS_OK) {
MSGBOX("Can't create secondary buffer");
_DirectSoundDestroy(DS.lpDirectSound);
return AUDIO_ERROR_NODEVICE;
}
/* set up buffer chunk variables */
DS.dwBufferOffset = 0L;
DS.dwBufferSize = dsbd.dwBufferBytes;
/* start playing the primary buffer */
DS.lpPrimaryBuffer->lpVtbl->Play(DS.lpPrimaryBuffer, 0, 0, DSBPLAY_LOOPING);
/* start playing the secondary buffer */
DS.lpSoundBuffer->lpVtbl->Play(DS.lpSoundBuffer, 0, 0, DSBPLAY_LOOPING);
/* save audio format settings */
DS.nSampleRate = lpInfo->nSampleRate;
DS.wFormat = lpInfo->wFormat;
return AUDIO_ERROR_NONE;
}
static UINT AIAPI CloseAudio(VOID)
{
if (DS.lpDirectSound != NULL) {
/* release secondary sound buffer */
if (DS.lpSoundBuffer != NULL) {
DS.lpSoundBuffer->lpVtbl->Stop(DS.lpSoundBuffer);
DS.lpSoundBuffer->lpVtbl->Release(DS.lpSoundBuffer);
}
/* release primary sound buffer */
if (DS.lpPrimaryBuffer != NULL) {
DS.lpPrimaryBuffer->lpVtbl->Stop(DS.lpPrimaryBuffer);
DS.lpPrimaryBuffer->lpVtbl->Release(DS.lpPrimaryBuffer);
}
/* release direct sound */
_DirectSoundDestroy(DS.lpDirectSound);
}
memset(&DS, 0, sizeof(DS));
return AUDIO_ERROR_NONE;
}
static UINT AIAPI UpdateAudio(UINT nFrames)
{
LPVOID lpPtr1, lpPtr2;
DWORD dwBytes1, dwBytes2;
DWORD dwPlayOffset, dwWriteOffset;
LONG dwBytes;
if (DS.wFormat & AUDIO_FORMAT_STEREO) nFrames <<= 1;
if (DS.wFormat & AUDIO_FORMAT_16BITS) nFrames <<= 1;
if (nFrames <= 0 || nFrames >= DS.dwBufferSize)
nFrames = DS.dwBufferSize;
if (DS.lpSoundBuffer->lpVtbl->GetCurrentPosition(
DS.lpSoundBuffer, &dwPlayOffset, &dwWriteOffset) == DS_OK) {
if ((dwBytes = dwPlayOffset - DS.dwBufferOffset) < 0)
dwBytes += DS.dwBufferSize;
if (dwBytes > nFrames)
dwBytes = nFrames;
dwBytes &= ~3;
if ((dwBytes -= 128) > 0) {
if (DS.lpSoundBuffer->lpVtbl->Lock(
DS.lpSoundBuffer, DS.dwBufferOffset, dwBytes,
&lpPtr1, &dwBytes1, &lpPtr2, &dwBytes2, 0) == DS_OK) {
if (DS.lpfnAudioWave != NULL) {
DS.lpfnAudioWave(lpPtr1, dwBytes1);
if (lpPtr2 != NULL)
DS.lpfnAudioWave(lpPtr2, dwBytes2);
}
else {
memset(lpPtr1, 0, dwBytes1);
if (lpPtr2 != NULL)
memset(lpPtr2, 0, dwBytes2);
}
DS.lpSoundBuffer->lpVtbl->Unlock(DS.lpSoundBuffer,
lpPtr1, dwBytes1, lpPtr2, dwBytes2);
if ((DS.dwBufferOffset += dwBytes) >= DS.dwBufferSize)
DS.dwBufferOffset -= DS.dwBufferSize;
}
else {
DS.lpSoundBuffer->lpVtbl->Restore(DS.lpSoundBuffer);
}
}
}
return AUDIO_ERROR_NONE;
}
static UINT AIAPI SetAudioCallback(LPFNAUDIOWAVE lpfnAudioWave)
{
DS.lpfnAudioWave = lpfnAudioWave;
return AUDIO_ERROR_NONE;
}
/*
* DirectSound driver public interfaces
*/
AUDIOWAVEDRIVER DirectSoundWaveDriver =
{
GetAudioCaps, PingAudio, OpenAudio, CloseAudio,
UpdateAudio, SetAudioCallback
};
AUDIODRIVER DirectSoundDriver =
{
&DirectSoundWaveDriver, NULL
};

663
seal-hack/src/dsdrv2.c Normal file
View File

@@ -0,0 +1,663 @@
/*
* $Id: dsdrv2.c 0.4 1998/12/26 chasan Exp $
*
* DirectSound accelerated audio driver (Experimental)
*
* Copyright (C) 1998-1999 Carlos Hasan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <windows.h>
#include <objbase.h>
#include <dsound.h>
#include <math.h>
#include "audio.h"
#include "drivers.h"
#if 0
#define MSGBOX(text) MessageBox(NULL, text, "DirectSound", MB_OK)
#else
#define MSGBOX(text)
#endif
static struct {
LPDIRECTSOUND lpDirectSound;
LPDIRECTSOUNDBUFFER lpPrimaryBuffer;
LPDIRECTSOUNDBUFFER aSoundBuffer[AUDIO_MAX_VOICES];
LPFNAUDIOTIMER lpfnTimerHandler;
LONG aLogVolumeTable[AUDIO_MAX_VOLUME+1];
LONG aLogPanningTable[AUDIO_MAX_PANNING+1];
DWORD aFormatTable[AUDIO_MAX_VOICES];
LONG aFrequencyTable[AUDIO_MAX_VOICES];
UINT aVolumeTable[AUDIO_MAX_VOICES];
UINT aPanningTable[AUDIO_MAX_VOICES];
LONG dwTimer;
LONG dwTimerAccum;
LONG dwTimerRate;
} DS;
static HRESULT _DirectSoundCreate(GUID FAR *lpGuid,
LPDIRECTSOUND *lplpDirectSound, IUnknown FAR *lpUnkOuter)
{
HRESULT hresult;
CoInitialize(NULL);
hresult = CoCreateInstance(&CLSID_DirectSound, lpUnkOuter,
CLSCTX_ALL, &IID_IDirectSound, lplpDirectSound);
if (!FAILED(hresult))
hresult = IDirectSound_Initialize(*lplpDirectSound, NULL);
return hresult;
}
static HRESULT _DirectSoundDestroy(LPDIRECTSOUND lpDirectSound)
{
HRESULT hresult;
hresult = IDirectSound_Release(lpDirectSound);
CoUninitialize();
return hresult;
}
static UINT AIAPI SetAudioMixerValue(UINT, UINT);
/*
* DirectSound audio driver API interface
*/
static UINT AIAPI GetAudioCaps(LPAUDIOCAPS lpCaps)
{
static AUDIOCAPS Caps =
{
AUDIO_PRODUCT_NONE, "DirectSound (experimental)",
AUDIO_FORMAT_1M08 | AUDIO_FORMAT_1S08 |
AUDIO_FORMAT_1M16 | AUDIO_FORMAT_1S16 |
AUDIO_FORMAT_2M08 | AUDIO_FORMAT_2S08 |
AUDIO_FORMAT_2M16 | AUDIO_FORMAT_2S16 |
AUDIO_FORMAT_4M08 | AUDIO_FORMAT_4S08 |
AUDIO_FORMAT_4M16 | AUDIO_FORMAT_4S16
};
memcpy(lpCaps, &Caps, sizeof(AUDIOCAPS));
return AUDIO_ERROR_NONE;
}
static UINT AIAPI PingAudio(VOID)
{
LPDIRECTSOUND lpDirectSound;
if (_DirectSoundCreate(NULL, &lpDirectSound, NULL) != DS_OK)
return AUDIO_ERROR_NODEVICE;
_DirectSoundDestroy(lpDirectSound);
return AUDIO_ERROR_NONE;
}
static UINT AIAPI OpenAudio(LPAUDIOINFO lpInfo)
{
LPDIRECTSOUNDBUFFER lpPrimaryBuffer;
DSBUFFERDESC dsbd;
WAVEFORMATEX wfx;
DSCAPS dsc;
LONG nPanning;
memset(&DS, 0, sizeof(DS));
if (lpInfo == NULL)
return AUDIO_ERROR_INVALPARAM;
/* create direct sound object */
if (_DirectSoundCreate(NULL, &DS.lpDirectSound, NULL) != DS_OK)
return AUDIO_ERROR_NODEVICE;
/* set direct sound cooperative level */
if (DS.lpDirectSound->lpVtbl->SetCooperativeLevel(DS.lpDirectSound,
GetForegroundWindow(), DSSCL_PRIORITY) != DS_OK) {
_DirectSoundDestroy(DS.lpDirectSound);
return AUDIO_ERROR_NODEVICE;
}
/* get direct sound capabilities */
dsc.dwSize = sizeof(dsc);
if (DS.lpDirectSound->lpVtbl->GetCaps(DS.lpDirectSound, &dsc) != DS_OK) {
_DirectSoundDestroy(DS.lpDirectSound);
return AUDIO_ERROR_NODEVICE;
}
/* adjust the format settings */
lpInfo->nSampleRate = 44100;
if (!(dsc.dwFlags & DSCAPS_PRIMARYSTEREO))
lpInfo->wFormat &= ~AUDIO_FORMAT_STEREO;
if (!(dsc.dwFlags & DSCAPS_PRIMARY16BIT))
lpInfo->wFormat &= ~AUDIO_FORMAT_16BITS;
/* setup wave format structure */
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nChannels = lpInfo->wFormat & AUDIO_FORMAT_STEREO ? 2 : 1;
wfx.wBitsPerSample = lpInfo->wFormat & AUDIO_FORMAT_16BITS ? 16 : 8;
wfx.nSamplesPerSec = lpInfo->nSampleRate;
wfx.nAvgBytesPerSec = lpInfo->nSampleRate;
wfx.nBlockAlign = 1;
wfx.cbSize = 0;
if (lpInfo->wFormat & AUDIO_FORMAT_STEREO) {
wfx.nAvgBytesPerSec <<= 1;
wfx.nBlockAlign <<= 1;
}
if (lpInfo->wFormat & AUDIO_FORMAT_16BITS) {
wfx.nAvgBytesPerSec <<= 1;
wfx.nBlockAlign <<= 1;
}
/* create primary sound buffer */
memset(&dsbd, 0, sizeof(dsbd));
dsbd.dwSize = sizeof(dsbd);
dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER;
dsbd.dwBufferBytes = 0;
dsbd.lpwfxFormat = NULL;
if (DS.lpDirectSound->lpVtbl->CreateSoundBuffer(DS.lpDirectSound,
&dsbd, &DS.lpPrimaryBuffer, NULL) != DS_OK) {
MSGBOX("Can't create primary buffer");
_DirectSoundDestroy(DS.lpDirectSound);
return AUDIO_ERROR_NODEVICE;
}
/* setup primary buffer format */
while (DS.lpPrimaryBuffer->lpVtbl->SetFormat(DS.lpPrimaryBuffer, &wfx) != DS_OK) {
if (lpInfo->nSampleRate <= 11025) {
MSGBOX("Can't change primary buffer format");
_DirectSoundDestroy(DS.lpDirectSound);
return AUDIO_ERROR_NODEVICE;
}
wfx.nSamplesPerSec >>= 1;
wfx.nAvgBytesPerSec >>= 1;
wfx.nBlockAlign >>= 1;
lpInfo->nSampleRate >>= 1;
}
/* start playing primary buffer */
DS.lpPrimaryBuffer->lpVtbl->Play(DS.lpPrimaryBuffer, 0, 0, DSBPLAY_LOOPING);
/* set the timer settings */
DS.dwTimer = GetTickCount();
DS.dwTimerAccum = 0;
/* set default master volume */
SetAudioMixerValue(AUDIO_MIXER_MASTER_VOLUME, 96);
/* create log panning table */
for (nPanning = 0; nPanning <= AUDIO_MAX_PANNING; nPanning++) {
DS.aLogPanningTable[nPanning] = (2000 * (nPanning - 128)) >> 7;
}
return AUDIO_ERROR_NONE;
}
static UINT AIAPI CloseAudio(VOID)
{
UINT i;
if (DS.lpDirectSound != NULL) {
/* stop and release primary buffer */
if (DS.lpPrimaryBuffer != NULL) {
DS.lpPrimaryBuffer->lpVtbl->Stop(DS.lpPrimaryBuffer);
DS.lpPrimaryBuffer->lpVtbl->Release(DS.lpPrimaryBuffer);
}
/* release duplicated sound buffers */
for (i = 0; i < AUDIO_MAX_VOICES; i++) {
if (DS.aSoundBuffer[i] != NULL) {
DS.aSoundBuffer[i]->lpVtbl->Stop(DS.aSoundBuffer[i]);
DS.aSoundBuffer[i]->lpVtbl->Release(DS.aSoundBuffer[i]);
}
}
/* release direct sound buffer */
_DirectSoundDestroy(DS.lpDirectSound);
}
/* clean up DirectSound driver variables */
memset(&DS, 0, sizeof(DS));
return AUDIO_ERROR_NONE;
}
static UINT AIAPI UpdateAudio(UINT nFrames)
{
LONG dwTimer = GetTickCount();
/* call the virtual audio timer callback */
if ((DS.dwTimerAccum += dwTimer - DS.dwTimer) >= DS.dwTimerRate) {
DS.dwTimerAccum -= DS.dwTimerRate;
if (DS.lpfnTimerHandler != NULL)
DS.lpfnTimerHandler();
}
DS.dwTimer = dwTimer;
return AUDIO_ERROR_NONE;
}
static UINT AIAPI UpdateAudioSynth(VOID)
{
return AUDIO_ERROR_NONE;
}
static UINT AIAPI SetAudioMixerValue(UINT nChannel, UINT nValue)
{
LONG nVolume;
if (nChannel != AUDIO_MIXER_MASTER_VOLUME &&
nChannel != AUDIO_MIXER_TREBLE &&
nChannel != AUDIO_MIXER_BASS &&
nChannel != AUDIO_MIXER_CHORUS &&
nChannel != AUDIO_MIXER_REVERB)
return AUDIO_ERROR_INVALPARAM;
if (nChannel == AUDIO_MIXER_MASTER_VOLUME && nValue <= 256) {
DS.aLogVolumeTable[0] = -10000;
for (nVolume = 1; nVolume <= AUDIO_MAX_VOLUME; nVolume++) {
LONG value = (nValue * nVolume) >> 6;
DS.aLogVolumeTable[nVolume] = (LONG) (value == 0 ? -10000.0 : -2000.0 * log(value / 256.0) / log(1.0/256.0));
}
}
return AUDIO_ERROR_NONE;
}
static UINT AIAPI OpenVoices(UINT nVoices)
{
if (nVoices <= AUDIO_MAX_VOICES) {
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALPARAM;
}
static UINT AIAPI CloseVoices(VOID)
{
UINT i;
for (i = 0; i < AUDIO_MAX_VOICES; i++) {
/* stop and release duplicated sound buffers */
if (DS.aSoundBuffer[i] != NULL) {
DS.aSoundBuffer[i]->lpVtbl->Stop(DS.aSoundBuffer[i]);
DS.aSoundBuffer[i]->lpVtbl->Release(DS.aSoundBuffer[i]);
}
}
/* clean up duplicated sound buffer array */
memset(DS.aSoundBuffer, 0, sizeof(DS.aSoundBuffer));
return AUDIO_ERROR_NONE;
}
static UINT AIAPI SetAudioCallback(LPFNAUDIOWAVE lpfnAudioWave)
{
if (lpfnAudioWave != NULL) {
}
return AUDIO_ERROR_NONE;
}
static UINT AIAPI SetAudioTimerProc(LPFNAUDIOTIMER lpfnAudioTimer)
{
if (lpfnAudioTimer != NULL) {
/* start up the timer settings */
if (DS.lpfnTimerHandler == NULL) {
DS.dwTimer = GetTickCount();
DS.dwTimerAccum = 0;
}
DS.lpfnTimerHandler = lpfnAudioTimer;
}
return AUDIO_ERROR_NONE;
}
static UINT AIAPI SetAudioTimerRate(UINT nBPM)
{
if (nBPM >= 0x20 && nBPM <= 0xFF) {
/* set timer rate in milliseconds */
DS.dwTimerRate = (5 * 1000L) / (2 * nBPM);
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALPARAM;
}
static LONG AIAPI GetAudioDataAvail(VOID)
{
return 0L;
}
static UINT AIAPI CreateAudioData(LPAUDIOWAVE lpWave)
{
LPDIRECTSOUNDBUFFER lpSoundBuffer;
DSBUFFERDESC dsbd;
DSBCAPS dsbc;
WAVEFORMATEX wfx;
if (lpWave != NULL) {
lpWave->dwHandle = 0;
/* setup waveform format */
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nChannels = 1;
wfx.wBitsPerSample = lpWave->wFormat & AUDIO_FORMAT_16BITS ? 16 : 8;
wfx.nSamplesPerSec = lpWave->nSampleRate;
wfx.nAvgBytesPerSec = lpWave->nSampleRate;
wfx.nBlockAlign = 1;
wfx.cbSize = 0;
if (lpWave->wFormat & AUDIO_FORMAT_16BITS) {
wfx.nAvgBytesPerSec <<= 1;
wfx.nBlockAlign <<= 1;
}
/* setup sound buffer description */
dsbd.dwSize = sizeof(dsbd);
dsbd.dwFlags = DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME |
DSBCAPS_CTRLFREQUENCY | DSBCAPS_STICKYFOCUS |
DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_LOCSOFTWARE;
dsbd.dwBufferBytes = lpWave->dwLength;
dsbd.dwReserved = 0;
dsbd.lpwfxFormat = &wfx;
/* create sound buffer object */
if (DS.lpDirectSound->lpVtbl->CreateSoundBuffer(DS.lpDirectSound,
&dsbd, &lpSoundBuffer, NULL) != DS_OK) {
MSGBOX("Can't create DirectSoundBuffer object");
return AUDIO_ERROR_NOMEMORY;
}
lpWave->dwHandle = (DWORD) lpSoundBuffer;
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALPARAM;
}
static UINT AIAPI DestroyAudioData(LPAUDIOWAVE lpWave)
{
LPDIRECTSOUNDBUFFER lpSoundBuffer;
if (lpWave != NULL && lpWave->dwHandle != 0) {
lpSoundBuffer = (LPDIRECTSOUNDBUFFER) lpWave->dwHandle;
lpSoundBuffer->lpVtbl->Stop(lpSoundBuffer);
lpSoundBuffer->lpVtbl->Release(lpSoundBuffer);
lpWave->dwHandle = 0;
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALPARAM;
}
static UINT AIAPI WriteAudioData(LPAUDIOWAVE lpWave, DWORD dwOffset, UINT nCount)
{
LPDIRECTSOUNDBUFFER lpSoundBuffer;
LPVOID lpPtr1, lpPtr2;
DWORD dwBytes1, dwBytes2;
UINT i;
if (lpWave != NULL && lpWave->dwHandle != 0 && lpWave->lpData != NULL) {
if (dwOffset + nCount <= lpWave->dwLength) {
lpSoundBuffer = (LPDIRECTSOUNDBUFFER) lpWave->dwHandle;
/* lock sound buffer in memory */
if (lpSoundBuffer->lpVtbl->Lock(lpSoundBuffer, dwOffset, nCount,
&lpPtr1, &dwBytes1, &lpPtr2, &dwBytes2, 0) == DS_OK) {
/* copy samples to the sound buffer (convert to unsigned) */
if (lpWave->wFormat & AUDIO_FORMAT_16BITS) {
memcpy(lpPtr1, lpWave->lpData + dwOffset, dwBytes1);
}
else {
for (i = 0; i < dwBytes1; i++)
((LPBYTE)lpPtr1)[i] = lpWave->lpData[dwOffset++] ^ 0x80;
}
/* unlock the sound buffer from memory */
lpSoundBuffer->lpVtbl->Unlock(lpSoundBuffer, lpPtr1,
dwBytes1, lpPtr2, dwBytes2);
return AUDIO_ERROR_NONE;
}
else {
MSGBOX("Can't lock DirectSoundBuffer memory");
lpSoundBuffer->lpVtbl->Restore(lpSoundBuffer);
}
}
return AUDIO_ERROR_INVALPARAM;
}
return AUDIO_ERROR_INVALHANDLE;
}
static UINT AIAPI PrimeVoice(UINT nVoice, LPAUDIOWAVE lpWave)
{
LPDIRECTSOUNDBUFFER lpSoundBuffer;
if (nVoice < AUDIO_MAX_VOICES && lpWave != NULL) {
lpSoundBuffer = (LPDIRECTSOUNDBUFFER) lpWave->dwHandle;
/* release the sound buffer for this voice */
if (DS.aSoundBuffer[nVoice] != NULL) {
DS.aSoundBuffer[nVoice]->lpVtbl->Stop(DS.aSoundBuffer[nVoice]);
DS.aSoundBuffer[nVoice]->lpVtbl->Release(DS.aSoundBuffer[nVoice]);
DS.aSoundBuffer[nVoice] = NULL;
}
/* create a duplicate sound buffer */
if (DS.lpDirectSound->lpVtbl->DuplicateSoundBuffer(DS.lpDirectSound,
lpSoundBuffer, &DS.aSoundBuffer[nVoice]) != DS_OK) {
MSGBOX("Can't duplicate DirectSoundBuffer object");
return AUDIO_ERROR_NOMEMORY;
}
/* setup frequency, volume and panning */
DS.aSoundBuffer[nVoice]->lpVtbl->SetCurrentPosition(DS.aSoundBuffer[nVoice], 0);
DS.aSoundBuffer[nVoice]->lpVtbl->SetFrequency(DS.aSoundBuffer[nVoice],
DS.aFrequencyTable[nVoice]);
DS.aSoundBuffer[nVoice]->lpVtbl->SetVolume(DS.aSoundBuffer[nVoice],
DS.aLogVolumeTable[DS.aVolumeTable[nVoice]]);
DS.aSoundBuffer[nVoice]->lpVtbl->SetPan(DS.aSoundBuffer[nVoice],
DS.aLogPanningTable[DS.aPanningTable[nVoice]]);
/* save format of the sound buffer */
DS.aFormatTable[nVoice] = lpWave->wFormat;
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALHANDLE;
}
static UINT AIAPI StartVoice(UINT nVoice)
{
DWORD dwFlags;
if (nVoice < AUDIO_MAX_VOICES) {
// FIXME: handle looping samples!
if (DS.aSoundBuffer[nVoice] != NULL) {
dwFlags = (DS.aFormatTable[nVoice] & AUDIO_FORMAT_LOOP ? DSBPLAY_LOOPING : 0);
if (DS.aSoundBuffer[nVoice]->lpVtbl->Play(DS.aSoundBuffer[nVoice],
0, 0, dwFlags) != DS_OK) {
MSGBOX("Can't play DirectSoundBuffer object");
return AUDIO_ERROR_INVALHANDLE;
}
}
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALHANDLE;
}
static UINT AIAPI StopVoice(UINT nVoice)
{
if (nVoice < AUDIO_MAX_VOICES) {
if (DS.aSoundBuffer[nVoice] != NULL) {
if (DS.aSoundBuffer[nVoice]->lpVtbl->Stop(DS.aSoundBuffer[nVoice]) != DS_OK) {
MSGBOX("Can't stop DirectSoundBuffer object");
return AUDIO_ERROR_INVALHANDLE;
}
}
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALHANDLE;
}
static UINT AIAPI SetVoicePosition(UINT nVoice, LONG dwPosition)
{
if (nVoice < AUDIO_MAX_VOICES) {
if (dwPosition >= AUDIO_MIN_POSITION &&
dwPosition <= AUDIO_MAX_POSITION) {
// FIXME: adjust position for 16-bit samples
if (DS.aSoundBuffer[nVoice] != NULL) {
DS.aSoundBuffer[nVoice]->lpVtbl->SetCurrentPosition(DS.aSoundBuffer[nVoice], dwPosition);
}
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALPARAM;
}
return AUDIO_ERROR_INVALHANDLE;
}
static UINT AIAPI SetVoiceFrequency(UINT nVoice, LONG dwFrequency)
{
if (nVoice < AUDIO_MAX_VOICES) {
if (dwFrequency >= AUDIO_MIN_FREQUENCY &&
dwFrequency <= AUDIO_MAX_FREQUENCY) {
DS.aFrequencyTable[nVoice] = dwFrequency;
if (DS.aSoundBuffer[nVoice] != NULL) {
if (DS.aSoundBuffer[nVoice]->lpVtbl->SetFrequency(DS.aSoundBuffer[nVoice], dwFrequency) != DS_OK)
MSGBOX("Can't change DirectSoundBuffer frequency");
}
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALPARAM;
}
return AUDIO_ERROR_INVALHANDLE;
}
static UINT AIAPI SetVoiceVolume(UINT nVoice, UINT nVolume)
{
if (nVoice < AUDIO_MAX_VOICES) {
if (nVolume < AUDIO_MAX_VOLUME) {
DS.aVolumeTable[nVoice] = nVolume;
if (DS.aSoundBuffer[nVoice] != NULL) {
if (DS.aSoundBuffer[nVoice]->lpVtbl->SetVolume(DS.aSoundBuffer[nVoice], DS.aLogVolumeTable[nVolume]) != DS_OK)
MSGBOX("Can't change DirectSoundBuffer volume");
}
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALPARAM;
}
return AUDIO_ERROR_INVALHANDLE;
}
static UINT AIAPI SetVoicePanning(UINT nVoice, UINT nPanning)
{
if (nVoice < AUDIO_MAX_VOICES) {
if (nPanning < AUDIO_MAX_PANNING) {
DS.aPanningTable[nVoice] = nPanning;
if (DS.aSoundBuffer[nVoice] != NULL) {
if (DS.aSoundBuffer[nVoice]->lpVtbl->SetPan(DS.aSoundBuffer[nVoice], DS.aLogPanningTable[nPanning]) != DS_OK)
MSGBOX("Can't change DirectSoundBuffer panning");
}
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALPARAM;
}
return AUDIO_ERROR_INVALHANDLE;
}
static UINT AIAPI GetVoicePosition(UINT nVoice, LPLONG lpdwPosition)
{
DWORD dwWritePosition;
if (nVoice < AUDIO_MAX_VOICES) {
if (lpdwPosition != NULL) {
*lpdwPosition = 0L;
if (DS.aSoundBuffer[nVoice] != NULL) {
if (DS.aSoundBuffer[nVoice]->lpVtbl->GetCurrentPosition(
DS.aSoundBuffer[nVoice], lpdwPosition, &dwWritePosition) != DS_OK)
*lpdwPosition = 0L;
}
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALPARAM;
}
return AUDIO_ERROR_INVALHANDLE;
}
static UINT AIAPI GetVoiceFrequency(UINT nVoice, LPLONG lpdwFrequency)
{
if (nVoice < AUDIO_MAX_VOICES) {
if (lpdwFrequency != NULL) {
*lpdwFrequency = DS.aFrequencyTable[nVoice];
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALPARAM;
}
return AUDIO_ERROR_INVALHANDLE;
}
static UINT AIAPI GetVoiceVolume(UINT nVoice, LPUINT lpnVolume)
{
if (nVoice < AUDIO_MAX_VOICES) {
if (lpnVolume != NULL) {
*lpnVolume = DS.aVolumeTable[nVoice];
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALPARAM;
}
return AUDIO_ERROR_INVALHANDLE;
}
static UINT AIAPI GetVoicePanning(UINT nVoice, LPUINT lpnPanning)
{
if (nVoice < AUDIO_MAX_VOICES) {
if (lpnPanning != NULL) {
*lpnPanning = DS.aPanningTable[nVoice];
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALPARAM;
}
return AUDIO_ERROR_INVALHANDLE;
}
static UINT AIAPI GetVoiceStatus(UINT nVoice, LPBOOL lpnStatus)
{
if (nVoice < AUDIO_MAX_VOICES) {
if (lpnStatus != NULL) {
*lpnStatus = 1;
if (DS.aSoundBuffer[nVoice] != NULL) {
if (DS.aSoundBuffer[nVoice]->lpVtbl->GetStatus(DS.aSoundBuffer[nVoice], lpnStatus) != DS_OK)
MSGBOX("Can't getDirectSoundBuffer status");;
*lpnStatus = (*lpnStatus & DSBSTATUS_PLAYING ? 0 : 1);
}
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALPARAM;
}
return AUDIO_ERROR_INVALHANDLE;
}
/*
* DirectSound audio driver public interface
*/
static AUDIOWAVEDRIVER DirectSoundWaveDriver =
{
GetAudioCaps, PingAudio, OpenAudio, CloseAudio,
UpdateAudio, SetAudioCallback
};
static AUDIOSYNTHDRIVER DirectSoundSynthDriver =
{
GetAudioCaps, PingAudio, OpenAudio, CloseAudio,
UpdateAudioSynth, OpenVoices, CloseVoices,
SetAudioTimerProc, SetAudioTimerRate, SetAudioMixerValue,
GetAudioDataAvail, CreateAudioData, DestroyAudioData,
WriteAudioData, PrimeVoice, StartVoice, StopVoice,
SetVoicePosition, SetVoiceFrequency, SetVoiceVolume,
SetVoicePanning, GetVoicePosition, GetVoiceFrequency,
GetVoiceVolume, GetVoicePanning, GetVoiceStatus
};
AUDIODRIVER DirectSoundAccelDriver =
{
&DirectSoundWaveDriver, &DirectSoundSynthDriver
};

1818
seal-hack/src/gusdrv.c Normal file

File diff suppressed because it is too large Load Diff

110
seal-hack/src/iofile.c Normal file
View File

@@ -0,0 +1,110 @@
/*
* $Id: iofile.c 1.5 1996/08/05 18:51:19 chasan released $
*
* Input/Output file stream routines.
*
* Copyright (c) 1995-1999 Carlos Hasan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include "audio.h"
#include "iofile.h"
/*
* Audio I/O file stream routines
*/
static FILE *lpStream;
UINT AIAPI AIOOpenFile(LPSTR lpszFileName)
{
if ((lpStream = fopen(lpszFileName, "rb")) != NULL)
return AUDIO_ERROR_NONE;
return AUDIO_ERROR_FILENOTFOUND;
}
UINT AIAPI AIOCloseFile(VOID)
{
fclose(lpStream);
return AUDIO_ERROR_NONE;
}
UINT AIAPI AIOSeekFile(LONG dwOffset, UINT nWhere)
{
fseek(lpStream, dwOffset, nWhere);
return AUDIO_ERROR_NONE;
}
UINT AIAPI AIOReadFile(LPVOID lpData, UINT nSize)
{
if (fread(lpData, 1, nSize, lpStream) != nSize)
memset(lpData, 0, nSize);
return AUDIO_ERROR_NONE;
}
/* little-endian input routines */
UINT AIAPI AIOReadChar(LPBYTE lpData)
{
if (fread(lpData, 1, sizeof(BYTE), lpStream) != sizeof(BYTE))
memset(lpData, 0, sizeof(BYTE));
return AUDIO_ERROR_NONE;
}
UINT AIAPI AIOReadShort(LPWORD lpData)
{
if (fread(lpData, 1, sizeof(WORD), lpStream) != sizeof(WORD))
memset(lpData, 0, sizeof(WORD));
#ifdef __BIGENDIAN__
*lpData = MAKEWORD(HIBYTE(*lpData), LOBYTE(*lpData));
#endif
return AUDIO_ERROR_NONE;
}
UINT AIAPI AIOReadLong(LPDWORD lpData)
{
if (fread(lpData, 1, sizeof(DWORD), lpStream) != sizeof(DWORD))
memset(lpData, 0, sizeof(DWORD));
#ifdef __BIGENDIAN__
*lpData = MAKELONG(
MAKEWORD(HIBYTE(HIWORD(*lpData)), LOBYTE(HIWORD(*lpData))),
MAKEWORD(HIBYTE(LOWORD(*lpData)), LOBYTE(LOWORD(*lpData))));
#endif
return AUDIO_ERROR_NONE;
}
/* big-endian input routines */
UINT AIAPI AIOReadCharM(LPBYTE lpData)
{
if (fread(lpData, 1, sizeof(BYTE), lpStream) != sizeof(BYTE))
memset(lpData, 0, sizeof(BYTE));
return AUDIO_ERROR_NONE;
}
UINT AIAPI AIOReadShortM(LPWORD lpData)
{
if (fread(lpData, 1, sizeof(WORD), lpStream) != sizeof(WORD))
memset(lpData, 0, sizeof(WORD));
#ifndef __BIGENDIAN__
*lpData = MAKEWORD(HIBYTE(*lpData), LOBYTE(*lpData));
#endif
return AUDIO_ERROR_NONE;
}
UINT AIAPI AIOReadLongM(LPDWORD lpData)
{
if (fread(lpData, 1, sizeof(DWORD), lpStream) != sizeof(DWORD))
memset(lpData, 0, sizeof(DWORD));
#ifndef __BIGENDIAN__
*lpData = MAKELONG(
MAKEWORD(HIBYTE(HIWORD(*lpData)), LOBYTE(HIWORD(*lpData))),
MAKEWORD(HIBYTE(LOWORD(*lpData)), LOBYTE(LOWORD(*lpData))));
#endif
return AUDIO_ERROR_NONE;
}

43
seal-hack/src/iofile.h Normal file
View File

@@ -0,0 +1,43 @@
/*
* $Id: iofile.h 1.6 1996/09/13 16:30:26 chasan released $
*
* Input/Output file stream routines.
*
* Copyright (C) 1995-1999 Carlos Hasan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef __IOFILE_H
#define __IOFILE_H
#ifdef __GNUC__
#include <unistd.h>
#include <memory.h>
#else
#include <stdio.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
UINT AIAPI AIOOpenFile(LPSTR lpszFileName);
UINT AIAPI AIOCloseFile(VOID);
UINT AIAPI AIOSeekFile(LONG dwOffset, UINT nWhere);
UINT AIAPI AIOReadFile(LPVOID lpData, UINT nSize);
UINT AIAPI AIOReadChar(LPBYTE lpData);
UINT AIAPI AIOReadShort(LPWORD lpData);
UINT AIAPI AIOReadLong(LPDWORD lpData);
UINT AIAPI AIOReadCharM(LPBYTE lpData);
UINT AIAPI AIOReadShortM(LPWORD lpData);
UINT AIAPI AIOReadLongM(LPDWORD lpData);
#ifdef __cplusplus
};
#endif
#endif

144
seal-hack/src/lnxdrv.c Normal file
View File

@@ -0,0 +1,144 @@
/*
* $Id: lnxdrv.c 1.5 1996/08/05 18:51:19 chasan released $
*
* Linux's Voxware audio driver.
*
* Copyright (C) 1995-1999 Carlos Hasan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#ifdef __LINUX__
#include <linux/soundcard.h>
#endif
#ifdef __FREEBSD__
#include <machine/soundcard.h>
#endif
#include "audio.h"
#include "drivers.h"
/*
* Linux driver buffer fragments defines
*/
#define NUMFRAGS 16
#define FRAGSIZE 12
#define BUFFERSIZE (1 << FRAGSIZE)
/*
* Linux driver configuration structure
*/
static struct {
int nHandle;
BYTE aBuffer[BUFFERSIZE];
LPFNAUDIOWAVE lpfnAudioWave;
WORD wFormat;
} Audio;
/*
* Linux driver API interface
*/
static UINT AIAPI GetAudioCaps(LPAUDIOCAPS lpCaps)
{
static AUDIOCAPS Caps =
{
AUDIO_PRODUCT_LINUX, "Linux Voxware",
AUDIO_FORMAT_1M08 | AUDIO_FORMAT_1S08 |
AUDIO_FORMAT_1M16 | AUDIO_FORMAT_1S16 |
AUDIO_FORMAT_2M08 | AUDIO_FORMAT_2S08 |
AUDIO_FORMAT_2M16 | AUDIO_FORMAT_2S16 |
AUDIO_FORMAT_4M08 | AUDIO_FORMAT_4S08 |
AUDIO_FORMAT_4M16 | AUDIO_FORMAT_4S16
};
memcpy(lpCaps, &Caps, sizeof(AUDIOCAPS));
return AUDIO_ERROR_NONE;
}
static UINT AIAPI PingAudio(VOID)
{
return access("/dev/dsp", W_OK) ? AUDIO_ERROR_NODEVICE : AUDIO_ERROR_NONE;
}
static UINT AIAPI OpenAudio(LPAUDIOINFO lpInfo)
{
int nBitsPerSample, nStereoOn, nSampleRate, nFrags;
memset(&Audio, 0, sizeof(Audio));
/* try to open DSP audio device for playback */
if ((Audio.nHandle = open("/dev/dsp", O_WRONLY | O_NDELAY)) < 0)
return AUDIO_ERROR_DEVICEBUSY;
/* setup number and size of buffer fragments */
nFrags = (NUMFRAGS << 16) + (FRAGSIZE);
ioctl(Audio.nHandle, SNDCTL_DSP_SETFRAGMENT, &nFrags);
/* setup audio playback encoding format and sampling frequency */
nBitsPerSample = lpInfo->wFormat & AUDIO_FORMAT_16BITS ? 16 : 8;
nStereoOn = lpInfo->wFormat & AUDIO_FORMAT_STEREO ? 1 : 0;
nSampleRate = lpInfo->nSampleRate;
if (ioctl(Audio.nHandle, SNDCTL_DSP_SAMPLESIZE, &nBitsPerSample) < 0 ||
ioctl(Audio.nHandle, SNDCTL_DSP_STEREO, &nStereoOn) < 0 ||
ioctl(Audio.nHandle, SNDCTL_DSP_SPEED, &nSampleRate) < 0) {
close(Audio.nHandle);
return AUDIO_ERROR_BADFORMAT;
}
Audio.wFormat = lpInfo->wFormat;
return AUDIO_ERROR_NONE;
}
static UINT AIAPI CloseAudio(VOID)
{
/* close DSP audio device */
close(Audio.nHandle);
return AUDIO_ERROR_NONE;
}
static UINT AIAPI UpdateAudio(UINT nFrames)
{
/* compute frame size */
if (Audio.wFormat & AUDIO_FORMAT_16BITS) nFrames <<= 1;
if (Audio.wFormat & AUDIO_FORMAT_STEREO) nFrames <<= 1;
if (nFrames <= 0 || nFrames > sizeof(Audio.aBuffer))
nFrames = sizeof(Audio.aBuffer);
/* send PCM samples to the DSP audio device */
if (Audio.lpfnAudioWave != NULL) {
Audio.lpfnAudioWave(Audio.aBuffer, nFrames);
write(Audio.nHandle, Audio.aBuffer, nFrames);
}
return AUDIO_ERROR_NONE;
}
static UINT AIAPI SetAudioCallback(LPFNAUDIOWAVE lpfnAudioWave)
{
/* set up DSP audio device user's callback function */
Audio.lpfnAudioWave = lpfnAudioWave;
return AUDIO_ERROR_NONE;
}
/*
* Linux driver public interface
*/
AUDIOWAVEDRIVER LinuxWaveDriver =
{
GetAudioCaps, PingAudio, OpenAudio, CloseAudio,
UpdateAudio, SetAudioCallback
};
AUDIODRIVER LinuxDriver =
{
&LinuxWaveDriver, NULL
};

906
seal-hack/src/mixdrv.c Normal file
View File

@@ -0,0 +1,906 @@
/*
* $Id: mixdrv.c 1.13 1996/09/08 21:14:54 chasan released $
* 1.14 1998/10/24 18:20:53 chasan released (Mixer API)
*
* Software-based waveform synthesizer emulator driver.
*
* Copyright (C) 1995-1999 Carlos Hasan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#define __FILTER__
#ifdef __GNUC__
#include <memory.h>
#define cdecl
#endif
#include <string.h>
#include <stdlib.h>
#include "audio.h"
#include "drivers.h"
/*
* Voice control bit fields
*/
#define VOICE_STOP 0x01
#define VOICE_16BITS 0x02
#define VOICE_LOOP 0x04
#define VOICE_BIDILOOP 0x08
#define VOICE_REVERSE 0x10
/*
* Voice pitch accurary and mixing buffer size
*/
#define ACCURACY 12
#define BUFFERSIZE 512
/*
* Waveform synthesizer voice structure
*/
typedef struct {
LPVOID lpData;
LONG dwAccum;
LONG dwFrequency;
LONG dwLoopStart;
LONG dwLoopEnd;
BYTE nVolume;
BYTE nPanning;
BYTE bControl;
BYTE bReserved;
} VOICE, *LPVOICE;
/*
* Low level voice mixing routine prototype
*/
typedef VOID (cdecl* LPFNMIXAUDIO)(LPLONG, UINT, LPVOICE);
/*
* Waveform synthesizer state structure
*/
static struct {
VOICE aVoices[AUDIO_MAX_VOICES];
UINT nVoices;
UINT wFormat;
UINT nSampleRate;
LONG dwTimerRate;
LONG dwTimerAccum;
LPBYTE lpMemory;
LPFNAUDIOTIMER lpfnAudioTimer;
LPFNMIXAUDIO lpfnMixAudioProc[2];
} Synth;
LPLONG lpVolumeTable;
LPBYTE lpFilterTable;
static VOID AIAPI UpdateVoices(LPBYTE lpData, UINT nCount);
/* low level resamplation and quantization routines */
#ifdef __ASM__
VOID cdecl QuantAudioData08(LPVOID lpBuffer, LPLONG lpData, UINT nCount);
VOID cdecl QuantAudioData16(LPVOID lpBuffer, LPLONG lpData, UINT nCount);
VOID cdecl MixAudioData08M(LPLONG lpBuffer, UINT nCount, LPVOICE lpVoice);
VOID cdecl MixAudioData08S(LPLONG lpBuffer, UINT nCount, LPVOICE lpVoice);
VOID cdecl MixAudioData08MI(LPLONG lpBuffer, UINT nCount, LPVOICE lpVoice);
VOID cdecl MixAudioData08SI(LPLONG lpBuffer, UINT nCount, LPVOICE lpVoice);
VOID cdecl MixAudioData16M(LPLONG lpBuffer, UINT nCount, LPVOICE lpVoice);
VOID cdecl MixAudioData16S(LPLONG lpBuffer, UINT nCount, LPVOICE lpVoice);
VOID cdecl MixAudioData16MI(LPLONG lpBuffer, UINT nCount, LPVOICE lpVoice);
VOID cdecl MixAudioData16SI(LPLONG lpBuffer, UINT nCount, LPVOICE lpVoice);
static VOID QuantAudioData(LPVOID lpBuffer, LPLONG lpData, UINT nCount)
{
if (Synth.wFormat & AUDIO_FORMAT_16BITS)
QuantAudioData16(lpBuffer, lpData, nCount);
else
QuantAudioData08(lpBuffer, lpData, nCount);
}
#else
typedef short SHORT;
typedef SHORT* LPSHORT;
static VOID QuantAudioData(LPVOID lpBuffer, LPLONG lpData, UINT nCount)
{
LPSHORT lpwBuffer;
LPBYTE lpbBuffer;
LONG dwSample;
if (Synth.wFormat & AUDIO_FORMAT_16BITS) {
lpwBuffer = (LPSHORT) lpBuffer;
while (nCount-- > 0) {
dwSample = *lpData++;
if (dwSample < -32768)
dwSample = -32768;
else if (dwSample > +32767)
dwSample = +32767;
*lpwBuffer++ = (SHORT) dwSample;
}
}
else {
lpbBuffer = (LPBYTE) lpBuffer;
while (nCount-- > 0) {
dwSample = *lpData++;
if (dwSample < -32768)
dwSample = -32768;
else if (dwSample > +32767)
dwSample = +32767;
*lpbBuffer++ = (BYTE) ((dwSample >> 8) + 128);
}
}
}
static VOID AIAPI
MixAudioData08M(LPLONG lpBuffer, UINT nCount, LPVOICE lpVoice)
{
register UINT count;
register DWORD accum, delta;
register LPLONG table, buf;
register LPBYTE data;
accum = lpVoice->dwAccum;
delta = lpVoice->dwFrequency;
table = lpVolumeTable + ((UINT) lpVoice->nVolume << 8);
data = lpVoice->lpData;
buf = lpBuffer;
count = nCount;
do {
*buf++ += table[data[accum >> ACCURACY]];
accum += delta;
} while (--count != 0);
lpVoice->dwAccum = accum;
}
#define min(a, b) ((a) < (b) ? (a) : (b))
static VOID AIAPI
MixAudioData08S(LPLONG lpBuffer, UINT nCount, LPVOICE lpVoice)
{
register UINT a;
register DWORD accum, delta;
register LPLONG ltable, rtable, buf;
register LPBYTE data;
accum = lpVoice->dwAccum;
delta = lpVoice->dwFrequency;
a = ((UINT) lpVoice->nVolume * lpVoice->nPanning) >> 8;
rtable = lpVolumeTable + (a << 8);
ltable = lpVolumeTable + ((lpVoice->nVolume - a) << 8);
data = lpVoice->lpData;
buf = lpBuffer;
do {
a = data[accum >> ACCURACY];
buf[0] += ltable[a];
buf[1] += rtable[a];
accum += delta;
buf += 2;
} while (--nCount != 0);
lpVoice->dwAccum = accum;
}
static VOID AIAPI
MixAudioData08MI(LPLONG lpBuffer, UINT nCount, LPVOICE lpVoice)
{
register INT a, frac;
register DWORD accum, delta;
register LPLONG table, buf;
register LPBYTE data, ftable;
/* adaptive oversampling interpolation comparison */
if (lpVoice->dwFrequency < -(1 << ACCURACY) ||
lpVoice->dwFrequency > +(1 << ACCURACY)) {
MixAudioData08M(lpBuffer, nCount, lpVoice);
return;
}
accum = lpVoice->dwAccum;
delta = lpVoice->dwFrequency;
table = lpVolumeTable + ((UINT) lpVoice->nVolume << 8);
data = lpVoice->lpData;
buf = lpBuffer;
#ifdef __FILTER__
a = (BYTE) lpVoice->bReserved;
frac = ((long) delta < 0 ? -delta : +delta) >> (ACCURACY - 5);
ftable = lpFilterTable + (frac << 8);
do {
a = (BYTE)(a + ftable[data[accum >> ACCURACY]] - ftable[a]);
*buf++ += table[a];
accum += delta;
} while (--nCount != 0);
lpVoice->bReserved = (BYTE) a;
#else
do {
register INT b;
a = (signed char) data[accum >> ACCURACY];
b = (signed char) data[(accum >> ACCURACY) + 1];
frac = (accum & ((1 << ACCURACY) - 1)) >> (ACCURACY - 5);
a = (BYTE)(a + ((frac * (b - a)) >> 5));
*buf++ += table[a];
accum += delta;
} while (--nCount != 0);
#endif
lpVoice->dwAccum = accum;
}
static VOID AIAPI
MixAudioData08SI(LPLONG lpBuffer, UINT nCount, LPVOICE lpVoice)
{
register INT a, frac;
register DWORD accum, delta;
register LPLONG buf, ltable, rtable;
register LPBYTE data, ftable;
/* adaptive oversampling interpolation comparison */
if (lpVoice->dwFrequency < -(1 << ACCURACY) ||
lpVoice->dwFrequency > +(1 << ACCURACY)) {
MixAudioData08S(lpBuffer, nCount, lpVoice);
return;
}
accum = lpVoice->dwAccum;
delta = lpVoice->dwFrequency;
a = ((UINT) lpVoice->nVolume * lpVoice->nPanning) >> 8;
rtable = lpVolumeTable + (a << 8);
ltable = lpVolumeTable + ((lpVoice->nVolume - a) << 8);
data = lpVoice->lpData;
buf = lpBuffer;
#ifdef __FILTER__
a = (BYTE) lpVoice->bReserved;
frac = ((long) delta < 0 ? -delta : +delta) >> (ACCURACY - 5);
ftable = lpFilterTable + (frac << 8);
do {
a = (BYTE)(a + ftable[data[accum >> ACCURACY]] - ftable[a]);
buf[0] += ltable[a];
buf[1] += rtable[a];
accum += delta;
buf += 2;
} while (--nCount != 0);
lpVoice->bReserved = (BYTE) a;
#else
do {
register INT b;
a = (signed char) data[accum >> ACCURACY];
b = (signed char) data[(accum >> ACCURACY) + 1];
frac = (accum & ((1 << ACCURACY) - 1)) >> (ACCURACY - 5);
a = (BYTE)(a + ((frac * (b - a)) >> 5));
buf[0] += ltable[a];
buf[1] += rtable[a];
accum += delta;
buf += 2;
} while (--nCount != 0);
#endif
lpVoice->dwAccum = accum;
}
static VOID AIAPI
MixAudioData16M(LPLONG lpBuffer, UINT nCount, LPVOICE lpVoice)
{
register UINT a, count;
register DWORD accum, delta;
register LPLONG table, buf;
register LPWORD data;
accum = lpVoice->dwAccum;
delta = lpVoice->dwFrequency;
table = lpVolumeTable + ((UINT) lpVoice->nVolume << 8);
data = lpVoice->lpData;
buf = lpBuffer;
count = nCount;
do {
a = data[accum >> ACCURACY];
*buf++ += table[a >> 8];
accum += delta;
} while (--count != 0);
lpVoice->dwAccum = accum;
}
static VOID AIAPI
MixAudioData16S(LPLONG lpBuffer, UINT nCount, LPVOICE lpVoice)
{
register UINT a;
register DWORD accum, delta;
register LPLONG ltable, rtable, buf;
register LPWORD data;
accum = lpVoice->dwAccum;
delta = lpVoice->dwFrequency;
a = ((UINT) lpVoice->nVolume * lpVoice->nPanning) >> 8;
rtable = lpVolumeTable + (a << 8);
ltable = lpVolumeTable + ((lpVoice->nVolume - a) << 8);
data = lpVoice->lpData;
buf = lpBuffer;
do {
a = data[accum >> ACCURACY];
buf[0] += ltable[a >> 8];
buf[1] += rtable[a >> 8];
accum += delta;
buf += 2;
} while (--nCount != 0);
lpVoice->dwAccum = accum;
}
static VOID AIAPI
MixAudioData16MI(LPLONG lpBuffer, UINT nCount, LPVOICE lpVoice)
{
register UINT frac, count;
register DWORD a, b, accum, delta;
register LPLONG table, buf;
register LPWORD data;
/* adaptive oversampling interpolation comparison */
if (lpVoice->dwFrequency < -(1 << ACCURACY) ||
lpVoice->dwFrequency > +(1 << ACCURACY)) {
MixAudioData16M(lpBuffer, nCount, lpVoice);
return;
}
accum = lpVoice->dwAccum;
delta = lpVoice->dwFrequency;
table = lpVolumeTable + ((UINT) lpVoice->nVolume << 8);
data = lpVoice->lpData;
buf = lpBuffer;
count = nCount;
do {
a = data[accum >> ACCURACY];
b = data[(accum >> ACCURACY) + 1];
frac = (accum & ((1 << ACCURACY) - 1)) >> (ACCURACY - 5);
a = (WORD)((SHORT)a + ((frac * ((SHORT)b - (SHORT)a)) >> 5));
*buf++ += table[a >> 8];
accum += delta;
} while (--count != 0);
lpVoice->dwAccum = accum;
}
static VOID AIAPI
MixAudioData16SI(LPLONG lpBuffer, UINT nCount, LPVOICE lpVoice)
{
register UINT frac;
register DWORD a, b, accum, delta;
register LPLONG ltable, rtable, buf;
register LPWORD data;
/* adaptive oversampling interpolation comparison */
if (lpVoice->dwFrequency < -(1 << ACCURACY) ||
lpVoice->dwFrequency > +(1 << ACCURACY)) {
MixAudioData16S(lpBuffer, nCount, lpVoice);
return;
}
accum = lpVoice->dwAccum;
delta = lpVoice->dwFrequency;
a = ((UINT) lpVoice->nVolume * lpVoice->nPanning) >> 8;
rtable = lpVolumeTable + (a << 8);
ltable = lpVolumeTable + ((lpVoice->nVolume - a) << 8);
data = lpVoice->lpData;
buf = lpBuffer;
do {
a = data[accum >> ACCURACY];
b = data[(accum >> ACCURACY) + 1];
frac = (accum & ((1 << ACCURACY) - 1)) >> (ACCURACY - 5);
a = (WORD)((SHORT)a + ((frac * ((int)(SHORT)b - (int)(SHORT)a)) >> 5));
buf[0] += ltable[a >> 8];
buf[1] += rtable[a >> 8];
accum += delta;
buf += 2;
} while (--nCount != 0);
lpVoice->dwAccum = accum;
}
#endif
static VOID MixAudioData(LPLONG lpBuffer, UINT nCount, LPVOICE lpVoice)
{
UINT nSize;
if (Synth.wFormat & AUDIO_FORMAT_STEREO)
nCount >>= 1;
while (nCount > 0 && !(lpVoice->bControl & VOICE_STOP)) {
/* check boundary conditions */
if (lpVoice->bControl & VOICE_REVERSE) {
if (lpVoice->dwAccum < lpVoice->dwLoopStart) {
if (lpVoice->bControl & VOICE_BIDILOOP) {
lpVoice->dwAccum = lpVoice->dwLoopStart +
(lpVoice->dwLoopStart - lpVoice->dwAccum);
lpVoice->bControl ^= VOICE_REVERSE;
continue;
}
else if (lpVoice->bControl & VOICE_LOOP) {
lpVoice->dwAccum = lpVoice->dwLoopEnd -
(lpVoice->dwLoopStart - lpVoice->dwAccum);
continue;
}
else {
lpVoice->bControl |= VOICE_STOP;
break;
}
}
}
else {
if (lpVoice->dwAccum > lpVoice->dwLoopEnd) {
if (lpVoice->bControl & VOICE_BIDILOOP) {
lpVoice->dwAccum = lpVoice->dwLoopEnd -
(lpVoice->dwAccum - lpVoice->dwLoopEnd);
lpVoice->bControl ^= VOICE_REVERSE;
continue;
}
else if (lpVoice->bControl & VOICE_LOOP) {
lpVoice->dwAccum = lpVoice->dwLoopStart +
(lpVoice->dwAccum - lpVoice->dwLoopEnd);
continue;
}
else {
lpVoice->bControl |= VOICE_STOP;
break;
}
}
}
/* check for overflow and clip if necessary */
nSize = nCount;
if (lpVoice->bControl & VOICE_REVERSE) {
if (nSize * lpVoice->dwFrequency >
lpVoice->dwAccum - lpVoice->dwLoopStart)
nSize = (lpVoice->dwAccum - lpVoice->dwLoopStart +
lpVoice->dwFrequency) / lpVoice->dwFrequency;
}
else {
if (nSize * lpVoice->dwFrequency >
lpVoice->dwLoopEnd - lpVoice->dwAccum)
nSize = (lpVoice->dwLoopEnd - lpVoice->dwAccum +
lpVoice->dwFrequency) / lpVoice->dwFrequency;
}
if (lpVoice->bControl & VOICE_REVERSE)
lpVoice->dwFrequency = -lpVoice->dwFrequency;
/* mixes chunk of data in a burst mode */
if (lpVoice->bControl & VOICE_16BITS) {
Synth.lpfnMixAudioProc[1] (lpBuffer, nSize, lpVoice);
}
else {
Synth.lpfnMixAudioProc[0] (lpBuffer, nSize, lpVoice);
}
if (lpVoice->bControl & VOICE_REVERSE)
lpVoice->dwFrequency = -lpVoice->dwFrequency;
/* update mixing buffer address and counter */
lpBuffer += nSize;
if (Synth.wFormat & AUDIO_FORMAT_STEREO)
lpBuffer += nSize;
nCount -= nSize;
}
}
static VOID MixAudioVoices(LPLONG lpBuffer, UINT nCount)
{
UINT nVoice, nSize;
while (nCount > 0) {
nSize = nCount;
if (Synth.lpfnAudioTimer != NULL) {
nSize = (Synth.dwTimerRate - Synth.dwTimerAccum + 64L) & ~63L;
if (nSize > nCount)
nSize = nCount;
if ((Synth.dwTimerAccum += nSize) >= Synth.dwTimerRate) {
Synth.dwTimerAccum -= Synth.dwTimerRate;
Synth.lpfnAudioTimer();
}
}
for (nVoice = 0; nVoice < Synth.nVoices; nVoice++) {
MixAudioData(lpBuffer, nSize, &Synth.aVoices[nVoice]);
}
lpBuffer += nSize;
nCount -= nSize;
}
}
/*
* High level waveform synthesizer interface
*/
static UINT AIAPI GetAudioCaps(LPAUDIOCAPS lpCaps)
{
memset(lpCaps, 0, sizeof(AUDIOCAPS));
return AUDIO_ERROR_NOTSUPPORTED;
}
static UINT AIAPI PingAudio(VOID)
{
return AUDIO_ERROR_NOTSUPPORTED;
}
static UINT AIAPI OpenAudio(LPAUDIOINFO lpInfo)
{
memset(&Synth, 0, sizeof(Synth));
Synth.wFormat = lpInfo->wFormat;
Synth.nSampleRate = lpInfo->nSampleRate;
if (Synth.wFormat & AUDIO_FORMAT_FILTER) {
Synth.lpfnMixAudioProc[0] = (Synth.wFormat & AUDIO_FORMAT_STEREO) ?
MixAudioData08SI : MixAudioData08MI;
Synth.lpfnMixAudioProc[1] = (Synth.wFormat & AUDIO_FORMAT_STEREO) ?
MixAudioData16SI : MixAudioData16MI;
}
else {
Synth.lpfnMixAudioProc[0] = (Synth.wFormat & AUDIO_FORMAT_STEREO) ?
MixAudioData08S : MixAudioData08M;
Synth.lpfnMixAudioProc[1] = (Synth.wFormat & AUDIO_FORMAT_STEREO) ?
MixAudioData16S : MixAudioData16M;
}
/* allocate volume (0-64) and filter (0-31) table */
Synth.lpMemory = malloc(sizeof(LONG) * 65 * 256 +
sizeof(BYTE) * 32 * 256 + 1023);
if (Synth.lpMemory != NULL) {
lpVolumeTable = (LPLONG) (((DWORD) Synth.lpMemory + 1023) & ~1023);
lpFilterTable = (LPBYTE) (lpVolumeTable + 65 * 256);
ASetAudioMixerValue(AUDIO_MIXER_MASTER_VOLUME, 96);
ASetAudioCallback(UpdateVoices);
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_NOMEMORY;
}
static UINT AIAPI CloseAudio(VOID)
{
if (Synth.lpMemory != NULL)
free(Synth.lpMemory);
memset(&Synth, 0, sizeof(Synth));
return AUDIO_ERROR_NONE;
}
static UINT AIAPI SetAudioMixerValue(UINT nChannel, UINT nMixerValue)
{
LPBYTE lpFilter;
LPLONG lpVolume;
UINT nVolume, nSample;
LONG dwAccum, dwDelta;
if (Synth.lpMemory == NULL)
return AUDIO_ERROR_NOTSUPPORTED;
/* master volume must be less than 256 units */
if (nChannel != AUDIO_MIXER_MASTER_VOLUME || nMixerValue > 256)
return AUDIO_ERROR_INVALPARAM;
/* half dynamic range for mono output */
if (!(Synth.wFormat & AUDIO_FORMAT_STEREO))
nMixerValue >>= 1;
/* build volume table (0-64) */
lpVolume = lpVolumeTable;
dwDelta = 0;
for (nVolume = 0; nVolume <= 64; nVolume++, dwDelta += nMixerValue) {
dwAccum = 0;
for (nSample = 0; nSample < 128; nSample++, dwAccum += dwDelta)
*lpVolume++ = dwAccum >> 4;
dwAccum = -dwAccum;
for (nSample = 0; nSample < 128; nSample++, dwAccum += dwDelta)
*lpVolume++ = dwAccum >> 4;
}
#ifdef __FILTER__
/* build lowpass filter table (0-31) */
lpFilter = lpFilterTable;
for (nVolume = 0; nVolume < 32; nVolume++) {
dwAccum = 0;
for (nSample = 0; nSample < 128; nSample++, dwAccum += nVolume)
*lpFilter++ = dwAccum >> 5;
dwAccum = -dwAccum;
for (nSample = 0; nSample < 128; nSample++, dwAccum += nVolume)
*lpFilter++ = dwAccum >> 5;
}
#endif
return AUDIO_ERROR_NONE;
}
static UINT AIAPI OpenVoices(UINT nVoices)
{
UINT nVoice;
/*
* Initialize waveform synthesizer structure for playback
*/
if (nVoices >= 1 && nVoices <= AUDIO_MAX_VOICES) {
Synth.nVoices = nVoices;
for (nVoice = 0; nVoice < Synth.nVoices; nVoice++)
Synth.aVoices[nVoice].bControl = VOICE_STOP;
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALPARAM;
}
static UINT AIAPI CloseVoices(VOID)
{
UINT nVoice;
memset(Synth.aVoices, 0, sizeof(Synth.aVoices));
for (nVoice = 0; nVoice < AUDIO_MAX_VOICES; nVoice++)
Synth.aVoices[nVoice].bControl = VOICE_STOP;
return AUDIO_ERROR_NONE;
}
static UINT AIAPI UpdateAudio(VOID)
{
return AUDIO_ERROR_NONE;
}
static LONG AIAPI GetAudioDataAvail(VOID)
{
return 0;
}
static UINT AIAPI CreateAudioData(LPAUDIOWAVE lpWave)
{
if (lpWave != NULL) {
lpWave->dwHandle = (DWORD) lpWave->lpData;
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALHANDLE;
}
static UINT AIAPI DestroyAudioData(LPAUDIOWAVE lpWave)
{
if (lpWave != NULL && lpWave->dwHandle != 0) {
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALHANDLE;
}
static UINT AIAPI WriteAudioData(LPAUDIOWAVE lpWave, DWORD dwOffset, UINT nCount)
{
if (lpWave != NULL && lpWave->dwHandle != 0) {
/* anticlick removal work around */
if (lpWave->wFormat & AUDIO_FORMAT_LOOP) {
*(LPDWORD) (lpWave->dwHandle + lpWave->dwLoopEnd) =
*(LPDWORD) (lpWave->dwHandle + lpWave->dwLoopStart);
}
else if (dwOffset + nCount >= lpWave->dwLength) {
*(LPDWORD) (lpWave->dwHandle + lpWave->dwLength) = 0;
}
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALHANDLE;
}
static UINT AIAPI PrimeVoice(UINT nVoice, LPAUDIOWAVE lpWave)
{
LPVOICE lpVoice;
if (nVoice < Synth.nVoices && lpWave != NULL && lpWave->dwHandle != 0) {
lpVoice = &Synth.aVoices[nVoice];
lpVoice->lpData = (LPVOID) lpWave->dwHandle;
lpVoice->bControl = VOICE_STOP;
lpVoice->dwAccum = 0;
if (lpWave->wFormat & (AUDIO_FORMAT_LOOP | AUDIO_FORMAT_BIDILOOP)) {
lpVoice->dwLoopStart = lpWave->dwLoopStart;
lpVoice->dwLoopEnd = lpWave->dwLoopEnd;
lpVoice->bControl |= VOICE_LOOP;
if (lpWave->wFormat & AUDIO_FORMAT_BIDILOOP)
lpVoice->bControl |= VOICE_BIDILOOP;
}
else {
lpVoice->dwLoopStart = lpWave->dwLength;
lpVoice->dwLoopEnd = lpWave->dwLength;
}
if (lpWave->wFormat & AUDIO_FORMAT_16BITS) {
lpVoice->dwLoopStart >>= 1;
lpVoice->dwLoopEnd >>= 1;
lpVoice->bControl |= VOICE_16BITS;
}
lpVoice->dwAccum <<= ACCURACY;
lpVoice->dwLoopStart <<= ACCURACY;
lpVoice->dwLoopEnd <<= ACCURACY;
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALHANDLE;
}
static UINT AIAPI StartVoice(UINT nVoice)
{
if (nVoice < Synth.nVoices) {
Synth.aVoices[nVoice].bControl &= ~VOICE_STOP;
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALHANDLE;
}
static UINT AIAPI StopVoice(UINT nVoice)
{
if (nVoice < Synth.nVoices) {
Synth.aVoices[nVoice].bControl |= VOICE_STOP;
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALHANDLE;
}
static UINT AIAPI SetVoicePosition(UINT nVoice, LONG dwPosition)
{
if (nVoice < Synth.nVoices) {
dwPosition <<= ACCURACY;
if (dwPosition >= 0 && dwPosition < Synth.aVoices[nVoice].dwLoopEnd) {
Synth.aVoices[nVoice].dwAccum = dwPosition;
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALPARAM;
}
return AUDIO_ERROR_INVALHANDLE;
}
static UINT AIAPI SetVoiceFrequency(UINT nVoice, LONG dwFrequency)
{
if (nVoice < Synth.nVoices) {
if (dwFrequency >= AUDIO_MIN_FREQUENCY &&
dwFrequency <= AUDIO_MAX_FREQUENCY) {
Synth.aVoices[nVoice].dwFrequency = ((dwFrequency << ACCURACY) +
(Synth.nSampleRate >> 1)) / Synth.nSampleRate;
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALPARAM;
}
return AUDIO_ERROR_INVALHANDLE;
}
static UINT AIAPI SetVoiceVolume(UINT nVoice, UINT nVolume)
{
if (nVoice < Synth.nVoices) {
if (nVolume <= AUDIO_MAX_VOLUME) {
Synth.aVoices[nVoice].nVolume = nVolume >> 1;
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALPARAM;
}
return AUDIO_ERROR_INVALHANDLE;
}
static UINT AIAPI SetVoicePanning(UINT nVoice, UINT nPanning)
{
if (nVoice < Synth.nVoices) {
if (nPanning <= AUDIO_MAX_PANNING) {
Synth.aVoices[nVoice].nPanning = nPanning;
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALPARAM;
}
return AUDIO_ERROR_INVALHANDLE;
}
static UINT AIAPI GetVoicePosition(UINT nVoice, LPLONG lpdwPosition)
{
if (nVoice < Synth.nVoices) {
if (lpdwPosition != NULL) {
*lpdwPosition = Synth.aVoices[nVoice].dwAccum >> ACCURACY;
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALPARAM;
}
return AUDIO_ERROR_INVALHANDLE;
}
static UINT AIAPI GetVoiceFrequency(UINT nVoice, LPLONG lpdwFrequency)
{
if (nVoice < Synth.nVoices) {
if (lpdwFrequency != NULL) {
*lpdwFrequency = (Synth.aVoices[nVoice].dwFrequency *
Synth.nSampleRate) >> ACCURACY;
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALPARAM;
}
return AUDIO_ERROR_INVALHANDLE;
}
static UINT AIAPI GetVoiceVolume(UINT nVoice, LPUINT lpnVolume)
{
if (nVoice < Synth.nVoices) {
if (lpnVolume != NULL) {
*lpnVolume = Synth.aVoices[nVoice].nVolume << 1;
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALPARAM;
}
return AUDIO_ERROR_INVALHANDLE;
}
static UINT AIAPI GetVoicePanning(UINT nVoice, LPUINT lpnPanning)
{
if (nVoice < Synth.nVoices) {
if (lpnPanning != NULL) {
*lpnPanning = Synth.aVoices[nVoice].nPanning;
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALPARAM;
}
return AUDIO_ERROR_INVALHANDLE;
}
static UINT AIAPI GetVoiceStatus(UINT nVoice, LPBOOL lpnStatus)
{
if (nVoice < Synth.nVoices) {
if (lpnStatus != NULL) {
*lpnStatus = (Synth.aVoices[nVoice].bControl & VOICE_STOP) != 0;
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALPARAM;
}
return AUDIO_ERROR_INVALHANDLE;
}
static UINT AIAPI SetAudioTimerProc(LPFNAUDIOTIMER lpfnAudioTimer)
{
Synth.lpfnAudioTimer = lpfnAudioTimer;
return AUDIO_ERROR_NONE;
}
static UINT AIAPI SetAudioTimerRate(UINT nBPM)
{
if (nBPM >= 0x20 && nBPM <= 0xFF) {
Synth.dwTimerRate = Synth.nSampleRate;
if (Synth.wFormat & AUDIO_FORMAT_STEREO)
Synth.dwTimerRate <<= 1;
Synth.dwTimerRate = (5 * Synth.dwTimerRate) / (2 * nBPM);
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALPARAM;
}
static VOID AIAPI UpdateVoices(LPBYTE lpData, UINT nCount)
{
static LONG aBuffer[BUFFERSIZE];
UINT nSamples;
if (Synth.wFormat & AUDIO_FORMAT_16BITS)
nCount >>= 1;
while (nCount > 0) {
if ((nSamples = nCount) > BUFFERSIZE)
nSamples = BUFFERSIZE;
memset(aBuffer, 0, nSamples << 2);
MixAudioVoices(aBuffer, nSamples);
QuantAudioData(lpData, aBuffer, nSamples);
lpData += nSamples << ((Synth.wFormat & AUDIO_FORMAT_16BITS) != 0);
nCount -= nSamples;
}
}
/*
* Waveform synthesizer public interface
*/
AUDIOSYNTHDRIVER EmuSynthDriver =
{
GetAudioCaps, PingAudio, OpenAudio, CloseAudio,
UpdateAudio, OpenVoices, CloseVoices,
SetAudioTimerProc, SetAudioTimerRate, SetAudioMixerValue,
GetAudioDataAvail, CreateAudioData, DestroyAudioData,
WriteAudioData, PrimeVoice, StartVoice, StopVoice,
SetVoicePosition, SetVoiceFrequency, SetVoiceVolume,
SetVoicePanning, GetVoicePosition, GetVoiceFrequency,
GetVoiceVolume, GetVoicePanning, GetVoiceStatus
};

1651
seal-hack/src/modeng.c Normal file

File diff suppressed because it is too large Load Diff

309
seal-hack/src/modfile.c Normal file
View File

@@ -0,0 +1,309 @@
/*
* $Id: modfile.c 1.5 1996/09/13 15:10:01 chasan released $
*
* Protracker/Fastracker module file loader routines.
*
* Copyright (c) 1995-1999 Carlos Hasan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <stdlib.h>
#include <string.h>
#include "audio.h"
#include "iofile.h"
/*
* Protracker module file structures
*/
typedef struct {
CHAR aSampleName[22];
WORD wLength;
BYTE nFinetune;
BYTE nVolume;
WORD wLoopStart;
WORD wLoopLength;
} MODSAMPLEHEADER;
typedef struct {
CHAR aModuleName[20];
MODSAMPLEHEADER aSampleTable[31];
BYTE nSongLength;
BYTE nRestart;
BYTE aOrderTable[128];
CHAR aMagic[4];
} MODFILEHEADER;
/*
* Extended Protracker logarithmic period table
*/
static WORD aMODPeriodTable[96] =
{
6848, 6464, 6096, 5760, 5424, 5120, 4832, 4560, 4304, 4064, 3840, 3624,
3424, 3232, 3048, 2880, 2712, 2560, 2416, 2280, 2152, 2032, 1920, 1812,
1712, 1616, 1524, 1440, 1356, 1280, 1208, 1140, 1076, 1016, 960, 906,
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
};
/*
* Protracker module header signatures table
*/
static struct {
CHAR aMagic[4];
UINT nTracks;
} aFmtTable[] = {
{ "M.K.", 4 }, { "M!K!", 4 },
{ "M&K!", 4 }, { "OCTA", 4 },
{ "FLT4", 4 }, { "6CHN", 6 },
{ "8CHN", 8 }, { "FLT8", 8 },
{ "10CH", 10 }, { "12CH", 12 },
{ "14CH", 14 }, { "16CH", 16 },
{ "18CH", 18 }, { "20CH", 20 },
{ "22CH", 22 }, { "24CH", 24 },
{ "26CH", 26 }, { "28CH", 28 },
{ "30CH", 30 }, { "32CH", 32 }
};
/*
* Protracker module file loader routines
*/
static UINT MODGetNoteValue(UINT nPeriod)
{
UINT nNote;
if (nPeriod != 0) {
for (nNote = 0; nNote < 96; nNote++)
if (nPeriod >= aMODPeriodTable[nNote])
return nNote + 1;
}
return 0;
}
static UINT MODLoadPattern(UINT nTracks, LPAUDIOPATTERN lpPattern)
{
UINT nSize, fPacking, nNote, nSample, nCommand, nParams;
LPBYTE lpData, lpFTData;
/* initialize pattern header structure */
nSize = 4 * 64 * nTracks;
lpPattern->nPacking = 0;
lpPattern->nTracks = nTracks;
lpPattern->nRows = 64;
lpPattern->nSize = nSize + 64 * nTracks;
if ((lpPattern->lpData = malloc(lpPattern->nSize)) == NULL)
return AUDIO_ERROR_NOMEMORY;
/* load MOD pattern data from disk */
lpData = lpPattern->lpData + 64 * nTracks;
lpFTData = lpPattern->lpData;
AIOReadFile(lpData, nSize);
while (nSize != 0) {
/* grab MOD note event from the pattern */
nNote = MODGetNoteValue(((lpData[0] & 0x0F) << 8) + lpData[1]);
nSample = (lpData[0] & 0xF0) + ((lpData[2] >> 4) & 0x0F);
nCommand = (lpData[2] & 0x0F);
nParams = lpData[3];
lpData += 4;
nSize -= 4;
/* remove some dummy MOD command effects */
switch ((nCommand << 8) + nParams) {
case 0x100:
case 0x200:
case 0xA00:
case 0xE10:
case 0xE20:
case 0xEA0:
case 0xEB0:
nCommand = nParams = 0x00;
break;
}
/* convert DMP-style panning command */
if (nCommand == 0x8) {
if (nParams > 0x80)
nParams = 0x80;
else if (nParams < 0x80)
nParams <<= 1;
else
nParams = 0xFF;
}
/* insert packed note event */
fPacking = AUDIO_PATTERN_PACKED;
if (nNote)
fPacking |= AUDIO_PATTERN_NOTE;
if (nSample)
fPacking |= AUDIO_PATTERN_SAMPLE;
if (nCommand)
fPacking |= AUDIO_PATTERN_COMMAND;
if (nParams)
fPacking |= AUDIO_PATTERN_PARAMS;
*lpFTData++ = fPacking;
if (nNote)
*lpFTData++ = nNote;
if (nSample)
*lpFTData++ = nSample;
if (nCommand)
*lpFTData++ = nCommand;
if (nParams)
*lpFTData++ = nParams;
}
lpPattern->nSize = (lpFTData - lpPattern->lpData);
if ((lpPattern->lpData = realloc(lpPattern->lpData, lpPattern->nSize)) == NULL) {
return AUDIO_ERROR_NOMEMORY;
}
return AUDIO_ERROR_NONE;
}
UINT AIAPI ALoadModuleMOD(LPSTR lpszFileName,
LPAUDIOMODULE *lplpModule, DWORD dwFileOffset)
{
static MODFILEHEADER Header;
static MODSAMPLEHEADER Sample;
LPAUDIOMODULE lpModule;
LPAUDIOPATTERN lpPattern;
LPAUDIOPATCH lpPatch;
LPAUDIOSAMPLE lpSample;
UINT n, nErrorCode;
if (AIOOpenFile(lpszFileName)) {
return AUDIO_ERROR_FILENOTFOUND;
}
AIOSeekFile(dwFileOffset, SEEK_SET);
if ((lpModule = (LPAUDIOMODULE) calloc(1, sizeof(AUDIOMODULE))) == NULL) {
AIOCloseFile();
return AUDIO_ERROR_NOMEMORY;
}
/* load MOD module header */
AIOReadFile(Header.aModuleName, sizeof(Header.aModuleName));
for (n = 0; n < 31; n++) {
AIOReadFile(Header.aSampleTable[n].aSampleName,
sizeof(Header.aSampleTable[n].aSampleName));
AIOReadShortM(&Header.aSampleTable[n].wLength);
AIOReadCharM(&Header.aSampleTable[n].nFinetune);
AIOReadCharM(&Header.aSampleTable[n].nVolume);
AIOReadShortM(&Header.aSampleTable[n].wLoopStart);
AIOReadShortM(&Header.aSampleTable[n].wLoopLength);
}
AIOReadCharM(&Header.nSongLength);
AIOReadCharM(&Header.nRestart);
AIOReadFile(Header.aOrderTable, sizeof(Header.aOrderTable));
AIOReadFile(Header.aMagic, sizeof(Header.aMagic));
for (n = 0; n < sizeof(aFmtTable) / sizeof(aFmtTable[0]); n++) {
if (!memcmp(Header.aMagic, aFmtTable[n].aMagic, sizeof(DWORD))) {
lpModule->nTracks = aFmtTable[n].nTracks;
break;
}
}
if (lpModule->nTracks == 0) {
AFreeModuleFile(lpModule);
AIOCloseFile();
return AUDIO_ERROR_BADFILEFORMAT;
}
/* initialize the module structure */
strncpy(lpModule->szModuleName, Header.aModuleName,
sizeof(Header.aModuleName));
lpModule->wFlags = AUDIO_MODULE_AMIGA | AUDIO_MODULE_PANNING;
lpModule->nOrders = Header.nSongLength;
lpModule->nRestart = Header.nRestart;
lpModule->nPatches = 31;
lpModule->nTempo = 6;
lpModule->nBPM = 125;
for (n = 0; n < sizeof(Header.aOrderTable); n++) {
lpModule->aOrderTable[n] = Header.aOrderTable[n];
if (lpModule->nPatterns < Header.aOrderTable[n])
lpModule->nPatterns = Header.aOrderTable[n];
}
lpModule->nPatterns++;
for (n = 0; n < lpModule->nTracks; n++) {
lpModule->aPanningTable[n] =
((n & 3) == 0 || (n & 3) == 3) ? 0x00 : 0xFF;
}
if ((lpModule->aPatternTable = (LPAUDIOPATTERN)
calloc(lpModule->nPatterns, sizeof(AUDIOPATTERN))) == NULL) {
AFreeModuleFile(lpModule);
AIOCloseFile();
return AUDIO_ERROR_NOMEMORY;
}
if ((lpModule->aPatchTable = (LPAUDIOPATCH)
calloc(lpModule->nPatches, sizeof(AUDIOPATCH))) == NULL) {
AFreeModuleFile(lpModule);
AIOCloseFile();
return AUDIO_ERROR_NOMEMORY;
}
/* load MOD pattern sheets */
lpPattern = lpModule->aPatternTable;
for (n = 0; n < lpModule->nPatterns; n++, lpPattern++) {
if ((nErrorCode = MODLoadPattern(lpModule->nTracks, lpPattern)) != 0) {
AFreeModuleFile(lpModule);
AIOCloseFile();
return nErrorCode;
}
}
/* load MOD sample waveforms */
lpPatch = lpModule->aPatchTable;
for (n = 0; n < lpModule->nPatches; n++, lpPatch++) {
memcpy(&Sample, &Header.aSampleTable[n], sizeof(MODSAMPLEHEADER));
strncpy(lpPatch->szPatchName, Sample.aSampleName,
sizeof(Sample.aSampleName));
if (Sample.wLength != 0) {
if ((lpSample = (LPAUDIOSAMPLE)
calloc(1, sizeof(AUDIOSAMPLE))) == NULL) {
AFreeModuleFile(lpModule);
AIOCloseFile();
return AUDIO_ERROR_NOMEMORY;
}
lpPatch->nSamples = 1;
lpPatch->aSampleTable = lpSample;
/* initialize sample structure */
lpSample->Wave.wFormat = AUDIO_FORMAT_8BITS;
lpSample->Wave.dwLength = (DWORD) Sample.wLength << 1;
lpSample->Wave.nSampleRate = 8363;
if (Sample.wLoopLength > 1 && Sample.wLoopStart < Sample.wLength) {
lpSample->Wave.wFormat |= AUDIO_FORMAT_LOOP;
lpSample->Wave.dwLoopStart = (DWORD) Sample.wLoopStart << 1;
lpSample->Wave.dwLoopEnd = (DWORD) Sample.wLoopStart << 1;
lpSample->Wave.dwLoopEnd += (DWORD) Sample.wLoopLength << 1;
if (lpSample->Wave.dwLoopEnd > lpSample->Wave.dwLength)
lpSample->Wave.dwLoopEnd = lpSample->Wave.dwLength;
}
lpSample->nVolume = Sample.nVolume <= 64 ? Sample.nVolume : 64;
lpSample->nFinetune = (Sample.nFinetune & 0x0F) << 4;
lpSample->nPanning = 0x80;
nErrorCode = ACreateAudioData(&lpSample->Wave);
if (nErrorCode != AUDIO_ERROR_NONE) {
AFreeModuleFile(lpModule);
AIOCloseFile();
return nErrorCode;
}
/* upload waveform data */
AIOReadFile(lpSample->Wave.lpData, lpSample->Wave.dwLength);
AWriteAudioData(&lpSample->Wave, 0, lpSample->Wave.dwLength);
}
}
AIOCloseFile();
*lplpModule = lpModule;
return AUDIO_ERROR_NONE;
}

BIN
seal-hack/src/mp Executable file

Binary file not shown.

270
seal-hack/src/mp.c Normal file
View File

@@ -0,0 +1,270 @@
/*
* $Id: mp.c 1.13 1996/09/13 18:18:38 chasan released $
*
* Module player demonstration
*
* Copyright (C) 1995-1999 Carlos Hasan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "audio.h"
#if defined(__DOS16__) || defined(__DPMI__) || defined(__WINDOWS__)
#include <conio.h>
#else
#define kbhit() 0
#endif
#ifdef __SDL__
#include"SDL.h"
#endif
struct {
AUDIOINFO Info;
AUDIOCAPS Caps;
LPAUDIOMODULE lpModule;
UINT nVolume;
BOOL bStopped;
} State;
void Assert(UINT nErrorCode)
{
static CHAR szText[80];
if (nErrorCode != AUDIO_ERROR_NONE) {
AGetErrorText(nErrorCode, szText, sizeof(szText) - 1);
printf("%s\n", szText);
exit(1);
}
}
#ifdef __MSC__
void __cdecl CleanUp(void)
#else
void CleanUp(void)
#endif
{
ACloseAudio();
}
void Banner(void)
{
/* BeOS R3 */
#ifdef __BEOS__
#define _SYSTEM_ "BeOS"
#endif
/* OS/2 MMPM */
#ifdef __OS2__
#define _SYSTEM_ "OS/2 MMPM"
#endif
/* Linux/386 */
#ifdef __LINUX__
#define _SYSTEM_ "Linux"
#endif
/* Darwin/x86_64 */
#ifdef __OSX__
#define _SYSTEM_ "MacOS X"
#endif
/* FreeBSD/386 */
#ifdef __FREEBSD__
#define _SYSTEM_ "FreeBSD"
#endif
/* SunOS 4.1.x */
#ifdef __SPARC__
#define _SYSTEM_ "SPARC/SunOS"
#endif
/* Solaris 2.x */
#ifdef __SOLARIS__
#define _SYSTEM_ "SPARC/Solaris"
#endif
/* IRIX 4.x */
#ifdef __SILICON__
#define _SYSTEM_ "SGI/Irix"
#endif
/* Win32 */
#if defined(__WINDOWS__) && defined(__FLAT__)
#ifdef __BORLANDC__
#define _SYSTEM_ "Win32/BC32"
#endif
#ifdef __WATCOMC__
#define _SYSTEM_ "Win32/WC32"
#endif
#ifdef __MSC__
#define _SYSTEM_ "Win32/MSC32"
#endif
#endif
/* Win16 */
#if defined(__WINDOWS__) && defined(__LARGE__)
#ifdef __BORLANDC__
#define _SYSTEM_ "Win16/BC16"
#endif
#ifdef __WATCOMC__
#define _SYSTEM_ "Win16/WC16"
#endif
#endif
/* DPMI32 */
#if defined(__DPMI__) && defined(__FLAT__)
#ifdef __BORLANDC__
#define _SYSTEM_ "DPMI32/BC32"
#endif
#ifdef __WATCOMC__
#define _SYSTEM_ "DOS4GW/WC32"
#endif
#endif
#if defined(__DPMI__) && defined(__DJGPP__)
#define _SYSTEM_ "DPMI32/DJGPP"
#endif
/* DPMI16 */
#if defined(__DPMI__) && defined(__LARGE__)
#ifdef __BORLANDC__
#define _SYSTEM_ "DPMI16/BC16"
#endif
#endif
/* DOS */
#if defined(__DOS16__) && defined(__LARGE__)
#ifdef __BORLANDC__
#define _SYSTEM_ "DOS/BC16"
#endif
#ifdef __WATCOMC__
#define _SYSTEM_ "DOS/WC16"
#endif
#endif
#ifndef _SYSTEM_
#define _SYSTEM_ "UNKNOWN"
#endif
printf("MOD/MTM/S3M/XM Module Player Version 0.6 (" _SYSTEM_ " version)\n");
printf("Please send bug reports to: chasan@dcc.uchile.cl\n");
}
void Usage(void)
{
UINT n;
printf("Usage: mp [options] file...\n");
printf(" -c device select audio device\n");
for (n = 0; n < AGetAudioNumDevs(); n++) {
AGetAudioDevCaps(n, &State.Caps);
printf("\t\t%d=%s\n", n, State.Caps.szProductName);
}
printf(" -r rate set sampling rate\n");
printf(" -v volume change global volume\n");
printf(" -8 8-bit sample precision\n");
printf(" -m monophonic output\n");
printf(" -i enable filtering\n");
printf("\n");
exit(0);
}
int main(int argc, char *argv[])
{
LPSTR lpszOption, lpszOptArg, lpszFileName;
int n;
/* initialize the audio system library */
AInitialize();
/* display program information */
Banner();
if (argc < 2) Usage();
/* setup default initialization parameters */
State.Info.nDeviceId = AUDIO_DEVICE_MAPPER;
State.Info.wFormat = AUDIO_FORMAT_16BITS | AUDIO_FORMAT_STEREO;
State.Info.nSampleRate = 44100;
State.nVolume = 96;
/* parse command line options */
for (n = 1; n < argc && (lpszOption = argv[n])[0] == '-'; n++) {
lpszOptArg = &lpszOption[2];
if (strchr("crv", lpszOption[1]) && !lpszOptArg[0] && n < argc - 1)
lpszOptArg = argv[++n];
switch (lpszOption[1]) {
case 'c':
State.Info.nDeviceId = atoi(lpszOptArg);
break;
case '8':
State.Info.wFormat &= ~AUDIO_FORMAT_16BITS;
break;
case 'm':
State.Info.wFormat &= ~AUDIO_FORMAT_STEREO;
break;
case 'i':
State.Info.wFormat |= AUDIO_FORMAT_FILTER;
break;
case 'r':
State.Info.nSampleRate = (UINT) atoi(lpszOptArg);
if (State.Info.nSampleRate < 1000)
State.Info.nSampleRate *= 1000;
break;
case 'v':
State.nVolume = atoi(lpszOptArg);
break;
default:
Usage();
break;
}
}
/* initialize and open the audio system */
Assert(AOpenAudio(&State.Info));
atexit(CleanUp);
/* display playback audio device information */
Assert(AGetAudioDevCaps(State.Info.nDeviceId, &State.Caps));
printf("%s playing at %d-bit %s %u Hz\n", State.Caps.szProductName,
State.Info.wFormat & AUDIO_FORMAT_16BITS ? 16 : 8,
State.Info.wFormat & AUDIO_FORMAT_STEREO ? "stereo" : "mono",
State.Info.nSampleRate);
while (n < argc && (lpszFileName = argv[n++]) != NULL) {
/* load module file from disk */
printf("Loading: %s\n", lpszFileName);
Assert(ALoadModuleFile(lpszFileName, &State.lpModule, 0L));
/* play the module file */
printf("Playing: %s\n", State.lpModule->szModuleName);
Assert(AOpenVoices(State.lpModule->nTracks));
Assert(APlayModule(State.lpModule));
Assert(ASetAudioMixerValue(AUDIO_MIXER_MASTER_VOLUME, State.nVolume));
#if defined(__WINDOWS__) || defined(__BEOS__)
printf("Press enter to quit\n");
getchar();
#else
while (!kbhit()) {
Assert(AGetModuleStatus(&State.bStopped));
if (State.bStopped) break;
Assert(AUpdateAudio());
#ifdef __SDL__
SDL_Delay(10); /* don't peg the cpu, 'k? */
#endif
}
#endif
Assert(AStopModule());
Assert(ACloseVoices());
/* release the module file */
Assert(AFreeModuleFile(State.lpModule));
}
return 0;
}

560
seal-hack/src/msdos.c Normal file
View File

@@ -0,0 +1,560 @@
/*
* $Id: msdos.c 1.7 1996/08/15 02:33:44 chasan released $
*
* MS-DOS hardware programming API interface.
*
* Copyright (C) 1995-1999 Carlos Hasan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <stdlib.h>
#include <stdlib.h>
#include <string.h>
#include "audio.h"
#include "msdos.h"
/*
* MS-DOS direct memory access API routines
*/
static BYTE aDmaSingle[8] =
{
DMA1_SNGL, DMA1_SNGL, DMA1_SNGL, DMA1_SNGL,
DMA2_SNGL, DMA2_SNGL, DMA2_SNGL, DMA2_SNGL
};
static BYTE aDmaMode[8] =
{
DMA1_MODE, DMA1_MODE, DMA1_MODE, DMA1_MODE,
DMA2_MODE, DMA2_MODE, DMA2_MODE, DMA2_MODE
};
static BYTE aDmaClear[8] =
{
DMA1_CLRFF, DMA1_CLRFF, DMA1_CLRFF, DMA1_CLRFF,
DMA2_CLRFF, DMA2_CLRFF, DMA2_CLRFF, DMA2_CLRFF
};
static BYTE aDmaPage[8] =
{
DMA0_PAGE, DMA1_PAGE, DMA2_PAGE, DMA3_PAGE,
DMA4_PAGE, DMA5_PAGE, DMA6_PAGE, DMA7_PAGE
};
static BYTE aDmaAddr[8] =
{
DMA0_ADDR, DMA1_ADDR, DMA2_ADDR, DMA3_ADDR,
DMA4_ADDR, DMA5_ADDR, DMA6_ADDR, DMA7_ADDR
};
static BYTE aDmaCount[8] =
{
DMA0_CNT, DMA1_CNT, DMA2_CNT, DMA3_CNT,
DMA4_CNT, DMA5_CNT, DMA6_CNT, DMA7_CNT
};
static DWORD aDmaLinearAddress[8] =
{
0x00000, 0x00000, 0x00000, 0x00000,
0x00000, 0x00000, 0x00000, 0x00000
};
static WORD aDmaBufferLength[8] =
{
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000
};
VOID AIAPI DosSetupChannel(UINT nChannel, BYTE nMode, WORD nCount)
{
WORD wAddr;
BYTE nPage;
if (nChannel <= 7) {
/* check out the count parameter */
if (nCount <= 0 || nCount >= aDmaBufferLength[nChannel])
nCount = aDmaBufferLength[nChannel];
/* get buffer physical address and length */
if (nChannel >= 4) {
wAddr = LOWORD(aDmaLinearAddress[nChannel] >> 1);
nPage = (BYTE) HIWORD(aDmaLinearAddress[nChannel]);
nCount >>= 1;
}
else {
wAddr = LOWORD(aDmaLinearAddress[nChannel]);
nPage = (BYTE) HIWORD(aDmaLinearAddress[nChannel]);
}
nCount--;
/* disable DMA channel before setting parameters */
OUTB(aDmaSingle[nChannel], (nChannel & 0x03) | DMA_DISABLE);
/* set DMA channel transfer mode */
OUTB(aDmaMode[nChannel], (nChannel & 0x03) | nMode);
/* set DMA channel buffer physical address */
OUTB(aDmaClear[nChannel], 0x00);
OUTB(aDmaAddr[nChannel], LOBYTE(wAddr));
OUTB(aDmaAddr[nChannel], HIBYTE(wAddr));
OUTB(aDmaPage[nChannel], nPage);
/* set DMA channel buffer length */
OUTB(aDmaClear[nChannel], 0x00);
OUTB(aDmaCount[nChannel], LOBYTE(nCount));
OUTB(aDmaCount[nChannel], HIBYTE(nCount));
/* enable DMA channel for transfers */
OUTB(aDmaSingle[nChannel], (nChannel & 0x03) | DMA_ENABLE);
}
}
VOID AIAPI DosDisableChannel(UINT nChannel)
{
if (nChannel <= 7) {
OUTB(aDmaSingle[nChannel], (nChannel & 0x03) | DMA_DISABLE);
}
}
VOID AIAPI DosEnableChannel(UINT nChannel)
{
if (nChannel <= 7) {
OUTB(aDmaSingle[nChannel], (nChannel & 0x03) | DMA_ENABLE);
}
}
UINT AIAPI DosGetChannelCount(UINT nChannel)
{
INT nTimeOut, nCount, nDelta, nLoData, nHiData;
if (nChannel <= 7) {
/* clear DMA channel flip-flop register */
OUTB(aDmaClear[nChannel], 0x00);
for (nTimeOut = 0; nTimeOut < 1024; nTimeOut++) {
/* poll DMA channel count register */
nLoData = INB(aDmaCount[nChannel]);
nHiData = INB(aDmaCount[nChannel]);
nCount = MAKEWORD(nLoData, nHiData);
nLoData = INB(aDmaCount[nChannel]);
nHiData = INB(aDmaCount[nChannel]);
nDelta = MAKEWORD(nLoData, nHiData);
if ((nDelta -= nCount) > -16 && nDelta < +16)
break;
}
/* adjust counter for 16 bit DMA channels */
if (nChannel >= 4)
nCount <<= 1;
return nCount + 1;
}
return 0;
}
/*
* 16-bit real mode custom DMA programming API routines
*/
#ifdef __DOS16__
static LPVOID aDmaBufferAddr[8] =
{
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
};
UINT AIAPI DosAllocChannel(UINT nChannel, WORD nCount)
{
DWORD dwAddress;
/*
* Allocate DOS memory using standard memory allocation
* routines for Borland C++ 3.1 in real mode.
*/
if (nChannel <= 7 &&
(aDmaBufferAddr[nChannel] = malloc(nCount << 1)) != NULL) {
dwAddress = ((DWORD) FP_SEG(aDmaBufferAddr[nChannel]) << 4) +
FP_OFF(aDmaBufferAddr[nChannel]);
if ((dwAddress & 0xFFFFL) + nCount > 0x10000L)
dwAddress += 0x10000L - (dwAddress & 0xFFFFL);
aDmaLinearAddress[nChannel] = dwAddress;
aDmaBufferLength[nChannel] = nCount;
return 0;
}
return 1;
}
VOID AIAPI DosFreeChannel(UINT nChannel)
{
if (nChannel <= 7 && aDmaBufferAddr[nChannel]) {
free(aDmaBufferAddr[nChannel]);
aDmaBufferAddr[nChannel] = NULL;
}
}
LPVOID AIAPI DosLockChannel(UINT nChannel)
{
DWORD dwAddress;
if (nChannel <= 7) {
dwAddress = aDmaLinearAddress[nChannel];
return MK_FP((unsigned) (dwAddress >> 4),
(unsigned) (dwAddress & 0x000F));
}
return NULL;
}
VOID AIAPI DosUnlockChannel(UINT nChannel)
{
if (nChannel <= 7) {
}
}
#endif
/*
* 16/32-bit protected mode DPMI custom DMA programming API routines
*/
#if defined(__DPMI__) && !defined(__DJGPP__)
static WORD aDmaBufferSelector[8] =
{
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000
};
UINT AIAPI DosAllocChannel(UINT nChannel, WORD nCount)
{
static DOSREGS r;
DWORD dwAddress;
/*
* Allocate DOS memory using a DPMI system call, works with DOS/4GW
* and PMODE/W 32-bit DOS extenders, Borland's DPMI16 and DPMI32,
* and with DJGPP V2 32-bit DPMI host.
*/
if (nChannel <= 7) {
r.ax = 0x0100;
r.bx = ((nCount << 1) + 15) >> 4;
DosIntVector(0x31, &r);
if (!r.cflag) {
dwAddress = (DWORD) r.ax << 4;
if ((dwAddress & 0xFFFF) + nCount > 0x10000L)
dwAddress += 0x10000L - (dwAddress & 0xFFFFL);
aDmaBufferSelector[nChannel] = r.dx;
aDmaLinearAddress[nChannel] = dwAddress;
aDmaBufferLength[nChannel] = nCount;
return 0;
}
}
return 1;
}
VOID AIAPI DosFreeChannel(UINT nChannel)
{
static DOSREGS r;
if (nChannel <= 7 && aDmaBufferSelector[nChannel]) {
r.ax = 0x0101;
r.dx = aDmaBufferSelector[nChannel];
DosIntVector(0x31, &r);
aDmaBufferSelector[nChannel] = 0x0000;
}
}
LPVOID AIAPI DosLockChannel(UINT nChannel)
{
if (nChannel <= 7) {
#ifdef __FLAT__
/* TODO: This only works in DOS4GW and PMODEW extenders. */
return (LPVOID) aDmaLinearAddress[nChannel];
#else
return MK_FP(aDmaBufferSelector[nChannel], 0x0000);
#endif
}
return NULL;
}
VOID AIAPI DosUnlockChannel(UINT nChannel)
{
if (nChannel <= 7) {
}
}
#endif
/*
* DJGPP V2 custom DMA programming routines
*/
#ifdef __DJGPP__
static WORD aDmaBufferSelector[8] =
{
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000
};
UINT AIAPI DosAllocChannel(UINT nChannel, WORD nCount)
{
DWORD dwAddress;
UINT nSelector;
/*
* Allocate DOS memory using a DPMI system call
* for DJGPP V2 in 32-bit protected mode.
*/
if (nChannel <= 7) {
if (__dpmi_allocate_dos_memory(((nCount << 1) + 15) >> 4, &nSelector) != -1) {
__dpmi_get_segment_base_address(nSelector, &dwAddress);
if ((dwAddress & 0xFFFFL) + nCount > 0x10000L)
dwAddress += 0x10000L - (dwAddress & 0xFFFFL);
aDmaBufferSelector[nChannel] = nSelector;
aDmaLinearAddress[nChannel] = dwAddress;
aDmaBufferLength[nChannel] = nCount;
return 0;
}
}
return 1;
}
VOID AIAPI DosFreeChannel(UINT nChannel)
{
if (nChannel <= 7 && aDmaBufferSelector[nChannel]) {
__dpmi_free_dos_memory(aDmaBufferSelector[nChannel]);
aDmaBufferSelector[nChannel] = 0x0000;
}
}
LPVOID AIAPI DosLockChannel(UINT nChannel)
{
if (nChannel <= 7 && ((_crt0_startup_flags & _CRT0_FLAG_NEARPTR) ||
__djgpp_nearptr_enable())) {
return (LPVOID) (aDmaLinearAddress[nChannel] +
__djgpp_conventional_base);
}
return NULL;
}
VOID AIAPI DosUnlockChannel(UINT nChannel)
{
if (nChannel <= 7 && !(_crt0_startup_flags & _CRT0_FLAG_NEARPTR)) {
__djgpp_nearptr_disable();
}
}
#endif
/*
* MS-DOS interrupt programming API routines
*/
#ifdef __BORLANDC__
typedef VOID __interrupt (*LPFNHARDWAREVECTOR)(VOID);
#endif
#ifdef __WATCOMC__
typedef VOID (__interrupt* LPFNHARDWAREVECTOR)(VOID);
#endif
#ifdef __DJGPP__
typedef _go32_dpmi_seginfo LPFNHARDWAREVECTOR;
#define __interrupt
#endif
static BYTE aIrqSlotNumber[16] =
{
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77
};
static LPFNUSERVECTOR aUserVector[16] =
{
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
};
static LPFNHARDWAREVECTOR aHardwareVector[16];
static VOID MasterWrapVector(UINT nIrqLine)
{
if (aUserVector[nIrqLine] != NULL)
(*aUserVector[nIrqLine])();
if (nIrqLine >= 8)
OUTB(0xA0, 0x20);
OUTB(0x20, 0x20);
}
#define WRAPVECTOR(name, num) \
static VOID __interrupt name (VOID) { MasterWrapVector(num); }
WRAPVECTOR(Wrap0Vector, 0x00)
WRAPVECTOR(Wrap1Vector, 0x01)
WRAPVECTOR(Wrap2Vector, 0x02)
WRAPVECTOR(Wrap3Vector, 0x03)
WRAPVECTOR(Wrap4Vector, 0x04)
WRAPVECTOR(Wrap5Vector, 0x05)
WRAPVECTOR(Wrap6Vector, 0x06)
WRAPVECTOR(Wrap7Vector, 0x07)
WRAPVECTOR(Wrap8Vector, 0x08)
WRAPVECTOR(Wrap9Vector, 0x09)
WRAPVECTOR(WrapAVector, 0x0A)
WRAPVECTOR(WrapBVector, 0x0B)
WRAPVECTOR(WrapCVector, 0x0C)
WRAPVECTOR(WrapDVector, 0x0D)
WRAPVECTOR(WrapEVector, 0x0E)
WRAPVECTOR(WrapFVector, 0x0F)
#ifdef __DJGPP__
static LPFNUSERVECTOR aWrapVector[16] =
#else
static LPFNHARDWAREVECTOR aWrapVector[16] =
#endif
{
Wrap0Vector, Wrap1Vector, Wrap2Vector, Wrap3Vector,
Wrap4Vector, Wrap5Vector, Wrap6Vector, Wrap7Vector,
Wrap8Vector, Wrap9Vector, WrapAVector, WrapBVector,
WrapCVector, WrapDVector, WrapEVector, WrapFVector
};
VOID AIAPI DosEnableVectorHandler(UINT nIrqLine)
{
WORD wIrqMask;
if (nIrqLine <= 15) {
if (nIrqLine == 2) nIrqLine = 9;
wIrqMask = MAKEWORD(INB(0x21), INB(0xA1)) & ~(1 << nIrqLine);
OUTB(0x21, LOBYTE(wIrqMask));
OUTB(0xA1, HIBYTE(wIrqMask));
}
}
VOID AIAPI DosDisableVectorHandler(UINT nIrqLine)
{
WORD wIrqMask;
if (nIrqLine <= 15) {
if (nIrqLine == 2) nIrqLine = 9;
wIrqMask = MAKEWORD(INB(0x21), INB(0xA1)) | (1 << nIrqLine);
OUTB(0x21, LOBYTE(wIrqMask));
OUTB(0xA1, HIBYTE(wIrqMask));
}
}
VOID AIAPI DosSetVectorHandler(UINT nIrqLine, LPFNUSERVECTOR lpfnUserVector)
{
#ifdef __DJGPP__
_go32_dpmi_seginfo wrapper;
#endif
UINT nIntr;
if (nIrqLine <= 15) {
if (nIrqLine == 2) nIrqLine = 9;
nIntr = aIrqSlotNumber[nIrqLine];
if (lpfnUserVector != NULL) {
if (!aUserVector[nIrqLine]) {
#ifdef __DJGPP__
_go32_dpmi_get_protected_mode_interrupt_vector(nIntr, &aHardwareVector[nIrqLine]);
wrapper.pm_offset = (DWORD) aWrapVector[nIrqLine];
wrapper.pm_selector = _go32_my_cs();
_go32_dpmi_allocate_iret_wrapper(&wrapper);
_go32_dpmi_set_protected_mode_interrupt_vector(nIntr, &wrapper);
#else
aHardwareVector[nIrqLine] = _dos_getvect(nIntr);
_dos_setvect(nIntr, aWrapVector[nIrqLine]);
#endif
DosEnableVectorHandler(nIrqLine);
}
}
else {
if (aUserVector[nIrqLine]) {
DosDisableVectorHandler(nIrqLine);
#ifdef __DJGPP__
_go32_dpmi_get_protected_mode_interrupt_vector(nIntr, &wrapper);
_go32_dpmi_set_protected_mode_interrupt_vector(nIntr, &aHardwareVector[nIrqLine]);
_go32_dpmi_free_iret_wrapper(&wrapper);
#else
_dos_setvect(nIntr, aHardwareVector[nIrqLine]);
#endif
}
}
aUserVector[nIrqLine] = lpfnUserVector;
}
}
VOID AIAPI DosIntVector(UINT nIntr, LPDOSREGS lpRegs)
{
static union REGS r;
memset(&r, 0, sizeof(r));
#ifdef __FLAT__
r.w.ax = lpRegs->ax;
r.w.bx = lpRegs->bx;
r.w.cx = lpRegs->cx;
r.w.dx = lpRegs->dx;
r.w.si = lpRegs->si;
r.w.di = lpRegs->di;
int386(nIntr, &r, &r);
lpRegs->ax = r.w.ax;
lpRegs->bx = r.w.bx;
lpRegs->cx = r.w.cx;
lpRegs->dx = r.w.dx;
lpRegs->si = r.w.si;
lpRegs->di = r.w.di;
lpRegs->cflag = r.x.cflag;
#else
r.x.ax = lpRegs->ax;
r.x.bx = lpRegs->bx;
r.x.cx = lpRegs->cx;
r.x.dx = lpRegs->dx;
r.x.si = lpRegs->si;
r.x.di = lpRegs->di;
int86(nIntr, &r, &r);
lpRegs->ax = r.x.ax;
lpRegs->bx = r.x.bx;
lpRegs->cx = r.x.cx;
lpRegs->dx = r.x.dx;
lpRegs->si = r.x.si;
lpRegs->di = r.x.di;
lpRegs->cflag = r.x.cflag;
#endif
}
LPSTR AIAPI DosGetEnvironment(LPSTR lpszKeyName)
{
return getenv(lpszKeyName);
}
UINT AIAPI DosParseString(LPSTR lpszText, UINT nToken)
{
static LPSTR lpszString = NULL;
if (lpszText != NULL)
lpszString = lpszText;
if (lpszString != NULL) {
if (nToken == TOKEN_CHAR) {
return *lpszString++;
}
if (nToken == TOKEN_DEC) {
return strtol(lpszString, &lpszString, 10);
}
if (nToken == TOKEN_HEX) {
return strtol(lpszString, &lpszString, 0x10);
}
}
return BAD_TOKEN;
}

179
seal-hack/src/msdos.h Normal file
View File

@@ -0,0 +1,179 @@
/*
* $Id: msdos.h 1.5 1996/08/05 18:51:19 chasan released $
*
* MS-DOS hardware programming API interface.
*
* Copyright (C) 1995-1999 Carlos Hasan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef __MSDOS_H
#define __MSDOS_H
#ifdef __BORLANDC__
#include <dos.h>
#include <conio.h>
#endif
#ifdef __WATCOMC__
#include <i86.h>
#include <dos.h>
#include <conio.h>
#endif
#ifdef __DJGPP__
#include <sys/nearptr.h>
#include <dpmi.h>
#include <go32.h>
#include <pc.h>
#include <dos.h>
#include <crt0.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*
* I/O address space macro routines
*/
#ifdef __BORLANDC__
#define INB inportb
#define INW inport
#define OUTB outportb
#define OUTW outport
#endif
#ifdef __WATCOMC__
#define INB inp
#define INW inpw
#define OUTB outp
#define OUTW outpw
#endif
#ifdef __DJGPP__
#define INB inportb
#define INW inportw
#define OUTB outportb
#define OUTW outportw
#endif
/*
* 8-bit DMA controller register ports
*/
#define DMA1_STAT 0x08
#define DMA1_WCMD 0x08
#define DMA1_WREQ 0x09
#define DMA1_SNGL 0x0A
#define DMA1_MODE 0x0B
#define DMA1_CLRFF 0x0C
#define DMA1_MCLR 0x0D
#define DMA1_CLRM 0x0E
#define DMA1_WRTALL 0x0F
/*
* 16-bit DMA controller register ports
*/
#define DMA2_STAT 0xD0
#define DMA2_WCMD 0xD0
#define DMA2_WREQ 0xD2
#define DMA2_SNGL 0xD4
#define DMA2_MODE 0xD6
#define DMA2_CLRFF 0xD8
#define DMA2_MCLR 0xDA
#define DMA2_CLRM 0xDC
#define DMA2_WRTALL 0xDE
/*
* DMA controllers base address and count registers
*/
#define DMA0_ADDR 0x00
#define DMA0_CNT 0x01
#define DMA1_ADDR 0x02
#define DMA1_CNT 0x03
#define DMA2_ADDR 0x04
#define DMA2_CNT 0x05
#define DMA3_ADDR 0x06
#define DMA3_CNT 0x07
#define DMA4_ADDR 0xC0
#define DMA4_CNT 0xC2
#define DMA5_ADDR 0xC4
#define DMA5_CNT 0xC6
#define DMA6_ADDR 0xC8
#define DMA6_CNT 0xCA
#define DMA7_ADDR 0xCC
#define DMA7_CNT 0xCE
#define DMA0_PAGE 0x87
#define DMA1_PAGE 0x83
#define DMA2_PAGE 0x81
#define DMA3_PAGE 0x82
#define DMA4_PAGE 0x8F
#define DMA5_PAGE 0x8B
#define DMA6_PAGE 0x89
#define DMA7_PAGE 0x8A
/*
* DMA controller mode bit fields
*/
#define DMA_ENABLE 0x00
#define DMA_DISABLE 0x04
#define DMA_AUTOINIT 0x10
#define DMA_READ 0x44
#define DMA_WRITE 0x48
/*
* PIC hardware interrupt callback routine
*/
typedef VOID (AIAPI* LPFNUSERVECTOR)(VOID);
typedef struct {
WORD ax;
WORD bx;
WORD cx;
WORD dx;
WORD si;
WORD di;
WORD cflag;
} DOSREGS, *LPDOSREGS;
/*
* DOS environment parsing token types
*/
#define TOKEN_CHAR 0x00
#define TOKEN_DEC 0x01
#define TOKEN_HEX 0x02
#define BAD_TOKEN 0xFFFFU
/*
* MS-DOS hardware programming API interface
*/
VOID AIAPI DosSetVectorHandler(UINT nIrqLine, LPFNUSERVECTOR lpfnUserVector);
VOID AIAPI DosEnableVectorHandler(UINT nIrqLine);
VOID AIAPI DosDisableVectorHandler(UINT nIrqLine);
VOID AIAPI DosSetupChannel(UINT nChannel, BYTE nMode, WORD nCount);
VOID AIAPI DosDisableChannel(UINT nChannel);
VOID AIAPI DosEnableChannel(UINT nChannel);
UINT AIAPI DosGetChannelCount(UINT nChannel);
UINT AIAPI DosAllocChannel(UINT nChannel, WORD nCount);
VOID AIAPI DosFreeChannel(UINT nChannel);
LPVOID AIAPI DosLockChannel(UINT nChannel);
VOID AIAPI DosUnlockChannel(UINT nChannel);
VOID AIAPI DosIntVector(UINT nIntr, LPDOSREGS lpRegs);
LPSTR AIAPI DosGetEnvironment(LPSTR lpszKeyName);
UINT AIAPI DosParseString(LPSTR lpszText, UINT nToken);
#ifdef __cplusplus
};
#endif
#endif

299
seal-hack/src/mtmfile.c Normal file
View File

@@ -0,0 +1,299 @@
/*
* $Id: mtmfile.c 1.1 1996/09/25 17:19:14 chasan released $
*
* Multitracker 1.0 module file loader
*
* Copyright (C) 1995-1999 Carlos Hasan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "audio.h"
#include "iofile.h"
/*
* MTM file header signature defines
*/
#define MTM_SIGN_PATTERN 0x104D544DL
#define MTM_SIGN_MASK 0xF0FFFFFFL
/*
* MTM module header structure
*/
typedef struct {
DWORD dwMTM;
CHAR szModuleName[20];
WORD nSeqTracks;
BYTE nPatterns;
BYTE nOrders;
WORD nMesgSize;
BYTE nSamples;
BYTE bFlags;
BYTE nBeatsPerTrack;
BYTE nChannels;
BYTE aPanningTable[32];
} MTMHEADER, *LPMTMHEADER;
/*
* MTM sample header structure
*/
typedef struct {
CHAR szSampleName[22];
DWORD dwLength;
DWORD dwLoopStart;
DWORD dwLoopEnd;
BYTE nFinetune;
BYTE nVolume;
BYTE bFlags;
} MTMSAMPLE, *LPMTMSAMPLE;
/*
* MTM track data structure
*/
typedef struct {
BYTE aData[3*64];
} MTMTRACK, *LPMTMTRACK;
static UINT MTMMakePattern(UINT nTracks, UINT nSeqTracks,
LPAUDIOPATTERN lpPattern, WORD aPatSeqTable[32], LPMTMTRACK lpTrackTable)
{
LPBYTE lpData, lpEvent;
UINT nRowOfs, nTrack;
UINT fFlags, nNote, nSample, nCommand, nParams;
if ((lpData = (LPBYTE) malloc(64*5*nTracks)) == NULL)
return AUDIO_ERROR_NOMEMORY;
lpPattern->lpData = lpData;
lpPattern->nPacking = 0;
lpPattern->nTracks = nTracks;
lpPattern->nRows = 64;
for (nRowOfs = 0; nRowOfs < 3*64; nRowOfs += 3) {
for (nTrack = 0; nTrack < nTracks; nTrack++) {
if (aPatSeqTable[nTrack] >= 1 &&
aPatSeqTable[nTrack] <= nSeqTracks) {
lpEvent = &lpTrackTable[aPatSeqTable[nTrack]-1].aData[nRowOfs];
nNote = (lpEvent[0] >> 2) & 0x3F;
nSample = ((lpEvent[0] & 0x03) << 4) | (lpEvent[1] >> 4);
nCommand = (lpEvent[1] & 0x0F);
nParams = lpEvent[2];
fFlags = AUDIO_PATTERN_PACKED;
if (nNote) {
nNote += 12*2 + 1;
fFlags |= AUDIO_PATTERN_NOTE;
}
if (nSample)
fFlags |= AUDIO_PATTERN_SAMPLE;
if (nCommand)
fFlags |= AUDIO_PATTERN_COMMAND;
if (nParams)
fFlags |= AUDIO_PATTERN_PARAMS;
*lpData++ = fFlags;
if (fFlags & AUDIO_PATTERN_NOTE)
*lpData++ = nNote;
if (fFlags & AUDIO_PATTERN_SAMPLE)
*lpData++ = nSample;
if (fFlags & AUDIO_PATTERN_COMMAND)
*lpData++ = nCommand;
if (fFlags & AUDIO_PATTERN_PARAMS)
*lpData++ = nParams;
}
else {
*lpData++ = AUDIO_PATTERN_PACKED;
}
}
}
lpPattern->nSize = lpData - lpPattern->lpData;
if ((lpPattern->lpData = (LPBYTE)
realloc(lpPattern->lpData, lpPattern->nSize)) == NULL)
return AUDIO_ERROR_NOMEMORY;
return AUDIO_ERROR_NONE;
}
static UINT MTMMakeSample(LPAUDIOPATCH lpPatch, LPMTMSAMPLE lpMTMSample)
{
LPAUDIOSAMPLE lpSample;
LPBYTE lpData;
DWORD dwCount;
UINT rc;
strncpy(lpPatch->szPatchName, lpMTMSample->szSampleName,
sizeof(lpMTMSample->szSampleName));
if (lpMTMSample->dwLength) {
if ((lpSample = (LPAUDIOSAMPLE) calloc(1, sizeof(AUDIOSAMPLE))) == NULL)
return AUDIO_ERROR_NOMEMORY;
lpPatch->nSamples = 1;
lpPatch->aSampleTable = lpSample;
lpSample->Wave.wFormat = AUDIO_FORMAT_8BITS | AUDIO_FORMAT_MONO;
lpSample->Wave.dwLength = lpMTMSample->dwLength;
lpSample->nVolume = lpMTMSample->nVolume;
lpSample->nFinetune = lpMTMSample->nFinetune;
lpSample->nPanning = 0x80;
if (lpMTMSample->dwLoopStart + 2 < lpMTMSample->dwLoopEnd &&
lpMTMSample->dwLoopEnd <= lpMTMSample->dwLength) {
lpSample->Wave.wFormat |= AUDIO_FORMAT_LOOP;
lpSample->Wave.dwLoopStart = lpMTMSample->dwLoopStart;
lpSample->Wave.dwLoopEnd = lpMTMSample->dwLoopEnd;
}
if ((rc = ACreateAudioData(&lpSample->Wave)) != AUDIO_ERROR_NONE)
return rc;
AIOReadFile(lpSample->Wave.lpData, lpSample->Wave.dwLength);
lpData = lpSample->Wave.lpData;
dwCount = lpSample->Wave.dwLength;
while (dwCount--)
*lpData++ ^= 0x80;
AWriteAudioData(&lpSample->Wave, 0, lpSample->Wave.dwLength);
}
return AUDIO_ERROR_NONE;
}
UINT AIAPI ALoadModuleMTM(LPSTR lpszFileName,
LPAUDIOMODULE* lplpModule, DWORD dwFileOffset)
{
LPAUDIOMODULE lpModule;
static MTMHEADER Header;
LPMTMSAMPLE lpSampleTable;
LPMTMTRACK lpTrackTable;
static WORD aPatSeqTable[32];
UINT n, rc;
if (AIOOpenFile(lpszFileName)) {
return AUDIO_ERROR_FILENOTFOUND;
}
AIOSeekFile(dwFileOffset, SEEK_SET);
if ((lpModule = (LPAUDIOMODULE) calloc(1, sizeof(AUDIOMODULE))) == NULL) {
AIOCloseFile();
return AUDIO_ERROR_NOMEMORY;
}
/* load MTM module header data */
AIOReadLong(&Header.dwMTM);
AIOReadFile(Header.szModuleName, sizeof(Header.szModuleName));
AIOReadShort(&Header.nSeqTracks);
AIOReadChar(&Header.nPatterns);
AIOReadChar(&Header.nOrders);
AIOReadShort(&Header.nMesgSize);
AIOReadChar(&Header.nSamples);
AIOReadChar(&Header.bFlags);
AIOReadChar(&Header.nBeatsPerTrack);
AIOReadChar(&Header.nChannels);
AIOReadFile(Header.aPanningTable, sizeof(Header.aPanningTable));
/* check MTM file header signature and other fields */
if ((Header.dwMTM & MTM_SIGN_MASK) != MTM_SIGN_PATTERN ||
/*** (Header.nPatterns > AUDIO_MAX_PATTERNS) || FIX: avoid warnings ***/
/*** (Header.nOrders > AUDIO_MAX_ORDERS) || FIX: avoid warnings ***/
(Header.nSamples > AUDIO_MAX_PATCHES) ||
(Header.nChannels > AUDIO_MAX_VOICES) ||
(Header.nBeatsPerTrack != 64)) {
AFreeModuleFile(lpModule);
AIOCloseFile();
return AUDIO_ERROR_BADFILEFORMAT;
}
/* build the local module header structure */
strncpy(lpModule->szModuleName, Header.szModuleName,
sizeof(Header.szModuleName));
lpModule->wFlags = AUDIO_MODULE_AMIGA | AUDIO_MODULE_PANNING;
lpModule->nOrders = Header.nOrders + 1;
lpModule->nRestart = AUDIO_MAX_ORDERS;
lpModule->nTracks = Header.nChannels;
lpModule->nPatterns = Header.nPatterns + 1;
lpModule->nPatches = Header.nSamples;
lpModule->nTempo = 6;
lpModule->nBPM = 125;
for (n = 0; n < lpModule->nTracks; n++) {
lpModule->aPanningTable[n] = Header.aPanningTable[n] << 4;
}
/* allocate space for local patterns and patches */
if ((lpModule->aPatternTable = (LPAUDIOPATTERN)
calloc(lpModule->nPatterns, sizeof(AUDIOPATTERN))) == NULL) {
AFreeModuleFile(lpModule);
AIOCloseFile();
return AUDIO_ERROR_NOMEMORY;
}
if ((lpModule->aPatchTable = (LPAUDIOPATCH)
calloc(lpModule->nPatches, sizeof(AUDIOPATCH))) == NULL) {
AFreeModuleFile(lpModule);
AIOCloseFile();
return AUDIO_ERROR_NOMEMORY;
}
/* allocate space for MTM samples and track structures */
if ((lpSampleTable = (LPMTMSAMPLE)
calloc(Header.nSamples, sizeof(MTMSAMPLE))) == NULL) {
AFreeModuleFile(lpModule);
AIOCloseFile();
return AUDIO_ERROR_NOMEMORY;
}
if ((lpTrackTable = (LPMTMTRACK)
calloc(Header.nSeqTracks, sizeof(MTMTRACK))) == NULL) {
free(lpSampleTable);
AFreeModuleFile(lpModule);
AIOCloseFile();
return AUDIO_ERROR_NOMEMORY;
}
/* load MTM sample header structures */
for (n = 0; n < lpModule->nPatches; n++) {
AIOReadFile(lpSampleTable[n].szSampleName,
sizeof(lpSampleTable[n].szSampleName));
AIOReadLong(&lpSampleTable[n].dwLength);
AIOReadLong(&lpSampleTable[n].dwLoopStart);
AIOReadLong(&lpSampleTable[n].dwLoopEnd);
AIOReadChar(&lpSampleTable[n].nFinetune);
AIOReadChar(&lpSampleTable[n].nVolume);
AIOReadChar(&lpSampleTable[n].bFlags);
}
/* load the MTM module order list */
AIOReadFile(lpModule->aOrderTable, 128);
/* load MTM module tracks from disk */
AIOReadFile(lpTrackTable, sizeof(MTMTRACK) * Header.nSeqTracks);
/* build module patterns from tracks */
for (n = 0; n < lpModule->nPatterns; n++) {
AIOReadFile(aPatSeqTable, sizeof(aPatSeqTable));
rc = MTMMakePattern(lpModule->nTracks, Header.nSeqTracks,
&lpModule->aPatternTable[n], aPatSeqTable, lpTrackTable);
if (rc != AUDIO_ERROR_NONE) {
free(lpTrackTable);
free(lpSampleTable);
AFreeModuleFile(lpModule);
AIOCloseFile();
return rc;
}
}
free(lpTrackTable);
/* skip MTM comment message data */
AIOSeekFile(Header.nMesgSize, SEEK_CUR);
/* build module patches and samples structures */
for (n = 0; n < lpModule->nPatches; n++) {
rc = MTMMakeSample(&lpModule->aPatchTable[n], &lpSampleTable[n]);
if (rc != AUDIO_ERROR_NONE) {
free(lpSampleTable);
AFreeModuleFile(lpModule);
AIOCloseFile();
return rc;
}
}
free(lpSampleTable);
*lplpModule = lpModule;
return AUDIO_ERROR_NONE;
}

360
seal-hack/src/nondrv.c Normal file
View File

@@ -0,0 +1,360 @@
/*
* $Id: nondrv.c 1.6 1997/01/09 23:08:57 chasan Exp $
* 1.7 1998/10/24 18:20:54 chasan Exp (Mixer API)
*
* Silence(tm) audio driver.
*
* Copyright (C) 1995-1999 Carlos Hasan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <string.h>
#include "audio.h"
#include "drivers.h"
#ifndef __DPMI__
#include <time.h>
#else
#include "msdos.h"
#define AAD(val) (((val)&15)+10*((val)>>4))
typedef unsigned long time_t;
static time_t time(time_t *t)
{
long secs, val;
/* secs */
OUTB(0x70, 0x00);
val = INB(0x71);
secs = AAD(val);
/* min */
OUTB(0x70, 0x02);
val = INB(0x71);
secs += 60L * AAD(val);
/* hour */
OUTB(0x70, 0x04);
val = INB(0x71);
secs += 60L * 60L * AAD(val);
/* day */
OUTB(0x70, 0x07);
val = INB(0x71);
secs += 24L * 60L * 60L * AAD(val);
/* month */
OUTB(0x70, 0x08);
val = INB(0x71);
secs += 30L * 24L * 60L * 60L * AAD(val);
if (t != NULL) *t = secs;
return secs;
}
#endif
static struct {
LONG dwTimer;
LONG dwTimerAccum;
LONG dwTimerRate;
LPFNAUDIOTIMER lpfnTimerHandler;
} none;
/*
* Silence(tm) audio driver API interface
*/
static UINT AIAPI GetAudioCaps(LPAUDIOCAPS lpCaps)
{
static AUDIOCAPS Caps =
{
AUDIO_PRODUCT_NONE, "Silence",
AUDIO_FORMAT_1M08 | AUDIO_FORMAT_1S08 |
AUDIO_FORMAT_1M16 | AUDIO_FORMAT_1S16 |
AUDIO_FORMAT_2M08 | AUDIO_FORMAT_2S08 |
AUDIO_FORMAT_2M16 | AUDIO_FORMAT_2S16 |
AUDIO_FORMAT_4M08 | AUDIO_FORMAT_4S08 |
AUDIO_FORMAT_4M16 | AUDIO_FORMAT_4S16
};
memcpy(lpCaps, &Caps, sizeof(AUDIOCAPS));
return AUDIO_ERROR_NONE;
}
static UINT AIAPI PingAudio(VOID)
{
return AUDIO_ERROR_NONE;
}
static UINT AIAPI OpenAudio(LPAUDIOINFO lpInfo)
{
memset(&none, 0, sizeof(none));
none.dwTimer = 1000L * time(NULL);
return (lpInfo != NULL) ? AUDIO_ERROR_NONE : AUDIO_ERROR_INVALPARAM;
}
static UINT AIAPI CloseAudio(VOID)
{
return AUDIO_ERROR_NONE;
}
static UINT AIAPI UpdateAudio(UINT nFrames)
{
LONG dwTimer = 1000L * time(NULL);
if ((none.dwTimerAccum += dwTimer - none.dwTimer) >= none.dwTimerRate) {
none.dwTimerAccum -= none.dwTimerRate;
if (none.lpfnTimerHandler != NULL)
none.lpfnTimerHandler();
}
none.dwTimer = dwTimer;
return AUDIO_ERROR_NONE;
}
static UINT AIAPI UpdateAudioSynth(VOID)
{
return AUDIO_ERROR_NONE;
}
static UINT AIAPI SetAudioMixerValue(UINT nChannel, UINT nValue)
{
if (nChannel != AUDIO_MIXER_MASTER_VOLUME &&
nChannel != AUDIO_MIXER_TREBLE &&
nChannel != AUDIO_MIXER_BASS &&
nChannel != AUDIO_MIXER_CHORUS &&
nChannel != AUDIO_MIXER_REVERB)
return AUDIO_ERROR_INVALPARAM;
return AUDIO_ERROR_NONE;
}
static UINT AIAPI OpenVoices(UINT nVoices)
{
if (nVoices < AUDIO_MAX_VOICES) {
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALPARAM;
}
static UINT AIAPI CloseVoices(VOID)
{
return AUDIO_ERROR_NONE;
}
static UINT AIAPI SetAudioCallback(LPFNAUDIOWAVE lpfnAudioWave)
{
if (lpfnAudioWave != NULL) {
}
return AUDIO_ERROR_NONE;
}
static UINT AIAPI SetAudioTimerProc(LPFNAUDIOTIMER lpfnAudioTimer)
{
if (lpfnAudioTimer != NULL) {
none.lpfnTimerHandler = lpfnAudioTimer;
}
return AUDIO_ERROR_NONE;
}
static UINT AIAPI SetAudioTimerRate(UINT nRate)
{
if (nRate >= 0x20 && nRate <= 0xFF) {
/* set timer rate in milliseconds */
none.dwTimerRate = 60000L / (24 * nRate);
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALPARAM;
}
static LONG AIAPI GetAudioDataAvail(VOID)
{
return 0L;
}
static UINT AIAPI CreateAudioData(LPAUDIOWAVE lpWave)
{
if (lpWave != NULL) {
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALPARAM;
}
static UINT AIAPI DestroyAudioData(LPAUDIOWAVE lpWave)
{
if (lpWave != NULL) {
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALPARAM;
}
static UINT AIAPI WriteAudioData(LPAUDIOWAVE lpWave, DWORD dwOffset, UINT nCount)
{
if (lpWave != NULL && lpWave->lpData != NULL) {
if (dwOffset + nCount < lpWave->dwLength) {
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALPARAM;
}
return AUDIO_ERROR_INVALHANDLE;
}
static UINT AIAPI PrimeVoice(UINT nVoice, LPAUDIOWAVE lpWave)
{
if (nVoice < AUDIO_MAX_VOICES && lpWave != NULL) {
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALHANDLE;
}
static UINT AIAPI StartVoice(UINT nVoice)
{
if (nVoice < AUDIO_MAX_VOICES) {
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALHANDLE;
}
static UINT AIAPI StopVoice(UINT nVoice)
{
if (nVoice < AUDIO_MAX_VOICES) {
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALHANDLE;
}
static UINT AIAPI SetVoicePosition(UINT nVoice, LONG dwPosition)
{
if (nVoice < AUDIO_MAX_VOICES) {
if (dwPosition >= AUDIO_MIN_POSITION &&
dwPosition <= AUDIO_MAX_POSITION) {
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALPARAM;
}
return AUDIO_ERROR_INVALHANDLE;
}
static UINT AIAPI SetVoiceFrequency(UINT nVoice, LONG dwFrequency)
{
if (nVoice < AUDIO_MAX_VOICES) {
if (dwFrequency >= AUDIO_MIN_FREQUENCY &&
dwFrequency <= AUDIO_MAX_FREQUENCY) {
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALPARAM;
}
return AUDIO_ERROR_INVALHANDLE;
}
static UINT AIAPI SetVoiceVolume(UINT nVoice, UINT nVolume)
{
if (nVoice < AUDIO_MAX_VOICES) {
if (nVolume < AUDIO_MAX_VOLUME) {
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALPARAM;
}
return AUDIO_ERROR_INVALHANDLE;
}
static UINT AIAPI SetVoicePanning(UINT nVoice, UINT nPanning)
{
if (nVoice < AUDIO_MAX_VOICES) {
if (nPanning < AUDIO_MAX_PANNING) {
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALPARAM;
}
return AUDIO_ERROR_INVALHANDLE;
}
static UINT AIAPI GetVoicePosition(UINT nVoice, LPLONG lpdwPosition)
{
if (nVoice < AUDIO_MAX_VOICES) {
if (lpdwPosition != NULL) {
*lpdwPosition = 0L;
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALPARAM;
}
return AUDIO_ERROR_INVALHANDLE;
}
static UINT AIAPI GetVoiceFrequency(UINT nVoice, LPLONG lpdwFrequency)
{
if (nVoice < AUDIO_MAX_VOICES) {
if (lpdwFrequency != NULL) {
*lpdwFrequency = 0L;
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALPARAM;
}
return AUDIO_ERROR_INVALHANDLE;
}
static UINT AIAPI GetVoiceVolume(UINT nVoice, LPUINT lpnVolume)
{
if (nVoice < AUDIO_MAX_VOICES) {
if (lpnVolume != NULL) {
*lpnVolume = 0;
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALPARAM;
}
return AUDIO_ERROR_INVALHANDLE;
}
static UINT AIAPI GetVoicePanning(UINT nVoice, LPUINT lpnPanning)
{
if (nVoice < AUDIO_MAX_VOICES) {
if (lpnPanning != NULL) {
*lpnPanning = 0;
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALPARAM;
}
return AUDIO_ERROR_INVALHANDLE;
}
static UINT AIAPI GetVoiceStatus(UINT nVoice, LPBOOL lpnStatus)
{
if (nVoice < AUDIO_MAX_VOICES) {
if (lpnStatus != NULL) {
*lpnStatus = 1;
return AUDIO_ERROR_NONE;
}
return AUDIO_ERROR_INVALPARAM;
}
return AUDIO_ERROR_INVALHANDLE;
}
/*
* Silence(tm) audio driver public interface
*/
AUDIOWAVEDRIVER NoneWaveDriver =
{
GetAudioCaps, PingAudio, OpenAudio, CloseAudio,
UpdateAudio, SetAudioCallback
};
AUDIOSYNTHDRIVER NoneSynthDriver =
{
GetAudioCaps, PingAudio, OpenAudio, CloseAudio,
UpdateAudioSynth, OpenVoices, CloseVoices,
SetAudioTimerProc, SetAudioTimerRate, SetAudioMixerValue,
GetAudioDataAvail, CreateAudioData, DestroyAudioData,
WriteAudioData, PrimeVoice, StartVoice, StopVoice,
SetVoicePosition, SetVoiceFrequency, SetVoiceVolume,
SetVoicePanning, GetVoicePosition, GetVoiceFrequency,
GetVoiceVolume, GetVoicePanning, GetVoiceStatus
};
AUDIODRIVER NoneDriver =
{
&NoneWaveDriver, &NoneSynthDriver
};

323
seal-hack/src/os2drv.c Normal file
View File

@@ -0,0 +1,323 @@
/*
* $Id: os2drv.c 1.0 1998/10/18 14:06:31 chasan Exp $
*
* OS/2 MMPM audio driver.
*
* Copyright (C) 1998 by Martin Amodeo <marty@rochester.rr.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <process.h>
#define INCL_DOS
#include <os2.h>
#define INCL_OS2MM
#include <os2me.h>
#define WINAPI
typedef VOID* LPVOID;
typedef CHAR* LPCHAR;
typedef INT* LPINT;
typedef LONG* LPLONG;
typedef BOOL* LPBOOL;
typedef BYTE* LPBYTE;
typedef WORD* LPWORD;
typedef UINT* LPUINT;
typedef DWORD* LPDWORD;
#undef LPSTR
#include "audio.h"
#include "drivers.h"
/*
* OS/2 MMPM driver defines
*/
#define BUFFER_SIZE 15 // buffer length in milliseconds / 2
#define THREAD_STACK_SIZE 32768 // thread stack size in bytes
#define SEMWAIT_OPERATION 9 // Semaphore wait operation for playlist
#define SEMPOST_OPERATION 10 // Semaphore post operation for playlist
/*
* OS/2 MMPM driver global state
*/
static struct {
LPVOID lpBuffer[2];
ULONG nBufferSize;
HEV semNeedsBuffer[2];
HEV semHasBuffer[2];
HEV semAudioPing;
ULONG ulThread;
LPCHAR aThreadStack;
MCI_OPEN_PARMS mop;
LPFNAUDIOWAVE lpfnCallback;
struct {
ULONG operation;
ULONG operand1;
ULONG operand2;
ULONG operand3;
} playlist[8];
} OS2;
/*
* OS/2 MMPM driver API interface
*/
static UINT AIAPI GetAudioCaps(LPAUDIOCAPS lpCaps)
{
static AUDIOCAPS Caps =
{
AUDIO_PRODUCT_OS2MMPM, "OS/2 MMPM",
AUDIO_FORMAT_1M08 | AUDIO_FORMAT_1S08 |
AUDIO_FORMAT_1M16 | AUDIO_FORMAT_1S16 |
AUDIO_FORMAT_2M08 | AUDIO_FORMAT_2S08 |
AUDIO_FORMAT_2M16 | AUDIO_FORMAT_2S16 |
AUDIO_FORMAT_4M08 | AUDIO_FORMAT_4S08 |
AUDIO_FORMAT_4M16 | AUDIO_FORMAT_4S16
};
memcpy(lpCaps, &Caps, sizeof(AUDIOCAPS));
return AUDIO_ERROR_NONE;
}
static UINT AIAPI PingAudio(VOID)
{
return AUDIO_ERROR_NONE;
}
static void ThreadProc(void *data)
{
int i, junk;
for (i = 0; ; i ^= 1) {
/* wait until the buffer needs data */
DosWaitEventSem(OS2.semNeedsBuffer[i], -1);
DosResetEventSem(OS2.semNeedsBuffer[i], &junk);
DosResetEventSem(OS2.semAudioPing, &junk);
/* fill the needed buffer with samples */
DosEnterCritSec();
if (OS2.lpfnCallback != NULL)
(*OS2.lpfnCallback)(OS2.lpBuffer[i], OS2.nBufferSize);
else
memset(OS2.lpBuffer[i], 0, OS2.nBufferSize);
DosExitCritSec();
/* now the buffer has data */
DosPostEventSem(OS2.semAudioPing);
DosPostEventSem(OS2.semHasBuffer[i]);
}
}
static UINT AIAPI OpenAudio(LPAUDIOINFO lpInfo)
{
MCI_WAVE_SET_PARMS wsp;
MCI_PLAY_PARMS mpp;
/* clean the OS/2 driver state */
memset(&OS2, 0, sizeof(OS2));
/* compute the buffer length in bytes */
#if 1
OS2.nBufferSize = ( 266 * lpInfo->nSampleRate / 22050 ) *
(lpInfo->wFormat & AUDIO_FORMAT_16BITS ? 2 : 1) *
(lpInfo->wFormat & AUDIO_FORMAT_STEREO ? 2 : 1);
#else
OS2.nBufferSize = lpInfo->nSampleRate / (1000 / BUFFERSIZE);
if (lpInfo->wFormat & AUDIO_FORMAT_16BITS)
OS2.nBufferSize <<= 1;
if (lpInfo->wFormat & AUDIO_FORMAT_STEREO)
OS2.nBufferSize <<= 1;
#endif
OS2.nBufferSize = (OS2.nBufferSize + 3) & ~3;
/* allocate memory for double buffering */
if ((OS2.lpBuffer[0] = (LPVOID) malloc(OS2.nBufferSize)) == NULL ||
(OS2.lpBuffer[1] = (LPVOID) malloc(OS2.nBufferSize)) == NULL)
return AUDIO_ERROR_NOMEMORY;
if ((OS2.aThreadStack = (LPCHAR) malloc(THREAD_STACK_SIZE)) == NULL )
return AUDIO_ERROR_NOMEMORY;
/* create consumer/producer buffer semaphores */
DosCreateEventSem("\\SEM32\\Buffer1NeedsData",
&OS2.semNeedsBuffer[0], DC_SEM_SHARED, 1);
DosCreateEventSem("\\SEM32\\Buffer2NeedsData",
&OS2.semNeedsBuffer[1], DC_SEM_SHARED, 1);
DosCreateEventSem("\\SEM32\\Buffer1HasData",
&OS2.semHasBuffer[0], DC_SEM_SHARED, 0);
DosCreateEventSem("\\SEM32\\Buffer2HasData",
&OS2.semHasBuffer[1], DC_SEM_SHARED, 0);
/* Ping semaphore for synchronization of streamed audio */
DosCreateEventSem("\\SEM32\\AudioPing",
&OS2.semAudioPing, DC_SEM_SHARED, 0);
/* create MCI audio playlist commands */
/* wait until first buffer has data */
OS2.playlist[0].operation = SEMWAIT_OPERATION;
OS2.playlist[0].operand1 = OS2.semHasBuffer[0];
OS2.playlist[0].operand2 = -1;
OS2.playlist[0].operand3 = 0;
/* play the first buffer data */
OS2.playlist[1].operation = DATA_OPERATION;
OS2.playlist[1].operand1 = (long) OS2.lpBuffer[0];
OS2.playlist[1].operand2 = OS2.nBufferSize;
OS2.playlist[1].operand3 = 0;
/* tell first buffer needs data */
OS2.playlist[2].operation = SEMPOST_OPERATION;
OS2.playlist[2].operand1 = OS2.semNeedsBuffer[0];
OS2.playlist[2].operand2 = 0;
OS2.playlist[2].operand3 = 0;
/* wait until second buffer has data */
OS2.playlist[3].operation = SEMWAIT_OPERATION;
OS2.playlist[3].operand1 = OS2.semHasBuffer[1];
OS2.playlist[3].operand2 = -1;
OS2.playlist[3].operand3 = 0;
/* play the second buffer data */
OS2.playlist[4].operation = DATA_OPERATION;
OS2.playlist[4].operand1 = (long) OS2.lpBuffer[1];
OS2.playlist[4].operand2 = OS2.nBufferSize;
OS2.playlist[4].operand3 = 0;
/* tell second buffer needs data */
OS2.playlist[5].operation = SEMPOST_OPERATION;
OS2.playlist[5].operand1 = OS2.semNeedsBuffer[1];
OS2.playlist[5].operand2 = 0;
OS2.playlist[5].operand3 = 0;
/* branch to the first playlist entry */
OS2.playlist[6].operation = BRANCH_OPERATION;
OS2.playlist[6].operand1 = 0;
OS2.playlist[6].operand2 = 0; // goto OS2.playlist[0]
OS2.playlist[6].operand3 = 0;
/* exit the playlist */
OS2.playlist[7].operation = EXIT_OPERATION;
/* open the MCI waveform audio device */
OS2.mop.usDeviceID = 0;
OS2.mop.pszDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO_NAME;
OS2.mop.pszElementName = (LPCHAR) &OS2.playlist[0];
if (mciSendCommand(0, MCI_OPEN, MCI_WAIT | MCI_OPEN_SHAREABLE |
MCI_OPEN_PLAYLIST, &OS2.mop, 0) != MCIERR_SUCCESS)
return AUDIO_ERROR_DEVICEBUSY;
/* setup the MCI waveform device parameters */
wsp.hwndCallback = 0;
wsp.ulSamplesPerSec = lpInfo->nSampleRate;
wsp.usBitsPerSample = (lpInfo->wFormat & AUDIO_FORMAT_16BITS ? 16 : 8);
wsp.usChannels = (lpInfo->wFormat & AUDIO_FORMAT_STEREO ? 2 : 1);
if (mciSendCommand(OS2.mop.usDeviceID, MCI_SET,
MCI_WAIT |
MCI_WAVE_SET_SAMPLESPERSEC |
MCI_WAVE_SET_BITSPERSAMPLE |
MCI_WAVE_SET_CHANNELS,
&wsp, 0) != MCIERR_SUCCESS)
return AUDIO_ERROR_DEVICEBUSY;
/* start the OS/2 driver thread routine */
OS2.ulThread = _beginthread(ThreadProc, OS2.aThreadStack,
THREAD_STACK_SIZE, NULL);
DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, OS2.ulThread);
/* start playing the MCI audio device */
mpp.hwndCallback = 0;
mpp.ulFrom = 0;
if (mciSendCommand(OS2.mop.usDeviceID, MCI_PLAY,
0, &mpp, 0) != MCIERR_SUCCESS)
return AUDIO_ERROR_DEVICEBUSY;
return AUDIO_ERROR_NONE;
}
static UINT AIAPI CloseAudio(VOID)
{
MCI_GENERIC_PARMS mgp;
/* kill the OS/2 driver thread routine */
DosKillThread(OS2.ulThread);
/* let the branch fall through to the exit function */
OS2.playlist[6].operand2 = 7;
/* "fill" the buffers to unlock the playlist */
DosPostEventSem(OS2.semHasBuffer[0]);
DosPostEventSem(OS2.semHasBuffer[1]);
/* Unblock any threads that may be synchronizing */
DosPostEventSem(OS2.semAudioPing);
/* close the MCI waveform audio device */
mgp.hwndCallback = 0;
mciSendCommand(OS2.mop.usDeviceID, MCI_CLOSE, MCI_WAIT, &mgp, 0);
/* destroy the read/write buffer semaphores */
DosCloseEventSem(OS2.semNeedsBuffer[0]);
DosCloseEventSem(OS2.semNeedsBuffer[1]);
DosCloseEventSem(OS2.semHasBuffer[0]);
DosCloseEventSem(OS2.semHasBuffer[1]);
/* release the memory buffers */
if (OS2.lpBuffer[0] != NULL)
free(OS2.lpBuffer[0]);
if (OS2.lpBuffer[1] != NULL)
free(OS2.lpBuffer[1]);
if (OS2.aThreadStack != NULL)
free(OS2.aThreadStack);
/* clean the OS/2 driver state */
memset(&OS2, 0, sizeof(OS2));
return AUDIO_ERROR_NONE;
}
static UINT AIAPI UpdateAudio(UINT nFrames)
{
ULONG junk;
DosResetEventSem(OS2.semAudioPing, &junk);
DosWaitEventSem(OS2.semAudioPing, -1);
return AUDIO_ERROR_NONE;
}
static UINT AIAPI SetAudioCallback(LPFNAUDIOWAVE lpfnAudioWave)
{
/* set the user lpfnCallback routine */
OS2.lpfnCallback = lpfnAudioWave;
return AUDIO_ERROR_NONE;
}
/*
* OS/2 MMPM driver public interface
*/
AUDIOWAVEDRIVER OS2MMPMWaveDriver =
{
GetAudioCaps, PingAudio, OpenAudio, CloseAudio,
UpdateAudio, SetAudioCallback
};
AUDIODRIVER OS2MMPMDriver =
{
&OS2MMPMWaveDriver, NULL
};

183
seal-hack/src/osxdrv.c Normal file
View File

@@ -0,0 +1,183 @@
/*
* $Id: lnxdrv.c 1.5 1996/08/05 18:51:19 chasan released $
*
* SDL audio driver. Turns SEAL into a mixer on top of SDL.
*
* Copyright 2002 Greg Velichansky (hmaon@bumba.net)
*
* Based in part on the Linux Voxware driver,
* Copyright (C) 1995-1999 Carlos Hasan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include "SDL.h"
#include "audio.h"
#include "drivers.h"
/*
* fragments defines
*/
#define NUMFRAGS 16
#define FRAGSIZE 11
#define BUFFERSIZE (1 << FRAGSIZE)
/*
* configuration structure
*/
static struct AudioStruct {
SDL_AudioSpec desired, spec;
BYTE aBuffer[BUFFERSIZE*4];
LPFNAUDIOWAVE lpfnAudioWave;
WORD wFormat;
} Audio;
/*
* Linux driver API interface
*/
static UINT AIAPI GetAudioCaps(LPAUDIOCAPS lpCaps)
{
static AUDIOCAPS Caps =
{
AUDIO_PRODUCT_LINUX, "MacOS X - SDL",
AUDIO_FORMAT_1M08 | AUDIO_FORMAT_1S08 |
AUDIO_FORMAT_1M16 | AUDIO_FORMAT_1S16 |
AUDIO_FORMAT_2M08 | AUDIO_FORMAT_2S08 |
AUDIO_FORMAT_2M16 | AUDIO_FORMAT_2S16 |
AUDIO_FORMAT_4M08 | AUDIO_FORMAT_4S08 |
AUDIO_FORMAT_4M16 | AUDIO_FORMAT_4S16
};
memcpy(lpCaps, &Caps, sizeof(AUDIOCAPS));
return AUDIO_ERROR_NONE;
}
static UINT AIAPI PingAudio(VOID)
{
return 0;
/* return (SDL_INIT_AUDIO == SDL_WasInit(SDL_INIT_AUDIO)); */
}
static void updatecallback(void *userdata, Uint8 *stream, int len);
static UINT AIAPI OpenAudio(LPAUDIOINFO lpInfo)
{
int nBitsPerSample, nStereoOn, nSampleRate, nFrags;
memset(&Audio, 0, sizeof(Audio));
if (!SDL_WasInit(SDL_INIT_EVERYTHING))
{
SDL_Init(SDL_INIT_AUDIO);
} else
{
if (!SDL_WasInit(SDL_INIT_AUDIO) && SDL_InitSubSystem(SDL_INIT_AUDIO))
return AUDIO_ERROR_NODEVICE;
}
if (SDL_INIT_AUDIO != SDL_WasInit(SDL_INIT_AUDIO))
return AUDIO_ERROR_NODEVICE;
nBitsPerSample = lpInfo->wFormat & AUDIO_FORMAT_16BITS ? 16 : 8;
nStereoOn = lpInfo->wFormat & AUDIO_FORMAT_STEREO ? 1 : 0;
/*nSampleRate = lpInfo->nSampleRate;*/
Audio.desired.freq = lpInfo->nSampleRate;
Audio.desired.samples = 512;
Audio.desired.channels = nStereoOn ? 2 : 1;
Audio.desired.format = (lpInfo->wFormat & AUDIO_FORMAT_16BITS) ? AUDIO_U16SYS : AUDIO_U8;
Audio.desired.userdata = (void*)&Audio;
Audio.desired.callback = updatecallback;
SDL_OpenAudio(&(Audio.desired), &(Audio.spec));
/* we should probably do something here... blah... whatever :/ */
/* setup number and size of buffer fragments */
/*nFrags = (NUMFRAGS << 16) + (FRAGSIZE);
ioctl(Audio.nHandle, SNDCTL_DSP_SETFRAGMENT, &nFrags);*/
/* setup audio playback encoding format and sampling frequency */
/*if (ioctl(Audio.nHandle, SNDCTL_DSP_SAMPLESIZE, &nBitsPerSample) < 0 ||
ioctl(Audio.nHandle, SNDCTL_DSP_STEREO, &nStereoOn) < 0 ||
ioctl(Audio.nHandle, SNDCTL_DSP_SPEED, &nSampleRate) < 0) {
close(Audio.nHandle);
return AUDIO_ERROR_BADFORMAT;
}*/
/*Audio.wFormat = lpInfo->wFormat;*/
return AUDIO_ERROR_NONE;
}
static UINT AIAPI CloseAudio(VOID)
{
SDL_CloseAudio();
return AUDIO_ERROR_NONE;
}
static UINT AIAPI UpdateAudio(UINT nFrames)
{
/* compute frame size */
/*if (Audio.wFormat & AUDIO_FORMAT_16BITS) nFrames <<= 1;
if (Audio.wFormat & AUDIO_FORMAT_STEREO) nFrames <<= 1;
if (nFrames <= 0 || nFrames > sizeof(Audio.aBuffer))
nFrames = sizeof(Audio.aBuffer);*/
/* send PCM samples to the DSP audio device */
/*if (Audio.lpfnAudioWave != NULL) {
Audio.lpfnAudioWave(Audio.aBuffer, nFrames);
write(Audio.nHandle, Audio.aBuffer, nFrames);
}*/
SDL_PauseAudio(0); /* the only use I can think of for UpdateAudio() ...*/
return AUDIO_ERROR_NONE;
}
static void updatecallback(void *userdata, Uint8 *stream, int len)
{
struct AudioStruct *aud = userdata;
/* maybe this isn't necessary, we know where Audio is, after all... */
aud->lpfnAudioWave(stream, len); /* God speed... */
}
static UINT AIAPI SetAudioCallback(LPFNAUDIOWAVE lpfnAudioWave)
{
/* set up DSP audio device user's callback function */
Audio.lpfnAudioWave = lpfnAudioWave;
return AUDIO_ERROR_NONE;
}
/*
* Linux driver public interface
*/
AUDIOWAVEDRIVER MacOSXWaveDriver =
{
GetAudioCaps, PingAudio, OpenAudio, CloseAudio,
UpdateAudio, SetAudioCallback
};
AUDIODRIVER MacOSXDriver =
{
&MacOSXWaveDriver, NULL
};

586
seal-hack/src/pasdrv.c Normal file
View File

@@ -0,0 +1,586 @@
/*
* $Id: pasdrv.c 1.5 1996/08/05 18:51:19 chasan released $
*
* Pro Audio Spectrum series audio driver.
*
* Copyright (C) 1995-1999 Carlos Hasan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <string.h>
#include "audio.h"
#include "drivers.h"
#include "msdos.h"
/*
* Pro Audio Spectrum cards default I/O base addresses
*/
#define PAS_DEFAULT_BASE 0x0388 /* default base port address */
#define PAS_ALT_BASE_1 0x0384 /* first alternative base address */
#define PAS_ALT_BASE_2 0x038C /* second alternative base address */
#define PAS_ALT_BASE_3 0x0288 /* third alternative base address */
/*
* Pro Audio Spectrum direct register offsets
*/
#define PAS_AUDIOMXR 0x0B88 /* audio mixer control register */
#define PAS_AUDIOFILT 0x0B8A /* audio filter control register */
#define PAS_INTRSTAT 0x0B89 /* interrupt status register */
#define PAS_INTRCTLR 0x0B8B /* interrupt control register */
#define PAS_PCMDATA 0x0F88 /* PCM data PIO register */
#define PAS_CROSSCHANNEL 0x0F8A /* cross channel control register */
#define PAS_SAMPLERATE 0x1388 /* sample rate timer register */
#define PAS_SAMPLECNT 0x1389 /* sample count register */
#define PAS_SPKRTMR 0x138A /* local speaker timer address */
#define PAS_TMRCTLR 0x138B /* local timer control register */
/*
* Pro Audio Spectrum PAS2/CDPC (digital ASIC) direct register offsets
*/
#define PAS_MASTERCHIPR 0xFF88 /* master chip revision */
#define PAS_ENHSCSI 0x7F89 /* Enhanced SCSI detect port */
#define PAS_SYSCONFIG2 0x8389 /* system configuration register */
#define PAS_COMPATREGE 0xF788 /* compatible register enable */
#define PAS_MASTERMODRD 0xFF8B /* master mode read */
#define PAS_SLAVEMODRD 0xEF8B /* slave mode read */
/*
* Interrupt control register bit fields
*/
#define IC_INTRMASK 0x1F /* interrupt mask bit fields */
#define IC_REVBITS 0xE0 /* revision mask bit fields */
#define IC_LEFTFM 0x01 /* left FM interrupt enable */
#define IC_RIGHTFM 0x02 /* right FM interrupt enable */
#define IC_SAMPRATE 0x04 /* sample rate timer intr enable */
#define IC_SAMPBUFF 0x08 /* sample buffer timer intr enable */
#define IC_MIDI 0x10 /* MIDI interrupt enable */
/*
* Interrupt status register bit fields
*/
#define IS_INTRMASK 0x1F /* interrupts mask bit fields */
#define IS_LEFTFM 0x01 /* FM left interrupt active */
#define IS_RIGHTFM 0x02 /* FM right interrupt active */
#define IS_SAMPRATE 0x04 /* sample rate interrupt active */
#define IS_SAMPBUFF 0x08 /* sample buffer interrupt active */
#define IS_MIDI 0x10 /* MIDI interrupt active */
#define IS_PCMLR 0x20 /* PCM channel interrupt active */
#define IS_ACTIVE 0x40 /* hardware is active */
#define IS_CLIPPING 0x80 /* sample clipping has occured */
/*
* Audio filter select register bit fields
*/
#define AF_FILTMASK 0x1F /* filter select and decode bits */
#define AF_FILT1 0x01 /* select 17897 Hz filter */
#define AF_FILT2 0x02 /* select 15909 Hz filter */
#define AF_FILT3 0x09 /* select 11931 Hz filter */
#define AF_FILT4 0x11 /* select 8948 Hz filter */
#define AF_FILT5 0x19 /* select 5965 Hz filter */
#define AF_FILT6 0x04 /* select 2982 Hz filter */
#define AF_UNMUTE 0x20 /* filter unmute control */
#define AF_SAMPRATE 0x40 /* sample rate timer enable */
#define AF_SAMPBUFF 0x80 /* sample buffer counter enable */
/*
* Cross channel control register bit fields
*/
#define CC_CROSSMASK 0x0F /* cross channels bit fields */
#define CC_PCMMASK 0xF0 /* PCM/DMA control bit fields */
#define CC_R2R 0x01 /* cross channel right->right */
#define CC_L2R 0x02 /* cross channel left->right */
#define CC_R2L 0x04 /* cross channel right->left */
#define CC_L2L 0x08 /* cross channel left->left */
#define CC_DAC 0x10 /* select DAC output mode */
#define CC_ADC 0x00 /* select ADC input mode */
#define CC_MONO 0x20 /* select mono mode */
#define CC_STEREO 0x00 /* select stereo mode */
#define CC_ENAPCM 0x40 /* enable PCM machine */
#define CC_DRQ 0x80 /* enable DMA transfers */
/*
* Local timer control register bit fields
*/
#define TC_BIN 0x00 /* select binary counting mode */
#define TC_BCD 0x01 /* select BCD counting mode */
#define TC_SQUAREWAVE 0x04 /* select square wave generator */
#define TC_RATE 0x06 /* select rate generator */
#define TC_16BIT 0x30 /* set first LSB and then MSB */
#define TC_SAMPRATE 0x00 /* select sample rate timer */
#define TC_SAMPBUFF 0x40 /* select buffer counter timer */
#define TC_PCSPKR 0x80 /* select PC speaker counter timer */
/*
* Sample size and oversampling register bit fields
*/
#define SC2_OVRSMP 0x03 /* oversampling bit fields */
#define SC2_OVRSMP1X 0x00 /* select over sampling rate to 1X */
#define SC2_OVRSMP2X 0x01 /* select over sampling rate to 2X */
#define SC2_OVRSMP4X 0x03 /* select over sampling rate to 4X */
#define SC2_16BIT 0x04 /* select 16 bit audio */
#define SC2_12BIT 0x08 /* select 12 bit interleaving */
/*
* Compatible register enable bit fields
*/
#define CP_MPUEMUL 0x01 /* MPU-401 emulation enabled */
#define CP_SBEMUL 0x02 /* SB emulation enabled */
/*
* Slave mode read register bit fields
*/
#define SMRD_DRVTYPE 0x03 /* driver interface type */
#define SMRD_FMTYPE 0x04 /* 3812(0) or OPL3(1) FM chip */
#define SMRD_DACTYPE 0x08 /* 8-bit DAC(0) or 16-bit DAC(1) */
#define SMRD_IMIDI 0x10 /* use internal MIDI */
#define SMRD_SWREP 0x80 /* switch is auto repeating */
/*
* Master mode read register bit fields
*/
#define MMRD_ATPS2 0x01 /* PS2(0) or AT(1) bus */
#define MMRD_TMREMUL 0x02 /* timer emulation enabled */
#define MMRD_MSMD 0x04 /* master(0) or slave(1) mode */
#define MMRD_SLAVE 0x08 /* slave power on or device present */
#define MMRD_ATTIM 0x10 /* XT/AT timing */
#define MMRD_MSTREV 0xE0 /* master revision level */
/*
* Pro Audio Spectrum product feature bits
*/
#define MVA508 0x0001 /* MVA508(1) or National(0) */
#define MVPS2 0x0002 /* PS2(1) or AT(0) bus */
#define MVSLAVE 0x0004 /* CDPC slave device */
#define MVSCSI 0x0008 /* SCSI interface */
#define MVENHSCSI 0x0010 /* Enhanced SCSI interface */
#define MVSONY 0x0020 /* Sony 535 interface */
#define MVDAC16 0x0040 /* 16 bit DAC */
#define MVSBEMUL 0x0080 /* SB hardware emulation */
#define MVMPUEMUL 0x0100 /* MPU-401 hardware emulation */
#define MVOPL3 0x0200 /* OPL3(1) or 3812(0) chip */
#define MV101 0x0400 /* MV101 ASIC */
#define MV101_REV_BITS 0x3800 /* MV101 revision bit fields */
/*
* Pro Audio Spectrum product feature lists
*/
#define PRODUCT_PROAUDIO (MVSCSI)
#define PRODUCT_PROPLUS (MV101|MVSCSI|MVENHSCSI|MVSBEMUL|MVOPL3)
#define PRODUCT_PRO16 (MV101|MVA508|MVSCSI|MVENHSCSI|MVSBEMUL|MVDAC16|MVOPL3)
#define PRODUCT_CDPC (MV101|MVSLAVE|MVSONY|MVSBEMUL|MVDAC16|MVOPL3)
#define PRODUCT_CAREBITS (MVA508|MVDAC16|MVOPL3|MV101)
/*
* PAS clock source frequency and buffer size
*/
#define CLOCKFREQ 1193180 /* clock frequency in Hertz */
#define BUFFERSIZE 50 /* buffer length in milliseconds */
#define BUFFRAGSIZE 32 /* buffer fragment size in bytes */
/*
* Pro Audio Spectrum configuration structure
*/
static struct {
WORD wFormat; /* playback encoding format */
WORD nSampleRate; /* sampling frequency */
WORD wId; /* audio device identifier */
WORD wProduct; /* product feature bits */
WORD wPort; /* device base port */
BYTE nIrqLine; /* interrupt line */
BYTE nDmaChannel; /* output DMA channel */
LPBYTE lpBuffer; /* DMA buffer address */
UINT nBufferSize; /* DMA buffer length */
UINT nPosition; /* DMA buffer playing position */
LPFNAUDIOWAVE lpfnAudioWave; /* user callback routine */
} PAS;
/*
* Pro Audio Spectrum low level routines
*/
static VOID PASPortB(WORD nIndex, BYTE bData)
{
OUTB(PAS.wPort ^ nIndex, bData);
}
static BYTE PASPortRB(WORD nIndex)
{
return INB(PAS.wPort ^ nIndex);
}
static UINT PASProbe(VOID)
{
DWORD dwSampleRate;
BYTE nRevId, mmrd, smrd;
/*
* Probe PAS hardware checking the revision ID code from
* the interrupt mask register (it should be read only).
*/
if ((nRevId = PASPortRB(PAS_INTRCTLR)) == 0xFF)
return AUDIO_ERROR_NODEVICE;
PASPortB(PAS_INTRCTLR, nRevId ^ IC_REVBITS);
if (PASPortRB(PAS_INTRCTLR) != nRevId)
return AUDIO_ERROR_NODEVICE;
/*
* Checks the installed hardware for all the feature bits,
* and determine which PAS hardware card is present.
*/
PAS.wProduct = MVSCSI;
if ((nRevId & IC_REVBITS) != 0x00) {
/* all second generation PAS cards use MV101 and have SB emulation */
PAS.wProduct |= (MVSBEMUL | MV101);
/* determine if the enhanced SCSI interface is present */
PASPortB(PAS_ENHSCSI, 0x00);
if (!(PASPortRB(PAS_ENHSCSI) & 0x01))
PAS.wProduct |= MVENHSCSI;
/* determine AT/PS2, CDPC slave mode */
mmrd = PASPortRB(PAS_MASTERMODRD);
if (!(mmrd & MMRD_ATPS2))
PAS.wProduct |= MVPS2;
if (mmrd & MMRD_MSMD)
PAS.wProduct |= MVSLAVE;
/* merge in the chip revision level */
PAS.wProduct |= (WORD)(PASPortRB(PAS_MASTERCHIPR) & 0x0F) << 11;
/* determine CDROM type, FM chip, 8/16 bit DAC, and mixer */
smrd = PASPortRB(PAS_SLAVEMODRD);
if (smrd & SMRD_DACTYPE)
PAS.wProduct |= MVDAC16;
if (smrd & SMRD_FMTYPE)
PAS.wProduct |= MVOPL3;
if ((PAS.wProduct & (MVSLAVE | MVDAC16)) == MVDAC16)
PAS.wProduct |= MVA508;
if ((smrd & SMRD_DRVTYPE) == 2) {
PAS.wProduct &= ~(MVSCSI | MVENHSCSI);
PAS.wProduct |= MVSONY;
}
/* determine if MPU-401 emulation is active */
if (PASPortRB(PAS_COMPATREGE) & CP_MPUEMUL)
PAS.wProduct |= MVMPUEMUL;
}
/*
* Assume we have a PAS16 compatible card if the MV101 ASIC
* chip and the 16-bit DAC are both present.
*/
PAS.wId = (PAS.wProduct & (MV101 | MVDAC16)) == (MV101 | MVDAC16) ?
AUDIO_PRODUCT_PAS16 : AUDIO_PRODUCT_PAS;
/*
* Check out playback encoding format and sampling
* frequencies for the specified PAS sound card.
*/
if (PAS.wId != AUDIO_PRODUCT_PAS16)
PAS.wFormat &= ~AUDIO_FORMAT_16BITS;
if (PAS.nSampleRate < 5000)
PAS.nSampleRate = 5000;
if (PAS.nSampleRate > 44100)
PAS.nSampleRate = 44100;
/* get actual sampling frequency supported by hardware */
dwSampleRate = PAS.nSampleRate;
if (PAS.wFormat & AUDIO_FORMAT_STEREO)
dwSampleRate <<= 1;
dwSampleRate = CLOCKFREQ / (CLOCKFREQ / dwSampleRate);
if (PAS.wFormat & AUDIO_FORMAT_STEREO)
dwSampleRate >>= 1;
PAS.nSampleRate = dwSampleRate;
return AUDIO_ERROR_NONE;
}
static VOID PASStartPlayback(VOID)
{
DWORD nCount;
/*
* Setup the DMA controller channel for playback in
* auto init mode and start the PCM state machine.
*/
DosSetupChannel(PAS.nDmaChannel, DMA_WRITE | DMA_AUTOINIT, 0);
/* flush pending PCM interrupts writting interrupt status register */
PASPortB(PAS_INTRSTAT, 0x00);
/*
* Disable buffer counter and timer rate gates, and disable
* PAS16 output (these gates MUST be disabled before programming
* the timers).
*/
PASPortB(PAS_AUDIOFILT, AF_FILT1);
/*
* Disable DMA and PCM state machine (the time rate must
* be initialized BEFORE enabling the PCM state machine).
*/
PASPortB(PAS_CROSSCHANNEL, CC_DAC | CC_L2L | CC_R2R);
/*
* Set the PCM sample rate timer register (select rate timer,
* enable 16 bit timer, select rate generator, and set
* binary counting mode).
*/
nCount = PAS.nSampleRate;
if (PAS.wFormat & AUDIO_FORMAT_STEREO)
nCount <<= 1;
nCount = CLOCKFREQ / nCount;
PASPortB(PAS_TMRCTLR, TC_16BIT | TC_RATE | TC_SAMPRATE | TC_BIN);
PASPortB(PAS_SAMPLERATE, LOBYTE(nCount));
PASPortB(PAS_SAMPLERATE, HIBYTE(nCount));
/*
* Set the PCM sample buffer counter register (select buffer
* counter, enable 16 bit timer, select square wave generator
* and set binary counting mode).
*/
nCount = PAS.nBufferSize;
if (PAS.wFormat & AUDIO_FORMAT_16BITS) {
if (PAS.nDmaChannel <= 3)
nCount <<= 1;
}
else {
if (PAS.nDmaChannel >= 4)
nCount >>= 1;
}
PASPortB(PAS_TMRCTLR, TC_16BIT | TC_SQUAREWAVE | TC_SAMPBUFF | TC_BIN);
PASPortB(PAS_SAMPLECNT, LOBYTE(nCount));
PASPortB(PAS_SAMPLECNT, HIBYTE(nCount));
/*
* Setup 8/16-bit linear encoding format for playback
* (only possible for cards with the MV101 ASIC chip)
*/
if (PAS.wProduct & MV101) {
PASPortB(PAS_SYSCONFIG2, (PASPortRB(PAS_SYSCONFIG2) & ~SC2_16BIT) |
(PAS.wFormat & AUDIO_FORMAT_16BITS ? SC2_16BIT : 0x00));
}
/*
* Select mono/stereo mode and enable DMA and PCM state machine
* (DMA enable, disable PCM, DAC mode, L->L and R->R connections).
*/
PASPortB(PAS_CROSSCHANNEL, CC_DRQ | CC_DAC | CC_L2L | CC_R2R |
(PAS.wFormat & AUDIO_FORMAT_STEREO ? CC_STEREO : CC_MONO));
/* enable PCM state machine */
PASPortB(PAS_CROSSCHANNEL, PASPortRB(PAS_CROSSCHANNEL) | CC_ENAPCM);
/*
* Enable buffer counter and timer rate gates, and enable PAS output
* (enable gates and PAS16 output, select 17897 Hz filter).
*/
PASPortB(PAS_AUDIOFILT, AF_SAMPBUFF | AF_SAMPRATE | AF_UNMUTE | AF_FILT1);
}
static VOID PASStopPlayback(VOID)
{
/* disable buffer counter and timer rate gates and PAS16 output */
PASPortB(PAS_AUDIOFILT, AF_FILT1);
/* set back to 8 bit audio output */
if (PAS.wProduct & MV101) {
PASPortB(PAS_SYSCONFIG2, PASPortRB(PAS_SYSCONFIG2) & ~SC2_16BIT);
}
/* disable sample buffer interrupt */
PASPortB(PAS_INTRCTLR, PASPortRB(PAS_INTRCTLR) & ~IC_SAMPBUFF);
/* select mono mode, DAC mode, disable DMA and PCM state machine */
PASPortB(PAS_CROSSCHANNEL, CC_DAC | CC_L2L | CC_R2R);
/* reset DMA controller channel */
DosDisableChannel(PAS.nDmaChannel);
}
static UINT PASPing(WORD wPort)
{
static DOSREGS r;
/*
* Check if a PAS card is present making sure MVSOUND.SYS
* is loaded in memory, this is the way to know if the
* hardware is actually present.
*/
memset(&r, 0, sizeof(r));
r.ax = 0xBC00;
r.bx = 0x3F3F;
r.cx = 0x0000;
r.dx = 0x0000;
DosIntVector(0x2F, &r);
if ((r.bx ^ r.cx ^ r.dx) == 0x4D56) {
/* get the MVSOUND.SYS specified DMA and IRQ channels */
r.ax = 0xBC04;
DosIntVector(0x2F, &r);
PAS.wPort = wPort ^ PAS_DEFAULT_BASE;
PAS.nIrqLine = LOBYTE(r.cx);
PAS.nDmaChannel = LOBYTE(r.bx);
return PASProbe();
}
return AUDIO_ERROR_NODEVICE;
}
/*
* Pro Audio Spectrum driver API interface
*/
static UINT AIAPI GetAudioCaps(LPAUDIOCAPS lpCaps)
{
static AUDIOCAPS Caps =
{
AUDIO_PRODUCT_PAS, "Pro Audio Spectrum",
AUDIO_FORMAT_1M08 | AUDIO_FORMAT_1S08 |
AUDIO_FORMAT_2M08 | AUDIO_FORMAT_2S08 |
AUDIO_FORMAT_4M08 | AUDIO_FORMAT_4S08
};
static AUDIOCAPS Caps16 =
{
AUDIO_PRODUCT_PAS16, "Pro Audio Spectrum 16",
AUDIO_FORMAT_1M08 | AUDIO_FORMAT_1S08 |
AUDIO_FORMAT_1M16 | AUDIO_FORMAT_1S16 |
AUDIO_FORMAT_2M08 | AUDIO_FORMAT_2S08 |
AUDIO_FORMAT_2M16 | AUDIO_FORMAT_2S16 |
AUDIO_FORMAT_4M08 | AUDIO_FORMAT_4S08 |
AUDIO_FORMAT_4M16 | AUDIO_FORMAT_4S16
};
memcpy(lpCaps, PAS.wId != AUDIO_PRODUCT_PAS16 ?
&Caps : &Caps16, sizeof(AUDIOCAPS));
return AUDIO_ERROR_NONE;
}
static UINT AIAPI PingAudio(VOID)
{
if (!PASPing(PAS_DEFAULT_BASE))
return AUDIO_ERROR_NONE;
if (!PASPing(PAS_ALT_BASE_1))
return AUDIO_ERROR_NONE;
if (!PASPing(PAS_ALT_BASE_2))
return AUDIO_ERROR_NONE;
if (!PASPing(PAS_ALT_BASE_3))
return AUDIO_ERROR_NONE;
return AUDIO_ERROR_NODEVICE;
}
static UINT AIAPI OpenAudio(LPAUDIOINFO lpInfo)
{
DWORD dwBytesPerSecond;
memset(&PAS, 0, sizeof(PAS));
/*
* Initialize PAS16 configuration parameters
* and check whether we have such a card.
*/
PAS.wFormat = lpInfo->wFormat;
PAS.nSampleRate = lpInfo->nSampleRate;
if (PingAudio())
return AUDIO_ERROR_NODEVICE;
/* refresh configuration parameters */
lpInfo->wFormat = PAS.wFormat;
lpInfo->nSampleRate = PAS.nSampleRate;
/*
* Allocate and clean DMA channel buffer for playback
*/
dwBytesPerSecond = PAS.nSampleRate;
if (PAS.wFormat & AUDIO_FORMAT_16BITS)
dwBytesPerSecond <<= 1;
if (PAS.wFormat & AUDIO_FORMAT_STEREO)
dwBytesPerSecond <<= 1;
PAS.nBufferSize = dwBytesPerSecond / (1000 / BUFFERSIZE);
PAS.nBufferSize = (PAS.nBufferSize + BUFFRAGSIZE) & -BUFFRAGSIZE;
if (DosAllocChannel(PAS.nDmaChannel, PAS.nBufferSize))
return AUDIO_ERROR_NOMEMORY;
if ((PAS.lpBuffer = DosLockChannel(PAS.nDmaChannel)) != NULL) {
memset(PAS.lpBuffer, PAS.wFormat & AUDIO_FORMAT_16BITS ?
0x00 : 0x80, PAS.nBufferSize);
DosUnlockChannel(PAS.nDmaChannel);
}
/* start playback with the PAS16 PCM state machine */
PASStartPlayback();
return AUDIO_ERROR_NONE;
}
static UINT AIAPI CloseAudio(VOID)
{
PASStopPlayback();
DosFreeChannel(PAS.nDmaChannel);
return AUDIO_ERROR_NONE;
}
static UINT AIAPI UpdateAudio(UINT nFrames)
{
int nBlockSize, nSize;
if (PAS.wFormat & AUDIO_FORMAT_16BITS) nFrames <<= 1;
if (PAS.wFormat & AUDIO_FORMAT_STEREO) nFrames <<= 1;
if (nFrames <= 0 || nFrames > PAS.nBufferSize)
nFrames = PAS.nBufferSize;
if ((PAS.lpBuffer = DosLockChannel(PAS.nDmaChannel)) != NULL) {
nBlockSize = PAS.nBufferSize - PAS.nPosition -
DosGetChannelCount(PAS.nDmaChannel);
if (nBlockSize < 0)
nBlockSize += PAS.nBufferSize;
if (nBlockSize > nFrames)
nBlockSize = nFrames;
nBlockSize &= -BUFFRAGSIZE;
while (nBlockSize != 0) {
nSize = PAS.nBufferSize - PAS.nPosition;
if (nSize > nBlockSize)
nSize = nBlockSize;
if (PAS.lpfnAudioWave != NULL) {
PAS.lpfnAudioWave(&PAS.lpBuffer[PAS.nPosition], nSize);
}
else {
memset(&PAS.lpBuffer[PAS.nPosition],
PAS.wFormat & AUDIO_FORMAT_16BITS ?
0x00 : 0x80, nSize);
}
if ((PAS.nPosition += nSize) >= PAS.nBufferSize)
PAS.nPosition -= PAS.nBufferSize;
nBlockSize -= nSize;
}
DosUnlockChannel(PAS.nDmaChannel);
}
return AUDIO_ERROR_NONE;
}
static UINT AIAPI SetAudioCallback(LPFNAUDIOWAVE lpfnAudioWave)
{
PAS.lpfnAudioWave = lpfnAudioWave;
return AUDIO_ERROR_NONE;
}
/*
* Pro Audio Spectrum driver public interface
*/
AUDIOWAVEDRIVER ProAudioSpectrumWaveDriver =
{
GetAudioCaps, PingAudio, OpenAudio, CloseAudio,
UpdateAudio, SetAudioCallback
};
AUDIODRIVER ProAudioSpectrumDriver =
{
&ProAudioSpectrumWaveDriver, NULL
};

764
seal-hack/src/s3mfile.c Normal file
View File

@@ -0,0 +1,764 @@
/*
* $Id: s3mfile.c 1.7 1996/09/13 15:10:01 chasan released $
*
* Scream Tracker 3.0 module file loader routines.
*
* Copyright (c) 1995-1999 Carlos Hasan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "audio.h"
#include "iofile.h"
/*
* ScreamTracker 3.0 module file structures
*/
#define S3M_MAX_TRACKS 32
#define S3M_MAX_SAMPLES 100
#define S3M_MAX_PATTERNS 256
#define S3M_MAX_ORDERS 256
#define S3M_MAX_ROWS 64
#define S3M_SCRM_MAGIC 0x4D524353L
#define S3M_SCRS_MAGIC 0x53524353L
#define S3M_SCRS_PCM 0x01
#define S3M_SCRS_LOOPED 0x01
#pragma pack(1)
typedef struct {
CHAR aModuleName[28];
BYTE bPadding;
BYTE nFileType;
WORD wReserved;
WORD nSongLength;
WORD nSamples;
WORD nPatterns;
WORD wFlags;
WORD wVersion;
WORD nSampleType;
DWORD dwSCRM;
BYTE nGlobalVolume;
BYTE nTempo;
BYTE nBPM;
BYTE nMasterVolume;
BYTE nUltraClick;
BYTE nDefaultPanning;
BYTE aReserved[8];
WORD wSpecial;
BYTE aChannelTable[32];
} S3MFILEHEADER;
typedef struct {
BYTE nType;
CHAR aFileName[13];
WORD wDataSegPtr;
DWORD dwLength;
DWORD dwLoopStart;
DWORD dwLoopEnd;
BYTE nVolume;
BYTE nReserved;
BYTE nPacking;
BYTE bFlags;
DWORD nSampleRate;
BYTE aReserved[12];
CHAR aSampleName[28];
DWORD dwSCRS;
} S3MSAMPLEHEADER;
typedef struct {
WORD nSize;
LPBYTE lpData;
} S3MPATTERNHEADER;
typedef struct {
BYTE nNote;
BYTE nSample;
BYTE nVolume;
BYTE nCommand;
BYTE nParams;
} S3MTRACKDATA;
#pragma pack()
#define ACC 11
#define MUL(a,b) (((a)*(b)+(1<<(ACC-1)))>>ACC)
#define A (LONG)(12.0 * -2.4991805816500 * (1 << ACC))
#define B (LONG)(12.0 * +4.0305172865900 * (1 << ACC))
#define C (LONG)(12.0 * -2.0791605988100 * (1 << ACC))
#define D (LONG)(12.0 * +0.6262992372690 * (1 << ACC))
#define E (LONG)(12.0 * -0.0784753434027 * (1 << ACC))
static LONG S3MGetRelativeNote(LONG dwSampleRate)
{
LONG dwRelativeNote;
/*
* Compute the relative note value given a sampling frequency:
* RelativeNote = 12.0 * log2(SampleRate / 8363.0)
*
* The following algorithm uses 21.11 fixed-point arithmetic
* with an accuracy of about 1/128 for sampling frequencies
* between 522 and 65535 Hertz. (Thanks Zed!)
*/
dwSampleRate = (dwSampleRate << (ACC + 4)) / 8363;
dwRelativeNote = -48L << ACC;
while (dwSampleRate > (2L << ACC)) {
dwSampleRate = (dwSampleRate + 1) >> 1;
dwRelativeNote += (12L << ACC);
}
dwRelativeNote += A + MUL(B + MUL(C + MUL(D + MUL(E, dwSampleRate),
dwSampleRate), dwSampleRate), dwSampleRate);
return dwRelativeNote >> (ACC - 7);
}
static UINT S3MDecodePattern(UINT nTracks, LPBYTE lpData, UINT nSize,
BYTE aMappingTable[], LPAUDIOPATTERN lpPattern)
{
static S3MTRACKDATA aTrackTable[S3M_MAX_TRACKS];
static BYTE aParamTable[S3M_MAX_TRACKS];
UINT nRow, nTrack, nFlags, nNote, nSample, nVolume, nCommand, nParams;
LPBYTE lpFTData, lpEndData;
/* initialize the pattern structure */
lpPattern->nPacking = 0;
lpPattern->nTracks = nTracks;
lpPattern->nRows = S3M_MAX_ROWS;
lpPattern->nSize = 0;
if ((lpPattern->lpData = malloc(nTracks * 6 * S3M_MAX_ROWS)) == NULL) {
return AUDIO_ERROR_NOMEMORY;
}
lpFTData = lpPattern->lpData;
lpEndData = lpData + nSize;
memset(aParamTable, 0, sizeof(aParamTable));
for (nRow = 0; nRow < S3M_MAX_ROWS; nRow++) {
/* grab the next row of notes from the S3M pattern */
memset(aTrackTable, 0, sizeof(aTrackTable));
while (lpData < lpEndData && (nFlags = *lpData++) != 0x00) {
/* get the note event */
nNote = 0xFF;
nSample = 0x00;
nVolume = 0xFF;
nCommand = 0x00;
nParams = 0x00;
nTrack = nFlags & 0x1F;
if (nFlags & 0x20) {
nNote = *lpData++;
nSample = *lpData++;
}
if (nFlags & 0x40) {
nVolume = *lpData++;
}
if (nFlags & 0x80) {
nCommand = *lpData++;
nParams = *lpData++;
}
/* skip notes for non-PCM tracks */
if ((nTrack = aMappingTable[nTrack]) >= nTracks)
continue;
/* decode note index */
if (nNote == 0xFE) {
nNote = AUDIO_MAX_NOTES + 1;
}
else if (nNote == 0xFF) {
nNote = 0x00;
}
else {
nNote = 12 * (nNote >> 4) + (nNote & 0x0F) + 1;
if (nNote > AUDIO_MAX_NOTES)
nNote = 0;
}
/* decode S3M command effect default parameter stuff */
nCommand += 0x40;
if (nParams != 0x00) {
aParamTable[nTrack] = nParams;
}
else if (strchr("DEFGKLQ", nCommand)) {
nParams = aParamTable[nTrack];
}
/* decode S3M command effect */
switch (nCommand) {
case '@':
/* null command */
nCommand = nParams = 0x00;
break;
case 'A':
/* set tempo speed */
if (nParams < 0x20) {
nCommand = 0x0F;
}
else {
/* WARNING: tempo greater than 31 are not supported! */
nCommand = nParams = 0x00;
}
break;
case 'B':
/* jump position */
nCommand = 0x0B;
break;
case 'C':
/* break pattern */
nCommand = 0x0D;
break;
case 'D':
if ((nParams & 0xF0) == 0x00) {
/* volume slide down */
nCommand = 0x0A;
nParams &= 0x0F;
}
else if ((nParams & 0x0F) == 0x00) {
/* volume slide up */
nCommand = 0x0A;
nParams &= 0xF0;
}
else if ((nParams & 0xF0) == 0xF0) {
/* fine volume slide down */
nCommand = 0x0E;
nParams = 0xB0 | (nParams & 0x0F);
}
else if ((nParams & 0x0F) == 0x0F) {
/* fine volume slide up */
nCommand = 0x0E;
nParams = 0xA0 | (nParams >> 4);
}
else {
nCommand = nParams = 0x00;
}
break;
case 'E':
if ((nParams & 0xF0) == 0xF0) {
/* fine porta down */
nCommand = 0x0E;
nParams = 0x20 | (nParams & 0x0F);
}
else if ((nParams & 0xF0) == 0xE0) {
/* extra fine porta down */
nCommand = 0x21;
nParams = 0x20 | (nParams & 0x0F);
}
else {
/* portamento down */
nCommand = 0x02;
}
break;
case 'F':
if ((nParams & 0xF0) == 0xF0) {
/* fine portamento up */
nCommand = 0x0E;
nParams = 0x10 | (nParams & 0x0F);
}
else if ((nParams & 0xF0) == 0xe0) {
/* extra fine portamento up */
nCommand = 0x21;
nParams = 0x10 | (nParams & 0x0F);
}
else {
/* portamento up */
nCommand = 0x01;
}
break;
case 'G':
/* tone portamento */
nCommand = 0x03;
break;
case 'H':
/* vibrato */
nCommand = 0x04;
break;
case 'I':
/* tremor */
nCommand = 0x1d;
break;
case 'J':
/* arpeggio */
nCommand = 0x00;
break;
case 'K':
/* vibrato & volume slide */
nCommand = 0x06;
break;
case 'L':
/* tone portamento & volume slide */
nCommand = 0x05;
break;
case 'O':
/* set sample offset */
nCommand = 0x09;
break;
case 'Q':
/* multi-retrig */
nCommand = 0x1b;
break;
case 'R':
/* tremolo */
nCommand = 0x07;
break;
case 'S':
/* misc settings */
switch (nParams & 0xF0) {
case 0x00:
/* set filter on/off */
nCommand = 0x0E;
nParams = 0x00 | (nParams & 0x0F);
break;
case 0x10:
/* set glissando control */
nCommand = 0x0E;
nParams = 0x30 | (nParams & 0x0F);
break;
case 0x20:
/* set fine-tune */
nCommand = 0x0E;
nParams = 0x50 | (nParams & 0x0F);
break;
case 0x30:
/* set tremolo waveform */
nCommand = 0x0E;
nParams = 0x70 | (nParams & 0x0F);
break;
case 0x40:
/* set vibrato waveform */
nCommand = 0x0E;
nParams = 0x40 | (nParams & 0x0F);
break;
case 0x80:
/* set coarse panning */
nCommand = 0x0E;
nParams = 0x80 | (nParams & 0x0F);
break;
case 0xA0:
/* set stereo control */
nCommand = 0x08;
switch (nParams & 0x0F) {
case 0x00:
case 0x02:
/* hard left panning */
nParams = 0x00;
break;
case 0x01:
case 0x03:
/* hard right panning */
nParams = 0xFF;
break;
case 0x04:
/* left panning */
nParams = 0x40;
break;
case 0x05:
/* right panning */
nParams = 0xC0;
break;
case 0x06:
case 0x07:
/* middle panning */
nParams = 0x80;
break;
default:
nCommand = nParams = 0x00;
break;
}
break;
case 0xB0:
/* set/start pattern loop */
nCommand = 0x0E;
nParams = 0x60 | (nParams & 0x0F);
break;
case 0xC0:
/* note cut */
nCommand = 0x0E;
nParams = 0xC0 | (nParams & 0x0F);
break;
case 0xD0:
/* note delay */
nCommand = 0x0E;
nParams = 0xD0 | (nParams & 0x0F);
break;
case 0xE0:
/* pattern delay */
nCommand = 0x0E;
nParams = 0xE0 | (nParams & 0x0F);
break;
default:
nCommand = nParams = 0x00;
break;
}
break;
case 'T':
/* set BPM speed */
if (nParams >= 0x20)
nCommand = 0x0F;
else
nCommand = nParams = 0x00;
break;
case 'U':
/* fine vibrato */
/* WARNING: this is not an standard FT2 command! */
nCommand = 0x1E;
break;
case 'V':
/* set global volume */
nCommand = 0x10;
break;
case 'X':
/* set DMP-style panning */
nCommand = 0x08;
if (nParams > 0x80)
nParams = 0x80;
else if (nParams < 0x80)
nParams <<= 1;
else
nParams = 0xFF;
break;
case 'Z':
/* set sync mark */
/* WARNING: this is not an standard FT2 command! */
nCommand = 0x23;
break;
default:
/* unknown S3M command value */
nCommand = nParams = 0x00;
break;
}
/* save note message */
if (nNote) {
aTrackTable[nTrack].nNote = nNote;
}
if (nSample) {
aTrackTable[nTrack].nSample = nSample;
}
if (nVolume <= 64) {
aTrackTable[nTrack].nVolume = 0x10 + nVolume;
}
if (nCommand | nParams) {
aTrackTable[nTrack].nCommand = nCommand;
aTrackTable[nTrack].nParams = nParams;
}
}
/* encode row of notes in our pattern structure */
for (nTrack = 0; nTrack < nTracks; nTrack++) {
/* get saved note message */
nNote = aTrackTable[nTrack].nNote;
nSample = aTrackTable[nTrack].nSample;
nVolume = aTrackTable[nTrack].nVolume;
nCommand = aTrackTable[nTrack].nCommand;
nParams = aTrackTable[nTrack].nParams;
/* insert new note message */
nFlags = AUDIO_PATTERN_PACKED;
if (nNote)
nFlags |= AUDIO_PATTERN_NOTE;
if (nSample)
nFlags |= AUDIO_PATTERN_SAMPLE;
if (nVolume)
nFlags |= AUDIO_PATTERN_VOLUME;
if (nCommand)
nFlags |= AUDIO_PATTERN_COMMAND;
if (nParams)
nFlags |= AUDIO_PATTERN_PARAMS;
*lpFTData++ = nFlags;
if (nNote)
*lpFTData++ = nNote;
if (nSample)
*lpFTData++ = nSample;
if (nVolume)
*lpFTData++ = nVolume;
if (nCommand)
*lpFTData++ = nCommand;
if (nParams)
*lpFTData++ = nParams;
}
}
lpPattern->nSize = (lpFTData - lpPattern->lpData);
if ((lpPattern->lpData = realloc(lpPattern->lpData,
lpPattern->nSize)) == NULL) {
return AUDIO_ERROR_NOMEMORY;
}
return AUDIO_ERROR_NONE;
}
static VOID S3MDecodeSample(LPBYTE lpData, UINT nSize)
{
/* convert from 8-bit unsigned to 8-bit signed linear */
while (nSize--) {
*lpData++ ^= 0x80;
}
}
UINT AIAPI ALoadModuleS3M(LPSTR lpszFileName,
LPAUDIOMODULE *lplpModule, DWORD dwFileOffset)
{
static S3MFILEHEADER Header;
static S3MSAMPLEHEADER Sample;
static S3MPATTERNHEADER Pattern;
static WORD aSampleSegPtr[S3M_MAX_SAMPLES];
static WORD aPatternSegPtr[S3M_MAX_PATTERNS];
static BYTE aPanningTable[S3M_MAX_TRACKS];
static BYTE aMappingTable[S3M_MAX_TRACKS];
LPAUDIOMODULE lpModule;
LPAUDIOPATTERN lpPattern;
LPAUDIOPATCH lpPatch;
LPAUDIOSAMPLE lpSample;
LONG dwRelativeNote;
UINT n, nErrorCode;
if (AIOOpenFile(lpszFileName)) {
printf("File not found\n");
return AUDIO_ERROR_FILENOTFOUND;
}
AIOSeekFile(dwFileOffset, SEEK_SET);
if ((lpModule = (LPAUDIOMODULE) calloc(1, sizeof(AUDIOMODULE))) == NULL) {
AIOCloseFile();
printf("Memory error...\n");
return AUDIO_ERROR_NOMEMORY;
}
/* load S3M module file header */
AIOReadFile(Header.aModuleName, sizeof(Header.aModuleName));
AIOReadChar(&Header.bPadding);
AIOReadChar(&Header.nFileType);
AIOReadShort(&Header.wReserved);
AIOReadShort(&Header.nSongLength);
AIOReadShort(&Header.nSamples);
AIOReadShort(&Header.nPatterns);
AIOReadShort(&Header.wFlags);
AIOReadShort(&Header.wVersion);
AIOReadShort(&Header.nSampleType);
AIOReadLong(&Header.dwSCRM);
AIOReadChar(&Header.nGlobalVolume);
AIOReadChar(&Header.nTempo);
AIOReadChar(&Header.nBPM);
AIOReadChar(&Header.nMasterVolume);
AIOReadChar(&Header.nUltraClick);
AIOReadChar(&Header.nDefaultPanning);
AIOReadFile(Header.aReserved, sizeof(Header.aReserved));
AIOReadShort(&Header.wSpecial);
AIOReadFile(Header.aChannelTable, sizeof(Header.aChannelTable));
printf("[%lX] vs [%lX]\n", Header.dwSCRM, S3M_SCRM_MAGIC);
if (Header.dwSCRM != S3M_SCRM_MAGIC ||
Header.nSongLength > S3M_MAX_ORDERS ||
Header.nPatterns > S3M_MAX_PATTERNS ||
Header.nSamples > S3M_MAX_SAMPLES) {
AFreeModuleFile(lpModule);
AIOCloseFile();
return AUDIO_ERROR_BADFILEFORMAT;
}
/* load S3M order table and sample/pattern para-pointers */
AIOReadFile(lpModule->aOrderTable, Header.nSongLength);
for (n = 0; n < Header.nSamples; n++) {
AIOReadShort(&aSampleSegPtr[n]);
}
for (n = 0; n < Header.nPatterns; n++) {
AIOReadShort(&aPatternSegPtr[n]);
}
/* load S3M panning table if present */
memset(aPanningTable, 0x00, sizeof(aPanningTable));
if (Header.nDefaultPanning == 0xFC) {
AIOReadFile(aPanningTable, sizeof(aPanningTable));
}
/* fixup the S3M panning table */
for (n = 0; n < S3M_MAX_TRACKS; n++) {
if (aPanningTable[n] & 0x20) {
aPanningTable[n] = (aPanningTable[n] & 0x0F) << 4;
}
else {
if (Header.aChannelTable[n] <= 7) {
aPanningTable[n] = 0x00;
}
else if (Header.aChannelTable[n] <= 15) {
aPanningTable[n] = 0xFF;
}
}
}
/* initialize the module structure */
strncpy(lpModule->szModuleName, Header.aModuleName,
sizeof(lpModule->szModuleName) - 1);
lpModule->wFlags = AUDIO_MODULE_AMIGA | AUDIO_MODULE_PANNING;
lpModule->nPatterns = Header.nPatterns;
lpModule->nPatches = Header.nSamples;
lpModule->nTempo = Header.nTempo;
lpModule->nBPM = Header.nBPM;
for (n = 0; n < Header.nSongLength; n++) {
if (lpModule->aOrderTable[n] < Header.nPatterns) {
lpModule->aOrderTable[lpModule->nOrders++] =
lpModule->aOrderTable[n];
}
else {
lpModule->aOrderTable[n] = 0x00;
}
}
/* lpModule->nRestart = lpModule->nOrders; */
for (n = 0; n < S3M_MAX_TRACKS; n++) {
aMappingTable[n] = 0xFF;
if ((Header.aChannelTable[n] &= 0x7F) <= 15) {
aMappingTable[n] = (BYTE) lpModule->nTracks;
lpModule->aPanningTable[lpModule->nTracks++] =
aPanningTable[n];
}
}
if ((lpModule->aPatternTable = (LPAUDIOPATTERN)
calloc(lpModule->nPatterns, sizeof(AUDIOPATTERN))) == NULL) {
AFreeModuleFile(lpModule);
AIOCloseFile();
return AUDIO_ERROR_NOMEMORY;
}
if ((lpModule->aPatchTable = (LPAUDIOPATCH)
calloc(lpModule->nPatches, sizeof(AUDIOPATCH))) == NULL) {
AFreeModuleFile(lpModule);
AIOCloseFile();
return AUDIO_ERROR_NOMEMORY;
}
/* load S3M pattern sheets */
lpPattern = lpModule->aPatternTable;
for (n = 0; n < lpModule->nPatterns; n++, lpPattern++) {
AIOSeekFile(((LONG) aPatternSegPtr[n] << 4) + dwFileOffset, SEEK_SET);
AIOReadShort(&Pattern.nSize);
Pattern.nSize -= sizeof(Pattern.nSize);
if ((Pattern.lpData = malloc(Pattern.nSize)) == NULL) {
AFreeModuleFile(lpModule);
AIOCloseFile();
return AUDIO_ERROR_NOMEMORY;
}
AIOReadFile(Pattern.lpData, Pattern.nSize);
nErrorCode = S3MDecodePattern(lpModule->nTracks, Pattern.lpData,
Pattern.nSize, aMappingTable, lpPattern);
free(Pattern.lpData);
if (nErrorCode != AUDIO_ERROR_NONE) {
AFreeModuleFile(lpModule);
AIOCloseFile();
return nErrorCode;
}
}
/* load S3M sample waveforms */
lpPatch = lpModule->aPatchTable;
for (n = 0; n < lpModule->nPatches; n++, lpPatch++) {
/* load S3M sample header structure */
AIOSeekFile(((LONG) aSampleSegPtr[n] << 4) + dwFileOffset, SEEK_SET);
AIOReadChar(&Sample.nType);
AIOReadFile(&Sample.aFileName, sizeof(Sample.aFileName));
AIOReadShort(&Sample.wDataSegPtr);
AIOReadLong(&Sample.dwLength);
AIOReadLong(&Sample.dwLoopStart);
AIOReadLong(&Sample.dwLoopEnd);
AIOReadChar(&Sample.nVolume);
AIOReadChar(&Sample.nReserved);
AIOReadChar(&Sample.nPacking);
AIOReadChar(&Sample.bFlags);
AIOReadLong(&Sample.nSampleRate);
AIOReadFile(Sample.aReserved, sizeof(Sample.aReserved));
AIOReadFile(Sample.aSampleName, sizeof(Sample.aSampleName));
AIOReadLong(&Sample.dwSCRS);
if (Sample.nType == S3M_SCRS_PCM && Sample.dwSCRS != S3M_SCRS_MAGIC) {
AFreeModuleFile(lpModule);
AIOCloseFile();
return AUDIO_ERROR_BADFILEFORMAT;
}
/* initialize patch structure */
strncpy(lpPatch->szPatchName, Sample.aSampleName,
sizeof(lpPatch->szPatchName) - 1);
if (Sample.nType == S3M_SCRS_PCM && Sample.dwLength != 0) {
if ((lpSample = (LPAUDIOSAMPLE)
calloc(1, sizeof(AUDIOSAMPLE))) == NULL) {
AFreeModuleFile(lpModule);
AIOCloseFile();
return AUDIO_ERROR_NOMEMORY;
}
lpPatch->nSamples = 1;
lpPatch->aSampleTable = lpSample;
/* initialize sample structure */
lpSample->Wave.wFormat = AUDIO_FORMAT_8BITS;
if (Sample.bFlags & S3M_SCRS_LOOPED)
lpSample->Wave.wFormat |= AUDIO_FORMAT_LOOP;
lpSample->Wave.dwLength = Sample.dwLength;
lpSample->Wave.dwLoopStart = Sample.dwLoopStart;
lpSample->Wave.dwLoopEnd = Sample.dwLoopEnd;
lpSample->Wave.nSampleRate = (WORD) Sample.nSampleRate;
lpSample->nVolume = Sample.nVolume;
lpSample->nPanning = (AUDIO_MIN_PANNING + AUDIO_MAX_PANNING) / 2;
/* compute fine tuning for this sample */
if (Sample.nSampleRate != 0) {
dwRelativeNote = S3MGetRelativeNote(Sample.nSampleRate);
lpSample->nRelativeNote = (BYTE) (dwRelativeNote >> 7);
lpSample->nFinetune = (dwRelativeNote & 0x7F);
}
/* allocate sample waveform data */
nErrorCode = ACreateAudioData(&lpSample->Wave);
if (nErrorCode != AUDIO_ERROR_NONE) {
AFreeModuleFile(lpModule);
AIOCloseFile();
return nErrorCode;
}
/* load sample wavefrom data */
AIOSeekFile(((LONG) Sample.wDataSegPtr << 4) + dwFileOffset, SEEK_SET);
AIOReadFile(lpSample->Wave.lpData, lpSample->Wave.dwLength);
S3MDecodeSample(lpSample->Wave.lpData, lpSample->Wave.dwLength);
AWriteAudioData(&lpSample->Wave, 0, lpSample->Wave.dwLength);
}
}
AIOCloseFile();
*lplpModule = lpModule;
return AUDIO_ERROR_NONE;
}

762
seal-hack/src/sbdrv.c Normal file
View File

@@ -0,0 +1,762 @@
/*
* $Id: sbdrv.c 1.7 1996/08/05 18:51:19 chasan released $
* 1.8 1998/12/24 00:16:00 chasan
*
* Sound Blaster series DSP audio drivers.
*
* Copyright (C) 1995-1999 Carlos Hasan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <stdio.h>
#include <string.h>
#include "audio.h"
#include "drivers.h"
#include "msdos.h"
#define DEBUG(code)
/*
* Sound Blaster DSP and Mixer register offsets
*/
#define MIXER_ADDR 0x04 /* mixer index address register */
#define MIXER_DATA 0x05 /* mixer indexed data register */
#define DSP_RESET 0x06 /* master reset register */
#define DSP_READ_DATA 0x0A /* read data register */
#define DSP_READ_READY 0x0E /* data available register */
#define DSP_WRITE_DATA 0x0C /* write data register */
#define DSP_WRITE_BUSY 0x0C /* write status register */
#define DSP_DMA_ACK_8BIT 0x0E /* 8 bit DMA acknowledge */
#define DSP_DMA_ACK_16BIT 0x0F /* 16 bit DMA acknowledge */
/*
* Sound Blaster 1.0 (DSP 1.x, 2.0, 2.01, 3.xx, 4.xx) command defines
*/
#define DSP_PIO_DAC_8BIT 0x10 /* direct 8 bit output */
#define DSP_PIO_ADC_8BIT 0x20 /* direct 8 bit input */
#define DSP_DMA_TIME_CONST 0x40 /* transfer time constant */
#define DSP_DMA_DAC_8BIT 0x14 /* 8 bit DMA output transfer */
#define DSP_DMA_ADC_8BIT 0x24 /* 8 bit DMA input transfer */
#define DSP_DMA_PAUSE_8BIT 0xD0 /* pause 8 bit DMA transfer */
#define DSP_DMA_CONTINUE_8BIT 0xD4 /* continue 8 bit DMA transfer */
#define DSP_SPEAKER_ON 0xD1 /* turn speaker on */
#define DSP_SPEAKER_OFF 0xD3 /* turn speaker off */
#define DSP_GET_VERSION 0xE1 /* get DSP version */
/*
* Sound Blaster 1.5 (DSP 2.0, 2.01, 3.xx, 4.xx) command defines
*/
#define DSP_DMA_BLOCK_SIZE 0x48 /* transfer block size */
#define DSP_DMA_DAC_AI_8BIT 0x1C /* 8 bit low-speed A/I output */
#define DSP_DMA_ADC_AI_8BIT 0x2C /* 8 bit low-speed A/I input */
/*
* Sound Blaster 2.0 (DSP 2.01, 3.xx) command defines
*/
#define DSP_DMA_DAC_HS_8BIT 0x91 /* 8 bit high-speed output */
#define DSP_DMA_ADC_HS_8BIT 0x99 /* 8 bit high-speed input */
#define DSP_DMA_DAC_AI_HS_8BIT 0x90 /* 8 bit high-speed A/I output */
#define DSP_DMA_ADC_AI_HS_8BIT 0x98 /* 8 bit high-speed A/I input */
/*
* Sound Blaster Pro (DSP 3.xx) command defines
*/
#define DSP_DMA_ADC_MONO 0xA0 /* 8 bit mono input mode */
#define DSP_DMA_ADC_STEREO 0xA8 /* 8 bit stereo input mode */
/*
* Sound Blaster 16 (DSP 4.xx) command defines
*/
#define DSP_DMA_DAC_RATE 0x41 /* set output sample rate */
#define DSP_DMA_ADC_RATE 0x42 /* set input sample rate */
#define DSP_DMA_START_16BIT 0xB0 /* start 16 bit DMA transfer */
#define DSP_DMA_START_8BIT 0xC0 /* start 8 bit DMA transfer */
#define B_DSP_DMA_DAC_MODE 0x06 /* start DAC output mode */
#define B_DSP_DMA_ADC_MODE 0x0E /* start ADC input mode */
#define DSP_DMA_STOP_16BIT 0xD9 /* stop 16 bit DMA transfer */
#define DSP_DMA_STOP_8BIT 0xDA /* stop 8 bit DMA transfer */
#define DSP_DMA_PAUSE_16BIT 0xD5 /* pause 16 bit DMA transfer */
#define DSP_DMA_CONTINUE_16BIT 0xD6 /* continue 16 bit DMA transfer */
/*
* Sound Blaster Pro mixer indirect registers
*/
#define MIXER_RESET 0x00 /* mixer reset register */
#define MIXER_INPUT_CONTROL 0x0C /* input control register */
#define MIXER_OUTPUT_CONTROL 0x0E /* output control register */
#define MIXER_MASTER_VOLUME 0x22 /* master volume register */
#define MIXER_VOICE_VOLUME 0x04 /* voice volume register */
#define MIXER_MIDI_VOLUME 0x26 /* MIDI volume register */
#define MIXER_CD_VOLUME 0x28 /* CD volume register */
#define MIXER_LINE_VOLUME 0x2E /* line volume register */
#define MIXER_MIC_MIXING 0x0A /* mic volume register */
#define MIXER_IRQ_LINE 0x80 /* IRQ line register */
#define MIXER_DMA_CHANNEL 0x81 /* DMA channel register */
#define MIXER_IRQ_STATUS 0x82 /* IRQ status register */
/*
* Sound Blaster 16 mixer indirect registers
*/
#define MIXER_MASTER_LEFT 0x30 /* master left volume register */
#define MIXER_MASTER_RIGHT 0x31 /* master right volume register */
#define MIXER_VOICE_LEFT 0x32 /* voice left volume register */
#define MIXER_VOICE_RIGHT 0x33 /* voice right volume register */
#define MIXER_MIDI_LEFT 0x34 /* MIDI left volume register */
#define MIXER_MIDI_RIGHT 0x35 /* MIDI right volume register */
#define MIXER_CD_LEFT 0x36 /* CD left volume register */
#define MIXER_CD_RIGHT 0x37 /* CD right volume register */
#define MIXER_LINE_LEFT 0x38 /* line left volume register */
#define MIXER_LINE_RIGHT 0x39 /* line right volume register */
#define MIXER_MIC_VOLUME 0x3A /* mic input volume register */
#define MIXER_SPKR_VOLUME 0x3B /* speaker volume register */
#define MIXER_OUT_CONTROL 0x3C /* Output Line/CD/MIC control */
#define MIXER_INPUT_LEFT 0x3D /* input left control bits */
#define MIXER_INPUT_RIGHT 0x3E /* input right control bits */
#define MIXER_INPUT_GAIN 0x3F /* input gain level */
#define MIXER_OUT_GAIN_LEFT 0x41 /* Output gain left level */
#define MIXER_OUT_GAIN_RIGHT 0x42 /* Output gain right level */
#define MIXER_INPUT_AUTO_GAIN 0x43 /* input auto gain control */
#define MIXER_TREBLE_LEFT 0x44 /* Treble left level */
#define MIXER_TREBLE_RIGHT 0x45 /* Treble right level */
#define MIXER_BASS_LEFT 0x46 /* Bass left level */
#define MIXER_BASS_RIGHT 0x47 /* Bass right level */
/*
* Input source and filter select register bit fields (MIXER_INPUT_CONTROL)
*/
#define INPUT_SOURCE_MIC 0x00 /* select mic input */
#define INPUT_SOURCE_CD 0x02 /* select CD input */
#define INPUT_SOURCE_LINE 0x06 /* select line input */
#define INPUT_LOW_FILTER 0x00 /* select low-pass filter */
#define INPUT_HIGH_FILTER 0x08 /* select high-pass filter */
#define INPUT_NO_FILTER 0x20 /* disable filters */
/*
* Output voice feature settings register bit fields (MIXER_OUTPUT_CONTROL)
*/
#define OUTPUT_DISABLE_DNFI 0x20 /* disable output filter */
#define OUTPUT_ENABLE_VSTC 0x02 /* enable stereo mode */
/*
* Mixer output control register bit fields (MIXER_OUT_CONTROL)
*/
#define MUTE_LINE_LEFT 0x10 /* disable left line-out */
#define MUTE_LINE_RIGHT 0x08 /* disable right line-out */
#define MUTE_CD_LEFT 0x04 /* disable left CD output */
#define MUTE_CD_RIGHT 0x02 /* disable right CD output */
#define MUTE_MICROPHONE 0x01 /* disable MIC output */
/*
* Start DMA DAC transfer format bit fields (DSP_DMA_START_8/16BIT)
*/
#define B_DSP_DMA_UNSIGNED 0x00 /* select unsigned samples */
#define B_DSP_DMA_SIGNED 0x10 /* select signed samples */
#define B_DSP_DMA_MONO 0x00 /* select mono output */
#define B_DSP_DMA_STEREO 0x20 /* select stereo output */
/*
* Timeout and DMA buffer size defines
*/
#define TIMEOUT 200000 /* number of times to wait for */
#define BUFFERSIZE 50 /* buffer length in milliseconds */
#define BUFFRAGSIZE 32 /* buffer fragment size in BYTEs */
/*
* Sound Blaster configuration structure
*/
static struct {
WORD wId; /* audio device indentifier */
WORD wFormat; /* playback encoding format */
WORD nSampleRate; /* sampling frequency */
WORD wPort; /* DSP base port address */
BYTE nIrqLine; /* interrupt line */
BYTE nDmaChannel; /* output DMA channel */
BYTE nLowDmaChannel; /* 8-bit DMA channel */
BYTE nHighDmaChannel; /* 16-bit DMA channel */
LPBYTE lpBuffer; /* DMA buffer address */
UINT nBufferSize; /* DMA buffer length */
UINT nPosition; /* DMA buffer playing position */
LPFNAUDIOWAVE lpfnAudioWave; /* user callback routine */
} SB;
/*
* Sound Blaster DSP & Mixer programming routines
*/
static VOID DSPPortB(BYTE bData)
{
UINT n;
for (n = 0; n < TIMEOUT; n++)
if (!(INB(SB.wPort + DSP_WRITE_BUSY) & 0x80))
break;
OUTB(SB.wPort + DSP_WRITE_DATA, bData);
}
static BYTE DSPPortRB(VOID)
{
UINT n;
for (n = 0; n < TIMEOUT; n++)
if (INB(SB.wPort + DSP_READ_READY) & 0x80)
break;
return INB(SB.wPort + DSP_READ_DATA);
}
static VOID DSPMixerB(BYTE nIndex, BYTE bData)
{
OUTB(SB.wPort + MIXER_ADDR, nIndex);
OUTB(SB.wPort + MIXER_DATA, bData);
}
static BYTE DSPMixerRB(BYTE nIndex)
{
OUTB(SB.wPort + MIXER_ADDR, nIndex);
return INB(SB.wPort + MIXER_DATA);
}
static WORD DSPGetVersion(VOID)
{
WORD nMinor, nMajor;
DSPPortB(DSP_GET_VERSION);
nMajor = DSPPortRB();
nMinor = DSPPortRB();
return MAKEWORD(nMinor, nMajor);
}
static VOID DSPReset(VOID)
{
UINT n;
OUTB(SB.wPort + DSP_RESET, 1);
/* wait 3 microseconds */
for (n = 0; n < 32; n++)
INB(SB.wPort + DSP_RESET);
OUTB(SB.wPort + DSP_RESET, 0);
}
static BOOL DSPProbe(VOID)
{
WORD nVersion;
UINT n;
DEBUG(printf("DSPProbe: reset DSP processor\n"));
/* reset the DSP device */
for (n = 0; n < 8; n++) {
DSPReset();
if (DSPPortRB() == 0xAA)
break;
}
if (n >= 8)
return AUDIO_ERROR_NODEVICE;
DEBUG(printf("DSPProbe: read DSP version\n"));
/* get the DSP version */
nVersion = DSPGetVersion();
DEBUG(printf("DSPProbe: DSP version 0x%03x\n", nVersion));
/* [1998/12/24] don't use anything higher than specified by the user */
if (nVersion >= 0x400) {
if (SB.wId >= AUDIO_PRODUCT_SB16)
SB.wId = AUDIO_PRODUCT_SB16;
}
else if (nVersion >= 0x300) {
if (SB.wId >= AUDIO_PRODUCT_SBPRO)
SB.wId = AUDIO_PRODUCT_SBPRO;
}
else if (nVersion >= 0x201) {
if (SB.wId >= AUDIO_PRODUCT_SB20)
SB.wId = AUDIO_PRODUCT_SB20;
}
else if (nVersion >= 0x200) {
if (SB.wId >= AUDIO_PRODUCT_SB15)
SB.wId = AUDIO_PRODUCT_SB15;
}
else {
SB.wId = AUDIO_PRODUCT_SB;
}
return AUDIO_ERROR_NONE;
}
static VOID AIAPI DSPInterruptHandler(VOID)
{
if (SB.wId == AUDIO_PRODUCT_SB16) {
/*
* Acknowledge 8/16 bit mono/stereo high speed
* autoinit DMA transfer for SB16 (DSP 4.x) cards.
*/
INB(SB.wPort + (SB.wFormat & AUDIO_FORMAT_16BITS ?
DSP_DMA_ACK_16BIT : DSP_DMA_ACK_8BIT));
}
else if (SB.wId != AUDIO_PRODUCT_SB) {
/*
* Acknowledge 8 bit mono/stereo low/high speed autoinit
* DMA transfer for SB Pro (DSP 3.x), SB 2.0 (DSP 2.01)
* and SB 1.5 (DSP 2.0) cards.
*/
INB(SB.wPort + DSP_DMA_ACK_8BIT);
}
else {
/*
* Acknowledge and restart 8 bit mono low speed
* oneshot DMA transfer for SB 1.0 (DSP 1.x) cards.
*/
INB(SB.wPort + DSP_DMA_ACK_8BIT);
DSPPortB(DSP_DMA_DAC_8BIT);
DSPPortB(0xF0);
DSPPortB(0xFF);
}
}
static VOID DSPStartPlayback(VOID)
{
DWORD dwBytesPerSecond;
DEBUG(printf("DSPStartPlayback: set DMA %d and IRQ %d resources\n", SB.nDmaChannel, SB.nIrqLine));
/* setup the DMA channel parameters */
DosSetupChannel(SB.nDmaChannel, DMA_WRITE | DMA_AUTOINIT, 0);
/* setup our IRQ interrupt handler */
DosSetVectorHandler(SB.nIrqLine, DSPInterruptHandler);
DEBUG(printf("DSPStartPlayback: reset DSP processor\n"));
/* reset the DSP processor */
DSPReset();
DEBUG(printf("DSPStartPlayback: turn on speaker\n"));
/* turn on the DSP speaker */
DSPPortB(DSP_SPEAKER_ON);
/* [1998/12/04] turn off filter and enable/disable SBPro stereo mode */
if (SB.wId == AUDIO_PRODUCT_SBPRO) {
DEBUG(printf("DSPStartPlayback: setup SBPro output control\n"));
DSPMixerB(MIXER_OUTPUT_CONTROL, DSPMixerRB(MIXER_OUTPUT_CONTROL) |
OUTPUT_DISABLE_DNFI |
(SB.wFormat & AUDIO_FORMAT_STEREO ? OUTPUT_ENABLE_VSTC : 0));
}
DEBUG(printf("DSPStartPlayback: set sample rate\n"));
/* set DSP output playback rate */
if (SB.wId == AUDIO_PRODUCT_SB16) {
/* set output sample rate for SB16 cards */
DSPPortB(DSP_DMA_DAC_RATE);
DSPPortB(HIBYTE(SB.nSampleRate));
DSPPortB(LOBYTE(SB.nSampleRate));
}
else {
/* set input/output sample rate for SB/SB20/SBPro cards */
dwBytesPerSecond = SB.nSampleRate;
if (SB.wFormat & AUDIO_FORMAT_STEREO)
dwBytesPerSecond <<= 1;
DSPPortB(DSP_DMA_TIME_CONST);
DSPPortB((65536 - (256000000L / dwBytesPerSecond)) >> 8);
}
DEBUG(printf("DSPStartPlayback: start playback transfer\n"));
/* start DMA playback transfer */
if (SB.wId == AUDIO_PRODUCT_SB) {
/*
* Start 8 bit mono low speed oneshot DMA output
* transfer for SB 1.0 (DSP 1.x) cards.
*/
DSPPortB(DSP_DMA_DAC_8BIT);
DSPPortB(0xF0);
DSPPortB(0xFF);
}
else if (SB.wId == AUDIO_PRODUCT_SB15) {
/*
* Start 8 bit mono low speed autoinit DMA output
* transfer for SB 1.5 (DSP 2.0) cards.
*/
DSPPortB(DSP_DMA_BLOCK_SIZE);
DSPPortB(0xF0);
DSPPortB(0xFF);
DSPPortB(DSP_DMA_DAC_AI_8BIT);
}
else if (SB.wId == AUDIO_PRODUCT_SB20) {
/*
* Start 8 bit mono high speed autoinit DMA transfer
* output transfer for SB 2.0 (DSP 2.01) cards.
*/
DSPPortB(DSP_DMA_BLOCK_SIZE);
DSPPortB(0xF0);
DSPPortB(0xFF);
DSPPortB(DSP_DMA_DAC_AI_HS_8BIT);
}
else if (SB.wId == AUDIO_PRODUCT_SBPRO) {
/*
* Start 8 bit mono/stereo high speed autoinit
* DMA transfer for SB Pro (DSP 3.x) cards.
*/
DSPPortB(DSP_DMA_BLOCK_SIZE);
DSPPortB(0xF0);
DSPPortB(0xFF);
DSPPortB(DSP_DMA_DAC_AI_HS_8BIT);
}
else {
/*
* Start 8/16 bit mono/stereo high speed autoinit
* DMA transfer for SB16 (DSP 4.x) cards.
*/
if (SB.wFormat & AUDIO_FORMAT_16BITS) {
DSPPortB(DSP_DMA_START_16BIT | B_DSP_DMA_DAC_MODE);
DSPPortB(B_DSP_DMA_SIGNED | (SB.wFormat & AUDIO_FORMAT_STEREO ?
B_DSP_DMA_STEREO : B_DSP_DMA_MONO));
DSPPortB(0xF0);
DSPPortB(0xFF);
}
else {
DSPPortB(DSP_DMA_START_8BIT | B_DSP_DMA_DAC_MODE);
DSPPortB(B_DSP_DMA_UNSIGNED | (SB.wFormat & AUDIO_FORMAT_STEREO ?
B_DSP_DMA_STEREO : B_DSP_DMA_MONO));
DSPPortB(0xF0);
DSPPortB(0xFF);
}
}
}
static VOID DSPStopPlayback(VOID)
{
DEBUG(printf("DSPStopPlayback: reset DSP processor\n"));
/* reset the DSP processor */
DSPReset();
DEBUG(printf("DSPStopPlayback: turn off speaker\n"));
/* turn off DSP speaker */
DSPPortB(DSP_SPEAKER_OFF);
/* turn off the stereo flag for SBPro cards */
if (SB.wId == AUDIO_PRODUCT_SBPRO) {
DSPMixerB(MIXER_OUTPUT_CONTROL,
DSPMixerRB(MIXER_OUTPUT_CONTROL) & ~OUTPUT_ENABLE_VSTC);
}
DEBUG(printf("DSPStopPlayback: restore DMA %d and IRQ %d resources\n", SB.nDmaChannel, SB.nIrqLine));
/* restore the interrupt handler */
DosSetVectorHandler(SB.nIrqLine, NULL);
/* reset the DMA channel parameters */
DosDisableChannel(SB.nDmaChannel);
}
static UINT DSPInitAudio(VOID)
{
#define CLIP(nRate, nMinRate, nMaxRate) \
(nRate < nMinRate ? nMinRate : \
(nRate > nMaxRate ? nMaxRate : nRate)) \
DEBUG(printf("DSPInitAudio: probe SB hardware at port 0x%03x\n", SB.wPort));
/*
* Probe if there is a SB present and detect the DSP version.
*/
if (DSPProbe())
return AUDIO_ERROR_NODEVICE;
DEBUG(printf("DSPInitAudio: check format and sample rate\n"));
/*
* Check playback encoding format and sampling frequency
*/
if (SB.wId == AUDIO_PRODUCT_SB) {
SB.nSampleRate = CLIP(SB.nSampleRate, 4000, 22050);
SB.wFormat &= ~(AUDIO_FORMAT_16BITS | AUDIO_FORMAT_STEREO);
}
else if (SB.wId == AUDIO_PRODUCT_SB15) {
SB.nSampleRate = CLIP(SB.nSampleRate, 5000, 22050);
SB.wFormat &= ~(AUDIO_FORMAT_16BITS | AUDIO_FORMAT_STEREO);
}
else if (SB.wId == AUDIO_PRODUCT_SB20) {
SB.nSampleRate = CLIP(SB.nSampleRate, 5000, 44100);
SB.wFormat &= ~(AUDIO_FORMAT_16BITS | AUDIO_FORMAT_STEREO);
}
else if (SB.wId == AUDIO_PRODUCT_SBPRO) {
if (SB.wFormat & AUDIO_FORMAT_STEREO) {
SB.nSampleRate = CLIP(SB.nSampleRate, 5000, 22050);
}
else {
SB.nSampleRate = CLIP(SB.nSampleRate, 5000, 44100);
}
SB.wFormat &= ~AUDIO_FORMAT_16BITS;
}
else {
SB.nSampleRate = CLIP(SB.nSampleRate, 5000, 44100);
}
if (SB.wId != AUDIO_PRODUCT_SB16) {
SB.nSampleRate = (65536 - (256000000L / SB.nSampleRate)) >> 8;
SB.nSampleRate = 1000000L / (256 - SB.nSampleRate);
}
SB.nDmaChannel = (SB.wFormat & AUDIO_FORMAT_16BITS ?
SB.nHighDmaChannel : SB.nLowDmaChannel);
DEBUG(printf("DSPInitAudio: DMA channel %d selected\n", SB.nDmaChannel));
return AUDIO_ERROR_NONE;
}
static VOID DSPDoneAudio(VOID)
{
DEBUG(printf("DSPDoneAudio: reset DSP processor\n"));
DSPReset();
}
/*
* Sound Blaster audio driver API interface
*/
static UINT AIAPI GetAudioCaps(LPAUDIOCAPS lpCaps)
{
static AUDIOCAPS Caps =
{
AUDIO_PRODUCT_SB, "Sound Blaster",
AUDIO_FORMAT_1M08 |
AUDIO_FORMAT_2M08
};
static AUDIOCAPS Caps15 =
{
AUDIO_PRODUCT_SB15, "Sound Blaster 1.5",
AUDIO_FORMAT_1M08 |
AUDIO_FORMAT_2M08
};
static AUDIOCAPS Caps20 =
{
AUDIO_PRODUCT_SB20, "Sound Blaster 2.0",
AUDIO_FORMAT_1M08 |
AUDIO_FORMAT_2M08 |
AUDIO_FORMAT_4M08
};
static AUDIOCAPS CapsPro =
{
AUDIO_PRODUCT_SBPRO, "Sound Blaster Pro",
AUDIO_FORMAT_1M08 | AUDIO_FORMAT_1S08 |
AUDIO_FORMAT_2M08 | AUDIO_FORMAT_2S08 |
AUDIO_FORMAT_4M08
};
static AUDIOCAPS Caps16 =
{
AUDIO_PRODUCT_SB16, "Sound Blaster 16",
AUDIO_FORMAT_1M08 | AUDIO_FORMAT_1S08 |
AUDIO_FORMAT_1M16 | AUDIO_FORMAT_1S16 |
AUDIO_FORMAT_2M08 | AUDIO_FORMAT_2S08 |
AUDIO_FORMAT_2M16 | AUDIO_FORMAT_2S16 |
AUDIO_FORMAT_4M08 | AUDIO_FORMAT_4S08 |
AUDIO_FORMAT_4M16 | AUDIO_FORMAT_4S16
};
switch (SB.wId) {
case AUDIO_PRODUCT_SB16:
memcpy(lpCaps, &Caps16, sizeof(AUDIOCAPS));
break;
case AUDIO_PRODUCT_SBPRO:
memcpy(lpCaps, &CapsPro, sizeof(AUDIOCAPS));
break;
case AUDIO_PRODUCT_SB20:
memcpy(lpCaps, &Caps20, sizeof(AUDIOCAPS));
break;
case AUDIO_PRODUCT_SB15:
memcpy(lpCaps, &Caps15, sizeof(AUDIOCAPS));
break;
default:
memcpy(lpCaps, &Caps, sizeof(AUDIOCAPS));
break;
}
return AUDIO_ERROR_NONE;
}
static UINT AIAPI PingAudio(VOID)
{
LPSTR lpszBlaster;
UINT nChar;
DEBUG(printf("SBPingAudio: fetch BLASTER variable\n"));
SB.wId = AUDIO_PRODUCT_SB16;
SB.wPort = 0x220;
SB.nIrqLine = 5;
SB.nLowDmaChannel = 1;
SB.nHighDmaChannel = 5;
if ((lpszBlaster = DosGetEnvironment("BLASTER")) != NULL) {
nChar = DosParseString(lpszBlaster, TOKEN_CHAR);
while (nChar != 0) {
switch (nChar) {
case 'A':
case 'a':
SB.wPort = DosParseString(NULL, TOKEN_HEX);
break;
case 'I':
case 'i':
SB.nIrqLine = DosParseString(NULL, TOKEN_DEC);
break;
case 'D':
case 'd':
SB.nLowDmaChannel = DosParseString(NULL, TOKEN_DEC);
break;
case 'H':
case 'h':
SB.nHighDmaChannel = DosParseString(NULL, TOKEN_DEC);
break;
case 'T':
case 't':
switch (DosParseString(NULL, TOKEN_DEC)) {
case 1: SB.wId = AUDIO_PRODUCT_SB; break;
case 2: SB.wId = AUDIO_PRODUCT_SB15; break; /*[1998/12/24]*/
case 3: SB.wId = AUDIO_PRODUCT_SB20; break;
case 4: SB.wId = AUDIO_PRODUCT_SBPRO; break;
case 5: SB.wId = AUDIO_PRODUCT_SBPRO; break;
case 6: SB.wId = AUDIO_PRODUCT_SB16; break;
}
break;
}
nChar = DosParseString(NULL, TOKEN_CHAR);
}
DEBUG(printf("SBPingAudio: probe SB hardware at Port 0x%03x, IRQ %d, DMA %d/%d\n", SB.wPort, SB.nIrqLine, SB.nLowDmaChannel, SB.nHighDmaChannel));
return DSPProbe();
}
return AUDIO_ERROR_NODEVICE;
}
static UINT AIAPI OpenAudio(LPAUDIOINFO lpInfo)
{
DWORD dwBytesPerSecond;
DEBUG(printf("SBOpenAudio: initialize SB driver\n"));
/*
* Initialize the SB audio driver for playback
*/
memset(&SB, 0, sizeof(SB));
SB.wFormat = lpInfo->wFormat;
SB.nSampleRate = lpInfo->nSampleRate;
if (PingAudio())
return AUDIO_ERROR_NODEVICE;
if (DSPInitAudio())
return AUDIO_ERROR_NODEVICE;
DEBUG(printf("SBOpenAudio: allocate DMA buffer\n"));
/*
* Allocate DMA channel buffer and start playback transfers
*/
dwBytesPerSecond = SB.nSampleRate;
if (SB.wFormat & AUDIO_FORMAT_16BITS)
dwBytesPerSecond <<= 1;
if (SB.wFormat & AUDIO_FORMAT_STEREO)
dwBytesPerSecond <<= 1;
SB.nBufferSize = dwBytesPerSecond / (1000 / BUFFERSIZE);
SB.nBufferSize = (SB.nBufferSize + BUFFRAGSIZE) & -BUFFRAGSIZE;
if (DosAllocChannel(SB.nDmaChannel, SB.nBufferSize)) {
DSPDoneAudio();
return AUDIO_ERROR_NOMEMORY;
}
if ((SB.lpBuffer = DosLockChannel(SB.nDmaChannel)) != NULL) {
memset(SB.lpBuffer, SB.wFormat & AUDIO_FORMAT_16BITS ?
0x00 : 0x80, SB.nBufferSize);
DosUnlockChannel(SB.nDmaChannel);
}
DEBUG(printf("SBOpenAudio: start playback\n"));
DSPStartPlayback();
/* refresh caller's encoding format and sampling frequency */
lpInfo->wFormat = SB.wFormat;
lpInfo->nSampleRate = SB.nSampleRate;
return AUDIO_ERROR_NONE;
}
static UINT AIAPI CloseAudio(VOID)
{
DEBUG(printf("SBCloseAudio: shutdown playback and release resources\n"));
/*
* Stop DMA playback transfers and reset the DSP processor
*/
DSPStopPlayback();
DosFreeChannel(SB.nDmaChannel);
DSPDoneAudio();
return AUDIO_ERROR_NONE;
}
static UINT AIAPI UpdateAudio(UINT nFrames)
{
int nBlockSize, nSize;
if (SB.wFormat & AUDIO_FORMAT_16BITS) nFrames <<= 1;
if (SB.wFormat & AUDIO_FORMAT_STEREO) nFrames <<= 1;
if (nFrames <= 0 || nFrames > SB.nBufferSize)
nFrames = SB.nBufferSize;
if ((SB.lpBuffer = DosLockChannel(SB.nDmaChannel)) != NULL) {
nBlockSize = SB.nBufferSize - SB.nPosition -
DosGetChannelCount(SB.nDmaChannel);
if (nBlockSize < 0)
nBlockSize += SB.nBufferSize;
if (nBlockSize > nFrames)
nBlockSize = nFrames;
nBlockSize &= -BUFFRAGSIZE;
while (nBlockSize != 0) {
nSize = SB.nBufferSize - SB.nPosition;
if (nSize > nBlockSize)
nSize = nBlockSize;
if (SB.lpfnAudioWave != NULL) {
SB.lpfnAudioWave(&SB.lpBuffer[SB.nPosition], nSize);
}
else {
memset(&SB.lpBuffer[SB.nPosition],
SB.wFormat & AUDIO_FORMAT_16BITS ?
0x00 : 0x80, nSize);
}
if ((SB.nPosition += nSize) >= SB.nBufferSize)
SB.nPosition -= SB.nBufferSize;
nBlockSize -= nSize;
}
DosUnlockChannel(SB.nDmaChannel);
}
return AUDIO_ERROR_NONE;
}
static UINT AIAPI SetAudioCallback(LPFNAUDIOWAVE lpfnAudioWave)
{
SB.lpfnAudioWave = lpfnAudioWave;
return AUDIO_ERROR_NONE;
}
/*
* Sound Blaster drivers public interface
*/
AUDIOWAVEDRIVER SoundBlasterWaveDriver =
{
GetAudioCaps, PingAudio, OpenAudio, CloseAudio,
UpdateAudio, SetAudioCallback
};
AUDIODRIVER SoundBlasterDriver =
{
&SoundBlasterWaveDriver, NULL
};

183
seal-hack/src/sdldrv.c Normal file
View File

@@ -0,0 +1,183 @@
/*
* $Id: lnxdrv.c 1.5 1996/08/05 18:51:19 chasan released $
*
* SDL audio driver. Turns SEAL into a mixer on top of SDL.
*
* Copyright 2002 Greg Velichansky (hmaon@bumba.net)
*
* Based in part on the Linux Voxware driver,
* Copyright (C) 1995-1999 Carlos Hasan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include "SDL.h"
#include "audio.h"
#include "drivers.h"
/*
* fragments defines
*/
#define NUMFRAGS 16
#define FRAGSIZE 11
#define BUFFERSIZE (1 << FRAGSIZE)
/*
* configuration structure
*/
static struct AudioStruct {
SDL_AudioSpec desired, spec;
BYTE aBuffer[BUFFERSIZE*4];
LPFNAUDIOWAVE lpfnAudioWave;
WORD wFormat;
} Audio;
/*
* Linux driver API interface
*/
static UINT AIAPI GetAudioCaps(LPAUDIOCAPS lpCaps)
{
static AUDIOCAPS Caps =
{
AUDIO_PRODUCT_LINUX, "SDL",
AUDIO_FORMAT_1M08 | AUDIO_FORMAT_1S08 |
AUDIO_FORMAT_1M16 | AUDIO_FORMAT_1S16 |
AUDIO_FORMAT_2M08 | AUDIO_FORMAT_2S08 |
AUDIO_FORMAT_2M16 | AUDIO_FORMAT_2S16 |
AUDIO_FORMAT_4M08 | AUDIO_FORMAT_4S08 |
AUDIO_FORMAT_4M16 | AUDIO_FORMAT_4S16
};
memcpy(lpCaps, &Caps, sizeof(AUDIOCAPS));
return AUDIO_ERROR_NONE;
}
static UINT AIAPI PingAudio(VOID)
{
return 0;
/* return (SDL_INIT_AUDIO == SDL_WasInit(SDL_INIT_AUDIO)); */
}
static void updatecallback(void *userdata, Uint8 *stream, int len);
static UINT AIAPI OpenAudio(LPAUDIOINFO lpInfo)
{
int nBitsPerSample, nStereoOn, nSampleRate, nFrags;
memset(&Audio, 0, sizeof(Audio));
if (!SDL_WasInit(SDL_INIT_EVERYTHING))
{
SDL_Init(SDL_INIT_AUDIO);
} else
{
if (!SDL_WasInit(SDL_INIT_AUDIO) && SDL_InitSubSystem(SDL_INIT_AUDIO))
return AUDIO_ERROR_NODEVICE;
}
if (SDL_INIT_AUDIO != SDL_WasInit(SDL_INIT_AUDIO))
return AUDIO_ERROR_NODEVICE;
nBitsPerSample = lpInfo->wFormat & AUDIO_FORMAT_16BITS ? 16 : 8;
nStereoOn = lpInfo->wFormat & AUDIO_FORMAT_STEREO ? 1 : 0;
/*nSampleRate = lpInfo->nSampleRate;*/
Audio.desired.freq = lpInfo->nSampleRate;
Audio.desired.samples = 512;
Audio.desired.channels = nStereoOn ? 2 : 1;
Audio.desired.format = (lpInfo->wFormat & AUDIO_FORMAT_16BITS) ? AUDIO_U16SYS : AUDIO_U8;
Audio.desired.userdata = (void*)&Audio;
Audio.desired.callback = updatecallback;
SDL_OpenAudio(&(Audio.desired), &(Audio.spec));
/* we should probably do something here... blah... whatever :/ */
/* setup number and size of buffer fragments */
/*nFrags = (NUMFRAGS << 16) + (FRAGSIZE);
ioctl(Audio.nHandle, SNDCTL_DSP_SETFRAGMENT, &nFrags);*/
/* setup audio playback encoding format and sampling frequency */
/*if (ioctl(Audio.nHandle, SNDCTL_DSP_SAMPLESIZE, &nBitsPerSample) < 0 ||
ioctl(Audio.nHandle, SNDCTL_DSP_STEREO, &nStereoOn) < 0 ||
ioctl(Audio.nHandle, SNDCTL_DSP_SPEED, &nSampleRate) < 0) {
close(Audio.nHandle);
return AUDIO_ERROR_BADFORMAT;
}*/
/*Audio.wFormat = lpInfo->wFormat;*/
return AUDIO_ERROR_NONE;
}
static UINT AIAPI CloseAudio(VOID)
{
SDL_CloseAudio();
return AUDIO_ERROR_NONE;
}
static UINT AIAPI UpdateAudio(UINT nFrames)
{
/* compute frame size */
/*if (Audio.wFormat & AUDIO_FORMAT_16BITS) nFrames <<= 1;
if (Audio.wFormat & AUDIO_FORMAT_STEREO) nFrames <<= 1;
if (nFrames <= 0 || nFrames > sizeof(Audio.aBuffer))
nFrames = sizeof(Audio.aBuffer);*/
/* send PCM samples to the DSP audio device */
/*if (Audio.lpfnAudioWave != NULL) {
Audio.lpfnAudioWave(Audio.aBuffer, nFrames);
write(Audio.nHandle, Audio.aBuffer, nFrames);
}*/
SDL_PauseAudio(0); /* the only use I can think of for UpdateAudio() ...*/
return AUDIO_ERROR_NONE;
}
static void updatecallback(void *userdata, Uint8 *stream, int len)
{
struct AudioStruct *aud = userdata;
/* maybe this isn't necessary, we know where Audio is, after all... */
aud->lpfnAudioWave(stream, len); /* God speed... */
}
static UINT AIAPI SetAudioCallback(LPFNAUDIOWAVE lpfnAudioWave)
{
/* set up DSP audio device user's callback function */
Audio.lpfnAudioWave = lpfnAudioWave;
return AUDIO_ERROR_NONE;
}
/*
* Linux driver public interface
*/
AUDIOWAVEDRIVER SDLWaveDriver =
{
GetAudioCaps, PingAudio, OpenAudio, CloseAudio,
UpdateAudio, SetAudioCallback
};
AUDIODRIVER SDLDriver =
{
&SDLWaveDriver, NULL
};

135
seal-hack/src/sgidrv.c Normal file
View File

@@ -0,0 +1,135 @@
/*
* $Id: sgidrv.c 1.5 1996/08/05 18:51:19 chasan released $
*
* Silicon Graphics Indigo audio driver.
*
* Copyright (C) 1995-1999 Carlos Hasan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <audio.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include "audio.h"
#include "drivers.h"
/*
* SGI audio driver buffer size
*/
#define BUFFERSIZE 2048
/*
* SGI audio driver configuration structure
*/
static struct {
ALport Port;
ALconfig Config;
WORD wFormat;
BYTE aBuffer[BUFFERSIZE];
LPFNAUDIOWAVE lpfnAudioWave;
} Audio;
/*
* SGI audio driver API interface
*/
static UINT AIAPI GetAudioCaps(LPAUDIOCAPS lpCaps)
{
static AUDIOCAPS Caps =
{
AUDIO_PRODUCT_SGI, "Silicon Graphics",
AUDIO_FORMAT_1M08 | AUDIO_FORMAT_1S08 |
AUDIO_FORMAT_1M16 | AUDIO_FORMAT_1S16 |
AUDIO_FORMAT_2M08 | AUDIO_FORMAT_2S08 |
AUDIO_FORMAT_2M16 | AUDIO_FORMAT_2S16 |
AUDIO_FORMAT_4M08 | AUDIO_FORMAT_4S08 |
AUDIO_FORMAT_4M16 | AUDIO_FORMAT_4S16
};
memcpy(lpCaps, &Caps, sizeof(AUDIOCAPS));
return AUDIO_ERROR_NONE;
}
static UINT AIAPI PingAudio(VOID)
{
return AUDIO_ERROR_NONE;
}
static UINT AIAPI OpenAudio(LPAUDIOINFO lpInfo)
{
long op[2];
memset(&Audio, 0, sizeof(Audio));
if ((Audio.Config = ALnewconfig()) != NULL) {
/* setup encoding format for playback */
ALsetwidth(Audio.Config, lpInfo->wFormat & AUDIO_FORMAT_16BITS ?
AL_SAMPLE_16 : AL_SAMPLE_8);
ALsetchannels(Audio.Config, lpInfo->wFormat & AUDIO_FORMAT_STEREO ?
AL_STEREO : AL_MONO);
/* open audio port and configure it */
Audio.Port = ALopenport("Audio Port", "w", Audio.Config);
Audio.wFormat = lpInfo->wFormat;
/* setup playback sampling frequency */
if (Audio.Port != NULL) {
op[0] = AL_OUTPUT_RATE;
op[1] = lpInfo->nSampleRate;
ALsetparms(AL_DEFAULT_DEVICE, op, 2);
return AUDIO_ERROR_NONE;
}
}
return AUDIO_ERROR_DEVICEBUSY;
}
static UINT AIAPI CloseAudio(VOID)
{
while (ALgetfilled(Audio.Port) > 0)
sleep(1);
ALcloseport(Audio.Port);
ALfreeconfig(Audio.Config);
return AUDIO_ERROR_NONE;
}
static UINT AIAPI UpdateAudio(UINT nFrames)
{
if (Audio.wFormat & AUDIO_FORMAT_16BITS) nFrames <<= 1;
if (Audio.wFormat & AUDIO_FORMAT_STEREO) nFrames <<= 1;
if (nFrames <= 0 || nFrames >= sizeof(Audio.aBuffer))
nFrames = sizeof(Audio.aBuffer);
if (Audio.lpfnAudioWave != NULL) {
Audio.lpfnAudioWave(Audio.aBuffer, nFrames);
ALwritesamps(Audio.Port, Audio.aBuffer, nFrames >>
((Audio.wFormat & AUDIO_FORMAT_16BITS) != 0));
}
return AUDIO_ERROR_NONE;
}
static UINT AIAPI SetAudioCallback(LPFNAUDIOWAVE lpfnAudioWave)
{
Audio.lpfnAudioWave = lpfnAudioWave;
return AUDIO_ERROR_NONE;
}
/*
* SGI audio driver public interface
*/
AUDIOWAVEDRIVER SiliconWaveDriver =
{
GetAudioCaps, PingAudio, OpenAudio, CloseAudio,
UpdateAudio, SetAudioCallback
};
AUDIODRIVER SiliconDriver =
{
&SiliconWaveDriver, NULL
};

257
seal-hack/src/sundrv.c Normal file
View File

@@ -0,0 +1,257 @@
/*
* $Id: sundrv.c 1.5 1996/08/05 18:51:19 chasan released $
*
* SPARCstation SunOS and Solaris audio drivers.
*
* Copyright (C) 1995-1999 Carlos Hasan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <memory.h>
#ifdef __SOLARIS__
#include <sun/audio.io.h>
#else
#include <sun/audioio.h>
#endif
#include "audio.h"
#include "drivers.h"
/*
* SPARC driver audio buffer size
*/
#define BUFFERSIZE 2048
/*
* Table for 8 bit unsigned PCM linear to companded u-law conversion
* (Reference: CCITT Recommendation G.711)
*/
static BYTE auLawTable[256] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
0x01, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03,
0x03, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05,
0x05, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07,
0x07, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09,
0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b,
0x0b, 0x0c, 0x0c, 0x0c, 0x0c, 0x0d, 0x0d, 0x0d,
0x0d, 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f,
0x0f, 0x10, 0x10, 0x11, 0x11, 0x12, 0x12, 0x13,
0x13, 0x14, 0x14, 0x15, 0x15, 0x16, 0x16, 0x17,
0x17, 0x18, 0x18, 0x19, 0x19, 0x1a, 0x1a, 0x1b,
0x1b, 0x1c, 0x1c, 0x1d, 0x1d, 0x1e, 0x1e, 0x1f,
0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e,
0x2f, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c,
0x3e, 0x41, 0x45, 0x49, 0x4d, 0x53, 0x5b, 0x67,
0xff, 0xe7, 0xdb, 0xd3, 0xcd, 0xc9, 0xc5, 0xc1,
0xbe, 0xbc, 0xba, 0xb8, 0xb6, 0xb4, 0xb2, 0xb0,
0xaf, 0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9, 0xa8,
0xa7, 0xa6, 0xa5, 0xa4, 0xa3, 0xa2, 0xa1, 0xa0,
0x9f, 0x9f, 0x9e, 0x9e, 0x9d, 0x9d, 0x9c, 0x9c,
0x9b, 0x9b, 0x9a, 0x9a, 0x99, 0x99, 0x98, 0x98,
0x97, 0x97, 0x96, 0x96, 0x95, 0x95, 0x94, 0x94,
0x93, 0x93, 0x92, 0x92, 0x91, 0x91, 0x90, 0x90,
0x8f, 0x8f, 0x8f, 0x8f, 0x8e, 0x8e, 0x8e, 0x8e,
0x8d, 0x8d, 0x8d, 0x8d, 0x8c, 0x8c, 0x8c, 0x8c,
0x8b, 0x8b, 0x8b, 0x8b, 0x8a, 0x8a, 0x8a, 0x8a,
0x89, 0x89, 0x89, 0x89, 0x88, 0x88, 0x88, 0x88,
0x87, 0x87, 0x87, 0x87, 0x86, 0x86, 0x86, 0x86,
0x85, 0x85, 0x85, 0x85, 0x84, 0x84, 0x84, 0x84,
0x83, 0x83, 0x83, 0x83, 0x82, 0x82, 0x82, 0x82,
0x81, 0x81, 0x81, 0x81, 0x80, 0x80, 0x80, 0x80
};
/*
* Table of supported sampling frequencies of dbri devices
*/
static LONG aSampleRate[] =
{
8000, 9600, 11025, 16000, 18900, 22050, 32000, 37800, 44100, 48000
};
/*
* SPARC driver configuration structure
*/
static struct {
int nHandle;
int nEncoding;
BYTE aBuffer[BUFFERSIZE];
LPFNAUDIOWAVE lpfnAudioWave;
WORD wFormat;
} Audio;
static LONG GetSampleRate(LONG nSampleRate)
{
int n;
/* return the nearest supported sampling frequency */
for (n = 0; n < sizeof(aSampleRate) / sizeof(LONG) - 1; n++) {
if (nSampleRate <= aSampleRate[n])
break;
}
return aSampleRate[n];
}
/*
* SPARC audio driver API interface
*/
static UINT AIAPI GetAudioCaps(LPAUDIOCAPS lpCaps)
{
static AUDIOCAPS Caps =
{
AUDIO_PRODUCT_SPARC, "SPARC SunOS",
#ifdef __SOLARIS__
AUDIO_FORMAT_1M08 | AUDIO_FORMAT_1S08 |
AUDIO_FORMAT_1M16 | AUDIO_FORMAT_1S16 |
AUDIO_FORMAT_2M08 | AUDIO_FORMAT_2S08 |
AUDIO_FORMAT_2M16 | AUDIO_FORMAT_2S16 |
AUDIO_FORMAT_4M08 | AUDIO_FORMAT_4S08 |
AUDIO_FORMAT_4M16 | AUDIO_FORMAT_4S16
#else
AUDIO_FORMAT_1M08
#endif
};
memcpy(lpCaps, &Caps, sizeof(AUDIOCAPS));
return AUDIO_ERROR_NONE;
}
static UINT AIAPI PingAudio(VOID)
{
return access("/dev/audio", W_OK) ? AUDIO_ERROR_NODEVICE : AUDIO_ERROR_NONE;
}
static UINT AIAPI OpenAudio(LPAUDIOINFO lpInfo)
{
int dbri, type;
audio_info_t info;
#ifdef __SOLARIS__
audio_device_t dev;
#endif
memset(&Audio, 0, sizeof(Audio));
/* try to open the audio device for playback */
#ifdef __SOLARIS__
if ((Audio.nHandle = open("/dev/audio", O_WRONLY)) < 0)
return AUDIO_ERROR_DEVICEBUSY;
#else
if ((Audio.nHandle = open("/dev/audio", O_WRONLY | O_NDELAY)) < 0)
return AUDIO_ERROR_DEVICEBUSY;
#endif
/* check whether we know about linear encoding */
#ifdef __SOLARIS__
dbri = (ioctl(Audio.nHandle, AUDIO_GETDEV, &dev) == 0 &&
strcmp(dev.name, "SUNW,dbri") == 0);
#else
#ifdef AUDIO_GETDEV
dbri = (ioctl(Audio.nHandle, AUDIO_GETDEV, &type) == 0 &&
type != AUDIO_DEV_AMD);
#else
/*
* There is no AUDIO_GETDEV under SunOS 4.1.1 so we have to
* assume that there is an AMD device attached to /dev/audio.
*/
dbri = 0;
#endif
#endif
/* setup audio configuration structure */
AUDIO_INITINFO(&info);
if (dbri) {
/* configure linear encoding for dbri devices */
info.play.encoding = AUDIO_ENCODING_LINEAR;
info.play.channels = lpInfo->wFormat & AUDIO_FORMAT_STEREO ? 2 : 1;
info.play.precision = lpInfo->wFormat & AUDIO_FORMAT_16BITS ? 16 : 8;
info.play.sample_rate = GetSampleRate(lpInfo->nSampleRate);
}
else {
/* configure companded u-law encoding for AMD devices */
info.play.encoding = AUDIO_ENCODING_ULAW;
info.play.channels = 1;
info.play.precision = 8;
info.play.sample_rate = 8000;
}
/* commit playback encoding format */
Audio.nEncoding = info.play.encoding;
if (ioctl(Audio.nHandle, AUDIO_SETINFO, &info) < 0) {
close(Audio.nHandle);
return AUDIO_ERROR_BADFORMAT;
}
/* refresh configuration structure */
lpInfo->wFormat &= ~(AUDIO_FORMAT_16BITS | AUDIO_FORMAT_STEREO);
lpInfo->wFormat |= info.play.precision != 16 ?
AUDIO_FORMAT_8BITS : AUDIO_FORMAT_16BITS;
lpInfo->wFormat |= info.play.channels != 2 ?
AUDIO_FORMAT_MONO : AUDIO_FORMAT_STEREO;
lpInfo->nSampleRate = info.play.sample_rate;
Audio.wFormat = lpInfo->wFormat;
return AUDIO_ERROR_NONE;
}
static UINT AIAPI CloseAudio(VOID)
{
ioctl(Audio.nHandle, AUDIO_DRAIN, NULL);
close(Audio.nHandle);
return AUDIO_ERROR_NONE;
}
static UINT AIAPI UpdateAudio(UINT nFrames)
{
int n;
if (Audio.wFormat & AUDIO_FORMAT_16BITS) nFrames <<= 1;
if (Audio.wFormat & AUDIO_FORMAT_STEREO) nFrames <<= 1;
if (nFrames <= 0 || nFrames > sizeof(Audio.aBuffer))
nFrames = sizeof(Audio.aBuffer);
if (Audio.lpfnAudioWave != NULL) {
Audio.lpfnAudioWave(Audio.aBuffer, nFrames);
if (Audio.nEncoding == AUDIO_ENCODING_ULAW) {
for (n = 0; n < nFrames; n++) {
Audio.aBuffer[n] = auLawTable[Audio.aBuffer[n]];
}
}
write(Audio.nHandle, Audio.aBuffer, nFrames);
}
return AUDIO_ERROR_NONE;
}
static UINT AIAPI SetAudioCallback(LPFNAUDIOWAVE lpfnAudioWave)
{
Audio.lpfnAudioWave = lpfnAudioWave;
return AUDIO_ERROR_NONE;
}
/*
* SPARC audio driver public interface
*/
AUDIOWAVEDRIVER SparcWaveDriver =
{
GetAudioCaps, PingAudio, OpenAudio, CloseAudio,
UpdateAudio, SetAudioCallback
};
AUDIODRIVER SparcDriver =
{
&SparcWaveDriver, NULL
};

197
seal-hack/src/tables.h Normal file
View File

@@ -0,0 +1,197 @@
/*
* $Id: tables.h 1.4 1996/08/05 18:51:19 chasan released $
*
* Extended module player private resources.
*
* Copyright (C) 1995-1999 Carlos Hasan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef __TABLES_H
#define __TABLES_H
/* dwFrequency = 8363*2^((6*12*16*4 - wPeriod)/(12*16*4)) */
static LONG aFrequencyTable[12 * 16 * 4] =
{
535232, 534749, 534267, 533785, 533303, 532822, 532341, 531861,
531381, 530902, 530423, 529945, 529466, 528989, 528512, 528035,
527558, 527083, 526607, 526132, 525657, 525183, 524709, 524236,
523763, 523291, 522819, 522347, 521876, 521405, 520934, 520465,
519995, 519526, 519057, 518589, 518121, 517654, 517187, 516720,
516254, 515788, 515323, 514858, 514394, 513930, 513466, 513003,
512540, 512078, 511616, 511154, 510693, 510232, 509772, 509312,
508853, 508394, 507935, 507477, 507019, 506561, 506104, 505648,
505192, 504736, 504281, 503826, 503371, 502917, 502463, 502010,
501557, 501105, 500653, 500201, 499750, 499299, 498849, 498399,
497949, 497500, 497051, 496602, 496154, 495707, 495260, 494813,
494367, 493921, 493475, 493030, 492585, 492141, 491697, 491253,
490810, 490367, 489925, 489483, 489041, 488600, 488159, 487719,
487279, 486839, 486400, 485961, 485523, 485085, 484647, 484210,
483773, 483337, 482901, 482465, 482030, 481595, 481161, 480727,
480293, 479860, 479427, 478994, 478562, 478130, 477699, 477268,
476838, 476407, 475978, 475548, 475119, 474691, 474262, 473834,
473407, 472980, 472553, 472127, 471701, 471275, 470850, 470426,
470001, 469577, 469154, 468730, 468307, 467885, 467463, 467041,
466620, 466199, 465778, 465358, 464938, 464519, 464100, 463681,
463263, 462845, 462427, 462010, 461593, 461177, 460761, 460345,
459930, 459515, 459101, 458686, 458273, 457859, 457446, 457033,
456621, 456209, 455798, 455386, 454976, 454565, 454155, 453745,
453336, 452927, 452519, 452110, 451702, 451295, 450888, 450481,
450075, 449669, 449263, 448858, 448453, 448048, 447644, 447240,
446837, 446434, 446031, 445628, 445226, 444825, 444424, 444023,
443622, 443222, 442822, 442423, 442023, 441625, 441226, 440828,
440430, 440033, 439636, 439240, 438843, 438447, 438052, 437657,
437262, 436867, 436473, 436080, 435686, 435293, 434900, 434508,
434116, 433725, 433333, 432942, 432552, 432162, 431772, 431382,
430993, 430604, 430216, 429828, 429440, 429052, 428665, 428279,
427892, 427506, 427121, 426735, 426350, 425966, 425581, 425198,
424814, 424431, 424048, 423665, 423283, 422901, 422520, 422139,
421758, 421377, 420997, 420617, 420238, 419859, 419480, 419102,
418723, 418346, 417968, 417591, 417215, 416838, 416462, 416086,
415711, 415336, 414961, 414587, 414213, 413839, 413466, 413093,
412720, 412348, 411976, 411604, 411233, 410862, 410491, 410121,
409751, 409381, 409012, 408643, 408274, 407906, 407538, 407171,
406803, 406436, 406070, 405703, 405337, 404972, 404606, 404241,
403877, 403512, 403148, 402784, 402421, 402058, 401695, 401333,
400971, 400609, 400248, 399887, 399526, 399166, 398805, 398446,
398086, 397727, 397368, 397010, 396652, 396294, 395936, 395579,
395222, 394866, 394510, 394154, 393798, 393443, 393088, 392733,
392379, 392025, 391671, 391318, 390965, 390612, 390260, 389908,
389556, 389205, 388854, 388503, 388152, 387802, 387452, 387103,
386754, 386405, 386056, 385708, 385360, 385012, 384665, 384318,
383971, 383625, 383279, 382933, 382587, 382242, 381897, 381553,
381209, 380865, 380521, 380178, 379835, 379492, 379150, 378808,
378466, 378125, 377784, 377443, 377102, 376762, 376422, 376083,
375743, 375404, 375066, 374727, 374389, 374052, 373714, 373377,
373040, 372704, 372367, 372032, 371696, 371361, 371026, 370691,
370356, 370022, 369689, 369355, 369022, 368689, 368356, 368024,
367692, 367360, 367029, 366698, 366367, 366036, 365706, 365376,
365047, 364717, 364388, 364060, 363731, 363403, 363075, 362748,
362420, 362094, 361767, 361440, 361114, 360789, 360463, 360138,
359813, 359489, 359164, 358840, 358516, 358193, 357870, 357547,
357225, 356902, 356580, 356259, 355937, 355616, 355295, 354975,
354655, 354335, 354015, 353696, 353376, 353058, 352739, 352421,
352103, 351785, 351468, 351151, 350834, 350518, 350201, 349886,
349570, 349255, 348939, 348625, 348310, 347996, 347682, 347368,
347055, 346742, 346429, 346117, 345804, 345492, 345181, 344869,
344558, 344247, 343937, 343627, 343317, 343007, 342697, 342388,
342079, 341771, 341462, 341154, 340847, 340539, 340232, 339925,
339618, 339312, 339006, 338700, 338394, 338089, 337784, 337479,
337175, 336871, 336567, 336263, 335960, 335657, 335354, 335052,
334749, 334447, 334146, 333844, 333543, 333242, 332941, 332641,
332341, 332041, 331742, 331442, 331143, 330845, 330546, 330248,
329950, 329652, 329355, 329058, 328761, 328464, 328168, 327872,
327576, 327281, 326986, 326691, 326396, 326101, 325807, 325513,
325220, 324926, 324633, 324340, 324048, 323755, 323463, 323171,
322880, 322589, 322298, 322007, 321716, 321426, 321136, 320846,
320557, 320268, 319979, 319690, 319402, 319114, 318826, 318538,
318251, 317964, 317677, 317390, 317104, 316818, 316532, 316247,
315961, 315676, 315391, 315107, 314823, 314539, 314255, 313971,
313688, 313405, 313122, 312840, 312558, 312276, 311994, 311713,
311431, 311150, 310870, 310589, 310309, 310029, 309749, 309470,
309191, 308912, 308633, 308355, 308077, 307799, 307521, 307244,
306966, 306690, 306413, 306136, 305860, 305584, 305309, 305033,
304758, 304483, 304208, 303934, 303660, 303386, 303112, 302839,
302566, 302293, 302020, 301747, 301475, 301203, 300932, 300660,
300389, 300118, 299847, 299577, 299306, 299036, 298767, 298497,
298228, 297959, 297690, 297421, 297153, 296885, 296617, 296350,
296082, 295815, 295548, 295282, 295015, 294749, 294483, 294218,
293952, 293687, 293422, 293157, 292893, 292629, 292365, 292101,
291837, 291574, 291311, 291048, 290786, 290523, 290261, 289999,
289738, 289476, 289215, 288954, 288694, 288433, 288173, 287913,
287653, 287394, 287135, 286876, 286617, 286358, 286100, 285842,
285584, 285326, 285069, 284812, 284555, 284298, 284042, 283785,
283529, 283273, 283018, 282763, 282508, 282253, 281998, 281744,
281489, 281236, 280982, 280728, 280475, 280222, 279969, 279717,
279464, 279212, 278960, 278709, 278457, 278206, 277955, 277704,
277454, 277204, 276953, 276704, 276454, 276205, 275955, 275706,
275458, 275209, 274961, 274713, 274465, 274217, 273970, 273723,
273476, 273229, 272983, 272737, 272491, 272245, 271999, 271754,
271509, 271264, 271019, 270774, 270530, 270286, 270042, 269799,
269555, 269312, 269069, 268826, 268584, 268342, 268100, 267858
};
/* wPeriod = 4*16*428*2^(-nNote/(12*16)) */
static WORD aPeriodTable[12 * 16] =
{
27392, 27293, 27195, 27097, 26999, 26902, 26805, 26708,
26612, 26516, 26421, 26326, 26231, 26136, 26042, 25948,
25855, 25761, 25669, 25576, 25484, 25392, 25301, 25209,
25119, 25028, 24938, 24848, 24758, 24669, 24580, 24492,
24403, 24316, 24228, 24141, 24054, 23967, 23881, 23795,
23709, 23623, 23538, 23453, 23369, 23285, 23201, 23117,
23034, 22951, 22868, 22786, 22704, 22622, 22540, 22459,
22378, 22297, 22217, 22137, 22057, 21978, 21899, 21820,
21741, 21663, 21585, 21507, 21429, 21352, 21275, 21199,
21122, 21046, 20970, 20895, 20819, 20744, 20670, 20595,
20521, 20447, 20373, 20300, 20227, 20154, 20081, 20009,
19937, 19865, 19793, 19722, 19651, 19580, 19509, 19439,
19369, 19299, 19230, 19160, 19091, 19023, 18954, 18886,
18818, 18750, 18682, 18615, 18548, 18481, 18414, 18348,
18282, 18216, 18150, 18085, 18020, 17955, 17890, 17826,
17762, 17698, 17634, 17570, 17507, 17444, 17381, 17318,
17256, 17194, 17132, 17070, 17008, 16947, 16886, 16825,
16765, 16704, 16644, 16584, 16524, 16465, 16405, 16346,
16287, 16229, 16170, 16112, 16054, 15996, 15938, 15881,
15824, 15767, 15710, 15653, 15597, 15541, 15485, 15429,
15373, 15318, 15263, 15208, 15153, 15098, 15044, 14990,
14936, 14882, 14828, 14775, 14721, 14668, 14616, 14563,
14510, 14458, 14406, 14354, 14302, 14251, 14199, 14148,
14097, 14047, 13996, 13945, 13895, 13845, 13795, 13746
};
static BYTE aSineTable[32] =
{
0, 24, 49, 74, 97, 120, 141, 161,
180, 197, 212, 224, 235, 244, 250, 253,
255, 253, 250, 244, 235, 224, 212, 197,
180, 161, 141, 120, 97, 74, 49, 24
};
static signed char aRetrigTable[32] =
{
0, -1, -2, -4, -8, -16, 0, 0, 0, 1, 2, 4, 8, 16, 0, 0,
16, 16, 16, 16, 16, 16, 11, 8, 16, 16, 16, 16, 16, 16, 24, 32
};
static signed char aAutoVibratoTable[256] =
{
0, -1, -2, -4, -5, -7, -8,-10,
-11,-13,-15,-16,-18,-19,-21,-22,
-23,-25,-26,-28,-29,-31,-32,-33,
-35,-36,-37,-38,-40,-41,-42,-43,
-44,-45,-46,-47,-48,-49,-50,-51,
-52,-53,-54,-55,-55,-56,-57,-58,
-58,-59,-59,-60,-60,-61,-61,-61,
-62,-62,-62,-63,-63,-63,-63,-63,
-63,-63,-63,-63,-63,-63,-62,-62,
-62,-61,-61,-61,-60,-60,-59,-59,
-58,-58,-57,-56,-55,-55,-54,-53,
-52,-51,-50,-49,-48,-47,-46,-45,
-44,-43,-42,-41,-40,-38,-37,-36,
-35,-33,-32,-31,-29,-28,-26,-25,
-23,-22,-21,-19,-18,-16,-15,-13,
-11,-10, -8, -7, -5, -4, -2, -1,
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
};
#endif

152
seal-hack/src/wavfile.c Normal file
View File

@@ -0,0 +1,152 @@
/*
* $Id: wavfile.c 1.7 1996/09/13 15:10:22 chasan released $
*
* Windows RIFF/WAVE PCM file loader routines.
*
* Copyright (C) 1995-1999 Carlos Hasan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "audio.h"
#include "iofile.h"
/*
* Windows RIFF/WAVE PCM file structures
*/
#define FOURCC_RIFF 0x46464952L
#define FOURCC_WAVE 0x45564157L
#define FOURCC_FMT 0x20746D66L
#define FOURCC_DATA 0x61746164L
#define WAVE_FORMAT_PCM 1
typedef struct {
WORD wFormatTag;
WORD nChannels;
DWORD nSamplesPerSec;
DWORD nAvgBytesPerSec;
WORD nBlockAlign;
WORD wBitsPerSample;
} PCMWAVEFORMAT;
typedef struct {
DWORD fccId;
DWORD dwSize;
} CHUNKHEADER;
typedef struct {
DWORD fccId;
DWORD dwSize;
DWORD fccType;
} RIFFHEADER;
UINT AIAPI ALoadWaveFile(LPSTR lpszFileName,
LPAUDIOWAVE* lplpWave, DWORD dwFileOffset)
{
static RIFFHEADER Header;
static CHUNKHEADER Chunk;
static PCMWAVEFORMAT Fmt;
LPAUDIOWAVE lpWave;
UINT n, nErrorCode;
if (lplpWave == NULL) {
return AUDIO_ERROR_INVALPARAM;
}
*lplpWave = NULL;
if (AIOOpenFile(lpszFileName)) {
return AUDIO_ERROR_FILENOTFOUND;
}
AIOSeekFile(dwFileOffset, SEEK_SET);
if ((lpWave = (LPAUDIOWAVE) calloc(1, sizeof(AUDIOWAVE))) == NULL) {
AIOCloseFile();
return AUDIO_ERROR_NOMEMORY;
}
/* read RIFF/WAVE header structure */
AIOReadLong(&Header.fccId);
AIOReadLong(&Header.dwSize);
AIOReadLong(&Header.fccType);
Header.dwSize += (Header.dwSize & 1);
if (Header.fccId != FOURCC_RIFF || Header.fccType != FOURCC_WAVE) {
AIOCloseFile();
AFreeWaveFile(lpWave);
return AUDIO_ERROR_BADFILEFORMAT;
}
memset(&Fmt, 0, sizeof(Fmt));
Header.dwSize -= sizeof(Header.fccType);
while (Header.dwSize != 0) {
/* read RIFF chunk header structure */
AIOReadLong(&Chunk.fccId);
AIOReadLong(&Chunk.dwSize);
Chunk.dwSize += (Chunk.dwSize & 1);
Header.dwSize -= sizeof(Chunk) + Chunk.dwSize;
if (Chunk.fccId == FOURCC_FMT) {
/* read RIFF/WAVE format chunk */
AIOReadShort(&Fmt.wFormatTag);
AIOReadShort(&Fmt.nChannels);
AIOReadLong(&Fmt.nSamplesPerSec);
AIOReadLong(&Fmt.nAvgBytesPerSec);
AIOReadShort(&Fmt.nBlockAlign);
AIOReadShort(&Fmt.wBitsPerSample);
AIOSeekFile(Chunk.dwSize - sizeof(Fmt), SEEK_CUR);
}
else if (Chunk.fccId == FOURCC_DATA) {
/* read RIFF/WAVE data chunk */
if (Fmt.wFormatTag != WAVE_FORMAT_PCM) {
AIOCloseFile();
AFreeWaveFile(lpWave);
return AUDIO_ERROR_BADFILEFORMAT;
}
lpWave->dwLength = Chunk.dwSize;
lpWave->nSampleRate = (WORD) Fmt.nSamplesPerSec;
lpWave->wFormat = AUDIO_FORMAT_8BITS | AUDIO_FORMAT_MONO;
if (Fmt.wBitsPerSample != 8)
lpWave->wFormat |= AUDIO_FORMAT_16BITS;
if (Fmt.nChannels != 1)
lpWave->wFormat |= AUDIO_FORMAT_STEREO;
if ((nErrorCode = ACreateAudioData(lpWave)) != AUDIO_ERROR_NONE) {
AIOCloseFile();
AFreeWaveFile(lpWave);
return nErrorCode;
}
AIOReadFile(lpWave->lpData, lpWave->dwLength);
if (!(lpWave->wFormat & AUDIO_FORMAT_16BITS)) {
for (n = 0; n < lpWave->dwLength; n++)
lpWave->lpData[n] ^= 0x80;
}
AWriteAudioData(lpWave, 0, lpWave->dwLength);
AIOCloseFile();
*lplpWave = lpWave;
return AUDIO_ERROR_NONE;
}
else {
/* skip unknown RIFF/WAVE chunks */
AIOSeekFile(Chunk.dwSize, SEEK_CUR);
}
}
AIOCloseFile();
return AUDIO_ERROR_BADFILEFORMAT;
}
UINT AIAPI AFreeWaveFile(LPAUDIOWAVE lpWave)
{
UINT rc;
rc = ADestroyAudioData(lpWave); /*** FIX: 04/12/98 ***/
free(lpWave);
return rc;
}

208
seal-hack/src/windrv.c Normal file
View File

@@ -0,0 +1,208 @@
/*
* $Id: windrv.c 1.10 1997/01/05 16:22:59 chasan Exp $
*
* Windows Wave audio driver.
*
* Copyright (c) 1995-1999 Carlos Hasan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <string.h>
#include <windows.h>
#include <mmsystem.h>
#include "audio.h"
#include "drivers.h"
/*
* Windows waveform block defines
*/
#define BUFFERSIZE 50 /* buffer size in milliseconds */
#define BUFFRAGSIZE 16 /* buffer fragment size in bytes */
#define NUMBLOCKS 3 /* total number of buffers [1998/12/24] */
/*
* Windows Wave output configuration structure
*/
static struct {
HWAVEOUT nHandle;
HGLOBAL aBlockHandle[NUMBLOCKS];
WAVEHDR aWaveHeader[NUMBLOCKS];
UINT nBlockIndex;
LPFNAUDIOWAVE lpfnAudioWave;
} WaveOut;
/*
* Windows Wave driver API routines
*/
static UINT AIAPI GetAudioCaps(LPAUDIOCAPS lpCaps)
{
WAVEOUTCAPS Caps;
if (waveOutGetDevCaps(WAVE_MAPPER, &Caps, sizeof(WAVEOUTCAPS)) != 0) {
strncpy(Caps.szPname, "Windows Wave", sizeof(Caps.szPname));
Caps.dwFormats = 0x00000000L;
}
strncpy(lpCaps->szProductName, Caps.szPname, sizeof(lpCaps->szProductName));
lpCaps->wProductId = AUDIO_PRODUCT_WINDOWS;
lpCaps->dwFormats = Caps.dwFormats;
return AUDIO_ERROR_NONE;
}
static UINT AIAPI PingAudio(VOID)
{
return waveOutGetNumDevs() ? AUDIO_ERROR_NONE : AUDIO_ERROR_NODEVICE;
}
static UINT AIAPI OpenAudio(LPAUDIOINFO lpInfo)
{
WAVEOUTCAPS caps;
PCMWAVEFORMAT format;
LONG nBufferSize;
UINT n;
memset(&WaveOut, 0, sizeof(WaveOut));
/* get wave output device capabilities */
if (waveOutGetDevCaps(WAVE_MAPPER, &caps, sizeof(WAVEOUTCAPS)) != 0) {
if (!(caps.dwFormats & (WAVE_FORMAT_1S08 | WAVE_FORMAT_1S16 |
WAVE_FORMAT_2S08 | WAVE_FORMAT_2S16 |
WAVE_FORMAT_4S08 | WAVE_FORMAT_4S16)))
lpInfo->wFormat &= ~AUDIO_FORMAT_STEREO;
if (!(caps.dwFormats & (WAVE_FORMAT_1M16 | WAVE_FORMAT_1S16 |
WAVE_FORMAT_2M16 | WAVE_FORMAT_2S16 |
WAVE_FORMAT_4M16 | WAVE_FORMAT_4S16)))
lpInfo->wFormat &= ~AUDIO_FORMAT_16BITS;
if (!(caps.dwFormats & (WAVE_FORMAT_4M08 | WAVE_FORMAT_4M16 |
WAVE_FORMAT_4S08 | WAVE_FORMAT_4S16)))
if (lpInfo->nSampleRate > 22050)
lpInfo->nSampleRate = 22050;
}
/* setup PCM wave format structure */
format.wf.wFormatTag = WAVE_FORMAT_PCM;
format.wf.nChannels = lpInfo->wFormat & AUDIO_FORMAT_STEREO ? 2 : 1;
format.wBitsPerSample = lpInfo->wFormat & AUDIO_FORMAT_16BITS ? 16 : 8;
format.wf.nSamplesPerSec = lpInfo->nSampleRate;
format.wf.nAvgBytesPerSec = lpInfo->nSampleRate;
format.wf.nBlockAlign = sizeof(char);
if (lpInfo->wFormat & AUDIO_FORMAT_STEREO) {
format.wf.nAvgBytesPerSec <<= 1;
format.wf.nBlockAlign <<= 1;
}
if (lpInfo->wFormat & AUDIO_FORMAT_16BITS) {
format.wf.nAvgBytesPerSec <<= 1;
format.wf.nBlockAlign <<= 1;
}
/* open wave output device using the PCM format structure */
if (waveOutOpen(&WaveOut.nHandle, WAVE_MAPPER,
(LPWAVEFORMATEX) &format, 0, 0, 0) != 0) {
return AUDIO_ERROR_NODEVICE;
}
/* compute wave output block buffer size in bytes */
nBufferSize = lpInfo->nSampleRate / (1000 / BUFFERSIZE);
if (lpInfo->wFormat & AUDIO_FORMAT_16BITS)
nBufferSize <<= 1;
if (lpInfo->wFormat & AUDIO_FORMAT_STEREO)
nBufferSize <<= 1;
nBufferSize = (nBufferSize + BUFFRAGSIZE - 1) & -BUFFRAGSIZE;
/* allocate and lock memory for wave output block buffers */
for (n = 0; n < NUMBLOCKS; n++) {
WaveOut.aBlockHandle[n] =
GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, nBufferSize);
WaveOut.aWaveHeader[n].lpData =
GlobalLock(WaveOut.aBlockHandle[n]);
WaveOut.aWaveHeader[n].dwBufferLength = nBufferSize;
WaveOut.aWaveHeader[n].dwFlags = WHDR_DONE;
WaveOut.aWaveHeader[n].dwLoops = 0;
WaveOut.aWaveHeader[n].dwUser = 0;
}
return AUDIO_ERROR_NONE;
}
static UINT AIAPI CloseAudio(VOID)
{
UINT n, nErrorCode;
/* reset wave output device and stop all playing blocks */
waveOutReset(WaveOut.nHandle);
/* make sure all wave output block buffers are done */
nErrorCode = AUDIO_ERROR_NONE;
for (n = 0; n < NUMBLOCKS; n++) {
if (!(WaveOut.aWaveHeader[n].dwFlags & WHDR_DONE))
nErrorCode = AUDIO_ERROR_DEVICEBUSY;
}
/* unprepare, unlock and free wave output block buffers */
for (n = 0; n < NUMBLOCKS; n++) {
if (WaveOut.aWaveHeader[n].dwUser != 0) {
waveOutUnprepareHeader(WaveOut.nHandle,
&WaveOut.aWaveHeader[n], sizeof(WAVEHDR));
}
GlobalUnlock(WaveOut.aBlockHandle[n]);
GlobalFree(WaveOut.aBlockHandle[n]);
}
/* close wave output device */
waveOutClose(WaveOut.nHandle);
return nErrorCode;
}
static UINT AIAPI UpdateAudio(UINT nFrames)
{
LPWAVEHDR lpWaveHeader;
lpWaveHeader = &WaveOut.aWaveHeader[WaveOut.nBlockIndex];
if ((lpWaveHeader->dwFlags & WHDR_DONE) && WaveOut.lpfnAudioWave) {
if (lpWaveHeader->dwUser != 0) {
waveOutUnprepareHeader(WaveOut.nHandle,
lpWaveHeader, sizeof(WAVEHDR));
lpWaveHeader->dwUser = 0;
}
if (lpWaveHeader->lpData != NULL) {
lpWaveHeader->dwFlags = 0;
lpWaveHeader->dwUser = 1;
WaveOut.lpfnAudioWave((PUCHAR) lpWaveHeader->lpData,
lpWaveHeader->dwBufferLength);
waveOutPrepareHeader(WaveOut.nHandle,
lpWaveHeader, sizeof(WAVEHDR));
waveOutWrite(WaveOut.nHandle,
lpWaveHeader, sizeof(WAVEHDR));
}
if (++WaveOut.nBlockIndex >= NUMBLOCKS)
WaveOut.nBlockIndex = 0;
}
return AUDIO_ERROR_NONE;
}
static UINT AIAPI SetAudioCallback(LPFNAUDIOWAVE lpfnAudioWave)
{
WaveOut.lpfnAudioWave = lpfnAudioWave;
return AUDIO_ERROR_NONE;
}
/*
* Windows Wave driver public interface
*/
AUDIOWAVEDRIVER WindowsWaveDriver =
{
GetAudioCaps, PingAudio, OpenAudio, CloseAudio,
UpdateAudio, SetAudioCallback
};
AUDIODRIVER WindowsDriver =
{
&WindowsWaveDriver, NULL
};

1214
seal-hack/src/wssdrv.c Normal file

File diff suppressed because it is too large Load Diff

407
seal-hack/src/xmfile.c Normal file
View File

@@ -0,0 +1,407 @@
/*
* $Id: xmfile.c 1.6 1996/12/12 16:28:54 chasan Exp $
*
* Extended module file loader routines.
*
* Copyright (c) 1995-1999 Carlos Hasan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <stdio.h>
#include <limits.h>
//#include <malloc.h>
#include <stdlib.h>
#include <string.h>
#include "audio.h"
#include "iofile.h"
/*
* Extended module file structures
*/
#define XM_FILE_HEADER_SIZE 276
#define XM_PATTERN_HEADER_SIZE 9
#define XM_PATCH_HEADER_SIZE 29
#define XM_PATCH_BODY_SIZE 214
#define XM_SAMPLE_HEADER_SIZE 40
#define XM_MODULE_LINEAR 0x0001
#define XM_ENVELOPE_ON 0x0001
#define XM_ENVELOPE_SUSTAIN 0x0002
#define XM_ENVELOPE_LOOP 0x0004
#define XM_SAMPLE_LOOP 0x0001
#define XM_SAMPLE_PINGPONG 0x0002
#define XM_SAMPLE_16BITS 0x0010
typedef struct {
CHAR aIdText[17];
CHAR aModuleName[20];
BYTE bPadding;
CHAR aTrackerName[20];
WORD wVersion;
DWORD dwHeaderSize;
WORD nSongLength;
WORD nRestart;
WORD nTracks;
WORD nPatterns;
WORD nPatches;
WORD wFlags;
WORD nTempo;
WORD nBPM;
BYTE aOrderTable[256];
} XMFILEHEADER;
typedef struct {
DWORD dwHeaderSize;
BYTE nPacking;
WORD nRows;
WORD nSize;
} XMPATTERNHEADER;
typedef struct {
DWORD dwHeaderSize;
CHAR aPatchName[22];
BYTE nType;
WORD nSamples;
DWORD dwSampleHeaderSize;
BYTE aSampleNumber[96];
DWORD aVolumeEnvelope[12];
DWORD aPanningEnvelope[12];
BYTE nVolumePoints;
BYTE nPanningPoints;
BYTE nVolumeSustain;
BYTE nVolumeLoopStart;
BYTE nVolumeLoopEnd;
BYTE nPanningSustain;
BYTE nPanningLoopStart;
BYTE nPanningLoopEnd;
BYTE bVolumeFlags;
BYTE bPanningFlags;
BYTE nVibratoType;
BYTE nVibratoSweep;
BYTE nVibratoDepth;
BYTE nVibratoRate;
WORD nVolumeFadeout;
WORD wReserved;
} XMPATCHHEADER;
typedef struct {
DWORD dwLength;
DWORD dwLoopStart;
DWORD dwLoopLength;
BYTE nVolume;
BYTE nFinetune;
BYTE bFlags;
BYTE nPanning;
BYTE nRelativeNote;
BYTE bReserved;
CHAR aSampleName[22];
} XMSAMPLEHEADER;
/*
* Extended module loader routines
*/
static VOID XMDecodeSamples(LPAUDIOWAVE lpWave)
{
LPWORD lpwCode;
LPBYTE lpbCode;
UINT nDelta, nCount;
nDelta = 0;
nCount = lpWave->dwLength;
if (lpWave->wFormat & AUDIO_FORMAT_16BITS) {
lpwCode = (LPWORD) lpWave->lpData;
nCount >>= 1;
while (nCount--) {
#ifdef __BIGENDIAN__
*lpwCode = MAKEWORD(HIBYTE(*lpwCode), LOBYTE(*lpwCode));
#endif
nDelta = *lpwCode++ += nDelta;
}
}
else {
lpbCode = (LPBYTE) lpWave->lpData;
while (nCount--) {
nDelta = (BYTE) (*lpbCode++ += (BYTE) nDelta);
}
}
}
UINT AIAPI ALoadModuleXM(LPSTR lpszFileName,
LPAUDIOMODULE *lplpModule, DWORD dwFileOffset)
{
static XMFILEHEADER Header;
static XMPATTERNHEADER Pattern;
static XMPATCHHEADER Patch;
static XMSAMPLEHEADER Sample;
LPAUDIOMODULE lpModule;
LPAUDIOPATTERN lpPattern;
LPAUDIOPATCH lpPatch;
LPAUDIOSAMPLE lpSample;
UINT n, m, nErrorCode;
/* open XM module file */
if (AIOOpenFile(lpszFileName)) {
return AUDIO_ERROR_FILENOTFOUND;
}
AIOSeekFile(dwFileOffset, SEEK_SET);
if ((lpModule = (LPAUDIOMODULE) calloc(1, sizeof(AUDIOMODULE))) == NULL) {
AIOCloseFile();
return AUDIO_ERROR_NOMEMORY;
}
/* load XM module header structure */
AIOReadFile(Header.aIdText, sizeof(Header.aIdText));
AIOReadFile(Header.aModuleName, sizeof(Header.aModuleName));
AIOReadChar(&Header.bPadding);
AIOReadFile(Header.aTrackerName, sizeof(Header.aTrackerName));
AIOReadShort(&Header.wVersion);
AIOReadLong(&Header.dwHeaderSize);
AIOReadShort(&Header.nSongLength);
AIOReadShort(&Header.nRestart);
AIOReadShort(&Header.nTracks);
AIOReadShort(&Header.nPatterns);
AIOReadShort(&Header.nPatches);
AIOReadShort(&Header.wFlags);
AIOReadShort(&Header.nTempo);
AIOReadShort(&Header.nBPM);
AIOReadFile(&Header.aOrderTable, sizeof(Header.aOrderTable));
AIOSeekFile(Header.dwHeaderSize - XM_FILE_HEADER_SIZE, SEEK_CUR);
if (memcmp(Header.aIdText, "Extended Module: ", sizeof(Header.aIdText)) ||
Header.wVersion != 0x104 ||
Header.nSongLength > AUDIO_MAX_ORDERS ||
Header.nPatterns > AUDIO_MAX_PATTERNS ||
Header.nPatches > AUDIO_MAX_PATCHES ||
Header.nTracks > AUDIO_MAX_VOICES) {
AFreeModuleFile(lpModule);
AIOCloseFile();
return AUDIO_ERROR_BADFILEFORMAT;
}
/* initialize module structure */
strncpy(lpModule->szModuleName, Header.aModuleName,
sizeof(Header.aModuleName));
if (Header.wFlags & XM_MODULE_LINEAR)
lpModule->wFlags |= AUDIO_MODULE_LINEAR;
lpModule->nOrders = Header.nSongLength;
lpModule->nRestart = Header.nRestart;
lpModule->nTracks = Header.nTracks;
lpModule->nPatterns = Header.nPatterns;
lpModule->nPatches = Header.nPatches;
lpModule->nTempo = Header.nTempo;
lpModule->nBPM = Header.nBPM;
for (n = 0; n < lpModule->nOrders; n++) {
lpModule->aOrderTable[n] = Header.aOrderTable[n];
}
for (n = 0; n < lpModule->nTracks; n++) {
lpModule->aPanningTable[n] = (AUDIO_MIN_PANNING + AUDIO_MAX_PANNING)/2;
}
if ((lpModule->aPatternTable = (LPAUDIOPATTERN)
calloc(lpModule->nPatterns, sizeof(AUDIOPATTERN))) == NULL) {
AFreeModuleFile(lpModule);
AIOCloseFile();
return AUDIO_ERROR_NOMEMORY;
}
if ((lpModule->aPatchTable = (LPAUDIOPATCH)
calloc(lpModule->nPatches, sizeof(AUDIOPATCH))) == NULL) {
AFreeModuleFile(lpModule);
AIOCloseFile();
return AUDIO_ERROR_NOMEMORY;
}
lpPattern = lpModule->aPatternTable;
for (n = 0; n < lpModule->nPatterns; n++, lpPattern++) {
/* load XM pattern header structure */
AIOReadLong(&Pattern.dwHeaderSize);
AIOReadChar(&Pattern.nPacking);
AIOReadShort(&Pattern.nRows);
AIOReadShort(&Pattern.nSize);
AIOSeekFile(Pattern.dwHeaderSize - XM_PATTERN_HEADER_SIZE, SEEK_CUR);
if (Pattern.nPacking != 0) {
AFreeModuleFile(lpModule);
AIOCloseFile();
return AUDIO_ERROR_BADFILEFORMAT;
}
/* initialize pattern structure */
lpPattern->nPacking = Pattern.nPacking;
lpPattern->nTracks = lpModule->nTracks;
lpPattern->nRows = Pattern.nRows;
lpPattern->nSize = Pattern.nSize;
if (lpPattern->nSize != 0) {
/* allocate and load pattern data */
if ((lpPattern->lpData = malloc(lpPattern->nSize)) == NULL) {
AFreeModuleFile(lpModule);
AIOCloseFile();
return AUDIO_ERROR_NOMEMORY;
}
AIOReadFile(lpPattern->lpData, lpPattern->nSize);
}
}
lpPatch = lpModule->aPatchTable;
for (n = 0; n < lpModule->nPatches; n++, lpPatch++) {
/* load XM patch header structure */
AIOReadLong(&Patch.dwHeaderSize);
AIOReadFile(Patch.aPatchName, sizeof(Patch.aPatchName));
AIOReadChar(&Patch.nType);
AIOReadShort(&Patch.nSamples);
if (Patch.nSamples != 0) {
AIOReadLong(&Patch.dwSampleHeaderSize);
AIOReadFile(Patch.aSampleNumber, sizeof(Patch.aSampleNumber));
for (m = 0; m < AUDIO_MAX_POINTS; m++) {
AIOReadLong(&Patch.aVolumeEnvelope[m]);
}
for (m = 0; m < AUDIO_MAX_POINTS; m++) {
AIOReadLong(&Patch.aPanningEnvelope[m]);
}
AIOReadChar(&Patch.nVolumePoints);
AIOReadChar(&Patch.nPanningPoints);
AIOReadChar(&Patch.nVolumeSustain);
AIOReadChar(&Patch.nVolumeLoopStart);
AIOReadChar(&Patch.nVolumeLoopEnd);
AIOReadChar(&Patch.nPanningSustain);
AIOReadChar(&Patch.nPanningLoopStart);
AIOReadChar(&Patch.nPanningLoopEnd);
AIOReadChar(&Patch.bVolumeFlags);
AIOReadChar(&Patch.bPanningFlags);
AIOReadChar(&Patch.nVibratoType);
AIOReadChar(&Patch.nVibratoSweep);
AIOReadChar(&Patch.nVibratoDepth);
AIOReadChar(&Patch.nVibratoRate);
AIOReadShort(&Patch.nVolumeFadeout);
AIOReadShort(&Patch.wReserved);
Patch.dwHeaderSize -= XM_PATCH_BODY_SIZE;
}
AIOSeekFile(Patch.dwHeaderSize - XM_PATCH_HEADER_SIZE, SEEK_CUR);
/* HACK: clamp envelope's number of points (12/12/96) */
if (Patch.nVolumePoints > AUDIO_MAX_POINTS)
Patch.nVolumePoints = AUDIO_MAX_POINTS;
if (Patch.nPanningPoints > AUDIO_MAX_POINTS)
Patch.nPanningPoints = AUDIO_MAX_POINTS;
if (Patch.nSamples > AUDIO_MAX_SAMPLES ||
Patch.nVolumePoints > AUDIO_MAX_POINTS ||
Patch.nPanningPoints > AUDIO_MAX_POINTS) {
AFreeModuleFile(lpModule);
AIOCloseFile();
return AUDIO_ERROR_BADFILEFORMAT;
}
/* initialize patch structure */
strncpy(lpPatch->szPatchName, Patch.aPatchName,
sizeof(Patch.aPatchName));
for (m = 0; m < AUDIO_MAX_NOTES; m++) {
lpPatch->aSampleNumber[m] = Patch.aSampleNumber[m];
if (lpPatch->aSampleNumber[m] >= Patch.nSamples)
lpPatch->aSampleNumber[m] = 0x00;
}
lpPatch->nSamples = Patch.nSamples;
lpPatch->nVibratoType = Patch.nVibratoType;
lpPatch->nVibratoSweep = Patch.nVibratoSweep;
lpPatch->nVibratoDepth = Patch.nVibratoDepth;
lpPatch->nVibratoRate = Patch.nVibratoRate;
lpPatch->nVolumeFadeout = Patch.nVolumeFadeout;
lpPatch->Volume.nPoints = Patch.nVolumePoints;
lpPatch->Volume.nSustain = Patch.nVolumeSustain;
lpPatch->Volume.nLoopStart = Patch.nVolumeLoopStart;
lpPatch->Volume.nLoopEnd = Patch.nVolumeLoopEnd;
if (Patch.bVolumeFlags & XM_ENVELOPE_ON)
lpPatch->Volume.wFlags |= AUDIO_ENVELOPE_ON;
if (Patch.bVolumeFlags & XM_ENVELOPE_SUSTAIN)
lpPatch->Volume.wFlags |= AUDIO_ENVELOPE_SUSTAIN;
if (Patch.bVolumeFlags & XM_ENVELOPE_LOOP)
lpPatch->Volume.wFlags |= AUDIO_ENVELOPE_LOOP;
for (m = 0; m < lpPatch->Volume.nPoints; m++) {
lpPatch->Volume.aEnvelope[m].nFrame =
LOWORD(Patch.aVolumeEnvelope[m]);
lpPatch->Volume.aEnvelope[m].nValue =
HIWORD(Patch.aVolumeEnvelope[m]);
}
lpPatch->Panning.nPoints = Patch.nPanningPoints;
lpPatch->Panning.nSustain = Patch.nPanningSustain;
lpPatch->Panning.nLoopStart = Patch.nPanningLoopStart;
lpPatch->Panning.nLoopEnd = Patch.nPanningLoopEnd;
if (Patch.bPanningFlags & XM_ENVELOPE_ON)
lpPatch->Panning.wFlags |= AUDIO_ENVELOPE_ON;
if (Patch.bPanningFlags & XM_ENVELOPE_SUSTAIN)
lpPatch->Panning.wFlags |= AUDIO_ENVELOPE_SUSTAIN;
if (Patch.bPanningFlags & XM_ENVELOPE_LOOP)
lpPatch->Panning.wFlags |= AUDIO_ENVELOPE_LOOP;
for (m = 0; m < lpPatch->Panning.nPoints; m++) {
lpPatch->Panning.aEnvelope[m].nFrame =
LOWORD(Patch.aPanningEnvelope[m]);
lpPatch->Panning.aEnvelope[m].nValue =
HIWORD(Patch.aPanningEnvelope[m]);
}
if (lpPatch->nSamples != 0) {
if ((lpPatch->aSampleTable = (LPAUDIOSAMPLE)
calloc(lpPatch->nSamples, sizeof(AUDIOSAMPLE))) == NULL) {
AFreeModuleFile(lpModule);
AIOCloseFile();
return AUDIO_ERROR_NOMEMORY;
}
}
/* load XM multi-sample header structures */
lpSample = lpPatch->aSampleTable;
for (m = 0; m < Patch.nSamples; m++, lpSample++) {
AIOReadLong(&Sample.dwLength);
AIOReadLong(&Sample.dwLoopStart);
AIOReadLong(&Sample.dwLoopLength);
AIOReadChar(&Sample.nVolume);
AIOReadChar(&Sample.nFinetune);
AIOReadChar(&Sample.bFlags);
AIOReadChar(&Sample.nPanning);
AIOReadChar(&Sample.nRelativeNote);
AIOReadChar(&Sample.bReserved);
AIOReadFile(Sample.aSampleName, sizeof(Sample.aSampleName));
AIOSeekFile(Patch.dwSampleHeaderSize -
XM_SAMPLE_HEADER_SIZE, SEEK_CUR);
strncpy(lpSample->szSampleName, Sample.aSampleName,
sizeof(Sample.aSampleName));
lpSample->Wave.dwLength = Sample.dwLength;
lpSample->Wave.dwLoopStart = Sample.dwLoopStart;
lpSample->Wave.dwLoopEnd = Sample.dwLoopStart + Sample.dwLoopLength;
lpSample->Wave.nSampleRate = 8363;
lpSample->nVolume = Sample.nVolume;
lpSample->nPanning = Sample.nPanning;
lpSample->nRelativeNote = Sample.nRelativeNote;
lpSample->nFinetune = Sample.nFinetune;
if (Sample.bFlags & XM_SAMPLE_16BITS) {
lpSample->Wave.wFormat |= AUDIO_FORMAT_16BITS;
}
if (Sample.bFlags & XM_SAMPLE_LOOP)
lpSample->Wave.wFormat |= AUDIO_FORMAT_LOOP;
if (Sample.bFlags & XM_SAMPLE_PINGPONG)
lpSample->Wave.wFormat |= AUDIO_FORMAT_BIDILOOP;
}
/* load XM multi-sample waveform data */
lpSample = lpPatch->aSampleTable;
for (m = 0; m < Patch.nSamples; m++, lpSample++) {
if (lpSample->Wave.dwLength == 0)
continue;
nErrorCode = ACreateAudioData(&lpSample->Wave);
if (nErrorCode != AUDIO_ERROR_NONE) {
AFreeModuleFile(lpModule);
AIOCloseFile();
return nErrorCode;
}
AIOReadFile(lpSample->Wave.lpData, lpSample->Wave.dwLength);
XMDecodeSamples(&lpSample->Wave);
AWriteAudioData(&lpSample->Wave, 0, lpSample->Wave.dwLength);
}
}
AIOCloseFile();
*lplpModule = lpModule;
return AUDIO_ERROR_NONE;
}