Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 87685 | Differences between
and this patch

Collapse All | Expand All

(-)./Makefile (-14 / +21 lines)
Lines 14-20 Link Here
14
# debugging enabled
14
# debugging enabled
15
#debug=-ggdb
15
#debug=-ggdb
16
# debugging disabled
16
# debugging disabled
17
debug=-ggdb -fomit-frame-pointer
17
debug=-fomit-frame-pointer
18
18
19
19
20
DXROOT=c:/sdks/msc/dx61
20
DXROOT=c:/sdks/msc/dx61
Lines 24-30 Link Here
24
24
25
CC=gcc
25
CC=gcc
26
# -Werror-implicit-function-declaration
26
# -Werror-implicit-function-declaration
27
CFLAGS=$(debug) -W -Wall -Werror-implicit-function-declaration \
27
CFLAGS=$(debug) -O2 -W -Wall -Werror-implicit-function-declaration \
28
	-Wno-char-subscripts -Wno-unused \
28
	-Wno-char-subscripts -Wno-unused \
29
	-march=pentium -funsigned-char -Dmain=app_main -DNO_GCC_BUILTINS \
29
	-march=pentium -funsigned-char -Dmain=app_main -DNO_GCC_BUILTINS \
30
	-I$(INC) -I$(EINC) -I$(SRC)jmact -I$(SRC)jaudiolib -I../jfaud/inc \
30
	-I$(INC) -I$(EINC) -I$(SRC)jmact -I$(SRC)jaudiolib -I../jfaud/inc \
Lines 44-58 Link Here
44
44
45
AUDIOLIB_FX_STUB=$(OBJ)audiolib_fxstub.$o
45
AUDIOLIB_FX_STUB=$(OBJ)audiolib_fxstub.$o
46
AUDIOLIB_MUSIC_STUB=$(OBJ)audiolib_musicstub.$o
46
AUDIOLIB_MUSIC_STUB=$(OBJ)audiolib_musicstub.$o
47
#AUDIOLIB_FX=$(OBJ)audiolib_fx_fmod.$o
48
AUDIOLIB_FX=$(OBJ)mv_mix.$o \
47
AUDIOLIB_FX=$(OBJ)mv_mix.$o \
49
	  $(OBJ)mv_mix16.$o \
48
	  $(OBJ)mv_mix16.$o \
50
	  $(OBJ)mvreverb.$o \
49
	  $(OBJ)mvreverb.$o \
51
	  $(OBJ)pitch.$o \
52
	  $(OBJ)multivoc.$o \
53
	  $(OBJ)ll_man.$o \
50
	  $(OBJ)ll_man.$o \
54
	  $(OBJ)fx_man.$o \
51
	  $(OBJ)fx_man.$o
55
	  $(OBJ)dsoundout.$o
56
AUDIOLIB_MUSIC=$(OBJ)midi.$o \
52
AUDIOLIB_MUSIC=$(OBJ)midi.$o \
57
	  $(OBJ)mpu401.$o \
53
	  $(OBJ)mpu401.$o \
58
	  $(OBJ)music.$o
54
	  $(OBJ)music.$o
Lines 102-115 Link Here
102
	#GAMEOBJS+= $(EOBJ)sdlayer.$o
98
	#GAMEOBJS+= $(EOBJ)sdlayer.$o
103
	#EDITOROBJS+= $(EOBJ)sdlayer.$o
99
	#EDITOROBJS+= $(EOBJ)sdlayer.$o
104
100
105
	override CFLAGS+= $(subst -Dmain=SDL_main,,$(shell sdl-config --cflags))
101
	CFLAGS+= $(subst -Dmain=SDL_main,,$(shell sdl-config --cflags) -D__cdecl=" ") 
106
	LIBS+= $(shell sdl-config --libs)
102
	LIBS+= $(shell sdl-config --libs) -lSDL_mixer
107
	AUDIOLIBOBJ=$(AUDIOLIB_MUSIC_STUB) $(AUDIOLIB_FX_STUB)
103
	AUDIOLIB_FX+= $(OBJ)dsl.$o \
104
		      $(OBJ)nodpmi.$o \
105
		      $(OBJ)unixpitch.$o \
106
		      $(OBJ)unixvoc.$o
107
		      
108
	AUDIOLIB_MUSIC=$(OBJ)sdlmusic.$o $(OBJ)unixglob.$o
109
	AUDIOLIBOBJ=$(AUDIOLIB_MUSIC) $(AUDIOLIB_FX)
108
else
110
else
109
	ifeq ($(RENDERTYPE),WIN)
111
	ifeq ($(RENDERTYPE),WIN)
110
		#GAMEOBJS+= $(EOBJ)winlayer.$o
112
		#GAMEOBJS+= $(EOBJ)winlayer.$o
111
		#EDITOROBJS+= $(EOBJ)winlayer.$o
113
		#EDITOROBJS+= $(EOBJ)winlayer.$o
112
		
114
		
115
		AUDIOLIB_FX+= $(OBJ)audiolib_fx_fmod.$o \
116
		              $(OBJ)dsoundout.$o \
117
		              $(OBJ)pitch.$o \
118
		              $(OBJ)multivoc.$o
113
		AUDIOLIBOBJ=$(AUDIOLIB_MUSIC) $(AUDIOLIB_FX)
119
		AUDIOLIBOBJ=$(AUDIOLIB_MUSIC) $(AUDIOLIB_FX)
114
	endif
120
	endif
115
endif
121
endif
Lines 124-147 Link Here
124
130
125
duke3d$(EXESUFFIX): $(GAMEOBJS) $(EOBJ)$(ENGINELIB)
131
duke3d$(EXESUFFIX): $(GAMEOBJS) $(EOBJ)$(ENGINELIB)
126
	$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
132
	$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
127
	-rm duke3d.sym$(EXESUFFIX)
133
	-rm -f duke3d.sym$(EXESUFFIX)
128
	cp duke3d$(EXESUFFIX) duke3d.sym$(EXESUFFIX)
134
	cp duke3d$(EXESUFFIX) duke3d.sym$(EXESUFFIX)
129
	strip duke3d$(EXESUFFIX)
135
	strip duke3d$(EXESUFFIX)
130
	
136
	
131
build$(EXESUFFIX): $(EDITOROBJS) $(EOBJ)$(EDITORLIB) $(EOBJ)$(ENGINELIB)
137
build$(EXESUFFIX): $(EDITOROBJS) $(EOBJ)$(EDITORLIB) $(EOBJ)$(ENGINELIB)
132
	$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
138
	$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
133
	-rm build.sym$(EXESUFFIX)
139
	-rm -f build.sym$(EXESUFFIX)
134
	cp build$(EXESUFFIX) build.sym$(EXESUFFIX)
140
	cp build$(EXESUFFIX) build.sym$(EXESUFFIX)
135
	strip build$(EXESUFFIX)
141
	strip build$(EXESUFFIX)
136
142
143
AUDIOLIB=$(SRC)/jaudiolib
137
include Makefile.deps
144
include Makefile.deps
138
145
139
$(EOBJ)$(ENGINELIB):
146
$(EOBJ)$(ENGINELIB):
140
	-mkdir $(EOBJ)
147
	-mkdir -p $(EOBJ)
141
	$(MAKE) -C $(EROOT) "OBJ=$(CURDIR)/$(EOBJ)" "CFLAGS=$(ENGINEOPTS)" enginelib
148
	$(MAKE) -C $(EROOT) "OBJ=$(CURDIR)/$(EOBJ)" "CFLAGS=$(ENGINEOPTS)" enginelib
142
149
143
$(EOBJ)$(EDITORLIB):
150
$(EOBJ)$(EDITORLIB):
144
	-mkdir $(EOBJ)
151
	-mkdir -p $(EOBJ)
145
	$(MAKE) -C $(EROOT) "OBJ=$(CURDIR)/$(EOBJ)" "CFLAGS=$(ENGINEOPTS)" editorlib
152
	$(MAKE) -C $(EROOT) "OBJ=$(CURDIR)/$(EOBJ)" "CFLAGS=$(ENGINEOPTS)" editorlib
146
153
147
# RULES
154
# RULES
(-)./Makefile.deps (+5 lines)
Lines 31-36 Link Here
31
$(OBJ)scriplib.$o: $(SRC)jmact/scriplib.c $(SRC)jmact/scriplib.h $(SRC)jmact/util_lib.h $(SRC)jmact/_scrplib.h $(INC)types.h $(EINC)compat.h
31
$(OBJ)scriplib.$o: $(SRC)jmact/scriplib.c $(SRC)jmact/scriplib.h $(SRC)jmact/util_lib.h $(SRC)jmact/_scrplib.h $(INC)types.h $(EINC)compat.h
32
32
33
# jAudioLib objects
33
# jAudioLib objects
34
$(OBJ)dsl.$o: $(SRC)jaudiolib/dsl.c $(SRC)jaudiolib/util.h
35
$(OBJ)nodpmi.$o: $(SRC)jaudiolib/nodpmi.c $(SRC)jaudiolib/dpmi.h
36
$(OBJ)unixpitch.$o: $(SRC)jaudiolib/unixpitch.c $(SRC)jaudiolib/pitch.h
37
$(OBJ)unixvoc.$o: $(SRC)jaudiolib/unixvoc.c $(SRC)jaudiolib/usrhooks.h $(SRC)jaudiolib/linklist.h $(SRC)jaudiolib/pitch.h $(SRC)jaudiolib/multivoc.h $(SRC)jaudiolib/_multivc.h
38
34
$(OBJ)audiolib_fxstub.$o: $(SRC)jaudiolib/audiolib_fxstub.c $(SRC)jaudiolib/fx_man.h
39
$(OBJ)audiolib_fxstub.$o: $(SRC)jaudiolib/audiolib_fxstub.c $(SRC)jaudiolib/fx_man.h
35
$(OBJ)audiolib_musicstub.$o: $(SRC)jaudiolib/audiolib_musicstub.c $(SRC)jaudiolib/music.h
40
$(OBJ)audiolib_musicstub.$o: $(SRC)jaudiolib/audiolib_musicstub.c $(SRC)jaudiolib/music.h
36
41
(-)./Makefile.deps.diff
Lines 1-14 Link Here
(-)./Makefile.diff
Lines 1-95 Link Here
(-)./source/config.c (-2 / +4 lines)
Lines 320-327 Link Here
320
   int32 i,f;
320
   int32 i,f;
321
   byte k1,k2;
321
   byte k1,k2;
322
322
323
   FXDevice = -1;
323
   FXDevice = 1;
324
   MusicDevice = -1;
324
   MusicDevice = 1;
325
   NumVoices = 4;
325
   NumVoices = 4;
326
   NumChannels = 2;
326
   NumChannels = 2;
327
   NumBits = 8;
327
   NumBits = 8;
Lines 931-936 Link Here
931
   SCRIPT_PutNumber( scripthandle, "Screen Setup", "GLTextureMode",gltexfiltermode,false,false);
931
   SCRIPT_PutNumber( scripthandle, "Screen Setup", "GLTextureMode",gltexfiltermode,false,false);
932
   SCRIPT_PutNumber( scripthandle, "Screen Setup", "GLAnisotropy",glanisotropy,false,false);
932
   SCRIPT_PutNumber( scripthandle, "Screen Setup", "GLAnisotropy",glanisotropy,false,false);
933
   SCRIPT_PutNumber( scripthandle, "Screen Setup", "GLUseTextureCompr",glusetexcompr,false,false);
933
   SCRIPT_PutNumber( scripthandle, "Screen Setup", "GLUseTextureCompr",glusetexcompr,false,false);
934
   SCRIPT_PutNumber( scripthandle, "Sound Setup", "FXDevice",FXDevice,false,false);
935
   SCRIPT_PutNumber( scripthandle, "Sound Setup", "MusicDevice",MusicDevice,false,false);
934
   SCRIPT_PutNumber( scripthandle, "Sound Setup", "FXVolume",FXVolume,false,false);
936
   SCRIPT_PutNumber( scripthandle, "Sound Setup", "FXVolume",FXVolume,false,false);
935
   SCRIPT_PutNumber( scripthandle, "Sound Setup", "MusicVolume",MusicVolume,false,false);
937
   SCRIPT_PutNumber( scripthandle, "Sound Setup", "MusicVolume",MusicVolume,false,false);
936
   SCRIPT_PutNumber( scripthandle, "Sound Setup", "SoundToggle",SoundToggle,false,false);
938
   SCRIPT_PutNumber( scripthandle, "Sound Setup", "SoundToggle",SoundToggle,false,false);
(-)./source/jaudiolib/debugio.h (+30 lines)
Line 0 Link Here
1
/*
2
Copyright (C) 1994-1995 Apogee Software, Ltd.
3
4
This program is free software; you can redistribute it and/or
5
modify it under the terms of the GNU General Public License
6
as published by the Free Software Foundation; either version 2
7
of the License, or (at your option) any later version.
8
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13
See the GNU General Public License for more details.
14
15
You should have received a copy of the GNU General Public License
16
along with this program; if not, write to the Free Software
17
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19
*/
20
#ifndef __DEBUGIO_H
21
#define __DEBUGIO_H
22
23
void DB_SetXY( int x, int y );
24
void DB_PutChar( char ch );
25
int  DB_PrintString( char *string );
26
int  DB_PrintNum( int number );
27
int  DB_PrintUnsigned( unsigned long number, int radix );
28
int  DB_printf( char *fmt, ... );
29
30
#endif
(-)./source/jaudiolib/dma.h (+83 lines)
Line 0 Link Here
1
/*
2
Copyright (C) 1994-1995 Apogee Software, Ltd.
3
4
This program is free software; you can redistribute it and/or
5
modify it under the terms of the GNU General Public License
6
as published by the Free Software Foundation; either version 2
7
of the License, or (at your option) any later version.
8
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13
See the GNU General Public License for more details.
14
15
You should have received a copy of the GNU General Public License
16
along with this program; if not, write to the Free Software
17
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19
*/
20
/**********************************************************************
21
   file:   DMA.H
22
23
   author: James R. Dose
24
   date:   February 4, 1994
25
26
   Public header file for DMA.C
27
28
   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
29
**********************************************************************/
30
31
#ifndef __DMA_H
32
#define __DMA_H
33
34
enum DMA_ERRORS
35
   {
36
   DMA_Error = -1,
37
   DMA_Ok    = 0,
38
   DMA_ChannelOutOfRange,
39
   DMA_InvalidChannel
40
   };
41
42
enum DMA_Modes
43
   {
44
   DMA_SingleShotRead,
45
   DMA_SingleShotWrite,
46
   DMA_AutoInitRead,
47
   DMA_AutoInitWrite
48
   };
49
50
char *DMA_ErrorString
51
   (
52
   int ErrorNumber
53
   );
54
55
int DMA_VerifyChannel
56
   (
57
   int channel
58
   );
59
60
int DMA_SetupTransfer
61
   (
62
   int  channel,
63
   char *address,
64
   int  length,
65
   int  mode
66
   );
67
68
int DMA_EndTransfer
69
   (
70
   int channel
71
   );
72
73
char *DMA_GetCurrentPos
74
   (
75
   int channel
76
   );
77
78
int DMA_GetTransferCount
79
   (
80
   int channel
81
   );
82
83
#endif
(-)./source/jaudiolib/dpmi.h (+43 lines)
Line 0 Link Here
1
/*
2
Copyright (C) 1994-1995 Apogee Software, Ltd.
3
4
This program is free software; you can redistribute it and/or
5
modify it under the terms of the GNU General Public License
6
as published by the Free Software Foundation; either version 2
7
of the License, or (at your option) any later version.
8
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13
See the GNU General Public License for more details.
14
15
You should have received a copy of the GNU General Public License
16
along with this program; if not, write to the Free Software
17
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19
*/
20
/**********************************************************************
21
   module: DPMI.H
22
23
   author: James R. Dose
24
   date:   March 31, 1994
25
26
   Inline functions for performing DPMI calls.
27
28
   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
29
**********************************************************************/
30
31
#ifndef __DPMI_H
32
#define __DPMI_H
33
34
enum DPMI_Errors
35
   {
36
   DPMI_Warning = -2,
37
   DPMI_Error   = -1,
38
   DPMI_Ok      = 0
39
   };
40
41
int  DPMI_GetDOSMemory( void **ptr, int *descriptor, unsigned length );
42
int  DPMI_FreeDOSMemory( int descriptor );
43
#endif
(-)./source/jaudiolib/dsl.c (+257 lines)
Line 0 Link Here
1
/*
2
Copyright (C) 2003-2004 Ryan C. Gordon. and James Bentler
3
4
This program is free software; you can redistribute it and/or
5
modify it under the terms of the GNU General Public License
6
as published by the Free Software Foundation; either version 2
7
of the License, or (at your option) any later version.
8
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13
See the GNU General Public License for more details.
14
15
You should have received a copy of the GNU General Public License
16
along with this program; if not, write to the Free Software
17
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19
Originally written by Ryan C. Gordon. (icculus@clutteredmind.org)
20
Adapted to work with JonoF's port by James Bentler (bentler@cs.umn.edu)
21
22
*/
23
#include <stdlib.h>
24
#include <string.h>
25
26
#include "dsl.h"
27
#include "util.h"
28
29
#include "SDL.h"
30
#include "SDL_mixer.h"
31
32
extern volatile int MV_MixPage;
33
34
static int DSL_ErrorCode = DSL_Ok;
35
36
static int mixer_initialized;
37
38
static void ( *_CallBackFunc )( void );
39
static volatile char *_BufferStart;
40
static int _BufferSize;
41
static int _NumDivisions;
42
static int _SampleRate;
43
static int _remainder;
44
45
static Mix_Chunk *blank;
46
static unsigned char *blank_buf;
47
48
/*
49
possible todo ideas: cache sdl/sdl mixer error messages.
50
*/
51
52
char *DSL_ErrorString( int ErrorNumber )
53
{
54
	char *ErrorString;
55
	
56
	switch (ErrorNumber) {
57
		case DSL_Warning:
58
		case DSL_Error:
59
			ErrorString = DSL_ErrorString(DSL_ErrorCode);
60
			break;
61
		
62
		case DSL_Ok:
63
			ErrorString = "SDL Driver ok.";
64
			break;
65
		
66
		case DSL_SDLInitFailure:
67
			ErrorString = "SDL Audio initialization failed.";
68
			break;
69
		
70
		case DSL_MixerActive:
71
			ErrorString = "SDL Mixer already initialized.";
72
			break;	
73
	
74
		case DSL_MixerInitFailure:
75
			ErrorString = "SDL Mixer initialization failed.";
76
			break;
77
			
78
		default:
79
			ErrorString = "Unknown SDL Driver error.";
80
			break;
81
	}
82
	
83
	return ErrorString;
84
}
85
86
static void DSL_SetErrorCode(int ErrorCode)
87
{
88
	DSL_ErrorCode = ErrorCode;
89
}
90
91
int DSL_Init( void )
92
{
93
	DSL_SetErrorCode(DSL_Ok);
94
	
95
	if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
96
		DSL_SetErrorCode(DSL_SDLInitFailure);
97
		
98
		return DSL_Error;
99
	}
