diff options
Diffstat (limited to 'games/eduke32/files/patch-source__jaudiolib__unixvoc.c')
-rw-r--r-- | games/eduke32/files/patch-source__jaudiolib__unixvoc.c | 2880 |
1 files changed, 0 insertions, 2880 deletions
diff --git a/games/eduke32/files/patch-source__jaudiolib__unixvoc.c b/games/eduke32/files/patch-source__jaudiolib__unixvoc.c deleted file mode 100644 index eb475a196596..000000000000 --- a/games/eduke32/files/patch-source__jaudiolib__unixvoc.c +++ /dev/null @@ -1,2880 +0,0 @@ ---- ./source/jaudiolib/unixvoc.c.orig Wed Aug 2 00:35:30 2006 -+++ ./source/jaudiolib/unixvoc.c Wed Aug 2 00:35:30 2006 -@@ -0,0 +1,2877 @@ -+/* -+Copyright (C) 1994-1995 Apogee Software, Ltd. -+ -+This program is free software; you can redistribute it and/or -+modify it under the terms of the GNU General Public License -+as published by the Free Software Foundation; either version 2 -+of the License, or (at your option) any later version. -+ -+This program 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 General Public License for more details. -+ -+ou should have received a copy of the GNU General Public License -+long with this program; if not, write to the Free Software -+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ -+*/ -+/********************************************************************** -+ module: MULTIVOC.C -+ -+ author: James R. Dose -+ date: December 20, 1993 -+ -+ Routines to provide multichannel digitized sound playback for -+ Sound Blaster compatible sound cards. -+ -+ (c) Copyright 1993 James R. Dose. All Rights Reserved. -+**********************************************************************/ -+ -+#include <stdio.h> -+#include <stdlib.h> -+#include <string.h> -+#include <time.h> -+ -+#include "util.h" -+#include "dpmi.h" -+#include "usrhooks.h" -+#include "interrup.h" -+#include "dma.h" -+#include "linklist.h" -+#include "dsl.h" -+ -+#include "pitch.h" -+#include "multivoc.h" -+#include "_multivc.h" -+#include "debugio.h" -+ -+// platform.h is from the build engine, but I need the byteswapping macros... --ryan. -+#include "platform.h" -+ -+#define RoundFixed( fixedval, bits ) \ -+ ( \ -+ ( \ -+ (fixedval) + ( 1 << ( (bits) - 1 ) )\ -+ ) >> (bits) \ -+ ) -+ -+#define IS_QUIET( ptr ) ( ( void * )( ptr ) == ( void * )&MV_VolumeTable[ 0 ] ) -+ -+static int MV_ReverbLevel; -+static int MV_ReverbDelay; -+static VOLUME16 *MV_ReverbTable = NULL; -+ -+//static signed short MV_VolumeTable[ MV_MaxVolume + 1 ][ 256 ]; -+static signed short MV_VolumeTable[ 63 + 1 ][ 256 ]; -+ -+//static Pan MV_PanTable[ MV_NumPanPositions ][ MV_MaxVolume + 1 ]; -+static Pan MV_PanTable[ MV_NumPanPositions ][ 63 + 1 ]; -+ -+static int MV_Installed = FALSE; -+static int MV_SoundCard = 1; -+static int MV_TotalVolume = MV_MaxTotalVolume; -+static int MV_MaxVoices = 1; -+static int MV_Recording; -+ -+static int MV_BufferSize = MixBufferSize; -+static int MV_BufferLength; -+ -+static int MV_NumberOfBuffers = NumberOfBuffers; -+ -+static int MV_MixMode = MONO_8BIT; -+static int MV_Channels = 1; -+static int MV_Bits = 8; -+ -+static int MV_Silence = SILENCE_8BIT; -+static int MV_SwapLeftRight = FALSE; -+ -+static int MV_RequestedMixRate; -+static int MV_MixRate; -+ -+static int MV_DMAChannel = -1; -+static int MV_BuffShift; -+ -+static int MV_TotalMemory; -+ -+static int MV_BufferDescriptor; -+static int MV_BufferEmpty[ NumberOfBuffers ]; -+char *MV_MixBuffer[ NumberOfBuffers + 1 ]; -+ -+static VoiceNode *MV_Voices = NULL; -+ -+static volatile VoiceNode VoiceList; -+static volatile VoiceNode VoicePool; -+ -+/*static*/ int MV_MixPage = 0; -+static int MV_VoiceHandle = MV_MinVoiceHandle; -+ -+static void ( *MV_CallBackFunc )( unsigned long ) = NULL; -+static void ( *MV_RecordFunc )( char *ptr, int length ) = NULL; -+static void ( *MV_MixFunction )( VoiceNode *voice, int buffer ); -+ -+static int MV_MaxVolume = 63; -+ -+char *MV_HarshClipTable; -+char *MV_MixDestination; -+short *MV_LeftVolume; -+short *MV_RightVolume; -+int MV_SampleSize = 1; -+int MV_RightChannelOffset; -+ -+unsigned long MV_MixPosition; -+ -+int MV_ErrorCode = MV_Ok; -+ -+#define MV_SetErrorCode( status ) \ -+ MV_ErrorCode = ( status ); -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_ErrorString -+ -+ Returns a pointer to the error message associated with an error -+ number. A -1 returns a pointer the current error. -+---------------------------------------------------------------------*/ -+ -+char *MV_ErrorString -+ ( -+ int ErrorNumber -+ ) -+ -+ { -+ char *ErrorString; -+ -+ switch( ErrorNumber ) -+ { -+ case MV_Warning : -+ case MV_Error : -+ ErrorString = MV_ErrorString( MV_ErrorCode ); -+ break; -+ -+ case MV_Ok : -+ ErrorString = "Multivoc ok."; -+ break; -+ -+ case MV_UnsupportedCard : -+ ErrorString = "Selected sound card is not supported by Multivoc."; -+ break; -+ -+ case MV_NotInstalled : -+ ErrorString = "Multivoc not installed."; -+ break; -+ -+ case MV_NoVoices : -+ ErrorString = "No free voices available to Multivoc."; -+ break; -+ -+ case MV_NoMem : -+ ErrorString = "Out of memory in Multivoc."; -+ break; -+ -+ case MV_VoiceNotFound : -+ ErrorString = "No voice with matching handle found."; -+ break; -+ -+ case MV_DPMI_Error : -+ ErrorString = "DPMI Error in Multivoc."; -+ break; -+ -+ case MV_InvalidVOCFile : -+ ErrorString = "Invalid VOC file passed in to Multivoc."; -+ break; -+ -+ case MV_InvalidWAVFile : -+ ErrorString = "Invalid WAV file passed in to Multivoc."; -+ break; -+ -+ case MV_InvalidMixMode : -+ ErrorString = "Invalid mix mode request in Multivoc."; -+ break; -+ -+ case MV_IrqFailure : -+ ErrorString = "Playback failed, possibly due to an invalid or conflicting IRQ."; -+ break; -+ -+ case MV_DMAFailure : -+ ErrorString = "Playback failed, possibly due to an invalid or conflicting DMA channel."; -+ break; -+ -+ case MV_DMA16Failure : -+ ErrorString = "Playback failed, possibly due to an invalid or conflicting DMA channel. \n" -+ "Make sure the 16-bit DMA channel is correct."; -+ break; -+ -+ case MV_NullRecordFunction : -+ ErrorString = "Null record function passed to MV_StartRecording."; -+ break; -+ -+ default : -+ ErrorString = "Unknown Multivoc error code."; -+ break; -+ } -+ -+ return( ErrorString ); -+ } -+ -+ -+/********************************************************************** -+ -+ Memory locked functions: -+ -+**********************************************************************/ -+ -+ -+#define MV_LockStart MV_Mix -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_Mix -+ -+ Mixes the sound into the buffer. -+---------------------------------------------------------------------*/ -+ -+static void MV_Mix -+ ( -+ VoiceNode *voice, -+ int buffer -+ ) -+ -+ { -+ char *start; -+ int length; -+ long voclength; -+ unsigned long position; -+ unsigned long rate; -+ unsigned long FixedPointBufferSize; -+ -+ if ( ( voice->length == 0 ) && -+ ( voice->GetSound != NULL ) && -+ ( voice->GetSound( voice ) != KeepPlaying ) ) -+ { -+ return; -+ } -+ -+ length = MixBufferSize; -+ FixedPointBufferSize = voice->FixedPointBufferSize; -+ -+ MV_MixDestination = MV_MixBuffer[ buffer ]; -+ MV_LeftVolume = voice->LeftVolume; -+ MV_RightVolume = voice->RightVolume; -+ -+ if ( ( MV_Channels == 2 ) && ( IS_QUIET( MV_LeftVolume ) ) ) -+ { -+ MV_LeftVolume = MV_RightVolume; -+ MV_MixDestination += MV_RightChannelOffset; -+ } -+ -+ // Add this voice to the mix -+ while( length > 0 ) -+ { -+ start = voice->sound; -+ rate = voice->RateScale; -+ position = voice->position; -+ -+ // Check if the last sample in this buffer would be -+ // beyond the length of the sample block -+ if ( ( position + FixedPointBufferSize ) >= voice->length ) -+ { -+ if ( position < voice->length ) -+ { -+ voclength = ( voice->length - position + rate - 1 ) / rate; -+ } -+ else -+ { -+ voice->GetSound( voice ); -+ return; -+ } -+ } -+ else -+ { -+ voclength = length; -+ } -+ -+ voice->mix( position, rate, start, voclength ); -+ -+ if ( voclength & 1 ) -+ { -+ MV_MixPosition += rate; -+ voclength -= 1; -+ } -+ voice->position = MV_MixPosition; -+ -+ length -= voclength; -+ -+ if ( voice->position >= voice->length ) -+ { -+ // Get the next block of sound -+ if ( voice->GetSound( voice ) != KeepPlaying ) -+ { -+ return; -+ } -+ -+ if ( length > 0 ) -+ { -+ // Get the position of the last sample in the buffer -+ FixedPointBufferSize = voice->RateScale * ( length - 1 ); -+ } -+ } -+ } -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_PlayVoice -+ -+ Adds a voice to the play list. -+---------------------------------------------------------------------*/ -+ -+void MV_PlayVoice -+ ( -+ VoiceNode *voice -+ ) -+ -+ { -+ unsigned flags; -+ -+ flags = DisableInterrupts(); -+ LL_SortedInsertion( &VoiceList, voice, prev, next, VoiceNode, priority ); -+ -+ RestoreInterrupts( flags ); -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_StopVoice -+ -+ Removes the voice from the play list and adds it to the free list. -+---------------------------------------------------------------------*/ -+ -+void MV_StopVoice -+ ( -+ VoiceNode *voice -+ ) -+ -+ { -+ unsigned flags; -+ -+ flags = DisableInterrupts(); -+ -+ // move the voice from the play list to the free list -+ LL_Remove( voice, next, prev ); -+ LL_Add( (VoiceNode *)&VoicePool, voice, next, prev ); -+ -+ RestoreInterrupts( flags ); -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_ServiceVoc -+ -+ Starts playback of the waiting buffer and mixes the next one. -+---------------------------------------------------------------------*/ -+ -+// static int backcolor = 1; -+ -+static int MV_ServiceVoc(int dummy_arg) -+ { -+ VoiceNode *voice; -+ VoiceNode *next; -+ char *buffer; -+ -+ // Toggle which buffer we'll mix next -+ MV_MixPage++; -+ if ( MV_MixPage >= MV_NumberOfBuffers ) -+ { -+ MV_MixPage -= MV_NumberOfBuffers; -+ } -+ -+ if ( MV_ReverbLevel == 0 ) -+ { -+ // Initialize buffer -+ //Commented out so that the buffer is always cleared. -+ //This is so the guys at Echo Speech can mix into the -+ //buffer even when no sounds are playing. -+ //if ( !MV_BufferEmpty[ MV_MixPage ] ) -+ { -+ ClearBuffer_DW( MV_MixBuffer[ MV_MixPage ], MV_Silence, MV_BufferSize >> 2 ); -+ MV_BufferEmpty[ MV_MixPage ] = TRUE; -+ } -+ } -+ else -+ { -+ char *end; -+ char *source; -+ char *dest; -+ int count; -+ int length; -+ -+ end = MV_MixBuffer[ 0 ] + MV_BufferLength;; -+ dest = MV_MixBuffer[ MV_MixPage ]; -+ source = MV_MixBuffer[ MV_MixPage ] - MV_ReverbDelay; -+ if ( source < MV_MixBuffer[ 0 ] ) -+ { -+ source += MV_BufferLength; -+ } -+ -+ length = MV_BufferSize; -+ while( length > 0 ) -+ { -+ count = length; -+ if ( source + count > end ) -+ { -+ count = end - source; -+ } -+ -+ if ( MV_Bits == 16 ) -+ { -+ if ( MV_ReverbTable != NULL ) -+ MV_16BitReverb( source, dest, (const VOLUME16 *)MV_ReverbTable, count / 2 ); -+ else -+ MV_16BitReverbFast( source, dest, count / 2, MV_ReverbLevel ); -+ } -+ else -+ { -+ if ( MV_ReverbTable != NULL ) -+ MV_8BitReverb( source, dest, (const VOLUME16 *)MV_ReverbTable, count ); -+ else -+ MV_8BitReverbFast( source, dest, count, MV_ReverbLevel ); -+ } -+ -+ // if we go through the loop again, it means that we've wrapped around the buffer -+ source = MV_MixBuffer[ 0 ]; -+ dest += count; -+ length -= count; -+ } -+ } -+ -+ // Play any waiting voices -+ for( voice = VoiceList.next; voice != &VoiceList; voice = next ) -+ { -+// if ( ( voice < &MV_Voices[ 0 ] ) || ( voice > &MV_Voices[ 8 ] ) ) -+// { -+// SetBorderColor(backcolor++); -+// break; -+// } -+ -+ MV_BufferEmpty[ MV_MixPage ] = FALSE; -+ -+ if (MV_MixFunction != NULL) -+ MV_MixFunction( voice, MV_MixPage ); -+ -+ next = voice->next; -+ -+ // Is this voice done? -+ if ( !voice->Playing ) -+ { -+ MV_StopVoice( voice ); -+ -+ if ( MV_CallBackFunc ) -+ { -+ MV_CallBackFunc( voice->callbackval ); -+ } -+ } -+ } -+ } -+ -+ -+int leftpage = -1; -+int rightpage = -1; -+ -+void MV_ServiceGus( char **ptr, unsigned long *length ) -+ { -+ if ( leftpage == MV_MixPage ) -+ { -+ MV_ServiceVoc(0); -+ } -+ -+ leftpage = MV_MixPage; -+ -+ *ptr = MV_MixBuffer[ MV_MixPage ]; -+ *length = MV_BufferSize; -+ } -+ -+void MV_ServiceRightGus( char **ptr, unsigned long *length ) -+ { -+ if ( rightpage == MV_MixPage ) -+ { -+ MV_ServiceVoc(0); -+ } -+ -+ rightpage = MV_MixPage; -+ -+ *ptr = MV_MixBuffer[ MV_MixPage ] + MV_RightChannelOffset; -+ *length = MV_BufferSize; -+ } -+ -+/*--------------------------------------------------------------------- -+ Function: MV_GetNextVOCBlock -+ -+ Interperate the information of a VOC format sound file. -+---------------------------------------------------------------------*/ -+static __inline unsigned int get_le32(void *p0) -+{ -+ //unsigned char *p = p0; -+ //return p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24); -+ unsigned int val = *((unsigned int *) p0); -+ return(BUILDSWAP_INTEL32(val)); -+} -+ -+static __inline unsigned int get_le16(void *p0) -+{ -+ //unsigned char *p = p0; -+ //return p[0] | (p[1]<<8); -+ unsigned short val = *((unsigned short *) p0); -+ return( (unsigned int) (BUILDSWAP_INTEL16(val)) ); -+} -+ -+playbackstatus MV_GetNextVOCBlock -+ ( -+ VoiceNode *voice -+ ) -+ -+ { -+ unsigned char *ptr; -+ int blocktype=0; -+ int lastblocktype=0; -+ unsigned long blocklength=0l; -+ unsigned long samplespeed=0l; -+ unsigned int tc=0; -+ int packtype=0; -+ int voicemode=0; -+ int done=0; -+ unsigned BitsPerSample; -+ unsigned Channels; -+ unsigned Format; -+ -+ if ( voice->BlockLength > 0 ) -+ { -+ voice->position -= voice->length; -+ voice->sound += voice->length >> 16; -+ if ( voice->bits == 16 ) -+ { -+ voice->sound += voice->length >> 16; -+ } -+ voice->length = min( voice->BlockLength, 0x8000 ); -+ voice->BlockLength -= voice->length; -+ voice->length <<= 16; -+ return( KeepPlaying ); -+ } -+ -+ if ( ( voice->length > 0 ) && ( voice->LoopEnd != NULL ) && -+ ( voice->LoopStart != NULL ) ) -+ { -+ voice->BlockLength = voice->LoopSize; -+ voice->sound = voice->LoopStart; -+ voice->position = 0; -+ voice->length = min( voice->BlockLength, 0x8000 ); -+ voice->BlockLength -= voice->length; -+ voice->length <<= 16; -+ return( KeepPlaying ); -+ } -+ -+ ptr = ( unsigned char * )voice->NextBlock; -+ -+ voice->Playing = TRUE; -+ -+ voicemode = 0; -+ lastblocktype = 0; -+ packtype = 0; -+ -+ done = FALSE; -+ while( !done ) -+ { -+ // Stop playing if we get a NULL pointer -+ if ( ptr == NULL ) -+ { -+ voice->Playing = FALSE; -+ done = TRUE; -+ break; -+ } -+ -+ { -+ unsigned tmp = get_le32(ptr); -+ blocktype = tmp&255; -+ blocklength = tmp>>8; -+ } -+ ptr += 4; -+ -+ switch( blocktype ) -+ { -+ case 0 : -+ // End of data -+ if ( ( voice->LoopStart == NULL ) || -+ ( (unsigned char *)voice->LoopStart >= ( ptr - 4 ) ) ) -+ { -+ voice->Playing = FALSE; -+ done = TRUE; -+ } -+ else -+ { -+ voice->BlockLength = ( ptr - 4 ) - (unsigned char *)voice->LoopStart; -+ voice->sound = voice->LoopStart; -+ voice->position = 0; -+ voice->length = min( voice->BlockLength, 0x8000 ); -+ voice->BlockLength -= voice->length; -+ voice->length <<= 16; -+ return( KeepPlaying ); -+ } -+ break; -+ -+ case 1 : -+ // Sound data block -+ voice->bits = 8; -+ if ( lastblocktype != 8 ) -+ { -+ tc = ( unsigned int )*ptr << 8; -+ packtype = *( ptr + 1 ); -+ } -+ -+ ptr += 2; -+ blocklength -= 2; -+ -+ samplespeed = 256000000L / ( 65536 - tc ); -+ -+ // Skip packed or stereo data -+ if ( ( packtype != 0 ) || ( voicemode != 0 ) ) -+ { -+ ptr += blocklength; -+ } -+ else -+ { -+ done = TRUE; -+ } -+ voicemode = 0; -+ break; -+ -+ case 2 : -+ // Sound continuation block -+ samplespeed = voice->SamplingRate; -+ done = TRUE; -+ break; -+ -+ case 3 : -+ // Silence -+ // Not implimented. -+ ptr += blocklength; -+ break; -+ -+ case 4 : -+ // Marker -+ // Not implimented. -+ ptr += blocklength; -+ break; -+ -+ case 5 : -+ // ASCII string -+ // Not implimented. -+ ptr += blocklength; -+ break; -+ -+ case 6 : -+ // Repeat begin -+ if ( voice->LoopEnd == NULL ) -+ { -+ voice->LoopCount = get_le16(ptr); -+ voice->LoopStart = ptr + blocklength; -+ } -+ ptr += blocklength; -+ break; -+ -+ case 7 : -+ // Repeat end -+ ptr += blocklength; -+ if ( lastblocktype == 6 ) -+ { -+ voice->LoopCount = 0; -+ } -+ else -+ { -+ if ( ( voice->LoopCount > 0 ) && ( voice->LoopStart != NULL ) ) -+ { -+ ptr = voice->LoopStart; -+ if ( voice->LoopCount < 0xffff ) -+ { -+ voice->LoopCount--; -+ if ( voice->LoopCount == 0 ) -+ { -+ voice->LoopStart = NULL; -+ } -+ } -+ } -+ } -+ break; -+ -+ case 8 : -+ // Extended block -+ voice->bits = 8; -+ tc = get_le16(ptr); -+ packtype = *( ptr + 2 ); -+ voicemode = *( ptr + 3 ); -+ ptr += blocklength; -+ break; -+ -+ case 9 : -+ // New sound data block -+ samplespeed = get_le32(ptr); -+ BitsPerSample = ptr[4]; -+ Channels = ptr[5]; -+ Format = get_le16(ptr+6); -+ -+ if ( ( BitsPerSample == 8 ) && ( Channels == 1 ) && -+ ( Format == VOC_8BIT ) ) -+ { -+ ptr += 12; -+ blocklength -= 12; -+ voice->bits = 8; -+ done = TRUE; -+ } -+ else if ( ( BitsPerSample == 16 ) && ( Channels == 1 ) && -+ ( Format == VOC_16BIT ) ) -+ { -+ ptr += 12; -+ blocklength -= 12; -+ voice->bits = 16; -+ done = TRUE; -+ } -+ else -+ { -+ ptr += blocklength; -+ } -+ break; -+ -+ default : -+ // Unknown data. Probably not a VOC file. -+ voice->Playing = FALSE; -+ done = TRUE; -+ break; -+ } -+ -+ lastblocktype = blocktype; -+ } -+ -+ if ( voice->Playing ) -+ { -+ voice->NextBlock = ptr + blocklength; -+ voice->sound = ptr; -+ -+ voice->SamplingRate = samplespeed; -+ voice->RateScale = ( voice->SamplingRate * voice->PitchScale ) / MV_MixRate; -+ -+ // Multiply by MixBufferSize - 1 -+ voice->FixedPointBufferSize = ( voice->RateScale * MixBufferSize ) - -+ voice->RateScale; -+ -+ if ( voice->LoopEnd != NULL ) -+ { -+ if ( blocklength > ( unsigned long )voice->LoopEnd ) -+ { -+ blocklength = ( unsigned long )voice->LoopEnd; -+ } -+ else -+ { -+ voice->LoopEnd = ( char * )blocklength; -+ } -+ -+ voice->LoopStart = voice->sound + ( unsigned long )voice->LoopStart; -+ voice->LoopEnd = voice->sound + ( unsigned long )voice->LoopEnd; -+ voice->LoopSize = voice->LoopEnd - voice->LoopStart; -+ } -+ -+ if ( voice->bits == 16 ) -+ { -+ blocklength /= 2; -+ } -+ -+ voice->position = 0; -+ voice->length = min( blocklength, 0x8000 ); -+ voice->BlockLength = blocklength - voice->length; -+ voice->length <<= 16; -+ -+ MV_SetVoiceMixMode( voice ); -+ -+ return( KeepPlaying ); -+ } -+ -+ return( NoMoreData ); -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_GetNextDemandFeedBlock -+ -+ Controls playback of demand fed data. -+---------------------------------------------------------------------*/ -+ -+playbackstatus MV_GetNextDemandFeedBlock -+ ( -+ VoiceNode *voice -+ ) -+ -+ { -+ if ( voice->BlockLength > 0 ) -+ { -+ voice->position -= voice->length; -+ voice->sound += voice->length >> 16; -+ voice->length = min( voice->BlockLength, 0x8000 ); -+ voice->BlockLength -= voice->length; -+ voice->length <<= 16; -+ -+ return( KeepPlaying ); -+ } -+ -+ if ( voice->DemandFeed == NULL ) -+ { -+ return( NoMoreData ); -+ } -+ -+ voice->position = 0; -+ ( voice->DemandFeed )( &voice->sound, &voice->BlockLength ); -+ voice->length = min( voice->BlockLength, 0x8000 ); -+ voice->BlockLength -= voice->length; -+ voice->length <<= 16; -+ -+ if ( ( voice->length > 0 ) && ( voice->sound != NULL ) ) -+ { -+ return( KeepPlaying ); -+ } -+ return( NoMoreData ); -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_GetNextRawBlock -+ -+ Controls playback of demand fed data. -+---------------------------------------------------------------------*/ -+ -+playbackstatus MV_GetNextRawBlock -+ ( -+ VoiceNode *voice -+ ) -+ -+ { -+ if ( voice->BlockLength <= 0 ) -+ { -+ if ( voice->LoopStart == NULL ) -+ { -+ voice->Playing = FALSE; -+ return( NoMoreData ); -+ } -+ -+ voice->BlockLength = voice->LoopSize; -+ voice->NextBlock = voice->LoopStart; -+ voice->length = 0; -+ voice->position = 0; -+ } -+ -+ voice->sound = voice->NextBlock; -+ voice->position -= voice->length; -+ voice->length = min( voice->BlockLength, 0x8000 ); -+ voice->NextBlock += voice->length; -+ if ( voice->bits == 16 ) -+ { -+ voice->NextBlock += voice->length; -+ } -+ voice->BlockLength -= voice->length; -+ voice->length <<= 16; -+ -+ return( KeepPlaying ); -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_GetNextWAVBlock -+ -+ Controls playback of demand fed data. -+---------------------------------------------------------------------*/ -+ -+playbackstatus MV_GetNextWAVBlock -+ ( -+ VoiceNode *voice -+ ) -+ -+ { -+ if ( voice->BlockLength <= 0 ) -+ { -+ if ( voice->LoopStart == NULL ) -+ { -+ voice->Playing = FALSE; -+ return( NoMoreData ); -+ } -+ -+ voice->BlockLength = voice->LoopSize; -+ voice->NextBlock = voice->LoopStart; -+ voice->length = 0; -+ voice->position = 0; -+ } -+ -+ voice->sound = voice->NextBlock; -+ voice->position -= voice->length; -+ voice->length = min( voice->BlockLength, 0x8000 ); -+ voice->NextBlock += voice->length; -+ if ( voice->bits == 16 ) -+ { -+ voice->NextBlock += voice->length; -+ } -+ voice->BlockLength -= voice->length; -+ voice->length <<= 16; -+ -+ return( KeepPlaying ); -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_ServiceRecord -+ -+ Starts recording of the waiting buffer. -+---------------------------------------------------------------------*/ -+ -+static void MV_ServiceRecord -+ ( -+ void -+ ) -+ -+ { -+ if ( MV_RecordFunc ) -+ { -+ MV_RecordFunc( MV_MixBuffer[ 0 ] + MV_MixPage * MixBufferSize, -+ MixBufferSize ); -+ } -+ -+ // Toggle which buffer we'll mix next -+ MV_MixPage++; -+ if ( MV_MixPage >= NumberOfBuffers ) -+ { -+ MV_MixPage = 0; -+ } -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_GetVoice -+ -+ Locates the voice with the specified handle. -+---------------------------------------------------------------------*/ -+ -+VoiceNode *MV_GetVoice -+ ( -+ int handle -+ ) -+ -+ { -+ VoiceNode *voice; -+ unsigned flags; -+ -+ flags = DisableInterrupts(); -+ -+ for( voice = VoiceList.next; voice != &VoiceList; voice = voice->next ) -+ { -+ if ( handle == voice->handle ) -+ { -+ break; -+ } -+ } -+ -+ RestoreInterrupts( flags ); -+ -+ if ( voice == &VoiceList ) -+ { -+ MV_SetErrorCode( MV_VoiceNotFound ); -+ -+ // SBF - should this return null? -+ return NULL; -+ } -+ -+ return( voice ); -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_VoicePlaying -+ -+ Checks if the voice associated with the specified handle is -+ playing. -+---------------------------------------------------------------------*/ -+ -+int MV_VoicePlaying -+ ( -+ int handle -+ ) -+ -+ { -+ VoiceNode *voice; -+ -+ if ( !MV_Installed ) -+ { -+ MV_SetErrorCode( MV_NotInstalled ); -+ return( FALSE ); -+ } -+ -+ voice = MV_GetVoice( handle ); -+ -+ if ( voice == NULL ) -+ { -+ return( FALSE ); -+ } -+ -+ return( TRUE ); -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_KillAllVoices -+ -+ Stops output of all currently active voices. -+---------------------------------------------------------------------*/ -+ -+int MV_KillAllVoices -+ ( -+ void -+ ) -+ -+ { -+ if ( !MV_Installed ) -+ { -+ MV_SetErrorCode( MV_NotInstalled ); -+ return( MV_Error ); -+ } -+ -+ // Remove all the voices from the list -+ while( VoiceList.next != &VoiceList ) -+ { -+ MV_Kill( VoiceList.next->handle ); -+ } -+ -+ return( MV_Ok ); -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_Kill -+ -+ Stops output of the voice associated with the specified handle. -+---------------------------------------------------------------------*/ -+ -+int MV_Kill -+ ( -+ int handle -+ ) -+ -+ { -+ VoiceNode *voice; -+ unsigned flags; -+ unsigned long callbackval; -+ -+ if ( !MV_Installed ) -+ { -+ MV_SetErrorCode( MV_NotInstalled ); -+ return( MV_Error ); -+ } -+ -+ flags = DisableInterrupts(); -+ -+ voice = MV_GetVoice( handle ); -+ if ( voice == NULL ) -+ { -+ RestoreInterrupts( flags ); -+ MV_SetErrorCode( MV_VoiceNotFound ); -+ return( MV_Error ); -+ } -+ -+ callbackval = voice->callbackval; -+ -+ MV_StopVoice( voice ); -+ -+ RestoreInterrupts( flags ); -+ -+ if ( MV_CallBackFunc ) -+ { -+ MV_CallBackFunc( callbackval ); -+ } -+ -+ return( MV_Ok ); -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_VoicesPlaying -+ -+ Determines the number of currently active voices. -+---------------------------------------------------------------------*/ -+ -+int MV_VoicesPlaying -+ ( -+ void -+ ) -+ -+ { -+ VoiceNode *voice; -+ int NumVoices = 0; -+ unsigned flags; -+ -+ if ( !MV_Installed ) -+ { -+ MV_SetErrorCode( MV_NotInstalled ); -+ return( 0 ); -+ } -+ -+ flags = DisableInterrupts(); -+ -+ for( voice = VoiceList.next; voice != &VoiceList; voice = voice->next ) -+ { -+ NumVoices++; -+ } -+ -+ RestoreInterrupts( flags ); -+ -+ return( NumVoices ); -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_AllocVoice -+ -+ Retrieve an inactive or lower priority voice for output. -+---------------------------------------------------------------------*/ -+ -+VoiceNode *MV_AllocVoice -+ ( -+ int priority -+ ) -+ -+ { -+ VoiceNode *voice; -+ VoiceNode *node; -+ unsigned flags; -+ -+//return( NULL ); -+ if ( MV_Recording ) -+ { -+ return( NULL ); -+ } -+ -+ flags = DisableInterrupts(); -+ -+ // Check if we have any free voices -+ if ( LL_Empty( &VoicePool, next, prev ) ) -+ { -+ // check if we have a higher priority than a voice that is playing. -+ voice = VoiceList.next; -+ for( node = voice->next; node != &VoiceList; node = node->next ) -+ { -+ if ( node->priority < voice->priority ) -+ { -+ voice = node; -+ } -+ } -+ -+ if ( priority >= voice->priority ) -+ { -+ MV_Kill( voice->handle ); -+ } -+ } -+ -+ // Check if any voices are in the voice pool -+ if ( LL_Empty( &VoicePool, next, prev ) ) -+ { -+ // No free voices -+ RestoreInterrupts( flags ); -+ return( NULL ); -+ } -+ -+ voice = VoicePool.next; -+ LL_Remove( voice, next, prev ); -+ RestoreInterrupts( flags ); -+ -+ // Find a free voice handle -+ do -+ { -+ MV_VoiceHandle++; -+ if ( MV_VoiceHandle < MV_MinVoiceHandle ) -+ { -+ MV_VoiceHandle = MV_MinVoiceHandle; -+ } -+ } -+ while( MV_VoicePlaying( MV_VoiceHandle ) ); -+ -+ voice->handle = MV_VoiceHandle; -+ -+ return( voice ); -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_VoiceAvailable -+ -+ Checks if a voice can be play at the specified priority. -+---------------------------------------------------------------------*/ -+ -+int MV_VoiceAvailable -+ ( -+ int priority -+ ) -+ -+ { -+ VoiceNode *voice; -+ VoiceNode *node; -+ unsigned flags; -+ -+ // Check if we have any free voices -+ if ( !LL_Empty( &VoicePool, next, prev ) ) -+ { -+ return( TRUE ); -+ } -+ -+ flags = DisableInterrupts(); -+ -+ // check if we have a higher priority than a voice that is playing. -+ voice = VoiceList.next; -+ for( node = VoiceList.next; node != &VoiceList; node = node->next ) -+ { -+ if ( node->priority < voice->priority ) -+ { -+ voice = node; -+ } -+ } -+ -+ RestoreInterrupts( flags ); -+ -+ if ( ( voice != &VoiceList ) && ( priority >= voice->priority ) ) -+ { -+ return( TRUE ); -+ } -+ -+ return( FALSE ); -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_SetVoicePitch -+ -+ Sets the pitch for the specified voice. -+---------------------------------------------------------------------*/ -+ -+void MV_SetVoicePitch -+ ( -+ VoiceNode *voice, -+ unsigned long rate, -+ int pitchoffset -+ ) -+ -+ { -+ voice->SamplingRate = rate; -+ voice->PitchScale = PITCH_GetScale( pitchoffset ); -+ voice->RateScale = ( rate * voice->PitchScale ) / MV_MixRate; -+ -+ // Multiply by MixBufferSize - 1 -+ voice->FixedPointBufferSize = ( voice->RateScale * MixBufferSize ) - -+ voice->RateScale; -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_SetPitch -+ -+ Sets the pitch for the voice associated with the specified handle. -+---------------------------------------------------------------------*/ -+ -+int MV_SetPitch -+ ( -+ int handle, -+ int pitchoffset -+ ) -+ -+ { -+ VoiceNode *voice; -+ -+ if ( !MV_Installed ) -+ { -+ MV_SetErrorCode( MV_NotInstalled ); -+ return( MV_Error ); -+ } -+ -+ voice = MV_GetVoice( handle ); -+ if ( voice == NULL ) -+ { -+ MV_SetErrorCode( MV_VoiceNotFound ); -+ return( MV_Error ); -+ } -+ -+ MV_SetVoicePitch( voice, voice->SamplingRate, pitchoffset ); -+ -+ return( MV_Ok ); -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_SetFrequency -+ -+ Sets the frequency for the voice associated with the specified handle. -+---------------------------------------------------------------------*/ -+ -+int MV_SetFrequency -+ ( -+ int handle, -+ int frequency -+ ) -+ -+ { -+ VoiceNode *voice; -+ -+ if ( !MV_Installed ) -+ { -+ MV_SetErrorCode( MV_NotInstalled ); -+ return( MV_Error ); -+ } -+ -+ voice = MV_GetVoice( handle ); -+ if ( voice == NULL ) -+ { -+ MV_SetErrorCode( MV_VoiceNotFound ); -+ return( MV_Error ); -+ } -+ -+ MV_SetVoicePitch( voice, frequency, 0 ); -+ -+ return( MV_Ok ); -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_GetVolumeTable -+ -+ Returns a pointer to the volume table associated with the specified -+ volume. -+---------------------------------------------------------------------*/ -+ -+static short *MV_GetVolumeTable -+ ( -+ int vol -+ ) -+ -+ { -+ int volume; -+ short *table; -+ -+ volume = MIX_VOLUME( vol ); -+ -+ table = (short *)&MV_VolumeTable[ volume ]; -+ -+ return( table ); -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_SetVoiceMixMode -+ -+ Selects which method should be used to mix the voice. -+---------------------------------------------------------------------*/ -+ -+static void MV_SetVoiceMixMode -+ ( -+ VoiceNode *voice -+ ) -+ -+ { -+ unsigned flags; -+ int test; -+ -+ flags = DisableInterrupts(); -+ -+ test = T_DEFAULT; -+ if ( MV_Bits == 8 ) -+ { -+ test |= T_8BITS; -+ } -+ -+ if ( voice->bits == 16 ) -+ { -+ test |= T_16BITSOURCE; -+ } -+ -+ if ( MV_Channels == 1 ) -+ { -+ test |= T_MONO; -+ } -+ else -+ { -+ if ( IS_QUIET( voice->RightVolume ) ) -+ { -+ test |= T_RIGHTQUIET; -+ } -+ else if ( IS_QUIET( voice->LeftVolume ) ) -+ { -+ test |= T_LEFTQUIET; -+ } -+ } -+ -+ // Default case -+ voice->mix = MV_Mix8BitMono; -+ -+ switch( test ) -+ { -+ case T_8BITS | T_MONO | T_16BITSOURCE : -+ voice->mix = MV_Mix8BitMono16; -+ break; -+ -+ case T_8BITS | T_MONO : -+ voice->mix = MV_Mix8BitMono; -+ break; -+ -+ case T_8BITS | T_16BITSOURCE | T_LEFTQUIET : -+ MV_LeftVolume = MV_RightVolume; -+ voice->mix = MV_Mix8BitMono16; -+ break; -+ -+ case T_8BITS | T_LEFTQUIET : -+ MV_LeftVolume = MV_RightVolume; -+ voice->mix = MV_Mix8BitMono; -+ break; -+ -+ case T_8BITS | T_16BITSOURCE | T_RIGHTQUIET : -+ voice->mix = MV_Mix8BitMono16; -+ break; -+ -+ case T_8BITS | T_RIGHTQUIET : -+ voice->mix = MV_Mix8BitMono; -+ break; -+ -+ case T_8BITS | T_16BITSOURCE : -+ voice->mix = MV_Mix8BitStereo16; -+ break; -+ -+ case T_8BITS : -+ voice->mix = MV_Mix8BitStereo; -+ break; -+ -+ case T_MONO | T_16BITSOURCE : -+ voice->mix = MV_Mix16BitMono16; -+ break; -+ -+ case T_MONO : -+ voice->mix = MV_Mix16BitMono; -+ break; -+ -+ case T_16BITSOURCE | T_LEFTQUIET : -+ MV_LeftVolume = MV_RightVolume; -+ voice->mix = MV_Mix16BitMono16; -+ break; -+ -+ case T_LEFTQUIET : -+ MV_LeftVolume = MV_RightVolume; -+ voice->mix = MV_Mix16BitMono; -+ break; -+ -+ case T_16BITSOURCE | T_RIGHTQUIET : -+ voice->mix = MV_Mix16BitMono16; -+ break; -+ -+ case T_RIGHTQUIET : -+ voice->mix = MV_Mix16BitMono; -+ break; -+ -+ case T_16BITSOURCE : -+ voice->mix = MV_Mix16BitStereo16; -+ break; -+ -+ case T_SIXTEENBIT_STEREO : -+ voice->mix = MV_Mix16BitStereo; -+ break; -+ -+ default : -+ voice->mix = MV_Mix8BitMono; -+ } -+ -+ RestoreInterrupts( flags ); -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_SetVoiceVolume -+ -+ Sets the stereo and mono volume level of the voice associated -+ with the specified handle. -+---------------------------------------------------------------------*/ -+ -+void MV_SetVoiceVolume -+ ( -+ VoiceNode *voice, -+ int vol, -+ int left, -+ int right -+ ) -+ -+ { -+ if ( MV_Channels == 1 ) -+ { -+ left = vol; -+ right = vol; -+ } -+ -+ if ( MV_SwapLeftRight ) -+ { -+ // SBPro uses reversed panning -+ voice->LeftVolume = MV_GetVolumeTable( right ); -+ voice->RightVolume = MV_GetVolumeTable( left ); -+ } -+ else -+ { -+ voice->LeftVolume = MV_GetVolumeTable( left ); -+ voice->RightVolume = MV_GetVolumeTable( right ); -+ } -+ -+ MV_SetVoiceMixMode( voice ); -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_EndLooping -+ -+ Stops the voice associated with the specified handle from looping -+ without stoping the sound. -+---------------------------------------------------------------------*/ -+ -+int MV_EndLooping -+ ( -+ int handle -+ ) -+ -+ { -+ VoiceNode *voice; -+ unsigned flags; -+ -+ if ( !MV_Installed ) -+ { -+ MV_SetErrorCode( MV_NotInstalled ); -+ return( MV_Error ); -+ } -+ -+ flags = DisableInterrupts(); -+ -+ voice = MV_GetVoice( handle ); -+ if ( voice == NULL ) -+ { -+ RestoreInterrupts( flags ); -+ MV_SetErrorCode( MV_VoiceNotFound ); -+ return( MV_Warning ); -+ } -+ -+ voice->LoopCount = 0; -+ voice->LoopStart = NULL; -+ voice->LoopEnd = NULL; -+ -+ RestoreInterrupts( flags ); -+ -+ return( MV_Ok ); -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_SetPan -+ -+ Sets the stereo and mono volume level of the voice associated -+ with the specified handle. -+---------------------------------------------------------------------*/ -+ -+int MV_SetPan -+ ( -+ int handle, -+ int vol, -+ int left, -+ int right -+ ) -+ -+ { -+ VoiceNode *voice; -+ -+ if ( !MV_Installed ) -+ { -+ MV_SetErrorCode( MV_NotInstalled ); -+ return( MV_Error ); -+ } -+ -+ voice = MV_GetVoice( handle ); -+ if ( voice == NULL ) -+ { -+ MV_SetErrorCode( MV_VoiceNotFound ); -+ return( MV_Warning ); -+ } -+ -+ MV_SetVoiceVolume( voice, vol, left, right ); -+ -+ return( MV_Ok ); -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_Pan3D -+ -+ Set the angle and distance from the listener of the voice associated -+ with the specified handle. -+---------------------------------------------------------------------*/ -+ -+int MV_Pan3D -+ ( -+ int handle, -+ int angle, -+ int distance -+ ) -+ -+ { -+ int left; -+ int right; -+ int mid; -+ int volume; -+ int status; -+ -+ if ( distance < 0 ) -+ { -+ distance = -distance; -+ angle += MV_NumPanPositions / 2; -+ } -+ -+ volume = MIX_VOLUME( distance ); -+ -+ // Ensure angle is within 0 - 31 -+ angle &= MV_MaxPanPosition; -+ -+ left = MV_PanTable[ angle ][ volume ].left; -+ right = MV_PanTable[ angle ][ volume ].right; -+ mid = max( 0, 255 - distance ); -+ -+ status = MV_SetPan( handle, mid, left, right ); -+ -+ return( status ); -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_SetReverb -+ -+ Sets the level of reverb to add to mix. -+---------------------------------------------------------------------*/ -+ -+void MV_SetReverb -+ ( -+ int reverb -+ ) -+ -+ { -+ MV_ReverbLevel = MIX_VOLUME( reverb ); -+ MV_ReverbTable = &MV_VolumeTable[ MV_ReverbLevel ]; -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_SetFastReverb -+ -+ Sets the level of reverb to add to mix. -+---------------------------------------------------------------------*/ -+ -+void MV_SetFastReverb -+ ( -+ int reverb -+ ) -+ -+ { -+ MV_ReverbLevel = max( 0, min( 16, reverb ) ); -+ MV_ReverbTable = NULL; -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_GetMaxReverbDelay -+ -+ Returns the maximum delay time for reverb. -+---------------------------------------------------------------------*/ -+ -+int MV_GetMaxReverbDelay -+ ( -+ void -+ ) -+ -+ { -+ int maxdelay; -+ -+ maxdelay = MixBufferSize * MV_NumberOfBuffers; -+ -+ return maxdelay; -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_GetReverbDelay -+ -+ Returns the current delay time for reverb. -+---------------------------------------------------------------------*/ -+ -+int MV_GetReverbDelay -+ ( -+ void -+ ) -+ -+ { -+ return MV_ReverbDelay / MV_SampleSize; -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_SetReverbDelay -+ -+ Sets the delay level of reverb to add to mix. -+---------------------------------------------------------------------*/ -+ -+void MV_SetReverbDelay -+ ( -+ int delay -+ ) -+ -+ { -+ int maxdelay; -+ -+ maxdelay = MV_GetMaxReverbDelay(); -+ MV_ReverbDelay = max( MixBufferSize, min( delay, maxdelay ) ); -+ MV_ReverbDelay *= MV_SampleSize; -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_SetMixMode -+ -+ Prepares Multivoc to play stereo of mono digitized sounds. -+---------------------------------------------------------------------*/ -+ -+int MV_SetMixMode -+ ( -+ int numchannels, -+ int samplebits -+ ) -+ -+ { -+ int mode; -+ -+ if ( !MV_Installed ) -+ { -+ MV_SetErrorCode( MV_NotInstalled ); -+ return( MV_Error ); -+ } -+ -+ mode = 0; -+ if ( numchannels == 2 ) -+ { -+ mode |= STEREO; -+ } -+ if ( samplebits == 16 ) -+ { -+ mode |= SIXTEEN_BIT; -+ } -+ -+ MV_MixMode = mode; -+ -+ MV_Channels = 1; -+ if ( MV_MixMode & STEREO ) -+ { -+ MV_Channels = 2; -+ } -+ -+ MV_Bits = 8; -+ if ( MV_MixMode & SIXTEEN_BIT ) -+ { -+ MV_Bits = 16; -+ } -+ -+ MV_BuffShift = 7 + MV_Channels; -+ MV_SampleSize = sizeof( MONO8 ) * MV_Channels; -+ -+ if ( MV_Bits == 8 ) -+ { -+ MV_Silence = SILENCE_8BIT; -+ } -+ else -+ { -+ MV_Silence = SILENCE_16BIT; -+ MV_BuffShift += 1; -+ MV_SampleSize *= 2; -+ } -+ -+ MV_BufferSize = MixBufferSize * MV_SampleSize; -+ MV_NumberOfBuffers = TotalBufferSize / MV_BufferSize; -+ MV_BufferLength = TotalBufferSize; -+ -+ MV_RightChannelOffset = MV_SampleSize / 2; -+ -+ return( MV_Ok ); -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_StartPlayback -+ -+ Starts the sound playback engine. -+---------------------------------------------------------------------*/ -+ -+int MV_StartPlayback -+ ( -+ void -+ ) -+ -+ { -+ int status; -+ int buffer; -+ -+ // Initialize the buffers -+ ClearBuffer_DW( MV_MixBuffer[ 0 ], MV_Silence, TotalBufferSize >> 2 ); -+ for( buffer = 0; buffer < MV_NumberOfBuffers; buffer++ ) -+ { -+ MV_BufferEmpty[ buffer ] = TRUE; -+ } -+ -+ // Set the mix buffer variables -+ MV_MixPage = 1; -+ -+ MV_MixFunction = MV_Mix; -+ -+ status = DSL_BeginBufferedPlayback( MV_MixBuffer[ 0 ], -+ TotalBufferSize, MV_NumberOfBuffers, -+ MV_RequestedMixRate, MV_MixMode, MV_ServiceVoc ); -+ -+ if ( status != DSL_Ok ) -+ { -+ MV_SetErrorCode( MV_BlasterError ); -+ return( MV_Error ); -+ } -+ -+ MV_MixRate = DSL_GetPlaybackRate(); -+ -+ return( MV_Ok ); -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_StopPlayback -+ -+ Stops the sound playback engine. -+---------------------------------------------------------------------*/ -+ -+void MV_StopPlayback -+ ( -+ void -+ ) -+ -+ { -+ VoiceNode *voice; -+ VoiceNode *next; -+ unsigned flags; -+ -+ DSL_StopPlayback(); -+ -+ // Make sure all callbacks are done. -+ flags = DisableInterrupts(); -+ -+ for( voice = VoiceList.next; voice != &VoiceList; voice = next ) -+ { -+ next = voice->next; -+ -+ MV_StopVoice( voice ); -+ -+ if ( MV_CallBackFunc ) -+ { -+ MV_CallBackFunc( voice->callbackval ); -+ } -+ } -+ -+ RestoreInterrupts( flags ); -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_StartRecording -+ -+ Starts the sound recording engine. -+---------------------------------------------------------------------*/ -+ -+int MV_StartRecording -+ ( -+ int MixRate, -+ void ( *function )( char *ptr, int length ) -+ ) -+ -+ { -+ MV_SetErrorCode( MV_UnsupportedCard ); -+ return( MV_Error ); -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_StopRecord -+ -+ Stops the sound record engine. -+---------------------------------------------------------------------*/ -+ -+void MV_StopRecord -+ ( -+ void -+ ) -+ -+ { -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_StartDemandFeedPlayback -+ -+ Plays a digitized sound from a user controlled buffering system. -+---------------------------------------------------------------------*/ -+ -+int MV_StartDemandFeedPlayback -+ ( -+ void ( *function )( char **ptr, unsigned long *length ), -+ int rate, -+ int pitchoffset, -+ int vol, -+ int left, -+ int right, -+ int priority, -+ unsigned long callbackval -+ ) -+ -+ { -+ VoiceNode *voice; -+ -+ if ( !MV_Installed ) -+ { -+ MV_SetErrorCode( MV_NotInstalled ); -+ return( MV_Error ); -+ } -+ -+ // Request a voice from the voice pool -+ voice = MV_AllocVoice( priority ); -+ if ( voice == NULL ) -+ { -+ MV_SetErrorCode( MV_NoVoices ); -+ return( MV_Error ); -+ } -+ -+ voice->wavetype = DemandFeed; -+ voice->bits = 8; -+ voice->GetSound = MV_GetNextDemandFeedBlock; -+ voice->NextBlock = NULL; -+ voice->DemandFeed = function; -+ voice->LoopStart = NULL; -+ voice->LoopCount = 0; -+ voice->BlockLength = 0; -+ voice->position = 0; -+ voice->sound = NULL; -+ voice->length = 0; -+ voice->BlockLength = 0; -+ voice->Playing = TRUE; -+ voice->next = NULL; -+ voice->prev = NULL; -+ voice->priority = priority; -+ voice->callbackval = callbackval; -+ -+ MV_SetVoicePitch( voice, rate, pitchoffset ); -+ MV_SetVoiceVolume( voice, vol, left, right ); -+ MV_PlayVoice( voice ); -+ -+ return( voice->handle ); -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_PlayRaw -+ -+ Begin playback of sound data with the given sound levels and -+ priority. -+---------------------------------------------------------------------*/ -+ -+int MV_PlayRaw -+ ( -+ char *ptr, -+ unsigned long length, -+ unsigned rate, -+ int pitchoffset, -+ int vol, -+ int left, -+ int right, -+ int priority, -+ unsigned long callbackval -+ ) -+ -+ { -+ int status; -+ -+ status = MV_PlayLoopedRaw( ptr, length, NULL, NULL, rate, pitchoffset, -+ vol, left, right, priority, callbackval ); -+ -+ return( status ); -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_PlayLoopedRaw -+ -+ Begin playback of sound data with the given sound levels and -+ priority. -+---------------------------------------------------------------------*/ -+ -+int MV_PlayLoopedRaw -+ ( -+ char *ptr, -+ long length, -+ char *loopstart, -+ char *loopend, -+ unsigned rate, -+ int pitchoffset, -+ int vol, -+ int left, -+ int right, -+ int priority, -+ unsigned long callbackval -+ ) -+ -+ { -+ VoiceNode *voice; -+ -+ if ( !MV_Installed ) -+ { -+ MV_SetErrorCode( MV_NotInstalled ); -+ return( MV_Error ); -+ } -+ -+ // Request a voice from the voice pool -+ voice = MV_AllocVoice( priority ); -+ if ( voice == NULL ) -+ { -+ MV_SetErrorCode( MV_NoVoices ); -+ return( MV_Error ); -+ } -+ -+ voice->wavetype = Raw; -+ voice->bits = 8; -+ voice->GetSound = MV_GetNextRawBlock; -+ voice->Playing = TRUE; -+ voice->NextBlock = ptr; -+ voice->position = 0; -+ voice->BlockLength = length; -+ voice->length = 0; -+ voice->next = NULL; -+ voice->prev = NULL; -+ voice->priority = priority; -+ voice->callbackval = callbackval; -+ voice->LoopStart = loopstart; -+ voice->LoopEnd = loopend; -+ voice->LoopSize = ( voice->LoopEnd - voice->LoopStart ) + 1; -+ -+ MV_SetVoicePitch( voice, rate, pitchoffset ); -+ MV_SetVoiceVolume( voice, vol, left, right ); -+ MV_PlayVoice( voice ); -+ -+ return( voice->handle ); -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_PlayWAV -+ -+ Begin playback of sound data with the given sound levels and -+ priority. -+---------------------------------------------------------------------*/ -+ -+int MV_PlayWAV -+ ( -+ char *ptr, -+ int pitchoffset, -+ int vol, -+ int left, -+ int right, -+ int priority, -+ unsigned long callbackval -+ ) -+ -+ { -+ int status; -+ -+ status = MV_PlayLoopedWAV( ptr, -1, -1, pitchoffset, vol, left, right, -+ priority, callbackval ); -+ -+ return( status ); -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_PlayWAV3D -+ -+ Begin playback of sound data at specified angle and distance -+ from listener. -+---------------------------------------------------------------------*/ -+ -+int MV_PlayWAV3D -+ ( -+ char *ptr, -+ int pitchoffset, -+ int angle, -+ int distance, -+ int priority, -+ unsigned long callbackval -+ ) -+ -+ { -+ int left; -+ int right; -+ int mid; -+ int volume; -+ int status; -+ -+ if ( !MV_Installed ) -+ { -+ MV_SetErrorCode( MV_NotInstalled ); -+ return( MV_Error ); -+ } -+ -+ if ( distance < 0 ) -+ { -+ distance = -distance; -+ angle += MV_NumPanPositions / 2; -+ } -+ -+ volume = MIX_VOLUME( distance ); -+ -+ // Ensure angle is within 0 - 31 -+ angle &= MV_MaxPanPosition; -+ -+ left = MV_PanTable[ angle ][ volume ].left; -+ right = MV_PanTable[ angle ][ volume ].right; -+ mid = max( 0, 255 - distance ); -+ -+ status = MV_PlayWAV( ptr, pitchoffset, mid, left, right, priority, -+ callbackval ); -+ -+ return( status ); -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_PlayLoopedWAV -+ -+ Begin playback of sound data with the given sound levels and -+ priority. -+---------------------------------------------------------------------*/ -+ -+int MV_PlayLoopedWAV -+ ( -+ char *ptr, -+ long loopstart, -+ long loopend, -+ int pitchoffset, -+ int vol, -+ int left, -+ int right, -+ int priority, -+ unsigned long callbackval -+ ) -+ -+ { -+ riff_header *riff; -+ format_header *format; -+ data_header *data; -+ VoiceNode *voice; -+ int length; -+ int absloopend; -+ int absloopstart; -+ -+ if ( !MV_Installed ) -+ { -+ MV_SetErrorCode( MV_NotInstalled ); -+ return( MV_Error ); -+ } -+ -+ riff = ( riff_header * )ptr; -+ -+ if ( ( strncmp( riff->RIFF, "RIFF", 4 ) != 0 ) || -+ ( strncmp( riff->WAVE, "WAVE", 4 ) != 0 ) || -+ ( strncmp( riff->fmt, "fmt ", 4) != 0 ) ) -+ { -+ MV_SetErrorCode( MV_InvalidWAVFile ); -+ return( MV_Error ); -+ } -+ -+ format = ( format_header * )( riff + 1 ); -+ data = ( data_header * )( ( ( char * )format ) + riff->format_size ); -+ -+ // Check if it's PCM data. -+ if ( format->wFormatTag != 1 ) -+ { -+ MV_SetErrorCode( MV_InvalidWAVFile ); -+ return( MV_Error ); -+ } -+ -+ if ( format->nChannels != 1 ) -+ { -+ MV_SetErrorCode( MV_InvalidWAVFile ); -+ return( MV_Error ); -+ } -+ -+ if ( ( format->nBitsPerSample != 8 ) && -+ ( format->nBitsPerSample != 16 ) ) -+ { -+ MV_SetErrorCode( MV_InvalidWAVFile ); -+ return( MV_Error ); -+ } -+ -+ if ( strncmp( data->DATA, "data", 4 ) != 0 ) -+ { -+ MV_SetErrorCode( MV_InvalidWAVFile ); -+ return( MV_Error ); -+ } -+ -+ // Request a voice from the voice pool -+ voice = MV_AllocVoice( priority ); -+ if ( voice == NULL ) -+ { -+ MV_SetErrorCode( MV_NoVoices ); -+ return( MV_Error ); -+ } -+ -+ voice->wavetype = WAV; -+ voice->bits = format->nBitsPerSample; -+ voice->GetSound = MV_GetNextWAVBlock; -+ -+ length = data->size; -+ absloopstart = loopstart; -+ absloopend = loopend; -+ if ( voice->bits == 16 ) -+ { -+ loopstart *= 2; -+ data->size &= ~1; -+ loopend *= 2; -+ length /= 2; -+ } -+ -+ loopend = min( loopend, (long)data->size ); -+ absloopend = min( absloopend, length ); -+ -+ voice->Playing = TRUE; -+ voice->DemandFeed = NULL; -+ voice->LoopStart = NULL; -+ voice->LoopCount = 0; -+ voice->position = 0; -+ voice->length = 0; -+ voice->BlockLength = absloopend; -+ voice->NextBlock = ( char * )( data + 1 ); -+ voice->next = NULL; -+ voice->prev = NULL; -+ voice->priority = priority; -+ voice->callbackval = callbackval; -+ voice->LoopStart = voice->NextBlock + loopstart; -+ voice->LoopEnd = voice->NextBlock + loopend; -+ voice->LoopSize = absloopend - absloopstart; -+ -+ if ( ( loopstart >= (long)data->size ) || ( loopstart < 0 ) ) -+ { -+ voice->LoopStart = NULL; -+ voice->LoopEnd = NULL; -+ voice->BlockLength = length; -+ } -+ -+ MV_SetVoicePitch( voice, format->nSamplesPerSec, pitchoffset ); -+ MV_SetVoiceVolume( voice, vol, left, right ); -+ MV_PlayVoice( voice ); -+ -+ return( voice->handle ); -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_PlayVOC3D -+ -+ Begin playback of sound data at specified angle and distance -+ from listener. -+---------------------------------------------------------------------*/ -+ -+int MV_PlayVOC3D -+ ( -+ char *ptr, -+ int pitchoffset, -+ int angle, -+ int distance, -+ int priority, -+ unsigned long callbackval -+ ) -+ -+ { -+ int left; -+ int right; -+ int mid; -+ int volume; -+ int status; -+ -+ if ( !MV_Installed ) -+ { -+ MV_SetErrorCode( MV_NotInstalled ); -+ return( MV_Error ); -+ } -+ -+ if ( distance < 0 ) -+ { -+ distance = -distance; -+ angle += MV_NumPanPositions / 2; -+ } -+ -+ volume = MIX_VOLUME( distance ); -+ -+ // Ensure angle is within 0 - 31 -+ angle &= MV_MaxPanPosition; -+ -+ left = MV_PanTable[ angle ][ volume ].left; -+ right = MV_PanTable[ angle ][ volume ].right; -+ mid = max( 0, 255 - distance ); -+ -+ status = MV_PlayVOC( ptr, pitchoffset, mid, left, right, priority, -+ callbackval ); -+ -+ return( status ); -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_PlayVOC -+ -+ Begin playback of sound data with the given sound levels and -+ priority. -+---------------------------------------------------------------------*/ -+ -+int MV_PlayVOC -+ ( -+ char *ptr, -+ int pitchoffset, -+ int vol, -+ int left, -+ int right, -+ int priority, -+ unsigned long callbackval -+ ) -+ -+ { -+ int status; -+ -+ status = MV_PlayLoopedVOC( ptr, -1, -1, pitchoffset, vol, left, right, -+ priority, callbackval ); -+ -+ return( status ); -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_PlayLoopedVOC -+ -+ Begin playback of sound data with the given sound levels and -+ priority. -+---------------------------------------------------------------------*/ -+ -+int MV_PlayLoopedVOC -+ ( -+ char *ptr, -+ long loopstart, -+ long loopend, -+ int pitchoffset, -+ int vol, -+ int left, -+ int right, -+ int priority, -+ unsigned long callbackval -+ ) -+ -+ { -+ VoiceNode *voice; -+ int status; -+ unsigned short nextpos; -+ -+ if ( !MV_Installed ) -+ { -+ MV_SetErrorCode( MV_NotInstalled ); -+ return( MV_Error ); -+ } -+ -+ // Make sure it's a valid VOC file. -+ status = strncmp( ptr, "Creative Voice File", 19 ); -+ if ( status != 0 ) -+ { -+ MV_SetErrorCode( MV_InvalidVOCFile ); -+ return( MV_Error ); -+ } -+ -+ // Request a voice from the voice pool -+ voice = MV_AllocVoice( priority ); -+ if ( voice == NULL ) -+ { -+ MV_SetErrorCode( MV_NoVoices ); -+ return( MV_Error ); -+ } -+ -+ voice->wavetype = VOC; -+ voice->bits = 8; -+ voice->GetSound = MV_GetNextVOCBlock; -+ -+ nextpos = *( unsigned short * )( ptr + 0x14 ); -+ voice->NextBlock = ptr + BUILDSWAP_INTEL16(nextpos); -+ -+ voice->DemandFeed = NULL; -+ voice->LoopStart = NULL; -+ voice->LoopCount = 0; -+ voice->BlockLength = 0; -+ voice->PitchScale = PITCH_GetScale( pitchoffset ); -+ voice->length = 0; -+ voice->next = NULL; -+ voice->prev = NULL; -+ voice->priority = priority; -+ voice->callbackval = callbackval; -+ voice->LoopStart = ( char * )loopstart; -+ voice->LoopEnd = ( char * )loopend; -+ voice->LoopSize = loopend - loopstart + 1; -+ -+ if ( loopstart < 0 ) -+ { -+ voice->LoopStart = NULL; -+ voice->LoopEnd = NULL; -+ } -+ -+ MV_SetVoiceVolume( voice, vol, left, right ); -+ MV_PlayVoice( voice ); -+ -+ return( voice->handle ); -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_LockEnd -+ -+ Used for determining the length of the functions to lock in memory. -+---------------------------------------------------------------------*/ -+ -+static void MV_LockEnd -+ ( -+ void -+ ) -+ -+ { -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_CreateVolumeTable -+ -+ Create the table used to convert sound data to a specific volume -+ level. -+---------------------------------------------------------------------*/ -+ -+void MV_CreateVolumeTable -+ ( -+ int index, -+ int volume, -+ int MaxVolume -+ ) -+ -+ { -+ int val; -+ int level; -+ int i; -+ -+ level = ( volume * MaxVolume ) / MV_MaxTotalVolume; -+ if ( MV_Bits == 16 ) -+ { -+ for( i = 0; i < 65536; i += 256 ) -+ { -+ val = i - 0x8000; -+ val *= level; -+ val /= MV_MaxVolume; -+ MV_VolumeTable[ index ][ i / 256 ] = val; -+ } -+ } -+ else -+ { -+ for( i = 0; i < 256; i++ ) -+ { -+ val = i - 0x80; -+ val *= level; -+ val /= MV_MaxVolume; -+ MV_VolumeTable[ volume ][ i ] = val; -+ } -+ } -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_CalcVolume -+ -+ Create the table used to convert sound data to a specific volume -+ level. -+---------------------------------------------------------------------*/ -+ -+void MV_CalcVolume -+ ( -+ int MaxVolume -+ ) -+ -+ { -+ int volume; -+ -+ for( volume = 0; volume < 128; volume++ ) -+ { -+ MV_HarshClipTable[ volume ] = 0; -+ MV_HarshClipTable[ volume + 384 ] = 255; -+ } -+ for( volume = 0; volume < 256; volume++ ) -+ { -+ MV_HarshClipTable[ volume + 128 ] = volume; -+ } -+ -+ // For each volume level, create a translation table with the -+ // appropriate volume calculated. -+ for( volume = 0; volume <= MV_MaxVolume; volume++ ) -+ { -+ MV_CreateVolumeTable( volume, volume, MaxVolume ); -+ } -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_CalcPanTable -+ -+ Create the table used to determine the stereo volume level of -+ a sound located at a specific angle and distance from the listener. -+---------------------------------------------------------------------*/ -+ -+void MV_CalcPanTable -+ ( -+ void -+ ) -+ -+ { -+ int level; -+ int angle; -+ int distance; -+ int HalfAngle; -+ int ramp; -+ -+ HalfAngle = ( MV_NumPanPositions / 2 ); -+ -+ for( distance = 0; distance <= MV_MaxVolume; distance++ ) -+ { -+ level = ( 255 * ( MV_MaxVolume - distance ) ) / MV_MaxVolume; -+ for( angle = 0; angle <= HalfAngle / 2; angle++ ) -+ { -+ ramp = level - ( ( level * angle ) / -+ ( MV_NumPanPositions / 4 ) ); -+ -+ MV_PanTable[ angle ][ distance ].left = ramp; -+ MV_PanTable[ HalfAngle - angle ][ distance ].left = ramp; -+ MV_PanTable[ HalfAngle + angle ][ distance ].left = level; -+ MV_PanTable[ MV_MaxPanPosition - angle ][ distance ].left = level; -+ -+ MV_PanTable[ angle ][ distance ].right = level; -+ MV_PanTable[ HalfAngle - angle ][ distance ].right = level; -+ MV_PanTable[ HalfAngle + angle ][ distance ].right = ramp; -+ MV_PanTable[ MV_MaxPanPosition - angle ][ distance ].right = ramp; -+ } -+ } -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_SetVolume -+ -+ Sets the volume of digitized sound playback. -+---------------------------------------------------------------------*/ -+ -+void MV_SetVolume -+ ( -+ int volume -+ ) -+ -+ { -+ volume = max( 0, volume ); -+ volume = min( volume, MV_MaxTotalVolume ); -+ -+ MV_TotalVolume = volume; -+ -+ // Calculate volume table -+ MV_CalcVolume( volume ); -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_GetVolume -+ -+ Returns the volume of digitized sound playback. -+---------------------------------------------------------------------*/ -+ -+int MV_GetVolume -+ ( -+ void -+ ) -+ -+ { -+ return( MV_TotalVolume ); -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_SetCallBack -+ -+ Set the function to call when a voice stops. -+---------------------------------------------------------------------*/ -+ -+void MV_SetCallBack -+ ( -+ void ( *function )( unsigned long ) -+ ) -+ -+ { -+ MV_CallBackFunc = function; -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_SetReverseStereo -+ -+ Set the orientation of the left and right channels. -+---------------------------------------------------------------------*/ -+ -+void MV_SetReverseStereo -+ ( -+ int setting -+ ) -+ -+ { -+ MV_SwapLeftRight = setting; -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_GetReverseStereo -+ -+ Returns the orientation of the left and right channels. -+---------------------------------------------------------------------*/ -+ -+int MV_GetReverseStereo -+ ( -+ void -+ ) -+ -+ { -+ return( MV_SwapLeftRight ); -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_TestPlayback -+ -+ Checks if playback has started. -+---------------------------------------------------------------------*/ -+ -+int MV_TestPlayback(void) -+ { -+ return MV_Ok; -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_Init -+ -+ Perform the initialization of variables and memory used by -+ Multivoc. -+---------------------------------------------------------------------*/ -+ -+int MV_Init -+ ( -+ int soundcard, -+ int MixRate, -+ int Voices, -+ int numchannels, -+ int samplebits -+ ) -+ -+ { -+ char *ptr; -+ int status; -+ int buffer; -+ int index; -+ -+ if ( MV_Installed ) -+ { -+ MV_Shutdown(); -+ } -+ -+ MV_SetErrorCode( MV_Ok ); -+ -+ MV_TotalMemory = Voices * sizeof( VoiceNode ) + sizeof( HARSH_CLIP_TABLE_8 ); -+ status = USRHOOKS_GetMem( ( void ** )&ptr, MV_TotalMemory ); -+ if ( status != USRHOOKS_Ok ) -+ { -+ MV_SetErrorCode( MV_NoMem ); -+ return( MV_Error ); -+ } -+ -+ MV_Voices = ( VoiceNode * )ptr; -+ MV_HarshClipTable = ptr + ( MV_TotalMemory - sizeof( HARSH_CLIP_TABLE_8 ) ); -+ -+ // Set number of voices before calculating volume table -+ MV_MaxVoices = Voices; -+ -+ LL_Reset( (VoiceNode *)&VoiceList, next, prev ); -+ LL_Reset( (VoiceNode *)&VoicePool, next, prev ); -+ -+ for( index = 0; index < Voices; index++ ) -+ { -+ LL_Add( (VoiceNode *)&VoicePool, &MV_Voices[ index ], next, prev ); -+ } -+ -+ // Allocate mix buffer within 1st megabyte -+ status = DPMI_GetDOSMemory( ( void ** )&ptr, &MV_BufferDescriptor, -+ 2 * TotalBufferSize ); -+ -+ if ( status ) -+ { -+ USRHOOKS_FreeMem( MV_Voices ); -+ MV_Voices = NULL; -+ MV_TotalMemory = 0; -+ -+ MV_SetErrorCode( MV_NoMem ); -+ return( MV_Error ); -+ } -+ -+ MV_SetReverseStereo( FALSE ); -+ -+ // Initialize the sound card -+ status = DSL_Init(); -+ if ( status != DSL_Ok ) -+ { -+ MV_SetErrorCode( MV_BlasterError ); -+ } -+ -+ if ( MV_ErrorCode != MV_Ok ) -+ { -+ status = MV_ErrorCode; -+ -+ USRHOOKS_FreeMem( MV_Voices ); -+ MV_Voices = NULL; -+ MV_TotalMemory = 0; -+ -+ DPMI_FreeDOSMemory( MV_BufferDescriptor ); -+ -+ MV_SetErrorCode( status ); -+ return( MV_Error ); -+ } -+ -+ MV_SoundCard = soundcard; -+ MV_Installed = TRUE; -+ MV_CallBackFunc = NULL; -+ MV_RecordFunc = NULL; -+ MV_Recording = FALSE; -+ MV_ReverbLevel = 0; -+ MV_ReverbTable = NULL; -+ -+ // Set the sampling rate -+ MV_RequestedMixRate = MixRate; -+ -+ // Set Mixer to play stereo digitized sound -+ MV_SetMixMode( numchannels, samplebits ); -+ MV_ReverbDelay = MV_BufferSize * 3; -+ -+ MV_MixBuffer[ MV_NumberOfBuffers ] = ptr; -+ for( buffer = 0; buffer < MV_NumberOfBuffers; buffer++ ) -+ { -+ MV_MixBuffer[ buffer ] = ptr; -+ ptr += MV_BufferSize; -+ } -+ -+ // Calculate pan table -+ MV_CalcPanTable(); -+ -+ MV_SetVolume( MV_MaxTotalVolume ); -+ -+ // Start the playback engine -+ status = MV_StartPlayback(); -+ if ( status != MV_Ok ) -+ { -+ // Preserve error code while we shutdown. -+ status = MV_ErrorCode; -+ MV_Shutdown(); -+ MV_SetErrorCode( status ); -+ return( MV_Error ); -+ } -+ -+ if ( MV_TestPlayback() != MV_Ok ) -+ { -+ status = MV_ErrorCode; -+ MV_Shutdown(); -+ MV_SetErrorCode( status ); -+ return( MV_Error ); -+ } -+ -+ return( MV_Ok ); -+ } -+ -+ -+/*--------------------------------------------------------------------- -+ Function: MV_Shutdown -+ -+ Restore any resources allocated by Multivoc back to the system. -+---------------------------------------------------------------------*/ -+ -+int MV_Shutdown -+ ( -+ void -+ ) -+ -+ { -+ int buffer; -+ unsigned flags; -+ -+ if ( !MV_Installed ) -+ { -+ return( MV_Ok ); -+ } -+ -+ flags = DisableInterrupts(); -+ -+ MV_KillAllVoices(); -+ -+ MV_Installed = FALSE; -+ -+ // Stop the sound recording engine -+ if ( MV_Recording ) -+ { -+ MV_StopRecord(); -+ } -+ -+ // Stop the sound playback engine -+ MV_StopPlayback(); -+ -+ // Shutdown the sound card -+ DSL_Shutdown(); -+ -+ RestoreInterrupts( flags ); -+ -+ // Free any voices we allocated -+ USRHOOKS_FreeMem( MV_Voices ); -+ MV_Voices = NULL; -+ MV_TotalMemory = 0; -+ -+ LL_Reset( (VoiceNode *)&VoiceList, next, prev ); -+ LL_Reset( (VoiceNode *)&VoicePool, next, prev ); -+ -+ MV_MaxVoices = 1; -+ -+ // Release the descriptor from our mix buffer -+ DPMI_FreeDOSMemory( MV_BufferDescriptor ); -+ for( buffer = 0; buffer < NumberOfBuffers; buffer++ ) -+ { -+ MV_MixBuffer[ buffer ] = NULL; -+ } -+ -+ return( MV_Ok ); -+ } |