123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133 |
- /*
- 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.
- You should have received a copy of the GNU General Public License
- along 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 <stdlib.h>
- #include "dpmi.h"
- #include "usrhooks.h"
- #include "interrup.h"
- #include "dpmi.h"
- #include "ll_man.h"
- #include "sndcards.h"
- #include "blaster.h"
- #include "sndsrc.h"
- #include "pas16.h"
- #include "pitch.h"
- #include "multivoc.h"
- #include "_multivc.h"
- static signed char MV_VolumeTable[ sizeof( VOLUME_TABLE_16BIT ) ];
- static VOLUME_TABLE_8BIT *MV_8BitVolumeTable = &MV_VolumeTable[ 0 ];
- static VOLUME_TABLE_16BIT *MV_16BitVolumeTable = &MV_VolumeTable[ 0 ];
- static Pan MV_PanTable[ MV_NumPanPositions ][ MV_MaxVolume + 1 ];
- static int MV_Installed = FALSE;
- static int MV_SoundCard = SoundBlaster;
- static int MV_TotalVolume = MV_MaxTotalVolume;
- static int MV_MaxVoices = 1;
- static int MV_BufferSize = MixBufferSize;
- static int MV_SampleSize = 1;
- static int MV_NumberOfBuffers = NumberOfBuffers;
- static int MV_MixMode = MONO_8BIT;
- static int MV_Silence = SILENCE_8BIT;
- static int MV_SwapLeftRight = FALSE;
- static int MV_RequestedMixRate;
- static int MV_MixRate;
- static int MV_BufferDescriptor;
- static char *MV_MixBuffer[ NumberOfBuffers ];
- static VoiceNode *MV_Voices = NULL;
- //static VoiceNode MV_Voices[ 16 ];
- static volatile VList VoiceList = { NULL, NULL };
- static volatile VList VoicePool = { NULL, NULL };
- static int MV_MixPage = 0;
- static int MV_PlayPage = 0;
- static int MV_VoiceHandle = MV_MinVoiceHandle;
- static void ( *MV_CallBackFunc )( unsigned long ) = NULL;
- //char HarshClipTable[ 8 * 256 ];
- //unsigned short HarshClipTable16[ 8 * 256 * 16 ];
- char *HarshClipTable;
- unsigned short *HarshClipTable16;
- short *HarshClipTable16s;
- 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_BlasterError :
- ErrorString = BLASTER_ErrorString( BLASTER_Error );
- break;
- case MV_PasError :
- ErrorString = PAS_ErrorString( PAS_Error );
- break;
- #ifndef SOUNDSOURCE_OFF
- case MV_SoundSourceError :
- ErrorString = SS_ErrorString( SS_Error );
- break;
- #endif
- case MV_DPMI_Error :
- ErrorString = "DPMI Error in Multivoc.";
- break;
- default :
- ErrorString = "Unknown Multivoc error code.";
- break;
- }
- return( ErrorString );
- }
- /**********************************************************************
- Memory locked functions:
- **********************************************************************/
- #define MV_LockStart MV_Mix8bitMono
- /*---------------------------------------------------------------------
- Function: MV_Mix8bitMono
- Mixes the sound into the buffer as an 8 bit mono sample.
- ---------------------------------------------------------------------*/
- void MV_Mix8bitMono
- (
- VoiceNode *voice,
- int buffer
- )
- {
- // MONO8 *to;
- char *to;
- VOLUME8 *VolumeTable;
- char *start;
- char *from;
- unsigned long position;
- int length;
- unsigned long rate;
- int samp;
- to = ( MONO8 * )MV_MixBuffer[ buffer ];
- VolumeTable = ( VOLUME8 * )&( *MV_8BitVolumeTable )[ voice->Volume ];
- start = voice->sound;
- rate = voice->RateScale;
- position = voice->position;
- length = MixBufferSize;
- // Add this voice to the mix
- while( length > 0 )
- {
- if ( position >= voice->length )
- {
- voice->position = position;
- MV_GetNextVOCBlock( voice );
- if ( voice->Playing )
- {
- start = voice->sound;
- rate = voice->RateScale;
- position = voice->position;
- }
- else
- {
- break;
- }
- }
- // from = start + ( position >> 16 );
- // *to += ( *VolumeTable )[ *from ];
- from = start + ( position >> 16 );
- samp = ( ( int )*to ) + ( *VolumeTable )[ *from ];
- *to = HarshClipTable[ 4 * 256 + samp - 0x80 ];
- to++;
- position += rate;
- length--;
- }
- voice->position = position;
- }
- /*---------------------------------------------------------------------
- Function: MV_Mix8bitStereo
- Mixes the sound into the buffer as an 8 bit stereo sample.
- ---------------------------------------------------------------------*/
- void MV_Mix8bitStereo
- (
- VoiceNode *voice,
- int buffer
- )
- {
- STEREO8 *to;
- VOLUME8 *LeftVolumeTable;
- VOLUME8 *RightVolumeTable;
- char *start;
- unsigned long position;
- int length;
- // int sample;
- unsigned long rate;
- char *from;
- int samp;
- to = ( STEREO8 * )MV_MixBuffer[ buffer ];
- LeftVolumeTable = ( VOLUME8 * )&( *MV_8BitVolumeTable )[ voice->LeftVolume ];
- RightVolumeTable = ( VOLUME8 * )&( *MV_8BitVolumeTable )[ voice->RightVolume ];
- start = voice->sound;
- rate = voice->RateScale;
- position = voice->position;
- length = MixBufferSize;
- // Add this voice to the mix
- while( length > 0 )
- {
- if ( position >= voice->length )
- {
- voice->position = position;
- MV_GetNextVOCBlock( voice );
- if ( voice->Playing )
- {
- start = voice->sound;
- rate = voice->RateScale;
- position = voice->position;
- }
- else
- {
- break;
- }
- }
- // sample = ( int )*( start + ( position >> 16 ) );
- // to->left += ( *LeftVolumeTable )[ sample ];
- // to->right += ( *RightVolumeTable )[ sample ];
- from = start + ( position >> 16 );
- samp = ( ( int )to->left ) + ( *LeftVolumeTable )[ *from ];
- to->left = HarshClipTable[ 4 * 256 + samp - 0x80 ];
- samp = ( ( int )to->right ) + ( *RightVolumeTable )[ *from ];
- to->right = HarshClipTable[ 4 * 256 + samp - 0x80 ];
- to++;
- position += rate;
- length--;
- }
- voice->position = position;
- }
- /*---------------------------------------------------------------------
- Function: MV_Mix16bitUnsignedMono
- Mixes the sound into the buffer as an 16 bit mono sample.
- ---------------------------------------------------------------------*/
- void MV_Mix16bitUnsignedMono
- (
- VoiceNode *voice,
- int buffer
- )
- {
- // MONO16 *to;
- unsigned short *to;
- VOLUME16 *VolumeTable;
- char *start;
- char *from;
- unsigned long position;
- int length;
- unsigned long rate;
- int samp;
- // to = ( MONO16 * )MV_MixBuffer[ buffer ];
- to = ( unsigned short * )MV_MixBuffer[ buffer ];
- VolumeTable = ( VOLUME16 * )&( *MV_16BitVolumeTable )[ voice->Volume ];
- start = voice->sound;
- rate = voice->RateScale;
- position = voice->position;
- length = MixBufferSize;
- // Add this voice to the mix
- while( length > 0 )
- {
- if ( position >= voice->length )
- {
- voice->position = position;
- MV_GetNextVOCBlock( voice );
- if ( voice->Playing )
- {
- start = voice->sound;
- rate = voice->RateScale;
- position = voice->position;
- }
- else
- {
- break;
- }
- }
- // from = start + ( position >> 16 );
- // *to += ( *VolumeTable )[ *from ];
- from = start + ( position >> 16 );
- samp = ( ( *to - 0x8000 ) >> 4 ) +
- ( *VolumeTable )[ *from ];
- *to = HarshClipTable16[ 4 * 256 * 16 + samp ];// << 4;
- to++;
- position += rate;
- length--;
- }
- voice->position = position;
- }
- /*---------------------------------------------------------------------
- Function: MV_Mix16bitUnsignedStereo
- Mixes the sound into the buffer as an 16 bit stereo sample.
- ---------------------------------------------------------------------*/
- void MV_Mix16bitUnsignedStereo
- (
- VoiceNode *voice,
- int buffer
- )
- {
- STEREO16 *to;
- VOLUME16 *LeftVolumeTable;
- VOLUME16 *RightVolumeTable;
- char *start;
- unsigned long position;
- int length;
- // int sample;
- unsigned long rate;
- char *from;
- int samp;
- to = ( STEREO16 * )MV_MixBuffer[ buffer ];
- LeftVolumeTable = ( VOLUME16 * )&( *MV_16BitVolumeTable )[ voice->LeftVolume ];
- RightVolumeTable = ( VOLUME16 * )&( *MV_16BitVolumeTable )[ voice->RightVolume ];
- start = voice->sound;
- rate = voice->RateScale;
- position = voice->position;
- length = MixBufferSize;
- // Add this voice to the mix
- while( length > 0 )
- {
- if ( position >= voice->length )
- {
- voice->position = position;
- MV_GetNextVOCBlock( voice );
- if ( voice->Playing )
- {
- start = voice->sound;
- rate = voice->RateScale;
- position = voice->position;
- }
- else
- {
- break;
- }
- }
- // sample = ( int )*( start + ( position >> 16 ) );
- // to->left += ( *LeftVolumeTable )[ sample ];
- // to->right += ( *RightVolumeTable )[ sample ];
- from = start + ( position >> 16 );
- samp = ( ( to->left - 0x8000 ) >> 4 ) +
- ( *LeftVolumeTable )[ *from ];
- to->left = HarshClipTable16[ 4 * 256 * 16 + samp ];// << 4;
- // to->left = ( length & 127 ) << 8;
- samp = ( ( to->right - 0x8000 ) >> 4 ) +
- ( *RightVolumeTable )[ *from ];
- to->right = HarshClipTable16[ 4 * 256 * 16 + samp ];// << 4;
- // to->right = ( length & 127 ) << 8;
- to++;
- position += rate;
- length--;
- }
- voice->position = position;
- }
- /*---------------------------------------------------------------------
- Function: MV_PrepareBuffer
- Initializes the current buffer and mixes the currently active
- voices.
- ---------------------------------------------------------------------*/
- void MV_PrepareBuffer
- (
- int page
- )
- {
- VoiceNode *voice;
- // Initialize buffer
- ClearBuffer_DW( MV_MixBuffer[ page ], MV_Silence, MV_BufferSize >> 2 );
- voice = VoiceList.start;
- while( voice != NULL )
- {
- switch( MV_MixMode )
- {
- case MONO_8BIT :
- MV_Mix8bitMono( voice, page );
- break;
- case STEREO_8BIT :
- MV_Mix8bitStereo( voice, page );
- break;
- case MONO_16BIT :
- MV_Mix16bitUnsignedMono( voice, page );
- break;
- case STEREO_16BIT :
- MV_Mix16bitUnsignedStereo( voice, page );
- break;
- }
- if ( voice->Playing )
- {
- voice->Active[ page ] = TRUE;
- }
- else
- {
- voice->Active[ page ] = FALSE;
- }
- voice = voice->next;
- }
- }
- /*---------------------------------------------------------------------
- Function: MV_DeleteDeadVoices
- Removes any voices that have finished playing.
- ---------------------------------------------------------------------*/
- void MV_DeleteDeadVoices
- (
- int page
- )
- {
- VoiceNode *voice;
- VoiceNode *next;
- unsigned flags;
- flags = DisableInterrupts();
- voice = VoiceList.start;
- while( voice != NULL )
- {
- next = voice->next;
- // Is this voice done?
- if ( !voice->Active[ page ] )
- {
- // Yes, move it from the play list into the free list
- LL_Remove( VoiceNode, &VoiceList, voice );
- LL_AddToTail( VoiceNode, &VoicePool, voice );
- if ( MV_CallBackFunc )
- {
- MV_CallBackFunc( voice->callbackval );
- }
- }
- voice = next;
- }
- RestoreInterrupts( flags );
- }
- /*---------------------------------------------------------------------
- Function: MV_ServiceVoc
- Starts playback of the waiting buffer and mixes the next one.
- ---------------------------------------------------------------------*/
- void MV_ServiceVoc
- (
- void
- )
- {
- int ErasePage;
- ErasePage = MV_PlayPage;
- // Delete any voices that are done playing
- MV_DeleteDeadVoices( ErasePage );
- // Set which buffer is currently being played.
- MV_PlayPage = MV_MixPage;
- // Toggle which buffer we'll mix next
- MV_MixPage++;
- if ( MV_MixPage >= MV_NumberOfBuffers )
- {
- MV_MixPage = 0;
- }
- // Play any waiting voices
- MV_PrepareBuffer( MV_MixPage );
- }
- /*---------------------------------------------------------------------
- Function: MV_GetVoice
- Locates the voice with the specified handle.
- ---------------------------------------------------------------------*/
- VoiceNode *MV_GetVoice
- (
- int handle
- )
- {
- VoiceNode *voice;
- unsigned flags;
- flags = DisableInterrupts();
- voice = VoiceList.start;
- while( voice != NULL )
- {
- if ( handle == voice->handle )
- {
- break;
- }
- voice = voice->next;
- }
- RestoreInterrupts( flags );
- if ( voice == NULL )
- {
- MV_SetErrorCode( MV_VoiceNotFound );
- }
- 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.start != NULL )
- {
- MV_Kill( VoiceList.start->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;
- // move the voice from the play list to the free list
- LL_Remove( VoiceNode, &VoiceList, voice );
- LL_AddToTail( VoiceNode, &VoicePool, voice );
- RestoreInterrupts( flags );
- if ( MV_CallBackFunc )
- {
- MV_CallBackFunc( callbackval );
- }
- MV_SetErrorCode( MV_Ok );
- 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();
- voice = VoiceList.start;
- while( voice != NULL )
- {
- NumVoices++;
- voice = voice->next;
- }
- 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;
- flags = DisableInterrupts();
- // Check if we have any free voices
- if ( VoicePool.start == NULL )
- {
- // check if we have a higher priority than a voice that is playing.
- node = VoiceList.start;
- voice = node;
- while( node != NULL )
- {
- if ( node->priority < voice->priority )
- {
- voice = node;
- }
- node = node->next;
- }
- if ( priority >= voice->priority )
- {
- MV_Kill( voice->handle );
- }
- }
- // Check if any voices are in the voice pool
- if ( VoicePool.start == NULL )
- {
- // No free voices
- RestoreInterrupts( flags );
- return( NULL );
- }
- voice = VoicePool.start;
- LL_Remove( VoiceNode, &VoicePool, voice );
- 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_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 );
- }
- voice->PitchScale = PITCH_GetScale( pitchoffset );
- voice->RateScale = ( voice->SamplingRate *
- voice->PitchScale ) / MV_MixRate;
- MV_SetErrorCode( MV_Ok );
- 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 );
- }
- voice->Volume = MIX_VOLUME( vol );
- if ( MV_SwapLeftRight )
- {
- // SBPro uses reversed panning
- voice->LeftVolume = MIX_VOLUME( right );
- voice->RightVolume = MIX_VOLUME( left );
- }
- else
- {
- voice->LeftVolume = MIX_VOLUME( left );
- voice->RightVolume = MIX_VOLUME( right );
- }
- MV_SetErrorCode( MV_Ok );
- 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_SetMixMode
- Prepares Multivoc to play stereo of mono digitized sounds.
- ---------------------------------------------------------------------*/
- int MV_SetMixMode
- (
- int mode
- )
- {
- if ( !MV_Installed )
- {
- MV_SetErrorCode( MV_NotInstalled );
- return( MV_Error );
- }
- switch( MV_SoundCard )
- {
- case SoundBlaster :
- case Awe32 :
- MV_MixMode = BLASTER_SetMixMode( mode );
- break;
- case ProAudioSpectrum :
- case SoundMan16 :
- MV_MixMode = PAS_SetMixMode( mode );
- break;
- #ifndef SOUNDSOURCE_OFF
- case SoundSource :
- case TandySoundSource :
- MV_MixMode = SS_SetMixMode( mode );
- break;
- #endif
- }
- MV_SampleSize = sizeof( MONO8 );
- MV_Silence = SILENCE_8BIT;
- switch( MV_MixMode )
- {
- case MONO_8BIT :
- MV_SampleSize = sizeof( MONO8 );
- MV_Silence = SILENCE_8BIT;
- break;
- case STEREO_8BIT :
- MV_SampleSize = sizeof( STEREO8 );
- MV_Silence = SILENCE_8BIT;
- break;
- case MONO_16BIT :
- MV_SampleSize = sizeof( MONO16 );
- // if ( ( MV_SoundCard == ProAudioSpectrum ) ||
- // ( MV_SoundCard == SoundMan16 ) )
- // {
- // MV_Silence = SILENCE_16BIT_PAS;
- // }
- // else
- // {
- MV_Silence = SILENCE_16BIT;
- // }
- break;
- case STEREO_16BIT :
- MV_SampleSize = sizeof( STEREO16 );
- // if ( ( MV_SoundCard == ProAudioSpectrum ) ||
- // ( MV_SoundCard == SoundMan16 ) )
- // {
- // MV_Silence = SILENCE_16BIT_PAS;
- // }
- // else
- // {
- MV_Silence = SILENCE_16BIT;
- // }
- break;
- }
- MV_BufferSize = MixBufferSize * MV_SampleSize;
- MV_NumberOfBuffers = TotalBufferSize / MV_BufferSize;
- return( MV_Ok );
- }
- /*---------------------------------------------------------------------
- Function: MV_StartPlayback
- Starts the sound playback engine.
- ---------------------------------------------------------------------*/
- int MV_StartPlayback
- (
- void
- )
- {
- int status;
- // Initialize the buffers
- ClearBuffer_DW( MV_MixBuffer[ 0 ], MV_Silence, TotalBufferSize >> 2 );
- // Set the mix buffer variables
- MV_PlayPage = 0;
- MV_MixPage = 1;
- // Start playback
- switch( MV_SoundCard )
- {
- case SoundBlaster :
- case Awe32 :
- status = BLASTER_BeginBufferedPlayback( MV_MixBuffer[ 0 ],
- TotalBufferSize, MV_NumberOfBuffers,
- MV_RequestedMixRate, MV_MixMode, MV_ServiceVoc );
- if ( status != BLASTER_Ok )
- {
- MV_SetErrorCode( MV_BlasterError );
- return( MV_Error );
- }
- MV_MixRate = BLASTER_GetPlaybackRate();
- break;
- case ProAudioSpectrum :
- case SoundMan16 :
- status = PAS_BeginBufferedPlayback( MV_MixBuffer[ 0 ],
- TotalBufferSize, MV_NumberOfBuffers,
- MV_RequestedMixRate, MV_MixMode, MV_ServiceVoc );
- if ( status != PAS_Ok )
- {
- MV_SetErrorCode( MV_PasError );
- return( MV_Error );
- }
- MV_MixRate = PAS_GetPlaybackRate();
- break;
- #ifndef SOUNDSOURCE_OFF
- case SoundSource :
- case TandySoundSource :
- SS_BeginBufferedPlayback( MV_MixBuffer[ 0 ],
- TotalBufferSize, MV_NumberOfBuffers,
- MV_ServiceVoc );
- MV_MixRate = SS_SampleRate;
- break;
- #endif
- }
- return( MV_Ok );
- }
- /*---------------------------------------------------------------------
- Function: MV_StopPlayback
- Stops the sound playback engine.
- ---------------------------------------------------------------------*/
- void MV_StopPlayback
- (
- void
- )
- {
- // Stop sound playback
- switch( MV_SoundCard )
- {
- case SoundBlaster :
- case Awe32 :
- BLASTER_StopPlayback();
- break;
- case ProAudioSpectrum :
- case SoundMan16 :
- PAS_StopPlayback();
- break;
- #ifndef SOUNDSOURCE_OFF
- case SoundSource :
- case TandySoundSource :
- SS_StopPlayback();
- break;
- #endif
- }
- }
- /*---------------------------------------------------------------------
- Function: MV_StartRecording
- Starts the sound recording engine.
- ---------------------------------------------------------------------*/
- int MV_StartRecording
- (
- int MixRate,
- void ( *function )( char *ptr, int length )
- )
- {
- return( MV_Ok );
- }
- /*---------------------------------------------------------------------
- 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
- (
- int MixRate,
- int vol,
- int left,
- int right,
- void ( *function )( char **ptr, unsigned long *length )
- )
- {
- return( MV_Ok );
- }
- /*---------------------------------------------------------------------
- Function: MV_GetNextVOCBlock
- Interperate the information of a VOC format sound file.
- ---------------------------------------------------------------------*/
- void MV_GetNextVOCBlock
- (
- VoiceNode *voice
- )
- {
- unsigned char *ptr;
- int blocktype;
- int lastblocktype;
- unsigned long blocklength;
- unsigned long samplespeed;
- unsigned int tc;
- int packtype;
- int voicemode;
- int done;
- unsigned BitsPerSample;
- unsigned Channels;
- unsigned Format;
- if ( voice->BlockLength > 0 )
- {
- voice->sound += 0x8000;
- voice->position -= 0x80000000;
- voice->length = min( voice->BlockLength, 0x8000 );
- voice->BlockLength -= voice->length;
- voice->length <<= 16;
- return;
- }
- ptr = ( unsigned char * )voice->NextBlock;
- voice->Playing = TRUE;
- done = FALSE;
- while( !done )
- {
- blocktype = ( int )*ptr;
- blocklength = ( *( unsigned long * )( ptr + 1 ) ) & 0x00ffffff;
- ptr += 4;
- voicemode = 0;
- lastblocktype = 0;
- switch( blocktype )
- {
- case 0 :
- // End of data
- voice->Playing = FALSE;
- done = TRUE;
- break;
- case 1 :
- // Sound data block
- if ( lastblocktype != 8 )
- {
- tc = ( unsigned int )*ptr;
- packtype = *( ptr + 1 );
- }
- ptr += 2;
- blocklength -= 2;
- samplespeed = 256000000L / ( 65536 - ( tc << 8 ) );
- // Skip packed or stereo data
- if ( ( packtype != 0 ) || ( voicemode != 0 ) )
- {
- ptr += blocklength;
- }
- else
- {
- done = TRUE;
- }
- 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
- voice->LoopCount = *( unsigned short * )ptr;
- ptr += blocklength;
- voice->LoopStart = ptr;
- 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
- tc = *( unsigned short * )ptr;
- packtype = *( ptr + 2 );
- voicemode = *( ptr + 3 );
- ptr += blocklength;
- break;
- case 9 :
- // New sound data block
- samplespeed = *( unsigned long * )ptr;
- BitsPerSample = ( unsigned )*( ptr + 4 );
- Channels = ( unsigned )*( ptr + 5 );
- Format = ( unsigned )*( unsigned short * )( ptr + 6 );
- if ( ( BitsPerSample == 8 ) && ( Channels == 1 ) &&
- ( Format == 0 ) )
- {
- ptr += 12;
- 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;
- voice->position = 0;
- voice->length = min( blocklength, 0x8000 );
- voice->BlockLength = blocklength - voice->length;
- voice->length <<= 16;
- }
- }
- /*---------------------------------------------------------------------
- Function: MV_Play
- Begin playback of sound data with the given sound levels and
- priority.
- ---------------------------------------------------------------------*/
- int MV_Play
- (
- char *ptr,
- int pitchoffset,
- int vol,
- int left,
- int right,
- int priority,
- unsigned long callbackval
- )
- {
- VoiceNode *voice;
- int buffer;
- unsigned flags;
- 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->NextBlock = ptr + *( unsigned short int * )( ptr + 0x14 );
- voice->LoopStart = NULL;
- voice->LoopCount = 0;
- voice->BlockLength = 0;
- voice->PitchScale = PITCH_GetScale( pitchoffset );
- MV_GetNextVOCBlock( voice );
- voice->next = NULL;
- voice->prev = NULL;
- for( buffer = 0; buffer < NumberOfBuffers; buffer++ )
- {
- voice->Active[ buffer ] = TRUE;
- }
- voice->Volume = MIX_VOLUME( vol );
- if ( MV_SwapLeftRight )
- {
- // SBPro uses reversed panning
- voice->LeftVolume = MIX_VOLUME( right );
- voice->RightVolume = MIX_VOLUME( left );
- }
- else
- {
- voice->LeftVolume = MIX_VOLUME( left );
- voice->RightVolume = MIX_VOLUME( right );
- }
- voice->priority = priority;
- voice->callbackval = callbackval;
- flags = DisableInterrupts();
- LL_AddToTail( VoiceNode, &VoiceList, voice );
- RestoreInterrupts( flags );
- MV_SetErrorCode( MV_Ok );
- return( voice->handle );
- }
- /*---------------------------------------------------------------------
- Function: MV_Play3D
- Begin playback of sound data at specified angle and distance
- from listener.
- ---------------------------------------------------------------------*/
- int MV_Play3D
- (
- 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_Play( ptr, pitchoffset, mid, left, right, priority,
- callbackval );
- return( status );
- }
- /*---------------------------------------------------------------------
- Function: MV_LockEnd
- Used for determining the length of the functions to lock in memory.
- ---------------------------------------------------------------------*/
- static void MV_LockEnd
- (
- void
- )
- {
- }
- /*---------------------------------------------------------------------
- Function: MV_CalcVolume
- Create the table used to convert sound data to a specific volume
- level.
- ---------------------------------------------------------------------*/
- void MV_CalcVolume
- (
- int MaxLevel
- )
- {
- int volume;
- int val;
- int level;
- int rate;
- int i;
- unsigned flags;
- flags = DisableInterrupts();
- // For each volume level, create a translation table with the
- // appropriate volume calculated.
- rate = ( MaxLevel << 16 ) / MV_MaxVolume;
- level = 0;
- if ( MV_MixMode & SIXTEEN_BIT )
- {
- for( volume = 0; volume <= MV_MaxVolume; volume++ )
- {
- for( i = 0; i < 256; i++ )
- {
- val = i - 128;
- val *= level;
- // val /= MV_MaxVoices;
- // val >>= 16;
- val >>= 20;
- ( *MV_16BitVolumeTable )[ volume ][ i ] = val;
- }
- level += rate;
- }
- /*
- // if ( ( MV_SoundCard == ProAudioSpectrum ) ||
- // ( MV_SoundCard == SoundMan16 ) )
- {
- for( volume = 0; volume < 4 * 256 * 16; volume++ )
- {
- HarshClipTable16s[ volume ] = -0x8000;
- HarshClipTable16s[ volume + 4 * 256 * 16 ] = 0xffff - 0x8000;
- }
- for( volume = 0; volume < 16 * 256; volume++ )
- {
- HarshClipTable16s[ volume + 4 * 256 * 16 - 0x800 ] =
- volume * 16 - 0x8000;
- }
- }
- else
- {
- */
- for( volume = 0; volume < 4 * 256 * 16; volume++ )
- {
- HarshClipTable16[ volume ] = 0;
- HarshClipTable16[ volume + 4 * 256 * 16 ] = 0xffff;
- }
- for( volume = 0; volume < 16 * 256; volume++ )
- {
- HarshClipTable16[ volume + 4 * 256 * 16 - 0x800 ] = volume * 16;
- }
- // }
- }
- else
- {
- for( volume = 0; volume <= MV_MaxVolume; volume++ )
- {
- for( i = 0; i < 256; i++ )
- {
- val = i - 128;
- val *= level;
- // DEBUG
- // val /= MV_MaxVoices;
- val >>= 24;
- ( *MV_8BitVolumeTable )[ volume ][ i ] = val;
- }
- level += rate;
- }
- for( volume = 0; volume < 4 * 256; volume++ )
- {
- HarshClipTable[ volume ] = 0;
- HarshClipTable[ volume + 4 * 256 ] = 255;
- }
- for( volume = 0; volume < 256; volume++ )
- {
- HarshClipTable[ volume + 4 * 256 - 128 ] = volume;
- }
- }
- RestoreInterrupts( flags );
- }
- /*---------------------------------------------------------------------
- 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
- )
- {
- int maxlevel;
- volume = max( 0, volume );
- volume = min( volume, MV_MaxTotalVolume );
- MV_TotalVolume = volume;
- maxlevel = ( MV_MaxLevel * volume ) / MV_MaxTotalVolume;
- //printf( "maxlevel = %d\n", maxlevel );
- // Calculate volume table
- MV_CalcVolume( maxlevel );
- }
- /*---------------------------------------------------------------------
- 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_Init
- Perform the initialization of variables and memory used by
- Multivoc.
- ---------------------------------------------------------------------*/
- int MV_Init
- (
- int soundcard,
- int MixRate,
- int Voices,
- int MixMode
- )
- {
- char *ptr;
- int status;
- int buffer;
- int index;
- if ( MV_Installed )
- {
- MV_Shutdown();
- }
- MV_SetErrorCode( MV_Ok );
- status = MV_LockMemory();
- if ( status != MV_Ok )
- {
- return( status );
- }
- status = USRHOOKS_GetMem( &MV_Voices, Voices * sizeof( VoiceNode ) );
- if ( status != USRHOOKS_Ok )
- {
- MV_UnlockMemory();
- MV_SetErrorCode( MV_NoMem );
- return( MV_Error );
- }
- if ( MixMode & SIXTEEN_BIT )
- {
- status = USRHOOKS_GetMem( &HarshClipTable, sizeof( HARSH_CLIP_TABLE_16 ) );
- HarshClipTable16 = ( unsigned short * )HarshClipTable;
- HarshClipTable16s = ( short * )HarshClipTable;
- }
- else
- {
- status = USRHOOKS_GetMem( &HarshClipTable, sizeof( HARSH_CLIP_TABLE_8 ) );
- HarshClipTable16 = ( unsigned short * )HarshClipTable;
- HarshClipTable16s = ( short * )HarshClipTable;
- }
- if ( status != USRHOOKS_Ok )
- {
- USRHOOKS_FreeMem( MV_Voices );
- MV_SetErrorCode( MV_NoMem );
- MV_UnlockMemory();
- return( MV_Error );
- }
- // Set number of voices before calculating volume table
- MV_MaxVoices = Voices;
- VoiceList.start = NULL;
- VoiceList.end = NULL;
- VoicePool.start = NULL;
- VoicePool.end = NULL;
- for( index = 0; index < Voices; index++ )
- {
- LL_AddToTail( VoiceNode, &VoicePool, &MV_Voices[ index ] );
- }
- // Allocate mix buffer within 1st megabyte
- status = DPMI_GetDOSMemory( &ptr, &MV_BufferDescriptor,
- 2 * TotalBufferSize );
- if ( status )
- {
- MV_SetErrorCode( MV_NoMem );
- MV_UnlockMemory();
- return( MV_Error );
- }
- MV_SwapLeftRight = FALSE;
- // Initialize the sound card
- switch( soundcard )
- {
- case SoundBlaster :
- case Awe32 :
- status = BLASTER_Init();
- if ( status != BLASTER_Ok )
- {
- MV_SetErrorCode( MV_BlasterError );
- }
- if ( ( BLASTER_Config.Type == SBPro ) ||
- ( BLASTER_Config.Type == SBPro2 ) )
- {
- MV_SwapLeftRight = TRUE;
- }
- break;
- case ProAudioSpectrum :
- case SoundMan16 :
- status = PAS_Init();
- if ( status != PAS_Ok )
- {
- MV_SetErrorCode( MV_PasError );
- }
- break;
- #ifndef SOUNDSOURCE_OFF
- case SoundSource :
- case TandySoundSource :
- status = SS_Init( soundcard );
- if ( status != SS_Ok )
- {
- MV_SetErrorCode( MV_SoundSourceError );
- }
- break;
- #endif
- default :
- MV_SetErrorCode( MV_UnsupportedCard );
- break;
- }
- if ( MV_ErrorCode != MV_Ok )
- {
- DPMI_FreeDOSMemory( MV_BufferDescriptor );
- MV_UnlockMemory();
- return( MV_Error );
- }
- MV_SoundCard = soundcard;
- MV_Installed = TRUE;
- MV_CallBackFunc = NULL;
- // Set the sampling rate
- MV_RequestedMixRate = MixRate;
- // Set Mixer to play stereo digitized sound
- MV_SetMixMode( MixMode );
- // Make sure we don't cross a physical page
- if ( ( ( unsigned long )ptr & 0xffff ) + TotalBufferSize > 0x10000 )
- {
- ptr = ( char * )( ( ( unsigned long )ptr & 0xff0000 ) + 0x10000 );
- }
- for( buffer = 0; buffer < MV_NumberOfBuffers; buffer++ )
- {
- MV_MixBuffer[ buffer ] = ptr;
- ptr += MV_BufferSize;
- }
- // Calculate pan table
- MV_CalcPanTable();
- MV_SetVolume( MV_MaxTotalVolume );
- // Init pitch scaler
- PITCH_Init();
- // 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 );
- }
- 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 )
- {
- MV_SetErrorCode( MV_NotInstalled );
- return( MV_Error );
- }
- flags = DisableInterrupts();
- MV_KillAllVoices();
- MV_Installed = FALSE;
- // Stop the sound playback engine
- MV_StopPlayback();
- // Shutdown the sound card
- switch( MV_SoundCard )
- {
- case SoundBlaster :
- case Awe32 :
- BLASTER_Shutdown();
- break;
- case ProAudioSpectrum :
- case SoundMan16 :
- PAS_Shutdown();
- break;
- #ifndef SOUNDSOURCE_OFF
- case SoundSource :
- case TandySoundSource :
- SS_Shutdown();
- break;
- #endif
- }
- RestoreInterrupts( flags );
- // Free any voices we allocated
- USRHOOKS_FreeMem( MV_Voices );
- MV_Voices = NULL;
- VoiceList.start = NULL;
- VoiceList.end = NULL;
- VoicePool.start = NULL;
- VoicePool.end = NULL;
- 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 );
- }
- /*---------------------------------------------------------------------
- Function: MV_UnlockMemory
- Unlocks all neccessary data.
- ---------------------------------------------------------------------*/
- void MV_UnlockMemory
- (
- void
- )
- {
- PITCH_UnlockMemory();
- DPMI_UnlockMemoryRegion( MV_LockStart, MV_LockEnd );
- DPMI_Unlock( MV_VolumeTable );
- DPMI_Unlock( MV_8BitVolumeTable );
- DPMI_Unlock( MV_16BitVolumeTable );
- DPMI_Unlock( MV_PanTable );
- DPMI_Unlock( MV_Installed );
- DPMI_Unlock( MV_SoundCard );
- DPMI_Unlock( MV_TotalVolume );
- DPMI_Unlock( MV_MaxVoices );
- DPMI_Unlock( MV_BufferSize );
- DPMI_Unlock( MV_SampleSize );
- DPMI_Unlock( MV_NumberOfBuffers );
- DPMI_Unlock( MV_MixMode );
- DPMI_Unlock( MV_Silence );
- DPMI_Unlock( MV_SwapLeftRight );
- DPMI_Unlock( MV_RequestedMixRate );
- DPMI_Unlock( MV_MixRate );
- DPMI_Unlock( MV_BufferDescriptor );
- DPMI_Unlock( MV_MixBuffer );
- DPMI_Unlock( MV_Voices );
- DPMI_Unlock( VoiceList );
- DPMI_Unlock( VoicePool );
- DPMI_Unlock( MV_MixPage );
- DPMI_Unlock( MV_PlayPage );
- DPMI_Unlock( MV_VoiceHandle );
- DPMI_Unlock( MV_CallBackFunc );
- DPMI_Unlock( HarshClipTable );
- DPMI_Unlock( HarshClipTable16 );
- DPMI_Unlock( HarshClipTable16s );
- DPMI_Unlock( MV_ErrorCode );
- }
- /*---------------------------------------------------------------------
- Function: MV_LockMemory
- Locks all neccessary data.
- ---------------------------------------------------------------------*/
- int MV_LockMemory
- (
- void
- )
- {
- int status;
- int pitchstatus;
- status = DPMI_LockMemoryRegion( MV_LockStart, MV_LockEnd );
- status |= DPMI_Lock( MV_VolumeTable );
- status |= DPMI_Lock( MV_8BitVolumeTable );
- status |= DPMI_Lock( MV_16BitVolumeTable );
- status |= DPMI_Lock( MV_PanTable );
- status |= DPMI_Lock( MV_Installed );
- status |= DPMI_Lock( MV_SoundCard );
- status |= DPMI_Lock( MV_TotalVolume );
- status |= DPMI_Lock( MV_MaxVoices );
- status |= DPMI_Lock( MV_BufferSize );
- status |= DPMI_Lock( MV_SampleSize );
- status |= DPMI_Lock( MV_NumberOfBuffers );
- status |= DPMI_Lock( MV_MixMode );
- status |= DPMI_Lock( MV_Silence );
- status |= DPMI_Lock( MV_SwapLeftRight );
- status |= DPMI_Lock( MV_RequestedMixRate );
- status |= DPMI_Lock( MV_MixRate );
- status |= DPMI_Lock( MV_BufferDescriptor );
- status |= DPMI_Lock( MV_MixBuffer );
- status |= DPMI_Lock( MV_Voices );
- status |= DPMI_Lock( VoiceList );
- status |= DPMI_Lock( VoicePool );
- status |= DPMI_Lock( MV_MixPage );
- status |= DPMI_Lock( MV_PlayPage );
- status |= DPMI_Lock( MV_VoiceHandle );
- status |= DPMI_Lock( MV_CallBackFunc );
- status |= DPMI_Lock( HarshClipTable );
- status |= DPMI_Lock( HarshClipTable16 );
- status |= DPMI_Lock( HarshClipTable16s );
- status |= DPMI_Lock( MV_ErrorCode );
- pitchstatus = PITCH_LockMemory();
- if ( ( pitchstatus != PITCH_Ok ) || ( status != DPMI_Ok ) )
- {
- MV_UnlockMemory();
- MV_SetErrorCode( MV_DPMI_Error );
- return( MV_Error );
- }
- return( MV_Ok );
- }
|