100
	
101
	return DSL_Ok;
102
}
103
104
void DSL_Shutdown( void )
105
{
106
	DSL_StopPlayback();
107
}
108
109
static void mixer_callback(int chan, void *stream, int len, void *udata)
110
{
111
	Uint8 *stptr;
112
	Uint8 *fxptr;
113
	int copysize;
114
	
115
	/* len should equal _BufferSize, else this is screwed up */
116
117
	stptr = (Uint8 *)stream;
118
	
119
	if (_remainder > 0) {
120
		copysize = min(len, _remainder);
121
		
122
		fxptr = (Uint8 *)(&_BufferStart[MV_MixPage * 
123
			_BufferSize]);
124
		
125
		memcpy(stptr, fxptr+(_BufferSize-_remainder), copysize);
126
		
127
		len -= copysize;
128
		_remainder -= copysize;
129
		
130
		stptr += copysize;
131
	}
132
	
133
	while (len > 0) {
134
		/* new buffer */
135
		
136
		_CallBackFunc();
137
		
138
		fxptr = (Uint8 *)(&_BufferStart[MV_MixPage * 
139
			_BufferSize]);
140
141
		copysize = min(len, _BufferSize);
142
		
143
		memcpy(stptr, fxptr, copysize);
144
		
145
		len -= copysize;
146
		
147
		stptr += copysize;
148
	}
149
	
150
	_remainder = len;
151
}
152
153
int   DSL_BeginBufferedPlayback( char *BufferStart,
154
      int BufferSize, int NumDivisions, unsigned SampleRate,
155
      int MixMode, void ( *CallBackFunc )( void ) )
156
{
157
	Uint16 format;
158
	Uint8 *tmp;
159
	int channels;
160
	int chunksize;
161
		
162
	if (mixer_initialized) {
163
		DSL_SetErrorCode(DSL_MixerActive);
164
		
165
		return DSL_Error;
166
	}
167
	
168
	_CallBackFunc = CallBackFunc;
169
	_BufferStart = BufferStart;
170
	_BufferSize = (BufferSize / NumDivisions);
171
	_NumDivisions = NumDivisions;
172
	_SampleRate = SampleRate;
173
174
	_remainder = 0;
175
	
176
	format = (MixMode & SIXTEEN_BIT) ? AUDIO_S16SYS : AUDIO_U8;
177
	channels = (MixMode & STEREO) ? 2 : 1;
178
179
/*
180
	23ms is typically ideal (11025,22050,44100)
181
	46ms isn't bad
182
*/
183
	
184
	chunksize = 512;
185
	
186
	if (SampleRate >= 16000) chunksize *= 2;
187
	if (SampleRate >= 32000) chunksize *= 2;
188
	
189
/*	
190
// SDL mixer does this already
191
	if (MixMode & SIXTEEN_BIT) chunksize *= 2;
192
	if (MixMode & STEREO) chunksize *= 2;
193
*/
194
	
195
	if (Mix_OpenAudio(SampleRate, format, channels, chunksize) < 0) {
196
		DSL_SetErrorCode(DSL_MixerInitFailure);
197
		
198
		return DSL_Error;
199
	}
200
201
/*
202
	Mix_SetPostMix(mixer_callback, NULL);
203
*/
204
	/* have to use a channel because postmix will overwrite the music... */
205
	Mix_RegisterEffect(0, mixer_callback, NULL, NULL);
206
	
207
	/* create a dummy sample just to allocate that channel */
208
	blank_buf = (Uint8 *)malloc(4096);
209
	memset(blank_buf, 0, 4096);
210
	
211
	blank = Mix_QuickLoad_RAW(blank_buf, 4096);
212
		
213
	Mix_PlayChannel(0, blank, -1);
214
	
215
	mixer_initialized = 1;
216
	
217
	return DSL_Ok;
218
}
219
220
void DSL_StopPlayback( void )
221
{
222
	if (mixer_initialized) {
223
		Mix_HaltChannel(0);
224
	}
225
	
226
	if (blank != NULL) {
227
		Mix_FreeChunk(blank);
228
	}
229
	
230
	blank = NULL;
231
	
232
	if (blank_buf  != NULL) {
233
		free(blank_buf);
234
	}
235
	
236
	blank_buf = NULL;
237
	
238
	if (mixer_initialized) {
239
		Mix_CloseAudio();
240
	}
241
	
242
	mixer_initialized = 0;
243
}
244
245
unsigned DSL_GetPlaybackRate( void )
246
{
247
	return _SampleRate;
248
}
249
250
unsigned long DisableInterrupts( void )
251
{
252
	return 0;
253
}
254
255
void RestoreInterrupts( unsigned long flags )
256
{
257
}
(-)./source/jaudiolib/dsl.h (+50 lines)
Line 0 Link Here
1
/*
2
Copyright (C) 2003-2004 Ryan C. Gordon. and James Bentler
3
4
This program is free software; you can redistribute it and/or
5
modify it under the terms of the GNU General Public License
6
as published by the Free Software Foundation; either version 2
7
of the License, or (at your option) any later version.
8
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13
See the GNU General Public License for more details.
14
15
You should have received a copy of the GNU General Public License
16
along with this program; if not, write to the Free Software
17
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19
Originally written by Ryan C. Gordon. (icculus@clutteredmind.org)
20
Adapted to work with JonoF's port by James Bentler (bentler@cs.umn.edu)
21
22
*/
23
#ifndef AUDIOLIB__DSL_H
24
#define AUDIOLIB__DSL_H
25
26
#define MONO_8BIT    0
27
#define STEREO      1
28
#define SIXTEEN_BIT 2
29
#define STEREO_16BIT ( STEREO | SIXTEEN_BIT )
30
31
enum DSL_ERRORS
32
   {
33
   DSL_Warning = -2,
34
   DSL_Error = -1,
35
   DSL_Ok = 0,
36
   DSL_SDLInitFailure,
37
   DSL_MixerActive,
38
   DSL_MixerInitFailure
39
   };
40
41
char *DSL_ErrorString( int ErrorNumber );
42
int   DSL_Init( void );
43
void  DSL_StopPlayback( void );
44
unsigned DSL_GetPlaybackRate( void );
45
int   DSL_BeginBufferedPlayback( char *BufferStart,
46
      int BufferSize, int NumDivisions, unsigned SampleRate,
47
      int MixMode, void ( *CallBackFunc )( void ) );
48
void  DSL_Shutdown( void );
49
50
#endif
(-)./source/jaudiolib/interrup.h (+50 lines)
Line 0 Link Here
1
/*
2
Copyright (C) 1994-1995 Apogee Software, Ltd.
3
4
This program is free software; you can redistribute it and/or
5
modify it under the terms of the GNU General Public License
6
as published by the Free Software Foundation; either version 2
7
of the License, or (at your option) any later version.
8
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13
See the GNU General Public License for more details.
14
15
You should have received a copy of the GNU General Public License
16
along with this program; if not, write to the Free Software
17
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19
*/
20
/**********************************************************************
21
   module: INTERRUP.H
22
23
   author: James R. Dose
24
   date:   March 31, 1994
25
26
   Inline functions for disabling and restoring the interrupt flag.
27
28
   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
29
**********************************************************************/
30
31
#ifndef __INTERRUPT_H
32
#define __INTERRUPT_H
33
34
unsigned long DisableInterrupts( void );
35
void          RestoreInterrupts( unsigned long flags );
36
37
#ifdef PLAT_DOS
38
#pragma aux DisableInterrupts = \
39
   "pushfd",                    \
40
   "pop    eax",                \
41
   "cli"                        \
42
   modify [ eax ];
43
44
#pragma aux RestoreInterrupts = \
45
   "push   eax",                \
46
   "popfd"                      \
47
   parm [ eax ];
48
#endif
49
50
#endif
(-)./source/jaudiolib/_multivc.h (-1 / +4 lines)
Lines 67-74 Link Here
67
#define SILENCE_8BIT      0x80808080
67
#define SILENCE_8BIT      0x80808080
68
//#define SILENCE_16BIT_PAS 0
68
//#define SILENCE_16BIT_PAS 0
69
69
70
//#define MixBufferSize     256
70
#ifdef WINDOWS
71
#define MixBufferSize     (MV_GetBufferSize(MV_RequestedMixRate))
71
#define MixBufferSize     (MV_GetBufferSize(MV_RequestedMixRate))
72
#else
73
#define MixBufferSize     256
74
#endif
72
75
73
#define NumberOfBuffers   16
76
#define NumberOfBuffers   16
74
#define TotalBufferSize   ( MixBufferSize * NumberOfBuffers )
77
#define TotalBufferSize   ( MixBufferSize * NumberOfBuffers )
(-)./source/jaudiolib/nodpmi.c (+50 lines)
Line 0 Link Here
1
/*
2
Copyright (C) 1994-1995 Apogee Software, Ltd.
3
4
This program is free software; you can redistribute it and/or
5
modify it under the terms of the GNU General Public License
6
as published by the Free Software Foundation; either version 2
7
of the License, or (at your option) any later version.
8
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13
See the GNU General Public License for more details.
14
15
You should have received a copy of the GNU General Public License
16
along with this program; if not, write to the Free Software
17
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19
*/
20
/**********************************************************************
21
   module: NODPMI.C
22
23
   Functions for faking DPMI calls.
24
25
**********************************************************************/
26
27
#include <stdlib.h>
28
#include <string.h>
29
#include "dpmi.h"
30
31
#define TRUE  ( 1 == 1 )
32
#define FALSE ( !TRUE )
33
34
int DPMI_GetDOSMemory( void **ptr, int *descriptor, unsigned length )
35
{
36
	/* Lovely... */
37
	
38
	*ptr = (void *)malloc(length);
39
	
40
	*descriptor = (int) *ptr;
41
	
42
	return (descriptor == 0) ? DPMI_Error : DPMI_Ok;
43
}
44
45
int DPMI_FreeDOSMemory( int descriptor )
46
{
47
	free((void *)descriptor);
48
	
49
	return (descriptor == 0) ? DPMI_Error : DPMI_Ok;
50
}
(-)./source/jaudiolib/platform.h (+62 lines)
Line 0 Link Here
1
#ifndef _INCLUDE_PLATFORM_H_
2
#define _INCLUDE_PLATFORM_H_
3
4
#if (!defined __EXPORT__)
5
#define __EXPORT__
6
#endif
7
8
#if (defined __WATCOMC__)
9
#define snprintf _snprintf
10
#endif
11
12
static __inline unsigned short _swap16(unsigned short D)
13
{
14
#if PLATFORM_MACOSX
15
    register unsigned short returnValue;
16
    __asm__ volatile("lhbrx %0,0,%1"
17
        : "=r" (returnValue)
18
        : "r" (&D)
19
    );
20
    return returnValue;
21
#else
22
    return((D<<8)|(D>>8));
23
#endif
24
}
25
26
static __inline unsigned int _swap32(unsigned int D)
27
{
28
#if PLATFORM_MACOSX
29
    register unsigned int returnValue;
30
    __asm__ volatile("lwbrx %0,0,%1"
31
        : "=r" (returnValue)
32
        : "r" (&D)
33
    );
34
    return returnValue;
35
#else
36
    return((D<<24)|((D<<8)&0x00FF0000)|((D>>8)&0x0000FF00)|(D>>24));
37
#endif
38
}
39
40
#if PLATFORM_MACOSX
41
#define PLATFORM_BIGENDIAN 1
42
#define BUILDSWAP_INTEL16(x) _swap16(x)
43
#define BUILDSWAP_INTEL32(x) _swap32(x)
44
#else
45
#if __BYTE_ORDER == __LITTLE_ENDIAN
46
#define PLATFORM_LITTLEENDIAN 1
47
#define BUILDSWAP_INTEL16(x) (x)
48
#define BUILDSWAP_INTEL32(x) (x)
49
#else
50
#define PLATFORM_BIGENDIAN 1
51
#define BUILDSWAP_INTEL16(x) _swap16(x)
52
#define BUILDSWAP_INTEL32(x) _swap32(x)
53
#endif
54
#endif
55
56
extern int has_altivec;  /* PowerPC-specific. */
57
58
#endif  /* !defined _INCLUDE_PLATFORM_H_ */
59
60
/* end of platform.h ... */
61
62
(-)./source/jaudiolib/sdlmusic.c (+474 lines)
Line 0 Link Here
1
/*
2
Copyright (C) 2003-2004 Ryan C. Gordon. and James Bentler
3
4
This program is free software; you can redistribute it and/or
5
modify it under the terms of the GNU General Public License
6
as published by the Free Software Foundation; either version 2
7
of the License, or (at your option) any later version.
8
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13
See the GNU General Public License for more details.
14
15
You should have received a copy of the GNU General Public License
16
along with this program; if not, write to the Free Software
17
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19
Originally written by Ryan C. Gordon. (icculus@clutteredmind.org)
20
Adapted to work with JonoF's port by James Bentler (bentler@cs.umn.edu)
21
22
*/
23
/*
24
 * A reimplementation of Jim Dose's FX_MAN routines, using  SDL_mixer 1.2.
25
 *   Whee. FX_MAN is also known as the "Apogee Sound System", or "ASS" for
26
 *   short. How strangely appropriate that seems.
27
 */
