Initial Commit
This commit is contained in:
36
seal-hack/src/BeOS/Makefile
Normal file
36
seal-hack/src/BeOS/Makefile
Normal 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
|
||||
45
seal-hack/src/BeOS/audio_driver.h
Normal file
45
seal-hack/src/BeOS/audio_driver.h
Normal 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 */
|
||||
|
||||
86
seal-hack/src/BeOS/old_audio_driver.h
Normal file
86
seal-hack/src/BeOS/old_audio_driver.h
Normal 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
|
||||
33
seal-hack/src/DOS/DPMI16/Borland/Makefile
Normal file
33
seal-hack/src/DOS/DPMI16/Borland/Makefile
Normal 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
|
||||
1
seal-hack/src/DOS/DPMI16/Borland/audiobcx.lnk
Normal file
1
seal-hack/src/DOS/DPMI16/Borland/audiobcx.lnk
Normal 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
|
||||
33
seal-hack/src/DOS/DPMI32/Borland/Makefile
Normal file
33
seal-hack/src/DOS/DPMI32/Borland/Makefile
Normal 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
|
||||
1
seal-hack/src/DOS/DPMI32/Borland/audiobcf.lnk
Normal file
1
seal-hack/src/DOS/DPMI32/Borland/audiobcf.lnk
Normal 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
|
||||
39
seal-hack/src/DOS/DPMI32/DJGPP/Makefile
Normal file
39
seal-hack/src/DOS/DPMI32/DJGPP/Makefile
Normal 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
|
||||
40
seal-hack/src/DOS/DPMI32/Watcom/Makefile
Normal file
40
seal-hack/src/DOS/DPMI32/Watcom/Makefile
Normal 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
|
||||
33
seal-hack/src/DOS/Large/Borland/Makefile
Normal file
33
seal-hack/src/DOS/Large/Borland/Makefile
Normal 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
|
||||
1
seal-hack/src/DOS/Large/Borland/audiobcl.lnk
Normal file
1
seal-hack/src/DOS/Large/Borland/audiobcl.lnk
Normal 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
|
||||
32
seal-hack/src/DOS/Large/Watcom/Makefile
Normal file
32
seal-hack/src/DOS/Large/Watcom/Makefile
Normal 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
|
||||
30
seal-hack/src/FreeBSD/Makefile
Normal file
30
seal-hack/src/FreeBSD/Makefile
Normal 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
|
||||
30
seal-hack/src/Indigo/Makefile
Normal file
30
seal-hack/src/Indigo/Makefile
Normal 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
|
||||
34
seal-hack/src/MacOSX/Makefile
Normal file
34
seal-hack/src/MacOSX/Makefile
Normal 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
34
seal-hack/src/Makefile
Normal 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
|
||||
53
seal-hack/src/OS2/Makefile
Normal file
53
seal-hack/src/OS2/Makefile
Normal 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
|
||||
|
||||
|
||||
52
seal-hack/src/OS2/audio.def
Normal file
52
seal-hack/src/OS2/audio.def
Normal 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
|
||||
30
seal-hack/src/Solaris/Makefile
Normal file
30
seal-hack/src/Solaris/Makefile
Normal 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
|
||||
30
seal-hack/src/SunOS/Makefile
Normal file
30
seal-hack/src/SunOS/Makefile
Normal 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
|
||||
32
seal-hack/src/Windows/Win16/Borland/Makefile
Normal file
32
seal-hack/src/Windows/Win16/Borland/Makefile
Normal 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
|
||||
1
seal-hack/src/Windows/Win16/Borland/audw16bc.lnk
Normal file
1
seal-hack/src/Windows/Win16/Borland/audw16bc.lnk
Normal file
@@ -0,0 +1 @@
|
||||
+audio.obj +wavfile.obj +xmfile.obj +s3mfile.obj +modfile.obj +iofile.obj +modeng.obj +nondrv.obj +mixdrv.obj +windrv.obj
|
||||
31
seal-hack/src/Windows/Win16/Watcom/Makefile
Normal file
31
seal-hack/src/Windows/Win16/Watcom/Makefile
Normal 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
|
||||
37
seal-hack/src/Windows/Win32/Borland/Makefile
Normal file
37
seal-hack/src/Windows/Win32/Borland/Makefile
Normal 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
|
||||
54
seal-hack/src/Windows/Win32/Borland/audiow32.def
Normal file
54
seal-hack/src/Windows/Win32/Borland/audiow32.def
Normal 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
|
||||
7
seal-hack/src/Windows/Win32/Borland/audiow32.lnk
Normal file
7
seal-hack/src/Windows/Win32/Borland/audiow32.lnk
Normal 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
|
||||
48
seal-hack/src/Windows/Win32/VisualC/Makefile
Normal file
48
seal-hack/src/Windows/Win32/VisualC/Makefile
Normal 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
|
||||
54
seal-hack/src/Windows/Win32/VisualC/audiow32.def
Normal file
54
seal-hack/src/Windows/Win32/VisualC/audiow32.def
Normal 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
|
||||
39
seal-hack/src/Windows/Win32/Watcom/Makefile
Normal file
39
seal-hack/src/Windows/Win32/Watcom/Makefile
Normal 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
|
||||
49
seal-hack/src/Windows/Win32/Watcom/audiow32.lbc
Normal file
49
seal-hack/src/Windows/Win32/Watcom/audiow32.lbc
Normal 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
|
||||
57
seal-hack/src/Windows/Win32/Watcom/audiow32.lnk
Normal file
57
seal-hack/src/Windows/Win32/Watcom/audiow32.lnk
Normal 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
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
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
172
seal-hack/src/allegdrv.c
Normal 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
370
seal-hack/src/ariadrv.c
Normal 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
559
seal-hack/src/audio.c
Normal 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
391
seal-hack/src/audio.h
Normal 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
383
seal-hack/src/audiodj.c
Normal 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
68
seal-hack/src/audiow32.c
Normal 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
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
185
seal-hack/src/be3drv.c
Normal 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, ¶ms) < 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, ¶ms) < 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
185
seal-hack/src/be4drv.c
Normal 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
174
seal-hack/src/bedrv.cpp
Normal 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
83
seal-hack/src/drivers.h
Normal 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
313
seal-hack/src/dsdrv.c
Normal 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
663
seal-hack/src/dsdrv2.c
Normal 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
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
110
seal-hack/src/iofile.c
Normal 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
43
seal-hack/src/iofile.h
Normal 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
144
seal-hack/src/lnxdrv.c
Normal 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
906
seal-hack/src/mixdrv.c
Normal 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
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
309
seal-hack/src/modfile.c
Normal 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
BIN
seal-hack/src/mp
Executable file
Binary file not shown.
270
seal-hack/src/mp.c
Normal file
270
seal-hack/src/mp.c
Normal 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
560
seal-hack/src/msdos.c
Normal 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
179
seal-hack/src/msdos.h
Normal 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
299
seal-hack/src/mtmfile.c
Normal 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
360
seal-hack/src/nondrv.c
Normal 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
323
seal-hack/src/os2drv.c
Normal 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
183
seal-hack/src/osxdrv.c
Normal 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
586
seal-hack/src/pasdrv.c
Normal 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
764
seal-hack/src/s3mfile.c
Normal 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
762
seal-hack/src/sbdrv.c
Normal 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
183
seal-hack/src/sdldrv.c
Normal 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
135
seal-hack/src/sgidrv.c
Normal 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
257
seal-hack/src/sundrv.c
Normal 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
197
seal-hack/src/tables.h
Normal 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
152
seal-hack/src/wavfile.c
Normal 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
208
seal-hack/src/windrv.c
Normal 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
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
407
seal-hack/src/xmfile.c
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user