/contrib/games/wolf3d/Makefile |
---|
3,21 → 3,64 |
SDK_DIR = $(abspath ../../sdk) |
CFLAGS = -c -fno-ident -O2 -fomit-frame-pointer -fno-ident -U__WIN32__ -U_Win32 -U_WIN32 -U__MINGW32__ -UWIN32 |
CFLAGS = -c -fno-ident -O2 -fomit-frame-pointer -fno-ident -U__WIN32__ -U_Win32 -U_WIN32 -U__MINGW32__ -UWIN32 -D_KOLIBRI |
LDFLAGS = -static -S -nostdlib -T $(SDK_DIR)/sources/newlib/app.lds --image-base 0 |
INCLUDES = -I$(SDK_DIR)/sources/newlib/libc/include -I$(SDK_DIR)/sources/SDL-1.2.2_newlib/include -I. |
INCLUDES = -I$(SDK_DIR)/sources/newlib/libc/include -I$(SDK_DIR)/sources/SDL-1.2.2_newlib/include -I. -I SDL_mixer |
LIBPATH = -L $(SDK_DIR)/lib -L /home/autobuild/tools/win32/mingw32/lib |
OBJECTS = wl_cloudsky.o wl_debug.o id_sd.o wl_play.o id_vl.o wl_act2.o wl_floorceiling.o wl_dir3dspr.o wl_state.o wl_atmos.o id_in.o signon.o wl_parallax.o wl_agent.o sdl_winmain.o wl_inter.o wl_text.o id_pm.o wl_draw.o wl_menu.o wl_game.o wl_act1.o wl_main.o wl_shade.o id_us_1.o id_vh.o id_ca.o joystick_stub.o kolibri.o |
OBJECTS += wl_cloudsky.o |
OBJECTS += wl_debug.o |
OBJECTS += id_sd.o |
OBJECTS += wl_play.o |
OBJECTS += id_vl.o |
OBJECTS += wl_act2.o |
OBJECTS += wl_floorceiling.o |
OBJECTS += wl_dir3dspr.o |
OBJECTS += wl_state.o |
OBJECTS += wl_atmos.o |
OBJECTS += id_in.o |
OBJECTS += signon.o |
OBJECTS += wl_parallax.o |
OBJECTS += wl_agent.o |
OBJECTS += sdl_winmain.o |
OBJECTS += wl_inter.o |
OBJECTS += wl_text.o |
OBJECTS += id_pm.o |
OBJECTS += wl_draw.o |
OBJECTS += wl_menu.o |
OBJECTS += wl_game.o |
OBJECTS += wl_act1.o |
OBJECTS += wl_main.o |
OBJECTS += wl_shade.o |
OBJECTS += id_us_1.o |
OBJECTS += id_vh.o |
OBJECTS += id_ca.o |
OBJECTS += joystick_stub.o |
OBJECTS += kolibri.o |
OBJECTS += mame/fmopl.o |
default: $(OBJECTS) |
kos32-ld $(LDFLAGS) $(LIBPATH) --subsystem native -o wolf3d $(OBJECTS) -lSDLn -lsound -lstdc++ -lsupc++ -lgcc -lc.dll |
objcopy wolf3d -O binary |
kpack --nologo wolf3d |
SDL_OBJ += SDL/SDL_wave.o |
SDL_OBJ += SDL/SDL_audiocvt.o |
SDL_OBJ += SDL/SDL_mixer.o |
SDL_MIX_OBJ += SDL_mixer/mixer.o |
SDL_MIX_OBJ += SDL_mixer/music.o |
SDL_MIX_OBJ += SDL_mixer/load_aiff.o |
SDL_MIX_OBJ += SDL_mixer/load_voc.o |
SDL_MIX_OBJ += SDL_mixer/effects_internal.o |
SDL_MIX_OBJ += SDL_mixer/effect_position.o |
default: $(OBJECTS) $(SDL_MIX_OBJ) $(SDL_OBJ) |
kos32-ld $(LDFLAGS) $(LIBPATH) --subsystem native -o bin/wolf3d $(OBJECTS) $(SDL_MIX_OBJ) $(SDL_OBJ) -lSDLn -lsound -lstdc++ -lsupc++ -lgcc -lc.dll |
objcopy bin/wolf3d -O binary |
kpack --nologo bin/wolf3d |
%.o : %.cpp |
$(CC) $(CFLAGS) $(INCLUDES) -o $@ $< |
%.o : %.c |
$(CC) $(CFLAGS) $(INCLUDES) -o $@ $< |
clean: |
rm *.o |
rm *.o SDL_mixer/*.o mame/*.o SDL/*.o *.d SDL_mixer/*.d mame/*.d SDL/*.d |
/contrib/games/wolf3d/Makefile.linux |
---|
0,0 → 1,126 |
CONFIG ?= config.default |
-include $(CONFIG) |
BINARY ?= bin/wolf3d |
PREFIX ?= /usr/local |
MANPREFIX ?= $(PREFIX)/share/man/ |
MANPAGE ?= man6/wolf4sdl.6 |
DATADIR ?= $(PREFIX)/share/games/wolf3d/ |
INSTALL ?= install |
INSTALL_PROGRAM ?= $(INSTALL) -m 555 -s |
INSTALL_MAN ?= $(INSTALL) -m 444 |
INSTALL_DATA ?= $(INSTALL) -m 444 |
SDL_CONFIG ?= sdl-config |
CFLAGS_SDL ?= $(shell $(SDL_CONFIG) --cflags) |
LDFLAGS_SDL ?= $(shell $(SDL_CONFIG) --libs) |
CFLAGS += $(CFLAGS_SDL) |
#CFLAGS += -Wall |
#CFLAGS += -W |
CFLAGS += -Wpointer-arith |
CFLAGS += -Wreturn-type |
CFLAGS += -Wwrite-strings |
CFLAGS += -Wcast-align |
ifdef DATADIR |
CFLAGS += -DDATADIR=\"$(DATADIR)\" |
endif |
CCFLAGS += $(CFLAGS) |
CCFLAGS += -std=gnu99 |
CCFLAGS += -Werror-implicit-function-declaration |
CCFLAGS += -Wimplicit-int |
CCFLAGS += -Wsequence-point |
CXXFLAGS += $(CFLAGS) |
LDFLAGS += $(LDFLAGS_SDL) |
SRCS := |
SRCS += mame/fmopl.cpp |
SRCS += id_ca.cpp |
SRCS += id_in.cpp |
SRCS += id_pm.cpp |
SRCS += id_sd.cpp |
SRCS += id_us_1.cpp |
SRCS += id_vh.cpp |
SRCS += id_vl.cpp |
SRCS += signon.cpp |
SRCS += wl_act1.cpp |
SRCS += wl_act2.cpp |
SRCS += wl_agent.cpp |
SRCS += wl_atmos.cpp |
SRCS += wl_cloudsky.cpp |
SRCS += wl_debug.cpp |
SRCS += wl_draw.cpp |
SRCS += wl_floorceiling.cpp |
SRCS += wl_game.cpp |
SRCS += wl_inter.cpp |
SRCS += wl_main.cpp |
SRCS += wl_menu.cpp |
SRCS += wl_parallax.cpp |
SRCS += wl_play.cpp |
SRCS += wl_state.cpp |
SRCS += wl_text.cpp |
SRCS += SDL_mixer/mixer.c |
SRCS += SDL_mixer/music.c |
SRCS += SDL_mixer/load_aiff.c |
SRCS += SDL_mixer/load_voc.c |
SRCS += SDL_mixer/effects_internal.c |
SRCS += SDL_mixer/effect_position.c |
DEPS = $(filter %.d, $(SRCS:.c=.d) $(SRCS:.cpp=.d)) |
OBJS = $(filter %.o, $(SRCS:.c=.o) $(SRCS:.cpp=.o)) |
.SUFFIXES: |
.SUFFIXES: .c .cpp .d .o |
Q ?= @ |
all: $(BINARY) |
ifndef NO_DEPS |
depend: $(DEPS) |
ifeq ($(findstring $(MAKECMDGOALS), clean depend Data),) |
-include $(DEPS) |
endif |
endif |
$(BINARY): $(OBJS) |
@echo '===> LD $@' |
$(Q)$(CXX) $(CFLAGS) $(OBJS) $(LDFLAGS) -o $@ |
.c.o: |
@echo '===> CC $<' |
$(Q)$(CC) $(CCFLAGS) -c $< -o $@ |
.cpp.o: |
@echo '===> CXX $<' |
$(Q)$(CXX) $(CXXFLAGS) -c $< -o $@ |
.c.d: |
@echo '===> DEP $<' |
$(Q)$(CC) $(CCFLAGS) -MM $< | sed 's#^$(@F:%.d=%.o):#$@ $(@:%.d=%.o):#' > $@ |
.cpp.d: |
@echo '===> DEP $<' |
$(Q)$(CXX) $(CXXFLAGS) -MM $< | sed 's#^$(@F:%.d=%.o):#$@ $(@:%.d=%.o):#' > $@ |
clean distclean: |
@echo '===> CLEAN' |
$(Q)rm -fr $(DEPS) $(OBJS) $(BINARY) |
install: $(BINARY) |
@echo '===> INSTALL' |
$(Q)$(INSTALL) -d $(PREFIX)/bin |
$(Q)$(INSTALL_PROGRAM) $(BINARY) $(PREFIX)/bin |
$(Q)$(INSTALL_MAN) $(MANPAGE) $(MANPREFIX)/man6 |
/contrib/games/wolf3d/SDL/SDL_audiocvt.c |
---|
0,0 → 1,642 |
/* |
SDL - Simple DirectMedia Layer |
Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga |
This library is free software; you can redistribute it and/or |
modify it under the terms of the GNU Library General Public |
License as published by the Free Software Foundation; either |
version 2 of the License, or (at your option) any later version. |
This library is distributed in the hope that it will be useful, |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
Library General Public License for more details. |
You should have received a copy of the GNU Library General Public |
License along with this library; if not, write to the Free |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
Sam Lantinga |
slouken@devolution.com |
*/ |
#ifdef SAVE_RCSID |
static char rcsid = |
"@(#) $Id: SDL_audiocvt.c,v 1.2 2001/04/26 16:50:17 hercules Exp $"; |
#endif |
/* Functions for audio drivers to perform runtime conversion of audio format */ |
#include <stdio.h> |
#include "SDL_error.h" |
#include "SDL_audio.h" |
/* Effectively mix right and left channels into a single channel */ |
void SDL_ConvertMono(SDL_AudioCVT *cvt, Uint16 format) |
{ |
int i; |
Sint32 sample; |
#ifdef DEBUG_CONVERT |
fprintf(stderr, "Converting to mono\n"); |
#endif |
switch (format&0x8018) { |
case AUDIO_U8: { |
Uint8 *src, *dst; |
src = cvt->buf; |
dst = cvt->buf; |
for ( i=cvt->len_cvt/2; i; --i ) { |
sample = src[0] + src[1]; |
if ( sample > 255 ) { |
*dst = 255; |
} else { |
*dst = sample; |
} |
src += 2; |
dst += 1; |
} |
} |
break; |
case AUDIO_S8: { |
Sint8 *src, *dst; |
src = (Sint8 *)cvt->buf; |
dst = (Sint8 *)cvt->buf; |
for ( i=cvt->len_cvt/2; i; --i ) { |
sample = src[0] + src[1]; |
if ( sample > 127 ) { |
*dst = 127; |
} else |
if ( sample < -128 ) { |
*dst = -128; |
} else { |
*dst = sample; |
} |
src += 2; |
dst += 1; |
} |
} |
break; |
case AUDIO_U16: { |
Uint8 *src, *dst; |
src = cvt->buf; |
dst = cvt->buf; |
if ( (format & 0x1000) == 0x1000 ) { |
for ( i=cvt->len_cvt/4; i; --i ) { |
sample = (Uint16)((src[0]<<8)|src[1])+ |
(Uint16)((src[2]<<8)|src[3]); |
if ( sample > 65535 ) { |
dst[0] = 0xFF; |
dst[1] = 0xFF; |
} else { |
dst[1] = (sample&0xFF); |
sample >>= 8; |
dst[0] = (sample&0xFF); |
} |
src += 4; |
dst += 2; |
} |
} else { |
for ( i=cvt->len_cvt/4; i; --i ) { |
sample = (Uint16)((src[1]<<8)|src[0])+ |
(Uint16)((src[3]<<8)|src[2]); |
if ( sample > 65535 ) { |
dst[0] = 0xFF; |
dst[1] = 0xFF; |
} else { |
dst[0] = (sample&0xFF); |
sample >>= 8; |
dst[1] = (sample&0xFF); |
} |
src += 4; |
dst += 2; |
} |
} |
} |
break; |
case AUDIO_S16: { |
Uint8 *src, *dst; |
src = cvt->buf; |
dst = cvt->buf; |
if ( (format & 0x1000) == 0x1000 ) { |
for ( i=cvt->len_cvt/4; i; --i ) { |
sample = (Sint16)((src[0]<<8)|src[1])+ |
(Sint16)((src[2]<<8)|src[3]); |
if ( sample > 32767 ) { |
dst[0] = 0x7F; |
dst[1] = 0xFF; |
} else |
if ( sample < -32768 ) { |
dst[0] = 0x80; |
dst[1] = 0x00; |
} else { |
dst[1] = (sample&0xFF); |
sample >>= 8; |
dst[0] = (sample&0xFF); |
} |
src += 4; |
dst += 2; |
} |
} else { |
for ( i=cvt->len_cvt/4; i; --i ) { |
sample = (Sint16)((src[1]<<8)|src[0])+ |
(Sint16)((src[3]<<8)|src[2]); |
if ( sample > 32767 ) { |
dst[1] = 0x7F; |
dst[0] = 0xFF; |
} else |
if ( sample < -32768 ) { |
dst[1] = 0x80; |
dst[0] = 0x00; |
} else { |
dst[0] = (sample&0xFF); |
sample >>= 8; |
dst[1] = (sample&0xFF); |
} |
src += 4; |
dst += 2; |
} |
} |
} |
break; |
} |
cvt->len_cvt /= 2; |
if ( cvt->filters[++cvt->filter_index] ) { |
cvt->filters[cvt->filter_index](cvt, format); |
} |
} |
/* Duplicate a mono channel to both stereo channels */ |
void SDL_ConvertStereo(SDL_AudioCVT *cvt, Uint16 format) |
{ |
int i; |
#ifdef DEBUG_CONVERT |
fprintf(stderr, "Converting to stereo\n"); |
#endif |
if ( (format & 0xFF) == 16 ) { |
Uint16 *src, *dst; |
src = (Uint16 *)(cvt->buf+cvt->len_cvt); |
dst = (Uint16 *)(cvt->buf+cvt->len_cvt*2); |
for ( i=cvt->len_cvt/2; i; --i ) { |
dst -= 2; |
src -= 1; |
dst[0] = src[0]; |
dst[1] = src[0]; |
} |
} else { |
Uint8 *src, *dst; |
src = cvt->buf+cvt->len_cvt; |
dst = cvt->buf+cvt->len_cvt*2; |
for ( i=cvt->len_cvt; i; --i ) { |
dst -= 2; |
src -= 1; |
dst[0] = src[0]; |
dst[1] = src[0]; |
} |
} |
cvt->len_cvt *= 2; |
if ( cvt->filters[++cvt->filter_index] ) { |
cvt->filters[cvt->filter_index](cvt, format); |
} |
} |
/* Convert 8-bit to 16-bit - LSB */ |
void SDL_Convert16LSB(SDL_AudioCVT *cvt, Uint16 format) |
{ |
int i; |
Uint8 *src, *dst; |
#ifdef DEBUG_CONVERT |
fprintf(stderr, "Converting to 16-bit LSB\n"); |
#endif |
src = cvt->buf+cvt->len_cvt; |
dst = cvt->buf+cvt->len_cvt*2; |
for ( i=cvt->len_cvt; i; --i ) { |
src -= 1; |
dst -= 2; |
dst[1] = *src; |
dst[0] = 0; |
} |
format = ((format & ~0x0008) | AUDIO_U16LSB); |
cvt->len_cvt *= 2; |
if ( cvt->filters[++cvt->filter_index] ) { |
cvt->filters[cvt->filter_index](cvt, format); |
} |
} |
/* Convert 8-bit to 16-bit - MSB */ |
void SDL_Convert16MSB(SDL_AudioCVT *cvt, Uint16 format) |
{ |
int i; |
Uint8 *src, *dst; |
#ifdef DEBUG_CONVERT |
fprintf(stderr, "Converting to 16-bit MSB\n"); |
#endif |
src = cvt->buf+cvt->len_cvt; |
dst = cvt->buf+cvt->len_cvt*2; |
for ( i=cvt->len_cvt; i; --i ) { |
src -= 1; |
dst -= 2; |
dst[0] = *src; |
dst[1] = 0; |
} |
format = ((format & ~0x0008) | AUDIO_U16MSB); |
cvt->len_cvt *= 2; |
if ( cvt->filters[++cvt->filter_index] ) { |
cvt->filters[cvt->filter_index](cvt, format); |
} |
} |
/* Convert 16-bit to 8-bit */ |
void SDL_Convert8(SDL_AudioCVT *cvt, Uint16 format) |
{ |
int i; |
Uint8 *src, *dst; |
#ifdef DEBUG_CONVERT |
fprintf(stderr, "Converting to 8-bit\n"); |
#endif |
src = cvt->buf; |
dst = cvt->buf; |
if ( (format & 0x1000) != 0x1000 ) { /* Little endian */ |
++src; |
} |
for ( i=cvt->len_cvt/2; i; --i ) { |
*dst = *src; |
src += 2; |
dst += 1; |
} |
format = ((format & ~0x9010) | AUDIO_U8); |
cvt->len_cvt /= 2; |
if ( cvt->filters[++cvt->filter_index] ) { |
cvt->filters[cvt->filter_index](cvt, format); |
} |
} |
/* Toggle signed/unsigned */ |
void SDL_ConvertSign(SDL_AudioCVT *cvt, Uint16 format) |
{ |
int i; |
Uint8 *data; |
#ifdef DEBUG_CONVERT |
fprintf(stderr, "Converting audio signedness\n"); |
#endif |
data = cvt->buf; |
if ( (format & 0xFF) == 16 ) { |
if ( (format & 0x1000) != 0x1000 ) { /* Little endian */ |
++data; |
} |
for ( i=cvt->len_cvt/2; i; --i ) { |
*data ^= 0x80; |
data += 2; |
} |
} else { |
for ( i=cvt->len_cvt; i; --i ) { |
*data++ ^= 0x80; |
} |
} |
format = (format ^ 0x8000); |
if ( cvt->filters[++cvt->filter_index] ) { |
cvt->filters[cvt->filter_index](cvt, format); |
} |
} |
/* Toggle endianness */ |
void SDL_ConvertEndian(SDL_AudioCVT *cvt, Uint16 format) |
{ |
int i; |
Uint8 *data, tmp; |
#ifdef DEBUG_CONVERT |
fprintf(stderr, "Converting audio endianness\n"); |
#endif |
data = cvt->buf; |
for ( i=cvt->len_cvt/2; i; --i ) { |
tmp = data[0]; |
data[0] = data[1]; |
data[1] = tmp; |
data += 2; |
} |
format = (format ^ 0x1000); |
if ( cvt->filters[++cvt->filter_index] ) { |
cvt->filters[cvt->filter_index](cvt, format); |
} |
} |
/* Convert rate up by multiple of 2 */ |
void SDL_RateMUL2(SDL_AudioCVT *cvt, Uint16 format) |
{ |
int i; |
Uint8 *src, *dst; |
#ifdef DEBUG_CONVERT |
fprintf(stderr, "Converting audio rate * 2\n"); |
#endif |
src = cvt->buf+cvt->len_cvt; |
dst = cvt->buf+cvt->len_cvt*2; |
switch (format & 0xFF) { |
case 8: |
for ( i=cvt->len_cvt; i; --i ) { |
src -= 1; |
dst -= 2; |
dst[0] = src[0]; |
dst[1] = src[0]; |
} |
break; |
case 16: |
for ( i=cvt->len_cvt/2; i; --i ) { |
src -= 2; |
dst -= 4; |
dst[0] = src[0]; |
dst[1] = src[1]; |
dst[2] = src[0]; |
dst[3] = src[1]; |
} |
break; |
} |
cvt->len_cvt *= 2; |
if ( cvt->filters[++cvt->filter_index] ) { |
cvt->filters[cvt->filter_index](cvt, format); |
} |
} |
/* Convert rate down by multiple of 2 */ |
void SDL_RateDIV2(SDL_AudioCVT *cvt, Uint16 format) |
{ |
int i; |
Uint8 *src, *dst; |
#ifdef DEBUG_CONVERT |
fprintf(stderr, "Converting audio rate / 2\n"); |
#endif |
src = cvt->buf; |
dst = cvt->buf; |
switch (format & 0xFF) { |
case 8: |
for ( i=cvt->len_cvt/2; i; --i ) { |
dst[0] = src[0]; |
src += 2; |
dst += 1; |
} |
break; |
case 16: |
for ( i=cvt->len_cvt/4; i; --i ) { |
dst[0] = src[0]; |
dst[1] = src[1]; |
src += 4; |
dst += 2; |
} |
break; |
} |
cvt->len_cvt /= 2; |
if ( cvt->filters[++cvt->filter_index] ) { |
cvt->filters[cvt->filter_index](cvt, format); |
} |
} |
/* Very slow rate conversion routine */ |
void SDL_RateSLOW(SDL_AudioCVT *cvt, Uint16 format) |
{ |
double ipos; |
int i, clen; |
#ifdef DEBUG_CONVERT |
fprintf(stderr, "Converting audio rate * %4.4f\n", 1.0/cvt->rate_incr); |
#endif |
clen = (int)((double)cvt->len_cvt / cvt->rate_incr); |
if ( cvt->rate_incr > 1.0 ) { |
switch (format & 0xFF) { |
case 8: { |
Uint8 *output; |
output = cvt->buf; |
ipos = 0.0; |
for ( i=clen; i; --i ) { |
*output = cvt->buf[(int)ipos]; |
ipos += cvt->rate_incr; |
output += 1; |
} |
} |
break; |
case 16: { |
Uint16 *output; |
clen &= ~1; |
output = (Uint16 *)cvt->buf; |
ipos = 0.0; |
for ( i=clen/2; i; --i ) { |
*output=((Uint16 *)cvt->buf)[(int)ipos]; |
ipos += cvt->rate_incr; |
output += 1; |
} |
} |
break; |
} |
} else { |
switch (format & 0xFF) { |
case 8: { |
Uint8 *output; |
output = cvt->buf+clen; |
ipos = (double)cvt->len_cvt; |
for ( i=clen; i; --i ) { |
ipos -= cvt->rate_incr; |
output -= 1; |
*output = cvt->buf[(int)ipos]; |
} |
} |
break; |
case 16: { |
Uint16 *output; |
clen &= ~1; |
output = (Uint16 *)(cvt->buf+clen); |
ipos = (double)cvt->len_cvt/2; |
for ( i=clen/2; i; --i ) { |
ipos -= cvt->rate_incr; |
output -= 1; |
*output=((Uint16 *)cvt->buf)[(int)ipos]; |
} |
} |
break; |
} |
} |
cvt->len_cvt = clen; |
if ( cvt->filters[++cvt->filter_index] ) { |
cvt->filters[cvt->filter_index](cvt, format); |
} |
} |
int SDL_ConvertAudio(SDL_AudioCVT *cvt) |
{ |
/* Make sure there's data to convert */ |
if ( cvt->buf == NULL ) { |
SDL_SetError("No buffer allocated for conversion"); |
return(-1); |
} |
/* Return okay if no conversion is necessary */ |
cvt->len_cvt = cvt->len; |
if ( cvt->filters[0] == NULL ) { |
return(0); |
} |
/* Set up the conversion and go! */ |
cvt->filter_index = 0; |
cvt->filters[0](cvt, cvt->src_format); |
return(0); |
} |
/* Creates a set of audio filters to convert from one format to another. |
Returns -1 if the format conversion is not supported, or 1 if the |
audio filter is set up. |
*/ |
int SDL_BuildAudioCVT(SDL_AudioCVT *cvt, |
Uint16 src_format, Uint8 src_channels, int src_rate, |
Uint16 dst_format, Uint8 dst_channels, int dst_rate) |
{ |
/* Start off with no conversion necessary */ |
cvt->needed = 0; |
cvt->filter_index = 0; |
cvt->filters[0] = NULL; |
cvt->len_mult = 1; |
cvt->len_ratio = 1.0; |
/* First filter: Endian conversion from src to dst */ |
if ( (src_format & 0x1000) != (dst_format & 0x1000) |
&& ((src_format & 0xff) != 8) ) { |
cvt->filters[cvt->filter_index++] = SDL_ConvertEndian; |
} |
/* Second filter: Sign conversion -- signed/unsigned */ |
if ( (src_format & 0x8000) != (dst_format & 0x8000) ) { |
cvt->filters[cvt->filter_index++] = SDL_ConvertSign; |
} |
/* Next filter: Convert 16 bit <--> 8 bit PCM */ |
if ( (src_format & 0xFF) != (dst_format & 0xFF) ) { |
switch (dst_format&0x10FF) { |
case AUDIO_U8: |
cvt->filters[cvt->filter_index++] = |
SDL_Convert8; |
cvt->len_ratio /= 2; |
break; |
case AUDIO_U16LSB: |
cvt->filters[cvt->filter_index++] = |
SDL_Convert16LSB; |
cvt->len_mult *= 2; |
cvt->len_ratio *= 2; |
break; |
case AUDIO_U16MSB: |
cvt->filters[cvt->filter_index++] = |
SDL_Convert16MSB; |
cvt->len_mult *= 2; |
cvt->len_ratio *= 2; |
break; |
} |
} |
/* Last filter: Mono/Stereo conversion */ |
if ( src_channels != dst_channels ) { |
while ( (src_channels*2) <= dst_channels ) { |
cvt->filters[cvt->filter_index++] = |
SDL_ConvertStereo; |
cvt->len_mult *= 2; |
src_channels *= 2; |
cvt->len_ratio *= 2; |
} |
/* This assumes that 4 channel audio is in the format: |
Left {front/back} + Right {front/back} |
so converting to L/R stereo works properly. |
*/ |
while ( ((src_channels%2) == 0) && |
((src_channels/2) >= dst_channels) ) { |
cvt->filters[cvt->filter_index++] = |
SDL_ConvertMono; |
src_channels /= 2; |
cvt->len_ratio /= 2; |
} |
if ( src_channels != dst_channels ) { |
/* Uh oh.. */; |
} |
} |
/* Do rate conversion */ |
cvt->rate_incr = 0.0; |
if ( (src_rate/100) != (dst_rate/100) ) { |
Uint32 hi_rate, lo_rate; |
int len_mult; |
double len_ratio; |
void (*rate_cvt)(SDL_AudioCVT *cvt, Uint16 format); |
if ( src_rate > dst_rate ) { |
hi_rate = src_rate; |
lo_rate = dst_rate; |
rate_cvt = SDL_RateDIV2; |
len_mult = 1; |
len_ratio = 0.5; |
} else { |
hi_rate = dst_rate; |
lo_rate = src_rate; |
rate_cvt = SDL_RateMUL2; |
len_mult = 2; |
len_ratio = 2.0; |
} |
/* If hi_rate = lo_rate*2^x then conversion is easy */ |
while ( ((lo_rate*2)/100) <= (hi_rate/100) ) { |
cvt->filters[cvt->filter_index++] = rate_cvt; |
cvt->len_mult *= len_mult; |
lo_rate *= 2; |
cvt->len_ratio *= len_ratio; |
} |
/* We may need a slow conversion here to finish up */ |
if ( (lo_rate/100) != (hi_rate/100) ) { |
#if 1 |
/* The problem with this is that if the input buffer is |
say 1K, and the conversion rate is say 1.1, then the |
output buffer is 1.1K, which may not be an acceptable |
buffer size for the audio driver (not a power of 2) |
*/ |
/* For now, punt and hope the rate distortion isn't great. |
*/ |
#else |
if ( src_rate < dst_rate ) { |
cvt->rate_incr = (double)lo_rate/hi_rate; |
cvt->len_mult *= 2; |
cvt->len_ratio /= cvt->rate_incr; |
} else { |
cvt->rate_incr = (double)hi_rate/lo_rate; |
cvt->len_ratio *= cvt->rate_incr; |
} |
cvt->filters[cvt->filter_index++] = SDL_RateSLOW; |
#endif |
} |
} |
/* Set up the filter information */ |
if ( cvt->filter_index != 0 ) { |
cvt->needed = 1; |
cvt->src_format = src_format; |
cvt->dst_format = dst_format; |
cvt->len = 0; |
cvt->buf = NULL; |
cvt->filters[cvt->filter_index] = NULL; |
} |
return(cvt->needed); |
} |
/contrib/games/wolf3d/SDL/SDL_mixer.c |
---|
0,0 → 1,218 |
/* |
SDL - Simple DirectMedia Layer |
Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga |
This library is free software; you can redistribute it and/or |
modify it under the terms of the GNU Library General Public |
License as published by the Free Software Foundation; either |
version 2 of the License, or (at your option) any later version. |
This library is distributed in the hope that it will be useful, |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
Library General Public License for more details. |
You should have received a copy of the GNU Library General Public |
License along with this library; if not, write to the Free |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
Sam Lantinga |
slouken@devolution.com |
*/ |
#ifdef SAVE_RCSID |
static char rcsid = |
"@(#) $Id: SDL_mixer.c,v 1.2 2001/04/26 16:50:17 hercules Exp $"; |
#endif |
/* This provides the default mixing callback for the SDL audio routines */ |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
#include "SDL_audio.h" |
#include "SDL_mutex.h" |
#include "SDL_timer.h" |
#include "SDL_sysaudio.h" |
SDL_AudioDevice *current_audio = NULL; |
/* This table is used to add two sound values together and pin |
* the value to avoid overflow. (used with permission from ARDI) |
* Changed to use 0xFE instead of 0xFF for better sound quality. |
*/ |
static const Uint8 mix8[] = |
{ |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, |
0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, |
0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, |
0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, |
0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, |
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, |
0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, |
0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, |
0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, |
0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, |
0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, |
0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, |
0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, |
0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, |
0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, |
0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, |
0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, |
0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, |
0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, |
0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, |
0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, |
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, |
0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, |
0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFE, 0xFE, |
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, |
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, |
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, |
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, |
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, |
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, |
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, |
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, |
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, |
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, |
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, |
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE |
}; |
/* The volume ranges from 0 - 128 */ |
#define ADJUST_VOLUME(s, v) (s = (s*v)/SDL_MIX_MAXVOLUME) |
#define ADJUST_VOLUME_U8(s, v) (s = (((s-128)*v)/SDL_MIX_MAXVOLUME)+128) |
void SDL_MixAudio (Uint8 *dst, const Uint8 *src, Uint32 len, int volume) |
{ |
Uint16 format; |
if ( volume == 0 ) { |
return; |
} |
/* Mix the user-level audio format */ |
if ( current_audio ) { |
if ( current_audio->convert.needed ) { |
format = current_audio->convert.src_format; |
} else { |
format = current_audio->spec.format; |
} |
} else { |
format = AUDIO_S16; |
} |
format = AUDIO_S16; |
switch (format) { |
case AUDIO_U8: { |
Uint8 src_sample; |
while ( len-- ) { |
src_sample = *src; |
ADJUST_VOLUME_U8(src_sample, volume); |
*dst = mix8[*dst+src_sample]; |
++dst; |
++src; |
} |
} |
break; |
case AUDIO_S8: { |
Sint8 *dst8, *src8; |
Sint8 src_sample; |
int dst_sample; |
const int max_audioval = ((1<<(8-1))-1); |
const int min_audioval = -(1<<(8-1)); |
src8 = (Sint8 *)src; |
dst8 = (Sint8 *)dst; |
while ( len-- ) { |
src_sample = *src8; |
ADJUST_VOLUME(src_sample, volume); |
dst_sample = *dst8 + src_sample; |
if ( dst_sample > max_audioval ) { |
*dst8 = max_audioval; |
} else |
if ( dst_sample < min_audioval ) { |
*dst8 = min_audioval; |
} else { |
*dst8 = dst_sample; |
} |
++dst8; |
++src8; |
} |
} |
break; |
case AUDIO_S16LSB: { |
Sint16 src1, src2; |
int dst_sample; |
const int max_audioval = ((1<<(16-1))-1); |
const int min_audioval = -(1<<(16-1)); |
len /= 2; |
while ( len-- ) { |
src1 = ((src[1])<<8|src[0]); |
ADJUST_VOLUME(src1, volume); |
src2 = ((dst[1])<<8|dst[0]); |
src += 2; |
dst_sample = src1+src2; |
if ( dst_sample > max_audioval ) { |
dst_sample = max_audioval; |
} else |
if ( dst_sample < min_audioval ) { |
dst_sample = min_audioval; |
} |
dst[0] = dst_sample&0xFF; |
dst_sample >>= 8; |
dst[1] = dst_sample&0xFF; |
dst += 2; |
} |
} |
break; |
case AUDIO_S16MSB: { |
Sint16 src1, src2; |
int dst_sample; |
const int max_audioval = ((1<<(16-1))-1); |
const int min_audioval = -(1<<(16-1)); |
len /= 2; |
while ( len-- ) { |
src1 = ((src[0])<<8|src[1]); |
ADJUST_VOLUME(src1, volume); |
src2 = ((dst[0])<<8|dst[1]); |
src += 2; |
dst_sample = src1+src2; |
if ( dst_sample > max_audioval ) { |
dst_sample = max_audioval; |
} else |
if ( dst_sample < min_audioval ) { |
dst_sample = min_audioval; |
} |
dst[1] = dst_sample&0xFF; |
dst_sample >>= 8; |
dst[0] = dst_sample&0xFF; |
dst += 2; |
} |
} |
break; |
default: /* If this happens... FIXME! */ |
SDL_SetError("SDL_MixAudio(): unknown audio format"); |
return; |
} |
} |
/contrib/games/wolf3d/SDL/SDL_sysaudio.h |
---|
0,0 → 1,150 |
/* |
SDL - Simple DirectMedia Layer |
Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga |
This library is free software; you can redistribute it and/or |
modify it under the terms of the GNU Library General Public |
License as published by the Free Software Foundation; either |
version 2 of the License, or (at your option) any later version. |
This library is distributed in the hope that it will be useful, |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
Library General Public License for more details. |
You should have received a copy of the GNU Library General Public |
License along with this library; if not, write to the Free |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
Sam Lantinga |
slouken@devolution.com |
*/ |
#ifdef SAVE_RCSID |
static char rcsid = |
"@(#) $Id: SDL_sysaudio.h,v 1.8 2001/07/23 02:58:42 slouken Exp $"; |
#endif |
#ifndef _SDL_sysaudio_h |
#define _SDL_sysaudio_h |
#include "SDL_mutex.h" |
#include "SDL_thread.h" |
/* The SDL audio driver */ |
typedef struct SDL_AudioDevice SDL_AudioDevice; |
/* Define the SDL audio driver structure */ |
#define _THIS SDL_AudioDevice *_this |
#ifndef _STATUS |
#define _STATUS SDL_status *status |
#endif |
struct SDL_AudioDevice { |
/* * * */ |
/* The name of this audio driver */ |
const char *name; |
/* * * */ |
/* The description of this audio driver */ |
const char *desc; |
/* * * */ |
/* Public driver functions */ |
int (*OpenAudio)(_THIS, SDL_AudioSpec *spec); |
void (*ThreadInit)(_THIS); /* Called by audio thread at start */ |
void (*WaitAudio)(_THIS); |
void (*PlayAudio)(_THIS); |
Uint8 *(*GetAudioBuf)(_THIS); |
void (*WaitDone)(_THIS); |
void (*CloseAudio)(_THIS); |
/* * * */ |
/* Data common to all devices */ |
/* The current audio specification (shared with audio thread) */ |
SDL_AudioSpec spec; |
/* An audio conversion block for audio format emulation */ |
SDL_AudioCVT convert; |
/* Current state flags */ |
int enabled; |
int paused; |
int opened; |
/* Fake audio buffer for when the audio hardware is busy */ |
Uint8 *fake_stream; |
/* A semaphore for locking the mixing buffers */ |
SDL_mutex *mixer_lock; |
/* A thread to feed the audio device */ |
SDL_Thread *thread; |
Uint32 threadid; |
/* * * */ |
/* Data private to this driver */ |
struct SDL_PrivateAudioData *hidden; |
/* * * */ |
/* The function used to dispose of this structure */ |
void (*free)(_THIS); |
}; |
#undef _THIS |
typedef struct AudioBootStrap { |
const char *name; |
const char *desc; |
int (*available)(void); |
SDL_AudioDevice *(*create)(int devindex); |
} AudioBootStrap; |
#ifdef OPENBSD_AUDIO_SUPPORT |
extern AudioBootStrap OPENBSD_AUDIO_bootstrap; |
#endif |
#ifdef OSS_SUPPORT |
extern AudioBootStrap DSP_bootstrap; |
extern AudioBootStrap DMA_bootstrap; |
#endif |
#ifdef ALSA_SUPPORT |
extern AudioBootStrap ALSA_bootstrap; |
#endif |
#if (defined(unix) && !defined(__CYGWIN32__)) && \ |
!defined(OSS_SUPPORT) && !defined(ALSA_SUPPORT) |
extern AudioBootStrap AUDIO_bootstrap; |
#endif |
#ifdef ARTSC_SUPPORT |
extern AudioBootStrap ARTSC_bootstrap; |
#endif |
#ifdef ESD_SUPPORT |
extern AudioBootStrap ESD_bootstrap; |
#endif |
#ifdef NAS_SUPPORT |
extern AudioBootStrap NAS_bootstrap; |
#endif |
#ifdef ENABLE_DIRECTX |
extern AudioBootStrap DSOUND_bootstrap; |
#endif |
#ifdef ENABLE_WINDIB |
extern AudioBootStrap WAVEOUT_bootstrap; |
#endif |
#ifdef _AIX |
extern AudioBootStrap Paud_bootstrap; |
#endif |
#ifdef __BEOS__ |
extern AudioBootStrap BAUDIO_bootstrap; |
#endif |
#if defined(macintosh) || TARGET_API_MAC_CARBON |
extern AudioBootStrap SNDMGR_bootstrap; |
#endif |
#ifdef ENABLE_AHI |
extern AudioBootStrap AHI_bootstrap; |
#endif |
#ifdef DISKAUD_SUPPORT |
extern AudioBootStrap DISKAUD_bootstrap; |
#endif |
/* This is the current audio device */ |
extern SDL_AudioDevice *current_audio; |
#endif /* _SDL_sysaudio_h */ |
/contrib/games/wolf3d/SDL/SDL_wave.c |
---|
0,0 → 1,591 |
/* |
SDL - Simple DirectMedia Layer |
Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga |
This library is free software; you can redistribute it and/or |
modify it under the terms of the GNU Library General Public |
License as published by the Free Software Foundation; either |
version 2 of the License, or (at your option) any later version. |
This library is distributed in the hope that it will be useful, |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
Library General Public License for more details. |
You should have received a copy of the GNU Library General Public |
License along with this library; if not, write to the Free |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
Sam Lantinga |
slouken@devolution.com |
*/ |
#ifdef SAVE_RCSID |
static char rcsid = |
"@(#) $Id: SDL_wave.c,v 1.2 2001/04/26 16:50:17 hercules Exp $"; |
#endif |
#ifndef DISABLE_FILE |
/* Microsoft WAVE file loading routines */ |
#include <stdlib.h> |
#include <string.h> |
#include "SDL_error.h" |
#include "SDL_audio.h" |
#include "SDL_wave.h" |
#include "SDL_endian.h" |
#ifndef NELEMS |
#define NELEMS(array) ((sizeof array)/(sizeof array[0])) |
#endif |
static int ReadChunk(SDL_RWops *src, Chunk *chunk); |
struct MS_ADPCM_decodestate { |
Uint8 hPredictor; |
Uint16 iDelta; |
Sint16 iSamp1; |
Sint16 iSamp2; |
}; |
static struct MS_ADPCM_decoder { |
WaveFMT wavefmt; |
Uint16 wSamplesPerBlock; |
Uint16 wNumCoef; |
Sint16 aCoeff[7][2]; |
/* * * */ |
struct MS_ADPCM_decodestate state[2]; |
} MS_ADPCM_state; |
static int InitMS_ADPCM(WaveFMT *format) |
{ |
Uint8 *rogue_feel; |
Uint16 extra_info; |
int i; |
/* Set the rogue pointer to the MS_ADPCM specific data */ |
MS_ADPCM_state.wavefmt.encoding = SDL_SwapLE16(format->encoding); |
MS_ADPCM_state.wavefmt.channels = SDL_SwapLE16(format->channels); |
MS_ADPCM_state.wavefmt.frequency = SDL_SwapLE32(format->frequency); |
MS_ADPCM_state.wavefmt.byterate = SDL_SwapLE32(format->byterate); |
MS_ADPCM_state.wavefmt.blockalign = SDL_SwapLE16(format->blockalign); |
MS_ADPCM_state.wavefmt.bitspersample = |
SDL_SwapLE16(format->bitspersample); |
rogue_feel = (Uint8 *)format+sizeof(*format); |
if ( sizeof(*format) == 16 ) { |
extra_info = ((rogue_feel[1]<<8)|rogue_feel[0]); |
rogue_feel += sizeof(Uint16); |
} |
MS_ADPCM_state.wSamplesPerBlock = ((rogue_feel[1]<<8)|rogue_feel[0]); |
rogue_feel += sizeof(Uint16); |
MS_ADPCM_state.wNumCoef = ((rogue_feel[1]<<8)|rogue_feel[0]); |
rogue_feel += sizeof(Uint16); |
if ( MS_ADPCM_state.wNumCoef != 7 ) { |
SDL_SetError("Unknown set of MS_ADPCM coefficients"); |
return(-1); |
} |
for ( i=0; i<MS_ADPCM_state.wNumCoef; ++i ) { |
MS_ADPCM_state.aCoeff[i][0] = ((rogue_feel[1]<<8)|rogue_feel[0]); |
rogue_feel += sizeof(Uint16); |
MS_ADPCM_state.aCoeff[i][1] = ((rogue_feel[1]<<8)|rogue_feel[0]); |
rogue_feel += sizeof(Uint16); |
} |
return(0); |
} |
static Sint32 MS_ADPCM_nibble(struct MS_ADPCM_decodestate *state, |
Uint8 nybble, Sint16 *coeff) |
{ |
const Sint32 max_audioval = ((1<<(16-1))-1); |
const Sint32 min_audioval = -(1<<(16-1)); |
const Sint32 adaptive[] = { |
230, 230, 230, 230, 307, 409, 512, 614, |
768, 614, 512, 409, 307, 230, 230, 230 |
}; |
Sint32 new_sample, delta; |
new_sample = ((state->iSamp1 * coeff[0]) + |
(state->iSamp2 * coeff[1]))/256; |
if ( nybble & 0x08 ) { |
new_sample += state->iDelta * (nybble-0x10); |
} else { |
new_sample += state->iDelta * nybble; |
} |
if ( new_sample < min_audioval ) { |
new_sample = min_audioval; |
} else |
if ( new_sample > max_audioval ) { |
new_sample = max_audioval; |
} |
delta = ((Sint32)state->iDelta * adaptive[nybble])/256; |
if ( delta < 16 ) { |
delta = 16; |
} |
state->iDelta = delta; |
state->iSamp2 = state->iSamp1; |
state->iSamp1 = new_sample; |
return(new_sample); |
} |
static int MS_ADPCM_decode(Uint8 **audio_buf, Uint32 *audio_len) |
{ |
struct MS_ADPCM_decodestate *state[2]; |
Uint8 *freeable, *encoded, *decoded; |
Sint32 encoded_len, samplesleft; |
Sint8 nybble, stereo; |
Sint16 *coeff[2]; |
Sint32 new_sample; |
/* Allocate the proper sized output buffer */ |
encoded_len = *audio_len; |
encoded = *audio_buf; |
freeable = *audio_buf; |
*audio_len = (encoded_len/MS_ADPCM_state.wavefmt.blockalign) * |
MS_ADPCM_state.wSamplesPerBlock* |
MS_ADPCM_state.wavefmt.channels*sizeof(Sint16); |
*audio_buf = (Uint8 *)malloc(*audio_len); |
if ( *audio_buf == NULL ) { |
SDL_Error(SDL_ENOMEM); |
return(-1); |
} |
decoded = *audio_buf; |
/* Get ready... Go! */ |
stereo = (MS_ADPCM_state.wavefmt.channels == 2); |
state[0] = &MS_ADPCM_state.state[0]; |
state[1] = &MS_ADPCM_state.state[stereo]; |
while ( encoded_len >= MS_ADPCM_state.wavefmt.blockalign ) { |
/* Grab the initial information for this block */ |
state[0]->hPredictor = *encoded++; |
if ( stereo ) { |
state[1]->hPredictor = *encoded++; |
} |
state[0]->iDelta = ((encoded[1]<<8)|encoded[0]); |
encoded += sizeof(Sint16); |
if ( stereo ) { |
state[1]->iDelta = ((encoded[1]<<8)|encoded[0]); |
encoded += sizeof(Sint16); |
} |
state[0]->iSamp1 = ((encoded[1]<<8)|encoded[0]); |
encoded += sizeof(Sint16); |
if ( stereo ) { |
state[1]->iSamp1 = ((encoded[1]<<8)|encoded[0]); |
encoded += sizeof(Sint16); |
} |
state[0]->iSamp2 = ((encoded[1]<<8)|encoded[0]); |
encoded += sizeof(Sint16); |
if ( stereo ) { |
state[1]->iSamp2 = ((encoded[1]<<8)|encoded[0]); |
encoded += sizeof(Sint16); |
} |
coeff[0] = MS_ADPCM_state.aCoeff[state[0]->hPredictor]; |
coeff[1] = MS_ADPCM_state.aCoeff[state[1]->hPredictor]; |
/* Store the two initial samples we start with */ |
decoded[0] = state[0]->iSamp2&0xFF; |
decoded[1] = state[0]->iSamp2>>8; |
decoded += 2; |
if ( stereo ) { |
decoded[0] = state[1]->iSamp2&0xFF; |
decoded[1] = state[1]->iSamp2>>8; |
decoded += 2; |
} |
decoded[0] = state[0]->iSamp1&0xFF; |
decoded[1] = state[0]->iSamp1>>8; |
decoded += 2; |
if ( stereo ) { |
decoded[0] = state[1]->iSamp1&0xFF; |
decoded[1] = state[1]->iSamp1>>8; |
decoded += 2; |
} |
/* Decode and store the other samples in this block */ |
samplesleft = (MS_ADPCM_state.wSamplesPerBlock-2)* |
MS_ADPCM_state.wavefmt.channels; |
while ( samplesleft > 0 ) { |
nybble = (*encoded)>>4; |
new_sample = MS_ADPCM_nibble(state[0],nybble,coeff[0]); |
decoded[0] = new_sample&0xFF; |
new_sample >>= 8; |
decoded[1] = new_sample&0xFF; |
decoded += 2; |
nybble = (*encoded)&0x0F; |
new_sample = MS_ADPCM_nibble(state[1],nybble,coeff[1]); |
decoded[0] = new_sample&0xFF; |
new_sample >>= 8; |
decoded[1] = new_sample&0xFF; |
decoded += 2; |
++encoded; |
samplesleft -= 2; |
} |
encoded_len -= MS_ADPCM_state.wavefmt.blockalign; |
} |
free(freeable); |
return(0); |
} |
struct IMA_ADPCM_decodestate { |
Sint32 sample; |
Sint8 index; |
}; |
static struct IMA_ADPCM_decoder { |
WaveFMT wavefmt; |
Uint16 wSamplesPerBlock; |
/* * * */ |
struct IMA_ADPCM_decodestate state[2]; |
} IMA_ADPCM_state; |
static int InitIMA_ADPCM(WaveFMT *format) |
{ |
Uint8 *rogue_feel; |
Uint16 extra_info; |
/* Set the rogue pointer to the IMA_ADPCM specific data */ |
IMA_ADPCM_state.wavefmt.encoding = SDL_SwapLE16(format->encoding); |
IMA_ADPCM_state.wavefmt.channels = SDL_SwapLE16(format->channels); |
IMA_ADPCM_state.wavefmt.frequency = SDL_SwapLE32(format->frequency); |
IMA_ADPCM_state.wavefmt.byterate = SDL_SwapLE32(format->byterate); |
IMA_ADPCM_state.wavefmt.blockalign = SDL_SwapLE16(format->blockalign); |
IMA_ADPCM_state.wavefmt.bitspersample = |
SDL_SwapLE16(format->bitspersample); |
rogue_feel = (Uint8 *)format+sizeof(*format); |
if ( sizeof(*format) == 16 ) { |
extra_info = ((rogue_feel[1]<<8)|rogue_feel[0]); |
rogue_feel += sizeof(Uint16); |
} |
IMA_ADPCM_state.wSamplesPerBlock = ((rogue_feel[1]<<8)|rogue_feel[0]); |
return(0); |
} |
static Sint32 IMA_ADPCM_nibble(struct IMA_ADPCM_decodestate *state,Uint8 nybble) |
{ |
const Sint32 max_audioval = ((1<<(16-1))-1); |
const Sint32 min_audioval = -(1<<(16-1)); |
const int index_table[16] = { |
-1, -1, -1, -1, |
2, 4, 6, 8, |
-1, -1, -1, -1, |
2, 4, 6, 8 |
}; |
const Sint32 step_table[89] = { |
7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, |
34, 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, |
143, 157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, |
449, 494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, |
1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327, |
3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, |
9493, 10442, 11487, 12635, 13899, 15289, 16818, 18500, 20350, |
22385, 24623, 27086, 29794, 32767 |
}; |
Sint32 delta, step; |
/* Compute difference and new sample value */ |
step = step_table[state->index]; |
delta = step >> 3; |
if ( nybble & 0x04 ) delta += step; |
if ( nybble & 0x02 ) delta += (step >> 1); |
if ( nybble & 0x01 ) delta += (step >> 2); |
if ( nybble & 0x08 ) delta = -delta; |
state->sample += delta; |
/* Update index value */ |
state->index += index_table[nybble]; |
if ( state->index > 88 ) { |
state->index = 88; |
} else |
if ( state->index < 0 ) { |
state->index = 0; |
} |
/* Clamp output sample */ |
if ( state->sample > max_audioval ) { |
state->sample = max_audioval; |
} else |
if ( state->sample < min_audioval ) { |
state->sample = min_audioval; |
} |
return(state->sample); |
} |
/* Fill the decode buffer with a channel block of data (8 samples) */ |
static void Fill_IMA_ADPCM_block(Uint8 *decoded, Uint8 *encoded, |
int channel, int numchannels, struct IMA_ADPCM_decodestate *state) |
{ |
int i; |
Sint8 nybble; |
Sint32 new_sample; |
decoded += (channel * 2); |
for ( i=0; i<4; ++i ) { |
nybble = (*encoded)&0x0F; |
new_sample = IMA_ADPCM_nibble(state, nybble); |
decoded[0] = new_sample&0xFF; |
new_sample >>= 8; |
decoded[1] = new_sample&0xFF; |
decoded += 2 * numchannels; |
nybble = (*encoded)>>4; |
new_sample = IMA_ADPCM_nibble(state, nybble); |
decoded[0] = new_sample&0xFF; |
new_sample >>= 8; |
decoded[1] = new_sample&0xFF; |
decoded += 2 * numchannels; |
++encoded; |
} |
} |
static int IMA_ADPCM_decode(Uint8 **audio_buf, Uint32 *audio_len) |
{ |
struct IMA_ADPCM_decodestate *state; |
Uint8 *freeable, *encoded, *decoded; |
Sint32 encoded_len, samplesleft; |
int c, channels; |
/* Check to make sure we have enough variables in the state array */ |
channels = IMA_ADPCM_state.wavefmt.channels; |
if ( channels > NELEMS(IMA_ADPCM_state.state) ) { |
SDL_SetError("IMA ADPCM decoder can only handle %d channels", |
NELEMS(IMA_ADPCM_state.state)); |
return(-1); |
} |
state = IMA_ADPCM_state.state; |
/* Allocate the proper sized output buffer */ |
encoded_len = *audio_len; |
encoded = *audio_buf; |
freeable = *audio_buf; |
*audio_len = (encoded_len/IMA_ADPCM_state.wavefmt.blockalign) * |
IMA_ADPCM_state.wSamplesPerBlock* |
IMA_ADPCM_state.wavefmt.channels*sizeof(Sint16); |
*audio_buf = (Uint8 *)malloc(*audio_len); |
if ( *audio_buf == NULL ) { |
SDL_Error(SDL_ENOMEM); |
return(-1); |
} |
decoded = *audio_buf; |
/* Get ready... Go! */ |
while ( encoded_len >= IMA_ADPCM_state.wavefmt.blockalign ) { |
/* Grab the initial information for this block */ |
for ( c=0; c<channels; ++c ) { |
/* Fill the state information for this block */ |
state[c].sample = ((encoded[1]<<8)|encoded[0]); |
encoded += 2; |
if ( state[c].sample & 0x8000 ) { |
state[c].sample -= 0x10000; |
} |
state[c].index = *encoded++; |
/* Reserved byte in buffer header, should be 0 */ |
if ( *encoded++ != 0 ) { |
/* Uh oh, corrupt data? Buggy code? */; |
} |
/* Store the initial sample we start with */ |
decoded[0] = state[c].sample&0xFF; |
decoded[1] = state[c].sample>>8; |
decoded += 2; |
} |
/* Decode and store the other samples in this block */ |
samplesleft = (IMA_ADPCM_state.wSamplesPerBlock-1)*channels; |
while ( samplesleft > 0 ) { |
for ( c=0; c<channels; ++c ) { |
Fill_IMA_ADPCM_block(decoded, encoded, |
c, channels, &state[c]); |
encoded += 4; |
samplesleft -= 8; |
} |
decoded += (channels * 8 * 2); |
} |
encoded_len -= IMA_ADPCM_state.wavefmt.blockalign; |
} |
free(freeable); |
return(0); |
} |
SDL_AudioSpec * SDL_LoadWAV_RW (SDL_RWops *src, int freesrc, |
SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len) |
{ |
int was_error; |
Chunk chunk; |
int lenread; |
int MS_ADPCM_encoded, IMA_ADPCM_encoded; |
int samplesize; |
/* WAV magic header */ |
Uint32 RIFFchunk; |
Uint32 wavelen; |
Uint32 WAVEmagic; |
/* FMT chunk */ |
WaveFMT *format = NULL; |
/* Make sure we are passed a valid data source */ |
was_error = 0; |
if ( src == NULL ) { |
was_error = 1; |
goto done; |
} |
/* Check the magic header */ |
RIFFchunk = SDL_ReadLE32(src); |
wavelen = SDL_ReadLE32(src); |
WAVEmagic = SDL_ReadLE32(src); |
if ( (RIFFchunk != RIFF) || (WAVEmagic != WAVE) ) { |
SDL_SetError("Unrecognized file type (not WAVE)"); |
was_error = 1; |
goto done; |
} |
/* Read the audio data format chunk */ |
chunk.data = NULL; |
do { |
if ( chunk.data != NULL ) { |
free(chunk.data); |
} |
lenread = ReadChunk(src, &chunk); |
if ( lenread < 0 ) { |
was_error = 1; |
goto done; |
} |
} while ( (chunk.magic == FACT) || (chunk.magic == LIST) ); |
/* Decode the audio data format */ |
format = (WaveFMT *)chunk.data; |
if ( chunk.magic != FMT ) { |
SDL_SetError("Complex WAVE files not supported"); |
was_error = 1; |
goto done; |
} |
MS_ADPCM_encoded = IMA_ADPCM_encoded = 0; |
switch (SDL_SwapLE16(format->encoding)) { |
case PCM_CODE: |
/* We can understand this */ |
break; |
case MS_ADPCM_CODE: |
/* Try to understand this */ |
if ( InitMS_ADPCM(format) < 0 ) { |
was_error = 1; |
goto done; |
} |
MS_ADPCM_encoded = 1; |
break; |
case IMA_ADPCM_CODE: |
/* Try to understand this */ |
if ( InitIMA_ADPCM(format) < 0 ) { |
was_error = 1; |
goto done; |
} |
IMA_ADPCM_encoded = 1; |
break; |
default: |
SDL_SetError("Unknown WAVE data format: 0x%.4x", |
SDL_SwapLE16(format->encoding)); |
was_error = 1; |
goto done; |
} |
memset(spec, 0, (sizeof *spec)); |
spec->freq = SDL_SwapLE32(format->frequency); |
switch (SDL_SwapLE16(format->bitspersample)) { |
case 4: |
if ( MS_ADPCM_encoded || IMA_ADPCM_encoded ) { |
spec->format = AUDIO_S16; |
} else { |
was_error = 1; |
} |
break; |
case 8: |
spec->format = AUDIO_U8; |
break; |
case 16: |
spec->format = AUDIO_S16; |
break; |
default: |
was_error = 1; |
break; |
} |
if ( was_error ) { |
SDL_SetError("Unknown %d-bit PCM data format", |
SDL_SwapLE16(format->bitspersample)); |
goto done; |
} |
spec->channels = (Uint8)SDL_SwapLE16(format->channels); |
spec->samples = 4096; /* Good default buffer size */ |
/* Read the audio data chunk */ |
*audio_buf = NULL; |
do { |
if ( *audio_buf != NULL ) { |
free(*audio_buf); |
} |
lenread = ReadChunk(src, &chunk); |
if ( lenread < 0 ) { |
was_error = 1; |
goto done; |
} |
*audio_len = lenread; |
*audio_buf = chunk.data; |
} while ( chunk.magic != DATA ); |
if ( MS_ADPCM_encoded ) { |
if ( MS_ADPCM_decode(audio_buf, audio_len) < 0 ) { |
was_error = 1; |
goto done; |
} |
} |
if ( IMA_ADPCM_encoded ) { |
if ( IMA_ADPCM_decode(audio_buf, audio_len) < 0 ) { |
was_error = 1; |
goto done; |
} |
} |
/* Don't return a buffer that isn't a multiple of samplesize */ |
samplesize = ((spec->format & 0xFF)/8)*spec->channels; |
*audio_len &= ~(samplesize-1); |
done: |
if ( format != NULL ) { |
free(format); |
} |
if ( freesrc && src ) { |
SDL_RWclose(src); |
} |
if ( was_error ) { |
spec = NULL; |
} |
return(spec); |
} |
/* Since the WAV memory is allocated in the shared library, it must also |
be freed here. (Necessary under Win32, VC++) |
*/ |
void SDL_FreeWAV(Uint8 *audio_buf) |
{ |
if ( audio_buf != NULL ) { |
free(audio_buf); |
} |
} |
static int ReadChunk(SDL_RWops *src, Chunk *chunk) |
{ |
chunk->magic = SDL_ReadLE32(src); |
chunk->length = SDL_ReadLE32(src); |
chunk->data = (Uint8 *)malloc(chunk->length); |
if ( chunk->data == NULL ) { |
SDL_Error(SDL_ENOMEM); |
return(-1); |
} |
if ( SDL_RWread(src, chunk->data, chunk->length, 1) != 1 ) { |
SDL_Error(SDL_EFREAD); |
free(chunk->data); |
return(-1); |
} |
return(chunk->length); |
} |
#endif /* ENABLE_FILE */ |
/contrib/games/wolf3d/SDL/SDL_wave.h |
---|
0,0 → 1,65 |
/* |
SDL - Simple DirectMedia Layer |
Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga |
This library is free software; you can redistribute it and/or |
modify it under the terms of the GNU Library General Public |
License as published by the Free Software Foundation; either |
version 2 of the License, or (at your option) any later version. |
This library is distributed in the hope that it will be useful, |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
Library General Public License for more details. |
You should have received a copy of the GNU Library General Public |
License along with this library; if not, write to the Free |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
Sam Lantinga |
slouken@devolution.com |
*/ |
#ifdef SAVE_RCSID |
static char rcsid = |
"@(#) $Id: SDL_wave.h,v 1.2 2001/04/26 16:50:17 hercules Exp $"; |
#endif |
/* WAVE files are little-endian */ |
/*******************************************/ |
/* Define values for Microsoft WAVE format */ |
/*******************************************/ |
#define RIFF 0x46464952 /* "RIFF" */ |
#define WAVE 0x45564157 /* "WAVE" */ |
#define FACT 0x74636166 /* "fact" */ |
#define LIST 0x5453494c /* "LIST" */ |
#define FMT 0x20746D66 /* "fmt " */ |
#define DATA 0x61746164 /* "data" */ |
#define PCM_CODE 0x0001 |
#define MS_ADPCM_CODE 0x0002 |
#define IMA_ADPCM_CODE 0x0011 |
#define WAVE_MONO 1 |
#define WAVE_STEREO 2 |
/* Normally, these three chunks come consecutively in a WAVE file */ |
typedef struct WaveFMT { |
/* Not saved in the chunk we read: |
Uint32 FMTchunk; |
Uint32 fmtlen; |
*/ |
Uint16 encoding; |
Uint16 channels; /* 1 = mono, 2 = stereo */ |
Uint32 frequency; /* One of 11025, 22050, or 44100 Hz */ |
Uint32 byterate; /* Average bytes per second */ |
Uint16 blockalign; /* Bytes per sample block */ |
Uint16 bitspersample; /* One of 8, 12, 16, or 4 for ADPCM */ |
} WaveFMT; |
/* The general chunk found in the WAVE file */ |
typedef struct Chunk { |
Uint32 magic; |
Uint32 length; |
Uint8 *data; /* Data includes magic and length */ |
} Chunk; |
/contrib/games/wolf3d/SDL_mixer/SDL_mixer.h |
---|
0,0 → 1,642 |
/* |
SDL_mixer: An audio mixer library based on the SDL library |
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org> |
This software is provided 'as-is', without any express or implied |
warranty. In no event will the authors be held liable for any damages |
arising from the use of this software. |
Permission is granted to anyone to use this software for any purpose, |
including commercial applications, and to alter it and redistribute it |
freely, subject to the following restrictions: |
1. The origin of this software must not be misrepresented; you must not |
claim that you wrote the original software. If you use this software |
in a product, an acknowledgment in the product documentation would be |
appreciated but is not required. |
2. Altered source versions must be plainly marked as such, and must not be |
misrepresented as being the original software. |
3. This notice may not be removed or altered from any source distribution. |
*/ |
/* $Id$ */ |
#ifndef _SDL_MIXER_H |
#define _SDL_MIXER_H |
#include "SDL_types.h" |
#include "SDL_rwops.h" |
#include "SDL_audio.h" |
#include "SDL_endian.h" |
#include "SDL_version.h" |
#include "begin_code.h" |
#define SDLCALL |
#define RW_SEEK_SET SEEK_SET |
#define SDL_free free |
#define SDL_malloc malloc |
#define SDL_realloc realloc |
#define SDL_calloc calloc |
#define SDL_abs abs |
/* Set up for C function definitions, even when using C++ */ |
#ifdef __cplusplus |
extern "C" { |
#endif |
/* Printable format: "%d.%d.%d", MAJOR, MINOR, PATCHLEVEL |
*/ |
#define SDL_MIXER_MAJOR_VERSION 1 |
#define SDL_MIXER_MINOR_VERSION 2 |
#define SDL_MIXER_PATCHLEVEL 12 |
/* This macro can be used to fill a version structure with the compile-time |
* version of the SDL_mixer library. |
*/ |
#define SDL_MIXER_VERSION(X) \ |
{ \ |
(X)->major = SDL_MIXER_MAJOR_VERSION; \ |
(X)->minor = SDL_MIXER_MINOR_VERSION; \ |
(X)->patch = SDL_MIXER_PATCHLEVEL; \ |
} |
/* Backwards compatibility */ |
#define MIX_MAJOR_VERSION SDL_MIXER_MAJOR_VERSION |
#define MIX_MINOR_VERSION SDL_MIXER_MINOR_VERSION |
#define MIX_PATCHLEVEL SDL_MIXER_PATCHLEVEL |
#define MIX_VERSION(X) SDL_MIXER_VERSION(X) |
/* This function gets the version of the dynamically linked SDL_mixer library. |
it should NOT be used to fill a version structure, instead you should |
use the SDL_MIXER_VERSION() macro. |
*/ |
extern DECLSPEC const SDL_version * SDLCALL Mix_Linked_Version(void); |
typedef enum |
{ |
MIX_INIT_FLAC = 0x00000001, |
MIX_INIT_MOD = 0x00000002, |
MIX_INIT_MP3 = 0x00000004, |
MIX_INIT_OGG = 0x00000008, |
MIX_INIT_FLUIDSYNTH = 0x00000010 |
} MIX_InitFlags; |
/* Loads dynamic libraries and prepares them for use. Flags should be |
one or more flags from MIX_InitFlags OR'd together. |
It returns the flags successfully initialized, or 0 on failure. |
*/ |
extern DECLSPEC int SDLCALL Mix_Init(int flags); |
/* Unloads libraries loaded with Mix_Init */ |
extern DECLSPEC void SDLCALL Mix_Quit(void); |
/* The default mixer has 8 simultaneous mixing channels */ |
#ifndef MIX_CHANNELS |
#define MIX_CHANNELS 8 |
#endif |
/* Good default values for a PC soundcard */ |
#define MIX_DEFAULT_FREQUENCY 22050 |
#if SDL_BYTEORDER == SDL_LIL_ENDIAN |
#define MIX_DEFAULT_FORMAT AUDIO_S16LSB |
#else |
#define MIX_DEFAULT_FORMAT AUDIO_S16MSB |
#endif |
#define MIX_DEFAULT_CHANNELS 2 |
#define MIX_MAX_VOLUME 128 /* Volume of a chunk */ |
/* The internal format for an audio chunk */ |
typedef struct Mix_Chunk { |
int allocated; |
Uint8 *abuf; |
Uint32 alen; |
Uint8 volume; /* Per-sample volume, 0-128 */ |
} Mix_Chunk; |
/* The different fading types supported */ |
typedef enum { |
MIX_NO_FADING, |
MIX_FADING_OUT, |
MIX_FADING_IN |
} Mix_Fading; |
typedef enum { |
MUS_NONE, |
MUS_CMD, |
MUS_WAV, |
MUS_MOD, |
MUS_MID, |
MUS_OGG, |
MUS_MP3, |
MUS_MP3_MAD, |
MUS_FLAC, |
MUS_MODPLUG |
} Mix_MusicType; |
/* The internal format for a music chunk interpreted via mikmod */ |
typedef struct _Mix_Music Mix_Music; |
/* Open the mixer with a certain audio format */ |
extern DECLSPEC int SDLCALL Mix_OpenAudio(int frequency, Uint16 format, int channels, |
int chunksize); |
/* Dynamically change the number of channels managed by the mixer. |
If decreasing the number of channels, the upper channels are |
stopped. |
This function returns the new number of allocated channels. |
*/ |
extern DECLSPEC int SDLCALL Mix_AllocateChannels(int numchans); |
/* Find out what the actual audio device parameters are. |
This function returns 1 if the audio has been opened, 0 otherwise. |
*/ |
extern DECLSPEC int SDLCALL Mix_QuerySpec(int *frequency,Uint16 *format,int *channels); |
/* Load a wave file or a music (.mod .s3m .it .xm) file */ |
extern DECLSPEC Mix_Chunk * SDLCALL Mix_LoadWAV_RW(SDL_RWops *src, int freesrc); |
#define Mix_LoadWAV(file) Mix_LoadWAV_RW(SDL_RWFromFile(file, "rb"), 1) |
extern DECLSPEC Mix_Music * SDLCALL Mix_LoadMUS(const char *file); |
/* Load a music file from an SDL_RWop object (Ogg and MikMod specific currently) |
Matt Campbell (matt@campbellhome.dhs.org) April 2000 */ |
extern DECLSPEC Mix_Music * SDLCALL Mix_LoadMUS_RW(SDL_RWops *rw); |
/* Load a music file from an SDL_RWop object assuming a specific format */ |
extern DECLSPEC Mix_Music * SDLCALL Mix_LoadMUSType_RW(SDL_RWops *rw, Mix_MusicType type, int freesrc); |
/* Load a wave file of the mixer format from a memory buffer */ |
extern DECLSPEC Mix_Chunk * SDLCALL Mix_QuickLoad_WAV(Uint8 *mem); |
/* Load raw audio data of the mixer format from a memory buffer */ |
extern DECLSPEC Mix_Chunk * SDLCALL Mix_QuickLoad_RAW(Uint8 *mem, Uint32 len); |
/* Free an audio chunk previously loaded */ |
extern DECLSPEC void SDLCALL Mix_FreeChunk(Mix_Chunk *chunk); |
extern DECLSPEC void SDLCALL Mix_FreeMusic(Mix_Music *music); |
/* Get a list of chunk/music decoders that this build of SDL_mixer provides. |
This list can change between builds AND runs of the program, if external |
libraries that add functionality become available. |
You must successfully call Mix_OpenAudio() before calling these functions. |
This API is only available in SDL_mixer 1.2.9 and later. |
// usage... |
int i; |
const int total = Mix_GetNumChunkDecoders(); |
for (i = 0; i < total; i++) |
printf("Supported chunk decoder: [%s]\n", Mix_GetChunkDecoder(i)); |
Appearing in this list doesn't promise your specific audio file will |
decode...but it's handy to know if you have, say, a functioning Timidity |
install. |
These return values are static, read-only data; do not modify or free it. |
The pointers remain valid until you call Mix_CloseAudio(). |
*/ |
extern DECLSPEC int SDLCALL Mix_GetNumChunkDecoders(void); |
extern DECLSPEC const char * SDLCALL Mix_GetChunkDecoder(int index); |
extern DECLSPEC int SDLCALL Mix_GetNumMusicDecoders(void); |
extern DECLSPEC const char * SDLCALL Mix_GetMusicDecoder(int index); |
/* Find out the music format of a mixer music, or the currently playing |
music, if 'music' is NULL. |
*/ |
extern DECLSPEC Mix_MusicType SDLCALL Mix_GetMusicType(const Mix_Music *music); |
/* Set a function that is called after all mixing is performed. |
This can be used to provide real-time visual display of the audio stream |
or add a custom mixer filter for the stream data. |
*/ |
extern DECLSPEC void SDLCALL Mix_SetPostMix(void (*mix_func) |
(void *udata, Uint8 *stream, int len), void *arg); |
/* Add your own music player or additional mixer function. |
If 'mix_func' is NULL, the default music player is re-enabled. |
*/ |
extern DECLSPEC void SDLCALL Mix_HookMusic(void (*mix_func) |
(void *udata, Uint8 *stream, int len), void *arg); |
/* Add your own callback when the music has finished playing. |
This callback is only called if the music finishes naturally. |
*/ |
extern DECLSPEC void SDLCALL Mix_HookMusicFinished(void (*music_finished)(void)); |
/* Get a pointer to the user data for the current music hook */ |
extern DECLSPEC void * SDLCALL Mix_GetMusicHookData(void); |
/* |
* Add your own callback when a channel has finished playing. NULL |
* to disable callback. The callback may be called from the mixer's audio |
* callback or it could be called as a result of Mix_HaltChannel(), etc. |
* do not call SDL_LockAudio() from this callback; you will either be |
* inside the audio callback, or SDL_mixer will explicitly lock the audio |
* before calling your callback. |
*/ |
extern DECLSPEC void SDLCALL Mix_ChannelFinished(void (*channel_finished)(int channel)); |
/* Special Effects API by ryan c. gordon. (icculus@icculus.org) */ |
#define MIX_CHANNEL_POST -2 |
/* This is the format of a special effect callback: |
* |
* myeffect(int chan, void *stream, int len, void *udata); |
* |
* (chan) is the channel number that your effect is affecting. (stream) is |
* the buffer of data to work upon. (len) is the size of (stream), and |
* (udata) is a user-defined bit of data, which you pass as the last arg of |
* Mix_RegisterEffect(), and is passed back unmolested to your callback. |
* Your effect changes the contents of (stream) based on whatever parameters |
* are significant, or just leaves it be, if you prefer. You can do whatever |
* you like to the buffer, though, and it will continue in its changed state |
* down the mixing pipeline, through any other effect functions, then finally |
* to be mixed with the rest of the channels and music for the final output |
* stream. |
* |
* DO NOT EVER call SDL_LockAudio() from your callback function! |
*/ |
typedef void (*Mix_EffectFunc_t)(int chan, void *stream, int len, void *udata); |
/* |
* This is a callback that signifies that a channel has finished all its |
* loops and has completed playback. This gets called if the buffer |
* plays out normally, or if you call Mix_HaltChannel(), implicitly stop |
* a channel via Mix_AllocateChannels(), or unregister a callback while |
* it's still playing. |
* |
* DO NOT EVER call SDL_LockAudio() from your callback function! |
*/ |
typedef void (*Mix_EffectDone_t)(int chan, void *udata); |
/* Register a special effect function. At mixing time, the channel data is |
* copied into a buffer and passed through each registered effect function. |
* After it passes through all the functions, it is mixed into the final |
* output stream. The copy to buffer is performed once, then each effect |
* function performs on the output of the previous effect. Understand that |
* this extra copy to a buffer is not performed if there are no effects |
* registered for a given chunk, which saves CPU cycles, and any given |
* effect will be extra cycles, too, so it is crucial that your code run |
* fast. Also note that the data that your function is given is in the |
* format of the sound device, and not the format you gave to Mix_OpenAudio(), |
* although they may in reality be the same. This is an unfortunate but |
* necessary speed concern. Use Mix_QuerySpec() to determine if you can |
* handle the data before you register your effect, and take appropriate |
* actions. |
* You may also specify a callback (Mix_EffectDone_t) that is called when |
* the channel finishes playing. This gives you a more fine-grained control |
* than Mix_ChannelFinished(), in case you need to free effect-specific |
* resources, etc. If you don't need this, you can specify NULL. |
* You may set the callbacks before or after calling Mix_PlayChannel(). |
* Things like Mix_SetPanning() are just internal special effect functions, |
* so if you are using that, you've already incurred the overhead of a copy |
* to a separate buffer, and that these effects will be in the queue with |
* any functions you've registered. The list of registered effects for a |
* channel is reset when a chunk finishes playing, so you need to explicitly |
* set them with each call to Mix_PlayChannel*(). |
* You may also register a special effect function that is to be run after |
* final mixing occurs. The rules for these callbacks are identical to those |
* in Mix_RegisterEffect, but they are run after all the channels and the |
* music have been mixed into a single stream, whereas channel-specific |
* effects run on a given channel before any other mixing occurs. These |
* global effect callbacks are call "posteffects". Posteffects only have |
* their Mix_EffectDone_t function called when they are unregistered (since |
* the main output stream is never "done" in the same sense as a channel). |
* You must unregister them manually when you've had enough. Your callback |
* will be told that the channel being mixed is (MIX_CHANNEL_POST) if the |
* processing is considered a posteffect. |
* |
* After all these effects have finished processing, the callback registered |
* through Mix_SetPostMix() runs, and then the stream goes to the audio |
* device. |
* |
* DO NOT EVER call SDL_LockAudio() from your callback function! |
* |
* returns zero if error (no such channel), nonzero if added. |
* Error messages can be retrieved from Mix_GetError(). |
*/ |
extern DECLSPEC int SDLCALL Mix_RegisterEffect(int chan, Mix_EffectFunc_t f, |
Mix_EffectDone_t d, void *arg); |
/* You may not need to call this explicitly, unless you need to stop an |
* effect from processing in the middle of a chunk's playback. |
* Posteffects are never implicitly unregistered as they are for channels, |
* but they may be explicitly unregistered through this function by |
* specifying MIX_CHANNEL_POST for a channel. |
* returns zero if error (no such channel or effect), nonzero if removed. |
* Error messages can be retrieved from Mix_GetError(). |
*/ |
extern DECLSPEC int SDLCALL Mix_UnregisterEffect(int channel, Mix_EffectFunc_t f); |
/* You may not need to call this explicitly, unless you need to stop all |
* effects from processing in the middle of a chunk's playback. Note that |
* this will also shut off some internal effect processing, since |
* Mix_SetPanning() and others may use this API under the hood. This is |
* called internally when a channel completes playback. |
* Posteffects are never implicitly unregistered as they are for channels, |
* but they may be explicitly unregistered through this function by |
* specifying MIX_CHANNEL_POST for a channel. |
* returns zero if error (no such channel), nonzero if all effects removed. |
* Error messages can be retrieved from Mix_GetError(). |
*/ |
extern DECLSPEC int SDLCALL Mix_UnregisterAllEffects(int channel); |
#define MIX_EFFECTSMAXSPEED "MIX_EFFECTSMAXSPEED" |
/* |
* These are the internally-defined mixing effects. They use the same API that |
* effects defined in the application use, but are provided here as a |
* convenience. Some effects can reduce their quality or use more memory in |
* the name of speed; to enable this, make sure the environment variable |
* MIX_EFFECTSMAXSPEED (see above) is defined before you call |
* Mix_OpenAudio(). |
*/ |
/* Set the panning of a channel. The left and right channels are specified |
* as integers between 0 and 255, quietest to loudest, respectively. |
* |
* Technically, this is just individual volume control for a sample with |
* two (stereo) channels, so it can be used for more than just panning. |
* If you want real panning, call it like this: |
* |
* Mix_SetPanning(channel, left, 255 - left); |
* |
* ...which isn't so hard. |
* |
* Setting (channel) to MIX_CHANNEL_POST registers this as a posteffect, and |
* the panning will be done to the final mixed stream before passing it on |
* to the audio device. |
* |
* This uses the Mix_RegisterEffect() API internally, and returns without |
* registering the effect function if the audio device is not configured |
* for stereo output. Setting both (left) and (right) to 255 causes this |
* effect to be unregistered, since that is the data's normal state. |
* |
* returns zero if error (no such channel or Mix_RegisterEffect() fails), |
* nonzero if panning effect enabled. Note that an audio device in mono |
* mode is a no-op, but this call will return successful in that case. |
* Error messages can be retrieved from Mix_GetError(). |
*/ |
extern DECLSPEC int SDLCALL Mix_SetPanning(int channel, Uint8 left, Uint8 right); |
/* Set the position of a channel. (angle) is an integer from 0 to 360, that |
* specifies the location of the sound in relation to the listener. (angle) |
* will be reduced as neccesary (540 becomes 180 degrees, -100 becomes 260). |
* Angle 0 is due north, and rotates clockwise as the value increases. |
* For efficiency, the precision of this effect may be limited (angles 1 |
* through 7 might all produce the same effect, 8 through 15 are equal, etc). |
* (distance) is an integer between 0 and 255 that specifies the space |
* between the sound and the listener. The larger the number, the further |
* away the sound is. Using 255 does not guarantee that the channel will be |
* culled from the mixing process or be completely silent. For efficiency, |
* the precision of this effect may be limited (distance 0 through 5 might |
* all produce the same effect, 6 through 10 are equal, etc). Setting (angle) |
* and (distance) to 0 unregisters this effect, since the data would be |
* unchanged. |
* |
* If you need more precise positional audio, consider using OpenAL for |
* spatialized effects instead of SDL_mixer. This is only meant to be a |
* basic effect for simple "3D" games. |
* |
* If the audio device is configured for mono output, then you won't get |
* any effectiveness from the angle; however, distance attenuation on the |
* channel will still occur. While this effect will function with stereo |
* voices, it makes more sense to use voices with only one channel of sound, |
* so when they are mixed through this effect, the positioning will sound |
* correct. You can convert them to mono through SDL before giving them to |
* the mixer in the first place if you like. |
* |
* Setting (channel) to MIX_CHANNEL_POST registers this as a posteffect, and |
* the positioning will be done to the final mixed stream before passing it |
* on to the audio device. |
* |
* This is a convenience wrapper over Mix_SetDistance() and Mix_SetPanning(). |
* |
* returns zero if error (no such channel or Mix_RegisterEffect() fails), |
* nonzero if position effect is enabled. |
* Error messages can be retrieved from Mix_GetError(). |
*/ |
extern DECLSPEC int SDLCALL Mix_SetPosition(int channel, Sint16 angle, Uint8 distance); |
/* Set the "distance" of a channel. (distance) is an integer from 0 to 255 |
* that specifies the location of the sound in relation to the listener. |
* Distance 0 is overlapping the listener, and 255 is as far away as possible |
* A distance of 255 does not guarantee silence; in such a case, you might |
* want to try changing the chunk's volume, or just cull the sample from the |
* mixing process with Mix_HaltChannel(). |
* For efficiency, the precision of this effect may be limited (distances 1 |
* through 7 might all produce the same effect, 8 through 15 are equal, etc). |
* (distance) is an integer between 0 and 255 that specifies the space |
* between the sound and the listener. The larger the number, the further |
* away the sound is. |
* Setting (distance) to 0 unregisters this effect, since the data would be |
* unchanged. |
* If you need more precise positional audio, consider using OpenAL for |
* spatialized effects instead of SDL_mixer. This is only meant to be a |
* basic effect for simple "3D" games. |
* |
* Setting (channel) to MIX_CHANNEL_POST registers this as a posteffect, and |
* the distance attenuation will be done to the final mixed stream before |
* passing it on to the audio device. |
* |
* This uses the Mix_RegisterEffect() API internally. |
* |
* returns zero if error (no such channel or Mix_RegisterEffect() fails), |
* nonzero if position effect is enabled. |
* Error messages can be retrieved from Mix_GetError(). |
*/ |
extern DECLSPEC int SDLCALL Mix_SetDistance(int channel, Uint8 distance); |
/* |
* !!! FIXME : Haven't implemented, since the effect goes past the |
* end of the sound buffer. Will have to think about this. |
* --ryan. |
*/ |
#if 0 |
/* Causes an echo effect to be mixed into a sound. (echo) is the amount |
* of echo to mix. 0 is no echo, 255 is infinite (and probably not |
* what you want). |
* |
* Setting (channel) to MIX_CHANNEL_POST registers this as a posteffect, and |
* the reverbing will be done to the final mixed stream before passing it on |
* to the audio device. |
* |
* This uses the Mix_RegisterEffect() API internally. If you specify an echo |
* of zero, the effect is unregistered, as the data is already in that state. |
* |
* returns zero if error (no such channel or Mix_RegisterEffect() fails), |
* nonzero if reversing effect is enabled. |
* Error messages can be retrieved from Mix_GetError(). |
*/ |
extern no_parse_DECLSPEC int SDLCALL Mix_SetReverb(int channel, Uint8 echo); |
#endif |
/* Causes a channel to reverse its stereo. This is handy if the user has his |
* speakers hooked up backwards, or you would like to have a minor bit of |
* psychedelia in your sound code. :) Calling this function with (flip) |
* set to non-zero reverses the chunks's usual channels. If (flip) is zero, |
* the effect is unregistered. |
* |
* This uses the Mix_RegisterEffect() API internally, and thus is probably |
* more CPU intensive than having the user just plug in his speakers |
* correctly. Mix_SetReverseStereo() returns without registering the effect |
* function if the audio device is not configured for stereo output. |
* |
* If you specify MIX_CHANNEL_POST for (channel), then this the effect is used |
* on the final mixed stream before sending it on to the audio device (a |
* posteffect). |
* |
* returns zero if error (no such channel or Mix_RegisterEffect() fails), |
* nonzero if reversing effect is enabled. Note that an audio device in mono |
* mode is a no-op, but this call will return successful in that case. |
* Error messages can be retrieved from Mix_GetError(). |
*/ |
extern DECLSPEC int SDLCALL Mix_SetReverseStereo(int channel, int flip); |
/* end of effects API. --ryan. */ |
/* Reserve the first channels (0 -> n-1) for the application, i.e. don't allocate |
them dynamically to the next sample if requested with a -1 value below. |
Returns the number of reserved channels. |
*/ |
extern DECLSPEC int SDLCALL Mix_ReserveChannels(int num); |
/* Channel grouping functions */ |
/* Attach a tag to a channel. A tag can be assigned to several mixer |
channels, to form groups of channels. |
If 'tag' is -1, the tag is removed (actually -1 is the tag used to |
represent the group of all the channels). |
Returns true if everything was OK. |
*/ |
extern DECLSPEC int SDLCALL Mix_GroupChannel(int which, int tag); |
/* Assign several consecutive channels to a group */ |
extern DECLSPEC int SDLCALL Mix_GroupChannels(int from, int to, int tag); |
/* Finds the first available channel in a group of channels, |
returning -1 if none are available. |
*/ |
extern DECLSPEC int SDLCALL Mix_GroupAvailable(int tag); |
/* Returns the number of channels in a group. This is also a subtle |
way to get the total number of channels when 'tag' is -1 |
*/ |
extern DECLSPEC int SDLCALL Mix_GroupCount(int tag); |
/* Finds the "oldest" sample playing in a group of channels */ |
extern DECLSPEC int SDLCALL Mix_GroupOldest(int tag); |
/* Finds the "most recent" (i.e. last) sample playing in a group of channels */ |
extern DECLSPEC int SDLCALL Mix_GroupNewer(int tag); |
/* Play an audio chunk on a specific channel. |
If the specified channel is -1, play on the first free channel. |
If 'loops' is greater than zero, loop the sound that many times. |
If 'loops' is -1, loop inifinitely (~65000 times). |
Returns which channel was used to play the sound. |
*/ |
#define Mix_PlayChannel(channel,chunk,loops) Mix_PlayChannelTimed(channel,chunk,loops,-1) |
/* The same as above, but the sound is played at most 'ticks' milliseconds */ |
extern DECLSPEC int SDLCALL Mix_PlayChannelTimed(int channel, Mix_Chunk *chunk, int loops, int ticks); |
extern DECLSPEC int SDLCALL Mix_PlayMusic(Mix_Music *music, int loops); |
/* Fade in music or a channel over "ms" milliseconds, same semantics as the "Play" functions */ |
extern DECLSPEC int SDLCALL Mix_FadeInMusic(Mix_Music *music, int loops, int ms); |
extern DECLSPEC int SDLCALL Mix_FadeInMusicPos(Mix_Music *music, int loops, int ms, double position); |
#define Mix_FadeInChannel(channel,chunk,loops,ms) Mix_FadeInChannelTimed(channel,chunk,loops,ms,-1) |
extern DECLSPEC int SDLCALL Mix_FadeInChannelTimed(int channel, Mix_Chunk *chunk, int loops, int ms, int ticks); |
/* Set the volume in the range of 0-128 of a specific channel or chunk. |
If the specified channel is -1, set volume for all channels. |
Returns the original volume. |
If the specified volume is -1, just return the current volume. |
*/ |
extern DECLSPEC int SDLCALL Mix_Volume(int channel, int volume); |
extern DECLSPEC int SDLCALL Mix_VolumeChunk(Mix_Chunk *chunk, int volume); |
extern DECLSPEC int SDLCALL Mix_VolumeMusic(int volume); |
/* Halt playing of a particular channel */ |
extern DECLSPEC int SDLCALL Mix_HaltChannel(int channel); |
extern DECLSPEC int SDLCALL Mix_HaltGroup(int tag); |
extern DECLSPEC int SDLCALL Mix_HaltMusic(void); |
/* Change the expiration delay for a particular channel. |
The sample will stop playing after the 'ticks' milliseconds have elapsed, |
or remove the expiration if 'ticks' is -1 |
*/ |
extern DECLSPEC int SDLCALL Mix_ExpireChannel(int channel, int ticks); |
/* Halt a channel, fading it out progressively till it's silent |
The ms parameter indicates the number of milliseconds the fading |
will take. |
*/ |
extern DECLSPEC int SDLCALL Mix_FadeOutChannel(int which, int ms); |
extern DECLSPEC int SDLCALL Mix_FadeOutGroup(int tag, int ms); |
extern DECLSPEC int SDLCALL Mix_FadeOutMusic(int ms); |
/* Query the fading status of a channel */ |
extern DECLSPEC Mix_Fading SDLCALL Mix_FadingMusic(void); |
extern DECLSPEC Mix_Fading SDLCALL Mix_FadingChannel(int which); |
/* Pause/Resume a particular channel */ |
extern DECLSPEC void SDLCALL Mix_Pause(int channel); |
extern DECLSPEC void SDLCALL Mix_Resume(int channel); |
extern DECLSPEC int SDLCALL Mix_Paused(int channel); |
/* Pause/Resume the music stream */ |
extern DECLSPEC void SDLCALL Mix_PauseMusic(void); |
extern DECLSPEC void SDLCALL Mix_ResumeMusic(void); |
extern DECLSPEC void SDLCALL Mix_RewindMusic(void); |
extern DECLSPEC int SDLCALL Mix_PausedMusic(void); |
/* Set the current position in the music stream. |
This returns 0 if successful, or -1 if it failed or isn't implemented. |
This function is only implemented for MOD music formats (set pattern |
order number) and for OGG, FLAC, MP3_MAD, and MODPLUG music (set |
position in seconds), at the moment. |
*/ |
extern DECLSPEC int SDLCALL Mix_SetMusicPosition(double position); |
/* Check the status of a specific channel. |
If the specified channel is -1, check all channels. |
*/ |
extern DECLSPEC int SDLCALL Mix_Playing(int channel); |
extern DECLSPEC int SDLCALL Mix_PlayingMusic(void); |
/* Stop music and set external music playback command */ |
extern DECLSPEC int SDLCALL Mix_SetMusicCMD(const char *command); |
/* Synchro value is set by MikMod from modules while playing */ |
extern DECLSPEC int SDLCALL Mix_SetSynchroValue(int value); |
extern DECLSPEC int SDLCALL Mix_GetSynchroValue(void); |
/* Set/Get/Iterate SoundFonts paths to use by supported MIDI backends */ |
extern DECLSPEC int SDLCALL Mix_SetSoundFonts(const char *paths); |
extern DECLSPEC const char* SDLCALL Mix_GetSoundFonts(void); |
extern DECLSPEC int SDLCALL Mix_EachSoundFont(int (*function)(const char*, void*), void *data); |
/* Get the Mix_Chunk currently associated with a mixer channel |
Returns NULL if it's an invalid channel, or there's no chunk associated. |
*/ |
extern DECLSPEC Mix_Chunk * SDLCALL Mix_GetChunk(int channel); |
/* Close the mixer, halting all playing audio */ |
extern DECLSPEC void SDLCALL Mix_CloseAudio(void); |
/* We'll use SDL for reporting errors */ |
#define Mix_SetError SDL_SetError |
#define Mix_GetError SDL_GetError |
/* Ends C function definitions when using C++ */ |
#ifdef __cplusplus |
} |
#endif |
#include "close_code.h" |
#endif /* _SDL_MIXER_H */ |
/contrib/games/wolf3d/SDL_mixer/dynamic_flac.h |
---|
0,0 → 1,66 |
/* |
SDL_mixer: An audio mixer library based on the SDL library |
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org> |
This software is provided 'as-is', without any express or implied |
warranty. In no event will the authors be held liable for any damages |
arising from the use of this software. |
Permission is granted to anyone to use this software for any purpose, |
including commercial applications, and to alter it and redistribute it |
freely, subject to the following restrictions: |
1. The origin of this software must not be misrepresented; you must not |
claim that you wrote the original software. If you use this software |
in a product, an acknowledgment in the product documentation would be |
appreciated but is not required. |
2. Altered source versions must be plainly marked as such, and must not be |
misrepresented as being the original software. |
3. This notice may not be removed or altered from any source distribution. |
The following file defines all of the functions/objects used to dynamically |
link to the libFLAC library. |
~ Austen Dicken (admin@cvpcs.org) |
*/ |
#ifdef FLAC_MUSIC |
#include <FLAC/stream_decoder.h> |
typedef struct { |
int loaded; |
void *handle; |
FLAC__StreamDecoder *(*FLAC__stream_decoder_new)(); |
void (*FLAC__stream_decoder_delete)(FLAC__StreamDecoder *decoder); |
FLAC__StreamDecoderInitStatus (*FLAC__stream_decoder_init_stream)( |
FLAC__StreamDecoder *decoder, |
FLAC__StreamDecoderReadCallback read_callback, |
FLAC__StreamDecoderSeekCallback seek_callback, |
FLAC__StreamDecoderTellCallback tell_callback, |
FLAC__StreamDecoderLengthCallback length_callback, |
FLAC__StreamDecoderEofCallback eof_callback, |
FLAC__StreamDecoderWriteCallback write_callback, |
FLAC__StreamDecoderMetadataCallback metadata_callback, |
FLAC__StreamDecoderErrorCallback error_callback, |
void *client_data); |
FLAC__bool (*FLAC__stream_decoder_finish)(FLAC__StreamDecoder *decoder); |
FLAC__bool (*FLAC__stream_decoder_flush)(FLAC__StreamDecoder *decoder); |
FLAC__bool (*FLAC__stream_decoder_process_single)( |
FLAC__StreamDecoder *decoder); |
FLAC__bool (*FLAC__stream_decoder_process_until_end_of_metadata)( |
FLAC__StreamDecoder *decoder); |
FLAC__bool (*FLAC__stream_decoder_process_until_end_of_stream)( |
FLAC__StreamDecoder *decoder); |
FLAC__bool (*FLAC__stream_decoder_seek_absolute)( |
FLAC__StreamDecoder *decoder, |
FLAC__uint64 sample); |
FLAC__StreamDecoderState (*FLAC__stream_decoder_get_state)( |
const FLAC__StreamDecoder *decoder); |
} flac_loader; |
extern flac_loader flac; |
#endif /* FLAC_MUSIC */ |
extern int Mix_InitFLAC(); |
extern void Mix_QuitFLAC(); |
/contrib/games/wolf3d/SDL_mixer/dynamic_fluidsynth.h |
---|
0,0 → 1,57 |
/* |
SDL_mixer: An audio mixer library based on the SDL library |
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org> |
This software is provided 'as-is', without any express or implied |
warranty. In no event will the authors be held liable for any damages |
arising from the use of this software. |
Permission is granted to anyone to use this software for any purpose, |
including commercial applications, and to alter it and redistribute it |
freely, subject to the following restrictions: |
1. The origin of this software must not be misrepresented; you must not |
claim that you wrote the original software. If you use this software |
in a product, an acknowledgment in the product documentation would be |
appreciated but is not required. |
2. Altered source versions must be plainly marked as such, and must not be |
misrepresented as being the original software. |
3. This notice may not be removed or altered from any source distribution. |
James Le Cuirot |
chewi@aura-online.co.uk |
*/ |
#ifdef USE_FLUIDSYNTH_MIDI |
#include <fluidsynth.h> |
typedef struct { |
int loaded; |
void *handle; |
int (*delete_fluid_player)(fluid_player_t*); |
void (*delete_fluid_settings)(fluid_settings_t*); |
int (*delete_fluid_synth)(fluid_synth_t*); |
int (*fluid_player_add)(fluid_player_t*, const char*); |
int (*fluid_player_add_mem)(fluid_player_t*, const void*, size_t); |
int (*fluid_player_get_status)(fluid_player_t*); |
int (*fluid_player_play)(fluid_player_t*); |
int (*fluid_player_set_loop)(fluid_player_t*, int); |
int (*fluid_player_stop)(fluid_player_t*); |
int (*fluid_settings_setnum)(fluid_settings_t*, const char*, double); |
fluid_settings_t* (*fluid_synth_get_settings)(fluid_synth_t*); |
void (*fluid_synth_set_gain)(fluid_synth_t*, float); |
int (*fluid_synth_sfload)(fluid_synth_t*, const char*, int); |
int (*fluid_synth_write_s16)(fluid_synth_t*, int, void*, int, int, void*, int, int); |
fluid_player_t* (*new_fluid_player)(fluid_synth_t*); |
fluid_settings_t* (*new_fluid_settings)(void); |
fluid_synth_t* (*new_fluid_synth)(fluid_settings_t*); |
} fluidsynth_loader; |
extern fluidsynth_loader fluidsynth; |
#endif /* USE_FLUIDSYNTH_MIDI */ |
extern int Mix_InitFluidSynth(); |
extern void Mix_QuitFluidSynth(); |
/contrib/games/wolf3d/SDL_mixer/dynamic_mod.h |
---|
0,0 → 1,62 |
/* |
SDL_mixer: An audio mixer library based on the SDL library |
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org> |
This software is provided 'as-is', without any express or implied |
warranty. In no event will the authors be held liable for any damages |
arising from the use of this software. |
Permission is granted to anyone to use this software for any purpose, |
including commercial applications, and to alter it and redistribute it |
freely, subject to the following restrictions: |
1. The origin of this software must not be misrepresented; you must not |
claim that you wrote the original software. If you use this software |
in a product, an acknowledgment in the product documentation would be |
appreciated but is not required. |
2. Altered source versions must be plainly marked as such, and must not be |
misrepresented as being the original software. |
3. This notice may not be removed or altered from any source distribution. |
*/ |
#ifdef MOD_MUSIC |
#include "mikmod.h" |
typedef struct { |
int loaded; |
void *handle; |
void (*MikMod_Exit)(void); |
CHAR* (*MikMod_InfoDriver)(void); |
CHAR* (*MikMod_InfoLoader)(void); |
BOOL (*MikMod_Init)(CHAR*); |
void (*MikMod_RegisterAllLoaders)(void); |
void (*MikMod_RegisterDriver)(struct MDRIVER*); |
int* MikMod_errno; |
char* (*MikMod_strerror)(int); |
BOOL (*Player_Active)(void); |
void (*Player_Free)(MODULE*); |
MODULE* (*Player_LoadGeneric)(MREADER*,int,BOOL); |
void (*Player_SetPosition)(UWORD); |
void (*Player_SetVolume)(SWORD); |
void (*Player_Start)(MODULE*); |
void (*Player_Stop)(void); |
ULONG (*VC_WriteBytes)(SBYTE*,ULONG); |
struct MDRIVER* drv_nos; |
UWORD* md_device; |
UWORD* md_mixfreq; |
UWORD* md_mode; |
UBYTE* md_musicvolume; |
UBYTE* md_pansep; |
UBYTE* md_reverb; |
UBYTE* md_sndfxvolume; |
UBYTE* md_volume; |
} mikmod_loader; |
extern mikmod_loader mikmod; |
#endif /* MOD_MUSIC */ |
extern int Mix_InitMOD(); |
extern void Mix_QuitMOD(); |
/contrib/games/wolf3d/SDL_mixer/dynamic_mp3.h |
---|
0,0 → 1,47 |
/* |
SDL_mixer: An audio mixer library based on the SDL library |
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org> |
This software is provided 'as-is', without any express or implied |
warranty. In no event will the authors be held liable for any damages |
arising from the use of this software. |
Permission is granted to anyone to use this software for any purpose, |
including commercial applications, and to alter it and redistribute it |
freely, subject to the following restrictions: |
1. The origin of this software must not be misrepresented; you must not |
claim that you wrote the original software. If you use this software |
in a product, an acknowledgment in the product documentation would be |
appreciated but is not required. |
2. Altered source versions must be plainly marked as such, and must not be |
misrepresented as being the original software. |
3. This notice may not be removed or altered from any source distribution. |
*/ |
#ifdef MP3_MUSIC |
#include "smpeg.h" |
typedef struct { |
int loaded; |
void *handle; |
void (*SMPEG_actualSpec)( SMPEG *mpeg, SDL_AudioSpec *spec ); |
void (*SMPEG_delete)( SMPEG* mpeg ); |
void (*SMPEG_enableaudio)( SMPEG* mpeg, int enable ); |
void (*SMPEG_enablevideo)( SMPEG* mpeg, int enable ); |
SMPEG* (*SMPEG_new_rwops)(SDL_RWops *src, SMPEG_Info* info, int sdl_audio); |
void (*SMPEG_play)( SMPEG* mpeg ); |
int (*SMPEG_playAudio)( SMPEG *mpeg, Uint8 *stream, int len ); |
void (*SMPEG_rewind)( SMPEG* mpeg ); |
void (*SMPEG_setvolume)( SMPEG* mpeg, int volume ); |
void (*SMPEG_skip)( SMPEG* mpeg, float seconds ); |
SMPEGstatus (*SMPEG_status)( SMPEG* mpeg ); |
void (*SMPEG_stop)( SMPEG* mpeg ); |
} smpeg_loader; |
extern smpeg_loader smpeg; |
#endif /* MUSIC_MP3 */ |
extern int Mix_InitMP3(); |
extern void Mix_QuitMP3(); |
/contrib/games/wolf3d/SDL_mixer/dynamic_ogg.h |
---|
0,0 → 1,53 |
/* |
SDL_mixer: An audio mixer library based on the SDL library |
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org> |
This software is provided 'as-is', without any express or implied |
warranty. In no event will the authors be held liable for any damages |
arising from the use of this software. |
Permission is granted to anyone to use this software for any purpose, |
including commercial applications, and to alter it and redistribute it |
freely, subject to the following restrictions: |
1. The origin of this software must not be misrepresented; you must not |
claim that you wrote the original software. If you use this software |
in a product, an acknowledgment in the product documentation would be |
appreciated but is not required. |
2. Altered source versions must be plainly marked as such, and must not be |
misrepresented as being the original software. |
3. This notice may not be removed or altered from any source distribution. |
*/ |
#ifdef OGG_MUSIC |
#ifdef OGG_USE_TREMOR |
#include <tremor/ivorbisfile.h> |
#else |
#include <vorbis/vorbisfile.h> |
#endif |
typedef struct { |
int loaded; |
void *handle; |
int (*ov_clear)(OggVorbis_File *vf); |
vorbis_info *(*ov_info)(OggVorbis_File *vf,int link); |
int (*ov_open_callbacks)(void *datasource, OggVorbis_File *vf, char *initial, long ibytes, ov_callbacks callbacks); |
ogg_int64_t (*ov_pcm_total)(OggVorbis_File *vf,int i); |
#ifdef OGG_USE_TREMOR |
long (*ov_read)(OggVorbis_File *vf,char *buffer,int length, int *bitstream); |
#else |
long (*ov_read)(OggVorbis_File *vf,char *buffer,int length, int bigendianp,int word,int sgned,int *bitstream); |
#endif |
#ifdef OGG_USE_TREMOR |
int (*ov_time_seek)(OggVorbis_File *vf,ogg_int64_t pos); |
#else |
int (*ov_time_seek)(OggVorbis_File *vf,double pos); |
#endif |
} vorbis_loader; |
extern vorbis_loader vorbis; |
#endif /* OGG_MUSIC */ |
extern int Mix_InitOgg(); |
extern void Mix_QuitOgg(); |
/contrib/games/wolf3d/SDL_mixer/effect_position.c |
---|
0,0 → 1,1619 |
/* |
SDL_mixer: An audio mixer library based on the SDL library |
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org> |
This software is provided 'as-is', without any express or implied |
warranty. In no event will the authors be held liable for any damages |
arising from the use of this software. |
Permission is granted to anyone to use this software for any purpose, |
including commercial applications, and to alter it and redistribute it |
freely, subject to the following restrictions: |
1. The origin of this software must not be misrepresented; you must not |
claim that you wrote the original software. If you use this software |
in a product, an acknowledgment in the product documentation would be |
appreciated but is not required. |
2. Altered source versions must be plainly marked as such, and must not be |
misrepresented as being the original software. |
3. This notice may not be removed or altered from any source distribution. |
This file by Ryan C. Gordon (icculus@icculus.org) |
These are some internally supported special effects that use SDL_mixer's |
effect callback API. They are meant for speed over quality. :) |
*/ |
/* $Id$ */ |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
#include "SDL.h" |
#include "SDL_mixer.h" |
#include "SDL_endian.h" |
#define __MIX_INTERNAL_EFFECT__ |
#include "effects_internal.h" |
/* profile code: |
#include <sys/time.h> |
#include <unistd.h> |
struct timeval tv1; |
struct timeval tv2; |
gettimeofday(&tv1, NULL); |
... do your thing here ... |
gettimeofday(&tv2, NULL); |
printf("%ld\n", tv2.tv_usec - tv1.tv_usec); |
*/ |
/* |
* Positional effects...panning, distance attenuation, etc. |
*/ |
typedef struct _Eff_positionargs |
{ |
volatile float left_f; |
volatile float right_f; |
volatile Uint8 left_u8; |
volatile Uint8 right_u8; |
volatile float left_rear_f; |
volatile float right_rear_f; |
volatile float center_f; |
volatile float lfe_f; |
volatile Uint8 left_rear_u8; |
volatile Uint8 right_rear_u8; |
volatile Uint8 center_u8; |
volatile Uint8 lfe_u8; |
volatile float distance_f; |
volatile Uint8 distance_u8; |
volatile Sint16 room_angle; |
volatile int in_use; |
volatile int channels; |
} position_args; |
static position_args **pos_args_array = NULL; |
static position_args *pos_args_global = NULL; |
static int position_channels = 0; |
void _Eff_PositionDeinit(void) |
{ |
int i; |
for (i = 0; i < position_channels; i++) { |
SDL_free(pos_args_array[i]); |
} |
position_channels = 0; |
SDL_free(pos_args_global); |
pos_args_global = NULL; |
SDL_free(pos_args_array); |
pos_args_array = NULL; |
} |
/* This just frees up the callback-specific data. */ |
static void _Eff_PositionDone(int channel, void *udata) |
{ |
if (channel < 0) { |
if (pos_args_global != NULL) { |
SDL_free(pos_args_global); |
pos_args_global = NULL; |
} |
} |
else if (pos_args_array[channel] != NULL) { |
SDL_free(pos_args_array[channel]); |
pos_args_array[channel] = NULL; |
} |
} |
static void _Eff_position_u8(int chan, void *stream, int len, void *udata) |
{ |
volatile position_args *args = (volatile position_args *) udata; |
Uint8 *ptr = (Uint8 *) stream; |
int i; |
/* |
* if there's only a mono channnel (the only way we wouldn't have |
* a len divisible by 2 here), then left_f and right_f are always |
* 1.0, and are therefore throwaways. |
*/ |
if (len % sizeof (Uint16) != 0) { |
*ptr = (Uint8) (((float) *ptr) * args->distance_f); |
ptr++; |
len--; |
} |
if (args->room_angle == 180) |
for (i = 0; i < len; i += sizeof (Uint8) * 2) { |
/* must adjust the sample so that 0 is the center */ |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->right_f) * args->distance_f) + 128); |
ptr++; |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->left_f) * args->distance_f) + 128); |
ptr++; |
} |
else for (i = 0; i < len; i += sizeof (Uint8) * 2) { |
/* must adjust the sample so that 0 is the center */ |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->left_f) * args->distance_f) + 128); |
ptr++; |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->right_f) * args->distance_f) + 128); |
ptr++; |
} |
} |
static void _Eff_position_u8_c4(int chan, void *stream, int len, void *udata) |
{ |
volatile position_args *args = (volatile position_args *) udata; |
Uint8 *ptr = (Uint8 *) stream; |
int i; |
/* |
* if there's only a mono channnel (the only way we wouldn't have |
* a len divisible by 2 here), then left_f and right_f are always |
* 1.0, and are therefore throwaways. |
*/ |
if (len % sizeof (Uint16) != 0) { |
*ptr = (Uint8) (((float) *ptr) * args->distance_f); |
ptr++; |
len--; |
} |
if (args->room_angle == 0) |
for (i = 0; i < len; i += sizeof (Uint8) * 6) { |
/* must adjust the sample so that 0 is the center */ |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->left_f) * args->distance_f) + 128); |
ptr++; |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->right_f) * args->distance_f) + 128); |
ptr++; |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->left_rear_f) * args->distance_f) + 128); |
ptr++; |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->right_rear_f) * args->distance_f) + 128); |
ptr++; |
} |
else if (args->room_angle == 90) |
for (i = 0; i < len; i += sizeof (Uint8) * 6) { |
/* must adjust the sample so that 0 is the center */ |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->right_f) * args->distance_f) + 128); |
ptr++; |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->right_rear_f) * args->distance_f) + 128); |
ptr++; |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->left_f) * args->distance_f) + 128); |
ptr++; |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->left_rear_f) * args->distance_f) + 128); |
ptr++; |
} |
else if (args->room_angle == 180) |
for (i = 0; i < len; i += sizeof (Uint8) * 6) { |
/* must adjust the sample so that 0 is the center */ |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->right_rear_f) * args->distance_f) + 128); |
ptr++; |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->left_rear_f) * args->distance_f) + 128); |
ptr++; |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->right_f) * args->distance_f) + 128); |
ptr++; |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->left_f) * args->distance_f) + 128); |
ptr++; |
} |
else if (args->room_angle == 270) |
for (i = 0; i < len; i += sizeof (Uint8) * 6) { |
/* must adjust the sample so that 0 is the center */ |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->left_rear_f) * args->distance_f) + 128); |
ptr++; |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->left_f) * args->distance_f) + 128); |
ptr++; |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->right_rear_f) * args->distance_f) + 128); |
ptr++; |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->right_f) * args->distance_f) + 128); |
ptr++; |
} |
} |
static void _Eff_position_u8_c6(int chan, void *stream, int len, void *udata) |
{ |
volatile position_args *args = (volatile position_args *) udata; |
Uint8 *ptr = (Uint8 *) stream; |
int i; |
/* |
* if there's only a mono channnel (the only way we wouldn't have |
* a len divisible by 2 here), then left_f and right_f are always |
* 1.0, and are therefore throwaways. |
*/ |
if (len % sizeof (Uint16) != 0) { |
*ptr = (Uint8) (((float) *ptr) * args->distance_f); |
ptr++; |
len--; |
} |
if (args->room_angle == 0) |
for (i = 0; i < len; i += sizeof (Uint8) * 6) { |
/* must adjust the sample so that 0 is the center */ |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->left_f) * args->distance_f) + 128); |
ptr++; |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->right_f) * args->distance_f) + 128); |
ptr++; |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->left_rear_f) * args->distance_f) + 128); |
ptr++; |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->right_rear_f) * args->distance_f) + 128); |
ptr++; |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->center_f) * args->distance_f) + 128); |
ptr++; |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->lfe_f) * args->distance_f) + 128); |
ptr++; |
} |
else if (args->room_angle == 90) |
for (i = 0; i < len; i += sizeof (Uint8) * 6) { |
/* must adjust the sample so that 0 is the center */ |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->right_f) * args->distance_f) + 128); |
ptr++; |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->right_rear_f) * args->distance_f) + 128); |
ptr++; |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->left_f) * args->distance_f) + 128); |
ptr++; |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->left_rear_f) * args->distance_f) + 128); |
ptr++; |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->right_rear_f) * args->distance_f/2) + 128) |
+ (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->right_f) * args->distance_f/2) + 128); |
ptr++; |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->lfe_f) * args->distance_f) + 128); |
ptr++; |
} |
else if (args->room_angle == 180) |
for (i = 0; i < len; i += sizeof (Uint8) * 6) { |
/* must adjust the sample so that 0 is the center */ |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->right_rear_f) * args->distance_f) + 128); |
ptr++; |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->left_rear_f) * args->distance_f) + 128); |
ptr++; |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->right_f) * args->distance_f) + 128); |
ptr++; |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->left_f) * args->distance_f) + 128); |
ptr++; |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->right_rear_f) * args->distance_f/2) + 128) |
+ (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->left_rear_f) * args->distance_f/2) + 128); |
ptr++; |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->lfe_f) * args->distance_f) + 128); |
ptr++; |
} |
else if (args->room_angle == 270) |
for (i = 0; i < len; i += sizeof (Uint8) * 6) { |
/* must adjust the sample so that 0 is the center */ |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->left_rear_f) * args->distance_f) + 128); |
ptr++; |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->left_f) * args->distance_f) + 128); |
ptr++; |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->right_rear_f) * args->distance_f) + 128); |
ptr++; |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->right_f) * args->distance_f) + 128); |
ptr++; |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->left_f) * args->distance_f/2) + 128) |
+ (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->left_rear_f) * args->distance_f/2) + 128); |
ptr++; |
*ptr = (Uint8) ((Sint8) ((((float) (Sint8) (*ptr - 128)) |
* args->lfe_f) * args->distance_f) + 128); |
ptr++; |
} |
} |
/* |
* This one runs about 10.1 times faster than the non-table version, with |
* no loss in quality. It does, however, require 64k of memory for the |
* lookup table. Also, this will only update position information once per |
* call; the non-table version always checks the arguments for each sample, |
* in case the user has called Mix_SetPanning() or whatnot again while this |
* callback is running. |
*/ |
static void _Eff_position_table_u8(int chan, void *stream, int len, void *udata) |
{ |
volatile position_args *args = (volatile position_args *) udata; |
Uint8 *ptr = (Uint8 *) stream; |
Uint32 *p; |
int i; |
Uint8 *l = ((Uint8 *) _Eff_volume_table) + (256 * args->left_u8); |
Uint8 *r = ((Uint8 *) _Eff_volume_table) + (256 * args->right_u8); |
Uint8 *d = ((Uint8 *) _Eff_volume_table) + (256 * args->distance_u8); |
if (args->room_angle == 180) { |
Uint8 *temp = l; |
l = r; |
r = temp; |
} |
/* |
* if there's only a mono channnel, then l[] and r[] are always |
* volume 255, and are therefore throwaways. Still, we have to |
* be sure not to overrun the audio buffer... |
*/ |
while (len % sizeof (Uint32) != 0) { |
*ptr = d[l[*ptr]]; |
ptr++; |
if (args->channels > 1) { |
*ptr = d[r[*ptr]]; |
ptr++; |
} |
len -= args->channels; |
} |
p = (Uint32 *) ptr; |
for (i = 0; i < len; i += sizeof (Uint32)) { |
#if (SDL_BYTEORDER == SDL_BIG_ENDIAN) |
*p = (d[l[(*p & 0xFF000000) >> 24]] << 24) | |
(d[r[(*p & 0x00FF0000) >> 16]] << 16) | |
(d[l[(*p & 0x0000FF00) >> 8]] << 8) | |
(d[r[(*p & 0x000000FF) ]] ) ; |
#else |
*p = (d[r[(*p & 0xFF000000) >> 24]] << 24) | |
(d[l[(*p & 0x00FF0000) >> 16]] << 16) | |
(d[r[(*p & 0x0000FF00) >> 8]] << 8) | |
(d[l[(*p & 0x000000FF) ]] ) ; |
#endif |
++p; |
} |
} |
static void _Eff_position_s8(int chan, void *stream, int len, void *udata) |
{ |
volatile position_args *args = (volatile position_args *) udata; |
Sint8 *ptr = (Sint8 *) stream; |
int i; |
/* |
* if there's only a mono channnel (the only way we wouldn't have |
* a len divisible by 2 here), then left_f and right_f are always |
* 1.0, and are therefore throwaways. |
*/ |
if (len % sizeof (Sint16) != 0) { |
*ptr = (Sint8) (((float) *ptr) * args->distance_f); |
ptr++; |
len--; |
} |
if (args->room_angle == 180) |
for (i = 0; i < len; i += sizeof (Sint8) * 2) { |
*ptr = (Sint8)((((float) *ptr) * args->right_f) * args->distance_f); |
ptr++; |
*ptr = (Sint8)((((float) *ptr) * args->left_f) * args->distance_f); |
ptr++; |
} |
else |
for (i = 0; i < len; i += sizeof (Sint8) * 2) { |
*ptr = (Sint8)((((float) *ptr) * args->left_f) * args->distance_f); |
ptr++; |
*ptr = (Sint8)((((float) *ptr) * args->right_f) * args->distance_f); |
ptr++; |
} |
} |
static void _Eff_position_s8_c4(int chan, void *stream, int len, void *udata) |
{ |
volatile position_args *args = (volatile position_args *) udata; |
Sint8 *ptr = (Sint8 *) stream; |
int i; |
/* |
* if there's only a mono channnel (the only way we wouldn't have |
* a len divisible by 2 here), then left_f and right_f are always |
* 1.0, and are therefore throwaways. |
*/ |
if (len % sizeof (Sint16) != 0) { |
*ptr = (Sint8) (((float) *ptr) * args->distance_f); |
ptr++; |
len--; |
} |
for (i = 0; i < len; i += sizeof (Sint8) * 4) { |
switch (args->room_angle) { |
case 0: |
*ptr = (Sint8)((((float) *ptr) * args->left_f) * args->distance_f); ptr++; |
*ptr = (Sint8)((((float) *ptr) * args->right_f) * args->distance_f); ptr++; |
*ptr = (Sint8)((((float) *ptr) * args->left_rear_f) * args->distance_f); ptr++; |
*ptr = (Sint8)((((float) *ptr) * args->right_rear_f) * args->distance_f); ptr++; |
break; |
case 90: |
*ptr = (Sint8)((((float) *ptr) * args->right_f) * args->distance_f); ptr++; |
*ptr = (Sint8)((((float) *ptr) * args->right_rear_f) * args->distance_f); ptr++; |
*ptr = (Sint8)((((float) *ptr) * args->left_f) * args->distance_f); ptr++; |
*ptr = (Sint8)((((float) *ptr) * args->left_rear_f) * args->distance_f); ptr++; |
break; |
case 180: |
*ptr = (Sint8)((((float) *ptr) * args->right_rear_f) * args->distance_f); ptr++; |
*ptr = (Sint8)((((float) *ptr) * args->left_rear_f) * args->distance_f); ptr++; |
*ptr = (Sint8)((((float) *ptr) * args->right_f) * args->distance_f); ptr++; |
*ptr = (Sint8)((((float) *ptr) * args->left_f) * args->distance_f); ptr++; |
break; |
case 270: |
*ptr = (Sint8)((((float) *ptr) * args->left_rear_f) * args->distance_f); ptr++; |
*ptr = (Sint8)((((float) *ptr) * args->left_f) * args->distance_f); ptr++; |
*ptr = (Sint8)((((float) *ptr) * args->right_rear_f) * args->distance_f); ptr++; |
*ptr = (Sint8)((((float) *ptr) * args->right_f) * args->distance_f); ptr++; |
break; |
} |
} |
} |
static void _Eff_position_s8_c6(int chan, void *stream, int len, void *udata) |
{ |
volatile position_args *args = (volatile position_args *) udata; |
Sint8 *ptr = (Sint8 *) stream; |
int i; |
/* |
* if there's only a mono channnel (the only way we wouldn't have |
* a len divisible by 2 here), then left_f and right_f are always |
* 1.0, and are therefore throwaways. |
*/ |
if (len % sizeof (Sint16) != 0) { |
*ptr = (Sint8) (((float) *ptr) * args->distance_f); |
ptr++; |
len--; |
} |
for (i = 0; i < len; i += sizeof (Sint8) * 6) { |
switch (args->room_angle) { |
case 0: |
*ptr = (Sint8)((((float) *ptr) * args->left_f) * args->distance_f); ptr++; |
*ptr = (Sint8)((((float) *ptr) * args->right_f) * args->distance_f); ptr++; |
*ptr = (Sint8)((((float) *ptr) * args->left_rear_f) * args->distance_f); ptr++; |
*ptr = (Sint8)((((float) *ptr) * args->right_rear_f) * args->distance_f); ptr++; |
*ptr = (Sint8)((((float) *ptr) * args->center_f) * args->distance_f); ptr++; |
*ptr = (Sint8)((((float) *ptr) * args->lfe_f) * args->distance_f); ptr++; |
break; |
case 90: |
*ptr = (Sint8)((((float) *ptr) * args->right_f) * args->distance_f); ptr++; |
*ptr = (Sint8)((((float) *ptr) * args->right_rear_f) * args->distance_f); ptr++; |
*ptr = (Sint8)((((float) *ptr) * args->left_f) * args->distance_f); ptr++; |
*ptr = (Sint8)((((float) *ptr) * args->left_rear_f) * args->distance_f); ptr++; |
*ptr = (Sint8)((((float) *ptr) * args->right_rear_f) * args->distance_f / 2) |
+ (Sint8)((((float) *ptr) * args->right_f) * args->distance_f / 2); ptr++; |
*ptr = (Sint8)((((float) *ptr) * args->lfe_f) * args->distance_f); ptr++; |
break; |
case 180: |
*ptr = (Sint8)((((float) *ptr) * args->right_rear_f) * args->distance_f); ptr++; |
*ptr = (Sint8)((((float) *ptr) * args->left_rear_f) * args->distance_f); ptr++; |
*ptr = (Sint8)((((float) *ptr) * args->right_f) * args->distance_f); ptr++; |
*ptr = (Sint8)((((float) *ptr) * args->left_f) * args->distance_f); ptr++; |
*ptr = (Sint8)((((float) *ptr) * args->right_rear_f) * args->distance_f / 2) |
+ (Sint8)((((float) *ptr) * args->left_rear_f) * args->distance_f / 2); ptr++; |
*ptr = (Sint8)((((float) *ptr) * args->lfe_f) * args->distance_f); ptr++; |
break; |
case 270: |
*ptr = (Sint8)((((float) *ptr) * args->left_rear_f) * args->distance_f); ptr++; |
*ptr = (Sint8)((((float) *ptr) * args->left_f) * args->distance_f); ptr++; |
*ptr = (Sint8)((((float) *ptr) * args->right_rear_f) * args->distance_f); ptr++; |
*ptr = (Sint8)((((float) *ptr) * args->right_f) * args->distance_f); ptr++; |
*ptr = (Sint8)((((float) *ptr) * args->left_f) * args->distance_f / 2) |
+ (Sint8)((((float) *ptr) * args->left_rear_f) * args->distance_f / 2); ptr++; |
*ptr = (Sint8)((((float) *ptr) * args->lfe_f) * args->distance_f); ptr++; |
break; |
} |
} |
} |
/* |
* This one runs about 10.1 times faster than the non-table version, with |
* no loss in quality. It does, however, require 64k of memory for the |
* lookup table. Also, this will only update position information once per |
* call; the non-table version always checks the arguments for each sample, |
* in case the user has called Mix_SetPanning() or whatnot again while this |
* callback is running. |
*/ |
static void _Eff_position_table_s8(int chan, void *stream, int len, void *udata) |
{ |
volatile position_args *args = (volatile position_args *) udata; |
Sint8 *ptr = (Sint8 *) stream; |
Uint32 *p; |
int i; |
Sint8 *l = ((Sint8 *) _Eff_volume_table) + (256 * args->left_u8); |
Sint8 *r = ((Sint8 *) _Eff_volume_table) + (256 * args->right_u8); |
Sint8 *d = ((Sint8 *) _Eff_volume_table) + (256 * args->distance_u8); |
if (args->room_angle == 180) { |
Sint8 *temp = l; |
l = r; |
r = temp; |
} |
while (len % sizeof (Uint32) != 0) { |
*ptr = d[l[*ptr]]; |
ptr++; |
if (args->channels > 1) { |
*ptr = d[r[*ptr]]; |
ptr++; |
} |
len -= args->channels; |
} |
p = (Uint32 *) ptr; |
for (i = 0; i < len; i += sizeof (Uint32)) { |
#if (SDL_BYTEORDER == SDL_BIG_ENDIAN) |
*p = (d[l[((Sint16)(Sint8)((*p & 0xFF000000) >> 24))+128]] << 24) | |
(d[r[((Sint16)(Sint8)((*p & 0x00FF0000) >> 16))+128]] << 16) | |
(d[l[((Sint16)(Sint8)((*p & 0x0000FF00) >> 8))+128]] << 8) | |
(d[r[((Sint16)(Sint8)((*p & 0x000000FF) ))+128]] ) ; |
#else |
*p = (d[r[((Sint16)(Sint8)((*p & 0xFF000000) >> 24))+128]] << 24) | |
(d[l[((Sint16)(Sint8)((*p & 0x00FF0000) >> 16))+128]] << 16) | |
(d[r[((Sint16)(Sint8)((*p & 0x0000FF00) >> 8))+128]] << 8) | |
(d[l[((Sint16)(Sint8)((*p & 0x000000FF) ))+128]] ) ; |
#endif |
++p; |
} |
} |
/* !!! FIXME : Optimize the code for 16-bit samples? */ |
static void _Eff_position_u16lsb(int chan, void *stream, int len, void *udata) |
{ |
volatile position_args *args = (volatile position_args *) udata; |
Uint16 *ptr = (Uint16 *) stream; |
int i; |
for (i = 0; i < len; i += sizeof (Uint16) * 2) { |
Sint16 sampl = (Sint16) (SDL_SwapLE16(*(ptr+0)) - 32768); |
Sint16 sampr = (Sint16) (SDL_SwapLE16(*(ptr+1)) - 32768); |
Uint16 swapl = (Uint16) ((Sint16) (((float) sampl * args->left_f) |
* args->distance_f) + 32768); |
Uint16 swapr = (Uint16) ((Sint16) (((float) sampr * args->right_f) |
* args->distance_f) + 32768); |
if (args->room_angle == 180) { |
*(ptr++) = (Uint16) SDL_SwapLE16(swapr); |
*(ptr++) = (Uint16) SDL_SwapLE16(swapl); |
} |
else { |
*(ptr++) = (Uint16) SDL_SwapLE16(swapl); |
*(ptr++) = (Uint16) SDL_SwapLE16(swapr); |
} |
} |
} |
static void _Eff_position_u16lsb_c4(int chan, void *stream, int len, void *udata) |
{ |
volatile position_args *args = (volatile position_args *) udata; |
Uint16 *ptr = (Uint16 *) stream; |
int i; |
for (i = 0; i < len; i += sizeof (Uint16) * 4) { |
Sint16 sampl = (Sint16) (SDL_SwapLE16(*(ptr+0)) - 32768); |
Sint16 sampr = (Sint16) (SDL_SwapLE16(*(ptr+1)) - 32768); |
Sint16 samplr = (Sint16) (SDL_SwapLE16(*(ptr+2)) - 32768); |
Sint16 samprr = (Sint16) (SDL_SwapLE16(*(ptr+3)) - 32768); |
Uint16 swapl = (Uint16) ((Sint16) (((float) sampl * args->left_f) |
* args->distance_f) + 32768); |
Uint16 swapr = (Uint16) ((Sint16) (((float) sampr * args->right_f) |
* args->distance_f) + 32768); |
Uint16 swaplr = (Uint16) ((Sint16) (((float) samplr * args->left_rear_f) |
* args->distance_f) + 32768); |
Uint16 swaprr = (Uint16) ((Sint16) (((float) samprr * args->right_rear_f) |
* args->distance_f) + 32768); |
switch (args->room_angle) { |
case 0: |
*(ptr++) = (Uint16) SDL_SwapLE16(swapl); |
*(ptr++) = (Uint16) SDL_SwapLE16(swapr); |
*(ptr++) = (Uint16) SDL_SwapLE16(swaplr); |
*(ptr++) = (Uint16) SDL_SwapLE16(swaprr); |
break; |
case 90: |
*(ptr++) = (Uint16) SDL_SwapLE16(swapr); |
*(ptr++) = (Uint16) SDL_SwapLE16(swaprr); |
*(ptr++) = (Uint16) SDL_SwapLE16(swapl); |
*(ptr++) = (Uint16) SDL_SwapLE16(swaplr); |
break; |
case 180: |
*(ptr++) = (Uint16) SDL_SwapLE16(swaprr); |
*(ptr++) = (Uint16) SDL_SwapLE16(swaplr); |
*(ptr++) = (Uint16) SDL_SwapLE16(swapr); |
*(ptr++) = (Uint16) SDL_SwapLE16(swapl); |
break; |
case 270: |
*(ptr++) = (Uint16) SDL_SwapLE16(swaplr); |
*(ptr++) = (Uint16) SDL_SwapLE16(swapl); |
*(ptr++) = (Uint16) SDL_SwapLE16(swaprr); |
*(ptr++) = (Uint16) SDL_SwapLE16(swapr); |
break; |
} |
} |
} |
static void _Eff_position_u16lsb_c6(int chan, void *stream, int len, void *udata) |
{ |
volatile position_args *args = (volatile position_args *) udata; |
Uint16 *ptr = (Uint16 *) stream; |
int i; |
for (i = 0; i < len; i += sizeof (Uint16) * 6) { |
Sint16 sampl = (Sint16) (SDL_SwapLE16(*(ptr+0)) - 32768); |
Sint16 sampr = (Sint16) (SDL_SwapLE16(*(ptr+1)) - 32768); |
Sint16 samplr = (Sint16) (SDL_SwapLE16(*(ptr+2)) - 32768); |
Sint16 samprr = (Sint16) (SDL_SwapLE16(*(ptr+3)) - 32768); |
Sint16 sampce = (Sint16) (SDL_SwapLE16(*(ptr+4)) - 32768); |
Sint16 sampwf = (Sint16) (SDL_SwapLE16(*(ptr+5)) - 32768); |
Uint16 swapl = (Uint16) ((Sint16) (((float) sampl * args->left_f) |
* args->distance_f) + 32768); |
Uint16 swapr = (Uint16) ((Sint16) (((float) sampr * args->right_f) |
* args->distance_f) + 32768); |
Uint16 swaplr = (Uint16) ((Sint16) (((float) samplr * args->left_rear_f) |
* args->distance_f) + 32768); |
Uint16 swaprr = (Uint16) ((Sint16) (((float) samprr * args->right_rear_f) |
* args->distance_f) + 32768); |
Uint16 swapce = (Uint16) ((Sint16) (((float) sampce * args->center_f) |
* args->distance_f) + 32768); |
Uint16 swapwf = (Uint16) ((Sint16) (((float) sampwf * args->lfe_f) |
* args->distance_f) + 32768); |
switch (args->room_angle) { |
case 0: |
*(ptr++) = (Uint16) SDL_SwapLE16(swapl); |
*(ptr++) = (Uint16) SDL_SwapLE16(swapr); |
*(ptr++) = (Uint16) SDL_SwapLE16(swaplr); |
*(ptr++) = (Uint16) SDL_SwapLE16(swaprr); |
*(ptr++) = (Uint16) SDL_SwapLE16(swapce); |
*(ptr++) = (Uint16) SDL_SwapLE16(swapwf); |
break; |
case 90: |
*(ptr++) = (Uint16) SDL_SwapLE16(swapr); |
*(ptr++) = (Uint16) SDL_SwapLE16(swaprr); |
*(ptr++) = (Uint16) SDL_SwapLE16(swapl); |
*(ptr++) = (Uint16) SDL_SwapLE16(swaplr); |
*(ptr++) = (Uint16) SDL_SwapLE16(swapr)/2 + (Uint16) SDL_SwapLE16(swaprr)/2; |
*(ptr++) = (Uint16) SDL_SwapLE16(swapwf); |
break; |
case 180: |
*(ptr++) = (Uint16) SDL_SwapLE16(swaprr); |
*(ptr++) = (Uint16) SDL_SwapLE16(swaplr); |
*(ptr++) = (Uint16) SDL_SwapLE16(swapr); |
*(ptr++) = (Uint16) SDL_SwapLE16(swapl); |
*(ptr++) = (Uint16) SDL_SwapLE16(swaprr)/2 + (Uint16) SDL_SwapLE16(swaplr)/2; |
*(ptr++) = (Uint16) SDL_SwapLE16(swapwf); |
break; |
case 270: |
*(ptr++) = (Uint16) SDL_SwapLE16(swaplr); |
*(ptr++) = (Uint16) SDL_SwapLE16(swapl); |
*(ptr++) = (Uint16) SDL_SwapLE16(swaprr); |
*(ptr++) = (Uint16) SDL_SwapLE16(swapr); |
*(ptr++) = (Uint16) SDL_SwapLE16(swapl)/2 + (Uint16) SDL_SwapLE16(swaplr)/2; |
*(ptr++) = (Uint16) SDL_SwapLE16(swapwf); |
break; |
} |
} |
} |
static void _Eff_position_s16lsb(int chan, void *stream, int len, void *udata) |
{ |
/* 16 signed bits (lsb) * 2 channels. */ |
volatile position_args *args = (volatile position_args *) udata; |
Sint16 *ptr = (Sint16 *) stream; |
int i; |
#if 0 |
if (len % (sizeof(Sint16) * 2)) { |
fprintf(stderr,"Not an even number of frames! len=%d\n", len); |
return; |
} |
#endif |
for (i = 0; i < len; i += sizeof (Sint16) * 2) { |
Sint16 swapl = (Sint16) ((((float) (Sint16) SDL_SwapLE16(*(ptr+0))) * |
args->left_f) * args->distance_f); |
Sint16 swapr = (Sint16) ((((float) (Sint16) SDL_SwapLE16(*(ptr+1))) * |
args->right_f) * args->distance_f); |
if (args->room_angle == 180) { |
*(ptr++) = (Sint16) SDL_SwapLE16(swapr); |
*(ptr++) = (Sint16) SDL_SwapLE16(swapl); |
} |
else { |
*(ptr++) = (Sint16) SDL_SwapLE16(swapl); |
*(ptr++) = (Sint16) SDL_SwapLE16(swapr); |
} |
} |
} |
static void _Eff_position_s16lsb_c4(int chan, void *stream, int len, void *udata) |
{ |
/* 16 signed bits (lsb) * 4 channels. */ |
volatile position_args *args = (volatile position_args *) udata; |
Sint16 *ptr = (Sint16 *) stream; |
int i; |
for (i = 0; i < len; i += sizeof (Sint16) * 4) { |
Sint16 swapl = (Sint16) ((((float) (Sint16) SDL_SwapLE16(*(ptr+0))) * |
args->left_f) * args->distance_f); |
Sint16 swapr = (Sint16) ((((float) (Sint16) SDL_SwapLE16(*(ptr+1))) * |
args->right_f) * args->distance_f); |
Sint16 swaplr = (Sint16) ((((float) (Sint16) SDL_SwapLE16(*(ptr+1))) * |
args->left_rear_f) * args->distance_f); |
Sint16 swaprr = (Sint16) ((((float) (Sint16) SDL_SwapLE16(*(ptr+2))) * |
args->right_rear_f) * args->distance_f); |
switch (args->room_angle) { |
case 0: |
*(ptr++) = (Sint16) SDL_SwapLE16(swapl); |
*(ptr++) = (Sint16) SDL_SwapLE16(swapr); |
*(ptr++) = (Sint16) SDL_SwapLE16(swaplr); |
*(ptr++) = (Sint16) SDL_SwapLE16(swaprr); |
break; |
case 90: |
*(ptr++) = (Sint16) SDL_SwapLE16(swapr); |
*(ptr++) = (Sint16) SDL_SwapLE16(swaprr); |
*(ptr++) = (Sint16) SDL_SwapLE16(swapl); |
*(ptr++) = (Sint16) SDL_SwapLE16(swaplr); |
break; |
case 180: |
*(ptr++) = (Sint16) SDL_SwapLE16(swaprr); |
*(ptr++) = (Sint16) SDL_SwapLE16(swaplr); |
*(ptr++) = (Sint16) SDL_SwapLE16(swapr); |
*(ptr++) = (Sint16) SDL_SwapLE16(swapl); |
break; |
case 270: |
*(ptr++) = (Sint16) SDL_SwapLE16(swaplr); |
*(ptr++) = (Sint16) SDL_SwapLE16(swapl); |
*(ptr++) = (Sint16) SDL_SwapLE16(swaprr); |
*(ptr++) = (Sint16) SDL_SwapLE16(swapr); |
break; |
} |
} |
} |
static void _Eff_position_s16lsb_c6(int chan, void *stream, int len, void *udata) |
{ |
/* 16 signed bits (lsb) * 6 channels. */ |
volatile position_args *args = (volatile position_args *) udata; |
Sint16 *ptr = (Sint16 *) stream; |
int i; |
for (i = 0; i < len; i += sizeof (Sint16) * 6) { |
Sint16 swapl = (Sint16) ((((float) (Sint16) SDL_SwapLE16(*(ptr+0))) * |
args->left_f) * args->distance_f); |
Sint16 swapr = (Sint16) ((((float) (Sint16) SDL_SwapLE16(*(ptr+1))) * |
args->right_f) * args->distance_f); |
Sint16 swaplr = (Sint16) ((((float) (Sint16) SDL_SwapLE16(*(ptr+2))) * |
args->left_rear_f) * args->distance_f); |
Sint16 swaprr = (Sint16) ((((float) (Sint16) SDL_SwapLE16(*(ptr+3))) * |
args->right_rear_f) * args->distance_f); |
Sint16 swapce = (Sint16) ((((float) (Sint16) SDL_SwapLE16(*(ptr+4))) * |
args->center_f) * args->distance_f); |
Sint16 swapwf = (Sint16) ((((float) (Sint16) SDL_SwapLE16(*(ptr+5))) * |
args->lfe_f) * args->distance_f); |
switch (args->room_angle) { |
case 0: |
*(ptr++) = (Sint16) SDL_SwapLE16(swapl); |
*(ptr++) = (Sint16) SDL_SwapLE16(swapr); |
*(ptr++) = (Sint16) SDL_SwapLE16(swaplr); |
*(ptr++) = (Sint16) SDL_SwapLE16(swaprr); |
*(ptr++) = (Sint16) SDL_SwapLE16(swapce); |
*(ptr++) = (Sint16) SDL_SwapLE16(swapwf); |
break; |
case 90: |
*(ptr++) = (Sint16) SDL_SwapLE16(swapr); |
*(ptr++) = (Sint16) SDL_SwapLE16(swaprr); |
*(ptr++) = (Sint16) SDL_SwapLE16(swapl); |
*(ptr++) = (Sint16) SDL_SwapLE16(swaplr); |
*(ptr++) = (Sint16) SDL_SwapLE16(swapr)/2 + (Sint16) SDL_SwapLE16(swaprr)/2; |
*(ptr++) = (Sint16) SDL_SwapLE16(swapwf); |
break; |
case 180: |
*(ptr++) = (Sint16) SDL_SwapLE16(swaprr); |
*(ptr++) = (Sint16) SDL_SwapLE16(swaplr); |
*(ptr++) = (Sint16) SDL_SwapLE16(swapr); |
*(ptr++) = (Sint16) SDL_SwapLE16(swapl); |
*(ptr++) = (Sint16) SDL_SwapLE16(swaprr)/2 + (Sint16) SDL_SwapLE16(swaplr)/2; |
*(ptr++) = (Sint16) SDL_SwapLE16(swapwf); |
break; |
case 270: |
*(ptr++) = (Sint16) SDL_SwapLE16(swaplr); |
*(ptr++) = (Sint16) SDL_SwapLE16(swapl); |
*(ptr++) = (Sint16) SDL_SwapLE16(swaprr); |
*(ptr++) = (Sint16) SDL_SwapLE16(swapr); |
*(ptr++) = (Sint16) SDL_SwapLE16(swapl)/2 + (Sint16) SDL_SwapLE16(swaplr)/2; |
*(ptr++) = (Sint16) SDL_SwapLE16(swapwf); |
break; |
} |
} |
} |
static void _Eff_position_u16msb(int chan, void *stream, int len, void *udata) |
{ |
/* 16 signed bits (lsb) * 2 channels. */ |
volatile position_args *args = (volatile position_args *) udata; |
Uint16 *ptr = (Uint16 *) stream; |
int i; |
for (i = 0; i < len; i += sizeof (Sint16) * 2) { |
Sint16 sampl = (Sint16) (SDL_SwapBE16(*(ptr+0)) - 32768); |
Sint16 sampr = (Sint16) (SDL_SwapBE16(*(ptr+1)) - 32768); |
Uint16 swapl = (Uint16) ((Sint16) (((float) sampl * args->left_f) |
* args->distance_f) + 32768); |
Uint16 swapr = (Uint16) ((Sint16) (((float) sampr * args->right_f) |
* args->distance_f) + 32768); |
if (args->room_angle == 180) { |
*(ptr++) = (Uint16) SDL_SwapBE16(swapr); |
*(ptr++) = (Uint16) SDL_SwapBE16(swapl); |
} |
else { |
*(ptr++) = (Uint16) SDL_SwapBE16(swapl); |
*(ptr++) = (Uint16) SDL_SwapBE16(swapr); |
} |
} |
} |
static void _Eff_position_u16msb_c4(int chan, void *stream, int len, void *udata) |
{ |
/* 16 signed bits (lsb) * 4 channels. */ |
volatile position_args *args = (volatile position_args *) udata; |
Uint16 *ptr = (Uint16 *) stream; |
int i; |
for (i = 0; i < len; i += sizeof (Sint16) * 4) { |
Sint16 sampl = (Sint16) (SDL_SwapBE16(*(ptr+0)) - 32768); |
Sint16 sampr = (Sint16) (SDL_SwapBE16(*(ptr+1)) - 32768); |
Sint16 samplr = (Sint16) (SDL_SwapBE16(*(ptr+2)) - 32768); |
Sint16 samprr = (Sint16) (SDL_SwapBE16(*(ptr+3)) - 32768); |
Uint16 swapl = (Uint16) ((Sint16) (((float) sampl * args->left_f) |
* args->distance_f) + 32768); |
Uint16 swapr = (Uint16) ((Sint16) (((float) sampr * args->right_f) |
* args->distance_f) + 32768); |
Uint16 swaplr = (Uint16) ((Sint16) (((float) samplr * args->left_rear_f) |
* args->distance_f) + 32768); |
Uint16 swaprr = (Uint16) ((Sint16) (((float) samprr * args->right_rear_f) |
* args->distance_f) + 32768); |
switch (args->room_angle) { |
case 0: |
*(ptr++) = (Uint16) SDL_SwapBE16(swapl); |
*(ptr++) = (Uint16) SDL_SwapBE16(swapr); |
*(ptr++) = (Uint16) SDL_SwapBE16(swaplr); |
*(ptr++) = (Uint16) SDL_SwapBE16(swaprr); |
break; |
case 90: |
*(ptr++) = (Uint16) SDL_SwapBE16(swapr); |
*(ptr++) = (Uint16) SDL_SwapBE16(swaprr); |
*(ptr++) = (Uint16) SDL_SwapBE16(swapl); |
*(ptr++) = (Uint16) SDL_SwapBE16(swaplr); |
break; |
case 180: |
*(ptr++) = (Uint16) SDL_SwapBE16(swaprr); |
*(ptr++) = (Uint16) SDL_SwapBE16(swaplr); |
*(ptr++) = (Uint16) SDL_SwapBE16(swapr); |
*(ptr++) = (Uint16) SDL_SwapBE16(swapl); |
break; |
case 270: |
*(ptr++) = (Uint16) SDL_SwapBE16(swaplr); |
*(ptr++) = (Uint16) SDL_SwapBE16(swapl); |
*(ptr++) = (Uint16) SDL_SwapBE16(swaprr); |
*(ptr++) = (Uint16) SDL_SwapBE16(swapr); |
break; |
} |
} |
} |
static void _Eff_position_u16msb_c6(int chan, void *stream, int len, void *udata) |
{ |
/* 16 signed bits (lsb) * 6 channels. */ |
volatile position_args *args = (volatile position_args *) udata; |
Uint16 *ptr = (Uint16 *) stream; |
int i; |
for (i = 0; i < len; i += sizeof (Sint16) * 6) { |
Sint16 sampl = (Sint16) (SDL_SwapBE16(*(ptr+0)) - 32768); |
Sint16 sampr = (Sint16) (SDL_SwapBE16(*(ptr+1)) - 32768); |
Sint16 samplr = (Sint16) (SDL_SwapBE16(*(ptr+2)) - 32768); |
Sint16 samprr = (Sint16) (SDL_SwapBE16(*(ptr+3)) - 32768); |
Sint16 sampce = (Sint16) (SDL_SwapBE16(*(ptr+4)) - 32768); |
Sint16 sampwf = (Sint16) (SDL_SwapBE16(*(ptr+5)) - 32768); |
Uint16 swapl = (Uint16) ((Sint16) (((float) sampl * args->left_f) |
* args->distance_f) + 32768); |
Uint16 swapr = (Uint16) ((Sint16) (((float) sampr * args->right_f) |
* args->distance_f) + 32768); |
Uint16 swaplr = (Uint16) ((Sint16) (((float) samplr * args->left_rear_f) |
* args->distance_f) + 32768); |
Uint16 swaprr = (Uint16) ((Sint16) (((float) samprr * args->right_rear_f) |
* args->distance_f) + 32768); |
Uint16 swapce = (Uint16) ((Sint16) (((float) sampce * args->center_f) |
* args->distance_f) + 32768); |
Uint16 swapwf = (Uint16) ((Sint16) (((float) sampwf * args->lfe_f) |
* args->distance_f) + 32768); |
switch (args->room_angle) { |
case 0: |
*(ptr++) = (Uint16) SDL_SwapBE16(swapl); |
*(ptr++) = (Uint16) SDL_SwapBE16(swapr); |
*(ptr++) = (Uint16) SDL_SwapBE16(swaplr); |
*(ptr++) = (Uint16) SDL_SwapBE16(swaprr); |
*(ptr++) = (Uint16) SDL_SwapBE16(swapce); |
*(ptr++) = (Uint16) SDL_SwapBE16(swapwf); |
break; |
case 90: |
*(ptr++) = (Uint16) SDL_SwapBE16(swapr); |
*(ptr++) = (Uint16) SDL_SwapBE16(swaprr); |
*(ptr++) = (Uint16) SDL_SwapBE16(swapl); |
*(ptr++) = (Uint16) SDL_SwapBE16(swaplr); |
*(ptr++) = (Uint16) SDL_SwapBE16(swapr)/2 + (Uint16) SDL_SwapBE16(swaprr)/2; |
*(ptr++) = (Uint16) SDL_SwapBE16(swapwf); |
break; |
case 180: |
*(ptr++) = (Uint16) SDL_SwapBE16(swaprr); |
*(ptr++) = (Uint16) SDL_SwapBE16(swaplr); |
*(ptr++) = (Uint16) SDL_SwapBE16(swapr); |
*(ptr++) = (Uint16) SDL_SwapBE16(swapl); |
*(ptr++) = (Uint16) SDL_SwapBE16(swaprr)/2 + (Uint16) SDL_SwapBE16(swaplr)/2; |
*(ptr++) = (Uint16) SDL_SwapBE16(swapwf); |
break; |
case 270: |
*(ptr++) = (Uint16) SDL_SwapBE16(swaplr); |
*(ptr++) = (Uint16) SDL_SwapBE16(swapl); |
*(ptr++) = (Uint16) SDL_SwapBE16(swaprr); |
*(ptr++) = (Uint16) SDL_SwapBE16(swapr); |
*(ptr++) = (Uint16) SDL_SwapBE16(swapl)/2 + (Uint16) SDL_SwapBE16(swaplr)/2; |
*(ptr++) = (Uint16) SDL_SwapBE16(swapwf); |
break; |
} |
} |
} |
static void _Eff_position_s16msb(int chan, void *stream, int len, void *udata) |
{ |
/* 16 signed bits (lsb) * 2 channels. */ |
volatile position_args *args = (volatile position_args *) udata; |
Sint16 *ptr = (Sint16 *) stream; |
int i; |
for (i = 0; i < len; i += sizeof (Sint16) * 2) { |
Sint16 swapl = (Sint16) ((((float) (Sint16) SDL_SwapBE16(*(ptr+0))) * |
args->left_f) * args->distance_f); |
Sint16 swapr = (Sint16) ((((float) (Sint16) SDL_SwapBE16(*(ptr+1))) * |
args->right_f) * args->distance_f); |
*(ptr++) = (Sint16) SDL_SwapBE16(swapl); |
*(ptr++) = (Sint16) SDL_SwapBE16(swapr); |
} |
} |
static void _Eff_position_s16msb_c4(int chan, void *stream, int len, void *udata) |
{ |
/* 16 signed bits (lsb) * 4 channels. */ |
volatile position_args *args = (volatile position_args *) udata; |
Sint16 *ptr = (Sint16 *) stream; |
int i; |
for (i = 0; i < len; i += sizeof (Sint16) * 4) { |
Sint16 swapl = (Sint16) ((((float) (Sint16) SDL_SwapBE16(*(ptr+0))) * |
args->left_f) * args->distance_f); |
Sint16 swapr = (Sint16) ((((float) (Sint16) SDL_SwapBE16(*(ptr+1))) * |
args->right_f) * args->distance_f); |
Sint16 swaplr = (Sint16) ((((float) (Sint16) SDL_SwapBE16(*(ptr+2))) * |
args->left_rear_f) * args->distance_f); |
Sint16 swaprr = (Sint16) ((((float) (Sint16) SDL_SwapBE16(*(ptr+3))) * |
args->right_rear_f) * args->distance_f); |
switch (args->room_angle) { |
case 0: |
*(ptr++) = (Sint16) SDL_SwapBE16(swapl); |
*(ptr++) = (Sint16) SDL_SwapBE16(swapr); |
*(ptr++) = (Sint16) SDL_SwapBE16(swaplr); |
*(ptr++) = (Sint16) SDL_SwapBE16(swaprr); |
break; |
case 90: |
*(ptr++) = (Sint16) SDL_SwapBE16(swapr); |
*(ptr++) = (Sint16) SDL_SwapBE16(swaprr); |
*(ptr++) = (Sint16) SDL_SwapBE16(swapl); |
*(ptr++) = (Sint16) SDL_SwapBE16(swaplr); |
break; |
case 180: |
*(ptr++) = (Sint16) SDL_SwapBE16(swaprr); |
*(ptr++) = (Sint16) SDL_SwapBE16(swaplr); |
*(ptr++) = (Sint16) SDL_SwapBE16(swapr); |
*(ptr++) = (Sint16) SDL_SwapBE16(swapl); |
break; |
case 270: |
*(ptr++) = (Sint16) SDL_SwapBE16(swaplr); |
*(ptr++) = (Sint16) SDL_SwapBE16(swapl); |
*(ptr++) = (Sint16) SDL_SwapBE16(swaprr); |
*(ptr++) = (Sint16) SDL_SwapBE16(swapr); |
break; |
} |
} |
} |
static void _Eff_position_s16msb_c6(int chan, void *stream, int len, void *udata) |
{ |
/* 16 signed bits (lsb) * 6 channels. */ |
volatile position_args *args = (volatile position_args *) udata; |
Sint16 *ptr = (Sint16 *) stream; |
int i; |
for (i = 0; i < len; i += sizeof (Sint16) * 6) { |
Sint16 swapl = (Sint16) ((((float) (Sint16) SDL_SwapBE16(*(ptr+0))) * |
args->left_f) * args->distance_f); |
Sint16 swapr = (Sint16) ((((float) (Sint16) SDL_SwapBE16(*(ptr+1))) * |
args->right_f) * args->distance_f); |
Sint16 swaplr = (Sint16) ((((float) (Sint16) SDL_SwapBE16(*(ptr+2))) * |
args->left_rear_f) * args->distance_f); |
Sint16 swaprr = (Sint16) ((((float) (Sint16) SDL_SwapBE16(*(ptr+3))) * |
args->right_rear_f) * args->distance_f); |
Sint16 swapce = (Sint16) ((((float) (Sint16) SDL_SwapBE16(*(ptr+4))) * |
args->center_f) * args->distance_f); |
Sint16 swapwf = (Sint16) ((((float) (Sint16) SDL_SwapBE16(*(ptr+5))) * |
args->lfe_f) * args->distance_f); |
switch (args->room_angle) { |
case 0: |
*(ptr++) = (Sint16) SDL_SwapBE16(swapl); |
*(ptr++) = (Sint16) SDL_SwapBE16(swapr); |
*(ptr++) = (Sint16) SDL_SwapBE16(swaplr); |
*(ptr++) = (Sint16) SDL_SwapBE16(swaprr); |
*(ptr++) = (Sint16) SDL_SwapBE16(swapce); |
*(ptr++) = (Sint16) SDL_SwapBE16(swapwf); |
break; |
case 90: |
*(ptr++) = (Sint16) SDL_SwapBE16(swapr); |
*(ptr++) = (Sint16) SDL_SwapBE16(swaprr); |
*(ptr++) = (Sint16) SDL_SwapBE16(swapl); |
*(ptr++) = (Sint16) SDL_SwapBE16(swaplr); |
*(ptr++) = (Sint16) SDL_SwapBE16(swapr)/2 + (Sint16) SDL_SwapBE16(swaprr)/2; |
*(ptr++) = (Sint16) SDL_SwapBE16(swapwf); |
break; |
case 180: |
*(ptr++) = (Sint16) SDL_SwapBE16(swaprr); |
*(ptr++) = (Sint16) SDL_SwapBE16(swaplr); |
*(ptr++) = (Sint16) SDL_SwapBE16(swapr); |
*(ptr++) = (Sint16) SDL_SwapBE16(swapl); |
*(ptr++) = (Sint16) SDL_SwapBE16(swaprr)/2 + (Sint16) SDL_SwapBE16(swaplr)/2; |
*(ptr++) = (Sint16) SDL_SwapBE16(swapwf); |
break; |
case 270: |
*(ptr++) = (Sint16) SDL_SwapBE16(swaplr); |
*(ptr++) = (Sint16) SDL_SwapBE16(swapl); |
*(ptr++) = (Sint16) SDL_SwapBE16(swaprr); |
*(ptr++) = (Sint16) SDL_SwapBE16(swapr); |
*(ptr++) = (Sint16) SDL_SwapBE16(swapl)/2 + (Sint16) SDL_SwapBE16(swaplr)/2; |
*(ptr++) = (Sint16) SDL_SwapBE16(swapwf); |
break; |
} |
} |
} |
static void init_position_args(position_args *args) |
{ |
memset(args, '\0', sizeof (position_args)); |
args->in_use = 0; |
args->room_angle = 0; |
args->left_u8 = args->right_u8 = args->distance_u8 = 255; |
args->left_f = args->right_f = args->distance_f = 1.0f; |
args->left_rear_u8 = args->right_rear_u8 = args->center_u8 = args->lfe_u8 = 255; |
args->left_rear_f = args->right_rear_f = args->center_f = args->lfe_f = 1.0f; |
Mix_QuerySpec(NULL, NULL, (int *) &args->channels); |
} |
static position_args *get_position_arg(int channel) |
{ |
void *rc; |
int i; |
if (channel < 0) { |
if (pos_args_global == NULL) { |
pos_args_global = SDL_malloc(sizeof (position_args)); |
if (pos_args_global == NULL) { |
Mix_SetError("Out of memory"); |
return(NULL); |
} |
init_position_args(pos_args_global); |
} |
return(pos_args_global); |
} |
if (channel >= position_channels) { |
rc = SDL_realloc(pos_args_array, (channel + 1) * sizeof (position_args *)); |
if (rc == NULL) { |
Mix_SetError("Out of memory"); |
return(NULL); |
} |
pos_args_array = (position_args **) rc; |
for (i = position_channels; i <= channel; i++) { |
pos_args_array[i] = NULL; |
} |
position_channels = channel + 1; |
} |
if (pos_args_array[channel] == NULL) { |
pos_args_array[channel] = (position_args *)SDL_malloc(sizeof(position_args)); |
if (pos_args_array[channel] == NULL) { |
Mix_SetError("Out of memory"); |
return(NULL); |
} |
init_position_args(pos_args_array[channel]); |
} |
return(pos_args_array[channel]); |
} |
static Mix_EffectFunc_t get_position_effect_func(Uint16 format, int channels) |
{ |
Mix_EffectFunc_t f = NULL; |
switch (format) { |
case AUDIO_U8: |
switch (channels) { |
case 1: |
case 2: |
f = (_Eff_build_volume_table_u8()) ? _Eff_position_table_u8 : |
_Eff_position_u8; |
break; |
case 4: |
f = _Eff_position_u8_c4; |
break; |
case 6: |
f = _Eff_position_u8_c6; |
break; |
} |
break; |
case AUDIO_S8: |
switch (channels) { |
case 1: |
case 2: |
f = (_Eff_build_volume_table_s8()) ? _Eff_position_table_s8 : |
_Eff_position_s8; |
break; |
case 4: |
f = _Eff_position_s8_c4; |
break; |
case 6: |
f = _Eff_position_s8_c6; |
break; |
} |
break; |
case AUDIO_U16LSB: |
switch (channels) { |
case 1: |
case 2: |
f = _Eff_position_u16lsb; |
break; |
case 4: |
f = _Eff_position_u16lsb_c4; |
break; |
case 6: |
f = _Eff_position_u16lsb_c6; |
break; |
} |
break; |
case AUDIO_S16LSB: |
switch (channels) { |
case 1: |
case 2: |
f = _Eff_position_s16lsb; |
break; |
case 4: |
f = _Eff_position_s16lsb_c4; |
break; |
case 6: |
f = _Eff_position_s16lsb_c6; |
break; |
} |
break; |
case AUDIO_U16MSB: |
switch (channels) { |
case 1: |
case 2: |
f = _Eff_position_u16msb; |
break; |
case 4: |
f = _Eff_position_u16msb_c4; |
break; |
case 6: |
f = _Eff_position_u16msb_c6; |
break; |
} |
break; |
case AUDIO_S16MSB: |
switch (channels) { |
case 1: |
case 2: |
f = _Eff_position_s16msb; |
break; |
case 4: |
f = _Eff_position_s16msb_c4; |
break; |
case 6: |
f = _Eff_position_s16msb_c6; |
break; |
} |
break; |
default: |
Mix_SetError("Unsupported audio format"); |
} |
return(f); |
} |
static Uint8 speaker_amplitude[6]; |
static void set_amplitudes(int channels, int angle, int room_angle) |
{ |
int left = 255, right = 255; |
int left_rear = 255, right_rear = 255, center = 255; |
angle = SDL_abs(angle) % 360; /* make angle between 0 and 359. */ |
if (channels == 2) |
{ |
/* |
* We only attenuate by position if the angle falls on the far side |
* of center; That is, an angle that's due north would not attenuate |
* either channel. Due west attenuates the right channel to 0.0, and |
* due east attenuates the left channel to 0.0. Slightly east of |
* center attenuates the left channel a little, and the right channel |
* not at all. I think of this as occlusion by one's own head. :) |
* |
* ...so, we split our angle circle into four quadrants... |
*/ |
if (angle < 90) { |
left = 255 - ((int) (255.0f * (((float) angle) / 89.0f))); |
} else if (angle < 180) { |
left = (int) (255.0f * (((float) (angle - 90)) / 89.0f)); |
} else if (angle < 270) { |
right = 255 - ((int) (255.0f * (((float) (angle - 180)) / 89.0f))); |
} else { |
right = (int) (255.0f * (((float) (angle - 270)) / 89.0f)); |
} |
} |
if (channels == 4 || channels == 6) |
{ |
/* |
* An angle that's due north does not attenuate the center channel. |
* An angle in the first quadrant, 0-90, does not attenuate the RF. |
* |
* ...so, we split our angle circle into 8 ... |
* |
* CE |
* 0 |
* LF | RF |
* | |
* 270<-------|----------->90 |
* | |
* LR | RR |
* 180 |
* |
*/ |
if (angle < 45) { |
left = ((int) (255.0f * (((float) (180 - angle)) / 179.0f))); |
left_rear = 255 - ((int) (255.0f * (((float) (angle + 45)) / 89.0f))); |
right_rear = 255 - ((int) (255.0f * (((float) (90 - angle)) / 179.0f))); |
} else if (angle < 90) { |
center = ((int) (255.0f * (((float) (225 - angle)) / 179.0f))); |
left = ((int) (255.0f * (((float) (180 - angle)) / 179.0f))); |
left_rear = 255 - ((int) (255.0f * (((float) (135 - angle)) / 89.0f))); |
right_rear = ((int) (255.0f * (((float) (90 + angle)) / 179.0f))); |
} else if (angle < 135) { |
center = ((int) (255.0f * (((float) (225 - angle)) / 179.0f))); |
left = 255 - ((int) (255.0f * (((float) (angle - 45)) / 89.0f))); |
right = ((int) (255.0f * (((float) (270 - angle)) / 179.0f))); |
left_rear = ((int) (255.0f * (((float) (angle)) / 179.0f))); |
} else if (angle < 180) { |
center = 255 - ((int) (255.0f * (((float) (angle - 90)) / 89.0f))); |
left = 255 - ((int) (255.0f * (((float) (225 - angle)) / 89.0f))); |
right = ((int) (255.0f * (((float) (270 - angle)) / 179.0f))); |
left_rear = ((int) (255.0f * (((float) (angle)) / 179.0f))); |
} else if (angle < 225) { |
center = 255 - ((int) (255.0f * (((float) (270 - angle)) / 89.0f))); |
left = ((int) (255.0f * (((float) (angle - 90)) / 179.0f))); |
right = 255 - ((int) (255.0f * (((float) (angle - 135)) / 89.0f))); |
right_rear = ((int) (255.0f * (((float) (360 - angle)) / 179.0f))); |
} else if (angle < 270) { |
center = ((int) (255.0f * (((float) (angle - 135)) / 179.0f))); |
left = ((int) (255.0f * (((float) (angle - 90)) / 179.0f))); |
right = 255 - ((int) (255.0f * (((float) (315 - angle)) / 89.0f))); |
right_rear = ((int) (255.0f * (((float) (360 - angle)) / 179.0f))); |
} else if (angle < 315) { |
center = ((int) (255.0f * (((float) (angle - 135)) / 179.0f))); |
right = ((int) (255.0f * (((float) (angle - 180)) / 179.0f))); |
left_rear = ((int) (255.0f * (((float) (450 - angle)) / 179.0f))); |
right_rear = 255 - ((int) (255.0f * (((float) (angle - 225)) / 89.0f))); |
} else { |
right = ((int) (255.0f * (((float) (angle - 180)) / 179.0f))); |
left_rear = ((int) (255.0f * (((float) (450 - angle)) / 179.0f))); |
right_rear = 255 - ((int) (255.0f * (((float) (405 - angle)) / 89.0f))); |
} |
} |
if (left < 0) left = 0; if (left > 255) left = 255; |
if (right < 0) right = 0; if (right > 255) right = 255; |
if (left_rear < 0) left_rear = 0; if (left_rear > 255) left_rear = 255; |
if (right_rear < 0) right_rear = 0; if (right_rear > 255) right_rear = 255; |
if (center < 0) center = 0; if (center > 255) center = 255; |
if (room_angle == 90) { |
speaker_amplitude[0] = (Uint8)left_rear; |
speaker_amplitude[1] = (Uint8)left; |
speaker_amplitude[2] = (Uint8)right_rear; |
speaker_amplitude[3] = (Uint8)right; |
} |
else if (room_angle == 180) { |
if (channels == 2) { |
speaker_amplitude[0] = (Uint8)right; |
speaker_amplitude[1] = (Uint8)left; |
} |
else { |
speaker_amplitude[0] = (Uint8)right_rear; |
speaker_amplitude[1] = (Uint8)left_rear; |
speaker_amplitude[2] = (Uint8)right; |
speaker_amplitude[3] = (Uint8)left; |
} |
} |
else if (room_angle == 270) { |
speaker_amplitude[0] = (Uint8)right; |
speaker_amplitude[1] = (Uint8)right_rear; |
speaker_amplitude[2] = (Uint8)left; |
speaker_amplitude[3] = (Uint8)left_rear; |
} |
else { |
speaker_amplitude[0] = (Uint8)left; |
speaker_amplitude[1] = (Uint8)right; |
speaker_amplitude[2] = (Uint8)left_rear; |
speaker_amplitude[3] = (Uint8)right_rear; |
} |
speaker_amplitude[4] = (Uint8)center; |
speaker_amplitude[5] = 255; |
} |
int Mix_SetPosition(int channel, Sint16 angle, Uint8 distance); |
int Mix_SetPanning(int channel, Uint8 left, Uint8 right) |
{ |
Mix_EffectFunc_t f = NULL; |
int channels; |
Uint16 format; |
position_args *args = NULL; |
int retval = 1; |
Mix_QuerySpec(NULL, &format, &channels); |
if (channels != 2 && channels != 4 && channels != 6) /* it's a no-op; we call that successful. */ |
return(1); |
if (channels > 2) { |
/* left = right = 255 => angle = 0, to unregister effect as when channels = 2 */ |
/* left = 255 => angle = -90; left = 0 => angle = +89 */ |
int angle = 0; |
if ((left != 255) || (right != 255)) { |
angle = (int)left; |
angle = 127 - angle; |
angle = -angle; |
angle = angle * 90 / 128; /* Make it larger for more effect? */ |
} |
return( Mix_SetPosition(channel, angle, 0) ); |
} |
f = get_position_effect_func(format, channels); |
if (f == NULL) |
return(0); |
SDL_LockAudio(); |
args = get_position_arg(channel); |
if (!args) { |
SDL_UnlockAudio(); |
return(0); |
} |
/* it's a no-op; unregister the effect, if it's registered. */ |
if ((args->distance_u8 == 255) && (left == 255) && (right == 255)) { |
if (args->in_use) { |
retval = _Mix_UnregisterEffect_locked(channel, f); |
SDL_UnlockAudio(); |
return(retval); |
} else { |
SDL_UnlockAudio(); |
return(1); |
} |
} |
args->left_u8 = left; |
args->left_f = ((float) left) / 255.0f; |
args->right_u8 = right; |
args->right_f = ((float) right) / 255.0f; |
args->room_angle = 0; |
if (!args->in_use) { |
args->in_use = 1; |
retval=_Mix_RegisterEffect_locked(channel, f, _Eff_PositionDone, (void*)args); |
} |
SDL_UnlockAudio(); |
return(retval); |
} |
int Mix_SetDistance(int channel, Uint8 distance) |
{ |
Mix_EffectFunc_t f = NULL; |
Uint16 format; |
position_args *args = NULL; |
int channels; |
int retval = 1; |
Mix_QuerySpec(NULL, &format, &channels); |
f = get_position_effect_func(format, channels); |
if (f == NULL) |
return(0); |
SDL_LockAudio(); |
args = get_position_arg(channel); |
if (!args) { |
SDL_UnlockAudio(); |
return(0); |
} |
distance = 255 - distance; /* flip it to our scale. */ |
/* it's a no-op; unregister the effect, if it's registered. */ |
if ((distance == 255) && (args->left_u8 == 255) && (args->right_u8 == 255)) { |
if (args->in_use) { |
retval = _Mix_UnregisterEffect_locked(channel, f); |
SDL_UnlockAudio(); |
return(retval); |
} else { |
SDL_UnlockAudio(); |
return(1); |
} |
} |
args->distance_u8 = distance; |
args->distance_f = ((float) distance) / 255.0f; |
if (!args->in_use) { |
args->in_use = 1; |
retval = _Mix_RegisterEffect_locked(channel, f, _Eff_PositionDone, (void *) args); |
} |
SDL_UnlockAudio(); |
return(retval); |
} |
int Mix_SetPosition(int channel, Sint16 angle, Uint8 distance) |
{ |
Mix_EffectFunc_t f = NULL; |
Uint16 format; |
int channels; |
position_args *args = NULL; |
Sint16 room_angle = 0; |
int retval = 1; |
Mix_QuerySpec(NULL, &format, &channels); |
f = get_position_effect_func(format, channels); |
if (f == NULL) |
return(0); |
angle = SDL_abs(angle) % 360; /* make angle between 0 and 359. */ |
SDL_LockAudio(); |
args = get_position_arg(channel); |
if (!args) { |
SDL_UnlockAudio(); |
return(0); |
} |
/* it's a no-op; unregister the effect, if it's registered. */ |
if ((!distance) && (!angle)) { |
if (args->in_use) { |
retval = _Mix_UnregisterEffect_locked(channel, f); |
SDL_UnlockAudio(); |
return(retval); |
} else { |
SDL_UnlockAudio(); |
return(1); |
} |
} |
if (channels == 2) |
{ |
if (angle > 180) |
room_angle = 180; /* exchange left and right channels */ |
else room_angle = 0; |
} |
if (channels == 4 || channels == 6) |
{ |
if (angle > 315) room_angle = 0; |
else if (angle > 225) room_angle = 270; |
else if (angle > 135) room_angle = 180; |
else if (angle > 45) room_angle = 90; |
else room_angle = 0; |
} |
distance = 255 - distance; /* flip it to scale Mix_SetDistance() uses. */ |
set_amplitudes(channels, angle, room_angle); |
args->left_u8 = speaker_amplitude[0]; |
args->left_f = ((float) speaker_amplitude[0]) / 255.0f; |
args->right_u8 = speaker_amplitude[1]; |
args->right_f = ((float) speaker_amplitude[1]) / 255.0f; |
args->left_rear_u8 = speaker_amplitude[2]; |
args->left_rear_f = ((float) speaker_amplitude[2]) / 255.0f; |
args->right_rear_u8 = speaker_amplitude[3]; |
args->right_rear_f = ((float) speaker_amplitude[3]) / 255.0f; |
args->center_u8 = speaker_amplitude[4]; |
args->center_f = ((float) speaker_amplitude[4]) / 255.0f; |
args->lfe_u8 = speaker_amplitude[5]; |
args->lfe_f = ((float) speaker_amplitude[5]) / 255.0f; |
args->distance_u8 = distance; |
args->distance_f = ((float) distance) / 255.0f; |
args->room_angle = room_angle; |
if (!args->in_use) { |
args->in_use = 1; |
retval = _Mix_RegisterEffect_locked(channel, f, _Eff_PositionDone, (void *) args); |
} |
SDL_UnlockAudio(); |
return(retval); |
} |
/* end of effects_position.c ... */ |
/contrib/games/wolf3d/SDL_mixer/effects_internal.c |
---|
0,0 → 1,124 |
/* |
SDL_mixer: An audio mixer library based on the SDL library |
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org> |
This software is provided 'as-is', without any express or implied |
warranty. In no event will the authors be held liable for any damages |
arising from the use of this software. |
Permission is granted to anyone to use this software for any purpose, |
including commercial applications, and to alter it and redistribute it |
freely, subject to the following restrictions: |
1. The origin of this software must not be misrepresented; you must not |
claim that you wrote the original software. If you use this software |
in a product, an acknowledgment in the product documentation would be |
appreciated but is not required. |
2. Altered source versions must be plainly marked as such, and must not be |
misrepresented as being the original software. |
3. This notice may not be removed or altered from any source distribution. |
This file by Ryan C. Gordon (icculus@icculus.org) |
These are some helper functions for the internal mixer special effects. |
*/ |
/* $Id$ */ |
/* ------ These are used internally only. Don't touch. ------ */ |
#include <stdio.h> |
#include <stdlib.h> |
#include "SDL_mixer.h" |
#define __MIX_INTERNAL_EFFECT__ |
#include "effects_internal.h" |
/* Should we favor speed over memory usage and/or quality of output? */ |
int _Mix_effects_max_speed = 0; |
void _Mix_InitEffects(void) |
{ |
_Mix_effects_max_speed = (SDL_getenv(MIX_EFFECTSMAXSPEED) != NULL); |
} |
void _Mix_DeinitEffects(void) |
{ |
_Eff_PositionDeinit(); |
} |
void *_Eff_volume_table = NULL; |
/* Build the volume table for Uint8-format samples. |
* |
* Each column of the table is a possible sample, while each row of the |
* table is a volume. Volume is a Uint8, where 0 is silence and 255 is full |
* volume. So _Eff_volume_table[128][mysample] would be the value of |
* mysample, at half volume. |
*/ |
void *_Eff_build_volume_table_u8(void) |
{ |
int volume; |
int sample; |
Uint8 *rc; |
if (!_Mix_effects_max_speed) { |
return(NULL); |
} |
if (!_Eff_volume_table) { |
rc = SDL_malloc(256 * 256); |
if (rc) { |
_Eff_volume_table = (void *) rc; |
for (volume = 0; volume < 256; volume++) { |
for (sample = -128; sample < 128; sample ++) { |
*rc = (Uint8)(((float) sample) * ((float) volume / 255.0)) |
+ 128; |
rc++; |
} |
} |
} |
} |
return(_Eff_volume_table); |
} |
/* Build the volume table for Sint8-format samples. |
* |
* Each column of the table is a possible sample, while each row of the |
* table is a volume. Volume is a Uint8, where 0 is silence and 255 is full |
* volume. So _Eff_volume_table[128][mysample+128] would be the value of |
* mysample, at half volume. |
*/ |
void *_Eff_build_volume_table_s8(void) |
{ |
int volume; |
int sample; |
Sint8 *rc; |
if (!_Eff_volume_table) { |
rc = SDL_malloc(256 * 256); |
if (rc) { |
_Eff_volume_table = (void *) rc; |
for (volume = 0; volume < 256; volume++) { |
for (sample = -128; sample < 128; sample ++) { |
*rc = (Sint8)(((float) sample) * ((float) volume / 255.0)); |
rc++; |
} |
} |
} |
} |
return(_Eff_volume_table); |
} |
/* end of effects.c ... */ |
/contrib/games/wolf3d/SDL_mixer/effects_internal.h |
---|
0,0 → 1,60 |
/* |
SDL_mixer: An audio mixer library based on the SDL library |
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org> |
This software is provided 'as-is', without any express or implied |
warranty. In no event will the authors be held liable for any damages |
arising from the use of this software. |
Permission is granted to anyone to use this software for any purpose, |
including commercial applications, and to alter it and redistribute it |
freely, subject to the following restrictions: |
1. The origin of this software must not be misrepresented; you must not |
claim that you wrote the original software. If you use this software |
in a product, an acknowledgment in the product documentation would be |
appreciated but is not required. |
2. Altered source versions must be plainly marked as such, and must not be |
misrepresented as being the original software. |
3. This notice may not be removed or altered from any source distribution. |
*/ |
/* $Id$ */ |
#ifndef _INCLUDE_EFFECTS_INTERNAL_H_ |
#define _INCLUDE_EFFECTS_INTERNAL_H_ |
#ifndef __MIX_INTERNAL_EFFECT__ |
#error You should not include this file or use these functions. |
#endif |
#include "SDL_mixer.h" |
/* Set up for C function definitions, even when using C++ */ |
#ifdef __cplusplus |
extern "C" { |
#endif |
extern int _Mix_effects_max_speed; |
extern void *_Eff_volume_table; |
void *_Eff_build_volume_table_u8(void); |
void *_Eff_build_volume_table_s8(void); |
void _Mix_InitEffects(void); |
void _Mix_DeinitEffects(void); |
void _Eff_PositionDeinit(void); |
int _Mix_RegisterEffect_locked(int channel, Mix_EffectFunc_t f, |
Mix_EffectDone_t d, void *arg); |
int _Mix_UnregisterEffect_locked(int channel, Mix_EffectFunc_t f); |
int _Mix_UnregisterAllEffects_locked(int channel); |
/* Set up for C function definitions, even when using C++ */ |
#ifdef __cplusplus |
} |
#endif |
#endif |
/contrib/games/wolf3d/SDL_mixer/fluidsynth.h |
---|
0,0 → 1,51 |
/* |
SDL_mixer: An audio mixer library based on the SDL library |
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org> |
This software is provided 'as-is', without any express or implied |
warranty. In no event will the authors be held liable for any damages |
arising from the use of this software. |
Permission is granted to anyone to use this software for any purpose, |
including commercial applications, and to alter it and redistribute it |
freely, subject to the following restrictions: |
1. The origin of this software must not be misrepresented; you must not |
claim that you wrote the original software. If you use this software |
in a product, an acknowledgment in the product documentation would be |
appreciated but is not required. |
2. Altered source versions must be plainly marked as such, and must not be |
misrepresented as being the original software. |
3. This notice may not be removed or altered from any source distribution. |
James Le Cuirot |
chewi@aura-online.co.uk |
*/ |
#ifndef _FLUIDSYNTH_H_ |
#define _FLUIDSYNTH_H_ |
#ifdef USE_FLUIDSYNTH_MIDI |
#include "dynamic_fluidsynth.h" |
#include <SDL_rwops.h> |
#include <SDL_audio.h> |
typedef struct { |
SDL_AudioCVT convert; |
fluid_synth_t *synth; |
fluid_player_t* player; |
} FluidSynthMidiSong; |
int fluidsynth_init(SDL_AudioSpec *mixer); |
FluidSynthMidiSong *fluidsynth_loadsong_RW(SDL_RWops *rw, int freerw); |
void fluidsynth_freesong(FluidSynthMidiSong *song); |
void fluidsynth_start(FluidSynthMidiSong *song); |
void fluidsynth_stop(FluidSynthMidiSong *song); |
int fluidsynth_active(FluidSynthMidiSong *song); |
void fluidsynth_setvolume(FluidSynthMidiSong *song, int volume); |
int fluidsynth_playsome(FluidSynthMidiSong *song, void *stream, int len); |
#endif /* USE_FLUIDSYNTH_MIDI */ |
#endif /* _FLUIDSYNTH_H_ */ |
/contrib/games/wolf3d/SDL_mixer/load_aiff.c |
---|
0,0 → 1,250 |
/* |
SDL_mixer: An audio mixer library based on the SDL library |
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org> |
This software is provided 'as-is', without any express or implied |
warranty. In no event will the authors be held liable for any damages |
arising from the use of this software. |
Permission is granted to anyone to use this software for any purpose, |
including commercial applications, and to alter it and redistribute it |
freely, subject to the following restrictions: |
1. The origin of this software must not be misrepresented; you must not |
claim that you wrote the original software. If you use this software |
in a product, an acknowledgment in the product documentation would be |
appreciated but is not required. |
2. Altered source versions must be plainly marked as such, and must not be |
misrepresented as being the original software. |
3. This notice may not be removed or altered from any source distribution. |
This is the source needed to decode an AIFF file into a waveform. |
It's pretty straightforward once you get going. The only |
externally-callable function is Mix_LoadAIFF_RW(), which is meant to |
act as identically to SDL_LoadWAV_RW() as possible. |
This file by Torbjörn Andersson (torbjorn.andersson@eurotime.se) |
8SVX file support added by Marc Le Douarain (mavati@club-internet.fr) |
in december 2002. |
*/ |
/* $Id$ */ |
#include <stdlib.h> |
#include <string.h> |
#include "SDL_endian.h" |
#include "SDL_mixer.h" |
#include "load_aiff.h" |
/*********************************************/ |
/* Define values for AIFF (IFF audio) format */ |
/*********************************************/ |
#define FORM 0x4d524f46 /* "FORM" */ |
#define AIFF 0x46464941 /* "AIFF" */ |
#define SSND 0x444e5353 /* "SSND" */ |
#define COMM 0x4d4d4f43 /* "COMM" */ |
#define _8SVX 0x58565338 /* "8SVX" */ |
#define VHDR 0x52444856 /* "VHDR" */ |
#define BODY 0x59444F42 /* "BODY" */ |
/* This function was taken from libsndfile. I don't pretend to fully |
* understand it. |
*/ |
static Uint32 SANE_to_Uint32 (Uint8 *sanebuf) |
{ |
/* Is the frequency outside of what we can represent with Uint32? */ |
if ( (sanebuf[0] & 0x80) || (sanebuf[0] <= 0x3F) || (sanebuf[0] > 0x40) |
|| (sanebuf[0] == 0x40 && sanebuf[1] > 0x1C) ) |
return 0; |
return ((sanebuf[2] << 23) | (sanebuf[3] << 15) | (sanebuf[4] << 7) |
| (sanebuf[5] >> 1)) >> (29 - sanebuf[1]); |
} |
/* This function is based on SDL_LoadWAV_RW(). */ |
SDL_AudioSpec *Mix_LoadAIFF_RW (SDL_RWops *src, int freesrc, |
SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len) |
{ |
int was_error; |
int found_SSND; |
int found_COMM; |
int found_VHDR; |
int found_BODY; |
long start = 0; |
Uint32 chunk_type; |
Uint32 chunk_length; |
long next_chunk; |
/* AIFF magic header */ |
Uint32 FORMchunk; |
Uint32 AIFFmagic; |
/* SSND chunk */ |
Uint32 offset; |
Uint32 blocksize; |
/* COMM format chunk */ |
Uint16 channels = 0; |
Uint32 numsamples = 0; |
Uint16 samplesize = 0; |
Uint8 sane_freq[10]; |
Uint32 frequency = 0; |
/* Make sure we are passed a valid data source */ |
was_error = 0; |
if ( src == NULL ) { |
was_error = 1; |
goto done; |
} |
FORMchunk = SDL_ReadLE32(src); |
chunk_length = SDL_ReadBE32(src); |
if ( chunk_length == AIFF ) { /* The FORMchunk has already been read */ |
AIFFmagic = chunk_length; |
chunk_length = FORMchunk; |
FORMchunk = FORM; |
} else { |
AIFFmagic = SDL_ReadLE32(src); |
} |
if ( (FORMchunk != FORM) || ( (AIFFmagic != AIFF) && (AIFFmagic != _8SVX) ) ) { |
SDL_SetError("Unrecognized file type (not AIFF nor 8SVX)"); |
was_error = 1; |
goto done; |
} |
/* TODO: Better santity-checking. */ |
found_SSND = 0; |
found_COMM = 0; |
found_VHDR = 0; |
found_BODY = 0; |
do { |
chunk_type = SDL_ReadLE32(src); |
chunk_length = SDL_ReadBE32(src); |
next_chunk = SDL_RWtell(src) + chunk_length; |
/* Paranoia to avoid infinite loops */ |
if (chunk_length == 0) |
break; |
switch (chunk_type) { |
case SSND: |
found_SSND = 1; |
offset = SDL_ReadBE32(src); |
blocksize = SDL_ReadBE32(src); |
start = SDL_RWtell(src) + offset; |
break; |
case COMM: |
found_COMM = 1; |
channels = SDL_ReadBE16(src); |
numsamples = SDL_ReadBE32(src); |
samplesize = SDL_ReadBE16(src); |
SDL_RWread(src, sane_freq, sizeof(sane_freq), 1); |
frequency = SANE_to_Uint32(sane_freq); |
if (frequency == 0) { |
SDL_SetError("Bad AIFF sample frequency"); |
was_error = 1; |
goto done; |
} |
break; |
case VHDR: |
found_VHDR = 1; |
SDL_ReadBE32(src); |
SDL_ReadBE32(src); |
SDL_ReadBE32(src); |
frequency = SDL_ReadBE16(src); |
channels = 1; |
samplesize = 8; |
break; |
case BODY: |
found_BODY = 1; |
numsamples = chunk_length; |
start = SDL_RWtell(src); |
break; |
default: |
break; |
} |
/* a 0 pad byte can be stored for any odd-length chunk */ |
if (chunk_length&1) |
next_chunk++; |
} while ( ( ( (AIFFmagic == AIFF) && ( !found_SSND || !found_COMM ) ) |
|| ( (AIFFmagic == _8SVX ) && ( !found_VHDR || !found_BODY ) ) ) |
&& SDL_RWseek(src, next_chunk, RW_SEEK_SET) != 1 ); |
if ( (AIFFmagic == AIFF) && !found_SSND ) { |
SDL_SetError("Bad AIFF (no SSND chunk)"); |
was_error = 1; |
goto done; |
} |
if ( (AIFFmagic == AIFF) && !found_COMM ) { |
SDL_SetError("Bad AIFF (no COMM chunk)"); |
was_error = 1; |
goto done; |
} |
if ( (AIFFmagic == _8SVX) && !found_VHDR ) { |
SDL_SetError("Bad 8SVX (no VHDR chunk)"); |
was_error = 1; |
goto done; |
} |
if ( (AIFFmagic == _8SVX) && !found_BODY ) { |
SDL_SetError("Bad 8SVX (no BODY chunk)"); |
was_error = 1; |
goto done; |
} |
/* Decode the audio data format */ |
memset(spec, 0, sizeof(*spec)); |
spec->freq = frequency; |
switch (samplesize) { |
case 8: |
spec->format = AUDIO_S8; |
break; |
case 16: |
spec->format = AUDIO_S16MSB; |
break; |
default: |
SDL_SetError("Unsupported AIFF samplesize"); |
was_error = 1; |
goto done; |
} |
spec->channels = (Uint8) channels; |
spec->samples = 4096; /* Good default buffer size */ |
*audio_len = channels * numsamples * (samplesize / 8); |
*audio_buf = (Uint8 *)SDL_malloc(*audio_len); |
if ( *audio_buf == NULL ) { |
SDL_SetError("Out of memory"); |
return(NULL); |
} |
SDL_RWseek(src, start, RW_SEEK_SET); |
if ( SDL_RWread(src, *audio_buf, *audio_len, 1) != 1 ) { |
SDL_SetError("Unable to read audio data"); |
return(NULL); |
} |
/* Don't return a buffer that isn't a multiple of samplesize */ |
*audio_len &= ~((samplesize / 8) - 1); |
done: |
if ( freesrc && src ) { |
SDL_RWclose(src); |
} |
if ( was_error ) { |
spec = NULL; |
} |
return(spec); |
} |
/contrib/games/wolf3d/SDL_mixer/load_aiff.h |
---|
0,0 → 1,31 |
/* |
SDL_mixer: An audio mixer library based on the SDL library |
Copyright (C) 1997-2009 Sam Lantinga |
This library is free software; you can redistribute it and/or |
modify it under the terms of the GNU Library General Public |
License as published by the Free Software Foundation; either |
version 2 of the License, or (at your option) any later version. |
This library is distributed in the hope that it will be useful, |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
Library General Public License for more details. |
You should have received a copy of the GNU Library General Public |
License along with this library; if not, write to the Free |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
This is the source needed to decode an AIFF file into a waveform. |
It's pretty straightforward once you get going. The only |
externally-callable function is Mix_LoadAIFF_RW(), which is meant to |
act as identically to SDL_LoadWAV_RW() as possible. |
This file by Torbjörn Andersson (torbjorn.andersson@eurotime.se) |
*/ |
/* $Id$ */ |
/* Don't call this directly; use Mix_LoadWAV_RW() for now. */ |
SDL_AudioSpec *Mix_LoadAIFF_RW (SDL_RWops *src, int freesrc, |
SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len); |
/contrib/games/wolf3d/SDL_mixer/load_flac.h |
---|
0,0 → 1,31 |
/* |
SDL_mixer: An audio mixer library based on the SDL library |
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org> |
This software is provided 'as-is', without any express or implied |
warranty. In no event will the authors be held liable for any damages |
arising from the use of this software. |
Permission is granted to anyone to use this software for any purpose, |
including commercial applications, and to alter it and redistribute it |
freely, subject to the following restrictions: |
1. The origin of this software must not be misrepresented; you must not |
claim that you wrote the original software. If you use this software |
in a product, an acknowledgment in the product documentation would be |
appreciated but is not required. |
2. Altered source versions must be plainly marked as such, and must not be |
misrepresented as being the original software. |
3. This notice may not be removed or altered from any source distribution. |
This is the source needed to decode a FLAC into a waveform. |
~ Austen Dicken (admin@cvpcs.org). |
*/ |
/* $Id: $ */ |
#ifdef FLAC_MUSIC |
/* Don't call this directly; use Mix_LoadWAV_RW() for now. */ |
SDL_AudioSpec *Mix_LoadFLAC_RW (SDL_RWops *src, int freesrc, |
SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len); |
#endif |
/contrib/games/wolf3d/SDL_mixer/load_ogg.h |
---|
0,0 → 1,31 |
/* |
SDL_mixer: An audio mixer library based on the SDL library |
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org> |
This software is provided 'as-is', without any express or implied |
warranty. In no event will the authors be held liable for any damages |
arising from the use of this software. |
Permission is granted to anyone to use this software for any purpose, |
including commercial applications, and to alter it and redistribute it |
freely, subject to the following restrictions: |
1. The origin of this software must not be misrepresented; you must not |
claim that you wrote the original software. If you use this software |
in a product, an acknowledgment in the product documentation would be |
appreciated but is not required. |
2. Altered source versions must be plainly marked as such, and must not be |
misrepresented as being the original software. |
3. This notice may not be removed or altered from any source distribution. |
This is the source needed to decode an Ogg Vorbis into a waveform. |
This file by Vaclav Slavik (vaclav.slavik@matfyz.cz). |
*/ |
/* $Id$ */ |
#ifdef OGG_MUSIC |
/* Don't call this directly; use Mix_LoadWAV_RW() for now. */ |
SDL_AudioSpec *Mix_LoadOGG_RW (SDL_RWops *src, int freesrc, |
SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len); |
#endif |
/contrib/games/wolf3d/SDL_mixer/load_voc.c |
---|
0,0 → 1,462 |
/* |
SDL_mixer: An audio mixer library based on the SDL library |
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org> |
This software is provided 'as-is', without any express or implied |
warranty. In no event will the authors be held liable for any damages |
arising from the use of this software. |
Permission is granted to anyone to use this software for any purpose, |
including commercial applications, and to alter it and redistribute it |
freely, subject to the following restrictions: |
1. The origin of this software must not be misrepresented; you must not |
claim that you wrote the original software. If you use this software |
in a product, an acknowledgment in the product documentation would be |
appreciated but is not required. |
2. Altered source versions must be plainly marked as such, and must not be |
misrepresented as being the original software. |
3. This notice may not be removed or altered from any source distribution. |
This is the source needed to decode a Creative Labs VOC file into a |
waveform. It's pretty straightforward once you get going. The only |
externally-callable function is Mix_LoadVOC_RW(), which is meant to |
act as identically to SDL_LoadWAV_RW() as possible. |
This file by Ryan C. Gordon (icculus@icculus.org). |
Heavily borrowed from sox v12.17.1's voc.c. |
(http://www.freshmeat.net/projects/sox/) |
*/ |
/* $Id$ */ |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
#include "SDL_mutex.h" |
#include "SDL_endian.h" |
#include "SDL_timer.h" |
#include "SDL_mixer.h" |
#include "load_voc.h" |
/* Private data for VOC file */ |
typedef struct vocstuff { |
Uint32 rest; /* bytes remaining in current block */ |
Uint32 rate; /* rate code (byte) of this chunk */ |
int silent; /* sound or silence? */ |
Uint32 srate; /* rate code (byte) of silence */ |
Uint32 blockseek; /* start of current output block */ |
Uint32 samples; /* number of samples output */ |
Uint32 size; /* word length of data */ |
Uint8 channels; /* number of sound channels */ |
int has_extended; /* Has an extended block been read? */ |
} vs_t; |
/* Size field */ |
/* SJB: note that the 1st 3 are sometimes used as sizeof(type) */ |
#define ST_SIZE_BYTE 1 |
#define ST_SIZE_8BIT 1 |
#define ST_SIZE_WORD 2 |
#define ST_SIZE_16BIT 2 |
#define ST_SIZE_DWORD 4 |
#define ST_SIZE_32BIT 4 |
#define ST_SIZE_FLOAT 5 |
#define ST_SIZE_DOUBLE 6 |
#define ST_SIZE_IEEE 7 /* IEEE 80-bit floats. */ |
/* Style field */ |
#define ST_ENCODING_UNSIGNED 1 /* unsigned linear: Sound Blaster */ |
#define ST_ENCODING_SIGN2 2 /* signed linear 2's comp: Mac */ |
#define ST_ENCODING_ULAW 3 /* U-law signed logs: US telephony, SPARC */ |
#define ST_ENCODING_ALAW 4 /* A-law signed logs: non-US telephony */ |
#define ST_ENCODING_ADPCM 5 /* Compressed PCM */ |
#define ST_ENCODING_IMA_ADPCM 6 /* Compressed PCM */ |
#define ST_ENCODING_GSM 7 /* GSM 6.10 33-byte frame lossy compression */ |
#define VOC_TERM 0 |
#define VOC_DATA 1 |
#define VOC_CONT 2 |
#define VOC_SILENCE 3 |
#define VOC_MARKER 4 |
#define VOC_TEXT 5 |
#define VOC_LOOP 6 |
#define VOC_LOOPEND 7 |
#define VOC_EXTENDED 8 |
#define VOC_DATA_16 9 |
static int voc_check_header(SDL_RWops *src) |
{ |
/* VOC magic header */ |
Uint8 signature[20]; /* "Creative Voice File\032" */ |
Uint16 datablockofs; |
SDL_RWseek(src, 0, RW_SEEK_SET); |
if (SDL_RWread(src, signature, sizeof (signature), 1) != 1) |
return(0); |
if (memcmp(signature, "Creative Voice File\032", sizeof (signature)) != 0) { |
SDL_SetError("Unrecognized file type (not VOC)"); |
return(0); |
} |
/* get the offset where the first datablock is located */ |
if (SDL_RWread(src, &datablockofs, sizeof (Uint16), 1) != 1) |
return(0); |
datablockofs = SDL_SwapLE16(datablockofs); |
if (SDL_RWseek(src, datablockofs, RW_SEEK_SET) != datablockofs) |
return(0); |
return(1); /* success! */ |
} /* voc_check_header */ |
/* Read next block header, save info, leave position at start of data */ |
static int voc_get_block(SDL_RWops *src, vs_t *v, SDL_AudioSpec *spec) |
{ |
Uint8 bits24[3]; |
Uint8 uc, block; |
Uint32 sblen; |
Uint16 new_rate_short; |
Uint32 new_rate_long; |
Uint8 trash[6]; |
Uint16 period; |
unsigned int i; |
v->silent = 0; |
while (v->rest == 0) |
{ |
if (SDL_RWread(src, &block, sizeof (block), 1) != 1) |
return 1; /* assume that's the end of the file. */ |
if (block == VOC_TERM) |
return 1; |
if (SDL_RWread(src, bits24, sizeof (bits24), 1) != 1) |
return 1; /* assume that's the end of the file. */ |
/* Size is an 24-bit value. Ugh. */ |
sblen = ( (bits24[0]) | (bits24[1] << 8) | (bits24[2] << 16) ); |
switch(block) |
{ |
case VOC_DATA: |
if (SDL_RWread(src, &uc, sizeof (uc), 1) != 1) |
return 0; |
/* When DATA block preceeded by an EXTENDED */ |
/* block, the DATA blocks rate value is invalid */ |
if (!v->has_extended) |
{ |
if (uc == 0) |
{ |
SDL_SetError("VOC Sample rate is zero?"); |
return 0; |
} |
if ((v->rate != -1) && (uc != v->rate)) |
{ |
SDL_SetError("VOC sample rate codes differ"); |
return 0; |
} |
v->rate = uc; |
spec->freq = (Uint16)(1000000.0/(256 - v->rate)); |
v->channels = 1; |
} |
if (SDL_RWread(src, &uc, sizeof (uc), 1) != 1) |
return 0; |
if (uc != 0) |
{ |
SDL_SetError("VOC decoder only interprets 8-bit data"); |
return 0; |
} |
v->has_extended = 0; |
v->rest = sblen - 2; |
v->size = ST_SIZE_BYTE; |
return 1; |
case VOC_DATA_16: |
if (SDL_RWread(src, &new_rate_long, sizeof (new_rate_long), 1) != 1) |
return 0; |
new_rate_long = SDL_SwapLE32(new_rate_long); |
if (new_rate_long == 0) |
{ |
SDL_SetError("VOC Sample rate is zero?"); |
return 0; |
} |
if ((v->rate != -1) && (new_rate_long != v->rate)) |
{ |
SDL_SetError("VOC sample rate codes differ"); |
return 0; |
} |
v->rate = new_rate_long; |
spec->freq = new_rate_long; |
if (SDL_RWread(src, &uc, sizeof (uc), 1) != 1) |
return 0; |
switch (uc) |
{ |
case 8: v->size = ST_SIZE_BYTE; break; |
case 16: v->size = ST_SIZE_WORD; break; |
default: |
SDL_SetError("VOC with unknown data size"); |
return 0; |
} |
if (SDL_RWread(src, &v->channels, sizeof (Uint8), 1) != 1) |
return 0; |
if (SDL_RWread(src, trash, sizeof (Uint8), 6) != 6) |
return 0; |
v->rest = sblen - 12; |
return 1; |
case VOC_CONT: |
v->rest = sblen; |
return 1; |
case VOC_SILENCE: |
if (SDL_RWread(src, &period, sizeof (period), 1) != 1) |
return 0; |
period = SDL_SwapLE16(period); |
if (SDL_RWread(src, &uc, sizeof (uc), 1) != 1) |
return 0; |
if (uc == 0) |
{ |
SDL_SetError("VOC silence sample rate is zero"); |
return 0; |
} |
/* |
* Some silence-packed files have gratuitously |
* different sample rate codes in silence. |
* Adjust period. |
*/ |
if ((v->rate != -1) && (uc != v->rate)) |
period = (Uint16)((period * (256 - uc))/(256 - v->rate)); |
else |
v->rate = uc; |
v->rest = period; |
v->silent = 1; |
return 1; |
case VOC_LOOP: |
case VOC_LOOPEND: |
for(i = 0; i < sblen; i++) /* skip repeat loops. */ |
{ |
if (SDL_RWread(src, trash, sizeof (Uint8), 1) != 1) |
return 0; |
} |
break; |
case VOC_EXTENDED: |
/* An Extended block is followed by a data block */ |
/* Set this byte so we know to use the rate */ |
/* value from the extended block and not the */ |
/* data block. */ |
v->has_extended = 1; |
if (SDL_RWread(src, &new_rate_short, sizeof (new_rate_short), 1) != 1) |
return 0; |
new_rate_short = SDL_SwapLE16(new_rate_short); |
if (new_rate_short == 0) |
{ |
SDL_SetError("VOC sample rate is zero"); |
return 0; |
} |
if ((v->rate != -1) && (new_rate_short != v->rate)) |
{ |
SDL_SetError("VOC sample rate codes differ"); |
return 0; |
} |
v->rate = new_rate_short; |
if (SDL_RWread(src, &uc, sizeof (uc), 1) != 1) |
return 0; |
if (uc != 0) |
{ |
SDL_SetError("VOC decoder only interprets 8-bit data"); |
return 0; |
} |
if (SDL_RWread(src, &uc, sizeof (uc), 1) != 1) |
return 0; |
if (uc) |
spec->channels = 2; /* Stereo */ |
/* Needed number of channels before finishing |
compute for rate */ |
spec->freq = (256000000L/(65536L - v->rate))/spec->channels; |
/* An extended block must be followed by a data */ |
/* block to be valid so loop back to top so it */ |
/* can be grabed. */ |
continue; |
case VOC_MARKER: |
if (SDL_RWread(src, trash, sizeof (Uint8), 2) != 2) |
return 0; |
/* Falling! Falling! */ |
default: /* text block or other krapola. */ |
for(i = 0; i < sblen; i++) |
{ |
if (SDL_RWread(src, &trash, sizeof (Uint8), 1) != 1) |
return 0; |
} |
if (block == VOC_TEXT) |
continue; /* get next block */ |
} |
} |
return 1; |
} |
static int voc_read(SDL_RWops *src, vs_t *v, Uint8 *buf, SDL_AudioSpec *spec) |
{ |
int done = 0; |
Uint8 silence = 0x80; |
if (v->rest == 0) |
{ |
if (!voc_get_block(src, v, spec)) |
return 0; |
} |
if (v->rest == 0) |
return 0; |
if (v->silent) |
{ |
if (v->size == ST_SIZE_WORD) |
silence = 0x00; |
/* Fill in silence */ |
memset(buf, silence, v->rest); |
done = v->rest; |
v->rest = 0; |
} |
else |
{ |
done = SDL_RWread(src, buf, 1, v->rest); |
v->rest -= done; |
if (v->size == ST_SIZE_WORD) |
{ |
#if (SDL_BYTEORDER == SDL_BIG_ENDIAN) |
Uint16 *samples = (Uint16 *)buf; |
for (; v->rest > 0; v->rest -= 2) |
{ |
*samples = SDL_SwapLE16(*samples); |
samples++; |
} |
#endif |
done >>= 1; |
} |
} |
return done; |
} /* voc_read */ |
/* don't call this directly; use Mix_LoadWAV_RW() for now. */ |
SDL_AudioSpec *Mix_LoadVOC_RW (SDL_RWops *src, int freesrc, |
SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len) |
{ |
vs_t v; |
int was_error = 1; |
int samplesize; |
Uint8 *fillptr; |
void *ptr; |
if ( (!src) || (!audio_buf) || (!audio_len) ) /* sanity checks. */ |
goto done; |
if ( !voc_check_header(src) ) |
goto done; |
v.rate = -1; |
v.rest = 0; |
v.has_extended = 0; |
*audio_buf = NULL; |
*audio_len = 0; |
memset(spec, '\0', sizeof (SDL_AudioSpec)); |
if (!voc_get_block(src, &v, spec)) |
goto done; |
if (v.rate == -1) |
{ |
SDL_SetError("VOC data had no sound!"); |
goto done; |
} |
spec->format = ((v.size == ST_SIZE_WORD) ? AUDIO_S16 : AUDIO_U8); |
if (spec->channels == 0) |
spec->channels = v.channels; |
*audio_len = v.rest; |
*audio_buf = SDL_malloc(v.rest); |
if (*audio_buf == NULL) |
goto done; |
fillptr = *audio_buf; |
while (voc_read(src, &v, fillptr, spec) > 0) |
{ |
if (!voc_get_block(src, &v, spec)) |
goto done; |
*audio_len += v.rest; |
ptr = SDL_realloc(*audio_buf, *audio_len); |
if (ptr == NULL) |
{ |
SDL_free(*audio_buf); |
*audio_buf = NULL; |
*audio_len = 0; |
goto done; |
} |
*audio_buf = ptr; |
fillptr = ((Uint8 *) ptr) + (*audio_len - v.rest); |
} |
spec->samples = (Uint16)(*audio_len / v.size); |
was_error = 0; /* success, baby! */ |
/* Don't return a buffer that isn't a multiple of samplesize */ |
samplesize = ((spec->format & 0xFF)/8)*spec->channels; |
*audio_len &= ~(samplesize-1); |
done: |
if (src) |
{ |
if (freesrc) |
SDL_RWclose(src); |
else |
SDL_RWseek(src, 0, RW_SEEK_SET); |
} |
if ( was_error ) |
spec = NULL; |
return(spec); |
} /* Mix_LoadVOC_RW */ |
/* end of load_voc.c ... */ |
/contrib/games/wolf3d/SDL_mixer/load_voc.h |
---|
0,0 → 1,36 |
/* |
SDL_mixer: An audio mixer library based on the SDL library |
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org> |
This software is provided 'as-is', without any express or implied |
warranty. In no event will the authors be held liable for any damages |
arising from the use of this software. |
Permission is granted to anyone to use this software for any purpose, |
including commercial applications, and to alter it and redistribute it |
freely, subject to the following restrictions: |
1. The origin of this software must not be misrepresented; you must not |
claim that you wrote the original software. If you use this software |
in a product, an acknowledgment in the product documentation would be |
appreciated but is not required. |
2. Altered source versions must be plainly marked as such, and must not be |
misrepresented as being the original software. |
3. This notice may not be removed or altered from any source distribution. |
This is the source needed to decode a Creative Labs VOC file into a |
waveform. It's pretty straightforward once you get going. The only |
externally-callable function is Mix_LoadVOC_RW(), which is meant to |
act as identically to SDL_LoadWAV_RW() as possible. |
This file by Ryan C. Gordon (icculus@icculus.org). |
Heavily borrowed from sox v12.17.1's voc.c. |
(http://www.freshmeat.net/projects/sox/) |
*/ |
/* $Id$ */ |
/* Don't call this directly; use Mix_LoadWAV_RW() for now. */ |
SDL_AudioSpec *Mix_LoadVOC_RW (SDL_RWops *src, int freesrc, |
SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len); |
/contrib/games/wolf3d/SDL_mixer/mixer.c |
---|
0,0 → 1,1488 |
/* |
SDL_mixer: An audio mixer library based on the SDL library |
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org> |
This software is provided 'as-is', without any express or implied |
warranty. In no event will the authors be held liable for any damages |
arising from the use of this software. |
Permission is granted to anyone to use this software for any purpose, |
including commercial applications, and to alter it and redistribute it |
freely, subject to the following restrictions: |
1. The origin of this software must not be misrepresented; you must not |
claim that you wrote the original software. If you use this software |
in a product, an acknowledgment in the product documentation would be |
appreciated but is not required. |
2. Altered source versions must be plainly marked as such, and must not be |
misrepresented as being the original software. |
3. This notice may not be removed or altered from any source distribution. |
*/ |
/* $Id$ */ |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
#include "SDL_mutex.h" |
#include "SDL_endian.h" |
#include "SDL_timer.h" |
#include "SDL_mixer.h" |
#include "load_aiff.h" |
#include "load_voc.h" |
#include "load_ogg.h" |
#include "load_flac.h" |
#include "dynamic_flac.h" |
#include "dynamic_mod.h" |
#include "dynamic_mp3.h" |
#include "dynamic_ogg.h" |
#define __MIX_INTERNAL_EFFECT__ |
#include "effects_internal.h" |
/* Magic numbers for various audio file formats */ |
#define RIFF 0x46464952 /* "RIFF" */ |
#define WAVE 0x45564157 /* "WAVE" */ |
#define FORM 0x4d524f46 /* "FORM" */ |
#define OGGS 0x5367674f /* "OggS" */ |
#define CREA 0x61657243 /* "Crea" */ |
#define FLAC 0x43614C66 /* "fLaC" */ |
static int audio_opened = 0; |
static SDL_AudioSpec mixer; |
typedef struct _Mix_effectinfo |
{ |
Mix_EffectFunc_t callback; |
Mix_EffectDone_t done_callback; |
void *udata; |
struct _Mix_effectinfo *next; |
} effect_info; |
static struct _Mix_Channel { |
Mix_Chunk *chunk; |
int playing; |
int paused; |
Uint8 *samples; |
int volume; |
int looping; |
int tag; |
Uint32 expire; |
Uint32 start_time; |
Mix_Fading fading; |
int fade_volume; |
int fade_volume_reset; |
Uint32 fade_length; |
Uint32 ticks_fade; |
effect_info *effects; |
} *mix_channel = NULL; |
static effect_info *posteffects = NULL; |
static int num_channels; |
static int reserved_channels = 0; |
/* Support for hooking into the mixer callback system */ |
static void (*mix_postmix)(void *udata, Uint8 *stream, int len) = NULL; |
static void *mix_postmix_data = NULL; |
/* rcg07062001 callback to alert when channels are done playing. */ |
static void (*channel_done_callback)(int channel) = NULL; |
/* Music function declarations */ |
extern int open_music(SDL_AudioSpec *mixer); |
extern void close_music(void); |
/* Support for user defined music functions, plus the default one */ |
extern int volatile music_active; |
extern void music_mixer(void *udata, Uint8 *stream, int len); |
static void (*mix_music)(void *udata, Uint8 *stream, int len) = music_mixer; |
static void *music_data = NULL; |
/* rcg06042009 report available decoders at runtime. */ |
static const char **chunk_decoders = NULL; |
static int num_decoders = 0; |
/* Semicolon-separated SoundFont paths */ |
#ifdef MID_MUSIC |
extern char* soundfont_paths; |
#endif |
int Mix_GetNumChunkDecoders(void) |
{ |
return(num_decoders); |
} |
const char *Mix_GetChunkDecoder(int index) |
{ |
if ((index < 0) || (index >= num_decoders)) { |
return NULL; |
} |
return(chunk_decoders[index]); |
} |
static void add_chunk_decoder(const char *decoder) |
{ |
void *ptr = SDL_realloc(chunk_decoders, (num_decoders + 1) * sizeof (const char **)); |
if (ptr == NULL) { |
return; /* oh well, go on without it. */ |
} |
chunk_decoders = (const char **) ptr; |
chunk_decoders[num_decoders++] = decoder; |
} |
/* rcg06192001 get linked library's version. */ |
const SDL_version *Mix_Linked_Version(void) |
{ |
static SDL_version linked_version; |
SDL_MIXER_VERSION(&linked_version); |
return(&linked_version); |
} |
static int initialized = 0; |
int Mix_Init(int flags) |
{ |
int result = 0; |
if (flags & MIX_INIT_FLUIDSYNTH) { |
#ifdef USE_FLUIDSYNTH_MIDI |
if ((initialized & MIX_INIT_FLUIDSYNTH) || Mix_InitFluidSynth() == 0) { |
result |= MIX_INIT_FLUIDSYNTH; |
} |
#else |
Mix_SetError("Mixer not built with FluidSynth support"); |
#endif |
} |
if (flags & MIX_INIT_FLAC) { |
#ifdef FLAC_MUSIC |
if ((initialized & MIX_INIT_FLAC) || Mix_InitFLAC() == 0) { |
result |= MIX_INIT_FLAC; |
} |
#else |
Mix_SetError("Mixer not built with FLAC support"); |
#endif |
} |
if (flags & MIX_INIT_MOD) { |
#ifdef MOD_MUSIC |
if ((initialized & MIX_INIT_MOD) || Mix_InitMOD() == 0) { |
result |= MIX_INIT_MOD; |
} |
#else |
Mix_SetError("Mixer not built with MOD support"); |
#endif |
} |
if (flags & MIX_INIT_MP3) { |
#ifdef MP3_MUSIC |
if ((initialized & MIX_INIT_MP3) || Mix_InitMP3() == 0) { |
result |= MIX_INIT_MP3; |
} |
#else |
Mix_SetError("Mixer not built with MP3 support"); |
#endif |
} |
if (flags & MIX_INIT_OGG) { |
#ifdef OGG_MUSIC |
if ((initialized & MIX_INIT_OGG) || Mix_InitOgg() == 0) { |
result |= MIX_INIT_OGG; |
} |
#else |
Mix_SetError("Mixer not built with Ogg Vorbis support"); |
#endif |
} |
initialized |= result; |
return (result); |
} |
void Mix_Quit() |
{ |
#ifdef USE_FLUIDSYNTH_MIDI |
if (initialized & MIX_INIT_FLUIDSYNTH) { |
Mix_QuitFluidSynth(); |
} |
#endif |
#ifdef FLAC_MUSIC |
if (initialized & MIX_INIT_FLAC) { |
Mix_QuitFLAC(); |
} |
#endif |
#ifdef MOD_MUSIC |
if (initialized & MIX_INIT_MOD) { |
Mix_QuitMOD(); |
} |
#endif |
#ifdef MP3_MUSIC |
if (initialized & MIX_INIT_MP3) { |
Mix_QuitMP3(); |
} |
#endif |
#ifdef OGG_MUSIC |
if (initialized & MIX_INIT_OGG) { |
Mix_QuitOgg(); |
} |
#endif |
#ifdef MID_MUSIC |
if (soundfont_paths) { |
SDL_free(soundfont_paths); |
} |
#endif |
initialized = 0; |
} |
static int _Mix_remove_all_effects(int channel, effect_info **e); |
/* |
* rcg06122001 Cleanup effect callbacks. |
* MAKE SURE SDL_LockAudio() is called before this (or you're in the |
* audio callback). |
*/ |
static void _Mix_channel_done_playing(int channel) |
{ |
if (channel_done_callback) { |
channel_done_callback(channel); |
} |
/* |
* Call internal function directly, to avoid locking audio from |
* inside audio callback. |
*/ |
_Mix_remove_all_effects(channel, &mix_channel[channel].effects); |
} |
static void *Mix_DoEffects(int chan, void *snd, int len) |
{ |
int posteffect = (chan == MIX_CHANNEL_POST); |
effect_info *e = ((posteffect) ? posteffects : mix_channel[chan].effects); |
void *buf = snd; |
if (e != NULL) { /* are there any registered effects? */ |
/* if this is the postmix, we can just overwrite the original. */ |
if (!posteffect) { |
buf = SDL_malloc(len); |
if (buf == NULL) { |
return(snd); |
} |
memcpy(buf, snd, len); |
} |
for (; e != NULL; e = e->next) { |
if (e->callback != NULL) { |
e->callback(chan, buf, len, e->udata); |
} |
} |
} |
/* be sure to SDL_free() the return value if != snd ... */ |
return(buf); |
} |
/* Mixing function */ |
static void mix_channels(void *udata, Uint8 *stream, int len) |
{ |
Uint8 *mix_input; |
int i, mixable, volume = SDL_MIX_MAXVOLUME; |
Uint32 sdl_ticks; |
#if SDL_VERSION_ATLEAST(1, 3, 0) |
/* Need to initialize the stream in SDL 1.3+ */ |
memset(stream, mixer.silence, len); |
#endif |
/* Mix the music (must be done before the channels are added) */ |
if ( music_active || (mix_music != music_mixer) ) { |
mix_music(music_data, stream, len); |
} |
/* Mix any playing channels... */ |
sdl_ticks = SDL_GetTicks(); |
for ( i=0; i<num_channels; ++i ) { |
if( ! mix_channel[i].paused ) { |
if ( mix_channel[i].expire > 0 && mix_channel[i].expire < sdl_ticks ) { |
/* Expiration delay for that channel is reached */ |
mix_channel[i].playing = 0; |
mix_channel[i].looping = 0; |
mix_channel[i].fading = MIX_NO_FADING; |
mix_channel[i].expire = 0; |
_Mix_channel_done_playing(i); |
} else if ( mix_channel[i].fading != MIX_NO_FADING ) { |
Uint32 ticks = sdl_ticks - mix_channel[i].ticks_fade; |
if( ticks > mix_channel[i].fade_length ) { |
Mix_Volume(i, mix_channel[i].fade_volume_reset); /* Restore the volume */ |
if( mix_channel[i].fading == MIX_FADING_OUT ) { |
mix_channel[i].playing = 0; |
mix_channel[i].looping = 0; |
mix_channel[i].expire = 0; |
_Mix_channel_done_playing(i); |
} |
mix_channel[i].fading = MIX_NO_FADING; |
} else { |
if( mix_channel[i].fading == MIX_FADING_OUT ) { |
Mix_Volume(i, (mix_channel[i].fade_volume * (mix_channel[i].fade_length-ticks)) |
/ mix_channel[i].fade_length ); |
} else { |
Mix_Volume(i, (mix_channel[i].fade_volume * ticks) / mix_channel[i].fade_length ); |
} |
} |
} |
if ( mix_channel[i].playing > 0 ) { |
int index = 0; |
int remaining = len; |
while (mix_channel[i].playing > 0 && index < len) { |
remaining = len - index; |
volume = (mix_channel[i].volume*mix_channel[i].chunk->volume) / MIX_MAX_VOLUME; |
mixable = mix_channel[i].playing; |
if ( mixable > remaining ) { |
mixable = remaining; |
} |
mix_input = Mix_DoEffects(i, mix_channel[i].samples, mixable); |
SDL_MixAudio(stream+index,mix_input,mixable,volume); |
if (mix_input != mix_channel[i].samples) |
SDL_free(mix_input); |
mix_channel[i].samples += mixable; |
mix_channel[i].playing -= mixable; |
index += mixable; |
/* rcg06072001 Alert app if channel is done playing. */ |
if (!mix_channel[i].playing && !mix_channel[i].looping) { |
_Mix_channel_done_playing(i); |
} |
} |
/* If looping the sample and we are at its end, make sure |
we will still return a full buffer */ |
while ( mix_channel[i].looping && index < len ) { |
int alen = mix_channel[i].chunk->alen; |
remaining = len - index; |
if (remaining > alen) { |
remaining = alen; |
} |
mix_input = Mix_DoEffects(i, mix_channel[i].chunk->abuf, remaining); |
SDL_MixAudio(stream+index, mix_input, remaining, volume); |
if (mix_input != mix_channel[i].chunk->abuf) |
SDL_free(mix_input); |
--mix_channel[i].looping; |
mix_channel[i].samples = mix_channel[i].chunk->abuf + remaining; |
mix_channel[i].playing = mix_channel[i].chunk->alen - remaining; |
index += remaining; |
} |
if ( ! mix_channel[i].playing && mix_channel[i].looping ) { |
--mix_channel[i].looping; |
mix_channel[i].samples = mix_channel[i].chunk->abuf; |
mix_channel[i].playing = mix_channel[i].chunk->alen; |
} |
} |
} |
} |
/* rcg06122001 run posteffects... */ |
Mix_DoEffects(MIX_CHANNEL_POST, stream, len); |
if ( mix_postmix ) { |
mix_postmix(mix_postmix_data, stream, len); |
} |
} |
#if 0 |
static void PrintFormat(char *title, SDL_AudioSpec *fmt) |
{ |
printf("%s: %d bit %s audio (%s) at %u Hz\n", title, (fmt->format&0xFF), |
(fmt->format&0x8000) ? "signed" : "unsigned", |
(fmt->channels > 2) ? "surround" : |
(fmt->channels > 1) ? "stereo" : "mono", fmt->freq); |
} |
#endif |
/* Open the mixer with a certain desired audio format */ |
int Mix_OpenAudio(int frequency, Uint16 format, int nchannels, int chunksize) |
{ |
int i; |
SDL_AudioSpec desired; |
/* If the mixer is already opened, increment open count */ |
if ( audio_opened ) { |
if ( format == mixer.format && nchannels == mixer.channels ) { |
++audio_opened; |
return(0); |
} |
while ( audio_opened ) { |
Mix_CloseAudio(); |
} |
} |
/* Set the desired format and frequency */ |
desired.freq = frequency; |
desired.format = format; |
desired.channels = nchannels; |
desired.samples = chunksize; |
desired.callback = mix_channels; |
desired.userdata = NULL; |
/* Accept nearly any audio format */ |
if ( SDL_OpenAudio(&desired, &mixer) < 0 ) { |
return(-1); |
} |
#if 0 |
PrintFormat("Audio device", &mixer); |
#endif |
/* Initialize the music players */ |
if ( open_music(&mixer) < 0 ) { |
SDL_CloseAudio(); |
return(-1); |
} |
num_channels = MIX_CHANNELS; |
mix_channel = (struct _Mix_Channel *) SDL_malloc(num_channels * sizeof(struct _Mix_Channel)); |
/* Clear out the audio channels */ |
for ( i=0; i<num_channels; ++i ) { |
mix_channel[i].chunk = NULL; |
mix_channel[i].playing = 0; |
mix_channel[i].looping = 0; |
mix_channel[i].volume = SDL_MIX_MAXVOLUME; |
mix_channel[i].fade_volume = SDL_MIX_MAXVOLUME; |
mix_channel[i].fade_volume_reset = SDL_MIX_MAXVOLUME; |
mix_channel[i].fading = MIX_NO_FADING; |
mix_channel[i].tag = -1; |
mix_channel[i].expire = 0; |
mix_channel[i].effects = NULL; |
mix_channel[i].paused = 0; |
} |
Mix_VolumeMusic(SDL_MIX_MAXVOLUME); |
_Mix_InitEffects(); |
/* This list is (currently) decided at build time. */ |
add_chunk_decoder("WAVE"); |
add_chunk_decoder("AIFF"); |
add_chunk_decoder("VOC"); |
#ifdef OGG_MUSIC |
add_chunk_decoder("OGG"); |
#endif |
#ifdef FLAC_MUSIC |
add_chunk_decoder("FLAC"); |
#endif |
audio_opened = 1; |
SDL_PauseAudio(0); |
return(0); |
} |
/* Dynamically change the number of channels managed by the mixer. |
If decreasing the number of channels, the upper channels are |
stopped. |
*/ |
int Mix_AllocateChannels(int numchans) |
{ |
if ( numchans<0 || numchans==num_channels ) |
return(num_channels); |
if ( numchans < num_channels ) { |
/* Stop the affected channels */ |
int i; |
for(i=numchans; i < num_channels; i++) { |
Mix_UnregisterAllEffects(i); |
Mix_HaltChannel(i); |
} |
} |
SDL_LockAudio(); |
mix_channel = (struct _Mix_Channel *) SDL_realloc(mix_channel, numchans * sizeof(struct _Mix_Channel)); |
if ( numchans > num_channels ) { |
/* Initialize the new channels */ |
int i; |
for(i=num_channels; i < numchans; i++) { |
mix_channel[i].chunk = NULL; |
mix_channel[i].playing = 0; |
mix_channel[i].looping = 0; |
mix_channel[i].volume = SDL_MIX_MAXVOLUME; |
mix_channel[i].fade_volume = SDL_MIX_MAXVOLUME; |
mix_channel[i].fade_volume_reset = SDL_MIX_MAXVOLUME; |
mix_channel[i].fading = MIX_NO_FADING; |
mix_channel[i].tag = -1; |
mix_channel[i].expire = 0; |
mix_channel[i].effects = NULL; |
mix_channel[i].paused = 0; |
} |
} |
num_channels = numchans; |
SDL_UnlockAudio(); |
return(num_channels); |
} |
/* Return the actual mixer parameters */ |
int Mix_QuerySpec(int *frequency, Uint16 *format, int *channels) |
{ |
if ( audio_opened ) { |
if ( frequency ) { |
*frequency = mixer.freq; |
} |
if ( format ) { |
*format = mixer.format; |
} |
if ( channels ) { |
*channels = mixer.channels; |
} |
} |
return(audio_opened); |
} |
/* |
* !!! FIXME: Ideally, we want a Mix_LoadSample_RW(), which will handle the |
* generic setup, then call the correct file format loader. |
*/ |
/* Load a wave file */ |
Mix_Chunk *Mix_LoadWAV_RW(SDL_RWops *src, int freesrc) |
{ |
Uint32 magic; |
Mix_Chunk *chunk; |
SDL_AudioSpec wavespec, *loaded; |
SDL_AudioCVT wavecvt; |
int samplesize; |
/* rcg06012001 Make sure src is valid */ |
if ( ! src ) { |
SDL_SetError("Mix_LoadWAV_RW with NULL src"); |
return(NULL); |
} |
/* Make sure audio has been opened */ |
if ( ! audio_opened ) { |
SDL_SetError("Audio device hasn't been opened"); |
if ( freesrc && src ) { |
SDL_RWclose(src); |
} |
return(NULL); |
} |
/* Allocate the chunk memory */ |
chunk = (Mix_Chunk *)SDL_malloc(sizeof(Mix_Chunk)); |
if ( chunk == NULL ) { |
SDL_SetError("Out of memory"); |
if ( freesrc ) { |
SDL_RWclose(src); |
} |
return(NULL); |
} |
/* Find out what kind of audio file this is */ |
magic = SDL_ReadLE32(src); |
/* Seek backwards for compatibility with older loaders */ |
SDL_RWseek(src, -(int)sizeof(Uint32), SEEK_CUR); |
switch (magic) { |
case WAVE: |
case RIFF: |
loaded = SDL_LoadWAV_RW(src, freesrc, &wavespec, |
(Uint8 **)&chunk->abuf, &chunk->alen); |
break; |
case FORM: |
loaded = Mix_LoadAIFF_RW(src, freesrc, &wavespec, |
(Uint8 **)&chunk->abuf, &chunk->alen); |
break; |
#ifdef OGG_MUSIC |
case OGGS: |
loaded = Mix_LoadOGG_RW(src, freesrc, &wavespec, |
(Uint8 **)&chunk->abuf, &chunk->alen); |
break; |
#endif |
#ifdef FLAC_MUSIC |
case FLAC: |
loaded = Mix_LoadFLAC_RW(src, freesrc, &wavespec, |
(Uint8 **)&chunk->abuf, &chunk->alen); |
break; |
#endif |
case CREA: |
loaded = Mix_LoadVOC_RW(src, freesrc, &wavespec, |
(Uint8 **)&chunk->abuf, &chunk->alen); |
break; |
default: |
SDL_SetError("Unrecognized sound file type"); |
return(0); |
} |
if ( !loaded ) { |
SDL_free(chunk); |
if ( freesrc ) { |
SDL_RWclose(src); |
} |
return(NULL); |
} |
#if 0 |
PrintFormat("Audio device", &mixer); |
PrintFormat("-- Wave file", &wavespec); |
#endif |
/* Build the audio converter and create conversion buffers */ |
if ( wavespec.format != mixer.format || |
wavespec.channels != mixer.channels || |
wavespec.freq != mixer.freq ) { |
if ( SDL_BuildAudioCVT(&wavecvt, |
wavespec.format, wavespec.channels, wavespec.freq, |
mixer.format, mixer.channels, mixer.freq) < 0 ) { |
SDL_free(chunk->abuf); |
SDL_free(chunk); |
return(NULL); |
} |
samplesize = ((wavespec.format & 0xFF)/8)*wavespec.channels; |
wavecvt.len = chunk->alen & ~(samplesize-1); |
wavecvt.buf = (Uint8 *)SDL_calloc(1, wavecvt.len*wavecvt.len_mult); |
if ( wavecvt.buf == NULL ) { |
SDL_SetError("Out of memory"); |
SDL_free(chunk->abuf); |
SDL_free(chunk); |
return(NULL); |
} |
memcpy(wavecvt.buf, chunk->abuf, chunk->alen); |
SDL_free(chunk->abuf); |
/* Run the audio converter */ |
if ( SDL_ConvertAudio(&wavecvt) < 0 ) { |
SDL_free(wavecvt.buf); |
SDL_free(chunk); |
return(NULL); |
} |
chunk->abuf = wavecvt.buf; |
chunk->alen = wavecvt.len_cvt; |
} |
chunk->allocated = 1; |
chunk->volume = MIX_MAX_VOLUME; |
return(chunk); |
} |
/* Load a wave file of the mixer format from a memory buffer */ |
Mix_Chunk *Mix_QuickLoad_WAV(Uint8 *mem) |
{ |
Mix_Chunk *chunk; |
Uint8 magic[4]; |
/* Make sure audio has been opened */ |
if ( ! audio_opened ) { |
SDL_SetError("Audio device hasn't been opened"); |
return(NULL); |
} |
/* Allocate the chunk memory */ |
chunk = (Mix_Chunk *)SDL_calloc(1,sizeof(Mix_Chunk)); |
if ( chunk == NULL ) { |
SDL_SetError("Out of memory"); |
return(NULL); |
} |
/* Essentially just skip to the audio data (no error checking - fast) */ |
chunk->allocated = 0; |
mem += 12; /* WAV header */ |
do { |
memcpy(magic, mem, 4); |
mem += 4; |
chunk->alen = ((mem[3]<<24)|(mem[2]<<16)|(mem[1]<<8)|(mem[0])); |
mem += 4; |
chunk->abuf = mem; |
mem += chunk->alen; |
} while ( memcmp(magic, "data", 4) != 0 ); |
chunk->volume = MIX_MAX_VOLUME; |
return(chunk); |
} |
/* Load raw audio data of the mixer format from a memory buffer */ |
Mix_Chunk *Mix_QuickLoad_RAW(Uint8 *mem, Uint32 len) |
{ |
Mix_Chunk *chunk; |
/* Make sure audio has been opened */ |
if ( ! audio_opened ) { |
SDL_SetError("Audio device hasn't been opened"); |
return(NULL); |
} |
/* Allocate the chunk memory */ |
chunk = (Mix_Chunk *)SDL_malloc(sizeof(Mix_Chunk)); |
if ( chunk == NULL ) { |
SDL_SetError("Out of memory"); |
return(NULL); |
} |
/* Essentially just point at the audio data (no error checking - fast) */ |
chunk->allocated = 0; |
chunk->alen = len; |
chunk->abuf = mem; |
chunk->volume = MIX_MAX_VOLUME; |
return(chunk); |
} |
/* Free an audio chunk previously loaded */ |
void Mix_FreeChunk(Mix_Chunk *chunk) |
{ |
int i; |
/* Caution -- if the chunk is playing, the mixer will crash */ |
if ( chunk ) { |
/* Guarantee that this chunk isn't playing */ |
SDL_LockAudio(); |
if ( mix_channel ) { |
for ( i=0; i<num_channels; ++i ) { |
if ( chunk == mix_channel[i].chunk ) { |
mix_channel[i].playing = 0; |
mix_channel[i].looping = 0; |
} |
} |
} |
SDL_UnlockAudio(); |
/* Actually free the chunk */ |
if ( chunk->allocated ) { |
SDL_free(chunk->abuf); |
} |
SDL_free(chunk); |
} |
} |
/* Set a function that is called after all mixing is performed. |
This can be used to provide real-time visual display of the audio stream |
or add a custom mixer filter for the stream data. |
*/ |
void Mix_SetPostMix(void (*mix_func) |
(void *udata, Uint8 *stream, int len), void *arg) |
{ |
SDL_LockAudio(); |
mix_postmix_data = arg; |
mix_postmix = mix_func; |
SDL_UnlockAudio(); |
} |
/* Add your own music player or mixer function. |
If 'mix_func' is NULL, the default music player is re-enabled. |
*/ |
void Mix_HookMusic(void (*mix_func)(void *udata, Uint8 *stream, int len), |
void *arg) |
{ |
SDL_LockAudio(); |
if ( mix_func != NULL ) { |
music_data = arg; |
mix_music = mix_func; |
} else { |
music_data = NULL; |
mix_music = music_mixer; |
} |
SDL_UnlockAudio(); |
} |
void *Mix_GetMusicHookData(void) |
{ |
return(music_data); |
} |
void Mix_ChannelFinished(void (*channel_finished)(int channel)) |
{ |
SDL_LockAudio(); |
channel_done_callback = channel_finished; |
SDL_UnlockAudio(); |
} |
/* Reserve the first channels (0 -> n-1) for the application, i.e. don't allocate |
them dynamically to the next sample if requested with a -1 value below. |
Returns the number of reserved channels. |
*/ |
int Mix_ReserveChannels(int num) |
{ |
if (num > num_channels) |
num = num_channels; |
reserved_channels = num; |
return num; |
} |
static int checkchunkintegral(Mix_Chunk *chunk) |
{ |
int frame_width = 1; |
if ((mixer.format & 0xFF) == 16) frame_width = 2; |
frame_width *= mixer.channels; |
while (chunk->alen % frame_width) chunk->alen--; |
return chunk->alen; |
} |
/* Play an audio chunk on a specific channel. |
If the specified channel is -1, play on the first free channel. |
'ticks' is the number of milliseconds at most to play the sample, or -1 |
if there is no limit. |
Returns which channel was used to play the sound. |
*/ |
int Mix_PlayChannelTimed(int which, Mix_Chunk *chunk, int loops, int ticks) |
{ |
int i; |
/* Don't play null pointers :-) */ |
if ( chunk == NULL ) { |
Mix_SetError("Tried to play a NULL chunk"); |
return(-1); |
} |
if ( !checkchunkintegral(chunk)) { |
Mix_SetError("Tried to play a chunk with a bad frame"); |
return(-1); |
} |
/* Lock the mixer while modifying the playing channels */ |
SDL_LockAudio(); |
{ |
/* If which is -1, play on the first free channel */ |
if ( which == -1 ) { |
for ( i=reserved_channels; i<num_channels; ++i ) { |
if ( mix_channel[i].playing <= 0 ) |
break; |
} |
if ( i == num_channels ) { |
Mix_SetError("No free channels available"); |
which = -1; |
} else { |
which = i; |
} |
} |
/* Queue up the audio data for this channel */ |
if ( which >= 0 && which < num_channels ) { |
Uint32 sdl_ticks = SDL_GetTicks(); |
if (Mix_Playing(which)) |
_Mix_channel_done_playing(which); |
mix_channel[which].samples = chunk->abuf; |
mix_channel[which].playing = chunk->alen; |
mix_channel[which].looping = loops; |
mix_channel[which].chunk = chunk; |
mix_channel[which].paused = 0; |
mix_channel[which].fading = MIX_NO_FADING; |
mix_channel[which].start_time = sdl_ticks; |
mix_channel[which].expire = (ticks>0) ? (sdl_ticks + ticks) : 0; |
} |
} |
SDL_UnlockAudio(); |
/* Return the channel on which the sound is being played */ |
return(which); |
} |
/* Change the expiration delay for a channel */ |
int Mix_ExpireChannel(int which, int ticks) |
{ |
int status = 0; |
if ( which == -1 ) { |
int i; |
for ( i=0; i < num_channels; ++ i ) { |
status += Mix_ExpireChannel(i, ticks); |
} |
} else if ( which < num_channels ) { |
SDL_LockAudio(); |
mix_channel[which].expire = (ticks>0) ? (SDL_GetTicks() + ticks) : 0; |
SDL_UnlockAudio(); |
++ status; |
} |
return(status); |
} |
/* Fade in a sound on a channel, over ms milliseconds */ |
int Mix_FadeInChannelTimed(int which, Mix_Chunk *chunk, int loops, int ms, int ticks) |
{ |
int i; |
/* Don't play null pointers :-) */ |
if ( chunk == NULL ) { |
return(-1); |
} |
if ( !checkchunkintegral(chunk)) { |
Mix_SetError("Tried to play a chunk with a bad frame"); |
return(-1); |
} |
/* Lock the mixer while modifying the playing channels */ |
SDL_LockAudio(); |
{ |
/* If which is -1, play on the first free channel */ |
if ( which == -1 ) { |
for ( i=reserved_channels; i<num_channels; ++i ) { |
if ( mix_channel[i].playing <= 0 ) |
break; |
} |
if ( i == num_channels ) { |
which = -1; |
} else { |
which = i; |
} |
} |
/* Queue up the audio data for this channel */ |
if ( which >= 0 && which < num_channels ) { |
Uint32 sdl_ticks = SDL_GetTicks(); |
if (Mix_Playing(which)) |
_Mix_channel_done_playing(which); |
mix_channel[which].samples = chunk->abuf; |
mix_channel[which].playing = chunk->alen; |
mix_channel[which].looping = loops; |
mix_channel[which].chunk = chunk; |
mix_channel[which].paused = 0; |
mix_channel[which].fading = MIX_FADING_IN; |
mix_channel[which].fade_volume = mix_channel[which].volume; |
mix_channel[which].fade_volume_reset = mix_channel[which].volume; |
mix_channel[which].volume = 0; |
mix_channel[which].fade_length = (Uint32)ms; |
mix_channel[which].start_time = mix_channel[which].ticks_fade = sdl_ticks; |
mix_channel[which].expire = (ticks > 0) ? (sdl_ticks+ticks) : 0; |
} |
} |
SDL_UnlockAudio(); |
/* Return the channel on which the sound is being played */ |
return(which); |
} |
/* Set volume of a particular channel */ |
int Mix_Volume(int which, int volume) |
{ |
int i; |
int prev_volume = 0; |
if ( which == -1 ) { |
for ( i=0; i<num_channels; ++i ) { |
prev_volume += Mix_Volume(i, volume); |
} |
prev_volume /= num_channels; |
} else if ( which < num_channels ) { |
prev_volume = mix_channel[which].volume; |
if ( volume >= 0 ) { |
if ( volume > SDL_MIX_MAXVOLUME ) { |
volume = SDL_MIX_MAXVOLUME; |
} |
mix_channel[which].volume = volume; |
} |
} |
return(prev_volume); |
} |
/* Set volume of a particular chunk */ |
int Mix_VolumeChunk(Mix_Chunk *chunk, int volume) |
{ |
int prev_volume; |
prev_volume = chunk->volume; |
if ( volume >= 0 ) { |
if ( volume > MIX_MAX_VOLUME ) { |
volume = MIX_MAX_VOLUME; |
} |
chunk->volume = volume; |
} |
return(prev_volume); |
} |
/* Halt playing of a particular channel */ |
int Mix_HaltChannel(int which) |
{ |
int i; |
if ( which == -1 ) { |
for ( i=0; i<num_channels; ++i ) { |
Mix_HaltChannel(i); |
} |
} else if ( which < num_channels ) { |
SDL_LockAudio(); |
if (mix_channel[which].playing) { |
_Mix_channel_done_playing(which); |
mix_channel[which].playing = 0; |
mix_channel[which].looping = 0; |
} |
mix_channel[which].expire = 0; |
if(mix_channel[which].fading != MIX_NO_FADING) /* Restore volume */ |
mix_channel[which].volume = mix_channel[which].fade_volume_reset; |
mix_channel[which].fading = MIX_NO_FADING; |
SDL_UnlockAudio(); |
} |
return(0); |
} |
/* Halt playing of a particular group of channels */ |
int Mix_HaltGroup(int tag) |
{ |
int i; |
for ( i=0; i<num_channels; ++i ) { |
if( mix_channel[i].tag == tag ) { |
Mix_HaltChannel(i); |
} |
} |
return(0); |
} |
/* Fade out a channel and then stop it automatically */ |
int Mix_FadeOutChannel(int which, int ms) |
{ |
int status; |
status = 0; |
if ( audio_opened ) { |
if ( which == -1 ) { |
int i; |
for ( i=0; i<num_channels; ++i ) { |
status += Mix_FadeOutChannel(i, ms); |
} |
} else if ( which < num_channels ) { |
SDL_LockAudio(); |
if ( mix_channel[which].playing && |
(mix_channel[which].volume > 0) && |
(mix_channel[which].fading != MIX_FADING_OUT) ) { |
mix_channel[which].fade_volume = mix_channel[which].volume; |
mix_channel[which].fading = MIX_FADING_OUT; |
mix_channel[which].fade_length = ms; |
mix_channel[which].ticks_fade = SDL_GetTicks(); |
/* only change fade_volume_reset if we're not fading. */ |
if (mix_channel[which].fading == MIX_NO_FADING) { |
mix_channel[which].fade_volume_reset = mix_channel[which].volume; |
} |
++status; |
} |
SDL_UnlockAudio(); |
} |
} |
return(status); |
} |
/* Halt playing of a particular group of channels */ |
int Mix_FadeOutGroup(int tag, int ms) |
{ |
int i; |
int status = 0; |
for ( i=0; i<num_channels; ++i ) { |
if( mix_channel[i].tag == tag ) { |
status += Mix_FadeOutChannel(i,ms); |
} |
} |
return(status); |
} |
Mix_Fading Mix_FadingChannel(int which) |
{ |
if ( which < 0 || which >= num_channels ) { |
return MIX_NO_FADING; |
} |
return mix_channel[which].fading; |
} |
/* Check the status of a specific channel. |
If the specified mix_channel is -1, check all mix channels. |
*/ |
int Mix_Playing(int which) |
{ |
int status; |
status = 0; |
if ( which == -1 ) { |
int i; |
for ( i=0; i<num_channels; ++i ) { |
if ((mix_channel[i].playing > 0) || |
(mix_channel[i].looping > 0)) |
{ |
++status; |
} |
} |
} else if ( which < num_channels ) { |
if ( (mix_channel[which].playing > 0) || |
(mix_channel[which].looping > 0) ) |
{ |
++status; |
} |
} |
return(status); |
} |
/* rcg06072001 Get the chunk associated with a channel. */ |
Mix_Chunk *Mix_GetChunk(int channel) |
{ |
Mix_Chunk *retval = NULL; |
if ((channel >= 0) && (channel < num_channels)) { |
retval = mix_channel[channel].chunk; |
} |
return(retval); |
} |
/* Close the mixer, halting all playing audio */ |
void Mix_CloseAudio(void) |
{ |
int i; |
if ( audio_opened ) { |
if ( audio_opened == 1 ) { |
for (i = 0; i < num_channels; i++) { |
Mix_UnregisterAllEffects(i); |
} |
Mix_UnregisterAllEffects(MIX_CHANNEL_POST); |
close_music(); |
Mix_HaltChannel(-1); |
_Mix_DeinitEffects(); |
SDL_CloseAudio(); |
SDL_free(mix_channel); |
mix_channel = NULL; |
/* rcg06042009 report available decoders at runtime. */ |
SDL_free(chunk_decoders); |
chunk_decoders = NULL; |
num_decoders = 0; |
} |
--audio_opened; |
} |
} |
/* Pause a particular channel (or all) */ |
void Mix_Pause(int which) |
{ |
Uint32 sdl_ticks = SDL_GetTicks(); |
if ( which == -1 ) { |
int i; |
for ( i=0; i<num_channels; ++i ) { |
if ( mix_channel[i].playing > 0 ) { |
mix_channel[i].paused = sdl_ticks; |
} |
} |
} else if ( which < num_channels ) { |
if ( mix_channel[which].playing > 0 ) { |
mix_channel[which].paused = sdl_ticks; |
} |
} |
} |
/* Resume a paused channel */ |
void Mix_Resume(int which) |
{ |
Uint32 sdl_ticks = SDL_GetTicks(); |
SDL_LockAudio(); |
if ( which == -1 ) { |
int i; |
for ( i=0; i<num_channels; ++i ) { |
if ( mix_channel[i].playing > 0 ) { |
if(mix_channel[i].expire > 0) |
mix_channel[i].expire += sdl_ticks - mix_channel[i].paused; |
mix_channel[i].paused = 0; |
} |
} |
} else if ( which < num_channels ) { |
if ( mix_channel[which].playing > 0 ) { |
if(mix_channel[which].expire > 0) |
mix_channel[which].expire += sdl_ticks - mix_channel[which].paused; |
mix_channel[which].paused = 0; |
} |
} |
SDL_UnlockAudio(); |
} |
int Mix_Paused(int which) |
{ |
if ( which < 0 ) { |
int status = 0; |
int i; |
for( i=0; i < num_channels; ++i ) { |
if ( mix_channel[i].paused ) { |
++ status; |
} |
} |
return(status); |
} else if ( which < num_channels ) { |
return(mix_channel[which].paused != 0); |
} else { |
return(0); |
} |
} |
/* Change the group of a channel */ |
int Mix_GroupChannel(int which, int tag) |
{ |
if ( which < 0 || which > num_channels ) |
return(0); |
SDL_LockAudio(); |
mix_channel[which].tag = tag; |
SDL_UnlockAudio(); |
return(1); |
} |
/* Assign several consecutive channels to a group */ |
int Mix_GroupChannels(int from, int to, int tag) |
{ |
int status = 0; |
for( ; from <= to; ++ from ) { |
status += Mix_GroupChannel(from, tag); |
} |
return(status); |
} |
/* Finds the first available channel in a group of channels */ |
int Mix_GroupAvailable(int tag) |
{ |
int i; |
for( i=0; i < num_channels; i ++ ) { |
if ( ((tag == -1) || (tag == mix_channel[i].tag)) && |
(mix_channel[i].playing <= 0) ) |
return i; |
} |
return(-1); |
} |
int Mix_GroupCount(int tag) |
{ |
int count = 0; |
int i; |
for( i=0; i < num_channels; i ++ ) { |
if ( mix_channel[i].tag==tag || tag==-1 ) |
++ count; |
} |
return(count); |
} |
/* Finds the "oldest" sample playing in a group of channels */ |
int Mix_GroupOldest(int tag) |
{ |
int chan = -1; |
Uint32 mintime = SDL_GetTicks(); |
int i; |
for( i=0; i < num_channels; i ++ ) { |
if ( (mix_channel[i].tag==tag || tag==-1) && mix_channel[i].playing > 0 |
&& mix_channel[i].start_time <= mintime ) { |
mintime = mix_channel[i].start_time; |
chan = i; |
} |
} |
return(chan); |
} |
/* Finds the "most recent" (i.e. last) sample playing in a group of channels */ |
int Mix_GroupNewer(int tag) |
{ |
int chan = -1; |
Uint32 maxtime = 0; |
int i; |
for( i=0; i < num_channels; i ++ ) { |
if ( (mix_channel[i].tag==tag || tag==-1) && mix_channel[i].playing > 0 |
&& mix_channel[i].start_time >= maxtime ) { |
maxtime = mix_channel[i].start_time; |
chan = i; |
} |
} |
return(chan); |
} |
/* |
* rcg06122001 The special effects exportable API. |
* Please see effect_*.c for internally-implemented effects, such |
* as Mix_SetPanning(). |
*/ |
/* MAKE SURE you hold the audio lock (SDL_LockAudio()) before calling this! */ |
static int _Mix_register_effect(effect_info **e, Mix_EffectFunc_t f, |
Mix_EffectDone_t d, void *arg) |
{ |
effect_info *new_e; |
if (!e) { |
Mix_SetError("Internal error"); |
return(0); |
} |
if (f == NULL) { |
Mix_SetError("NULL effect callback"); |
return(0); |
} |
new_e = SDL_malloc(sizeof (effect_info)); |
if (new_e == NULL) { |
Mix_SetError("Out of memory"); |
return(0); |
} |
new_e->callback = f; |
new_e->done_callback = d; |
new_e->udata = arg; |
new_e->next = NULL; |
/* add new effect to end of linked list... */ |
if (*e == NULL) { |
*e = new_e; |
} else { |
effect_info *cur = *e; |
while (1) { |
if (cur->next == NULL) { |
cur->next = new_e; |
break; |
} |
cur = cur->next; |
} |
} |
return(1); |
} |
/* MAKE SURE you hold the audio lock (SDL_LockAudio()) before calling this! */ |
static int _Mix_remove_effect(int channel, effect_info **e, Mix_EffectFunc_t f) |
{ |
effect_info *cur; |
effect_info *prev = NULL; |
effect_info *next = NULL; |
if (!e) { |
Mix_SetError("Internal error"); |
return(0); |
} |
for (cur = *e; cur != NULL; cur = cur->next) { |
if (cur->callback == f) { |
next = cur->next; |
if (cur->done_callback != NULL) { |
cur->done_callback(channel, cur->udata); |
} |
SDL_free(cur); |
if (prev == NULL) { /* removing first item of list? */ |
*e = next; |
} else { |
prev->next = next; |
} |
return(1); |
} |
prev = cur; |
} |
Mix_SetError("No such effect registered"); |
return(0); |
} |
/* MAKE SURE you hold the audio lock (SDL_LockAudio()) before calling this! */ |
static int _Mix_remove_all_effects(int channel, effect_info **e) |
{ |
effect_info *cur; |
effect_info *next; |
if (!e) { |
Mix_SetError("Internal error"); |
return(0); |
} |
for (cur = *e; cur != NULL; cur = next) { |
next = cur->next; |
if (cur->done_callback != NULL) { |
cur->done_callback(channel, cur->udata); |
} |
SDL_free(cur); |
} |
*e = NULL; |
return(1); |
} |
/* MAKE SURE you hold the audio lock (SDL_LockAudio()) before calling this! */ |
int _Mix_RegisterEffect_locked(int channel, Mix_EffectFunc_t f, |
Mix_EffectDone_t d, void *arg) |
{ |
effect_info **e = NULL; |
if (channel == MIX_CHANNEL_POST) { |
e = &posteffects; |
} else { |
if ((channel < 0) || (channel >= num_channels)) { |
Mix_SetError("Invalid channel number"); |
return(0); |
} |
e = &mix_channel[channel].effects; |
} |
return _Mix_register_effect(e, f, d, arg); |
} |
int Mix_RegisterEffect(int channel, Mix_EffectFunc_t f, |
Mix_EffectDone_t d, void *arg) |
{ |
int retval; |
SDL_LockAudio(); |
retval = _Mix_RegisterEffect_locked(channel, f, d, arg); |
SDL_UnlockAudio(); |
return retval; |
} |
/* MAKE SURE you hold the audio lock (SDL_LockAudio()) before calling this! */ |
int _Mix_UnregisterEffect_locked(int channel, Mix_EffectFunc_t f) |
{ |
effect_info **e = NULL; |
if (channel == MIX_CHANNEL_POST) { |
e = &posteffects; |
} else { |
if ((channel < 0) || (channel >= num_channels)) { |
Mix_SetError("Invalid channel number"); |
return(0); |
} |
e = &mix_channel[channel].effects; |
} |
return _Mix_remove_effect(channel, e, f); |
} |
int Mix_UnregisterEffect(int channel, Mix_EffectFunc_t f) |
{ |
int retval; |
SDL_LockAudio(); |
retval = _Mix_UnregisterEffect_locked(channel, f); |
SDL_UnlockAudio(); |
return(retval); |
} |
/* MAKE SURE you hold the audio lock (SDL_LockAudio()) before calling this! */ |
int _Mix_UnregisterAllEffects_locked(int channel) |
{ |
effect_info **e = NULL; |
if (channel == MIX_CHANNEL_POST) { |
e = &posteffects; |
} else { |
if ((channel < 0) || (channel >= num_channels)) { |
Mix_SetError("Invalid channel number"); |
return(0); |
} |
e = &mix_channel[channel].effects; |
} |
return _Mix_remove_all_effects(channel, e); |
} |
int Mix_UnregisterAllEffects(int channel) |
{ |
int retval; |
SDL_LockAudio(); |
retval = _Mix_UnregisterAllEffects_locked(channel); |
SDL_UnlockAudio(); |
return(retval); |
} |
/* end of mixer.c ... */ |
/contrib/games/wolf3d/SDL_mixer/music.c |
---|
0,0 → 1,1597 |
/* |
SDL_mixer: An audio mixer library based on the SDL library |
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org> |
This software is provided 'as-is', without any express or implied |
warranty. In no event will the authors be held liable for any damages |
arising from the use of this software. |
Permission is granted to anyone to use this software for any purpose, |
including commercial applications, and to alter it and redistribute it |
freely, subject to the following restrictions: |
1. The origin of this software must not be misrepresented; you must not |
claim that you wrote the original software. If you use this software |
in a product, an acknowledgment in the product documentation would be |
appreciated but is not required. |
2. Altered source versions must be plainly marked as such, and must not be |
misrepresented as being the original software. |
3. This notice may not be removed or altered from any source distribution. |
*/ |
/* $Id$ */ |
#include <stdlib.h> |
#include <string.h> |
#include <ctype.h> |
#include <assert.h> |
#include "SDL_endian.h" |
#include "SDL_audio.h" |
#include "SDL_timer.h" |
#include "SDL_mixer.h" |
#ifdef CMD_MUSIC |
#include "music_cmd.h" |
#endif |
#ifdef WAV_MUSIC |
#include "wavestream.h" |
#endif |
#ifdef MODPLUG_MUSIC |
#include "music_modplug.h" |
#endif |
#ifdef MOD_MUSIC |
#include "music_mod.h" |
#endif |
#ifdef MID_MUSIC |
# ifdef USE_TIMIDITY_MIDI |
# include "timidity.h" |
# endif |
# ifdef USE_FLUIDSYNTH_MIDI |
# include "fluidsynth.h" |
# endif |
# ifdef USE_NATIVE_MIDI |
# include "native_midi.h" |
# endif |
#endif |
#ifdef OGG_MUSIC |
#include "music_ogg.h" |
#endif |
#ifdef MP3_MUSIC |
#include "dynamic_mp3.h" |
#endif |
#ifdef MP3_MAD_MUSIC |
#include "music_mad.h" |
#endif |
#ifdef FLAC_MUSIC |
#include "music_flac.h" |
#endif |
#if defined(MP3_MUSIC) || defined(MP3_MAD_MUSIC) |
static SDL_AudioSpec used_mixer; |
#endif |
int volatile music_active = 1; |
static int volatile music_stopped = 0; |
static int music_loops = 0; |
static char *music_cmd = NULL; |
static Mix_Music * volatile music_playing = NULL; |
static int music_volume = MIX_MAX_VOLUME; |
struct _Mix_Music { |
Mix_MusicType type; |
union { |
#ifdef CMD_MUSIC |
MusicCMD *cmd; |
#endif |
#ifdef WAV_MUSIC |
WAVStream *wave; |
#endif |
#ifdef MODPLUG_MUSIC |
modplug_data *modplug; |
#endif |
#ifdef MOD_MUSIC |
struct MODULE *module; |
#endif |
#ifdef MID_MUSIC |
#ifdef USE_TIMIDITY_MIDI |
MidiSong *midi; |
#endif |
#ifdef USE_FLUIDSYNTH_MIDI |
FluidSynthMidiSong *fluidsynthmidi; |
#endif |
#ifdef USE_NATIVE_MIDI |
NativeMidiSong *nativemidi; |
#endif |
#endif |
#ifdef OGG_MUSIC |
OGG_music *ogg; |
#endif |
#ifdef MP3_MUSIC |
SMPEG *mp3; |
#endif |
#ifdef MP3_MAD_MUSIC |
mad_data *mp3_mad; |
#endif |
#ifdef FLAC_MUSIC |
FLAC_music *flac; |
#endif |
} data; |
Mix_Fading fading; |
int fade_step; |
int fade_steps; |
int error; |
}; |
#ifdef MID_MUSIC |
#ifdef USE_TIMIDITY_MIDI |
static int timidity_ok; |
static int samplesize; |
#endif |
#ifdef USE_FLUIDSYNTH_MIDI |
static int fluidsynth_ok; |
#endif |
#ifdef USE_NATIVE_MIDI |
static int native_midi_ok; |
#endif |
#endif |
/* Used to calculate fading steps */ |
static int ms_per_step; |
/* rcg06042009 report available decoders at runtime. */ |
static const char **music_decoders = NULL; |
static int num_decoders = 0; |
/* Semicolon-separated SoundFont paths */ |
#ifdef MID_MUSIC |
char* soundfont_paths = NULL; |
#endif |
int Mix_GetNumMusicDecoders(void) |
{ |
return(num_decoders); |
} |
const char *Mix_GetMusicDecoder(int index) |
{ |
if ((index < 0) || (index >= num_decoders)) { |
return NULL; |
} |
return(music_decoders[index]); |
} |
static void add_music_decoder(const char *decoder) |
{ |
void *ptr = SDL_realloc(music_decoders, (num_decoders + 1) * sizeof (const char **)); |
if (ptr == NULL) { |
return; /* oh well, go on without it. */ |
} |
music_decoders = (const char **) ptr; |
music_decoders[num_decoders++] = decoder; |
} |
/* Local low-level functions prototypes */ |
static void music_internal_initialize_volume(void); |
static void music_internal_volume(int volume); |
static int music_internal_play(Mix_Music *music, double position); |
static int music_internal_position(double position); |
static int music_internal_playing(); |
static void music_internal_halt(void); |
/* Support for hooking when the music has finished */ |
static void (*music_finished_hook)(void) = NULL; |
void Mix_HookMusicFinished(void (*music_finished)(void)) |
{ |
SDL_LockAudio(); |
music_finished_hook = music_finished; |
SDL_UnlockAudio(); |
} |
/* If music isn't playing, halt it if no looping is required, restart it */ |
/* otherwhise. NOP if the music is playing */ |
static int music_halt_or_loop (void) |
{ |
/* Restart music if it has to loop */ |
if (!music_internal_playing()) |
{ |
#ifdef USE_NATIVE_MIDI |
/* Native MIDI handles looping internally */ |
if (music_playing->type == MUS_MID && native_midi_ok) { |
music_loops = 0; |
} |
#endif |
/* Restart music if it has to loop at a high level */ |
if (music_loops) |
{ |
Mix_Fading current_fade; |
--music_loops; |
current_fade = music_playing->fading; |
music_internal_play(music_playing, 0.0); |
music_playing->fading = current_fade; |
} |
else |
{ |
music_internal_halt(); |
if (music_finished_hook) |
music_finished_hook(); |
return 0; |
} |
} |
return 1; |
} |
/* Mixing function */ |
void music_mixer(void *udata, Uint8 *stream, int len) |
{ |
int left = 0; |
if ( music_playing && music_active ) { |
/* Handle fading */ |
if ( music_playing->fading != MIX_NO_FADING ) { |
if ( music_playing->fade_step++ < music_playing->fade_steps ) { |
int volume; |
int fade_step = music_playing->fade_step; |
int fade_steps = music_playing->fade_steps; |
if ( music_playing->fading == MIX_FADING_OUT ) { |
volume = (music_volume * (fade_steps-fade_step)) / fade_steps; |
} else { /* Fading in */ |
volume = (music_volume * fade_step) / fade_steps; |
} |
music_internal_volume(volume); |
} else { |
if ( music_playing->fading == MIX_FADING_OUT ) { |
music_internal_halt(); |
if ( music_finished_hook ) { |
music_finished_hook(); |
} |
return; |
} |
music_playing->fading = MIX_NO_FADING; |
} |
} |
music_halt_or_loop(); |
if (!music_internal_playing()) |
return; |
switch (music_playing->type) { |
#ifdef CMD_MUSIC |
case MUS_CMD: |
/* The playing is done externally */ |
break; |
#endif |
#ifdef WAV_MUSIC |
case MUS_WAV: |
left = WAVStream_PlaySome(stream, len); |
break; |
#endif |
#ifdef MODPLUG_MUSIC |
case MUS_MODPLUG: |
left = modplug_playAudio(music_playing->data.modplug, stream, len); |
break; |
#endif |
#ifdef MOD_MUSIC |
case MUS_MOD: |
left = MOD_playAudio(music_playing->data.module, stream, len); |
break; |
#endif |
#ifdef MID_MUSIC |
case MUS_MID: |
#ifdef USE_NATIVE_MIDI |
if ( native_midi_ok ) { |
/* Native midi is handled asynchronously */ |
goto skip; |
} |
#endif |
#ifdef USE_FLUIDSYNTH_MIDI |
if ( fluidsynth_ok ) { |
fluidsynth_playsome(music_playing->data.fluidsynthmidi, stream, len); |
goto skip; |
} |
#endif |
#ifdef USE_TIMIDITY_MIDI |
if ( timidity_ok ) { |
int samples = len / samplesize; |
Timidity_PlaySome(stream, samples); |
goto skip; |
} |
#endif |
break; |
#endif |
#ifdef OGG_MUSIC |
case MUS_OGG: |
left = OGG_playAudio(music_playing->data.ogg, stream, len); |
break; |
#endif |
#ifdef FLAC_MUSIC |
case MUS_FLAC: |
left = FLAC_playAudio(music_playing->data.flac, stream, len); |
break; |
#endif |
#ifdef MP3_MUSIC |
case MUS_MP3: |
left = (len - smpeg.SMPEG_playAudio(music_playing->data.mp3, stream, len)); |
break; |
#endif |
#ifdef MP3_MAD_MUSIC |
case MUS_MP3_MAD: |
left = mad_getSamples(music_playing->data.mp3_mad, stream, len); |
break; |
#endif |
default: |
/* Unknown music type?? */ |
break; |
} |
} |
skip: |
/* Handle seamless music looping */ |
if (left > 0 && left < len) { |
music_halt_or_loop(); |
if (music_internal_playing()) |
music_mixer(udata, stream+(len-left), left); |
} |
} |
/* Initialize the music players with a certain desired audio format */ |
int open_music(SDL_AudioSpec *mixer) |
{ |
#ifdef WAV_MUSIC |
if ( WAVStream_Init(mixer) == 0 ) { |
add_music_decoder("WAVE"); |
} |
#endif |
#ifdef MODPLUG_MUSIC |
if ( modplug_init(mixer) == 0 ) { |
add_music_decoder("MODPLUG"); |
} |
#endif |
#ifdef MOD_MUSIC |
if ( MOD_init(mixer) == 0 ) { |
add_music_decoder("MIKMOD"); |
} |
#endif |
#ifdef MID_MUSIC |
#ifdef USE_TIMIDITY_MIDI |
samplesize = mixer->size / mixer->samples; |
if ( Timidity_Init(mixer->freq, mixer->format, |
mixer->channels, mixer->samples) == 0 ) { |
timidity_ok = 1; |
add_music_decoder("TIMIDITY"); |
} else { |
timidity_ok = 0; |
} |
#endif |
#ifdef USE_FLUIDSYNTH_MIDI |
if ( fluidsynth_init(mixer) == 0 ) { |
fluidsynth_ok = 1; |
add_music_decoder("FLUIDSYNTH"); |
} else { |
fluidsynth_ok = 0; |
} |
#endif |
#ifdef USE_NATIVE_MIDI |
#ifdef USE_FLUIDSYNTH_MIDI |
native_midi_ok = !fluidsynth_ok; |
if ( native_midi_ok ) |
#endif |
#ifdef USE_TIMIDITY_MIDI |
native_midi_ok = !timidity_ok; |
if ( !native_midi_ok ) { |
native_midi_ok = (getenv("SDL_NATIVE_MUSIC") != NULL); |
} |
if ( native_midi_ok ) |
#endif |
native_midi_ok = native_midi_detect(); |
if ( native_midi_ok ) |
add_music_decoder("NATIVEMIDI"); |
#endif |
#endif |
#ifdef OGG_MUSIC |
if ( OGG_init(mixer) == 0 ) { |
add_music_decoder("OGG"); |
} |
#endif |
#ifdef FLAC_MUSIC |
if ( FLAC_init(mixer) == 0 ) { |
add_music_decoder("FLAC"); |
} |
#endif |
#if defined(MP3_MUSIC) || defined(MP3_MAD_MUSIC) |
/* Keep a copy of the mixer */ |
used_mixer = *mixer; |
add_music_decoder("MP3"); |
#endif |
music_playing = NULL; |
music_stopped = 0; |
Mix_VolumeMusic(SDL_MIX_MAXVOLUME); |
/* Calculate the number of ms for each callback */ |
ms_per_step = (int) (((float)mixer->samples * 1000.0) / mixer->freq); |
return(0); |
} |
/* Portable case-insensitive string compare function */ |
int MIX_string_equals(const char *str1, const char *str2) |
{ |
while ( *str1 && *str2 ) { |
if ( toupper((unsigned char)*str1) != |
toupper((unsigned char)*str2) ) |
break; |
++str1; |
++str2; |
} |
return (!*str1 && !*str2); |
} |
static int detect_mp3(Uint8 *magic) |
{ |
if ( strncmp((char *)magic, "ID3", 3) == 0 ) { |
return 1; |
} |
/* Detection code lifted from SMPEG */ |
if(((magic[0] & 0xff) != 0xff) || // No sync bits |
((magic[1] & 0xf0) != 0xf0) || // |
((magic[2] & 0xf0) == 0x00) || // Bitrate is 0 |
((magic[2] & 0xf0) == 0xf0) || // Bitrate is 15 |
((magic[2] & 0x0c) == 0x0c) || // Frequency is 3 |
((magic[1] & 0x06) == 0x00)) { // Layer is 4 |
return(0); |
} |
return 1; |
} |
/* MUS_MOD can't be auto-detected. If no other format was detected, MOD is |
* assumed and MUS_MOD will be returned, meaning that the format might not |
* actually be MOD-based. |
* |
* Returns MUS_NONE in case of errors. */ |
static Mix_MusicType detect_music_type(SDL_RWops *rw) |
{ |
Uint8 magic[5]; |
Uint8 moremagic[9]; |
int start = SDL_RWtell(rw); |
if (SDL_RWread(rw, magic, 1, 4) != 4 || SDL_RWread(rw, moremagic, 1, 8) != 8 ) { |
Mix_SetError("Couldn't read from RWops"); |
return MUS_NONE; |
} |
SDL_RWseek(rw, start, RW_SEEK_SET); |
magic[4]='\0'; |
moremagic[8] = '\0'; |
/* WAVE files have the magic four bytes "RIFF" |
AIFF files have the magic 12 bytes "FORM" XXXX "AIFF" */ |
if (((strcmp((char *)magic, "RIFF") == 0) && (strcmp((char *)(moremagic+4), "WAVE") == 0)) || |
(strcmp((char *)magic, "FORM") == 0)) { |
return MUS_WAV; |
} |
/* Ogg Vorbis files have the magic four bytes "OggS" */ |
if (strcmp((char *)magic, "OggS") == 0) { |
return MUS_OGG; |
} |
/* FLAC files have the magic four bytes "fLaC" */ |
if (strcmp((char *)magic, "fLaC") == 0) { |
return MUS_FLAC; |
} |
/* MIDI files have the magic four bytes "MThd" */ |
if (strcmp((char *)magic, "MThd") == 0) { |
return MUS_MID; |
} |
if (detect_mp3(magic)) { |
return MUS_MP3; |
} |
/* Assume MOD format. |
* |
* Apparently there is no way to check if the file is really a MOD, |
* or there are too many formats supported by MikMod/ModPlug, or |
* MikMod/ModPlug does this check by itself. */ |
return MUS_MOD; |
} |
/* Load a music file */ |
Mix_Music *Mix_LoadMUS(const char *file) |
{ |
SDL_RWops *rw; |
Mix_Music *music; |
Mix_MusicType type; |
char *ext = strrchr(file, '.'); |
#ifdef CMD_MUSIC |
if ( music_cmd ) { |
/* Allocate memory for the music structure */ |
music = (Mix_Music *)SDL_malloc(sizeof(Mix_Music)); |
if ( music == NULL ) { |
Mix_SetError("Out of memory"); |
return(NULL); |
} |
music->error = 0; |
music->type = MUS_CMD; |
music->data.cmd = MusicCMD_LoadSong(music_cmd, file); |
if ( music->data.cmd == NULL ) { |
SDL_free(music); |
music == NULL; |
} |
return music; |
} |
#endif |
rw = SDL_RWFromFile(file, "rb"); |
if ( rw == NULL ) { |
Mix_SetError("Couldn't open '%s'", file); |
return NULL; |
} |
/* Use the extension as a first guess on the file type */ |
type = MUS_NONE; |
ext = strrchr(file, '.'); |
/* No need to guard these with #ifdef *_MUSIC stuff, |
* since we simply call Mix_LoadMUSType_RW() later */ |
if ( ext ) { |
++ext; /* skip the dot in the extension */ |
if ( MIX_string_equals(ext, "WAV") ) { |
type = MUS_WAV; |
} else if ( MIX_string_equals(ext, "MID") || |
MIX_string_equals(ext, "MIDI") || |
MIX_string_equals(ext, "KAR") ) { |
type = MUS_MID; |
} else if ( MIX_string_equals(ext, "OGG") ) { |
type = MUS_OGG; |
} else if ( MIX_string_equals(ext, "FLAC") ) { |
type = MUS_FLAC; |
} else if ( MIX_string_equals(ext, "MPG") || |
MIX_string_equals(ext, "MPEG") || |
MIX_string_equals(ext, "MP3") || |
MIX_string_equals(ext, "MAD") ) { |
type = MUS_MP3; |
} |
} |
if ( type == MUS_NONE ) { |
type = detect_music_type(rw); |
} |
/* We need to know if a specific error occurs; if not, we'll set a |
* generic one, so we clear the current one. */ |
Mix_SetError(""); |
music = Mix_LoadMUSType_RW(rw, type, SDL_TRUE); |
if ( music == NULL && Mix_GetError()[0] == '\0' ) { |
SDL_FreeRW(rw); |
Mix_SetError("Couldn't open '%s'", file); |
} |
return music; |
} |
Mix_Music *Mix_LoadMUS_RW(SDL_RWops *rw) |
{ |
return Mix_LoadMUSType_RW(rw, MUS_NONE, SDL_FALSE); |
} |
Mix_Music *Mix_LoadMUSType_RW(SDL_RWops *rw, Mix_MusicType type, int freesrc) |
{ |
Mix_Music *music; |
if (!rw) { |
Mix_SetError("RWops pointer is NULL"); |
return NULL; |
} |
/* If the caller wants auto-detection, figure out what kind of file |
* this is. */ |
if (type == MUS_NONE) { |
if ((type = detect_music_type(rw)) == MUS_NONE) { |
/* Don't call Mix_SetError() here since detect_music_type() |
* does that. */ |
return NULL; |
} |
} |
/* Allocate memory for the music structure */ |
music = (Mix_Music *)SDL_malloc(sizeof(Mix_Music)); |
if (music == NULL ) { |
Mix_SetError("Out of memory"); |
return NULL; |
} |
music->error = 0; |
switch (type) { |
#ifdef WAV_MUSIC |
case MUS_WAV: |
/* The WAVE loader needs the first 4 bytes of the header */ |
{ |
Uint8 magic[5]; |
int start = SDL_RWtell(rw); |
if (SDL_RWread(rw, magic, 1, 4) != 4) { |
Mix_SetError("Couldn't read from RWops"); |
return MUS_NONE; |
} |
SDL_RWseek(rw, start, RW_SEEK_SET); |
magic[4] = '\0'; |
music->type = MUS_WAV; |
music->data.wave = WAVStream_LoadSong_RW(rw, (char *)magic, freesrc); |
} |
if (music->data.wave == NULL) { |
music->error = 1; |
} |
break; |
#endif |
#ifdef OGG_MUSIC |
case MUS_OGG: |
music->type = MUS_OGG; |
music->data.ogg = OGG_new_RW(rw, freesrc); |
if ( music->data.ogg == NULL ) { |
music->error = 1; |
} |
break; |
#endif |
#ifdef FLAC_MUSIC |
case MUS_FLAC: |
music->type = MUS_FLAC; |
music->data.flac = FLAC_new_RW(rw, freesrc); |
if ( music->data.flac == NULL ) { |
music->error = 1; |
} |
break; |
#endif |
#ifdef MP3_MUSIC |
case MUS_MP3: |
if ( Mix_Init(MIX_INIT_MP3) ) { |
SMPEG_Info info; |
music->type = MUS_MP3; |
music->data.mp3 = smpeg.SMPEG_new_rwops(rw, &info, 0); |
if ( !info.has_audio ) { |
Mix_SetError("MPEG file does not have any audio stream."); |
music->error = 1; |
} else { |
smpeg.SMPEG_actualSpec(music->data.mp3, &used_mixer); |
} |
} else { |
music->error = 1; |
} |
break; |
#elif defined(MP3_MAD_MUSIC) |
case MUS_MP3: |
music->type = MUS_MP3_MAD; |
music->data.mp3_mad = mad_openFileRW(rw, &used_mixer, freesrc); |
if (music->data.mp3_mad == 0) { |
Mix_SetError("Could not initialize MPEG stream."); |
music->error = 1; |
} |
break; |
#endif |
#ifdef MID_MUSIC |
case MUS_MID: |
music->type = MUS_MID; |
#ifdef USE_NATIVE_MIDI |
if ( native_midi_ok ) { |
music->data.nativemidi = native_midi_loadsong_RW(rw, freesrc); |
if ( music->data.nativemidi == NULL ) { |
Mix_SetError("%s", native_midi_error()); |
music->error = 1; |
} |
break; |
} |
#endif |
#ifdef USE_FLUIDSYNTH_MIDI |
if ( fluidsynth_ok ) { |
music->data.fluidsynthmidi = fluidsynth_loadsong_RW(rw, freesrc); |
if ( music->data.fluidsynthmidi == NULL ) { |
music->error = 1; |
} |
break; |
} |
#endif |
#ifdef USE_TIMIDITY_MIDI |
if ( timidity_ok ) { |
music->data.midi = Timidity_LoadSong_RW(rw, freesrc); |
if ( music->data.midi == NULL ) { |
Mix_SetError("%s", Timidity_Error()); |
music->error = 1; |
} |
} else { |
Mix_SetError("%s", Timidity_Error()); |
music->error = 1; |
} |
#endif |
break; |
#endif |
#if defined(MODPLUG_MUSIC) || defined(MOD_MUSIC) |
case MUS_MOD: |
music->error = 1; |
#ifdef MODPLUG_MUSIC |
if ( music->error ) { |
music->type = MUS_MODPLUG; |
music->data.modplug = modplug_new_RW(rw, freesrc); |
if ( music->data.modplug ) { |
music->error = 0; |
} |
} |
#endif |
#ifdef MOD_MUSIC |
if ( music->error ) { |
music->type = MUS_MOD; |
music->data.module = MOD_new_RW(rw, freesrc); |
if ( music->data.module ) { |
music->error = 0; |
} |
} |
#endif |
break; |
#endif |
default: |
Mix_SetError("Unrecognized music format"); |
music->error=1; |
} /* switch (want) */ |
if (music->error) { |
SDL_free(music); |
music=NULL; |
} |
return(music); |
} |
/* Free a music chunk previously loaded */ |
void Mix_FreeMusic(Mix_Music *music) |
{ |
if ( music ) { |
/* Stop the music if it's currently playing */ |
SDL_LockAudio(); |
if ( music == music_playing ) { |
/* Wait for any fade out to finish */ |
while ( music->fading == MIX_FADING_OUT ) { |
SDL_UnlockAudio(); |
SDL_Delay(100); |
SDL_LockAudio(); |
} |
if ( music == music_playing ) { |
music_internal_halt(); |
} |
} |
SDL_UnlockAudio(); |
switch (music->type) { |
#ifdef CMD_MUSIC |
case MUS_CMD: |
MusicCMD_FreeSong(music->data.cmd); |
break; |
#endif |
#ifdef WAV_MUSIC |
case MUS_WAV: |
WAVStream_FreeSong(music->data.wave); |
break; |
#endif |
#ifdef MODPLUG_MUSIC |
case MUS_MODPLUG: |
modplug_delete(music->data.modplug); |
break; |
#endif |
#ifdef MOD_MUSIC |
case MUS_MOD: |
MOD_delete(music->data.module); |
break; |
#endif |
#ifdef MID_MUSIC |
case MUS_MID: |
#ifdef USE_NATIVE_MIDI |
if ( native_midi_ok ) { |
native_midi_freesong(music->data.nativemidi); |
goto skip; |
} |
#endif |
#ifdef USE_FLUIDSYNTH_MIDI |
if ( fluidsynth_ok ) { |
fluidsynth_freesong(music->data.fluidsynthmidi); |
goto skip; |
} |
#endif |
#ifdef USE_TIMIDITY_MIDI |
if ( timidity_ok ) { |
Timidity_FreeSong(music->data.midi); |
goto skip; |
} |
#endif |
break; |
#endif |
#ifdef OGG_MUSIC |
case MUS_OGG: |
OGG_delete(music->data.ogg); |
break; |
#endif |
#ifdef FLAC_MUSIC |
case MUS_FLAC: |
FLAC_delete(music->data.flac); |
break; |
#endif |
#ifdef MP3_MUSIC |
case MUS_MP3: |
smpeg.SMPEG_delete(music->data.mp3); |
break; |
#endif |
#ifdef MP3_MAD_MUSIC |
case MUS_MP3_MAD: |
mad_closeFile(music->data.mp3_mad); |
break; |
#endif |
default: |
/* Unknown music type?? */ |
break; |
} |
skip: |
SDL_free(music); |
} |
} |
/* Find out the music format of a mixer music, or the currently playing |
music, if 'music' is NULL. |
*/ |
Mix_MusicType Mix_GetMusicType(const Mix_Music *music) |
{ |
Mix_MusicType type = MUS_NONE; |
if ( music ) { |
type = music->type; |
} else { |
SDL_LockAudio(); |
if ( music_playing ) { |
type = music_playing->type; |
} |
SDL_UnlockAudio(); |
} |
return(type); |
} |
/* Play a music chunk. Returns 0, or -1 if there was an error. |
*/ |
static int music_internal_play(Mix_Music *music, double position) |
{ |
int retval = 0; |
#if defined(__MACOSX__) && defined(USE_NATIVE_MIDI) |
/* This fixes a bug with native MIDI on Mac OS X, where you |
can't really stop and restart MIDI from the audio callback. |
*/ |
if ( music == music_playing && music->type == MUS_MID && native_midi_ok ) { |
/* Just a seek suffices to restart playing */ |
music_internal_position(position); |
return 0; |
} |
#endif |
/* Note the music we're playing */ |
if ( music_playing ) { |
music_internal_halt(); |
} |
music_playing = music; |
/* Set the initial volume */ |
if ( music->type != MUS_MOD ) { |
music_internal_initialize_volume(); |
} |
/* Set up for playback */ |
switch (music->type) { |
#ifdef CMD_MUSIC |
case MUS_CMD: |
MusicCMD_Start(music->data.cmd); |
break; |
#endif |
#ifdef WAV_MUSIC |
case MUS_WAV: |
WAVStream_Start(music->data.wave); |
break; |
#endif |
#ifdef MODPLUG_MUSIC |
case MUS_MODPLUG: |
/* can't set volume until file is loaded, so finally set it now */ |
music_internal_initialize_volume(); |
modplug_play(music->data.modplug); |
break; |
#endif |
#ifdef MOD_MUSIC |
case MUS_MOD: |
MOD_play(music->data.module); |
/* Player_SetVolume() does nothing before Player_Start() */ |
music_internal_initialize_volume(); |
break; |
#endif |
#ifdef MID_MUSIC |
case MUS_MID: |
#ifdef USE_NATIVE_MIDI |
if ( native_midi_ok ) { |
native_midi_start(music->data.nativemidi, music_loops); |
goto skip; |
} |
#endif |
#ifdef USE_FLUIDSYNTH_MIDI |
if (fluidsynth_ok ) { |
fluidsynth_start(music->data.fluidsynthmidi); |
goto skip; |
} |
#endif |
#ifdef USE_TIMIDITY_MIDI |
if ( timidity_ok ) { |
Timidity_Start(music->data.midi); |
goto skip; |
} |
#endif |
break; |
#endif |
#ifdef OGG_MUSIC |
case MUS_OGG: |
OGG_play(music->data.ogg); |
break; |
#endif |
#ifdef FLAC_MUSIC |
case MUS_FLAC: |
FLAC_play(music->data.flac); |
break; |
#endif |
#ifdef MP3_MUSIC |
case MUS_MP3: |
smpeg.SMPEG_enableaudio(music->data.mp3,1); |
smpeg.SMPEG_enablevideo(music->data.mp3,0); |
smpeg.SMPEG_play(music_playing->data.mp3); |
break; |
#endif |
#ifdef MP3_MAD_MUSIC |
case MUS_MP3_MAD: |
mad_start(music->data.mp3_mad); |
break; |
#endif |
default: |
Mix_SetError("Can't play unknown music type"); |
retval = -1; |
break; |
} |
skip: |
/* Set the playback position, note any errors if an offset is used */ |
if ( retval == 0 ) { |
if ( position > 0.0 ) { |
if ( music_internal_position(position) < 0 ) { |
Mix_SetError("Position not implemented for music type"); |
retval = -1; |
} |
} else { |
music_internal_position(0.0); |
} |
} |
/* If the setup failed, we're not playing any music anymore */ |
if ( retval < 0 ) { |
music_playing = NULL; |
} |
return(retval); |
} |
int Mix_FadeInMusicPos(Mix_Music *music, int loops, int ms, double position) |
{ |
int retval; |
if ( ms_per_step == 0 ) { |
SDL_SetError("Audio device hasn't been opened"); |
return(-1); |
} |
/* Don't play null pointers :-) */ |
if ( music == NULL ) { |
Mix_SetError("music parameter was NULL"); |
return(-1); |
} |
/* Setup the data */ |
if ( ms ) { |
music->fading = MIX_FADING_IN; |
} else { |
music->fading = MIX_NO_FADING; |
} |
music->fade_step = 0; |
music->fade_steps = ms/ms_per_step; |
/* Play the puppy */ |
SDL_LockAudio(); |
/* If the current music is fading out, wait for the fade to complete */ |
while ( music_playing && (music_playing->fading == MIX_FADING_OUT) ) { |
SDL_UnlockAudio(); |
SDL_Delay(100); |
SDL_LockAudio(); |
} |
music_active = 1; |
if (loops == 1) { |
/* Loop is the number of times to play the audio */ |
loops = 0; |
} |
music_loops = loops; |
retval = music_internal_play(music, position); |
SDL_UnlockAudio(); |
return(retval); |
} |
int Mix_FadeInMusic(Mix_Music *music, int loops, int ms) |
{ |
return Mix_FadeInMusicPos(music, loops, ms, 0.0); |
} |
int Mix_PlayMusic(Mix_Music *music, int loops) |
{ |
return Mix_FadeInMusicPos(music, loops, 0, 0.0); |
} |
/* Set the playing music position */ |
int music_internal_position(double position) |
{ |
int retval = 0; |
switch (music_playing->type) { |
#ifdef MODPLUG_MUSIC |
case MUS_MODPLUG: |
modplug_jump_to_time(music_playing->data.modplug, position); |
break; |
#endif |
#ifdef MOD_MUSIC |
case MUS_MOD: |
MOD_jump_to_time(music_playing->data.module, position); |
break; |
#endif |
#ifdef OGG_MUSIC |
case MUS_OGG: |
OGG_jump_to_time(music_playing->data.ogg, position); |
break; |
#endif |
#ifdef FLAC_MUSIC |
case MUS_FLAC: |
FLAC_jump_to_time(music_playing->data.flac, position); |
break; |
#endif |
#ifdef MP3_MUSIC |
case MUS_MP3: |
smpeg.SMPEG_rewind(music_playing->data.mp3); |
smpeg.SMPEG_play(music_playing->data.mp3); |
if ( position > 0.0 ) { |
smpeg.SMPEG_skip(music_playing->data.mp3, (float)position); |
} |
break; |
#endif |
#ifdef MP3_MAD_MUSIC |
case MUS_MP3_MAD: |
mad_seek(music_playing->data.mp3_mad, position); |
break; |
#endif |
default: |
/* TODO: Implement this for other music backends */ |
retval = -1; |
break; |
} |
return(retval); |
} |
int Mix_SetMusicPosition(double position) |
{ |
int retval; |
SDL_LockAudio(); |
if ( music_playing ) { |
retval = music_internal_position(position); |
if ( retval < 0 ) { |
Mix_SetError("Position not implemented for music type"); |
} |
} else { |
Mix_SetError("Music isn't playing"); |
retval = -1; |
} |
SDL_UnlockAudio(); |
return(retval); |
} |
/* Set the music's initial volume */ |
static void music_internal_initialize_volume(void) |
{ |
if ( music_playing->fading == MIX_FADING_IN ) { |
music_internal_volume(0); |
} else { |
music_internal_volume(music_volume); |
} |
} |
/* Set the music volume */ |
static void music_internal_volume(int volume) |
{ |
switch (music_playing->type) { |
#ifdef CMD_MUSIC |
case MUS_CMD: |
MusicCMD_SetVolume(volume); |
break; |
#endif |
#ifdef WAV_MUSIC |
case MUS_WAV: |
WAVStream_SetVolume(volume); |
break; |
#endif |
#ifdef MODPLUG_MUSIC |
case MUS_MODPLUG: |
modplug_setvolume(music_playing->data.modplug, volume); |
break; |
#endif |
#ifdef MOD_MUSIC |
case MUS_MOD: |
MOD_setvolume(music_playing->data.module, volume); |
break; |
#endif |
#ifdef MID_MUSIC |
case MUS_MID: |
#ifdef USE_NATIVE_MIDI |
if ( native_midi_ok ) { |
native_midi_setvolume(volume); |
return; |
} |
#endif |
#ifdef USE_FLUIDSYNTH_MIDI |
if ( fluidsynth_ok ) { |
fluidsynth_setvolume(music_playing->data.fluidsynthmidi, volume); |
return; |
} |
#endif |
#ifdef USE_TIMIDITY_MIDI |
if ( timidity_ok ) { |
Timidity_SetVolume(volume); |
return; |
} |
#endif |
break; |
#endif |
#ifdef OGG_MUSIC |
case MUS_OGG: |
OGG_setvolume(music_playing->data.ogg, volume); |
break; |
#endif |
#ifdef FLAC_MUSIC |
case MUS_FLAC: |
FLAC_setvolume(music_playing->data.flac, volume); |
break; |
#endif |
#ifdef MP3_MUSIC |
case MUS_MP3: |
smpeg.SMPEG_setvolume(music_playing->data.mp3,(int)(((float)volume/(float)MIX_MAX_VOLUME)*100.0)); |
break; |
#endif |
#ifdef MP3_MAD_MUSIC |
case MUS_MP3_MAD: |
mad_setVolume(music_playing->data.mp3_mad, volume); |
break; |
#endif |
default: |
/* Unknown music type?? */ |
break; |
} |
} |
int Mix_VolumeMusic(int volume) |
{ |
int prev_volume; |
prev_volume = music_volume; |
if ( volume < 0 ) { |
return prev_volume; |
} |
if ( volume > SDL_MIX_MAXVOLUME ) { |
volume = SDL_MIX_MAXVOLUME; |
} |
music_volume = volume; |
SDL_LockAudio(); |
if ( music_playing ) { |
music_internal_volume(music_volume); |
} |
SDL_UnlockAudio(); |
return(prev_volume); |
} |
/* Halt playing of music */ |
static void music_internal_halt(void) |
{ |
switch (music_playing->type) { |
#ifdef CMD_MUSIC |
case MUS_CMD: |
MusicCMD_Stop(music_playing->data.cmd); |
break; |
#endif |
#ifdef WAV_MUSIC |
case MUS_WAV: |
WAVStream_Stop(); |
break; |
#endif |
#ifdef MODPLUG_MUSIC |
case MUS_MODPLUG: |
modplug_stop(music_playing->data.modplug); |
break; |
#endif |
#ifdef MOD_MUSIC |
case MUS_MOD: |
MOD_stop(music_playing->data.module); |
break; |
#endif |
#ifdef MID_MUSIC |
case MUS_MID: |
#ifdef USE_NATIVE_MIDI |
if ( native_midi_ok ) { |
native_midi_stop(); |
goto skip; |
} |
#endif |
#ifdef USE_FLUIDSYNTH_MIDI |
if ( fluidsynth_ok ) { |
fluidsynth_stop(music_playing->data.fluidsynthmidi); |
goto skip; |
} |
#endif |
#ifdef USE_TIMIDITY_MIDI |
if ( timidity_ok ) { |
Timidity_Stop(); |
goto skip; |
} |
#endif |
break; |
#endif |
#ifdef OGG_MUSIC |
case MUS_OGG: |
OGG_stop(music_playing->data.ogg); |
break; |
#endif |
#ifdef FLAC_MUSIC |
case MUS_FLAC: |
FLAC_stop(music_playing->data.flac); |
break; |
#endif |
#ifdef MP3_MUSIC |
case MUS_MP3: |
smpeg.SMPEG_stop(music_playing->data.mp3); |
break; |
#endif |
#ifdef MP3_MAD_MUSIC |
case MUS_MP3_MAD: |
mad_stop(music_playing->data.mp3_mad); |
break; |
#endif |
default: |
/* Unknown music type?? */ |
return; |
} |
skip: |
music_playing->fading = MIX_NO_FADING; |
music_playing = NULL; |
} |
int Mix_HaltMusic(void) |
{ |
SDL_LockAudio(); |
if ( music_playing ) { |
music_internal_halt(); |
} |
SDL_UnlockAudio(); |
return(0); |
} |
/* Progressively stop the music */ |
int Mix_FadeOutMusic(int ms) |
{ |
int retval = 0; |
if ( ms_per_step == 0 ) { |
SDL_SetError("Audio device hasn't been opened"); |
return 0; |
} |
if (ms <= 0) { /* just halt immediately. */ |
Mix_HaltMusic(); |
return 1; |
} |
SDL_LockAudio(); |
if ( music_playing) { |
int fade_steps = (ms + ms_per_step - 1)/ms_per_step; |
if ( music_playing->fading == MIX_NO_FADING ) { |
music_playing->fade_step = 0; |
} else { |
int step; |
int old_fade_steps = music_playing->fade_steps; |
if ( music_playing->fading == MIX_FADING_OUT ) { |
step = music_playing->fade_step; |
} else { |
step = old_fade_steps |
- music_playing->fade_step + 1; |
} |
music_playing->fade_step = (step * fade_steps) |
/ old_fade_steps; |
} |
music_playing->fading = MIX_FADING_OUT; |
music_playing->fade_steps = fade_steps; |
retval = 1; |
} |
SDL_UnlockAudio(); |
return(retval); |
} |
Mix_Fading Mix_FadingMusic(void) |
{ |
Mix_Fading fading = MIX_NO_FADING; |
SDL_LockAudio(); |
if ( music_playing ) { |
fading = music_playing->fading; |
} |
SDL_UnlockAudio(); |
return(fading); |
} |
/* Pause/Resume the music stream */ |
void Mix_PauseMusic(void) |
{ |
music_active = 0; |
} |
void Mix_ResumeMusic(void) |
{ |
music_active = 1; |
} |
void Mix_RewindMusic(void) |
{ |
Mix_SetMusicPosition(0.0); |
} |
int Mix_PausedMusic(void) |
{ |
return (music_active == 0); |
} |
/* Check the status of the music */ |
static int music_internal_playing() |
{ |
int playing = 1; |
if (music_playing == NULL) { |
return 0; |
} |
switch (music_playing->type) { |
#ifdef CMD_MUSIC |
case MUS_CMD: |
if (!MusicCMD_Active(music_playing->data.cmd)) { |
playing = 0; |
} |
break; |
#endif |
#ifdef WAV_MUSIC |
case MUS_WAV: |
if ( ! WAVStream_Active() ) { |
playing = 0; |
} |
break; |
#endif |
#ifdef MODPLUG_MUSIC |
case MUS_MODPLUG: |
if ( ! modplug_playing(music_playing->data.modplug) ) { |
playing = 0; |
} |
break; |
#endif |
#ifdef MOD_MUSIC |
case MUS_MOD: |
if ( ! MOD_playing(music_playing->data.module) ) { |
playing = 0; |
} |
break; |
#endif |
#ifdef MID_MUSIC |
case MUS_MID: |
#ifdef USE_NATIVE_MIDI |
if ( native_midi_ok ) { |
if ( ! native_midi_active() ) |
playing = 0; |
goto skip; |
} |
#endif |
#ifdef USE_FLUIDSYNTH_MIDI |
if ( fluidsynth_ok ) { |
if ( ! fluidsynth_active(music_playing->data.fluidsynthmidi) ) |
playing = 0; |
goto skip; |
} |
#endif |
#ifdef USE_TIMIDITY_MIDI |
if ( timidity_ok ) { |
if ( ! Timidity_Active() ) |
playing = 0; |
goto skip; |
} |
#endif |
break; |
#endif |
#ifdef OGG_MUSIC |
case MUS_OGG: |
if ( ! OGG_playing(music_playing->data.ogg) ) { |
playing = 0; |
} |
break; |
#endif |
#ifdef FLAC_MUSIC |
case MUS_FLAC: |
if ( ! FLAC_playing(music_playing->data.flac) ) { |
playing = 0; |
} |
break; |
#endif |
#ifdef MP3_MUSIC |
case MUS_MP3: |
if ( smpeg.SMPEG_status(music_playing->data.mp3) != SMPEG_PLAYING ) |
playing = 0; |
break; |
#endif |
#ifdef MP3_MAD_MUSIC |
case MUS_MP3_MAD: |
if (!mad_isPlaying(music_playing->data.mp3_mad)) { |
playing = 0; |
} |
break; |
#endif |
default: |
playing = 0; |
break; |
} |
skip: |
return(playing); |
} |
int Mix_PlayingMusic(void) |
{ |
int playing = 0; |
SDL_LockAudio(); |
if ( music_playing ) { |
playing = music_loops || music_internal_playing(); |
} |
SDL_UnlockAudio(); |
return(playing); |
} |
/* Set the external music playback command */ |
int Mix_SetMusicCMD(const char *command) |
{ |
Mix_HaltMusic(); |
if ( music_cmd ) { |
SDL_free(music_cmd); |
music_cmd = NULL; |
} |
if ( command ) { |
music_cmd = (char *)SDL_malloc(strlen(command)+1); |
if ( music_cmd == NULL ) { |
return(-1); |
} |
strcpy(music_cmd, command); |
} |
return(0); |
} |
int Mix_SetSynchroValue(int i) |
{ |
/* Not supported by any players at this time */ |
return(-1); |
} |
int Mix_GetSynchroValue(void) |
{ |
/* Not supported by any players at this time */ |
return(-1); |
} |
/* Uninitialize the music players */ |
void close_music(void) |
{ |
Mix_HaltMusic(); |
#ifdef CMD_MUSIC |
Mix_SetMusicCMD(NULL); |
#endif |
#ifdef MODPLUG_MUSIC |
modplug_exit(); |
#endif |
#ifdef MOD_MUSIC |
MOD_exit(); |
#endif |
#ifdef MID_MUSIC |
# ifdef USE_TIMIDITY_MIDI |
Timidity_Close(); |
# endif |
#endif |
/* rcg06042009 report available decoders at runtime. */ |
SDL_free(music_decoders); |
music_decoders = NULL; |
num_decoders = 0; |
ms_per_step = 0; |
} |
int Mix_SetSoundFonts(const char *paths) |
{ |
#ifdef MID_MUSIC |
if (soundfont_paths) { |
SDL_free(soundfont_paths); |
soundfont_paths = NULL; |
} |
if (paths) { |
if (!(soundfont_paths = SDL_strdup(paths))) { |
Mix_SetError("Insufficient memory to set SoundFonts"); |
return 0; |
} |
} |
#endif |
return 1; |
} |
#ifdef MID_MUSIC |
const char* Mix_GetSoundFonts(void) |
{ |
const char* force = getenv("SDL_FORCE_SOUNDFONTS"); |
if (!soundfont_paths || (force && force[0] == '1')) { |
return getenv("SDL_SOUNDFONTS"); |
} else { |
return soundfont_paths; |
} |
} |
int Mix_EachSoundFont(int (*function)(const char*, void*), void *data) |
{ |
char *context, *path, *paths; |
const char* cpaths = Mix_GetSoundFonts(); |
if (!cpaths) { |
Mix_SetError("No SoundFonts have been requested"); |
return 0; |
} |
if (!(paths = SDL_strdup(cpaths))) { |
Mix_SetError("Insufficient memory to iterate over SoundFonts"); |
return 0; |
} |
#if defined(__MINGW32__) || defined(__MINGW64__) |
for (path = strtok(paths, ";"); path; path = strtok(NULL, ";")) { |
#elif defined(_WIN32) |
for (path = strtok_s(paths, ";", &context); path; path = strtok_s(NULL, ";", &context)) { |
#else |
for (path = strtok_r(paths, ":;", &context); path; path = strtok_r(NULL, ":;", &context)) { |
#endif |
if (!function(path, data)) { |
SDL_free(paths); |
return 0; |
} |
} |
SDL_free(paths); |
return 1; |
} |
#endif |
/contrib/games/wolf3d/SDL_mixer/music_cmd.h |
---|
0,0 → 1,62 |
/* |
SDL_mixer: An audio mixer library based on the SDL library |
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org> |
This software is provided 'as-is', without any express or implied |
warranty. In no event will the authors be held liable for any damages |
arising from the use of this software. |
Permission is granted to anyone to use this software for any purpose, |
including commercial applications, and to alter it and redistribute it |
freely, subject to the following restrictions: |
1. The origin of this software must not be misrepresented; you must not |
claim that you wrote the original software. If you use this software |
in a product, an acknowledgment in the product documentation would be |
appreciated but is not required. |
2. Altered source versions must be plainly marked as such, and must not be |
misrepresented as being the original software. |
3. This notice may not be removed or altered from any source distribution. |
*/ |
/* This file supports an external command for playing music */ |
#ifdef CMD_MUSIC |
#include <sys/types.h> |
#include <limits.h> |
#include <stdio.h> |
#if defined(__linux__) && defined(__arm__) |
# include <linux/limits.h> |
#endif |
typedef struct { |
char file[PATH_MAX]; |
char cmd[PATH_MAX]; |
pid_t pid; |
} MusicCMD; |
/* Unimplemented */ |
extern void MusicCMD_SetVolume(int volume); |
/* Load a music stream from the given file */ |
extern MusicCMD *MusicCMD_LoadSong(const char *cmd, const char *file); |
/* Start playback of a given music stream */ |
extern void MusicCMD_Start(MusicCMD *music); |
/* Stop playback of a stream previously started with MusicCMD_Start() */ |
extern void MusicCMD_Stop(MusicCMD *music); |
/* Pause playback of a given music stream */ |
extern void MusicCMD_Pause(MusicCMD *music); |
/* Resume playback of a given music stream */ |
extern void MusicCMD_Resume(MusicCMD *music); |
/* Close the given music stream */ |
extern void MusicCMD_FreeSong(MusicCMD *music); |
/* Return non-zero if a stream is currently playing */ |
extern int MusicCMD_Active(MusicCMD *music); |
#endif /* CMD_MUSIC */ |
/contrib/games/wolf3d/SDL_mixer/music_flac.h |
---|
0,0 → 1,90 |
/* |
SDL_mixer: An audio mixer library based on the SDL library |
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org> |
This software is provided 'as-is', without any express or implied |
warranty. In no event will the authors be held liable for any damages |
arising from the use of this software. |
Permission is granted to anyone to use this software for any purpose, |
including commercial applications, and to alter it and redistribute it |
freely, subject to the following restrictions: |
1. The origin of this software must not be misrepresented; you must not |
claim that you wrote the original software. If you use this software |
in a product, an acknowledgment in the product documentation would be |
appreciated but is not required. |
2. Altered source versions must be plainly marked as such, and must not be |
misrepresented as being the original software. |
3. This notice may not be removed or altered from any source distribution. |
Header to handle loading FLAC music files in SDL. |
~ Austen Dicken (admin@cvpcs.org) |
*/ |
/* $Id: $ */ |
#ifdef FLAC_MUSIC |
#include <FLAC/stream_decoder.h> |
typedef struct { |
FLAC__uint64 sample_size; |
unsigned sample_rate; |
unsigned channels; |
unsigned bits_per_sample; |
FLAC__uint64 total_samples; |
// the following are used to handle the callback nature of the writer |
int max_to_read; |
char *data; // pointer to beginning of data array |
int data_len; // size of data array |
int data_read; // amount of data array used |
char *overflow; // pointer to beginning of overflow array |
int overflow_len; // size of overflow array |
int overflow_read; // amount of overflow array used |
} FLAC_Data; |
typedef struct { |
int playing; |
int volume; |
int section; |
FLAC__StreamDecoder *flac_decoder; |
FLAC_Data flac_data; |
SDL_RWops *rwops; |
int freerw; |
SDL_AudioCVT cvt; |
int len_available; |
Uint8 *snd_available; |
} FLAC_music; |
/* Initialize the FLAC player, with the given mixer settings |
This function returns 0, or -1 if there was an error. |
*/ |
extern int FLAC_init(SDL_AudioSpec *mixer); |
/* Set the volume for a FLAC stream */ |
extern void FLAC_setvolume(FLAC_music *music, int volume); |
/* Load an FLAC stream from an SDL_RWops object */ |
extern FLAC_music *FLAC_new_RW(SDL_RWops *rw, int freerw); |
/* Start playback of a given FLAC stream */ |
extern void FLAC_play(FLAC_music *music); |
/* Return non-zero if a stream is currently playing */ |
extern int FLAC_playing(FLAC_music *music); |
/* Play some of a stream previously started with FLAC_play() */ |
extern int FLAC_playAudio(FLAC_music *music, Uint8 *stream, int len); |
/* Stop playback of a stream previously started with FLAC_play() */ |
extern void FLAC_stop(FLAC_music *music); |
/* Close the given FLAC stream */ |
extern void FLAC_delete(FLAC_music *music); |
/* Jump (seek) to a given position (time is in seconds) */ |
extern void FLAC_jump_to_time(FLAC_music *music, double time); |
#endif /* FLAC_MUSIC */ |
/contrib/games/wolf3d/SDL_mixer/music_mad.h |
---|
0,0 → 1,72 |
/* |
SDL_mixer: An audio mixer library based on the SDL library |
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org> |
This software is provided 'as-is', without any express or implied |
warranty. In no event will the authors be held liable for any damages |
arising from the use of this software. |
Permission is granted to anyone to use this software for any purpose, |
including commercial applications, and to alter it and redistribute it |
freely, subject to the following restrictions: |
1. The origin of this software must not be misrepresented; you must not |
claim that you wrote the original software. If you use this software |
in a product, an acknowledgment in the product documentation would be |
appreciated but is not required. |
2. Altered source versions must be plainly marked as such, and must not be |
misrepresented as being the original software. |
3. This notice may not be removed or altered from any source distribution. |
*/ |
#ifdef MP3_MAD_MUSIC |
#include "mad.h" |
#include "SDL_rwops.h" |
#include "SDL_audio.h" |
#include "SDL_mixer.h" |
#define MAD_INPUT_BUFFER_SIZE (5*8192) |
#define MAD_OUTPUT_BUFFER_SIZE 8192 |
enum { |
MS_input_eof = 0x0001, |
MS_input_error = 0x0001, |
MS_decode_eof = 0x0002, |
MS_decode_error = 0x0004, |
MS_error_flags = 0x000f, |
MS_playing = 0x0100, |
MS_cvt_decoded = 0x0200, |
}; |
typedef struct { |
SDL_RWops *rw; |
int freerw; |
struct mad_stream stream; |
struct mad_frame frame; |
struct mad_synth synth; |
int frames_read; |
mad_timer_t next_frame_start; |
int volume; |
int status; |
int output_begin, output_end; |
SDL_AudioSpec mixer; |
SDL_AudioCVT cvt; |
unsigned char input_buffer[MAD_INPUT_BUFFER_SIZE + MAD_BUFFER_GUARD]; |
unsigned char output_buffer[MAD_OUTPUT_BUFFER_SIZE]; |
} mad_data; |
mad_data *mad_openFileRW(SDL_RWops *rw, SDL_AudioSpec *mixer, int freerw); |
void mad_closeFile(mad_data *mp3_mad); |
void mad_start(mad_data *mp3_mad); |
void mad_stop(mad_data *mp3_mad); |
int mad_isPlaying(mad_data *mp3_mad); |
int mad_getSamples(mad_data *mp3_mad, Uint8 *stream, int len); |
void mad_seek(mad_data *mp3_mad, double position); |
void mad_setVolume(mad_data *mp3_mad, int volume); |
#endif |
/contrib/games/wolf3d/SDL_mixer/music_mod.h |
---|
0,0 → 1,62 |
/* |
SDL_mixer: An audio mixer library based on the SDL library |
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org> |
This software is provided 'as-is', without any express or implied |
warranty. In no event will the authors be held liable for any damages |
arising from the use of this software. |
Permission is granted to anyone to use this software for any purpose, |
including commercial applications, and to alter it and redistribute it |
freely, subject to the following restrictions: |
1. The origin of this software must not be misrepresented; you must not |
claim that you wrote the original software. If you use this software |
in a product, an acknowledgment in the product documentation would be |
appreciated but is not required. |
2. Altered source versions must be plainly marked as such, and must not be |
misrepresented as being the original software. |
3. This notice may not be removed or altered from any source distribution. |
*/ |
/* $Id: music_mod.h 4211 2008-12-08 00:27:32Z slouken $ */ |
#ifdef MOD_MUSIC |
/* This file supports MOD tracker music streams */ |
struct MODULE; |
/* Initialize the Ogg Vorbis player, with the given mixer settings |
This function returns 0, or -1 if there was an error. |
*/ |
extern int MOD_init(SDL_AudioSpec *mixer); |
/* Uninitialize the music players */ |
extern void MOD_exit(void); |
/* Set the volume for a MOD stream */ |
extern void MOD_setvolume(struct MODULE *music, int volume); |
/* Load a MOD stream from an SDL_RWops object */ |
extern struct MODULE *MOD_new_RW(SDL_RWops *rw, int freerw); |
/* Start playback of a given MOD stream */ |
extern void MOD_play(struct MODULE *music); |
/* Return non-zero if a stream is currently playing */ |
extern int MOD_playing(struct MODULE *music); |
/* Play some of a stream previously started with MOD_play() */ |
extern int MOD_playAudio(struct MODULE *music, Uint8 *stream, int len); |
/* Stop playback of a stream previously started with MOD_play() */ |
extern void MOD_stop(struct MODULE *music); |
/* Close the given MOD stream */ |
extern void MOD_delete(struct MODULE *music); |
/* Jump (seek) to a given position (time is in seconds) */ |
extern void MOD_jump_to_time(struct MODULE *music, double time); |
#endif /* MOD_MUSIC */ |
/contrib/games/wolf3d/SDL_mixer/music_modplug.h |
---|
0,0 → 1,42 |
#ifdef MODPLUG_MUSIC |
#include "modplug.h" |
#include "SDL_rwops.h" |
#include "SDL_audio.h" |
#include "SDL_mixer.h" |
typedef struct { |
ModPlugFile *file; |
int playing; |
} modplug_data; |
int modplug_init(SDL_AudioSpec *mixer); |
/* Uninitialize the music players */ |
void modplug_exit(void); |
/* Set the volume for a modplug stream */ |
void modplug_setvolume(modplug_data *music, int volume); |
/* Load a modplug stream from an SDL_RWops object */ |
modplug_data *modplug_new_RW(SDL_RWops *rw, int freerw); |
/* Start playback of a given modplug stream */ |
void modplug_play(modplug_data *music); |
/* Return non-zero if a stream is currently playing */ |
int modplug_playing(modplug_data *music); |
/* Play some of a stream previously started with modplug_play() */ |
int modplug_playAudio(modplug_data *music, Uint8 *stream, int len); |
/* Stop playback of a stream previously started with modplug_play() */ |
void modplug_stop(modplug_data *music); |
/* Close the given modplug stream */ |
void modplug_delete(modplug_data *music); |
/* Jump (seek) to a given position (time is in seconds) */ |
void modplug_jump_to_time(modplug_data *music, double time); |
#endif |
/contrib/games/wolf3d/SDL_mixer/music_ogg.h |
---|
0,0 → 1,75 |
/* |
SDL_mixer: An audio mixer library based on the SDL library |
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org> |
This software is provided 'as-is', without any express or implied |
warranty. In no event will the authors be held liable for any damages |
arising from the use of this software. |
Permission is granted to anyone to use this software for any purpose, |
including commercial applications, and to alter it and redistribute it |
freely, subject to the following restrictions: |
1. The origin of this software must not be misrepresented; you must not |
claim that you wrote the original software. If you use this software |
in a product, an acknowledgment in the product documentation would be |
appreciated but is not required. |
2. Altered source versions must be plainly marked as such, and must not be |
misrepresented as being the original software. |
3. This notice may not be removed or altered from any source distribution. |
*/ |
/* $Id$ */ |
#ifdef OGG_MUSIC |
/* This file supports Ogg Vorbis music streams */ |
#ifdef OGG_USE_TREMOR |
#include <tremor/ivorbisfile.h> |
#else |
#include <vorbis/vorbisfile.h> |
#endif |
typedef struct { |
SDL_RWops *rw; |
int freerw; |
int playing; |
int volume; |
OggVorbis_File vf; |
int section; |
SDL_AudioCVT cvt; |
int len_available; |
Uint8 *snd_available; |
} OGG_music; |
/* Initialize the Ogg Vorbis player, with the given mixer settings |
This function returns 0, or -1 if there was an error. |
*/ |
extern int OGG_init(SDL_AudioSpec *mixer); |
/* Set the volume for an OGG stream */ |
extern void OGG_setvolume(OGG_music *music, int volume); |
/* Load an OGG stream from an SDL_RWops object */ |
extern OGG_music *OGG_new_RW(SDL_RWops *rw, int freerw); |
/* Start playback of a given OGG stream */ |
extern void OGG_play(OGG_music *music); |
/* Return non-zero if a stream is currently playing */ |
extern int OGG_playing(OGG_music *music); |
/* Play some of a stream previously started with OGG_play() */ |
extern int OGG_playAudio(OGG_music *music, Uint8 *stream, int len); |
/* Stop playback of a stream previously started with OGG_play() */ |
extern void OGG_stop(OGG_music *music); |
/* Close the given OGG stream */ |
extern void OGG_delete(OGG_music *music); |
/* Jump (seek) to a given position (time is in seconds) */ |
extern void OGG_jump_to_time(OGG_music *music, double time); |
#endif /* OGG_MUSIC */ |
/contrib/games/wolf3d/SDL_mixer/wavestream.h |
---|
0,0 → 1,60 |
/* |
SDL_mixer: An audio mixer library based on the SDL library |
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org> |
This software is provided 'as-is', without any express or implied |
warranty. In no event will the authors be held liable for any damages |
arising from the use of this software. |
Permission is granted to anyone to use this software for any purpose, |
including commercial applications, and to alter it and redistribute it |
freely, subject to the following restrictions: |
1. The origin of this software must not be misrepresented; you must not |
claim that you wrote the original software. If you use this software |
in a product, an acknowledgment in the product documentation would be |
appreciated but is not required. |
2. Altered source versions must be plainly marked as such, and must not be |
misrepresented as being the original software. |
3. This notice may not be removed or altered from any source distribution. |
*/ |
/* $Id$ */ |
/* This file supports streaming WAV files, without volume adjustment */ |
#include <stdio.h> |
typedef struct { |
SDL_RWops *rw; |
SDL_bool freerw; |
long start; |
long stop; |
SDL_AudioCVT cvt; |
} WAVStream; |
/* Initialize the WAVStream player, with the given mixer settings |
This function returns 0, or -1 if there was an error. |
*/ |
extern int WAVStream_Init(SDL_AudioSpec *mixer); |
/* Unimplemented */ |
extern void WAVStream_SetVolume(int volume); |
/* Load a WAV stream from an SDL_RWops object */ |
extern WAVStream *WAVStream_LoadSong_RW(SDL_RWops *rw, const char *magic, int freerw); |
/* Start playback of a given WAV stream */ |
extern void WAVStream_Start(WAVStream *wave); |
/* Play some of a stream previously started with WAVStream_Start() */ |
extern int WAVStream_PlaySome(Uint8 *stream, int len); |
/* Stop playback of a stream previously started with WAVStream_Start() */ |
extern void WAVStream_Stop(void); |
/* Close the given WAV stream */ |
extern void WAVStream_FreeSong(WAVStream *wave); |
/* Return non-zero if a stream is currently playing */ |
extern int WAVStream_Active(void); |
/contrib/games/wolf3d/compile_flags.txt |
---|
0,0 → 1,4 |
-I |
../../sdk/sources/SDL-1.2.2_newlib/include |
../../sdk/sources/newlib/libc/include |
. |
/contrib/games/wolf3d/id_sd.cpp |
---|
27,21 → 27,16 |
// NeedsMusic - load music? |
// |
/// ///////////// /// |
/// In Kolibrios - stub |
#include "wl_def.h" |
//#include <SDL_mixer.h> |
#include "SDL_mixer/SDL_mixer.h" |
#if defined(GP2X_940) |
#include "gp2x/fmopl.h" |
#else |
#ifdef USE_GPL |
#include "dosbox/dbopl.h" |
#else |
#include "mame/fmopl.h" |
#endif |
#endif |
#pragma hdrstop |
#define ORIGSAMPLERATE 7042 |
typedef struct |
71,6 → 66,11 |
uint32_t length; |
} digiinfo; |
static Mix_Chunk *SoundChunks[ STARTMUSIC - STARTDIGISOUNDS]; |
static byte *SoundBuffers[STARTMUSIC - STARTDIGISOUNDS]; |
globalsoundpos channelSoundPos[MIX_CHANNELS]; |
// Global variables |
boolean AdLibPresent, |
SoundBlasterPresent,SBProPresent, |
116,29 → 116,1309 |
static int sqHackSeqLen; |
static longword sqHackTime; |
// STUB |
void SD_Startup(void){}; |
void SD_Shutdown(void){}; |
int SD_GetChannelForDigi(int which){}; |
void SD_PositionSound(int leftvol,int rightvol){}; |
boolean SD_PlaySound(soundnames sound){}; |
void SD_SetPosition(int channel, int leftvol,int rightvol){}; |
void SD_StopSound(void){}; |
void SD_WaitSoundDone(void){}; |
static void SDL_SoundFinished(void) |
{ |
SoundNumber = (soundnames)0; |
SoundPriority = 0; |
} |
void SD_StartMusic(int chunk){}; |
void SD_ContinueMusic(int chunk, int startoffs){}; |
void SD_MusicOn(void){}; |
void SD_FadeOutMusic(void){}; |
int SD_MusicOff(void){}; |
boolean SD_MusicPlaying(void){}; |
boolean SD_SetSoundMode(SDMode mode){}; |
boolean SD_SetMusicMode(SMMode mode){}; |
word SD_SoundPlaying(void){}; |
#ifdef NOTYET |
void SD_SetDigiDevice(SDSMode){}; |
void SD_PrepareSound(int which){}; |
int SD_PlayDigitized(word which,int leftpos,int rightpos){}; |
void SD_StopDigitized(void){}; |
void SDL_turnOnPCSpeaker(word timerval); |
#pragma aux SDL_turnOnPCSpeaker = \ |
"mov al,0b6h" \ |
"out 43h,al" \ |
"mov al,bl" \ |
"out 42h,al" \ |
"mov al,bh" \ |
"out 42h,al" \ |
"in al,61h" \ |
"or al,3" \ |
"out 61h,al" \ |
parm [bx] \ |
modify exact [al] |
void SDL_turnOffPCSpeaker(); |
#pragma aux SDL_turnOffPCSpeaker = \ |
"in al,61h" \ |
"and al,0fch" \ |
"out 61h,al" \ |
modify exact [al] |
void SDL_setPCSpeaker(byte val); |
#pragma aux SDL_setPCSpeaker = \ |
"in al,61h" \ |
"and al,0fch" \ |
"or al,ah" \ |
"out 61h,al" \ |
parm [ah] \ |
modify exact [al] |
void inline SDL_DoFX() |
{ |
if(pcSound) |
{ |
if(*pcSound!=pcLastSample) |
{ |
pcLastSample=*pcSound; |
if(pcLastSample) |
SDL_turnOnPCSpeaker(pcLastSample*60); |
else |
SDL_turnOffPCSpeaker(); |
} |
pcSound++; |
pcLengthLeft--; |
if(!pcLengthLeft) |
{ |
pcSound=0; |
SoundNumber=(soundnames)0; |
SoundPriority=0; |
SDL_turnOffPCSpeaker(); |
} |
} |
// [adlib sound stuff removed...] |
} |
static void SDL_DigitizedDoneInIRQ(void); |
void inline SDL_DoFast() |
{ |
count_fx++; |
if(count_fx>=5) |
{ |
count_fx=0; |
SDL_DoFX(); |
count_time++; |
if(count_time>=2) |
{ |
TimeCount++; |
count_time=0; |
} |
} |
// [adlib music and soundsource stuff removed...] |
TimerCount+=TimerDivisor; |
if(*((word *)&TimerCount+1)) |
{ |
*((word *)&TimerCount+1)=0; |
t0OldService(); |
} |
else |
{ |
outp(0x20,0x20); |
} |
} |
// Timer 0 ISR for 7000Hz interrupts |
void __interrupt SDL_t0ExtremeAsmService(void) |
{ |
if(pcindicate) |
{ |
if(pcSound) |
{ |
SDL_setPCSpeaker(((*pcSound++)&0x80)>>6); |
pcLengthLeft--; |
if(!pcLengthLeft) |
{ |
pcSound=0; |
SDL_turnOffPCSpeaker(); |
SDL_DigitizedDoneInIRQ(); |
} |
} |
} |
extreme++; |
if(extreme>=10) |
{ |
extreme=0; |
SDL_DoFast(); |
} |
else |
outp(0x20,0x20); |
} |
// Timer 0 ISR for 700Hz interrupts |
void __interrupt SDL_t0FastAsmService(void) |
{ |
SDL_DoFast(); |
} |
// Timer 0 ISR for 140Hz interrupts |
void __interrupt SDL_t0SlowAsmService(void) |
{ |
count_time++; |
if(count_time>=2) |
{ |
TimeCount++; |
count_time=0; |
} |
SDL_DoFX(); |
TimerCount+=TimerDivisor; |
if(*((word *)&TimerCount+1)) |
{ |
*((word *)&TimerCount+1)=0; |
t0OldService(); |
} |
else |
outp(0x20,0x20); |
} |
void SDL_IndicatePC(boolean ind) |
{ |
pcindicate=ind; |
} |
/////////////////////////////////////////////////////////////////////////// |
// |
// SDL_SetTimer0() - Sets system timer 0 to the specified speed |
// |
/////////////////////////////////////////////////////////////////////////// |
static void |
SDL_SetTimer0(word speed) |
{ |
#ifndef TPROF // If using Borland's profiling, don't screw with the timer |
// _asm pushfd |
_asm cli |
outp(0x43,0x36); // Change timer 0 |
outp(0x40,(byte)speed); |
outp(0x40,speed >> 8); |
// Kludge to handle special case for digitized PC sounds |
if (TimerDivisor == (1192030 / (TickBase * 100))) |
TimerDivisor = (1192030 / (TickBase * 10)); |
else |
TimerDivisor = speed; |
// _asm popfd |
_asm sti |
#else |
TimerDivisor = 0x10000; |
#endif |
} |
/////////////////////////////////////////////////////////////////////////// |
// |
// SDL_SetIntsPerSec() - Uses SDL_SetTimer0() to set the number of |
// interrupts generated by system timer 0 per second |
// |
/////////////////////////////////////////////////////////////////////////// |
static void |
SDL_SetIntsPerSec(word ints) |
{ |
TimerRate = ints; |
SDL_SetTimer0(1192030 / ints); |
} |
static void |
SDL_SetTimerSpeed(void) |
{ |
word rate; |
void (_interrupt *isr)(void); |
if ((DigiMode == sds_PC) && DigiPlaying) |
{ |
rate = TickBase * 100; |
isr = SDL_t0ExtremeAsmService; |
} |
else if ((MusicMode == smm_AdLib) || ((DigiMode == sds_SoundSource) && DigiPlaying) ) |
{ |
rate = TickBase * 10; |
isr = SDL_t0FastAsmService; |
} |
else |
{ |
rate = TickBase * 2; |
isr = SDL_t0SlowAsmService; |
} |
if (rate != TimerRate) |
{ |
_dos_setvect(8,isr); |
SDL_SetIntsPerSec(rate); |
TimerRate = rate; |
} |
} |
// |
// PC Sound code |
// |
/////////////////////////////////////////////////////////////////////////// |
// |
// SDL_PCPlaySample() - Plays the specified sample on the PC speaker |
// |
/////////////////////////////////////////////////////////////////////////// |
#ifdef _MUSE_ |
void |
#else |
static void |
#endif |
SDL_PCPlaySample(byte *data,longword len,boolean inIRQ) |
{ |
if(!inIRQ) |
{ |
// _asm pushfd |
_asm cli |
} |
SDL_IndicatePC(true); |
pcLengthLeft = len; |
pcSound = (volatile byte *)data; |
if(!inIRQ) |
{ |
// _asm popfd |
_asm sti |
} |
} |
/////////////////////////////////////////////////////////////////////////// |
// |
// SDL_PCStopSample() - Stops a sample playing on the PC speaker |
// |
/////////////////////////////////////////////////////////////////////////// |
#ifdef _MUSE_ |
void |
#else |
static void |
#endif |
SDL_PCStopSampleInIRQ(void) |
{ |
pcSound = 0; |
SDL_IndicatePC(false); |
_asm in al,0x61 // Turn the speaker off |
_asm and al,0xfd // ~2 |
_asm out 0x61,al |
} |
/////////////////////////////////////////////////////////////////////////// |
// |
// SDL_PCPlaySound() - Plays the specified sound on the PC speaker |
// |
/////////////////////////////////////////////////////////////////////////// |
#ifdef _MUSE_ |
void |
#else |
static void |
#endif |
SDL_PCPlaySound(PCSound *sound) |
{ |
// _asm pushfd |
_asm cli |
pcLastSample = -1; |
pcLengthLeft = sound->common.length; |
pcSound = sound->data; |
// _asm popfd |
_asm sti |
} |
/////////////////////////////////////////////////////////////////////////// |
// |
// SDL_PCStopSound() - Stops the current sound playing on the PC Speaker |
// |
/////////////////////////////////////////////////////////////////////////// |
#ifdef _MUSE_ |
void |
#else |
static void |
#endif |
SDL_PCStopSound(void) |
{ |
// _asm pushfd |
_asm cli |
pcSound = 0; |
_asm in al,0x61 // Turn the speaker off |
_asm and al,0xfd // ~2 |
_asm out 0x61,al |
// _asm popfd |
_asm sti |
} |
/////////////////////////////////////////////////////////////////////////// |
// |
// SDL_ShutPC() - Turns off the pc speaker |
// |
/////////////////////////////////////////////////////////////////////////// |
static void |
SDL_ShutPC(void) |
{ |
// _asm pushfd |
_asm cli |
pcSound = 0; |
_asm in al,0x61 // Turn the speaker & gate off |
_asm and al,0xfc // ~3 |
_asm out 0x61,al |
// _asm popfd |
_asm sti |
} |
#endif |
void |
SD_StopDigitized(void) |
{ |
DigiPlaying = false; |
DigiNumber = (soundnames) 0; |
DigiPriority = 0; |
SoundPositioned = false; |
if ((DigiMode == sds_PC) && (SoundMode == sdm_PC)) |
SDL_SoundFinished(); |
switch (DigiMode) |
{ |
case sds_PC: |
// SDL_PCStopSampleInIRQ(); |
break; |
case sds_SoundBlaster: |
// SDL_SBStopSampleInIRQ(); |
Mix_HaltChannel(-1); |
break; |
} |
} |
int SD_GetChannelForDigi(int which) |
{ |
if(DigiChannel[which] != -1) return DigiChannel[which]; |
int channel = Mix_GroupAvailable(1); |
if(channel == -1) channel = Mix_GroupOldest(1); |
if(channel == -1) // All sounds stopped in the meantime? |
return Mix_GroupAvailable(1); |
return channel; |
} |
void SD_SetPosition(int channel, int leftpos, int rightpos) |
{ |
if((leftpos < 0) || (leftpos > 15) || (rightpos < 0) || (rightpos > 15) |
|| ((leftpos == 15) && (rightpos == 15))) |
Quit("SD_SetPosition: Illegal position"); |
switch (DigiMode) |
{ |
case sds_SoundBlaster: |
// SDL_PositionSBP(leftpos,rightpos); |
Mix_SetPanning(channel, ((15 - leftpos) << 4) + 15, |
((15 - rightpos) << 4) + 15); |
break; |
} |
} |
Sint16 GetSample(float csample, byte *samples, int size) |
{ |
float s0=0, s1=0, s2=0; |
int cursample = (int) csample; |
float sf = csample - (float) cursample; |
if(cursample-1 >= 0) s0 = (float) (samples[cursample-1] - 128); |
s1 = (float) (samples[cursample] - 128); |
if(cursample+1 < size) s2 = (float) (samples[cursample+1] - 128); |
float val = s0*sf*(sf-1)/2 - s1*(sf*sf-1) + s2*(sf+1)*sf/2; |
int32_t intval = (int32_t) (val * 256); |
if(intval < -32768) intval = -32768; |
else if(intval > 32767) intval = 32767; |
return (Sint16) intval; |
} |
void SD_PrepareSound(int which) |
{ |
if(DigiList == NULL) |
Quit("SD_PrepareSound(%i): DigiList not initialized!\n", which); |
int page = DigiList[which].startpage; |
int size = DigiList[which].length; |
byte *origsamples = PM_GetSound(page); |
if(origsamples + size >= PM_GetEnd()) |
Quit("SD_PrepareSound(%i): Sound reaches out of page file!\n", which); |
int destsamples = (int) ((float) size * (float) param_samplerate |
/ (float) ORIGSAMPLERATE); |
byte *wavebuffer = (byte *) malloc(sizeof(headchunk) + sizeof(wavechunk) |
+ destsamples * 2); // dest are 16-bit samples |
if(wavebuffer == NULL) |
Quit("Unable to allocate wave buffer for sound %i!\n", which); |
headchunk head = {{'R','I','F','F'}, 0, {'W','A','V','E'}, |
{'f','m','t',' '}, 0x10, 0x0001, 1, param_samplerate, param_samplerate*2, 2, 16}; |
wavechunk dhead = {{'d', 'a', 't', 'a'}, destsamples*2}; |
head.filelenminus8 = sizeof(head) + destsamples*2; // (sizeof(dhead)-8 = 0) |
memcpy(wavebuffer, &head, sizeof(head)); |
memcpy(wavebuffer+sizeof(head), &dhead, sizeof(dhead)); |
// alignment is correct, as wavebuffer comes from malloc |
// and sizeof(headchunk) % 4 == 0 and sizeof(wavechunk) % 4 == 0 |
Sint16 *newsamples = (Sint16 *)(void *) (wavebuffer + sizeof(headchunk) |
+ sizeof(wavechunk)); |
float cursample = 0.F; |
float samplestep = (float) ORIGSAMPLERATE / (float) param_samplerate; |
for(int i=0; i<destsamples; i++, cursample+=samplestep) |
{ |
newsamples[i] = GetSample((float)size * (float)i / (float)destsamples, |
origsamples, size); |
} |
SoundBuffers[which] = wavebuffer; |
SoundChunks[which] = Mix_LoadWAV_RW(SDL_RWFromMem(wavebuffer, |
sizeof(headchunk) + sizeof(wavechunk) + destsamples * 2), 1); |
} |
int SD_PlayDigitized(word which,int leftpos,int rightpos) |
{ |
if (!DigiMode) |
return 0; |
if (which >= NumDigi) |
Quit("SD_PlayDigitized: bad sound number %i", which); |
int channel = SD_GetChannelForDigi(which); |
SD_SetPosition(channel, leftpos,rightpos); |
DigiPlaying = true; |
Mix_Chunk *sample = SoundChunks[which]; |
if(sample == NULL) |
{ |
printf("SoundChunks[%i] is NULL!\n", which); |
return 0; |
} |
if(Mix_PlayChannel(channel, sample, 0) == -1) |
{ |
printf("Unable to play sound: %s\n", Mix_GetError()); |
return 0; |
} |
return channel; |
} |
void SD_ChannelFinished(int channel) |
{ |
channelSoundPos[channel].valid = 0; |
} |
void |
SD_SetDigiDevice(SDSMode mode) |
{ |
boolean devicenotpresent; |
if (mode == DigiMode) |
return; |
SD_StopDigitized(); |
devicenotpresent = false; |
switch (mode) |
{ |
case sds_SoundBlaster: |
if (!SoundBlasterPresent) |
devicenotpresent = true; |
break; |
} |
if (!devicenotpresent) |
{ |
DigiMode = mode; |
#ifdef NOTYET |
SDL_SetTimerSpeed(); |
#endif |
} |
} |
void |
SDL_SetupDigi(void) |
{ |
// Correct padding enforced by PM_Startup() |
word *soundInfoPage = (word *) (void *) PM_GetPage(ChunksInFile-1); |
NumDigi = (word) PM_GetPageSize(ChunksInFile - 1) / 4; |
DigiList = (digiinfo *) malloc(NumDigi * sizeof(digiinfo)); |
int i; |
for(i = 0; i < NumDigi; i++) |
{ |
// Calculate the size of the digi from the sizes of the pages between |
// the start page and the start page of the next sound |
DigiList[i].startpage = soundInfoPage[i * 2]; |
if((int) DigiList[i].startpage >= ChunksInFile - 1) |
{ |
NumDigi = i; |
break; |
} |
int lastPage; |
if(i < NumDigi - 1) |
{ |
lastPage = soundInfoPage[i * 2 + 2]; |
if(lastPage == 0 || lastPage + PMSoundStart > ChunksInFile - 1) lastPage = ChunksInFile - 1; |
else lastPage += PMSoundStart; |
} |
else lastPage = ChunksInFile - 1; |
int size = 0; |
for(int page = PMSoundStart + DigiList[i].startpage; page < lastPage; page++) |
size += PM_GetPageSize(page); |
// Don't include padding of sound info page, if padding was added |
if(lastPage == ChunksInFile - 1 && PMSoundInfoPagePadded) size--; |
// Patch lower 16-bit of size with size from sound info page. |
// The original VSWAP contains padding which is included in the page size, |
// but not included in the 16-bit size. So we use the more precise value. |
if((size & 0xffff0000) != 0 && (size & 0xffff) < soundInfoPage[i * 2 + 1]) |
size -= 0x10000; |
size = (size & 0xffff0000) | soundInfoPage[i * 2 + 1]; |
DigiList[i].length = size; |
} |
for(i = 0; i < LASTSOUND; i++) |
{ |
DigiMap[i] = -1; |
DigiChannel[i] = -1; |
} |
} |
// AdLib Code |
/////////////////////////////////////////////////////////////////////////// |
// |
// SDL_ALStopSound() - Turns off any sound effects playing through the |
// AdLib card |
// |
/////////////////////////////////////////////////////////////////////////// |
static void |
SDL_ALStopSound(void) |
{ |
alSound = 0; |
alOut(alFreqH + 0, 0); |
} |
static void |
SDL_AlSetFXInst(Instrument *inst) |
{ |
byte c,m; |
m = 0; // modulator cell for channel 0 |
c = 3; // carrier cell for channel 0 |
alOut(m + alChar,inst->mChar); |
alOut(m + alScale,inst->mScale); |
alOut(m + alAttack,inst->mAttack); |
alOut(m + alSus,inst->mSus); |
alOut(m + alWave,inst->mWave); |
alOut(c + alChar,inst->cChar); |
alOut(c + alScale,inst->cScale); |
alOut(c + alAttack,inst->cAttack); |
alOut(c + alSus,inst->cSus); |
alOut(c + alWave,inst->cWave); |
// Note: Switch commenting on these lines for old MUSE compatibility |
// alOutInIRQ(alFeedCon,inst->nConn); |
alOut(alFeedCon,0); |
} |
/////////////////////////////////////////////////////////////////////////// |
// |
// SDL_ALPlaySound() - Plays the specified sound on the AdLib card |
// |
/////////////////////////////////////////////////////////////////////////// |
static void |
SDL_ALPlaySound(AdLibSound *sound) |
{ |
Instrument *inst; |
byte *data; |
SDL_ALStopSound(); |
alLengthLeft = sound->common.length; |
data = sound->data; |
alBlock = ((sound->block & 7) << 2) | 0x20; |
inst = &sound->inst; |
if (!(inst->mSus | inst->cSus)) |
{ |
Quit("SDL_ALPlaySound() - Bad instrument"); |
} |
SDL_AlSetFXInst(inst); |
alSound = (byte *)data; |
} |
/////////////////////////////////////////////////////////////////////////// |
// |
// SDL_ShutAL() - Shuts down the AdLib card for sound effects |
// |
/////////////////////////////////////////////////////////////////////////// |
static void |
SDL_ShutAL(void) |
{ |
alSound = 0; |
alOut(alEffects,0); |
alOut(alFreqH + 0,0); |
SDL_AlSetFXInst(&alZeroInst); |
} |
/////////////////////////////////////////////////////////////////////////// |
// |
// SDL_CleanAL() - Totally shuts down the AdLib card |
// |
/////////////////////////////////////////////////////////////////////////// |
static void |
SDL_CleanAL(void) |
{ |
int i; |
alOut(alEffects,0); |
for (i = 1; i < 0xf5; i++) |
alOut(i, 0); |
} |
/////////////////////////////////////////////////////////////////////////// |
// |
// SDL_StartAL() - Starts up the AdLib card for sound effects |
// |
/////////////////////////////////////////////////////////////////////////// |
static void |
SDL_StartAL(void) |
{ |
alOut(alEffects, 0); |
SDL_AlSetFXInst(&alZeroInst); |
} |
/////////////////////////////////////////////////////////////////////////// |
// |
// SDL_DetectAdLib() - Determines if there's an AdLib (or SoundBlaster |
// emulating an AdLib) present |
// |
/////////////////////////////////////////////////////////////////////////// |
static boolean |
SDL_DetectAdLib(void) |
{ |
for (int i = 1; i <= 0xf5; i++) // Zero all the registers |
alOut(i, 0); |
alOut(1, 0x20); // Set WSE=1 |
// alOut(8, 0); // Set CSM=0 & SEL=0 |
return true; |
} |
//////////////////////////////////////////////////////////////////////////// |
// |
// SDL_ShutDevice() - turns off whatever device was being used for sound fx |
// |
//////////////////////////////////////////////////////////////////////////// |
static void |
SDL_ShutDevice(void) |
{ |
switch (SoundMode) |
{ |
case sdm_PC: |
// SDL_ShutPC(); |
break; |
case sdm_AdLib: |
SDL_ShutAL(); |
break; |
} |
SoundMode = sdm_Off; |
} |
/////////////////////////////////////////////////////////////////////////// |
// |
// SDL_CleanDevice() - totally shuts down all sound devices |
// |
/////////////////////////////////////////////////////////////////////////// |
static void |
SDL_CleanDevice(void) |
{ |
if ((SoundMode == sdm_AdLib) || (MusicMode == smm_AdLib)) |
SDL_CleanAL(); |
} |
/////////////////////////////////////////////////////////////////////////// |
// |
// SDL_StartDevice() - turns on whatever device is to be used for sound fx |
// |
/////////////////////////////////////////////////////////////////////////// |
static void |
SDL_StartDevice(void) |
{ |
switch (SoundMode) |
{ |
case sdm_AdLib: |
SDL_StartAL(); |
break; |
} |
SoundNumber = (soundnames) 0; |
SoundPriority = 0; |
} |
// Public routines |
/////////////////////////////////////////////////////////////////////////// |
// |
// SD_SetSoundMode() - Sets which sound hardware to use for sound effects |
// |
/////////////////////////////////////////////////////////////////////////// |
boolean |
SD_SetSoundMode(SDMode mode) |
{ |
boolean result = false; |
word tableoffset; |
SD_StopSound(); |
if ((mode == sdm_AdLib) && !AdLibPresent) |
mode = sdm_PC; |
switch (mode) |
{ |
case sdm_Off: |
tableoffset = STARTADLIBSOUNDS; |
result = true; |
break; |
case sdm_PC: |
tableoffset = STARTPCSOUNDS; |
result = true; |
break; |
case sdm_AdLib: |
tableoffset = STARTADLIBSOUNDS; |
if (AdLibPresent) |
result = true; |
break; |
default: |
Quit("SD_SetSoundMode: Invalid sound mode %i", mode); |
return false; |
} |
SoundTable = &audiosegs[tableoffset]; |
if (result && (mode != SoundMode)) |
{ |
SDL_ShutDevice(); |
SoundMode = mode; |
SDL_StartDevice(); |
} |
return(result); |
} |
/////////////////////////////////////////////////////////////////////////// |
// |
// SD_SetMusicMode() - sets the device to use for background music |
// |
/////////////////////////////////////////////////////////////////////////// |
boolean |
SD_SetMusicMode(SMMode mode) |
{ |
boolean result = false; |
SD_FadeOutMusic(); |
while (SD_MusicPlaying()) |
SDL_Delay(5); |
switch (mode) |
{ |
case smm_Off: |
result = true; |
break; |
case smm_AdLib: |
if (AdLibPresent) |
result = true; |
break; |
} |
if (result) |
MusicMode = mode; |
// SDL_SetTimerSpeed(); |
return(result); |
} |
int numreadysamples = 0; |
byte *curAlSound = 0; |
byte *curAlSoundPtr = 0; |
longword curAlLengthLeft = 0; |
int soundTimeCounter = 5; |
int samplesPerMusicTick; |
void SDL_IMFMusicPlayer(void *udata, Uint8 *stream, int len) |
{ |
int stereolen = len>>1; |
int sampleslen = stereolen>>1; |
INT16 *stream16 = (INT16 *) (void *) stream; // expect correct alignment |
while(1) |
{ |
if(numreadysamples) |
{ |
if(numreadysamples<sampleslen) |
{ |
YM3812UpdateOne(0, stream16, numreadysamples); |
stream16 += numreadysamples*2; |
sampleslen -= numreadysamples; |
} |
else |
{ |
YM3812UpdateOne(0, stream16, sampleslen); |
numreadysamples -= sampleslen; |
return; |
} |
} |
soundTimeCounter--; |
if(!soundTimeCounter) |
{ |
soundTimeCounter = 5; |
if(curAlSound != alSound) |
{ |
curAlSound = curAlSoundPtr = alSound; |
curAlLengthLeft = alLengthLeft; |
} |
if(curAlSound) |
{ |
if(*curAlSoundPtr) |
{ |
alOut(alFreqL, *curAlSoundPtr); |
alOut(alFreqH, alBlock); |
} |
else alOut(alFreqH, 0); |
curAlSoundPtr++; |
curAlLengthLeft--; |
if(!curAlLengthLeft) |
{ |
curAlSound = alSound = 0; |
SoundNumber = (soundnames) 0; |
SoundPriority = 0; |
alOut(alFreqH, 0); |
} |
} |
} |
if(sqActive) |
{ |
do |
{ |
if(sqHackTime > alTimeCount) break; |
sqHackTime = alTimeCount + *(sqHackPtr+1); |
alOut(*(byte *) sqHackPtr, *(((byte *) sqHackPtr)+1)); |
sqHackPtr += 2; |
sqHackLen -= 4; |
} |
while(sqHackLen>0); |
alTimeCount++; |
if(!sqHackLen) |
{ |
sqHackPtr = sqHack; |
sqHackLen = sqHackSeqLen; |
sqHackTime = 0; |
alTimeCount = 0; |
} |
} |
numreadysamples = samplesPerMusicTick; |
} |
} |
/////////////////////////////////////////////////////////////////////////// |
// |
// SD_Startup() - starts up the Sound Mgr |
// Detects all additional sound hardware and installs my ISR |
// |
/////////////////////////////////////////////////////////////////////////// |
void |
SD_Startup(void) |
{ |
int i; |
if (SD_Started) |
return; |
if(Mix_OpenAudio(param_samplerate, AUDIO_S16, 2, param_audiobuffer)) |
{ |
printf("Unable to open audio: %s\n", Mix_GetError()); |
return; |
} |
Mix_ReserveChannels(2); // reserve player and boss weapon channels |
Mix_GroupChannels(2, MIX_CHANNELS-1, 1); // group remaining channels |
// Init music |
samplesPerMusicTick = param_samplerate / 700; // SDL_t0FastAsmService played at 700Hz |
if(YM3812Init(1,3579545,param_samplerate)) |
{ |
printf("Unable to create virtual OPL!!\n"); |
} |
for(i=1;i<0xf6;i++) |
YM3812Write(0,i,0); |
YM3812Write(0,1,0x20); // Set WSE=1 |
// YM3812Write(0,8,0); // Set CSM=0 & SEL=0 // already set in for statement |
Mix_HookMusic(SDL_IMFMusicPlayer, 0); |
Mix_ChannelFinished(SD_ChannelFinished); |
AdLibPresent = true; |
SoundBlasterPresent = true; |
alTimeCount = 0; |
SD_SetSoundMode(sdm_Off); |
SD_SetMusicMode(smm_Off); |
SDL_SetupDigi(); |
SD_Started = true; |
} |
/////////////////////////////////////////////////////////////////////////// |
// |
// SD_Shutdown() - shuts down the Sound Mgr |
// Removes sound ISR and turns off whatever sound hardware was active |
// |
/////////////////////////////////////////////////////////////////////////// |
void |
SD_Shutdown(void) |
{ |
if (!SD_Started) |
return; |
SD_MusicOff(); |
SD_StopSound(); |
for(int i = 0; i < STARTMUSIC - STARTDIGISOUNDS; i++) |
{ |
if(SoundChunks[i]) Mix_FreeChunk(SoundChunks[i]); |
if(SoundBuffers[i]) free(SoundBuffers[i]); |
} |
free(DigiList); |
SD_Started = false; |
} |
/////////////////////////////////////////////////////////////////////////// |
// |
// SD_PositionSound() - Sets up a stereo imaging location for the next |
// sound to be played. Each channel ranges from 0 to 15. |
// |
/////////////////////////////////////////////////////////////////////////// |
void |
SD_PositionSound(int leftvol,int rightvol) |
{ |
LeftPosition = leftvol; |
RightPosition = rightvol; |
nextsoundpos = true; |
} |
/////////////////////////////////////////////////////////////////////////// |
// |
// SD_PlaySound() - plays the specified sound on the appropriate hardware |
// |
/////////////////////////////////////////////////////////////////////////// |
boolean |
SD_PlaySound(soundnames sound) |
{ |
boolean ispos; |
SoundCommon *s; |
int lp,rp; |
lp = LeftPosition; |
rp = RightPosition; |
LeftPosition = 0; |
RightPosition = 0; |
ispos = nextsoundpos; |
nextsoundpos = false; |
if (sound == -1 || (DigiMode == sds_Off && SoundMode == sdm_Off)) |
return 0; |
s = (SoundCommon *) SoundTable[sound]; |
if ((SoundMode != sdm_Off) && !s) |
Quit("SD_PlaySound() - Uncached sound"); |
if ((DigiMode != sds_Off) && (DigiMap[sound] != -1)) |
{ |
if ((DigiMode == sds_PC) && (SoundMode == sdm_PC)) |
{ |
#ifdef NOTYET |
if (s->priority < SoundPriority) |
return 0; |
SDL_PCStopSound(); |
SD_PlayDigitized(DigiMap[sound],lp,rp); |
SoundPositioned = ispos; |
SoundNumber = sound; |
SoundPriority = s->priority; |
#else |
return 0; |
#endif |
} |
else |
{ |
#ifdef NOTYET |
if (s->priority < DigiPriority) |
return(false); |
#endif |
int channel = SD_PlayDigitized(DigiMap[sound], lp, rp); |
SoundPositioned = ispos; |
DigiNumber = sound; |
DigiPriority = s->priority; |
return channel + 1; |
} |
return(true); |
} |
if (SoundMode == sdm_Off) |
return 0; |
if (!s->length) |
Quit("SD_PlaySound() - Zero length sound"); |
if (s->priority < SoundPriority) |
return 0; |
switch (SoundMode) |
{ |
case sdm_PC: |
// SDL_PCPlaySound((PCSound *)s); |
break; |
case sdm_AdLib: |
SDL_ALPlaySound((AdLibSound *)s); |
break; |
} |
SoundNumber = sound; |
SoundPriority = s->priority; |
return 0; |
} |
/////////////////////////////////////////////////////////////////////////// |
// |
// SD_SoundPlaying() - returns the sound number that's playing, or 0 if |
// no sound is playing |
// |
/////////////////////////////////////////////////////////////////////////// |
word |
SD_SoundPlaying(void) |
{ |
boolean result = false; |
switch (SoundMode) |
{ |
case sdm_PC: |
result = pcSound? true : false; |
break; |
case sdm_AdLib: |
result = alSound? true : false; |
break; |
} |
if (result) |
return(SoundNumber); |
else |
return(false); |
} |
/////////////////////////////////////////////////////////////////////////// |
// |
// SD_StopSound() - if a sound is playing, stops it |
// |
/////////////////////////////////////////////////////////////////////////// |
void |
SD_StopSound(void) |
{ |
if (DigiPlaying) |
SD_StopDigitized(); |
switch (SoundMode) |
{ |
case sdm_PC: |
// SDL_PCStopSound(); |
break; |
case sdm_AdLib: |
SDL_ALStopSound(); |
break; |
} |
SoundPositioned = false; |
SDL_SoundFinished(); |
} |
/////////////////////////////////////////////////////////////////////////// |
// |
// SD_WaitSoundDone() - waits until the current sound is done playing |
// |
/////////////////////////////////////////////////////////////////////////// |
void |
SD_WaitSoundDone(void) |
{ |
while (SD_SoundPlaying()) |
SDL_Delay(5); |
} |
/////////////////////////////////////////////////////////////////////////// |
// |
// SD_MusicOn() - turns on the sequencer |
// |
/////////////////////////////////////////////////////////////////////////// |
void |
SD_MusicOn(void) |
{ |
sqActive = true; |
} |
/////////////////////////////////////////////////////////////////////////// |
// |
// SD_MusicOff() - turns off the sequencer and any playing notes |
// returns the last music offset for music continue |
// |
/////////////////////////////////////////////////////////////////////////// |
int |
SD_MusicOff(void) |
{ |
word i; |
sqActive = false; |
switch (MusicMode) |
{ |
case smm_AdLib: |
alOut(alEffects, 0); |
for (i = 0;i < sqMaxTracks;i++) |
alOut(alFreqH + i + 1, 0); |
break; |
} |
return (int) (sqHackPtr-sqHack); |
} |
/////////////////////////////////////////////////////////////////////////// |
// |
// SD_StartMusic() - starts playing the music pointed to |
// |
/////////////////////////////////////////////////////////////////////////// |
void |
SD_StartMusic(int chunk) |
{ |
SD_MusicOff(); |
if (MusicMode == smm_AdLib) |
{ |
int32_t chunkLen = CA_CacheAudioChunk(chunk); |
sqHack = (word *)(void *) audiosegs[chunk]; // alignment is correct |
if(*sqHack == 0) sqHackLen = sqHackSeqLen = chunkLen; |
else sqHackLen = sqHackSeqLen = *sqHack++; |
sqHackPtr = sqHack; |
sqHackTime = 0; |
alTimeCount = 0; |
SD_MusicOn(); |
} |
} |
void |
SD_ContinueMusic(int chunk, int startoffs) |
{ |
SD_MusicOff(); |
if (MusicMode == smm_AdLib) |
{ |
int32_t chunkLen = CA_CacheAudioChunk(chunk); |
sqHack = (word *)(void *) audiosegs[chunk]; // alignment is correct |
if(*sqHack == 0) sqHackLen = sqHackSeqLen = chunkLen; |
else sqHackLen = sqHackSeqLen = *sqHack++; |
sqHackPtr = sqHack; |
if(startoffs >= sqHackLen) |
{ |
Quit("SD_StartMusic: Illegal startoffs provided!"); |
} |
// fast forward to correct position |
// (needed to reconstruct the instruments) |
for(int i = 0; i < startoffs; i += 2) |
{ |
byte reg = *(byte *)sqHackPtr; |
byte val = *(((byte *)sqHackPtr) + 1); |
if(reg >= 0xb1 && reg <= 0xb8) val &= 0xdf; // disable play note flag |
else if(reg == 0xbd) val &= 0xe0; // disable drum flags |
alOut(reg,val); |
sqHackPtr += 2; |
sqHackLen -= 4; |
} |
sqHackTime = 0; |
alTimeCount = 0; |
SD_MusicOn(); |
} |
} |
/////////////////////////////////////////////////////////////////////////// |
// |
// SD_FadeOutMusic() - starts fading out the music. Call SD_MusicPlaying() |
// to see if the fadeout is complete |
// |
/////////////////////////////////////////////////////////////////////////// |
void |
SD_FadeOutMusic(void) |
{ |
switch (MusicMode) |
{ |
case smm_AdLib: |
// DEBUG - quick hack to turn the music off |
SD_MusicOff(); |
break; |
} |
} |
/////////////////////////////////////////////////////////////////////////// |
// |
// SD_MusicPlaying() - returns true if music is currently playing, false if |
// not |
// |
/////////////////////////////////////////////////////////////////////////// |
boolean |
SD_MusicPlaying(void) |
{ |
boolean result; |
switch (MusicMode) |
{ |
case smm_AdLib: |
result = sqActive; |
break; |
default: |
result = false; |
break; |
} |
return(result); |
} |
/contrib/games/wolf3d/id_sd.h |
---|
8,7 → 8,7 |
#ifndef __ID_SD__ |
#define __ID_SD__ |
#define alOut(n,b) YM3812Write(oplChip, n, b) |
#define alOut(n,b) YM3812Write(0, n, b) |
#define TickBase 70 // 70Hz per tick - used as a base for timer 0 |
107,7 → 107,7 |
fixed globalsoundx, globalsoundy; |
} globalsoundpos; |
extern int channelSoundPos[]; |
extern globalsoundpos channelSoundPos[]; |
// Global variables |
extern boolean AdLibPresent, |
/contrib/games/wolf3d/wl_inter.cpp |
---|
2,7 → 2,7 |
#include "wl_def.h" |
#pragma hdrstop |
#define itoa ltoa |
LRstruct LevelRatios[LRpack]; |
int32_t lastBreathTime = 0; |
/contrib/games/wolf3d/wl_main.cpp |
---|
1210,11 → 1210,12 |
#if defined _WIN32 |
putenv("SDL_VIDEODRIVER=directx"); |
#endif |
if(SDL_Init(SDL_INIT_VIDEO /*| SDL_INIT_AUDIO | SDL_INIT_JOYSTICK*/) < 0) |
if(SDL_Init(SDL_INIT_VIDEO) < 0) |
{ |
printf("Unable to init SDL: %s\n", SDL_GetError()); |
exit(1); |
} |
SDL_AudioInit(NULL); |
atexit(SDL_Quit); |
int numJoysticks = SDL_NumJoysticks(); |
1232,7 → 1233,9 |
#endif |
SignonScreen (); |
#ifdef _KOLIBRI |
kolibri_set_win_center(); |
#endif |
#if defined _WIN32 |
if(!fullscreen) |
1886,6 → 1889,9 |
printf( |
"Wolf4SDL v1.7 ($Revision$)\n" |
"Ported by Chaos-Software (http://www.chaos-software.de.vu)\n" |
#ifdef _KOLIBRI |
"Ported for KolibriOS by 'turbocat2001' and 'maxcodehack'\n" |
#endif |
"Original Wolfenstein 3D by id Software\n\n" |
"Usage: Wolf4SDL [options]\n" |
"Options:\n" |
1896,8 → 1902,10 |
" --normal Sets the difficulty to normal for tedlevel\n" |
" --hard Sets the difficulty to hard for tedlevel\n" |
" --nowait Skips intro screens\n" |
#ifndef _KOLIBRI |
" --windowed[-mouse] Starts the game in a window [and grabs mouse]\n" |
" --res <width> <height> Sets the screen resolution\n" |
#endif |
" (must be multiple of 320x200 or 320x240)\n" |
" --resf <w> <h> Sets any screen resolution >= 320x200\n" |
" (which may result in graphic errors)\n" |
1907,9 → 1915,11 |
" --nodblbuf Don't use SDL's double buffering\n" |
" --extravbls <vbls> Sets a delay after each frame, which may help to\n" |
" reduce flickering (unit is currently 8 ms, default: 0)\n" |
#ifndef _KOLIBRI |
" --joystick <index> Use the index-th joystick if available\n" |
" (-1 to disable joystick, default: 0)\n" |
" --joystickhat <index> Enables movement with the given coolie hat\n" |
#endif |
" --samplerate <rate> Sets the sound sample rate (given in Hz, default: %i)\n" |
" --audiobuffer <size> Sets the size of the audio buffer (-> sound latency)\n" |
" (given in bytes, default: 2048 / (44100 / samplerate))\n" |