28
29
#include <stdio.h>
30
#include <stdlib.h>
31
#include <stdarg.h>
32
#include <string.h>
33
#include <assert.h>
34
35
#include "duke3d.h"
36
#include "cache1d.h"
37
38
#if (defined __WATCOMC__)
39
// This is probably out of date.  --ryan.
40
#include "dukesnd_watcom.h"
41
#endif
42
43
#if (!defined __WATCOMC__)
44
#define cdecl
45
#endif
46
47
#include "SDL.h"
48
#include "SDL_mixer.h"
49
#include "music.h"
50
51
#define __FX_TRUE  (1 == 1)
52
#define __FX_FALSE (!__FX_TRUE)
53
54
#define DUKESND_DEBUG       "DUKESND_DEBUG"
55
56
#ifndef min
57
#define min(a, b)  (((a) < (b)) ? (a) : (b))
58
#endif
59
60
#ifndef max
61
#define max(a, b)  (((a) > (b)) ? (a) : (b))
62
#endif
63
64
void GetUnixPathFromEnvironment( char *fullname, int32 length, const char *filename );
65
66
int MUSIC_ErrorCode = MUSIC_Ok;
67
68
static char warningMessage[80];
69
static char errorMessage[80];
70
static int fx_initialized = 0;
71
static int numChannels = MIX_CHANNELS;
72
static void (*callback)(unsigned long);
73
static int reverseStereo = 0;
74
static int reverbDelay = 256;
75
static int reverbLevel = 0;
76
static int fastReverb = 0;
77
static FILE *debug_file = NULL;
78
static int initialized_debugging = 0;
79
static int mixerIsStereo = 1;
80
81
// This gets called all over the place for information and debugging messages.
82
//  If the user set the DUKESND_DEBUG environment variable, the messages
83
//  go to the file that is specified in that variable. Otherwise, they
84
//  are ignored for the expense of the function call. If DUKESND_DEBUG is
85
//  set to "-" (without the quotes), then the output goes to stdout.
86
static void musdebug(const char *fmt, ...)
87
{
88
    va_list ap;
89
90
    if (debug_file)
91
    {
92
        fprintf(debug_file, "DUKEMUS: ");
93
        va_start(ap, fmt);
94
        vfprintf(debug_file, fmt, ap);
95
        va_end(ap);
96
        fprintf(debug_file, "\n");
97
        fflush(debug_file);
98
    } // if
99
} // musdebug
100
101
static void init_debugging(void)
102
{
103
    const char *envr;
104
105
    if (initialized_debugging)
106
        return;
107
108
    envr = getenv(DUKESND_DEBUG);
109
    if (envr != NULL)
110
    {
111
        if (strcmp(envr, "-") == 0)
112
            debug_file = stdout;
113
        else
114
            debug_file = fopen(envr, "w");
115
116
        if (debug_file == NULL)
117
            fprintf(stderr, "DUKESND: -WARNING- Could not open debug file!\n");
118
        else
119
            setbuf(debug_file, NULL);
120
    } // if
121
122
    initialized_debugging = 1;
123
} // init_debugging
124
125
static void setWarningMessage(const char *msg)
126
{
127
    strncpy(warningMessage, msg, sizeof (warningMessage));
128
    // strncpy() doesn't add the null char if there isn't room...
129
    warningMessage[sizeof (warningMessage) - 1] = '\0';
130
    musdebug("Warning message set to [%s].", warningMessage);
131
} // setErrorMessage
132
133
134
static void setErrorMessage(const char *msg)
135
{
136
    strncpy(errorMessage, msg, sizeof (errorMessage));
137
    // strncpy() doesn't add the null char if there isn't room...
138
    errorMessage[sizeof (errorMessage) - 1] = '\0';
139
    musdebug("Error message set to [%s].", errorMessage);
140
} // setErrorMessage
141
142
// The music functions...
143
144
char *MUSIC_ErrorString(int ErrorNumber)
145
{
146
    switch (ErrorNumber)
147
    {
148
        case MUSIC_Warning:
149
            return(warningMessage);
150
151
        case MUSIC_Error:
152
            return(errorMessage);
153
154
        case MUSIC_Ok:
155
            return("OK; no error.");
156
157
        case MUSIC_ASSVersion:
158
            return("Incorrect sound library version.");
159
160
        case MUSIC_SoundCardError:
161
            return("General sound card error.");
162
163
        case MUSIC_InvalidCard:
164
            return("Invalid sound card.");
165
166
        case MUSIC_MidiError:
167
            return("MIDI error.");
168
169
        case MUSIC_MPU401Error:
170
            return("MPU401 error.");
171
172
        case MUSIC_TaskManError:
173
            return("Task Manager error.");
174
175
        //case MUSIC_FMNotDetected:
176
        //    return("FM not detected error.");
177
178
        case MUSIC_DPMI_Error:
179
            return("DPMI error.");
180
181
        default:
182
            return("Unknown error.");
183
    } // switch
184
185
    assert(0);    // shouldn't hit this point.
186
    return(NULL);
187
} // MUSIC_ErrorString
188
189
190
static int music_initialized = 0;
191
static int music_context = 0;
192
static int music_loopflag = MUSIC_PlayOnce;
193
static char *music_songdata = NULL;
194
static Mix_Music *music_musicchunk = NULL;
195
196
int MUSIC_Init(int SoundCard, int Address)
197
{
198
    init_debugging();
199
200
    musdebug("INIT! card=>%d, address=>%d...", SoundCard, Address);
201
202
    if (music_initialized)
203
    {
204
        setErrorMessage("Music system is already initialized.");
205
        return(MUSIC_Error);
206
    } // if
207
    
208
    SoundCard = 1;
209
210
    music_initialized = 1;
211
    return(MUSIC_Ok);
212
} // MUSIC_Init
213
214
215
int MUSIC_Shutdown(void)
216
{
217
    musdebug("shutting down sound subsystem.");
218
219
    MUSIC_StopSong();
220
    music_context = 0;
221
    music_initialized = 0;
222
    music_loopflag = MUSIC_PlayOnce;
223
    return(MUSIC_Ok);
224
} // MUSIC_Shutdown
225
226
227
void MUSIC_SetMaxFMMidiChannel(int channel)
228
{
229
    musdebug("STUB ... MUSIC_SetMaxFMMidiChannel(%d).\n", channel);
230
} // MUSIC_SetMaxFMMidiChannel
231
232
233
void MUSIC_SetVolume(int volume)
234
{
235
    volume = max( 0, volume );
236
    volume = min( volume, 255 );
237
238
    Mix_VolumeMusic(volume >> 1);  // convert 0-255 to 0-128.
239
} // MUSIC_SetVolume
240
241
242
void MUSIC_SetMidiChannelVolume(int channel, int volume)
243
{
244
    musdebug("STUB ... MUSIC_SetMidiChannelVolume(%d, %d).\n", channel, volume);
245
} // MUSIC_SetMidiChannelVolume
246
247
248
void MUSIC_ResetMidiChannelVolumes(void)
249
{
250
    musdebug("STUB ... MUSIC_ResetMidiChannelVolumes().\n");
251
} // MUSIC_ResetMidiChannelVolumes
252
253
254
int MUSIC_GetVolume(void)
255
{
256
    return(Mix_VolumeMusic(-1) << 1);  // convert 0-128 to 0-255.
257
} // MUSIC_GetVolume
258
259
260
void MUSIC_SetLoopFlag(int loopflag)
261
{
262
    music_loopflag = loopflag;
263
} // MUSIC_SetLoopFlag
264
265
266
int MUSIC_SongPlaying(void)
267
{
268
    return((Mix_PlayingMusic()) ? __FX_TRUE : __FX_FALSE);
269
} // MUSIC_SongPlaying
270
271
272
void MUSIC_Continue(void)
273
{
274
    if (Mix_PausedMusic())
275
        Mix_ResumeMusic();
276
    else if (music_songdata)
277
        MUSIC_PlaySong(music_songdata, MUSIC_PlayOnce);
278
} // MUSIC_Continue
279
280
281
void MUSIC_Pause(void)
282
{
283
    Mix_PauseMusic();
284
} // MUSIC_Pause
285
286
287
int MUSIC_StopSong(void)
288
{
289
    //if (!fx_initialized)
290
    if (!Mix_QuerySpec(NULL, NULL, NULL))
291
    {
292
        setErrorMessage("Need FX system initialized, too. Sorry.");
293
        return(MUSIC_Error);
294
    } // if
295
296
    if ( (Mix_PlayingMusic()) || (Mix_PausedMusic()) )
297
        Mix_HaltMusic();
298
299
    if (music_musicchunk)
300
        Mix_FreeMusic(music_musicchunk);
301
302
    music_songdata = NULL;
303
    music_musicchunk = NULL;
304
    return(MUSIC_Ok);
305
} // MUSIC_StopSong
306
307
308
int MUSIC_PlaySong(unsigned char *song, int loopflag)
309
{
310
    //SDL_RWops *rw;
311
312
    MUSIC_StopSong();
313
314
    music_songdata = song;
315
316
    // !!! FIXME: This could be a problem...SDL/SDL_mixer wants a RWops, which
317
    // !!! FIXME:  is an i/o abstraction. Since we already have the MIDI data
318
    // !!! FIXME:  in memory, we fake it with a memory-based RWops. None of
319
    // !!! FIXME:  this is a problem, except the RWops wants to know how big
320
    // !!! FIXME:  its memory block is (so it can do things like seek on an
321
    // !!! FIXME:  offset from the end of the block), and since we don't have
322
    // !!! FIXME:  this information, we have to give it SOMETHING.
323
324
    /* !!! ARGH! There's no LoadMUS_RW  ?!
325
    rw = SDL_RWFromMem((void *) song, (10 * 1024) * 1024);  // yikes.
326
    music_musicchunk = Mix_LoadMUS_RW(rw);
327
    Mix_PlayMusic(music_musicchunk, (loopflag == MUSIC_PlayOnce) ? 0 : -1);
328
    */
329
330
    return(MUSIC_Ok);
331
} // MUSIC_PlaySong
332
333
334
extern char ApogeePath[256];
335
336
// Duke3D-specific.  --ryan.
337
void PlayMusic(char *_filename)
338
{
339
    //char filename[MAX_PATH];
340
    //strcpy(filename, _filename);
341
    //FixFilePath(filename);
342
343
    char filename[MAX_PATH];
344
    long handle;
345
    long size;
346
    void *song;
347
    long rc;
348
349
    MUSIC_StopSong();
350
351
    // Read from a groupfile, write it to disk so SDL_mixer can read it.
352
    //   Lame.  --ryan.
353
    handle = kopen4load(_filename, 0);
354
    if (handle == -1)
355
        return;
356
357
    size = kfilelength(handle);
358
    if (size == -1)
359
    {
360
        kclose(handle);
361
        return;
362
    } // if
363
364
    song = malloc(size);
365
    if (song == NULL)
366
    {
367
        kclose(handle);
368
        return;
369
    } // if
370
371
    rc = kread(handle, song, size);
372
    kclose(handle);
373
    if (rc != size)
374
    {
375
        free(song);
376
        return;
377
    } // if
378
379
    // save the file somewhere, so SDL_mixer can load it
380
    GetUnixPathFromEnvironment(filename, MAX_PATH, "tmpsong.mid");
381
    handle = SafeOpenWrite(filename, filetype_binary);
382
    
383
    SafeWrite(handle, song, size);
384
    close(handle);
385
    free(song);
386
    
387
    //music_songdata = song;
388
389
    music_musicchunk = Mix_LoadMUS(filename);
390
    if (music_musicchunk != NULL)
391
    {
392
        // !!! FIXME: I set the music to loop. Hope that's okay. --ryan.
393
        Mix_PlayMusic(music_musicchunk, -1);
394
    } // if
395
}
396
397
398
void MUSIC_SetContext(int context)
399
{
400
    musdebug("STUB ... MUSIC_SetContext().\n");
401
    music_context = context;
402
} // MUSIC_SetContext
403
404
405
int MUSIC_GetContext(void)
406
{
407
    return(music_context);
408
} // MUSIC_GetContext
409
410
411
void MUSIC_SetSongTick(unsigned long PositionInTicks)
412
{
413
    musdebug("STUB ... MUSIC_SetSongTick().\n");
414
} // MUSIC_SetSongTick
415
416
417
void MUSIC_SetSongTime(unsigned long milliseconds)
418
{
419
    musdebug("STUB ... MUSIC_SetSongTime().\n");
420
}// MUSIC_SetSongTime
421
422
423
void MUSIC_SetSongPosition(int measure, int beat, int tick)
424
{
425
    musdebug("STUB ... MUSIC_SetSongPosition().\n");
426
} // MUSIC_SetSongPosition
427
428
429
void MUSIC_GetSongPosition(songposition *pos)
430
{
431
    musdebug("STUB ... MUSIC_GetSongPosition().\n");
432
} // MUSIC_GetSongPosition
433
434
435
void MUSIC_GetSongLength(songposition *pos)
436
{
437
    musdebug("STUB ... MUSIC_GetSongLength().\n");
438
} // MUSIC_GetSongLength
439
440
441
int MUSIC_FadeVolume(int tovolume, int milliseconds)
442
{
443
    Mix_FadeOutMusic(milliseconds);
444
    return(MUSIC_Ok);
445
} // MUSIC_FadeVolume
446
447
448
int MUSIC_FadeActive(void)
449
{
450
    return((Mix_FadingMusic() == MIX_FADING_OUT) ? __FX_TRUE : __FX_FALSE);
451
} // MUSIC_FadeActive
452
453
454
void MUSIC_StopFade(void)
455
{
456
    musdebug("STUB ... MUSIC_StopFade().\n");
457
} // MUSIC_StopFade
458
459
460
void MUSIC_RerouteMidiChannel(int channel, int cdecl (*function)( int event, int c1, int c2 ))
461
{
462
    musdebug("STUB ... MUSIC_RerouteMidiChannel().\n");
463
} // MUSIC_RerouteMidiChannel
464
465
466
void MUSIC_RegisterTimbreBank(unsigned char *timbres)
467
{
468
    musdebug("STUB ... MUSIC_RegisterTimbreBank().\n");
469
} // MUSIC_RegisterTimbreBank
470
471
472
void MUSIC_Update(void)
473
{
474
}
(-)./source/jaudiolib/unixglob.c (+145 lines)
Line 0 Link Here
1
/*
2
Copyright (C) 2003-2004 Ryan C. Gordon. and James Bentler
3
4
This program is free software; you can redistribute it and/or
5
modify it under the terms of the GNU General Public License
6
as published by the Free Software Foundation; either version 2
7
of the License, or (at your option) any later version.
8
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13
See the GNU General Public License for more details.
14
15
You should have received a copy of the GNU General Public License
16
along with this program; if not, write to the Free Software
17
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19
Originally written by Ryan C. Gordon. (icculus@clutteredmind.org)
20
Adapted to work with JonoF's port by James Bentler (bentler@cs.umn.edu)
21
22
*/
23
24
static char ApogeePath[256];
25
26
#define PATH_SEP_CHAR '/'
27
#define PATH_SEP_STR  "/"
28
#define ROOTDIR       "/"
29
#define CURDIR        "./"
30
31
#include "duke3d.h"
32
#include <dirent.h>
33
#include <errno.h>
34
35
void FixFilePath(char *filename)
36
{
37
    char *ptr;
38
    char *lastsep = filename;
39
40
    if ((!filename) || (*filename == '\0'))
41
        return;
42
43
    if (access(filename, F_OK) == 0)  /* File exists; we're good to go. */
44
        return;
45
46
    for (ptr = filename; 1; ptr++)
47
    {
48
        if (*ptr == '\\')
49
            *ptr = PATH_SEP_CHAR;
50
51
        if ((*ptr == PATH_SEP_CHAR) || (*ptr == '\0'))
52
        {
53
            char pch = *ptr;
54
            struct dirent *dent = NULL;
55
            DIR *dir;
56
57
            if ((pch == PATH_SEP_CHAR) && (*(ptr + 1) == '\0'))
58
                return; /* eos is pathsep; we're done. */
59
60
            if (lastsep == ptr)
61
                continue;  /* absolute path; skip to next one. */
62
63
            *ptr = '\0';
64
            if (lastsep == filename) {
65
                dir = opendir((*lastsep == PATH_SEP_CHAR) ? ROOTDIR : CURDIR);
66
                
67
                if (*lastsep == PATH_SEP_CHAR) {
68
                    lastsep++;
69
                }
70
            } 
71
            else
72
            {
73
                *lastsep = '\0';
74
                dir = opendir(filename);
75
                *lastsep = PATH_SEP_CHAR;
76
                lastsep++;
77
            }
78
79
            if (dir == NULL)
80
            {
81
                *ptr = PATH_SEP_CHAR;
82
                return;  /* maybe dir doesn't exist? give up. */
83
            }
84
85
            while ((dent = readdir(dir)) != NULL)
86
            {
87
                if (strcasecmp(dent->d_name, lastsep) == 0)
88
                {
89
                    /* found match; replace it. */
90
                    strcpy(lastsep, dent->d_name);
91
                    break;
92
                }
93
            }
94
95
            closedir(dir);
96
            *ptr = pch;
97
            lastsep = ptr;
98
99
            if (dent == NULL)
100
                return;  /* no match. oh well. */
101
102
            if (pch == '\0')  /* eos? */
103
                return;
104
        }
105
    }
106
}
107
108
int32 SafeOpenWrite (const char *_filename, int32 filetype)
109
{
110
	int	handle;
111
    char filename[MAX_PATH];
112
    strncpy(filename, _filename, sizeof (filename));
113
    filename[sizeof (filename) - 1] = '\0';
114
    FixFilePath(filename);
115
116
	handle = open(filename,O_RDWR | O_BINARY | O_CREAT | O_TRUNC
117
	, S_IREAD | S_IWRITE);
118
119
	if (handle == -1)
120
		Error ("Error opening %s: %s",filename,strerror(errno));
121
122
	return handle;
123
}
124
125
126
void SafeWrite (int32 handle, void *buffer, int32 count)
127
{
128
	unsigned	iocount;
129
130
	while (count)
131
	{
132
		iocount = count > 0x8000 ? 0x8000 : count;
133
		if (write (handle,buffer,iocount) != (int)iocount)
134
			Error ("File write failure writing %ld bytes",count);
135
		buffer = (void *)( (byte *)buffer + iocount );
136
		count -= iocount;
137
	}
138
}
139
140
141
142
void GetUnixPathFromEnvironment( char *fullname, int32 length, const char *filename )
143
{
144
	snprintf(fullname, length-1, "%s%s", ApogeePath, filename);
145
}
(-)./source/jaudiolib/unixpitch.c (+212 lines)
Line 0 Link Here
1
/*
2
Copyright (C) 1994-1995 Apogee Software, Ltd.
3
4
This program is free software; you can redistribute it and/or
5
modify it under the terms of the GNU General Public License
6
as published by the Free Software Foundation; either version 2
7
of the License, or (at your option) any later version.
8
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13
See the GNU General Public License for more details.
14
15
You should have received a copy of the GNU General Public License
16
along with this program; if not, write to the Free Software
17
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19
*/
20
/**********************************************************************
21
   module: PITCH.C
22
23
   author: James R. Dose
24
   date:   June 14, 1993
25
26
   Routines for pitch scaling.
27
28
   (c) Copyright 1993 James R. Dose.  All Rights Reserved.
29
**********************************************************************/
30
31
#include <stdlib.h>
32
//#include <math.h>
33
#include "dpmi.h"
34
#include "standard.h"
35
#include "pitch.h"
36
37
#define MAXDETUNE 25
38
39
static unsigned long PitchTable[ 12 ][ MAXDETUNE ] =
40
   {
41
      { 0x10000, 0x10097, 0x1012f, 0x101c7, 0x10260, 0x102f9, 0x10392, 0x1042c,
42
      0x104c6, 0x10561, 0x105fb, 0x10696, 0x10732, 0x107ce, 0x1086a, 0x10907,
43
      0x109a4, 0x10a41, 0x10adf, 0x10b7d, 0x10c1b, 0x10cba, 0x10d59, 0x10df8,
44
      0x10e98 },
45
      { 0x10f38, 0x10fd9, 0x1107a, 0x1111b, 0x111bd, 0x1125f, 0x11302, 0x113a5,
46
      0x11448, 0x114eb, 0x1158f, 0x11634, 0x116d8, 0x1177e, 0x11823, 0x118c9,
47
      0x1196f, 0x11a16, 0x11abd, 0x11b64, 0x11c0c, 0x11cb4, 0x11d5d, 0x11e06,
48
      0x11eaf },
49
      { 0x11f59, 0x12003, 0x120ae, 0x12159, 0x12204, 0x122b0, 0x1235c, 0x12409,
50
      0x124b6, 0x12563, 0x12611, 0x126bf, 0x1276d, 0x1281c, 0x128cc, 0x1297b,
51
      0x12a2b, 0x12adc, 0x12b8d, 0x12c3e, 0x12cf0, 0x12da2, 0x12e55, 0x12f08,
52
      0x12fbc },
53
      { 0x1306f, 0x13124, 0x131d8, 0x1328d, 0x13343, 0x133f9, 0x134af, 0x13566,
54
      0x1361d, 0x136d5, 0x1378d, 0x13846, 0x138fe, 0x139b8, 0x13a72, 0x13b2c,
55
      0x13be6, 0x13ca1, 0x13d5d, 0x13e19, 0x13ed5, 0x13f92, 0x1404f, 0x1410d,
56
      0x141cb },
57
      { 0x1428a, 0x14349, 0x14408, 0x144c8, 0x14588, 0x14649, 0x1470a, 0x147cc,
58
      0x1488e, 0x14951, 0x14a14, 0x14ad7, 0x14b9b, 0x14c5f, 0x14d24, 0x14dea,
59
      0x14eaf, 0x14f75, 0x1503c, 0x15103, 0x151cb, 0x15293, 0x1535b, 0x15424,
60
      0x154ee },
61
      { 0x155b8, 0x15682, 0x1574d, 0x15818, 0x158e4, 0x159b0, 0x15a7d, 0x15b4a,
62
      0x15c18, 0x15ce6, 0x15db4, 0x15e83, 0x15f53, 0x16023, 0x160f4, 0x161c5,
63
      0x16296, 0x16368, 0x1643a, 0x1650d, 0x165e1, 0x166b5, 0x16789, 0x1685e,
64
      0x16934 },
65
      { 0x16a09, 0x16ae0, 0x16bb7, 0x16c8e, 0x16d66, 0x16e3e, 0x16f17, 0x16ff1,
66
      0x170ca, 0x171a5, 0x17280, 0x1735b, 0x17437, 0x17513, 0x175f0, 0x176ce,
67
      0x177ac, 0x1788a, 0x17969, 0x17a49, 0x17b29, 0x17c09, 0x17cea, 0x17dcc,
68
      0x17eae },
69
      { 0x17f91, 0x18074, 0x18157, 0x1823c, 0x18320, 0x18406, 0x184eb, 0x185d2,
70
      0x186b8, 0x187a0, 0x18888, 0x18970, 0x18a59, 0x18b43, 0x18c2d, 0x18d17,
71
      0x18e02, 0x18eee, 0x18fda, 0x190c7, 0x191b5, 0x192a2, 0x19391, 0x19480,
72
      0x1956f },
73
      { 0x1965f, 0x19750, 0x19841, 0x19933, 0x19a25, 0x19b18, 0x19c0c, 0x19d00,
74
      0x19df4, 0x19ee9, 0x19fdf, 0x1a0d5, 0x1a1cc, 0x1a2c4, 0x1a3bc, 0x1a4b4,
75
      0x1a5ad, 0x1a6a7, 0x1a7a1, 0x1a89c, 0x1a998, 0x1aa94, 0x1ab90, 0x1ac8d,
76
      0x1ad8b },
77
      { 0x1ae89, 0x1af88, 0x1b088, 0x1b188, 0x1b289, 0x1b38a, 0x1b48c, 0x1b58f,
78
      0x1b692, 0x1b795, 0x1b89a, 0x1b99f, 0x1baa4, 0x1bbaa, 0x1bcb1, 0x1bdb8,
79
      0x1bec0, 0x1bfc9, 0x1c0d2, 0x1c1dc, 0x1c2e6, 0x1c3f1, 0x1c4fd, 0x1c609,
80
      0x1c716 },
81
      { 0x1c823, 0x1c931, 0x1ca40, 0x1cb50, 0x1cc60, 0x1cd70, 0x1ce81, 0x1cf93,
82
      0x1d0a6, 0x1d1b9, 0x1d2cd, 0x1d3e1, 0x1d4f6, 0x1d60c, 0x1d722, 0x1d839,
83
      0x1d951, 0x1da69, 0x1db82, 0x1dc9c, 0x1ddb6, 0x1ded1, 0x1dfec, 0x1e109,
84
      0x1e225 },
85
      { 0x1e343, 0x1e461, 0x1e580, 0x1e6a0, 0x1e7c0, 0x1e8e0, 0x1ea02, 0x1eb24,
86
      0x1ec47, 0x1ed6b, 0x1ee8f, 0x1efb4, 0x1f0d9, 0x1f1ff, 0x1f326, 0x1f44e,
87
      0x1f576, 0x1f69f, 0x1f7c9, 0x1f8f3, 0x1fa1e, 0x1fb4a, 0x1fc76, 0x1fda3,
88
      0x1fed1 }
89
   };
90
91
92
//static int PITCH_Installed = FALSE;
93
94
95
/*---------------------------------------------------------------------
96
   Function: PITCH_Init
97
98
   Initializes pitch table.
99
---------------------------------------------------------------------*/
100
/*
101
void PITCH_Init
102
   (
103
   void
104
   )
105
106
   {
107
   int note;
108
   int detune;
109
110
   if ( !PITCH_Installed )
111
      {
112
      for( note = 0; note < 12; note++ )
113
         {
114
         for( detune = 0; detune < MAXDETUNE; detune++ )
115
            {
116
            PitchTable[ note ][ detune ] = 0x10000 *
117
               pow( 2, ( note * MAXDETUNE + detune ) / ( 12.0 * MAXDETUNE ) );
118
            }
119
         }
120
121
      PITCH_Installed = TRUE;
122
      }
123
   }
124
*/
125
126
/**********************************************************************
127
128
   Memory locked functions:
129
130
**********************************************************************/
131
132
133
#define PITCH_LockStart PITCH_GetScale
134
135
136
/*---------------------------------------------------------------------
137
   Function: PITCH_GetScale
138
139
   Returns a fixed-point value to scale number the specified amount.
140
---------------------------------------------------------------------*/
141
142
unsigned long PITCH_GetScale
143
   (
144
   int pitchoffset
145
   )
146
147
   {
148
   unsigned long scale;
149
   int octaveshift;
150
   int noteshift;
151
   int note;
152
   int detune;
153
154
//   if ( !PITCH_Installed )
155
//      {
156
//      PITCH_Init();
157
//      }
158
159
   if ( pitchoffset == 0 )
160
      {
161
      return( PitchTable[ 0 ][ 0 ] );
162
      }
163
164
   noteshift = pitchoffset % 1200;
165
   if ( noteshift < 0 )
166
      {
167
      noteshift += 1200;
168
      }
169
170
   note   = noteshift / 100;
171
   detune = ( noteshift % 100 ) / ( 100 / MAXDETUNE );
172
   octaveshift = ( pitchoffset - noteshift ) / 1200;
173
174
   if ( detune < 0 )
175
      {
176
      detune += ( 100 / MAXDETUNE );
177
      note--;
178
      if ( note < 0 )
179
         {
180
         note += 12;
181
         octaveshift--;
182
         }
183
      }
184
185
   scale = PitchTable[ note ][ detune ];
186
187
   if ( octaveshift < 0 )
188
      {
189
      scale >>= -octaveshift;
190
      }
191
   else
192
      {
193
      scale <<= octaveshift;
194
      }
195
196
   return( scale );
197
   }
198
199
200
/*---------------------------------------------------------------------
201
   Function: PITCH_LockEnd
202
203
   Used for determining the length of the functions to lock in memory.
204
---------------------------------------------------------------------*/
205
206
static void PITCH_LockEnd
207
   (
208
   void
209
   )
210
211
   {
212
   }
(-)./source/jaudiolib/unixvoc.c (+2877 lines)
Line 0 Link Here
1
/*
2
Copyright (C) 1994-1995 Apogee Software, Ltd.
3
4
This program is free software; you can redistribute it and/or
5
modify it under the terms of the GNU General Public License
6
as published by the Free Software Foundation; either version 2
7
of the License, or (at your option) any later version.
8
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13
See the GNU General Public License for more details.
14
15
You should have received a copy of the GNU General Public License
16
along with this program; if not, write to the Free Software
17
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19
*/
20
/**********************************************************************
21
   module: MULTIVOC.C
22
23
   author: James R. Dose
24
   date:   December 20, 1993
25
26
   Routines to provide multichannel digitized sound playback for
27
   Sound Blaster compatible sound cards.
28
29
   (c) Copyright 1993 James R. Dose.  All Rights Reserved.
30
**********************************************************************/
31
32
#include <stdio.h>
33
#include <stdlib.h>
34
#include <string.h>
35
#include <time.h>
36
37
#include "util.h"
38
#include "dpmi.h"
39
#include "usrhooks.h"
40
#include "interrup.h"
41
#include "dma.h"
42
#include "linklist.h"
43
#include "dsl.h"
44
45
#include "pitch.h"
46
#include "multivoc.h"
47
#include "_multivc.h"
48
#include "debugio.h"
49
50
// platform.h is from the build engine, but I need the byteswapping macros... --ryan.
51
#include "platform.h"
52
53
#define RoundFixed( fixedval, bits )            \
54
        (                                       \
55
          (                                     \
56
            (fixedval) + ( 1 << ( (bits) - 1 ) )\
57
          ) >> (bits)                           \
58
        )
59
60
#define IS_QUIET( ptr )  ( ( void * )( ptr ) == ( void * )&MV_VolumeTable[ 0 ] )
61
62
static int       MV_ReverbLevel;
63
static int       MV_ReverbDelay;
64
static VOLUME16 *MV_ReverbTable = NULL;
65
66
//static signed short MV_VolumeTable[ MV_MaxVolume + 1 ][ 256 ];
67
static signed short MV_VolumeTable[ 63 + 1 ][ 256 ];
68
69
//static Pan MV_PanTable[ MV_NumPanPositions ][ MV_MaxVolume + 1 ];
70
static Pan MV_PanTable[ MV_NumPanPositions ][ 63 + 1 ];
71
72
static int MV_Installed   = FALSE;
73
static int MV_SoundCard   = 1;
74
static int MV_TotalVolume = MV_MaxTotalVolume;
75
static int MV_MaxVoices   = 1;
76
static int MV_Recording;
77
78
static int MV_BufferSize = MixBufferSize;
79
static int MV_BufferLength;
80
81
static int MV_NumberOfBuffers = NumberOfBuffers;
82
83
static int MV_MixMode    = MONO_8BIT;
84
static int MV_Channels   = 1;
85
static int MV_Bits       = 8;
86
87
static int MV_Silence    = SILENCE_8BIT;
88
static int MV_SwapLeftRight = FALSE;
89
90
static int MV_RequestedMixRate;
91
static int MV_MixRate;
92
93
static int MV_DMAChannel = -1;
94
static int MV_BuffShift;
95
96
static int MV_TotalMemory;
97
98
static int   MV_BufferDescriptor;
99
static int   MV_BufferEmpty[ NumberOfBuffers ];
100
char *MV_MixBuffer[ NumberOfBuffers + 1 ];
101
102
static VoiceNode *MV_Voices = NULL;
103
104
static volatile VoiceNode VoiceList;
105
static volatile VoiceNode VoicePool;
106
107
/*static*/ int MV_MixPage      = 0;
108
static int MV_VoiceHandle  = MV_MinVoiceHandle;
109
110
static void ( *MV_CallBackFunc )( unsigned long ) = NULL;
111
static void ( *MV_RecordFunc )( char *ptr, int length ) = NULL;
112
static void ( *MV_MixFunction )( VoiceNode *voice, int buffer );
113
114
static int MV_MaxVolume = 63;
115
116
char  *MV_HarshClipTable;
117
char  *MV_MixDestination;
118
short *MV_LeftVolume;
119
short *MV_RightVolume;
120
int    MV_SampleSize = 1;
121
int    MV_RightChannelOffset;
122
123
unsigned long MV_MixPosition;
124
125
int MV_ErrorCode = MV_Ok;
126
127
#define MV_SetErrorCode( status ) \
128
   MV_ErrorCode   = ( status );
129
130
131
/*---------------------------------------------------------------------
132
   Function: MV_ErrorString
133
134
   Returns a pointer to the error message associated with an error
135
   number.  A -1 returns a pointer the current error.
136
---------------------------------------------------------------------*/
137
138
char *MV_ErrorString
139
   (
140
   int ErrorNumber
141
   )
142
143
   {
144
   char *ErrorString;
145
146
   switch( ErrorNumber )
147
      {
148
      case MV_Warning :
149
      case MV_Error :
150
         ErrorString = MV_ErrorString( MV_ErrorCode );
151
         break;
152
153
      case MV_Ok :
154
         ErrorString = "Multivoc ok.";
155
         break;
156
157
      case MV_UnsupportedCard :
158
         ErrorString = "Selected sound card is not supported by Multivoc.";
159
         break;
160
161
      case MV_NotInstalled :
162
         ErrorString = "Multivoc not installed.";
163
         break;
164
165
      case MV_NoVoices :
166
         ErrorString = "No free voices available to Multivoc.";
167
         break;
168
169
      case MV_NoMem :
170
         ErrorString = "Out of memory in Multivoc.";
171
         break;
172
173
      case MV_VoiceNotFound :
174
         ErrorString = "No voice with matching handle found.";
175
         break;
176
177
      case MV_DPMI_Error :
178
         ErrorString = "DPMI Error in Multivoc.";
179
         break;
180
181
      case MV_InvalidVOCFile :
182
         ErrorString = "Invalid VOC file passed in to Multivoc.";
183
         break;
184
185
      case MV_InvalidWAVFile :
186
         ErrorString = "Invalid WAV file passed in to Multivoc.";
187
         break;
188
189
      case MV_InvalidMixMode :
190
         ErrorString = "Invalid mix mode request in Multivoc.";
191
         break;
192
193
      case MV_IrqFailure :
194
         ErrorString = "Playback failed, possibly due to an invalid or conflicting IRQ.";
195
         break;
196
197
      case MV_DMAFailure :
198
         ErrorString = "Playback failed, possibly due to an invalid or conflicting DMA channel.";
199
         break;
200
201
      case MV_DMA16Failure :
202
         ErrorString = "Playback failed, possibly due to an invalid or conflicting DMA channel.  \n"
203
                       "Make sure the 16-bit DMA channel is correct.";
204
         break;
205
206
      case MV_NullRecordFunction :
207
         ErrorString = "Null record function passed to MV_StartRecording.";
208
         break;
209
210
      default :
211
         ErrorString = "Unknown Multivoc error code.";
212
         break;
213
      }
214
215
   return( ErrorString );
216
   }
217
218
219
/**********************************************************************
220
221
   Memory locked functions:
222
223
**********************************************************************/
224
225
226
#define MV_LockStart MV_Mix
227
228
229
/*---------------------------------------------------------------------
230
   Function: MV_Mix
231
232
   Mixes the sound into the buffer.
233
---------------------------------------------------------------------*/
234
235
static void MV_Mix
236
   (
237
   VoiceNode *voice,
238
   int        buffer
239
   )
240
241
   {
242
   char          *start;
243
   int            length;
244
   long           voclength;
245
   unsigned long  position;
246
   unsigned long  rate;
247
   unsigned long  FixedPointBufferSize;
248
249
   if ( ( voice->length == 0 ) &&
250
        ( voice->GetSound != NULL ) &&
251
        ( voice->GetSound( voice ) != KeepPlaying ) )
252
      {
253
      return;
254
      }
255
256
   length               = MixBufferSize;
257
   FixedPointBufferSize = voice->FixedPointBufferSize;
258
259
   MV_MixDestination    = MV_MixBuffer[ buffer ];
260
   MV_LeftVolume        = voice->LeftVolume;
261
   MV_RightVolume       = voice->RightVolume;
262
263
   if ( ( MV_Channels == 2 ) && ( IS_QUIET( MV_LeftVolume ) ) )
264
      {
265
      MV_LeftVolume      = MV_RightVolume;
266
      MV_MixDestination += MV_RightChannelOffset;
267
      }
268
269
   // Add this voice to the mix
270
   while( length > 0 )
271
      {
272
      start    = voice->sound;
273
      rate     = voice->RateScale;
274
      position = voice->position;
275
276
      // Check if the last sample in this buffer would be
277
      // beyond the length of the sample block
278
      if ( ( position + FixedPointBufferSize ) >= voice->length )
279
         {
280
         if ( position < voice->length )
281
            {
282
            voclength = ( voice->length - position + rate - 1 ) / rate;
283
            }
284
         else
285
            {
286
            voice->GetSound( voice );
287
            return;
288
            }
289
         }
290
      else
291
         {
292
         voclength = length;
293
         }
294
295
      voice->mix( position, rate, start, voclength );
296
297
      if ( voclength & 1 )
298
         {
299
         MV_MixPosition += rate;
300
         voclength -= 1;
301
         }
302
      voice->position = MV_MixPosition;
303
304
      length -= voclength;
305
306
      if ( voice->position >= voice->length )
307
         {
308
         // Get the next block of sound
309
         if ( voice->GetSound( voice ) != KeepPlaying )
310
            {
311
            return;
312
            }
313
314
         if ( length > 0 )
315
            {
316
            // Get the position of the last sample in the buffer
317
            FixedPointBufferSize = voice->RateScale * ( length - 1 );
318
            }
319
         }
320
      }
321
   }
322
323
324
/*---------------------------------------------------------------------
325
   Function: MV_PlayVoice
326
327
   Adds a voice to the play list.
328
---------------------------------------------------------------------*/
329
330
void MV_PlayVoice
331
   (
332
   VoiceNode *voice
333
   )
334
335
   {
336
   unsigned flags;
337
338
   flags = DisableInterrupts();
339
   LL_SortedInsertion( &VoiceList, voice, prev, next, VoiceNode, priority );
340
341
   RestoreInterrupts( flags );
342
   }
343
344
345
/*---------------------------------------------------------------------
346
   Function: MV_StopVoice
347
348
   Removes the voice from the play list and adds it to the free list.
349
---------------------------------------------------------------------*/
350
351
void MV_StopVoice
352
   (
353
   VoiceNode *voice
354
   )
355
356
   {
357
   unsigned  flags;
358
359
   flags = DisableInterrupts();
360
361
   // move the voice from the play list to the free list
362
   LL_Remove( voice, next, prev );
363
   LL_Add( (VoiceNode *)&VoicePool, voice, next, prev );
364
365
   RestoreInterrupts( flags );
366
   }
367
368
369
/*---------------------------------------------------------------------
370
   Function: MV_ServiceVoc
371
372
   Starts playback of the waiting buffer and mixes the next one.
373
---------------------------------------------------------------------*/
374
375
// static int backcolor = 1;
376
377
static int MV_ServiceVoc(int dummy_arg)
378
   {
379
   VoiceNode *voice;
380
   VoiceNode *next;
381
   char      *buffer;
382
383
   // Toggle which buffer we'll mix next
384
   MV_MixPage++;
385
   if ( MV_MixPage >= MV_NumberOfBuffers )
386
      {
387
      MV_MixPage -= MV_NumberOfBuffers;
388
      }
389
390
   if ( MV_ReverbLevel == 0 )
391
      {
392
      // Initialize buffer
393
      //Commented out so that the buffer is always cleared.
394
      //This is so the guys at Echo Speech can mix into the
395
      //buffer even when no sounds are playing.
396
      //if ( !MV_BufferEmpty[ MV_MixPage ] )
397
         {
398
         ClearBuffer_DW( MV_MixBuffer[ MV_MixPage ], MV_Silence, MV_BufferSize >> 2 );
399
         MV_BufferEmpty[ MV_MixPage ] = TRUE;
400
         }
401
      }
402
   else
403
      {
404
      char *end;
405
      char *source;
406
      char *dest;
407
      int   count;
408
      int   length;
409
410
      end = MV_MixBuffer[ 0 ] + MV_BufferLength;;
411
      dest = MV_MixBuffer[ MV_MixPage ];
412
      source = MV_MixBuffer[ MV_MixPage ] - MV_ReverbDelay;
413
      if ( source < MV_MixBuffer[ 0 ] )
414
         {
415
         source += MV_BufferLength;
416
         }
417
418
      length = MV_BufferSize;
419
      while( length > 0 )
420
         {
421
         count = length;
422
         if ( source + count > end )
423
            {
424
            count = end - source;
425
            }
426
427
         if ( MV_Bits == 16 )
428
            {
429
            if ( MV_ReverbTable != NULL )
430
                MV_16BitReverb( source, dest, (const VOLUME16 *)MV_ReverbTable, count / 2 );
431
            else
432
                MV_16BitReverbFast( source, dest, count / 2, MV_ReverbLevel );
433
            }
434
         else
435
            {
436
            if ( MV_ReverbTable != NULL )
437
                MV_8BitReverb( source, dest, (const VOLUME16 *)MV_ReverbTable, count );
438
            else
439
                MV_8BitReverbFast( source, dest, count, MV_ReverbLevel );
440
            }
441
442
         // if we go through the loop again, it means that we've wrapped around the buffer
443
         source  = MV_MixBuffer[ 0 ];
444
         dest   += count;
445
         length -= count;
446
         }
447
      }
448
449
   // Play any waiting voices
450
   for( voice = VoiceList.next; voice != &VoiceList; voice = next )
451
      {
452
//      if ( ( voice < &MV_Voices[ 0 ] ) || ( voice > &MV_Voices[ 8 ] ) )
453
//         {
454
//         SetBorderColor(backcolor++);
455
//         break;
456
//         }
457
458
      MV_BufferEmpty[ MV_MixPage ] = FALSE;
459
460
      if (MV_MixFunction != NULL)
461
        MV_MixFunction( voice, MV_MixPage );
462
463
      next = voice->next;
464
465
      // Is this voice done?
466
      if ( !voice->Playing )
467
         {
468
         MV_StopVoice( voice );
469
470
         if ( MV_CallBackFunc )
471
            {
472
            MV_CallBackFunc( voice->callbackval );
473
            }
474
         }
475
      }
476
   }
477
478
479
int leftpage  = -1;
480
int rightpage = -1;
481
482
void MV_ServiceGus( char **ptr, unsigned long *length )
483
   {
484
   if ( leftpage == MV_MixPage )
485
      {
486
      MV_ServiceVoc(0);
487
      }
488
489
   leftpage = MV_MixPage;
490
491
   *ptr = MV_MixBuffer[ MV_MixPage ];
492
   *length = MV_BufferSize;
493
   }
494
495
void MV_ServiceRightGus( char **ptr, unsigned long *length )
496
   {
497
   if ( rightpage == MV_MixPage )
498
      {
499
      MV_ServiceVoc(0);
500
      }
501
502
   rightpage = MV_MixPage;
503
504
   *ptr = MV_MixBuffer[ MV_MixPage ] + MV_RightChannelOffset;
505
   *length = MV_BufferSize;
506
   }
507
508
/*---------------------------------------------------------------------
509
   Function: MV_GetNextVOCBlock
510
511
   Interperate the information of a VOC format sound file.
512
---------------------------------------------------------------------*/
513
static __inline unsigned int get_le32(void *p0)
514
{
515
	//unsigned char *p = p0;
516
	//return p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);
517
	unsigned int val = *((unsigned int *) p0);
518
	return(BUILDSWAP_INTEL32(val));
519
}
520
521
static __inline unsigned int get_le16(void *p0)
522
{
523
	//unsigned char *p = p0;
524
	//return p[0] | (p[1]<<8);
525
	unsigned short val = *((unsigned short *) p0);
526
	return( (unsigned int) (BUILDSWAP_INTEL16(val)) );
527
}
528
529
playbackstatus MV_GetNextVOCBlock
530
   (
531
   VoiceNode *voice
532
   )
533
534
   {
535
   unsigned char *ptr;
536
   int            blocktype=0;
537
   int            lastblocktype=0;
538
   unsigned long  blocklength=0l;
539
   unsigned long  samplespeed=0l;
540
   unsigned int   tc=0;
541
   int            packtype=0;
542
   int            voicemode=0;
543
   int            done=0;
544
   unsigned       BitsPerSample;
545
   unsigned       Channels;
546
   unsigned       Format;
547
548
   if ( voice->BlockLength > 0 )
549
      {
550
      voice->position    -= voice->length;
551
      voice->sound       += voice->length >> 16;
552
      if ( voice->bits == 16 )
553
         {
554
         voice->sound += voice->length >> 16;
555
         }
556
      voice->length       = min( voice->BlockLength, 0x8000 );
557
      voice->BlockLength -= voice->length;
558
      voice->length     <<= 16;
559
      return( KeepPlaying );
560
      }
561
562
   if ( ( voice->length > 0 ) && ( voice->LoopEnd != NULL ) &&
563
      ( voice->LoopStart != NULL ) )
564
      {
565
      voice->BlockLength  = voice->LoopSize;
566
      voice->sound        = voice->LoopStart;
567
      voice->position     = 0;
568
      voice->length       = min( voice->BlockLength, 0x8000 );
569
      voice->BlockLength -= voice->length;
570
      voice->length     <<= 16;
571
      return( KeepPlaying );
572
      }
573
574
   ptr = ( unsigned char * )voice->NextBlock;
575
576
   voice->Playing = TRUE;
577
578
   voicemode = 0;
579
   lastblocktype = 0;
580
   packtype = 0;
581
582
   done = FALSE;
583
   while( !done )
584
      {
585
      // Stop playing if we get a NULL pointer
586
      if ( ptr == NULL )
587
         {
588
         voice->Playing = FALSE;
589
         done = TRUE;
590
         break;
591
         }
592
593
      {
594
      unsigned tmp = get_le32(ptr);
595
      blocktype = tmp&255;
596
      blocklength = tmp>>8;
597
      }
598
      ptr += 4;
599
600
      switch( blocktype )
601
         {
602
         case 0 :
603
            // End of data
604
            if ( ( voice->LoopStart == NULL ) ||
605
               ( (unsigned char *)voice->LoopStart >= ( ptr - 4 ) ) )
606
               {
607
               voice->Playing = FALSE;
608
               done = TRUE;
609
               }
610
            else
611
               {
612
               voice->BlockLength  = ( ptr - 4 ) - (unsigned char *)voice->LoopStart;
613
               voice->sound        = voice->LoopStart;
614
               voice->position     = 0;
615
               voice->length       = min( voice->BlockLength, 0x8000 );
616
               voice->BlockLength -= voice->length;
617
               voice->length     <<= 16;
618
               return( KeepPlaying );
619
               }
620
            break;
621
622
         case 1 :
623
            // Sound data block
624
            voice->bits  = 8;
625
            if ( lastblocktype != 8 )
626
               {
627
               tc = ( unsigned int )*ptr << 8;
628
               packtype = *( ptr + 1 );
629
               }
630
631
            ptr += 2;
632
            blocklength -= 2;
633
634
            samplespeed = 256000000L / ( 65536 - tc );
635
636
            // Skip packed or stereo data
637
            if ( ( packtype != 0 ) || ( voicemode != 0 ) )
638
               {
639
               ptr += blocklength;
640
               }
641
            else
642
               {
643
               done = TRUE;
644
               }
645
            voicemode = 0;
646
            break;
647
648
         case 2 :
649
            // Sound continuation block
650
            samplespeed = voice->SamplingRate;
651
            done = TRUE;
652
            break;
653
654
         case 3 :
655
            // Silence
656
            // Not implimented.
657
            ptr += blocklength;
658
            break;
659
660
         case 4 :
661
            // Marker
662
            // Not implimented.
663
            ptr += blocklength;
664
            break;
665
666
         case 5 :
667
            // ASCII string
668
            // Not implimented.
669
            ptr += blocklength;
670
            break;
671
672
         case 6 :
673
            // Repeat begin
674
            if ( voice->LoopEnd == NULL )
675
               {
676
               voice->LoopCount = get_le16(ptr);
677
               voice->LoopStart = ptr + blocklength;
678
               }
679
            ptr += blocklength;
680
            break;
681
682
         case 7 :
683
            // Repeat end
684
            ptr += blocklength;
685
            if ( lastblocktype == 6 )
686
               {
687
               voice->LoopCount = 0;
688
               }
689
            else
690
               {
691
               if ( ( voice->LoopCount > 0 ) && ( voice->LoopStart != NULL ) )
692
                  {
693
                  ptr = voice->LoopStart;
694
                  if ( voice->LoopCount < 0xffff )
695
                     {
696
                     voice->LoopCount--;
697
                     if ( voice->LoopCount == 0 )
698
                        {
699
                        voice->LoopStart = NULL;
700
                        }
701
                     }
702
                  }
703
               }
704
            break;
705
706
         case 8 :
707
            // Extended block
708
            voice->bits  = 8;
709
            tc = get_le16(ptr);
710
            packtype = *( ptr + 2 );
711
            voicemode = *( ptr + 3 );
712
            ptr += blocklength;
713
            break;
714
715
         case 9 :
716
            // New sound data block
717
            samplespeed = get_le32(ptr);
718
            BitsPerSample = ptr[4];
719
            Channels = ptr[5];
720
            Format = get_le16(ptr+6);
721
722
            if ( ( BitsPerSample == 8 ) && ( Channels == 1 ) &&
723
               ( Format == VOC_8BIT ) )
724
               {
725
               ptr         += 12;
726
               blocklength -= 12;
727
               voice->bits  = 8;
728
               done         = TRUE;
729
               }
730
            else if ( ( BitsPerSample == 16 ) && ( Channels == 1 ) &&
731
               ( Format == VOC_16BIT ) )
732
               {
733
               ptr         += 12;
734
               blocklength -= 12;
735
               voice->bits  = 16;
736
               done         = TRUE;
737
               }
738
            else
739
               {
740
               ptr += blocklength;
741
               }
742
            break;
743
744
         default :
745
            // Unknown data.  Probably not a VOC file.
746
            voice->Playing = FALSE;
747
            done = TRUE;
748
            break;
749
         }
750
751
      lastblocktype = blocktype;
752
      }
753
754
   if ( voice->Playing )
755
      {
756
      voice->NextBlock    = ptr + blocklength;
757
      voice->sound        = ptr;
758
759
      voice->SamplingRate = samplespeed;
760
      voice->RateScale    = ( voice->SamplingRate * voice->PitchScale ) / MV_MixRate;
761
762
      // Multiply by MixBufferSize - 1
763
      voice->FixedPointBufferSize = ( voice->RateScale * MixBufferSize ) -
764
         voice->RateScale;
765
766
      if ( voice->LoopEnd != NULL )
767
         {
768
         if ( blocklength > ( unsigned long )voice->LoopEnd )
769
            {
770
            blocklength = ( unsigned long )voice->LoopEnd;
771
            }
772
         else
773
            {
774
            voice->LoopEnd = ( char * )blocklength;
775
            }
776
777
         voice->LoopStart = voice->sound + ( unsigned long )voice->LoopStart;
778
         voice->LoopEnd   = voice->sound + ( unsigned long )voice->LoopEnd;
779
         voice->LoopSize  = voice->LoopEnd - voice->LoopStart;
780
         }
781
782
      if ( voice->bits == 16 )
783
         {
784
         blocklength /= 2;
785
         }
786
787
      voice->position     = 0;
788
      voice->length       = min( blocklength, 0x8000 );
789
      voice->BlockLength  = blocklength - voice->length;
790
      voice->length     <<= 16;
791
792
      MV_SetVoiceMixMode( voice );
793
794
      return( KeepPlaying );
795
      }
796
797
   return( NoMoreData );
798
   }
799
800
801
/*---------------------------------------------------------------------
802
   Function: MV_GetNextDemandFeedBlock
803
804
   Controls playback of demand fed data.
805
---------------------------------------------------------------------*/
806
807
playbackstatus MV_GetNextDemandFeedBlock
808
   (
809
   VoiceNode *voice
810
   )
811
812
   {
813
   if ( voice->BlockLength > 0 )
814
      {
815
      voice->position    -= voice->length;
816
      voice->sound       += voice->length >> 16;
817
      voice->length       = min( voice->BlockLength, 0x8000 );
818
      voice->BlockLength -= voice->length;
819
      voice->length     <<= 16;
820
821
      return( KeepPlaying );
822
      }
823
824
   if ( voice->DemandFeed == NULL )
825
      {
826
      return( NoMoreData );
827
      }
828
829
   voice->position     = 0;
830
   ( voice->DemandFeed )( &voice->sound, &voice->BlockLength );
831
   voice->length       = min( voice->BlockLength, 0x8000 );
832
   voice->BlockLength -= voice->length;
833
   voice->length     <<= 16;
834
835
   if ( ( voice->length > 0 ) && ( voice->sound != NULL ) )
836
      {
837
      return( KeepPlaying );
838
      }
839
   return( NoMoreData );
840
   }
841
842
843
/*---------------------------------------------------------------------
844
   Function: MV_GetNextRawBlock
845
846
   Controls playback of demand fed data.
847
---------------------------------------------------------------------*/
848
849
playbackstatus MV_GetNextRawBlock
850
   (
851
   VoiceNode *voice
852
   )
853
854
   {
855
   if ( voice->BlockLength <= 0 )
856
      {
857
      if ( voice->LoopStart == NULL )
858
         {
859
         voice->Playing = FALSE;
860
         return( NoMoreData );
861
         }
862
863
      voice->BlockLength = voice->LoopSize;
864
      voice->NextBlock   = voice->LoopStart;
865
      voice->length = 0;
866
      voice->position = 0;
867
      }
868
869
   voice->sound        = voice->NextBlock;
870
   voice->position    -= voice->length;
871
   voice->length       = min( voice->BlockLength, 0x8000 );
872
   voice->NextBlock   += voice->length;
873
   if ( voice->bits == 16 )
874
      {
875
      voice->NextBlock += voice->length;
876
      }
877
   voice->BlockLength -= voice->length;
878
   voice->length     <<= 16;
879
880
   return( KeepPlaying );
881
   }
882
883
884
/*---------------------------------------------------------------------
885
   Function: MV_GetNextWAVBlock
886
887
   Controls playback of demand fed data.
888
---------------------------------------------------------------------*/
889
890
playbackstatus MV_GetNextWAVBlock
891
   (
892
   VoiceNode *voice
893
   )
894
895
   {
896
   if ( voice->BlockLength <= 0 )
897
      {
898
      if ( voice->LoopStart == NULL )
899
         {
900
         voice->Playing = FALSE;
901
         return( NoMoreData );
902
         }
903
904
      voice->BlockLength = voice->LoopSize;
905
      voice->NextBlock   = voice->LoopStart;
906
      voice->length      = 0;
907
      voice->position    = 0;
908
      }
909
910
   voice->sound        = voice->NextBlock;
911
   voice->position    -= voice->length;
912
   voice->length       = min( voice->BlockLength, 0x8000 );
913
   voice->NextBlock   += voice->length;
914
   if ( voice->bits == 16 )
915
      {
916
      voice->NextBlock += voice->length;
917
      }
918
   voice->BlockLength -= voice->length;
919
   voice->length     <<= 16;
920
921
   return( KeepPlaying );
922
   }
923
924
925
/*---------------------------------------------------------------------
926
   Function: MV_ServiceRecord
927
928
   Starts recording of the waiting buffer.
929
---------------------------------------------------------------------*/
930
931
static void MV_ServiceRecord
932
   (
933
   void
934
   )
935
936
   {
937
   if ( MV_RecordFunc )
938
      {
939
      MV_RecordFunc( MV_MixBuffer[ 0 ] + MV_MixPage * MixBufferSize,
940
         MixBufferSize );
941
      }
942
943
   // Toggle which buffer we'll mix next
944
   MV_MixPage++;
945
   if ( MV_MixPage >= NumberOfBuffers )
946
      {
947
      MV_MixPage = 0;
948
      }
949
   }
950
951
952
/*---------------------------------------------------------------------
953
   Function: MV_GetVoice
954
955
   Locates the voice with the specified handle.
956
---------------------------------------------------------------------*/
957
958
VoiceNode *MV_GetVoice
959
   (
960
   int handle
961
   )
962
963
   {
964
   VoiceNode *voice;
965
   unsigned  flags;
966
967
   flags = DisableInterrupts();
968
969
   for( voice = VoiceList.next; voice != &VoiceList; voice = voice->next )
970
      {
971
      if ( handle == voice->handle )
972
         {
973
         break;
974
         }
975
      }
976
977
   RestoreInterrupts( flags );
978
979
   if ( voice == &VoiceList )
980
      {
981
      MV_SetErrorCode( MV_VoiceNotFound );
982
      
983
      // SBF - should this return null?
984
      return NULL;
985
      }
986
987
   return( voice );
988
   }
989
990
991
/*---------------------------------------------------------------------
992
   Function: MV_VoicePlaying
993
994
   Checks if the voice associated with the specified handle is
995
   playing.
996
---------------------------------------------------------------------*/
997
998
int MV_VoicePlaying
999
   (
1000
   int handle
1001
   )
1002
1003
   {
1004
   VoiceNode *voice;
1005
1006
   if ( !MV_Installed )
1007
      {
1008
      MV_SetErrorCode( MV_NotInstalled );
1009
      return( FALSE );
1010
      }
1011
1012
   voice = MV_GetVoice( handle );
1013
1014
   if ( voice == NULL )
1015
      {
1016
      return( FALSE );
1017
      }
1018
1019
   return( TRUE );
1020
   }
1021
1022
1023
/*---------------------------------------------------------------------
1024
   Function: MV_KillAllVoices
1025
1026
   Stops output of all currently active voices.
1027
---------------------------------------------------------------------*/
1028
1029
int MV_KillAllVoices
1030
   (
1031
   void
1032
   )
1033
1034
   {
1035
   if ( !MV_Installed )
1036
      {
1037
      MV_SetErrorCode( MV_NotInstalled );
1038
      return( MV_Error );
1039
      }
1040
1041
   // Remove all the voices from the list
1042
   while( VoiceList.next != &VoiceList )
1043
      {
1044
      MV_Kill( VoiceList.next->handle );
1045
      }
1046
1047
   return( MV_Ok );
1048
   }
1049
1050
1051
/*---------------------------------------------------------------------
1052
   Function: MV_Kill
1053
1054
   Stops output of the voice associated with the specified handle.
1055
---------------------------------------------------------------------*/
1056
1057
int MV_Kill
1058
   (
1059
   int handle
1060
   )
1061
1062
   {
1063
   VoiceNode *voice;
1064
   unsigned  flags;
1065
   unsigned  long callbackval;
1066
1067
   if ( !MV_Installed )
1068
      {
1069
      MV_SetErrorCode( MV_NotInstalled );
1070
      return( MV_Error );
1071
      }
1072
1073
   flags = DisableInterrupts();
1074
1075
   voice = MV_GetVoice( handle );
1076
   if ( voice == NULL )
1077
      {
1078
      RestoreInterrupts( flags );
1079
      MV_SetErrorCode( MV_VoiceNotFound );
1080
      return( MV_Error );
1081
      }
1082
1083
   callbackval = voice->callbackval;
1084
1085
   MV_StopVoice( voice );
1086
1087
   RestoreInterrupts( flags );
1088
1089
   if ( MV_CallBackFunc )
1090
      {
1091
      MV_CallBackFunc( callbackval );
1092
      }
1093
1094
   return( MV_Ok );
1095
   }
1096
1097
1098
/*---------------------------------------------------------------------
1099
   Function: MV_VoicesPlaying
1100
1101
   Determines the number of currently active voices.
1102
---------------------------------------------------------------------*/
1103
1104
int MV_VoicesPlaying
1105
   (
1106
   void
1107
   )
1108
1109
   {
1110
   VoiceNode   *voice;
1111
   int         NumVoices = 0;
1112
   unsigned    flags;
1113
1114
   if ( !MV_Installed )
1115
      {
1116
      MV_SetErrorCode( MV_NotInstalled );
1117
      return( 0 );
1118
      }
1119
1120
   flags = DisableInterrupts();
1121
1122
   for( voice = VoiceList.next; voice != &VoiceList; voice = voice->next )
1123
      {
1124
      NumVoices++;
1125
      }
1126
1127
   RestoreInterrupts( flags );
1128
1129
   return( NumVoices );
1130
   }
1131
1132
1133
/*---------------------------------------------------------------------
1134
   Function: MV_AllocVoice
1135
1136
   Retrieve an inactive or lower priority voice for output.
1137
---------------------------------------------------------------------*/
1138
1139
VoiceNode *MV_AllocVoice
1140
   (
1141
   int priority
1142
   )
1143
1144
   {
1145
   VoiceNode   *voice;
1146
   VoiceNode   *node;
1147
   unsigned    flags;
1148
1149
//return( NULL );
1150
   if ( MV_Recording )
1151
      {
1152
      return( NULL );
1153
      }
1154
1155
   flags = DisableInterrupts();
1156
1157
   // Check if we have any free voices
1158
   if ( LL_Empty( &VoicePool, next, prev ) )
1159
      {
1160
      // check if we have a higher priority than a voice that is playing.
1161
      voice = VoiceList.next;
1162
      for( node = voice->next; node != &VoiceList; node = node->next )
1163
         {
1164
         if ( node->priority < voice->priority )
1165
            {
1166
            voice = node;
1167
            }
1168
         }
1169
1170
      if ( priority >= voice->priority )
1171
         {
1172
         MV_Kill( voice->handle );
1173
         }
1174
      }
1175
1176
   // Check if any voices are in the voice pool
1177
   if ( LL_Empty( &VoicePool, next, prev ) )
1178
      {
1179
      // No free voices
1180
      RestoreInterrupts( flags );
1181
      return( NULL );
1182
      }
1183
1184
   voice = VoicePool.next;
1185
   LL_Remove( voice, next, prev );
1186
   RestoreInterrupts( flags );
1187
1188
   // Find a free voice handle
1189
   do
1190
      {
1191
      MV_VoiceHandle++;
1192
      if ( MV_VoiceHandle < MV_MinVoiceHandle )
1193
         {
1194
         MV_VoiceHandle = MV_MinVoiceHandle;
1195
         }
1196
      }
1197
   while( MV_VoicePlaying( MV_VoiceHandle ) );
1198
1199
   voice->handle = MV_VoiceHandle;
1200
1201
   return( voice );
1202
   }
1203
1204
1205
/*---------------------------------------------------------------------
1206
   Function: MV_VoiceAvailable
1207
1208
   Checks if a voice can be play at the specified priority.
1209
---------------------------------------------------------------------*/
1210
1211
int MV_VoiceAvailable
1212
   (
1213
   int priority
1214
   )
1215
1216
   {
1217
   VoiceNode   *voice;
1218
   VoiceNode   *node;
1219
   unsigned    flags;
1220
1221
   // Check if we have any free voices
1222
   if ( !LL_Empty( &VoicePool, next, prev ) )
1223
      {
1224
      return( TRUE );
1225
      }
1226
1227
   flags = DisableInterrupts();
1228
1229
   // check if we have a higher priority than a voice that is playing.
1230
   voice = VoiceList.next;
1231
   for( node = VoiceList.next; node != &VoiceList; node = node->next )
1232
      {
1233
      if ( node->priority < voice->priority )
1234
         {
1235
         voice = node;
1236
         }
1237
      }
1238
1239
   RestoreInterrupts( flags );
1240
1241
   if ( ( voice != &VoiceList ) && ( priority >= voice->priority ) )
1242
      {
1243
      return( TRUE );
1244
      }
1245
1246
   return( FALSE );
1247
   }
1248
1249
1250
/*---------------------------------------------------------------------
1251
   Function: MV_SetVoicePitch
1252
1253
   Sets the pitch for the specified voice.
1254
---------------------------------------------------------------------*/
1255
1256
void MV_SetVoicePitch
1257
   (
1258
   VoiceNode *voice,
1259
   unsigned long rate,
1260
   int pitchoffset
1261
   )
1262
1263
   {
1264
   voice->SamplingRate = rate;
1265
   voice->PitchScale   = PITCH_GetScale( pitchoffset );
1266
   voice->RateScale    = ( rate * voice->PitchScale ) / MV_MixRate;
1267
1268
   // Multiply by MixBufferSize - 1
1269
   voice->FixedPointBufferSize = ( voice->RateScale * MixBufferSize ) -
1270
      voice->RateScale;
1271
   }
1272
1273
1274
/*---------------------------------------------------------------------
1275
   Function: MV_SetPitch
1276
1277
   Sets the pitch for the voice associated with the specified handle.
1278
---------------------------------------------------------------------*/
1279
1280
int MV_SetPitch
1281
   (
1282
   int handle,
1283
   int pitchoffset
1284
   )
1285
1286
   {
1287
   VoiceNode *voice;
1288
1289
   if ( !MV_Installed )
1290
      {
1291
      MV_SetErrorCode( MV_NotInstalled );
1292
      return( MV_Error );
1293
      }
1294
1295
   voice = MV_GetVoice( handle );
1296
   if ( voice == NULL )
1297
      {
1298
      MV_SetErrorCode( MV_VoiceNotFound );
1299
      return( MV_Error );
1300
      }
1301
1302
   MV_SetVoicePitch( voice, voice->SamplingRate, pitchoffset );
1303
1304
   return( MV_Ok );
1305
   }
1306
1307
1308
/*---------------------------------------------------------------------
1309
   Function: MV_SetFrequency
1310
1311
   Sets the frequency for the voice associated with the specified handle.
1312
---------------------------------------------------------------------*/
1313
1314
int MV_SetFrequency
1315
   (
1316
   int handle,
1317
   int frequency
1318
   )
1319
1320
   {
1321
   VoiceNode *voice;
1322
1323
   if ( !MV_Installed )
1324
      {
1325
      MV_SetErrorCode( MV_NotInstalled );
1326
      return( MV_Error );
1327
      }
1328
1329
   voice = MV_GetVoice( handle );
1330
   if ( voice == NULL )
1331
      {
1332
      MV_SetErrorCode( MV_VoiceNotFound );
1333
      return( MV_Error );
1334
      }
1335
1336
   MV_SetVoicePitch( voice, frequency, 0 );
1337
1338
   return( MV_Ok );
1339
   }
1340
1341
1342
/*---------------------------------------------------------------------
1343
   Function: MV_GetVolumeTable
1344
1345
   Returns a pointer to the volume table associated with the specified
1346
   volume.
1347
---------------------------------------------------------------------*/
1348
1349
static short *MV_GetVolumeTable
1350
   (
1351
   int vol
1352
   )
1353
1354
   {
1355
   int volume;
1356
   short *table;
1357
1358
   volume = MIX_VOLUME( vol );
1359
1360
   table = (short *)&MV_VolumeTable[ volume ];
1361
1362
   return( table );
1363
   }
1364
1365
1366
/*---------------------------------------------------------------------
1367
   Function: MV_SetVoiceMixMode
1368
1369
   Selects which method should be used to mix the voice.
1370
---------------------------------------------------------------------*/
1371
1372
static void MV_SetVoiceMixMode
1373
   (
1374
   VoiceNode *voice
1375
   )
1376
1377
   {
1378
   unsigned flags;
1379
   int test;
1380
1381
   flags = DisableInterrupts();
1382
1383
   test = T_DEFAULT;
1384
   if ( MV_Bits == 8 )
1385
      {
1386
      test |= T_8BITS;
1387
      }
1388
1389
   if ( voice->bits == 16 )
1390
      {
1391
      test |= T_16BITSOURCE;
1392
      }
1393
1394
   if ( MV_Channels == 1 )
1395
      {
1396
      test |= T_MONO;
1397
      }
1398
   else
1399
      {
1400
      if ( IS_QUIET( voice->RightVolume ) )
1401
         {
1402
         test |= T_RIGHTQUIET;
1403
         }
1404
      else if ( IS_QUIET( voice->LeftVolume ) )
1405
         {
1406
         test |= T_LEFTQUIET;
1407
         }
1408
      }
1409
1410
   // Default case
1411
   voice->mix = MV_Mix8BitMono;
1412
1413
   switch( test )
1414
      {
1415
      case T_8BITS | T_MONO | T_16BITSOURCE :
1416
         voice->mix = MV_Mix8BitMono16;
1417
         break;
1418
1419
      case T_8BITS | T_MONO :
1420
         voice->mix = MV_Mix8BitMono;
1421
         break;
1422
1423
      case T_8BITS | T_16BITSOURCE | T_LEFTQUIET :
1424
         MV_LeftVolume = MV_RightVolume;
1425
         voice->mix = MV_Mix8BitMono16;
1426
         break;
1427
1428
      case T_8BITS | T_LEFTQUIET :
1429
         MV_LeftVolume = MV_RightVolume;
1430
         voice->mix = MV_Mix8BitMono;
1431
         break;
1432
1433
      case T_8BITS | T_16BITSOURCE | T_RIGHTQUIET :
1434
         voice->mix = MV_Mix8BitMono16;
1435
         break;
1436
1437
      case T_8BITS | T_RIGHTQUIET :
1438
         voice->mix = MV_Mix8BitMono;
1439
         break;
1440
1441
      case T_8BITS | T_16BITSOURCE :
1442
         voice->mix = MV_Mix8BitStereo16;
1443
         break;
1444
1445
      case T_8BITS :
1446
         voice->mix = MV_Mix8BitStereo;
1447
         break;
1448
1449
      case T_MONO | T_16BITSOURCE :
1450
         voice->mix = MV_Mix16BitMono16;
1451
         break;
1452
1453
      case T_MONO :
1454
         voice->mix = MV_Mix16BitMono;
1455
         break;
1456
1457
      case T_16BITSOURCE | T_LEFTQUIET :
1458
         MV_LeftVolume = MV_RightVolume;
1459
         voice->mix = MV_Mix16BitMono16;
1460
         break;
1461
1462
      case T_LEFTQUIET :
1463
         MV_LeftVolume = MV_RightVolume;
1464
         voice->mix = MV_Mix16BitMono;
1465
         break;
1466
1467
      case T_16BITSOURCE | T_RIGHTQUIET :
1468
         voice->mix = MV_Mix16BitMono16;
1469
         break;
1470
1471
      case T_RIGHTQUIET :
1472
         voice->mix = MV_Mix16BitMono;
1473
         break;
1474
1475
      case T_16BITSOURCE :
1476
         voice->mix = MV_Mix16BitStereo16;
1477
         break;
1478
1479
      case T_SIXTEENBIT_STEREO :
1480
         voice->mix = MV_Mix16BitStereo;
1481
         break;
1482
1483
      default :
1484
         voice->mix = MV_Mix8BitMono;
1485
      }
1486
1487
   RestoreInterrupts( flags );
1488
   }
1489
1490
1491
/*---------------------------------------------------------------------
1492
   Function: MV_SetVoiceVolume
1493
1494
   Sets the stereo and mono volume level of the voice associated
1495
   with the specified handle.
1496
---------------------------------------------------------------------*/
1497
1498
void MV_SetVoiceVolume
1499
   (
1500
   VoiceNode *voice,
1501
   int vol,
1502
   int left,
1503
   int right
1504
   )
1505
1506
   {
1507
   if ( MV_Channels == 1 )
1508
      {
1509
      left  = vol;
1510
      right = vol;
1511
      }
1512
1513
   if ( MV_SwapLeftRight )
1514
      {
1515
      // SBPro uses reversed panning
1516
      voice->LeftVolume  = MV_GetVolumeTable( right );
1517
      voice->RightVolume = MV_GetVolumeTable( left );
1518
      }
1519
   else
1520
      {
1521
      voice->LeftVolume  = MV_GetVolumeTable( left );
1522
      voice->RightVolume = MV_GetVolumeTable( right );
1523
      }
1524
1525
   MV_SetVoiceMixMode( voice );
1526
   }
1527
1528
1529
/*---------------------------------------------------------------------
1530
   Function: MV_EndLooping
1531
1532
   Stops the voice associated with the specified handle from looping
1533
   without stoping the sound.
1534
---------------------------------------------------------------------*/
1535
1536
int MV_EndLooping
1537
   (
1538
   int handle
1539
   )
1540
1541
   {
1542
   VoiceNode *voice;
1543
   unsigned flags;
1544
1545
   if ( !MV_Installed )
1546
      {
1547
      MV_SetErrorCode( MV_NotInstalled );
1548
      return( MV_Error );
1549
      }
1550
1551
   flags = DisableInterrupts();
1552
1553
   voice = MV_GetVoice( handle );
1554
   if ( voice == NULL )
1555
      {
1556
      RestoreInterrupts( flags );
1557
      MV_SetErrorCode( MV_VoiceNotFound );
1558
      return( MV_Warning );
1559
      }
1560
1561
   voice->LoopCount = 0;
1562
   voice->LoopStart = NULL;
1563
   voice->LoopEnd   = NULL;
1564
1565
   RestoreInterrupts( flags );
1566
1567
   return( MV_Ok );
1568
   }
1569
1570
1571
/*---------------------------------------------------------------------
1572
   Function: MV_SetPan
1573
1574
   Sets the stereo and mono volume level of the voice associated
1575
   with the specified handle.
1576
---------------------------------------------------------------------*/
1577
1578
int MV_SetPan
1579
   (
1580
   int handle,
1581
   int vol,
1582
   int left,
1583
   int right
1584
   )
1585
1586
   {
1587
   VoiceNode *voice;
1588
1589
   if ( !MV_Installed )
1590
      {
1591
      MV_SetErrorCode( MV_NotInstalled );
1592
      return( MV_Error );
1593
      }
1594
1595
   voice = MV_GetVoice( handle );
1596
   if ( voice == NULL )
1597
      {
1598
      MV_SetErrorCode( MV_VoiceNotFound );
1599
      return( MV_Warning );
1600
      }
1601
1602
   MV_SetVoiceVolume( voice, vol, left, right );
1603
1604
   return( MV_Ok );
1605
   }
1606
1607
1608
/*---------------------------------------------------------------------
1609
   Function: MV_Pan3D
1610
1611
   Set the angle and distance from the listener of the voice associated
1612
   with the specified handle.
1613
---------------------------------------------------------------------*/
1614
1615
int MV_Pan3D
1616
   (
1617
   int handle,
1618
   int angle,
1619
   int distance
1620
   )
1621
1622
   {
1623
   int left;
1624
   int right;
1625
   int mid;
1626
   int volume;
1627
   int status;
1628
1629
   if ( distance < 0 )
1630
      {
1631
      distance  = -distance;
1632
      angle    += MV_NumPanPositions / 2;
1633
      }
1634
1635
   volume = MIX_VOLUME( distance );
1636
1637
   // Ensure angle is within 0 - 31
1638
   angle &= MV_MaxPanPosition;
1639
1640
   left  = MV_PanTable[ angle ][ volume ].left;
1641
   right = MV_PanTable[ angle ][ volume ].right;
1642
   mid   = max( 0, 255 - distance );
1643
1644
   status = MV_SetPan( handle, mid, left, right );
1645
1646
   return( status );
1647
   }
1648
1649
1650
/*---------------------------------------------------------------------
1651
   Function: MV_SetReverb
1652
1653
   Sets the level of reverb to add to mix.
1654
---------------------------------------------------------------------*/
1655
1656
void MV_SetReverb
1657
   (
1658
   int reverb
1659
   )
1660
1661
   {
1662
   MV_ReverbLevel = MIX_VOLUME( reverb );
1663
   MV_ReverbTable = &MV_VolumeTable[ MV_ReverbLevel ];
1664
   }
1665
1666
1667
/*---------------------------------------------------------------------
1668
   Function: MV_SetFastReverb
1669
1670
   Sets the level of reverb to add to mix.
1671
---------------------------------------------------------------------*/
1672
1673
void MV_SetFastReverb
1674
   (
1675
   int reverb
1676
   )
1677
1678
   {
1679
   MV_ReverbLevel = max( 0, min( 16, reverb ) );
1680
   MV_ReverbTable = NULL;
1681
   }
1682
1683
1684
/*---------------------------------------------------------------------
1685
   Function: MV_GetMaxReverbDelay
1686
1687
   Returns the maximum delay time for reverb.
1688
---------------------------------------------------------------------*/
1689
1690
int MV_GetMaxReverbDelay
1691
   (
1692
   void
1693
   )
1694
1695
   {
1696
   int maxdelay;
1697
1698
   maxdelay = MixBufferSize * MV_NumberOfBuffers;
1699
1700
   return maxdelay;
1701
   }
1702
1703
1704
/*---------------------------------------------------------------------
1705
   Function: MV_GetReverbDelay
1706
1707
   Returns the current delay time for reverb.
1708
---------------------------------------------------------------------*/
1709
1710
int MV_GetReverbDelay
1711
   (
1712
   void
1713
   )
1714
1715
   {
1716
   return MV_ReverbDelay / MV_SampleSize;
1717
   }
1718
1719
1720
/*---------------------------------------------------------------------
1721
   Function: MV_SetReverbDelay
1722
1723
   Sets the delay level of reverb to add to mix.
1724
---------------------------------------------------------------------*/
1725
1726
void MV_SetReverbDelay
1727
   (
1728
   int delay
1729
   )
1730
1731
   {
1732
   int maxdelay;
1733
1734
   maxdelay = MV_GetMaxReverbDelay();
1735
   MV_ReverbDelay = max( MixBufferSize, min( delay, maxdelay ) );
1736
   MV_ReverbDelay *= MV_SampleSize;
1737
   }
1738
1739
1740
/*---------------------------------------------------------------------
1741
   Function: MV_SetMixMode
1742
1743
   Prepares Multivoc to play stereo of mono digitized sounds.
1744
---------------------------------------------------------------------*/
1745
1746
int MV_SetMixMode
1747
   (
1748
   int numchannels,
1749
   int samplebits
1750
   )
1751
1752
   {
1753
   int mode;
1754
1755
   if ( !MV_Installed )
1756
      {
1757
      MV_SetErrorCode( MV_NotInstalled );
1758
      return( MV_Error );
1759
      }
1760
1761
   mode = 0;
1762
   if ( numchannels == 2 )
1763
      {
1764
      mode |= STEREO;
1765
      }
1766
   if ( samplebits == 16 )
1767
      {
1768
      mode |= SIXTEEN_BIT;
1769
      }
1770
1771
   MV_MixMode = mode;
1772
1773
   MV_Channels = 1;
1774
   if ( MV_MixMode & STEREO )
1775
      {
1776
      MV_Channels = 2;
1777
      }
1778
1779
   MV_Bits = 8;
1780
   if ( MV_MixMode & SIXTEEN_BIT )
1781
      {
1782
      MV_Bits = 16;
1783
      }
1784
1785
   MV_BuffShift  = 7 + MV_Channels;
1786
   MV_SampleSize = sizeof( MONO8 ) * MV_Channels;
1787
1788
   if ( MV_Bits == 8 )
1789
      {
1790
      MV_Silence = SILENCE_8BIT;
1791
      }
1792
   else
1793
      {
1794
      MV_Silence     = SILENCE_16BIT;
1795
      MV_BuffShift  += 1;
1796
      MV_SampleSize *= 2;
1797
      }
1798
1799
   MV_BufferSize = MixBufferSize * MV_SampleSize;
1800
   MV_NumberOfBuffers = TotalBufferSize / MV_BufferSize;
1801
   MV_BufferLength = TotalBufferSize;
1802
1803
   MV_RightChannelOffset = MV_SampleSize / 2;
1804
1805
   return( MV_Ok );
1806
   }
1807
1808
1809
/*---------------------------------------------------------------------
1810
   Function: MV_StartPlayback
1811
1812
   Starts the sound playback engine.
1813
---------------------------------------------------------------------*/
1814
1815
int MV_StartPlayback
1816
   (
1817
   void
1818
   )
1819
1820
   {
1821
   int status;
1822
   int buffer;
1823
1824
   // Initialize the buffers
1825
   ClearBuffer_DW( MV_MixBuffer[ 0 ], MV_Silence, TotalBufferSize >> 2 );
1826
   for( buffer = 0; buffer < MV_NumberOfBuffers; buffer++ )
1827
      {
1828
      MV_BufferEmpty[ buffer ] = TRUE;
1829
      }
1830
1831
   // Set the mix buffer variables
1832
   MV_MixPage = 1;
1833
1834
   MV_MixFunction = MV_Mix;
1835
1836
    status = DSL_BeginBufferedPlayback( MV_MixBuffer[ 0 ],
1837
            TotalBufferSize, MV_NumberOfBuffers,
1838
            MV_RequestedMixRate, MV_MixMode, MV_ServiceVoc );
1839
1840
    if ( status != DSL_Ok )
1841
       {
1842
       MV_SetErrorCode( MV_BlasterError );
1843
       return( MV_Error );
1844
       }
1845
1846
    MV_MixRate = DSL_GetPlaybackRate();
1847
1848
   return( MV_Ok );
1849
   }
1850
1851
1852
/*---------------------------------------------------------------------
1853
   Function: MV_StopPlayback
1854
1855
   Stops the sound playback engine.
1856
---------------------------------------------------------------------*/
1857
1858
void MV_StopPlayback
1859
   (
1860
   void
1861
   )
1862
1863
   {
1864
   VoiceNode   *voice;
1865
   VoiceNode   *next;
1866
   unsigned    flags;
1867
1868
   DSL_StopPlayback();
1869
1870
   // Make sure all callbacks are done.
1871
   flags = DisableInterrupts();
1872
1873
   for( voice = VoiceList.next; voice != &VoiceList; voice = next )
1874
      {
1875
      next = voice->next;
1876
1877
      MV_StopVoice( voice );
1878
1879
      if ( MV_CallBackFunc )
1880
         {
1881
         MV_CallBackFunc( voice->callbackval );
1882
         }
1883
      }
1884
1885
   RestoreInterrupts( flags );
1886
   }
1887
1888
1889
/*---------------------------------------------------------------------
1890
   Function: MV_StartRecording
1891
1892
   Starts the sound recording engine.
1893
---------------------------------------------------------------------*/
1894
1895
int MV_StartRecording
1896
   (
1897
   int MixRate,
1898
   void ( *function )( char *ptr, int length )
1899
   )
1900
1901
   {
1902
   MV_SetErrorCode( MV_UnsupportedCard );
1903
   return( MV_Error );
1904
   }
1905
1906
1907
/*---------------------------------------------------------------------
1908
   Function: MV_StopRecord
1909
1910
   Stops the sound record engine.
1911
---------------------------------------------------------------------*/
1912
1913
void MV_StopRecord
1914
   (
1915
   void
1916
   )
1917
1918
   {
1919
   }
1920
1921
1922
/*---------------------------------------------------------------------
1923
   Function: MV_StartDemandFeedPlayback
1924
1925
   Plays a digitized sound from a user controlled buffering system.
1926
---------------------------------------------------------------------*/
1927
1928
int MV_StartDemandFeedPlayback
1929
   (
1930
   void ( *function )( char **ptr, unsigned long *length ),
1931
   int rate,
1932
   int pitchoffset,
1933
   int vol,
1934
   int left,
1935
   int right,
1936
   int priority,
1937
   unsigned long callbackval
1938
   )
1939
1940
   {
1941
   VoiceNode *voice;
1942
1943
   if ( !MV_Installed )
1944
      {
1945
      MV_SetErrorCode( MV_NotInstalled );
1946
      return( MV_Error );
1947
      }
1948
1949
   // Request a voice from the voice pool
1950
   voice = MV_AllocVoice( priority );
1951
   if ( voice == NULL )
1952
      {
1953
      MV_SetErrorCode( MV_NoVoices );
1954
      return( MV_Error );
1955
      }
1956
1957
   voice->wavetype    = DemandFeed;
1958
   voice->bits        = 8;
1959
   voice->GetSound    = MV_GetNextDemandFeedBlock;
1960
   voice->NextBlock   = NULL;
1961
   voice->DemandFeed  = function;
1962
   voice->LoopStart   = NULL;
1963
   voice->LoopCount   = 0;
1964
   voice->BlockLength = 0;
1965
   voice->position    = 0;
1966
   voice->sound       = NULL;
1967
   voice->length      = 0;
1968
   voice->BlockLength = 0;
1969
   voice->Playing     = TRUE;
1970
   voice->next        = NULL;
1971
   voice->prev        = NULL;
1972
   voice->priority    = priority;
1973
   voice->callbackval = callbackval;
1974
1975
   MV_SetVoicePitch( voice, rate, pitchoffset );
1976
   MV_SetVoiceVolume( voice, vol, left, right );
1977
   MV_PlayVoice( voice );
1978
1979
   return( voice->handle );
1980
   }
1981
1982
1983
/*---------------------------------------------------------------------
1984
   Function: MV_PlayRaw
1985
1986
   Begin playback of sound data with the given sound levels and
1987
   priority.
1988
---------------------------------------------------------------------*/
1989
1990
int MV_PlayRaw
1991
   (
1992
   char *ptr,
1993
   unsigned long length,
1994
   unsigned rate,
1995
   int   pitchoffset,
1996
   int   vol,
1997
   int   left,
1998
   int   right,
1999
   int   priority,
2000
   unsigned long callbackval
2001
   )
2002
2003
   {
2004
   int status;
2005
2006
   status = MV_PlayLoopedRaw( ptr, length, NULL, NULL, rate, pitchoffset,
2007
      vol, left, right, priority, callbackval );
2008
2009
   return( status );
2010
   }
2011
2012
2013
/*---------------------------------------------------------------------
2014
   Function: MV_PlayLoopedRaw
2015
2016
   Begin playback of sound data with the given sound levels and
2017
   priority.
2018
---------------------------------------------------------------------*/
2019
2020
int MV_PlayLoopedRaw
2021
   (
2022
   char *ptr,
2023
   long length,
2024
   char *loopstart,
2025
   char *loopend,
2026
   unsigned rate,
2027
   int   pitchoffset,
2028
   int   vol,
2029
   int   left,
2030
   int   right,
2031
   int   priority,
2032
   unsigned long callbackval
2033
   )
2034
2035
   {
2036
   VoiceNode *voice;
2037
2038
   if ( !MV_Installed )
2039
      {
2040
      MV_SetErrorCode( MV_NotInstalled );
2041
      return( MV_Error );
2042
      }
2043
2044
   // Request a voice from the voice pool
2045
   voice = MV_AllocVoice( priority );
2046
   if ( voice == NULL )
2047
      {
2048
      MV_SetErrorCode( MV_NoVoices );
2049
      return( MV_Error );
2050
      }
2051
2052
   voice->wavetype    = Raw;
2053
   voice->bits        = 8;
2054
   voice->GetSound    = MV_GetNextRawBlock;
2055
   voice->Playing     = TRUE;
2056
   voice->NextBlock   = ptr;
2057
   voice->position    = 0;
2058
   voice->BlockLength = length;
2059
   voice->length      = 0;
2060
   voice->next        = NULL;
2061
   voice->prev        = NULL;
2062
   voice->priority    = priority;
2063
   voice->callbackval = callbackval;
2064
   voice->LoopStart   = loopstart;
2065
   voice->LoopEnd     = loopend;
2066
   voice->LoopSize    = ( voice->LoopEnd - voice->LoopStart ) + 1;
2067
2068
   MV_SetVoicePitch( voice, rate, pitchoffset );
2069
   MV_SetVoiceVolume( voice, vol, left, right );
2070
   MV_PlayVoice( voice );
2071
2072
   return( voice->handle );
2073
   }
2074
2075
2076
/*---------------------------------------------------------------------
2077
   Function: MV_PlayWAV
2078
2079
   Begin playback of sound data with the given sound levels and
2080
   priority.
2081
---------------------------------------------------------------------*/
2082
2083
int MV_PlayWAV
2084
   (
2085
   char *ptr,
2086
   int   pitchoffset,
2087
   int   vol,
2088
   int   left,
2089
   int   right,
2090
   int   priority,
2091
   unsigned long callbackval
2092
   )
2093
2094
   {
2095
   int status;
2096
2097
   status = MV_PlayLoopedWAV( ptr, -1, -1, pitchoffset, vol, left, right,
2098
      priority, callbackval );
2099
2100
   return( status );
2101
   }
2102
2103
2104
/*---------------------------------------------------------------------
2105
   Function: MV_PlayWAV3D
2106
2107
   Begin playback of sound data at specified angle and distance
2108
   from listener.
2109
---------------------------------------------------------------------*/
2110
2111
int MV_PlayWAV3D
2112
   (
2113
   char *ptr,
2114
   int  pitchoffset,
2115
   int  angle,
2116
   int  distance,
2117
   int  priority,
2118
   unsigned long callbackval
2119
   )
2120
2121
   {
2122
   int left;
2123
   int right;
2124
   int mid;
2125
   int volume;
2126
   int status;
2127
2128
   if ( !MV_Installed )
2129
      {
2130
      MV_SetErrorCode( MV_NotInstalled );
2131
      return( MV_Error );
2132
      }
2133
2134
   if ( distance < 0 )
2135
      {
2136
      distance  = -distance;
2137
      angle    += MV_NumPanPositions / 2;
2138
      }
2139
2140
   volume = MIX_VOLUME( distance );
2141
2142
   // Ensure angle is within 0 - 31
2143
   angle &= MV_MaxPanPosition;
2144
2145
   left  = MV_PanTable[ angle ][ volume ].left;
2146
   right = MV_PanTable[ angle ][ volume ].right;
2147
   mid   = max( 0, 255 - distance );
2148
2149
   status = MV_PlayWAV( ptr, pitchoffset, mid, left, right, priority,
2150
      callbackval );
2151
2152
   return( status );
2153
   }
2154
2155
2156
/*---------------------------------------------------------------------
2157
   Function: MV_PlayLoopedWAV
2158
2159
   Begin playback of sound data with the given sound levels and
2160
   priority.
2161
---------------------------------------------------------------------*/
2162
2163
int MV_PlayLoopedWAV
2164
   (
2165
   char *ptr,
2166
   long  loopstart,
2167
   long  loopend,
2168
   int   pitchoffset,
2169
   int   vol,
2170
   int   left,
2171
   int   right,
2172
   int   priority,
2173
   unsigned long callbackval
2174
   )
2175
2176
   {
2177
   riff_header   *riff;
2178
   format_header *format;
2179
   data_header   *data;
2180
   VoiceNode     *voice;
2181
   int length;
2182
   int absloopend;
2183
   int absloopstart;
2184
2185
   if ( !MV_Installed )
2186
      {
2187
      MV_SetErrorCode( MV_NotInstalled );
2188
      return( MV_Error );
2189
      }
2190
2191
   riff = ( riff_header * )ptr;
2192
2193
   if ( ( strncmp( riff->RIFF, "RIFF", 4 ) != 0 ) ||
2194
      ( strncmp( riff->WAVE, "WAVE", 4 ) != 0 ) ||
2195
      ( strncmp( riff->fmt, "fmt ", 4) != 0 ) )
2196
      {
2197
      MV_SetErrorCode( MV_InvalidWAVFile );
2198
      return( MV_Error );
2199
      }
2200
2201
   format = ( format_header * )( riff + 1 );
2202
   data   = ( data_header * )( ( ( char * )format ) + riff->format_size );
2203
2204
   // Check if it's PCM data.
2205
   if ( format->wFormatTag != 1 )
2206
      {
2207
      MV_SetErrorCode( MV_InvalidWAVFile );
2208
      return( MV_Error );
2209
      }
2210
2211
   if ( format->nChannels != 1 )
2212
      {
2213
      MV_SetErrorCode( MV_InvalidWAVFile );
2214
      return( MV_Error );
2215
      }
2216
2217
   if ( ( format->nBitsPerSample != 8 ) &&
2218
      ( format->nBitsPerSample != 16 ) )
2219
      {
2220
      MV_SetErrorCode( MV_InvalidWAVFile );
2221
      return( MV_Error );
2222
      }
2223
2224
   if ( strncmp( data->DATA, "data", 4 ) != 0 )
2225
      {
2226
      MV_SetErrorCode( MV_InvalidWAVFile );
2227
      return( MV_Error );
2228
      }
2229
2230
   // Request a voice from the voice pool
2231
   voice = MV_AllocVoice( priority );
2232
   if ( voice == NULL )
2233
      {
2234
      MV_SetErrorCode( MV_NoVoices );
2235
      return( MV_Error );
2236
      }
2237
2238
   voice->wavetype    = WAV;
2239
   voice->bits        = format->nBitsPerSample;
2240
   voice->GetSound    = MV_GetNextWAVBlock;
2241
2242
   length = data->size;
2243
   absloopstart = loopstart;
2244
   absloopend   = loopend;
2245
   if ( voice->bits == 16 )
2246
      {
2247
      loopstart  *= 2;
2248
      data->size &= ~1;
2249
      loopend    *= 2;
2250
      length     /= 2;
2251
      }
2252
2253
   loopend    = min( loopend, (long)data->size );
2254
   absloopend = min( absloopend, length );
2255
2256
   voice->Playing     = TRUE;
2257
   voice->DemandFeed  = NULL;
2258
   voice->LoopStart   = NULL;
2259
   voice->LoopCount   = 0;
2260
   voice->position    = 0;
2261
   voice->length      = 0;
2262
   voice->BlockLength = absloopend;
2263
   voice->NextBlock   = ( char * )( data + 1 );
2264
   voice->next        = NULL;
2265
   voice->prev        = NULL;
2266
   voice->priority    = priority;
2267
   voice->callbackval = callbackval;
2268
   voice->LoopStart   = voice->NextBlock + loopstart;
2269
   voice->LoopEnd     = voice->NextBlock + loopend;
2270
   voice->LoopSize    = absloopend - absloopstart;
2271
2272
   if ( ( loopstart >= (long)data->size ) || ( loopstart < 0 ) )
2273
      {
2274
      voice->LoopStart = NULL;
2275
      voice->LoopEnd   = NULL;
2276
      voice->BlockLength = length;
2277
      }
2278
2279
   MV_SetVoicePitch( voice, format->nSamplesPerSec, pitchoffset );
2280
   MV_SetVoiceVolume( voice, vol, left, right );
2281
   MV_PlayVoice( voice );
2282
2283
   return( voice->handle );
2284
   }
2285
2286
2287
/*---------------------------------------------------------------------
2288
   Function: MV_PlayVOC3D
2289
2290
   Begin playback of sound data at specified angle and distance
2291
   from listener.
2292
---------------------------------------------------------------------*/
2293
2294
int MV_PlayVOC3D
2295
   (
2296
   char *ptr,
2297
   int  pitchoffset,
2298
   int  angle,
2299
   int  distance,
2300
   int  priority,
2301
   unsigned long callbackval
2302
   )
2303
2304
   {
2305
   int left;
2306
   int right;
2307
   int mid;
2308
   int volume;
2309
   int status;
2310
2311
   if ( !MV_Installed )
2312
      {
2313
      MV_SetErrorCode( MV_NotInstalled );
2314
      return( MV_Error );
2315
      }
2316
2317
   if ( distance < 0 )
2318
      {
2319
      distance  = -distance;
2320
      angle    += MV_NumPanPositions / 2;
2321
      }
2322
2323
   volume = MIX_VOLUME( distance );
2324
2325
   // Ensure angle is within 0 - 31
2326
   angle &= MV_MaxPanPosition;
2327
2328
   left  = MV_PanTable[ angle ][ volume ].left;
2329
   right = MV_PanTable[ angle ][ volume ].right;
2330
   mid   = max( 0, 255 - distance );
2331
2332
   status = MV_PlayVOC( ptr, pitchoffset, mid, left, right, priority,
2333
      callbackval );
2334
2335
   return( status );
2336
   }
2337
2338
2339
/*---------------------------------------------------------------------
2340
   Function: MV_PlayVOC
2341
2342
   Begin playback of sound data with the given sound levels and
2343
   priority.
2344
---------------------------------------------------------------------*/
2345
2346
int MV_PlayVOC
2347
   (
2348
   char *ptr,
2349
   int   pitchoffset,
2350
   int   vol,
2351
   int   left,
2352
   int   right,
2353
   int   priority,
2354
   unsigned long callbackval
2355
   )
2356
2357
   {
2358
   int status;
2359
2360
   status = MV_PlayLoopedVOC( ptr, -1, -1, pitchoffset, vol, left, right,
2361
      priority, callbackval );
2362
2363
   return( status );
2364
   }
2365
2366
2367
/*---------------------------------------------------------------------
2368
   Function: MV_PlayLoopedVOC
2369
2370
   Begin playback of sound data with the given sound levels and
2371
   priority.
2372
---------------------------------------------------------------------*/
2373
2374
int MV_PlayLoopedVOC
2375
   (
2376
   char *ptr,
2377
   long  loopstart,
2378
   long  loopend,
2379
   int   pitchoffset,
2380
   int   vol,
2381
   int   left,
2382
   int   right,
2383
   int   priority,
2384
   unsigned long callbackval
2385
   )
2386
2387
   {
2388
   VoiceNode   *voice;
2389
   int          status;
2390
   unsigned short nextpos;
2391
2392
   if ( !MV_Installed )
2393
      {
2394
      MV_SetErrorCode( MV_NotInstalled );
2395
      return( MV_Error );
2396
      }
2397
2398
   // Make sure it's a valid VOC file.
2399
   status = strncmp( ptr, "Creative Voice File", 19 );
2400
   if ( status != 0 )
2401
      {
2402
      MV_SetErrorCode( MV_InvalidVOCFile );
2403
      return( MV_Error );
2404
      }
2405
2406
   // Request a voice from the voice pool
2407
   voice = MV_AllocVoice( priority );
2408
   if ( voice == NULL )
2409
      {
2410
      MV_SetErrorCode( MV_NoVoices );
2411
      return( MV_Error );
2412
      }
2413
2414
   voice->wavetype    = VOC;
2415
   voice->bits        = 8;
2416
   voice->GetSound    = MV_GetNextVOCBlock;
2417
2418
   nextpos = *( unsigned short * )( ptr + 0x14 );
2419
   voice->NextBlock   = ptr + BUILDSWAP_INTEL16(nextpos);
2420
2421
   voice->DemandFeed  = NULL;
2422
   voice->LoopStart   = NULL;
2423
   voice->LoopCount   = 0;
2424
   voice->BlockLength = 0;
2425
   voice->PitchScale  = PITCH_GetScale( pitchoffset );
2426
   voice->length      = 0;
2427
   voice->next        = NULL;
2428
   voice->prev        = NULL;
2429
   voice->priority    = priority;
2430
   voice->callbackval = callbackval;
2431
   voice->LoopStart   = ( char * )loopstart;
2432
   voice->LoopEnd     = ( char * )loopend;
2433
   voice->LoopSize    = loopend - loopstart + 1;
2434
2435
   if ( loopstart < 0 )
2436
      {
2437
      voice->LoopStart = NULL;
2438
      voice->LoopEnd   = NULL;
2439
      }
2440
2441
   MV_SetVoiceVolume( voice, vol, left, right );
2442
   MV_PlayVoice( voice );
2443
2444
   return( voice->handle );
2445
   }
2446
2447
2448
/*---------------------------------------------------------------------
2449
   Function: MV_LockEnd
2450
2451
   Used for determining the length of the functions to lock in memory.
2452
---------------------------------------------------------------------*/
2453
2454
static void MV_LockEnd
2455
   (
2456
   void
2457
   )
2458
2459
   {
2460
   }
2461
2462
2463
/*---------------------------------------------------------------------
2464
   Function: MV_CreateVolumeTable
2465
2466
   Create the table used to convert sound data to a specific volume
2467
   level.
2468
---------------------------------------------------------------------*/
2469
2470
void MV_CreateVolumeTable
2471
   (
2472
   int index,
2473
   int volume,
2474
   int MaxVolume
2475
   )
2476
2477
   {
2478
   int val;
2479
   int level;
2480
   int i;
2481
2482
   level = ( volume * MaxVolume ) / MV_MaxTotalVolume;
2483
   if ( MV_Bits == 16 )
2484
      {
2485
      for( i = 0; i < 65536; i += 256 )
2486
         {
2487
         val   = i - 0x8000;
2488
         val  *= level;
2489
         val  /= MV_MaxVolume;
2490
         MV_VolumeTable[ index ][ i / 256 ] = val;
2491
         }
2492
      }
2493
   else
2494
      {
2495
      for( i = 0; i < 256; i++ )
2496
         {
2497
         val   = i - 0x80;
2498
         val  *= level;
2499
         val  /= MV_MaxVolume;
2500
         MV_VolumeTable[ volume ][ i ] = val;
2501
         }
2502
      }
2503
   }
2504
2505
2506
/*---------------------------------------------------------------------
2507
   Function: MV_CalcVolume
2508
2509
   Create the table used to convert sound data to a specific volume
2510
   level.
2511
---------------------------------------------------------------------*/
2512
2513
void MV_CalcVolume
2514
   (
2515
   int MaxVolume
2516
   )
2517
2518
   {
2519
   int volume;
2520
2521
   for( volume = 0; volume < 128; volume++ )
2522
      {
2523
      MV_HarshClipTable[ volume ] = 0;
2524
      MV_HarshClipTable[ volume + 384 ] = 255;
2525
      }
2526
   for( volume = 0; volume < 256; volume++ )
2527
      {
2528
      MV_HarshClipTable[ volume + 128 ] = volume;
2529
      }
2530
2531
   // For each volume level, create a translation table with the
2532
   // appropriate volume calculated.
2533
   for( volume = 0; volume <= MV_MaxVolume; volume++ )
2534
      {
2535
      MV_CreateVolumeTable( volume, volume, MaxVolume );
2536
      }
2537
   }
2538
2539
2540
/*---------------------------------------------------------------------
2541
   Function: MV_CalcPanTable
2542
2543
   Create the table used to determine the stereo volume level of
2544
   a sound located at a specific angle and distance from the listener.
2545
---------------------------------------------------------------------*/
2546
2547
void MV_CalcPanTable
2548
   (
2549
   void
2550
   )
2551
2552
   {
2553
   int   level;
2554
   int   angle;
2555
   int   distance;
2556
   int   HalfAngle;
2557
   int   ramp;
2558
2559
   HalfAngle = ( MV_NumPanPositions / 2 );
2560
2561
   for( distance = 0; distance <= MV_MaxVolume; distance++ )
2562
      {
2563
      level = ( 255 * ( MV_MaxVolume - distance ) ) / MV_MaxVolume;
2564
      for( angle = 0; angle <= HalfAngle / 2; angle++ )
2565
         {
2566
         ramp = level - ( ( level * angle ) /
2567
            ( MV_NumPanPositions / 4 ) );
2568
2569
         MV_PanTable[ angle ][ distance ].left = ramp;
2570
         MV_PanTable[ HalfAngle - angle ][ distance ].left = ramp;
2571
         MV_PanTable[ HalfAngle + angle ][ distance ].left = level;
2572
         MV_PanTable[ MV_MaxPanPosition - angle ][ distance ].left = level;
2573
2574
         MV_PanTable[ angle ][ distance ].right = level;
2575
         MV_PanTable[ HalfAngle - angle ][ distance ].right = level;
2576
         MV_PanTable[ HalfAngle + angle ][ distance ].right = ramp;
2577
         MV_PanTable[ MV_MaxPanPosition - angle ][ distance ].right = ramp;
2578
         }
2579
      }
2580
   }
2581
2582
2583
/*---------------------------------------------------------------------
2584
   Function: MV_SetVolume
2585
2586
   Sets the volume of digitized sound playback.
2587
---------------------------------------------------------------------*/
2588
2589
void MV_SetVolume
2590
   (
2591
   int volume
2592
   )
2593
2594
   {
2595
   volume = max( 0, volume );
2596
   volume = min( volume, MV_MaxTotalVolume );
2597
2598
   MV_TotalVolume = volume;
2599
2600
   // Calculate volume table
2601
   MV_CalcVolume( volume );
2602
   }
2603
2604
2605
/*---------------------------------------------------------------------
2606
   Function: MV_GetVolume
2607
2608
   Returns the volume of digitized sound playback.
2609
---------------------------------------------------------------------*/
2610
2611
int MV_GetVolume
2612
   (
2613
   void
2614
   )
2615
2616
   {
2617
   return( MV_TotalVolume );
2618
   }
2619
2620
2621
/*---------------------------------------------------------------------
2622
   Function: MV_SetCallBack
2623
2624
   Set the function to call when a voice stops.
2625
---------------------------------------------------------------------*/
2626
2627
void MV_SetCallBack
2628
   (
2629
   void ( *function )( unsigned long )
2630
   )
2631
2632
   {
2633
   MV_CallBackFunc = function;
2634
   }
2635
2636
2637
/*---------------------------------------------------------------------
2638
   Function: MV_SetReverseStereo
2639
2640
   Set the orientation of the left and right channels.
2641
---------------------------------------------------------------------*/
2642
2643
void MV_SetReverseStereo
2644
   (
2645
   int setting
2646
   )
2647
2648
   {
2649
   MV_SwapLeftRight = setting;
2650
   }
2651
2652
2653
/*---------------------------------------------------------------------
2654
   Function: MV_GetReverseStereo
2655
2656
   Returns the orientation of the left and right channels.
2657
---------------------------------------------------------------------*/
2658
2659
int MV_GetReverseStereo
2660
   (
2661
   void
2662
   )
2663
2664
   {
2665
   return( MV_SwapLeftRight );
2666
   }
2667
2668
2669
/*---------------------------------------------------------------------
2670
   Function: MV_TestPlayback
2671
2672
   Checks if playback has started.
2673
---------------------------------------------------------------------*/
2674
2675
int MV_TestPlayback(void)
2676
   {
2677
   return MV_Ok;
2678
   }
2679
2680
2681
/*---------------------------------------------------------------------
2682
   Function: MV_Init
2683
2684
   Perform the initialization of variables and memory used by
2685
   Multivoc.
2686
---------------------------------------------------------------------*/
2687
2688
int MV_Init
2689
   (
2690
   int soundcard,
2691
   int MixRate,
2692
   int Voices,
2693
   int numchannels,
2694
   int samplebits
2695
   )
2696
2697
   {
2698
   char *ptr;
2699
   int  status;
2700
   int  buffer;
2701
   int  index;
2702
2703
   if ( MV_Installed )
2704
      {
2705
      MV_Shutdown();
2706
      }
2707
2708
   MV_SetErrorCode( MV_Ok );
2709
2710
   MV_TotalMemory = Voices * sizeof( VoiceNode ) + sizeof( HARSH_CLIP_TABLE_8 );
2711
   status = USRHOOKS_GetMem( ( void ** )&ptr, MV_TotalMemory );
2712
   if ( status != USRHOOKS_Ok )
2713
      {
2714
      MV_SetErrorCode( MV_NoMem );
2715
      return( MV_Error );
2716
      }
2717
2718
   MV_Voices = ( VoiceNode * )ptr;
2719
   MV_HarshClipTable = ptr + ( MV_TotalMemory - sizeof( HARSH_CLIP_TABLE_8 ) );
2720
2721
   // Set number of voices before calculating volume table
2722
   MV_MaxVoices = Voices;
2723
2724
   LL_Reset( (VoiceNode *)&VoiceList, next, prev );
2725
   LL_Reset( (VoiceNode *)&VoicePool, next, prev );
2726
2727
   for( index = 0; index < Voices; index++ )
2728
      {
2729
      LL_Add( (VoiceNode *)&VoicePool, &MV_Voices[ index ], next, prev );
2730
      }
2731
2732
   // Allocate mix buffer within 1st megabyte
2733
   status = DPMI_GetDOSMemory( ( void ** )&ptr, &MV_BufferDescriptor,
2734
      2 * TotalBufferSize );
2735
2736
   if ( status )
2737
      {
2738
      USRHOOKS_FreeMem( MV_Voices );
2739
      MV_Voices      = NULL;
2740
      MV_TotalMemory = 0;
2741
2742
      MV_SetErrorCode( MV_NoMem );
2743
      return( MV_Error );
2744
      }
2745
2746
   MV_SetReverseStereo( FALSE );
2747
2748
   // Initialize the sound card
2749
   status = DSL_Init();
2750
   if ( status != DSL_Ok )
2751
      {
2752
      MV_SetErrorCode( MV_BlasterError );
2753
      }
2754
2755
   if ( MV_ErrorCode != MV_Ok )
2756
      {
2757
      status = MV_ErrorCode;
2758
2759
      USRHOOKS_FreeMem( MV_Voices );
2760
      MV_Voices      = NULL;
2761
      MV_TotalMemory = 0;
2762
2763
      DPMI_FreeDOSMemory( MV_BufferDescriptor );
2764
2765
      MV_SetErrorCode( status );
2766
      return( MV_Error );
2767
      }
2768
2769
   MV_SoundCard    = soundcard;
2770
   MV_Installed    = TRUE;
2771
   MV_CallBackFunc = NULL;
2772
   MV_RecordFunc   = NULL;
2773
   MV_Recording    = FALSE;
2774
   MV_ReverbLevel  = 0;
2775
   MV_ReverbTable  = NULL;
2776
2777
   // Set the sampling rate
2778
   MV_RequestedMixRate = MixRate;
2779
2780
   // Set Mixer to play stereo digitized sound
2781
   MV_SetMixMode( numchannels, samplebits );
2782
   MV_ReverbDelay = MV_BufferSize * 3;
2783
2784
   MV_MixBuffer[ MV_NumberOfBuffers ] = ptr;
2785
   for( buffer = 0; buffer < MV_NumberOfBuffers; buffer++ )
2786
      {
2787
      MV_MixBuffer[ buffer ] = ptr;
2788
      ptr += MV_BufferSize;
2789
      }
2790
2791
   // Calculate pan table
2792
   MV_CalcPanTable();
2793
2794
   MV_SetVolume( MV_MaxTotalVolume );
2795
2796
   // Start the playback engine
2797
   status = MV_StartPlayback();
2798
   if ( status != MV_Ok )
2799
      {
2800
      // Preserve error code while we shutdown.
2801
      status = MV_ErrorCode;
2802
      MV_Shutdown();
2803
      MV_SetErrorCode( status );
2804
      return( MV_Error );
2805
      }
2806
2807
   if ( MV_TestPlayback() != MV_Ok )
2808
      {
2809
      status = MV_ErrorCode;
2810
      MV_Shutdown();
2811
      MV_SetErrorCode( status );
2812
      return( MV_Error );
2813
      }
2814
2815
   return( MV_Ok );
2816
   }
2817
2818
2819
/*---------------------------------------------------------------------
2820
   Function: MV_Shutdown
2821
2822
   Restore any resources allocated by Multivoc back to the system.
2823
---------------------------------------------------------------------*/
2824
2825
int MV_Shutdown
2826
   (
2827
   void
2828
   )
2829
2830
   {
2831
   int      buffer;
2832
   unsigned flags;
2833
2834
   if ( !MV_Installed )
2835
      {
2836
      return( MV_Ok );
2837
      }
2838
2839
   flags = DisableInterrupts();
2840
2841
   MV_KillAllVoices();
2842
2843
   MV_Installed = FALSE;
2844
2845
   // Stop the sound recording engine
2846
   if ( MV_Recording )
2847
      {
2848
      MV_StopRecord();
2849
      }
2850
2851
   // Stop the sound playback engine
2852
   MV_StopPlayback();
2853
2854
   // Shutdown the sound card
2855
   DSL_Shutdown();
2856
2857
   RestoreInterrupts( flags );
2858
2859
   // Free any voices we allocated
2860
   USRHOOKS_FreeMem( MV_Voices );
2861
   MV_Voices      = NULL;
2862
   MV_TotalMemory = 0;
2863
2864
   LL_Reset( (VoiceNode *)&VoiceList, next, prev );
2865
   LL_Reset( (VoiceNode *)&VoicePool, next, prev );
2866
2867
   MV_MaxVoices = 1;
2868
2869
   // Release the descriptor from our mix buffer
2870
   DPMI_FreeDOSMemory( MV_BufferDescriptor );
2871
   for( buffer = 0; buffer < NumberOfBuffers; buffer++ )
2872
      {
2873
      MV_MixBuffer[ buffer ] = NULL;
2874
      }
2875
2876
   return( MV_Ok );
2877
   }
(-)./source/jaudiolib/util.h (+13 lines)
Line 0 Link Here
1
#ifndef AUDIOLIB__UTIL_H
2
#define AUDIOLIB__UTIL_H
3
4
#ifndef min
5
#define min(a, b)  ((a) < (b) ? (a) : (b))
6
#endif
7
8
#ifndef max
9
#define max(a, b)  ((a) > (b) ? (a) : (b))
10
#endif
11
12
#endif
13
(-)./source/sounds.c (+10 lines)
Lines 213-218 Link Here
213
213
214
void playmusic(char *fn)
214
void playmusic(char *fn)
215
{
215
{
216
#ifdef WINDOWS
216
    short      fp;
217
    short      fp;
217
    long        l;
218
    long        l;
218
219
Lines 234-239 Link Here
234
    kread( fp, MusicPtr, l);
235
    kread( fp, MusicPtr, l);
235
    kclose( fp );
236
    kclose( fp );
236
    MUSIC_PlaySong( MusicPtr, MUSIC_LoopSong );
237
    MUSIC_PlaySong( MusicPtr, MUSIC_LoopSong );
238
#else
239
    void PlayMusic(char *_filename);
240
    if(MusicToggle == 0) return;
241
    if(MusicDevice < 0) return;
242
243
     // FIXME: I need this to get the music volume initialized (not sure why) -- Jim Bentler
244
    MUSIC_SetVolume( MusicVolume );
245
    PlayMusic(fn);
246
#endif
237
}
247
}
238
248
239
char loadsound(unsigned short num)
249
char loadsound(unsigned short num)
(-)./source.diff (-1 lines)
Lines 1-4463 Link Here
1
diff -wruN source/config.c ../jfduke3d_src_20041013-linux/source/config.c

Return to bug 87685