MULTIVOC.C 82 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453
  1. /*
  2. Copyright (C) 1994-1995 Apogee Software, Ltd.
  3. This program is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU General Public License
  5. as published by the Free Software Foundation; either version 2
  6. of the License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. See the GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. */
  15. /**********************************************************************
  16. module: MULTIVOC.C
  17. author: James R. Dose
  18. date: December 20, 1993
  19. Routines to provide multichannel digitized sound playback for
  20. Sound Blaster compatible sound cards.
  21. (c) Copyright 1993 James R. Dose. All Rights Reserved.
  22. **********************************************************************/
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <dos.h>
  26. #include <time.h>
  27. #include <conio.h>
  28. #include "dpmi.h"
  29. #include "usrhooks.h"
  30. #include "interrup.h"
  31. #include "dma.h"
  32. #include "linklist.h"
  33. #include "sndcards.h"
  34. #include "blaster.h"
  35. #include "sndscape.h"
  36. #include "sndsrc.h"
  37. #include "pas16.h"
  38. #include "guswave.h"
  39. #include "pitch.h"
  40. #include "multivoc.h"
  41. #include "_multivc.h"
  42. #include "debugio.h"
  43. #define RoundFixed( fixedval, bits ) \
  44. ( \
  45. ( \
  46. (fixedval) + ( 1 << ( (bits) - 1 ) )\
  47. ) >> (bits) \
  48. )
  49. #define IS_QUIET( ptr ) ( ( void * )( ptr ) == ( void * )&MV_VolumeTable[ 0 ] )
  50. static int MV_ReverbLevel;
  51. static int MV_ReverbDelay;
  52. static VOLUME16 *MV_ReverbTable = NULL;
  53. //static signed short MV_VolumeTable[ MV_MaxVolume + 1 ][ 256 ];
  54. static signed short MV_VolumeTable[ 63 + 1 ][ 256 ];
  55. //static Pan MV_PanTable[ MV_NumPanPositions ][ MV_MaxVolume + 1 ];
  56. static Pan MV_PanTable[ MV_NumPanPositions ][ 63 + 1 ];
  57. static int MV_Installed = FALSE;
  58. static int MV_SoundCard = SoundBlaster;
  59. static int MV_TotalVolume = MV_MaxTotalVolume;
  60. static int MV_MaxVoices = 1;
  61. static int MV_Recording;
  62. static int MV_BufferSize = MixBufferSize;
  63. static int MV_BufferLength;
  64. static int MV_NumberOfBuffers = NumberOfBuffers;
  65. static int MV_MixMode = MONO_8BIT;
  66. static int MV_Channels = 1;
  67. static int MV_Bits = 8;
  68. static int MV_Silence = SILENCE_8BIT;
  69. static int MV_SwapLeftRight = FALSE;
  70. static int MV_RequestedMixRate;
  71. static int MV_MixRate;
  72. static int MV_DMAChannel = -1;
  73. static int MV_BuffShift;
  74. static int MV_TotalMemory;
  75. static int MV_BufferDescriptor;
  76. static int MV_BufferEmpty[ NumberOfBuffers ];
  77. char *MV_MixBuffer[ NumberOfBuffers + 1 ];
  78. static VoiceNode *MV_Voices = NULL;
  79. static volatile VoiceNode VoiceList;
  80. static volatile VoiceNode VoicePool;
  81. static int MV_MixPage = 0;
  82. static int MV_VoiceHandle = MV_MinVoiceHandle;
  83. static void ( *MV_CallBackFunc )( unsigned long ) = NULL;
  84. static void ( *MV_RecordFunc )( char *ptr, int length ) = NULL;
  85. static void ( *MV_MixFunction )( VoiceNode *voice, int buffer );
  86. static int MV_MaxVolume = 63;
  87. char *MV_HarshClipTable;
  88. char *MV_MixDestination;
  89. short *MV_LeftVolume;
  90. short *MV_RightVolume;
  91. int MV_SampleSize = 1;
  92. int MV_RightChannelOffset;
  93. unsigned long MV_MixPosition;
  94. int MV_ErrorCode = MV_Ok;
  95. #define MV_SetErrorCode( status ) \
  96. MV_ErrorCode = ( status );
  97. /*---------------------------------------------------------------------
  98. Function: MV_ErrorString
  99. Returns a pointer to the error message associated with an error
  100. number. A -1 returns a pointer the current error.
  101. ---------------------------------------------------------------------*/
  102. char *MV_ErrorString
  103. (
  104. int ErrorNumber
  105. )
  106. {
  107. char *ErrorString;
  108. switch( ErrorNumber )
  109. {
  110. case MV_Warning :
  111. case MV_Error :
  112. ErrorString = MV_ErrorString( MV_ErrorCode );
  113. break;
  114. case MV_Ok :
  115. ErrorString = "Multivoc ok.";
  116. break;
  117. case MV_UnsupportedCard :
  118. ErrorString = "Selected sound card is not supported by Multivoc.";
  119. break;
  120. case MV_NotInstalled :
  121. ErrorString = "Multivoc not installed.";
  122. break;
  123. case MV_NoVoices :
  124. ErrorString = "No free voices available to Multivoc.";
  125. break;
  126. case MV_NoMem :
  127. ErrorString = "Out of memory in Multivoc.";
  128. break;
  129. case MV_VoiceNotFound :
  130. ErrorString = "No voice with matching handle found.";
  131. break;
  132. case MV_BlasterError :
  133. ErrorString = BLASTER_ErrorString( BLASTER_Error );
  134. break;
  135. case MV_PasError :
  136. ErrorString = PAS_ErrorString( PAS_Error );
  137. break;
  138. case MV_SoundScapeError :
  139. ErrorString = SOUNDSCAPE_ErrorString( SOUNDSCAPE_Error );
  140. break;
  141. #ifndef SOUNDSOURCE_OFF
  142. case MV_SoundSourceError :
  143. ErrorString = SS_ErrorString( SS_Error );
  144. break;
  145. #endif
  146. case MV_DPMI_Error :
  147. ErrorString = "DPMI Error in Multivoc.";
  148. break;
  149. case MV_InvalidVOCFile :
  150. ErrorString = "Invalid VOC file passed in to Multivoc.";
  151. break;
  152. case MV_InvalidWAVFile :
  153. ErrorString = "Invalid WAV file passed in to Multivoc.";
  154. break;
  155. case MV_InvalidMixMode :
  156. ErrorString = "Invalid mix mode request in Multivoc.";
  157. break;
  158. case MV_SoundSourceFailure :
  159. ErrorString = "Sound Source playback failed.";
  160. break;
  161. case MV_IrqFailure :
  162. ErrorString = "Playback failed, possibly due to an invalid or conflicting IRQ.";
  163. break;
  164. case MV_DMAFailure :
  165. ErrorString = "Playback failed, possibly due to an invalid or conflicting DMA channel.";
  166. break;
  167. case MV_DMA16Failure :
  168. ErrorString = "Playback failed, possibly due to an invalid or conflicting DMA channel. \n"
  169. "Make sure the 16-bit DMA channel is correct.";
  170. break;
  171. case MV_NullRecordFunction :
  172. ErrorString = "Null record function passed to MV_StartRecording.";
  173. break;
  174. default :
  175. ErrorString = "Unknown Multivoc error code.";
  176. break;
  177. }
  178. return( ErrorString );
  179. }
  180. /**********************************************************************
  181. Memory locked functions:
  182. **********************************************************************/
  183. #define MV_LockStart MV_Mix
  184. /*---------------------------------------------------------------------
  185. Function: MV_Mix
  186. Mixes the sound into the buffer.
  187. ---------------------------------------------------------------------*/
  188. static void MV_Mix
  189. (
  190. VoiceNode *voice,
  191. int buffer
  192. )
  193. {
  194. char *start;
  195. int length;
  196. long voclength;
  197. unsigned long position;
  198. unsigned long rate;
  199. unsigned long FixedPointBufferSize;
  200. if ( ( voice->length == 0 ) && ( voice->GetSound( voice ) != KeepPlaying ) )
  201. {
  202. return;
  203. }
  204. length = MixBufferSize;
  205. FixedPointBufferSize = voice->FixedPointBufferSize;
  206. MV_MixDestination = MV_MixBuffer[ buffer ];
  207. MV_LeftVolume = voice->LeftVolume;
  208. MV_RightVolume = voice->RightVolume;
  209. if ( ( MV_Channels == 2 ) && ( IS_QUIET( MV_LeftVolume ) ) )
  210. {
  211. MV_LeftVolume = MV_RightVolume;
  212. MV_MixDestination += MV_RightChannelOffset;
  213. }
  214. // Add this voice to the mix
  215. while( length > 0 )
  216. {
  217. start = voice->sound;
  218. rate = voice->RateScale;
  219. position = voice->position;
  220. // Check if the last sample in this buffer would be
  221. // beyond the length of the sample block
  222. if ( ( position + FixedPointBufferSize ) >= voice->length )
  223. {
  224. if ( position < voice->length )
  225. {
  226. voclength = ( voice->length - position + rate - 1 ) / rate;
  227. }
  228. else
  229. {
  230. voice->GetSound( voice );
  231. return;
  232. }
  233. }
  234. else
  235. {
  236. voclength = length;
  237. }
  238. voice->mix( position, rate, start, voclength );
  239. if ( voclength & 1 )
  240. {
  241. MV_MixPosition += rate;
  242. voclength -= 1;
  243. }
  244. voice->position = MV_MixPosition;
  245. length -= voclength;
  246. if ( voice->position >= voice->length )
  247. {
  248. // Get the next block of sound
  249. if ( voice->GetSound( voice ) != KeepPlaying )
  250. {
  251. return;
  252. }
  253. if ( length > 0 )
  254. {
  255. // Get the position of the last sample in the buffer
  256. FixedPointBufferSize = voice->RateScale * ( length - 1 );
  257. }
  258. }
  259. }
  260. }
  261. /*---------------------------------------------------------------------
  262. Function: MV_PlayVoice
  263. Adds a voice to the play list.
  264. ---------------------------------------------------------------------*/
  265. void MV_PlayVoice
  266. (
  267. VoiceNode *voice
  268. )
  269. {
  270. unsigned flags;
  271. flags = DisableInterrupts();
  272. LL_SortedInsertion( &VoiceList, voice, prev, next, VoiceNode, priority );
  273. RestoreInterrupts( flags );
  274. }
  275. /*---------------------------------------------------------------------
  276. Function: MV_StopVoice
  277. Removes the voice from the play list and adds it to the free list.
  278. ---------------------------------------------------------------------*/
  279. void MV_StopVoice
  280. (
  281. VoiceNode *voice
  282. )
  283. {
  284. unsigned flags;
  285. flags = DisableInterrupts();
  286. // move the voice from the play list to the free list
  287. LL_Remove( voice, next, prev );
  288. LL_Add( &VoicePool, voice, next, prev );
  289. RestoreInterrupts( flags );
  290. }
  291. /*---------------------------------------------------------------------
  292. Function: MV_ServiceVoc
  293. Starts playback of the waiting buffer and mixes the next one.
  294. ---------------------------------------------------------------------*/
  295. // static int backcolor = 1;
  296. void MV_ServiceVoc
  297. (
  298. void
  299. )
  300. {
  301. VoiceNode *voice;
  302. VoiceNode *next;
  303. char *buffer;
  304. if ( MV_DMAChannel >= 0 )
  305. {
  306. // Get the currently playing buffer
  307. buffer = ( char * )DMA_GetCurrentPos( MV_DMAChannel );
  308. MV_MixPage = ( unsigned )( buffer - MV_MixBuffer[ 0 ] );
  309. MV_MixPage >>= MV_BuffShift;
  310. }
  311. // Toggle which buffer we'll mix next
  312. MV_MixPage++;
  313. if ( MV_MixPage >= MV_NumberOfBuffers )
  314. {
  315. MV_MixPage -= MV_NumberOfBuffers;
  316. }
  317. if ( MV_ReverbLevel == 0 )
  318. {
  319. // Initialize buffer
  320. //Commented out so that the buffer is always cleared.
  321. //This is so the guys at Echo Speech can mix into the
  322. //buffer even when no sounds are playing.
  323. //if ( !MV_BufferEmpty[ MV_MixPage ] )
  324. {
  325. ClearBuffer_DW( MV_MixBuffer[ MV_MixPage ], MV_Silence, MV_BufferSize >> 2 );
  326. if ( ( MV_SoundCard == UltraSound ) && ( MV_Channels == 2 ) )
  327. {
  328. ClearBuffer_DW( MV_MixBuffer[ MV_MixPage ] + MV_RightChannelOffset,
  329. MV_Silence, MV_BufferSize >> 2 );
  330. }
  331. MV_BufferEmpty[ MV_MixPage ] = TRUE;
  332. }
  333. }
  334. else
  335. {
  336. char *end;
  337. char *source;
  338. char *dest;
  339. int count;
  340. int length;
  341. end = MV_MixBuffer[ 0 ] + MV_BufferLength;;
  342. dest = MV_MixBuffer[ MV_MixPage ];
  343. source = MV_MixBuffer[ MV_MixPage ] - MV_ReverbDelay;
  344. if ( source < MV_MixBuffer[ 0 ] )
  345. {
  346. source += MV_BufferLength;
  347. }
  348. length = MV_BufferSize;
  349. while( length > 0 )
  350. {
  351. count = length;
  352. if ( source + count > end )
  353. {
  354. count = end - source;
  355. }
  356. if ( MV_Bits == 16 )
  357. {
  358. if ( MV_ReverbTable != NULL )
  359. {
  360. MV_16BitReverb( source, dest, MV_ReverbTable, count / 2 );
  361. if ( ( MV_SoundCard == UltraSound ) && ( MV_Channels == 2 ) )
  362. {
  363. MV_16BitReverb( source + MV_RightChannelOffset,
  364. dest + MV_RightChannelOffset, MV_ReverbTable, count / 2 );
  365. }
  366. }
  367. else
  368. {
  369. MV_16BitReverbFast( source, dest, count / 2, MV_ReverbLevel );
  370. if ( ( MV_SoundCard == UltraSound ) && ( MV_Channels == 2 ) )
  371. {
  372. MV_16BitReverbFast( source + MV_RightChannelOffset,
  373. dest + MV_RightChannelOffset, count / 2, MV_ReverbLevel );
  374. }
  375. }
  376. }
  377. else
  378. {
  379. if ( MV_ReverbTable != NULL )
  380. {
  381. MV_8BitReverb( source, dest, MV_ReverbTable, count );
  382. if ( ( MV_SoundCard == UltraSound ) && ( MV_Channels == 2 ) )
  383. {
  384. MV_8BitReverb( source + MV_RightChannelOffset,
  385. dest + MV_RightChannelOffset, MV_ReverbTable, count );
  386. }
  387. }
  388. else
  389. {
  390. MV_8BitReverbFast( source, dest, count, MV_ReverbLevel );
  391. if ( ( MV_SoundCard == UltraSound ) && ( MV_Channels == 2 ) )
  392. {
  393. MV_8BitReverbFast( source + MV_RightChannelOffset,
  394. dest + MV_RightChannelOffset, count, MV_ReverbLevel );
  395. }
  396. }
  397. }
  398. // if we go through the loop again, it means that we've wrapped around the buffer
  399. source = MV_MixBuffer[ 0 ];
  400. dest += count;
  401. length -= count;
  402. }
  403. }
  404. // Play any waiting voices
  405. for( voice = VoiceList.next; voice != &VoiceList; voice = next )
  406. {
  407. // if ( ( voice < &MV_Voices[ 0 ] ) || ( voice > &MV_Voices[ 8 ] ) )
  408. // {
  409. // SetBorderColor(backcolor++);
  410. // break;
  411. // }
  412. MV_BufferEmpty[ MV_MixPage ] = FALSE;
  413. MV_MixFunction( voice, MV_MixPage );
  414. next = voice->next;
  415. // Is this voice done?
  416. if ( !voice->Playing )
  417. {
  418. MV_StopVoice( voice );
  419. if ( MV_CallBackFunc )
  420. {
  421. MV_CallBackFunc( voice->callbackval );
  422. }
  423. }
  424. }
  425. }
  426. int leftpage = -1;
  427. int rightpage = -1;
  428. void MV_ServiceGus( char **ptr, unsigned long *length )
  429. {
  430. if ( leftpage == MV_MixPage )
  431. {
  432. MV_ServiceVoc();
  433. }
  434. leftpage = MV_MixPage;
  435. *ptr = MV_MixBuffer[ MV_MixPage ];
  436. *length = MV_BufferSize;
  437. }
  438. void MV_ServiceRightGus( char **ptr, unsigned long *length )
  439. {
  440. if ( rightpage == MV_MixPage )
  441. {
  442. MV_ServiceVoc();
  443. }
  444. rightpage = MV_MixPage;
  445. *ptr = MV_MixBuffer[ MV_MixPage ] + MV_RightChannelOffset;
  446. *length = MV_BufferSize;
  447. }
  448. /*---------------------------------------------------------------------
  449. Function: MV_GetNextVOCBlock
  450. Interperate the information of a VOC format sound file.
  451. ---------------------------------------------------------------------*/
  452. playbackstatus MV_GetNextVOCBlock
  453. (
  454. VoiceNode *voice
  455. )
  456. {
  457. unsigned char *ptr;
  458. int blocktype;
  459. int lastblocktype;
  460. unsigned long blocklength;
  461. unsigned long samplespeed;
  462. unsigned int tc;
  463. int packtype;
  464. int voicemode;
  465. int done;
  466. unsigned BitsPerSample;
  467. unsigned Channels;
  468. unsigned Format;
  469. if ( voice->BlockLength > 0 )
  470. {
  471. voice->position -= voice->length;
  472. voice->sound += voice->length >> 16;
  473. if ( voice->bits == 16 )
  474. {
  475. voice->sound += voice->length >> 16;
  476. }
  477. voice->length = min( voice->BlockLength, 0x8000 );
  478. voice->BlockLength -= voice->length;
  479. voice->length <<= 16;
  480. return( KeepPlaying );
  481. }
  482. if ( ( voice->length > 0 ) && ( voice->LoopEnd != NULL ) &&
  483. ( voice->LoopStart != NULL ) )
  484. {
  485. voice->BlockLength = voice->LoopSize;
  486. voice->sound = voice->LoopStart;
  487. voice->position = 0;
  488. voice->length = min( voice->BlockLength, 0x8000 );
  489. voice->BlockLength -= voice->length;
  490. voice->length <<= 16;
  491. return( KeepPlaying );
  492. }
  493. ptr = ( unsigned char * )voice->NextBlock;
  494. voice->Playing = TRUE;
  495. voicemode = 0;
  496. lastblocktype = 0;
  497. packtype = 0;
  498. done = FALSE;
  499. while( !done )
  500. {
  501. // Stop playing if we get a NULL pointer
  502. if ( ptr == NULL )
  503. {
  504. voice->Playing = FALSE;
  505. done = TRUE;
  506. break;
  507. }
  508. blocktype = ( int )*ptr;
  509. blocklength = ( *( unsigned long * )( ptr + 1 ) ) & 0x00ffffff;
  510. ptr += 4;
  511. switch( blocktype )
  512. {
  513. case 0 :
  514. // End of data
  515. if ( ( voice->LoopStart == NULL ) ||
  516. ( voice->LoopStart >= ( ptr - 4 ) ) )
  517. {
  518. voice->Playing = FALSE;
  519. done = TRUE;
  520. }
  521. else
  522. {
  523. voice->BlockLength = ( ptr - 4 ) - voice->LoopStart;
  524. voice->sound = voice->LoopStart;
  525. voice->position = 0;
  526. voice->length = min( voice->BlockLength, 0x8000 );
  527. voice->BlockLength -= voice->length;
  528. voice->length <<= 16;
  529. return( KeepPlaying );
  530. }
  531. break;
  532. case 1 :
  533. // Sound data block
  534. voice->bits = 8;
  535. if ( lastblocktype != 8 )
  536. {
  537. tc = ( unsigned int )*ptr << 8;
  538. packtype = *( ptr + 1 );
  539. }
  540. ptr += 2;
  541. blocklength -= 2;
  542. samplespeed = 256000000L / ( 65536 - tc );
  543. // Skip packed or stereo data
  544. if ( ( packtype != 0 ) || ( voicemode != 0 ) )
  545. {
  546. ptr += blocklength;
  547. }
  548. else
  549. {
  550. done = TRUE;
  551. }
  552. voicemode = 0;
  553. break;
  554. case 2 :
  555. // Sound continuation block
  556. samplespeed = voice->SamplingRate;
  557. done = TRUE;
  558. break;
  559. case 3 :
  560. // Silence
  561. // Not implimented.
  562. ptr += blocklength;
  563. break;
  564. case 4 :
  565. // Marker
  566. // Not implimented.
  567. ptr += blocklength;
  568. break;
  569. case 5 :
  570. // ASCII string
  571. // Not implimented.
  572. ptr += blocklength;
  573. break;
  574. case 6 :
  575. // Repeat begin
  576. if ( voice->LoopEnd == NULL )
  577. {
  578. voice->LoopCount = *( unsigned short * )ptr;
  579. voice->LoopStart = ptr + blocklength;
  580. }
  581. ptr += blocklength;
  582. break;
  583. case 7 :
  584. // Repeat end
  585. ptr += blocklength;
  586. if ( lastblocktype == 6 )
  587. {
  588. voice->LoopCount = 0;
  589. }
  590. else
  591. {
  592. if ( ( voice->LoopCount > 0 ) && ( voice->LoopStart != NULL ) )
  593. {
  594. ptr = voice->LoopStart;
  595. if ( voice->LoopCount < 0xffff )
  596. {
  597. voice->LoopCount--;
  598. if ( voice->LoopCount == 0 )
  599. {
  600. voice->LoopStart = NULL;
  601. }
  602. }
  603. }
  604. }
  605. break;
  606. case 8 :
  607. // Extended block
  608. voice->bits = 8;
  609. tc = *( unsigned short * )ptr;
  610. packtype = *( ptr + 2 );
  611. voicemode = *( ptr + 3 );
  612. ptr += blocklength;
  613. break;
  614. case 9 :
  615. // New sound data block
  616. samplespeed = *( unsigned long * )ptr;
  617. BitsPerSample = ( unsigned )*( ptr + 4 );
  618. Channels = ( unsigned )*( ptr + 5 );
  619. Format = ( unsigned )*( unsigned short * )( ptr + 6 );
  620. if ( ( BitsPerSample == 8 ) && ( Channels == 1 ) &&
  621. ( Format == VOC_8BIT ) )
  622. {
  623. ptr += 12;
  624. blocklength -= 12;
  625. voice->bits = 8;
  626. done = TRUE;
  627. }
  628. else if ( ( BitsPerSample == 16 ) && ( Channels == 1 ) &&
  629. ( Format == VOC_16BIT ) )
  630. {
  631. ptr += 12;
  632. blocklength -= 12;
  633. voice->bits = 16;
  634. done = TRUE;
  635. }
  636. else
  637. {
  638. ptr += blocklength;
  639. }
  640. break;
  641. default :
  642. // Unknown data. Probably not a VOC file.
  643. voice->Playing = FALSE;
  644. done = TRUE;
  645. break;
  646. }
  647. lastblocktype = blocktype;
  648. }
  649. if ( voice->Playing )
  650. {
  651. voice->NextBlock = ptr + blocklength;
  652. voice->sound = ptr;
  653. voice->SamplingRate = samplespeed;
  654. voice->RateScale = ( voice->SamplingRate * voice->PitchScale ) / MV_MixRate;
  655. // Multiply by MixBufferSize - 1
  656. voice->FixedPointBufferSize = ( voice->RateScale * MixBufferSize ) -
  657. voice->RateScale;
  658. if ( voice->LoopEnd != NULL )
  659. {
  660. if ( blocklength > ( unsigned long )voice->LoopEnd )
  661. {
  662. blocklength = ( unsigned long )voice->LoopEnd;
  663. }
  664. else
  665. {
  666. voice->LoopEnd = ( char * )blocklength;
  667. }
  668. voice->LoopStart = voice->sound + ( unsigned long )voice->LoopStart;
  669. voice->LoopEnd = voice->sound + ( unsigned long )voice->LoopEnd;
  670. voice->LoopSize = voice->LoopEnd - voice->LoopStart;
  671. }
  672. if ( voice->bits == 16 )
  673. {
  674. blocklength /= 2;
  675. }
  676. voice->position = 0;
  677. voice->length = min( blocklength, 0x8000 );
  678. voice->BlockLength = blocklength - voice->length;
  679. voice->length <<= 16;
  680. MV_SetVoiceMixMode( voice );
  681. return( KeepPlaying );
  682. }
  683. return( NoMoreData );
  684. }
  685. /*---------------------------------------------------------------------
  686. Function: MV_GetNextDemandFeedBlock
  687. Controls playback of demand fed data.
  688. ---------------------------------------------------------------------*/
  689. playbackstatus MV_GetNextDemandFeedBlock
  690. (
  691. VoiceNode *voice
  692. )
  693. {
  694. if ( voice->BlockLength > 0 )
  695. {
  696. voice->position -= voice->length;
  697. voice->sound += voice->length >> 16;
  698. voice->length = min( voice->BlockLength, 0x8000 );
  699. voice->BlockLength -= voice->length;
  700. voice->length <<= 16;
  701. return( KeepPlaying );
  702. }
  703. if ( voice->DemandFeed == NULL )
  704. {
  705. return( NoMoreData );
  706. }
  707. voice->position = 0;
  708. ( voice->DemandFeed )( &voice->sound, &voice->BlockLength );
  709. voice->length = min( voice->BlockLength, 0x8000 );
  710. voice->BlockLength -= voice->length;
  711. voice->length <<= 16;
  712. if ( ( voice->length > 0 ) && ( voice->sound != NULL ) )
  713. {
  714. return( KeepPlaying );
  715. }
  716. return( NoMoreData );
  717. }
  718. /*---------------------------------------------------------------------
  719. Function: MV_GetNextRawBlock
  720. Controls playback of demand fed data.
  721. ---------------------------------------------------------------------*/
  722. playbackstatus MV_GetNextRawBlock
  723. (
  724. VoiceNode *voice
  725. )
  726. {
  727. if ( voice->BlockLength <= 0 )
  728. {
  729. if ( voice->LoopStart == NULL )
  730. {
  731. voice->Playing = FALSE;
  732. return( NoMoreData );
  733. }
  734. voice->BlockLength = voice->LoopSize;
  735. voice->NextBlock = voice->LoopStart;
  736. voice->length = 0;
  737. voice->position = 0;
  738. }
  739. voice->sound = voice->NextBlock;
  740. voice->position -= voice->length;
  741. voice->length = min( voice->BlockLength, 0x8000 );
  742. voice->NextBlock += voice->length;
  743. if ( voice->bits == 16 )
  744. {
  745. voice->NextBlock += voice->length;
  746. }
  747. voice->BlockLength -= voice->length;
  748. voice->length <<= 16;
  749. return( KeepPlaying );
  750. }
  751. /*---------------------------------------------------------------------
  752. Function: MV_GetNextWAVBlock
  753. Controls playback of demand fed data.
  754. ---------------------------------------------------------------------*/
  755. playbackstatus MV_GetNextWAVBlock
  756. (
  757. VoiceNode *voice
  758. )
  759. {
  760. if ( voice->BlockLength <= 0 )
  761. {
  762. if ( voice->LoopStart == NULL )
  763. {
  764. voice->Playing = FALSE;
  765. return( NoMoreData );
  766. }
  767. voice->BlockLength = voice->LoopSize;
  768. voice->NextBlock = voice->LoopStart;
  769. voice->length = 0;
  770. voice->position = 0;
  771. }
  772. voice->sound = voice->NextBlock;
  773. voice->position -= voice->length;
  774. voice->length = min( voice->BlockLength, 0x8000 );
  775. voice->NextBlock += voice->length;
  776. if ( voice->bits == 16 )
  777. {
  778. voice->NextBlock += voice->length;
  779. }
  780. voice->BlockLength -= voice->length;
  781. voice->length <<= 16;
  782. return( KeepPlaying );
  783. }
  784. /*---------------------------------------------------------------------
  785. Function: MV_ServiceRecord
  786. Starts recording of the waiting buffer.
  787. ---------------------------------------------------------------------*/
  788. static void MV_ServiceRecord
  789. (
  790. void
  791. )
  792. {
  793. if ( MV_RecordFunc )
  794. {
  795. MV_RecordFunc( MV_MixBuffer[ 0 ] + MV_MixPage * MixBufferSize,
  796. MixBufferSize );
  797. }
  798. // Toggle which buffer we'll mix next
  799. MV_MixPage++;
  800. if ( MV_MixPage >= NumberOfBuffers )
  801. {
  802. MV_MixPage = 0;
  803. }
  804. }
  805. /*---------------------------------------------------------------------
  806. Function: MV_GetVoice
  807. Locates the voice with the specified handle.
  808. ---------------------------------------------------------------------*/
  809. VoiceNode *MV_GetVoice
  810. (
  811. int handle
  812. )
  813. {
  814. VoiceNode *voice;
  815. unsigned flags;
  816. flags = DisableInterrupts();
  817. for( voice = VoiceList.next; voice != &VoiceList; voice = voice->next )
  818. {
  819. if ( handle == voice->handle )
  820. {
  821. break;
  822. }
  823. }
  824. RestoreInterrupts( flags );
  825. if ( voice == &VoiceList )
  826. {
  827. MV_SetErrorCode( MV_VoiceNotFound );
  828. }
  829. return( voice );
  830. }
  831. /*---------------------------------------------------------------------
  832. Function: MV_VoicePlaying
  833. Checks if the voice associated with the specified handle is
  834. playing.
  835. ---------------------------------------------------------------------*/
  836. int MV_VoicePlaying
  837. (
  838. int handle
  839. )
  840. {
  841. VoiceNode *voice;
  842. if ( !MV_Installed )
  843. {
  844. MV_SetErrorCode( MV_NotInstalled );
  845. return( FALSE );
  846. }
  847. voice = MV_GetVoice( handle );
  848. if ( voice == NULL )
  849. {
  850. return( FALSE );
  851. }
  852. return( TRUE );
  853. }
  854. /*---------------------------------------------------------------------
  855. Function: MV_KillAllVoices
  856. Stops output of all currently active voices.
  857. ---------------------------------------------------------------------*/
  858. int MV_KillAllVoices
  859. (
  860. void
  861. )
  862. {
  863. if ( !MV_Installed )
  864. {
  865. MV_SetErrorCode( MV_NotInstalled );
  866. return( MV_Error );
  867. }
  868. // Remove all the voices from the list
  869. while( VoiceList.next != &VoiceList )
  870. {
  871. MV_Kill( VoiceList.next->handle );
  872. }
  873. return( MV_Ok );
  874. }
  875. /*---------------------------------------------------------------------
  876. Function: MV_Kill
  877. Stops output of the voice associated with the specified handle.
  878. ---------------------------------------------------------------------*/
  879. int MV_Kill
  880. (
  881. int handle
  882. )
  883. {
  884. VoiceNode *voice;
  885. unsigned flags;
  886. unsigned long callbackval;
  887. if ( !MV_Installed )
  888. {
  889. MV_SetErrorCode( MV_NotInstalled );
  890. return( MV_Error );
  891. }
  892. flags = DisableInterrupts();
  893. voice = MV_GetVoice( handle );
  894. if ( voice == NULL )
  895. {
  896. RestoreInterrupts( flags );
  897. MV_SetErrorCode( MV_VoiceNotFound );
  898. return( MV_Error );
  899. }
  900. callbackval = voice->callbackval;
  901. MV_StopVoice( voice );
  902. RestoreInterrupts( flags );
  903. if ( MV_CallBackFunc )
  904. {
  905. MV_CallBackFunc( callbackval );
  906. }
  907. return( MV_Ok );
  908. }
  909. /*---------------------------------------------------------------------
  910. Function: MV_VoicesPlaying
  911. Determines the number of currently active voices.
  912. ---------------------------------------------------------------------*/
  913. int MV_VoicesPlaying
  914. (
  915. void
  916. )
  917. {
  918. VoiceNode *voice;
  919. int NumVoices = 0;
  920. unsigned flags;
  921. if ( !MV_Installed )
  922. {
  923. MV_SetErrorCode( MV_NotInstalled );
  924. return( 0 );
  925. }
  926. flags = DisableInterrupts();
  927. for( voice = VoiceList.next; voice != &VoiceList; voice = voice->next )
  928. {
  929. NumVoices++;
  930. }
  931. RestoreInterrupts( flags );
  932. return( NumVoices );
  933. }
  934. /*---------------------------------------------------------------------
  935. Function: MV_AllocVoice
  936. Retrieve an inactive or lower priority voice for output.
  937. ---------------------------------------------------------------------*/
  938. VoiceNode *MV_AllocVoice
  939. (
  940. int priority
  941. )
  942. {
  943. VoiceNode *voice;
  944. VoiceNode *node;
  945. unsigned flags;
  946. //return( NULL );
  947. if ( MV_Recording )
  948. {
  949. return( NULL );
  950. }
  951. flags = DisableInterrupts();
  952. // Check if we have any free voices
  953. if ( LL_Empty( &VoicePool, next, prev ) )
  954. {
  955. // check if we have a higher priority than a voice that is playing.
  956. voice = VoiceList.next;
  957. for( node = voice->next; node != &VoiceList; node = node->next )
  958. {
  959. if ( node->priority < voice->priority )
  960. {
  961. voice = node;
  962. }
  963. }
  964. if ( priority >= voice->priority )
  965. {
  966. MV_Kill( voice->handle );
  967. }
  968. }
  969. // Check if any voices are in the voice pool
  970. if ( LL_Empty( &VoicePool, next, prev ) )
  971. {
  972. // No free voices
  973. RestoreInterrupts( flags );
  974. return( NULL );
  975. }
  976. voice = VoicePool.next;
  977. LL_Remove( voice, next, prev );
  978. RestoreInterrupts( flags );
  979. // Find a free voice handle
  980. do
  981. {
  982. MV_VoiceHandle++;
  983. if ( MV_VoiceHandle < MV_MinVoiceHandle )
  984. {
  985. MV_VoiceHandle = MV_MinVoiceHandle;
  986. }
  987. }
  988. while( MV_VoicePlaying( MV_VoiceHandle ) );
  989. voice->handle = MV_VoiceHandle;
  990. return( voice );
  991. }
  992. /*---------------------------------------------------------------------
  993. Function: MV_VoiceAvailable
  994. Checks if a voice can be play at the specified priority.
  995. ---------------------------------------------------------------------*/
  996. int MV_VoiceAvailable
  997. (
  998. int priority
  999. )
  1000. {
  1001. VoiceNode *voice;
  1002. VoiceNode *node;
  1003. unsigned flags;
  1004. // Check if we have any free voices
  1005. if ( !LL_Empty( &VoicePool, next, prev ) )
  1006. {
  1007. return( TRUE );
  1008. }
  1009. flags = DisableInterrupts();
  1010. // check if we have a higher priority than a voice that is playing.
  1011. voice = VoiceList.next;
  1012. for( node = VoiceList.next; node != &VoiceList; node = node->next )
  1013. {
  1014. if ( node->priority < voice->priority )
  1015. {
  1016. voice = node;
  1017. }
  1018. }
  1019. RestoreInterrupts( flags );
  1020. if ( ( voice != &VoiceList ) && ( priority >= voice->priority ) )
  1021. {
  1022. return( TRUE );
  1023. }
  1024. return( FALSE );
  1025. }
  1026. /*---------------------------------------------------------------------
  1027. Function: MV_SetVoicePitch
  1028. Sets the pitch for the specified voice.
  1029. ---------------------------------------------------------------------*/
  1030. void MV_SetVoicePitch
  1031. (
  1032. VoiceNode *voice,
  1033. unsigned long rate,
  1034. int pitchoffset
  1035. )
  1036. {
  1037. voice->SamplingRate = rate;
  1038. voice->PitchScale = PITCH_GetScale( pitchoffset );
  1039. voice->RateScale = ( rate * voice->PitchScale ) / MV_MixRate;
  1040. // Multiply by MixBufferSize - 1
  1041. voice->FixedPointBufferSize = ( voice->RateScale * MixBufferSize ) -
  1042. voice->RateScale;
  1043. }
  1044. /*---------------------------------------------------------------------
  1045. Function: MV_SetPitch
  1046. Sets the pitch for the voice associated with the specified handle.
  1047. ---------------------------------------------------------------------*/
  1048. int MV_SetPitch
  1049. (
  1050. int handle,
  1051. int pitchoffset
  1052. )
  1053. {
  1054. VoiceNode *voice;
  1055. if ( !MV_Installed )
  1056. {
  1057. MV_SetErrorCode( MV_NotInstalled );
  1058. return( MV_Error );
  1059. }
  1060. voice = MV_GetVoice( handle );
  1061. if ( voice == NULL )
  1062. {
  1063. MV_SetErrorCode( MV_VoiceNotFound );
  1064. return( MV_Error );
  1065. }
  1066. MV_SetVoicePitch( voice, voice->SamplingRate, pitchoffset );
  1067. return( MV_Ok );
  1068. }
  1069. /*---------------------------------------------------------------------
  1070. Function: MV_SetFrequency
  1071. Sets the frequency for the voice associated with the specified handle.
  1072. ---------------------------------------------------------------------*/
  1073. int MV_SetFrequency
  1074. (
  1075. int handle,
  1076. int frequency
  1077. )
  1078. {
  1079. VoiceNode *voice;
  1080. if ( !MV_Installed )
  1081. {
  1082. MV_SetErrorCode( MV_NotInstalled );
  1083. return( MV_Error );
  1084. }
  1085. voice = MV_GetVoice( handle );
  1086. if ( voice == NULL )
  1087. {
  1088. MV_SetErrorCode( MV_VoiceNotFound );
  1089. return( MV_Error );
  1090. }
  1091. MV_SetVoicePitch( voice, frequency, 0 );
  1092. return( MV_Ok );
  1093. }
  1094. /*---------------------------------------------------------------------
  1095. Function: MV_GetVolumeTable
  1096. Returns a pointer to the volume table associated with the specified
  1097. volume.
  1098. ---------------------------------------------------------------------*/
  1099. static short *MV_GetVolumeTable
  1100. (
  1101. int vol
  1102. )
  1103. {
  1104. int volume;
  1105. short *table;
  1106. volume = MIX_VOLUME( vol );
  1107. table = &MV_VolumeTable[ volume ];
  1108. return( table );
  1109. }
  1110. /*---------------------------------------------------------------------
  1111. Function: MV_SetVoiceMixMode
  1112. Selects which method should be used to mix the voice.
  1113. ---------------------------------------------------------------------*/
  1114. static void MV_SetVoiceMixMode
  1115. (
  1116. VoiceNode *voice
  1117. )
  1118. {
  1119. unsigned flags;
  1120. int test;
  1121. flags = DisableInterrupts();
  1122. test = T_DEFAULT;
  1123. if ( MV_Bits == 8 )
  1124. {
  1125. test |= T_8BITS;
  1126. }
  1127. if ( voice->bits == 16 )
  1128. {
  1129. test |= T_16BITSOURCE;
  1130. }
  1131. if ( MV_Channels == 1 )
  1132. {
  1133. test |= T_MONO;
  1134. }
  1135. else
  1136. {
  1137. if ( IS_QUIET( voice->RightVolume ) )
  1138. {
  1139. test |= T_RIGHTQUIET;
  1140. }
  1141. else if ( IS_QUIET( voice->LeftVolume ) )
  1142. {
  1143. test |= T_LEFTQUIET;
  1144. }
  1145. }
  1146. // Default case
  1147. voice->mix = MV_Mix8BitMono;
  1148. switch( test )
  1149. {
  1150. case T_8BITS | T_MONO | T_16BITSOURCE :
  1151. voice->mix = MV_Mix8BitMono16;
  1152. break;
  1153. case T_8BITS | T_MONO :
  1154. voice->mix = MV_Mix8BitMono;
  1155. break;
  1156. case T_8BITS | T_16BITSOURCE | T_LEFTQUIET :
  1157. MV_LeftVolume = MV_RightVolume;
  1158. voice->mix = MV_Mix8BitMono16;
  1159. break;
  1160. case T_8BITS | T_LEFTQUIET :
  1161. MV_LeftVolume = MV_RightVolume;
  1162. voice->mix = MV_Mix8BitMono;
  1163. break;
  1164. case T_8BITS | T_16BITSOURCE | T_RIGHTQUIET :
  1165. voice->mix = MV_Mix8BitMono16;
  1166. break;
  1167. case T_8BITS | T_RIGHTQUIET :
  1168. voice->mix = MV_Mix8BitMono;
  1169. break;
  1170. case T_8BITS | T_16BITSOURCE :
  1171. voice->mix = MV_Mix8BitStereo16;
  1172. break;
  1173. case T_8BITS :
  1174. voice->mix = MV_Mix8BitStereo;
  1175. break;
  1176. case T_MONO | T_16BITSOURCE :
  1177. voice->mix = MV_Mix16BitMono16;
  1178. break;
  1179. case T_MONO :
  1180. voice->mix = MV_Mix16BitMono;
  1181. break;
  1182. case T_16BITSOURCE | T_LEFTQUIET :
  1183. MV_LeftVolume = MV_RightVolume;
  1184. voice->mix = MV_Mix16BitMono16;
  1185. break;
  1186. case T_LEFTQUIET :
  1187. MV_LeftVolume = MV_RightVolume;
  1188. voice->mix = MV_Mix16BitMono;
  1189. break;
  1190. case T_16BITSOURCE | T_RIGHTQUIET :
  1191. voice->mix = MV_Mix16BitMono16;
  1192. break;
  1193. case T_RIGHTQUIET :
  1194. voice->mix = MV_Mix16BitMono;
  1195. break;
  1196. case T_16BITSOURCE :
  1197. voice->mix = MV_Mix16BitStereo16;
  1198. break;
  1199. case T_SIXTEENBIT_STEREO :
  1200. voice->mix = MV_Mix16BitStereo;
  1201. break;
  1202. default :
  1203. voice->mix = MV_Mix8BitMono;
  1204. }
  1205. RestoreInterrupts( flags );
  1206. }
  1207. /*---------------------------------------------------------------------
  1208. Function: MV_SetVoiceVolume
  1209. Sets the stereo and mono volume level of the voice associated
  1210. with the specified handle.
  1211. ---------------------------------------------------------------------*/
  1212. void MV_SetVoiceVolume
  1213. (
  1214. VoiceNode *voice,
  1215. int vol,
  1216. int left,
  1217. int right
  1218. )
  1219. {
  1220. if ( MV_Channels == 1 )
  1221. {
  1222. left = vol;
  1223. right = vol;
  1224. }
  1225. if ( MV_SwapLeftRight )
  1226. {
  1227. // SBPro uses reversed panning
  1228. voice->LeftVolume = MV_GetVolumeTable( right );
  1229. voice->RightVolume = MV_GetVolumeTable( left );
  1230. }
  1231. else
  1232. {
  1233. voice->LeftVolume = MV_GetVolumeTable( left );
  1234. voice->RightVolume = MV_GetVolumeTable( right );
  1235. }
  1236. MV_SetVoiceMixMode( voice );
  1237. }
  1238. /*---------------------------------------------------------------------
  1239. Function: MV_EndLooping
  1240. Stops the voice associated with the specified handle from looping
  1241. without stoping the sound.
  1242. ---------------------------------------------------------------------*/
  1243. int MV_EndLooping
  1244. (
  1245. int handle
  1246. )
  1247. {
  1248. VoiceNode *voice;
  1249. unsigned flags;
  1250. if ( !MV_Installed )
  1251. {
  1252. MV_SetErrorCode( MV_NotInstalled );
  1253. return( MV_Error );
  1254. }
  1255. flags = DisableInterrupts();
  1256. voice = MV_GetVoice( handle );
  1257. if ( voice == NULL )
  1258. {
  1259. RestoreInterrupts( flags );
  1260. MV_SetErrorCode( MV_VoiceNotFound );
  1261. return( MV_Warning );
  1262. }
  1263. voice->LoopCount = 0;
  1264. voice->LoopStart = NULL;
  1265. voice->LoopEnd = NULL;
  1266. RestoreInterrupts( flags );
  1267. return( MV_Ok );
  1268. }
  1269. /*---------------------------------------------------------------------
  1270. Function: MV_SetPan
  1271. Sets the stereo and mono volume level of the voice associated
  1272. with the specified handle.
  1273. ---------------------------------------------------------------------*/
  1274. int MV_SetPan
  1275. (
  1276. int handle,
  1277. int vol,
  1278. int left,
  1279. int right
  1280. )
  1281. {
  1282. VoiceNode *voice;
  1283. if ( !MV_Installed )
  1284. {
  1285. MV_SetErrorCode( MV_NotInstalled );
  1286. return( MV_Error );
  1287. }
  1288. voice = MV_GetVoice( handle );
  1289. if ( voice == NULL )
  1290. {
  1291. MV_SetErrorCode( MV_VoiceNotFound );
  1292. return( MV_Warning );
  1293. }
  1294. MV_SetVoiceVolume( voice, vol, left, right );
  1295. return( MV_Ok );
  1296. }
  1297. /*---------------------------------------------------------------------
  1298. Function: MV_Pan3D
  1299. Set the angle and distance from the listener of the voice associated
  1300. with the specified handle.
  1301. ---------------------------------------------------------------------*/
  1302. int MV_Pan3D
  1303. (
  1304. int handle,
  1305. int angle,
  1306. int distance
  1307. )
  1308. {
  1309. int left;
  1310. int right;
  1311. int mid;
  1312. int volume;
  1313. int status;
  1314. if ( distance < 0 )
  1315. {
  1316. distance = -distance;
  1317. angle += MV_NumPanPositions / 2;
  1318. }
  1319. volume = MIX_VOLUME( distance );
  1320. // Ensure angle is within 0 - 31
  1321. angle &= MV_MaxPanPosition;
  1322. left = MV_PanTable[ angle ][ volume ].left;
  1323. right = MV_PanTable[ angle ][ volume ].right;
  1324. mid = max( 0, 255 - distance );
  1325. status = MV_SetPan( handle, mid, left, right );
  1326. return( status );
  1327. }
  1328. /*---------------------------------------------------------------------
  1329. Function: MV_SetReverb
  1330. Sets the level of reverb to add to mix.
  1331. ---------------------------------------------------------------------*/
  1332. void MV_SetReverb
  1333. (
  1334. int reverb
  1335. )
  1336. {
  1337. MV_ReverbLevel = MIX_VOLUME( reverb );
  1338. MV_ReverbTable = &MV_VolumeTable[ MV_ReverbLevel ];
  1339. }
  1340. /*---------------------------------------------------------------------
  1341. Function: MV_SetFastReverb
  1342. Sets the level of reverb to add to mix.
  1343. ---------------------------------------------------------------------*/
  1344. void MV_SetFastReverb
  1345. (
  1346. int reverb
  1347. )
  1348. {
  1349. MV_ReverbLevel = max( 0, min( 16, reverb ) );
  1350. MV_ReverbTable = NULL;
  1351. }
  1352. /*---------------------------------------------------------------------
  1353. Function: MV_GetMaxReverbDelay
  1354. Returns the maximum delay time for reverb.
  1355. ---------------------------------------------------------------------*/
  1356. int MV_GetMaxReverbDelay
  1357. (
  1358. void
  1359. )
  1360. {
  1361. int maxdelay;
  1362. maxdelay = MixBufferSize * MV_NumberOfBuffers;
  1363. return maxdelay;
  1364. }
  1365. /*---------------------------------------------------------------------
  1366. Function: MV_GetReverbDelay
  1367. Returns the current delay time for reverb.
  1368. ---------------------------------------------------------------------*/
  1369. int MV_GetReverbDelay
  1370. (
  1371. void
  1372. )
  1373. {
  1374. return MV_ReverbDelay / MV_SampleSize;
  1375. }
  1376. /*---------------------------------------------------------------------
  1377. Function: MV_SetReverbDelay
  1378. Sets the delay level of reverb to add to mix.
  1379. ---------------------------------------------------------------------*/
  1380. void MV_SetReverbDelay
  1381. (
  1382. int delay
  1383. )
  1384. {
  1385. int maxdelay;
  1386. maxdelay = MV_GetMaxReverbDelay();
  1387. MV_ReverbDelay = max( MixBufferSize, min( delay, maxdelay ) );
  1388. MV_ReverbDelay *= MV_SampleSize;
  1389. }
  1390. /*---------------------------------------------------------------------
  1391. Function: MV_SetMixMode
  1392. Prepares Multivoc to play stereo of mono digitized sounds.
  1393. ---------------------------------------------------------------------*/
  1394. int MV_SetMixMode
  1395. (
  1396. int numchannels,
  1397. int samplebits
  1398. )
  1399. {
  1400. int mode;
  1401. if ( !MV_Installed )
  1402. {
  1403. MV_SetErrorCode( MV_NotInstalled );
  1404. return( MV_Error );
  1405. }
  1406. mode = 0;
  1407. if ( numchannels == 2 )
  1408. {
  1409. mode |= STEREO;
  1410. }
  1411. if ( samplebits == 16 )
  1412. {
  1413. mode |= SIXTEEN_BIT;
  1414. }
  1415. switch( MV_SoundCard )
  1416. {
  1417. case UltraSound :
  1418. MV_MixMode = mode;
  1419. break;
  1420. case SoundBlaster :
  1421. case Awe32 :
  1422. MV_MixMode = BLASTER_SetMixMode( mode );
  1423. break;
  1424. case ProAudioSpectrum :
  1425. case SoundMan16 :
  1426. MV_MixMode = PAS_SetMixMode( mode );
  1427. break;
  1428. case SoundScape :
  1429. MV_MixMode = SOUNDSCAPE_SetMixMode( mode );
  1430. break;
  1431. #ifndef SOUNDSOURCE_OFF
  1432. case SoundSource :
  1433. case TandySoundSource :
  1434. MV_MixMode = SS_SetMixMode( mode );
  1435. break;
  1436. #endif
  1437. }
  1438. MV_Channels = 1;
  1439. if ( MV_MixMode & STEREO )
  1440. {
  1441. MV_Channels = 2;
  1442. }
  1443. MV_Bits = 8;
  1444. if ( MV_MixMode & SIXTEEN_BIT )
  1445. {
  1446. MV_Bits = 16;
  1447. }
  1448. MV_BuffShift = 7 + MV_Channels;
  1449. MV_SampleSize = sizeof( MONO8 ) * MV_Channels;
  1450. if ( MV_Bits == 8 )
  1451. {
  1452. MV_Silence = SILENCE_8BIT;
  1453. }
  1454. else
  1455. {
  1456. MV_Silence = SILENCE_16BIT;
  1457. MV_BuffShift += 1;
  1458. MV_SampleSize *= 2;
  1459. }
  1460. MV_BufferSize = MixBufferSize * MV_SampleSize;
  1461. MV_NumberOfBuffers = TotalBufferSize / MV_BufferSize;
  1462. MV_BufferLength = TotalBufferSize;
  1463. MV_RightChannelOffset = MV_SampleSize / 2;
  1464. if ( ( MV_SoundCard == UltraSound ) && ( MV_Channels == 2 ) )
  1465. {
  1466. MV_SampleSize /= 2;
  1467. MV_BufferSize /= 2;
  1468. MV_RightChannelOffset = MV_BufferSize * MV_NumberOfBuffers;
  1469. MV_BufferLength /= 2;
  1470. }
  1471. return( MV_Ok );
  1472. }
  1473. /*---------------------------------------------------------------------
  1474. Function: MV_StartPlayback
  1475. Starts the sound playback engine.
  1476. ---------------------------------------------------------------------*/
  1477. int MV_StartPlayback
  1478. (
  1479. void
  1480. )
  1481. {
  1482. int status;
  1483. int buffer;
  1484. // Initialize the buffers
  1485. ClearBuffer_DW( MV_MixBuffer[ 0 ], MV_Silence, TotalBufferSize >> 2 );
  1486. for( buffer = 0; buffer < MV_NumberOfBuffers; buffer++ )
  1487. {
  1488. MV_BufferEmpty[ buffer ] = TRUE;
  1489. }
  1490. // Set the mix buffer variables
  1491. MV_MixPage = 1;
  1492. MV_MixFunction = MV_Mix;
  1493. //JIM
  1494. // MV_MixRate = MV_RequestedMixRate;
  1495. // return( MV_Ok );
  1496. // Start playback
  1497. switch( MV_SoundCard )
  1498. {
  1499. case SoundBlaster :
  1500. case Awe32 :
  1501. status = BLASTER_BeginBufferedPlayback( MV_MixBuffer[ 0 ],
  1502. TotalBufferSize, MV_NumberOfBuffers,
  1503. MV_RequestedMixRate, MV_MixMode, MV_ServiceVoc );
  1504. if ( status != BLASTER_Ok )
  1505. {
  1506. MV_SetErrorCode( MV_BlasterError );
  1507. return( MV_Error );
  1508. }
  1509. MV_MixRate = BLASTER_GetPlaybackRate();
  1510. MV_DMAChannel = BLASTER_DMAChannel;
  1511. break;
  1512. case UltraSound :
  1513. status = GUSWAVE_StartDemandFeedPlayback( MV_ServiceGus, 1,
  1514. MV_Bits, MV_RequestedMixRate, 0, ( MV_Channels == 1 ) ?
  1515. 0 : 24, 255, 0xffff, 0 );
  1516. if ( status < GUSWAVE_Ok )
  1517. {
  1518. MV_SetErrorCode( MV_BlasterError );
  1519. return( MV_Error );
  1520. }
  1521. if ( MV_Channels == 2 )
  1522. {
  1523. status = GUSWAVE_StartDemandFeedPlayback( MV_ServiceRightGus, 1,
  1524. MV_Bits, MV_RequestedMixRate, 0, 8, 255, 0xffff, 0 );
  1525. if ( status < GUSWAVE_Ok )
  1526. {
  1527. GUSWAVE_KillAllVoices();
  1528. MV_SetErrorCode( MV_BlasterError );
  1529. return( MV_Error );
  1530. }
  1531. }
  1532. MV_MixRate = MV_RequestedMixRate;
  1533. MV_DMAChannel = -1;
  1534. break;
  1535. case ProAudioSpectrum :
  1536. case SoundMan16 :
  1537. status = PAS_BeginBufferedPlayback( MV_MixBuffer[ 0 ],
  1538. TotalBufferSize, MV_NumberOfBuffers,
  1539. MV_RequestedMixRate, MV_MixMode, MV_ServiceVoc );
  1540. if ( status != PAS_Ok )
  1541. {
  1542. MV_SetErrorCode( MV_PasError );
  1543. return( MV_Error );
  1544. }
  1545. MV_MixRate = PAS_GetPlaybackRate();
  1546. MV_DMAChannel = PAS_DMAChannel;
  1547. break;
  1548. case SoundScape :
  1549. status = SOUNDSCAPE_BeginBufferedPlayback( MV_MixBuffer[ 0 ],
  1550. TotalBufferSize, MV_NumberOfBuffers, MV_RequestedMixRate,
  1551. MV_MixMode, MV_ServiceVoc );
  1552. if ( status != SOUNDSCAPE_Ok )
  1553. {
  1554. MV_SetErrorCode( MV_SoundScapeError );
  1555. return( MV_Error );
  1556. }
  1557. MV_MixRate = SOUNDSCAPE_GetPlaybackRate();
  1558. MV_DMAChannel = SOUNDSCAPE_DMAChannel;
  1559. break;
  1560. #ifndef SOUNDSOURCE_OFF
  1561. case SoundSource :
  1562. case TandySoundSource :
  1563. SS_BeginBufferedPlayback( MV_MixBuffer[ 0 ],
  1564. TotalBufferSize, MV_NumberOfBuffers,
  1565. MV_ServiceVoc );
  1566. MV_MixRate = SS_SampleRate;
  1567. MV_DMAChannel = -1;
  1568. break;
  1569. #endif
  1570. }
  1571. return( MV_Ok );
  1572. }
  1573. /*---------------------------------------------------------------------
  1574. Function: MV_StopPlayback
  1575. Stops the sound playback engine.
  1576. ---------------------------------------------------------------------*/
  1577. void MV_StopPlayback
  1578. (
  1579. void
  1580. )
  1581. {
  1582. VoiceNode *voice;
  1583. VoiceNode *next;
  1584. unsigned flags;
  1585. // Stop sound playback
  1586. switch( MV_SoundCard )
  1587. {
  1588. case SoundBlaster :
  1589. case Awe32 :
  1590. BLASTER_StopPlayback();
  1591. break;
  1592. case UltraSound :
  1593. GUSWAVE_KillAllVoices();
  1594. break;
  1595. case ProAudioSpectrum :
  1596. case SoundMan16 :
  1597. PAS_StopPlayback();
  1598. break;
  1599. case SoundScape :
  1600. SOUNDSCAPE_StopPlayback();
  1601. break;
  1602. #ifndef SOUNDSOURCE_OFF
  1603. case SoundSource :
  1604. case TandySoundSource :
  1605. SS_StopPlayback();
  1606. break;
  1607. #endif
  1608. }
  1609. // Make sure all callbacks are done.
  1610. flags = DisableInterrupts();
  1611. for( voice = VoiceList.next; voice != &VoiceList; voice = next )
  1612. {
  1613. next = voice->next;
  1614. MV_StopVoice( voice );
  1615. if ( MV_CallBackFunc )
  1616. {
  1617. MV_CallBackFunc( voice->callbackval );
  1618. }
  1619. }
  1620. RestoreInterrupts( flags );
  1621. }
  1622. /*---------------------------------------------------------------------
  1623. Function: MV_StartRecording
  1624. Starts the sound recording engine.
  1625. ---------------------------------------------------------------------*/
  1626. int MV_StartRecording
  1627. (
  1628. int MixRate,
  1629. void ( *function )( char *ptr, int length )
  1630. )
  1631. {
  1632. int status;
  1633. switch( MV_SoundCard )
  1634. {
  1635. case SoundBlaster :
  1636. case Awe32 :
  1637. case ProAudioSpectrum :
  1638. case SoundMan16 :
  1639. break;
  1640. default :
  1641. MV_SetErrorCode( MV_UnsupportedCard );
  1642. return( MV_Error );
  1643. break;
  1644. }
  1645. if ( function == NULL )
  1646. {
  1647. MV_SetErrorCode( MV_NullRecordFunction );
  1648. return( MV_Error );
  1649. }
  1650. MV_StopPlayback();
  1651. // Initialize the buffers
  1652. ClearBuffer_DW( MV_MixBuffer[ 0 ], SILENCE_8BIT, TotalBufferSize >> 2 );
  1653. // Set the mix buffer variables
  1654. MV_MixPage = 0;
  1655. MV_RecordFunc = function;
  1656. // Start playback
  1657. switch( MV_SoundCard )
  1658. {
  1659. case SoundBlaster :
  1660. case Awe32 :
  1661. status = BLASTER_BeginBufferedRecord( MV_MixBuffer[ 0 ],
  1662. TotalBufferSize, NumberOfBuffers, MixRate, MONO_8BIT,
  1663. MV_ServiceRecord );
  1664. if ( status != BLASTER_Ok )
  1665. {
  1666. MV_SetErrorCode( MV_BlasterError );
  1667. return( MV_Error );
  1668. }
  1669. break;
  1670. case ProAudioSpectrum :
  1671. case SoundMan16 :
  1672. status = PAS_BeginBufferedRecord( MV_MixBuffer[ 0 ],
  1673. TotalBufferSize, NumberOfBuffers, MixRate, MONO_8BIT,
  1674. MV_ServiceRecord );
  1675. if ( status != PAS_Ok )
  1676. {
  1677. MV_SetErrorCode( MV_PasError );
  1678. return( MV_Error );
  1679. }
  1680. break;
  1681. }
  1682. MV_Recording = TRUE;
  1683. return( MV_Ok );
  1684. }
  1685. /*---------------------------------------------------------------------
  1686. Function: MV_StopRecord
  1687. Stops the sound record engine.
  1688. ---------------------------------------------------------------------*/
  1689. void MV_StopRecord
  1690. (
  1691. void
  1692. )
  1693. {
  1694. // Stop sound playback
  1695. switch( MV_SoundCard )
  1696. {
  1697. case SoundBlaster :
  1698. case Awe32 :
  1699. BLASTER_StopPlayback();
  1700. break;
  1701. case ProAudioSpectrum :
  1702. case SoundMan16 :
  1703. PAS_StopPlayback();
  1704. break;
  1705. }
  1706. MV_Recording = FALSE;
  1707. MV_StartPlayback();
  1708. }
  1709. /*---------------------------------------------------------------------
  1710. Function: MV_StartDemandFeedPlayback
  1711. Plays a digitized sound from a user controlled buffering system.
  1712. ---------------------------------------------------------------------*/
  1713. int MV_StartDemandFeedPlayback
  1714. (
  1715. void ( *function )( char **ptr, unsigned long *length ),
  1716. int rate,
  1717. int pitchoffset,
  1718. int vol,
  1719. int left,
  1720. int right,
  1721. int priority,
  1722. unsigned long callbackval
  1723. )
  1724. {
  1725. VoiceNode *voice;
  1726. if ( !MV_Installed )
  1727. {
  1728. MV_SetErrorCode( MV_NotInstalled );
  1729. return( MV_Error );
  1730. }
  1731. // Request a voice from the voice pool
  1732. voice = MV_AllocVoice( priority );
  1733. if ( voice == NULL )
  1734. {
  1735. MV_SetErrorCode( MV_NoVoices );
  1736. return( MV_Error );
  1737. }
  1738. voice->wavetype = DemandFeed;
  1739. voice->bits = 8;
  1740. voice->GetSound = MV_GetNextDemandFeedBlock;
  1741. voice->NextBlock = NULL;
  1742. voice->DemandFeed = function;
  1743. voice->LoopStart = NULL;
  1744. voice->LoopCount = 0;
  1745. voice->BlockLength = 0;
  1746. voice->position = 0;
  1747. voice->sound = NULL;
  1748. voice->length = 0;
  1749. voice->BlockLength = 0;
  1750. voice->Playing = TRUE;
  1751. voice->next = NULL;
  1752. voice->prev = NULL;
  1753. voice->priority = priority;
  1754. voice->callbackval = callbackval;
  1755. MV_SetVoicePitch( voice, rate, pitchoffset );
  1756. MV_SetVoiceVolume( voice, vol, left, right );
  1757. MV_PlayVoice( voice );
  1758. return( voice->handle );
  1759. }
  1760. /*---------------------------------------------------------------------
  1761. Function: MV_PlayRaw
  1762. Begin playback of sound data with the given sound levels and
  1763. priority.
  1764. ---------------------------------------------------------------------*/
  1765. int MV_PlayRaw
  1766. (
  1767. char *ptr,
  1768. unsigned long length,
  1769. unsigned rate,
  1770. int pitchoffset,
  1771. int vol,
  1772. int left,
  1773. int right,
  1774. int priority,
  1775. unsigned long callbackval
  1776. )
  1777. {
  1778. int status;
  1779. status = MV_PlayLoopedRaw( ptr, length, NULL, NULL, rate, pitchoffset,
  1780. vol, left, right, priority, callbackval );
  1781. return( status );
  1782. }
  1783. /*---------------------------------------------------------------------
  1784. Function: MV_PlayLoopedRaw
  1785. Begin playback of sound data with the given sound levels and
  1786. priority.
  1787. ---------------------------------------------------------------------*/
  1788. int MV_PlayLoopedRaw
  1789. (
  1790. char *ptr,
  1791. long length,
  1792. char *loopstart,
  1793. char *loopend,
  1794. unsigned rate,
  1795. int pitchoffset,
  1796. int vol,
  1797. int left,
  1798. int right,
  1799. int priority,
  1800. unsigned long callbackval
  1801. )
  1802. {
  1803. VoiceNode *voice;
  1804. if ( !MV_Installed )
  1805. {
  1806. MV_SetErrorCode( MV_NotInstalled );
  1807. return( MV_Error );
  1808. }
  1809. // Request a voice from the voice pool
  1810. voice = MV_AllocVoice( priority );
  1811. if ( voice == NULL )
  1812. {
  1813. MV_SetErrorCode( MV_NoVoices );
  1814. return( MV_Error );
  1815. }
  1816. voice->wavetype = Raw;
  1817. voice->bits = 8;
  1818. voice->GetSound = MV_GetNextRawBlock;
  1819. voice->Playing = TRUE;
  1820. voice->NextBlock = ptr;
  1821. voice->position = 0;
  1822. voice->BlockLength = length;
  1823. voice->length = 0;
  1824. voice->next = NULL;
  1825. voice->prev = NULL;
  1826. voice->priority = priority;
  1827. voice->callbackval = callbackval;
  1828. voice->LoopStart = loopstart;
  1829. voice->LoopEnd = loopend;
  1830. voice->LoopSize = ( voice->LoopEnd - voice->LoopStart ) + 1;
  1831. MV_SetVoicePitch( voice, rate, pitchoffset );
  1832. MV_SetVoiceVolume( voice, vol, left, right );
  1833. MV_PlayVoice( voice );
  1834. return( voice->handle );
  1835. }
  1836. /*---------------------------------------------------------------------
  1837. Function: MV_PlayWAV
  1838. Begin playback of sound data with the given sound levels and
  1839. priority.
  1840. ---------------------------------------------------------------------*/
  1841. int MV_PlayWAV
  1842. (
  1843. char *ptr,
  1844. int pitchoffset,
  1845. int vol,
  1846. int left,
  1847. int right,
  1848. int priority,
  1849. unsigned long callbackval
  1850. )
  1851. {
  1852. int status;
  1853. status = MV_PlayLoopedWAV( ptr, -1, -1, pitchoffset, vol, left, right,
  1854. priority, callbackval );
  1855. return( status );
  1856. }
  1857. /*---------------------------------------------------------------------
  1858. Function: MV_PlayWAV3D
  1859. Begin playback of sound data at specified angle and distance
  1860. from listener.
  1861. ---------------------------------------------------------------------*/
  1862. int MV_PlayWAV3D
  1863. (
  1864. char *ptr,
  1865. int pitchoffset,
  1866. int angle,
  1867. int distance,
  1868. int priority,
  1869. unsigned long callbackval
  1870. )
  1871. {
  1872. int left;
  1873. int right;
  1874. int mid;
  1875. int volume;
  1876. int status;
  1877. if ( !MV_Installed )
  1878. {
  1879. MV_SetErrorCode( MV_NotInstalled );
  1880. return( MV_Error );
  1881. }
  1882. if ( distance < 0 )
  1883. {
  1884. distance = -distance;
  1885. angle += MV_NumPanPositions / 2;
  1886. }
  1887. volume = MIX_VOLUME( distance );
  1888. // Ensure angle is within 0 - 31
  1889. angle &= MV_MaxPanPosition;
  1890. left = MV_PanTable[ angle ][ volume ].left;
  1891. right = MV_PanTable[ angle ][ volume ].right;
  1892. mid = max( 0, 255 - distance );
  1893. status = MV_PlayWAV( ptr, pitchoffset, mid, left, right, priority,
  1894. callbackval );
  1895. return( status );
  1896. }
  1897. /*---------------------------------------------------------------------
  1898. Function: MV_PlayLoopedWAV
  1899. Begin playback of sound data with the given sound levels and
  1900. priority.
  1901. ---------------------------------------------------------------------*/
  1902. int MV_PlayLoopedWAV
  1903. (
  1904. char *ptr,
  1905. long loopstart,
  1906. long loopend,
  1907. int pitchoffset,
  1908. int vol,
  1909. int left,
  1910. int right,
  1911. int priority,
  1912. unsigned long callbackval
  1913. )
  1914. {
  1915. riff_header *riff;
  1916. format_header *format;
  1917. data_header *data;
  1918. VoiceNode *voice;
  1919. int length;
  1920. int absloopend;
  1921. int absloopstart;
  1922. if ( !MV_Installed )
  1923. {
  1924. MV_SetErrorCode( MV_NotInstalled );
  1925. return( MV_Error );
  1926. }
  1927. riff = ( riff_header * )ptr;
  1928. if ( ( strncmp( riff->RIFF, "RIFF", 4 ) != 0 ) ||
  1929. ( strncmp( riff->WAVE, "WAVE", 4 ) != 0 ) ||
  1930. ( strncmp( riff->fmt, "fmt ", 4) != 0 ) )
  1931. {
  1932. MV_SetErrorCode( MV_InvalidWAVFile );
  1933. return( MV_Error );
  1934. }
  1935. format = ( format_header * )( riff + 1 );
  1936. data = ( data_header * )( ( ( char * )format ) + riff->format_size );
  1937. // Check if it's PCM data.
  1938. if ( format->wFormatTag != 1 )
  1939. {
  1940. MV_SetErrorCode( MV_InvalidWAVFile );
  1941. return( MV_Error );
  1942. }
  1943. if ( format->nChannels != 1 )
  1944. {
  1945. MV_SetErrorCode( MV_InvalidWAVFile );
  1946. return( MV_Error );
  1947. }
  1948. if ( ( format->nBitsPerSample != 8 ) &&
  1949. ( format->nBitsPerSample != 16 ) )
  1950. {
  1951. MV_SetErrorCode( MV_InvalidWAVFile );
  1952. return( MV_Error );
  1953. }
  1954. if ( strncmp( data->DATA, "data", 4 ) != 0 )
  1955. {
  1956. MV_SetErrorCode( MV_InvalidWAVFile );
  1957. return( MV_Error );
  1958. }
  1959. // Request a voice from the voice pool
  1960. voice = MV_AllocVoice( priority );
  1961. if ( voice == NULL )
  1962. {
  1963. MV_SetErrorCode( MV_NoVoices );
  1964. return( MV_Error );
  1965. }
  1966. voice->wavetype = WAV;
  1967. voice->bits = format->nBitsPerSample;
  1968. voice->GetSound = MV_GetNextWAVBlock;
  1969. length = data->size;
  1970. absloopstart = loopstart;
  1971. absloopend = loopend;
  1972. if ( voice->bits == 16 )
  1973. {
  1974. loopstart *= 2;
  1975. data->size &= ~1;
  1976. loopend *= 2;
  1977. length /= 2;
  1978. }
  1979. loopend = min( loopend, data->size );
  1980. absloopend = min( absloopend, length );
  1981. voice->Playing = TRUE;
  1982. voice->DemandFeed = NULL;
  1983. voice->LoopStart = NULL;
  1984. voice->LoopCount = 0;
  1985. voice->position = 0;
  1986. voice->length = 0;
  1987. voice->BlockLength = absloopend;
  1988. voice->NextBlock = ( char * )( data + 1 );
  1989. voice->next = NULL;
  1990. voice->prev = NULL;
  1991. voice->priority = priority;
  1992. voice->callbackval = callbackval;
  1993. voice->LoopStart = voice->NextBlock + loopstart;
  1994. voice->LoopEnd = voice->NextBlock + loopend;
  1995. voice->LoopSize = absloopend - absloopstart;
  1996. if ( ( loopstart >= data->size ) || ( loopstart < 0 ) )
  1997. {
  1998. voice->LoopStart = NULL;
  1999. voice->LoopEnd = NULL;
  2000. voice->BlockLength = length;
  2001. }
  2002. MV_SetVoicePitch( voice, format->nSamplesPerSec, pitchoffset );
  2003. MV_SetVoiceVolume( voice, vol, left, right );
  2004. MV_PlayVoice( voice );
  2005. return( voice->handle );
  2006. }
  2007. /*---------------------------------------------------------------------
  2008. Function: MV_PlayVOC3D
  2009. Begin playback of sound data at specified angle and distance
  2010. from listener.
  2011. ---------------------------------------------------------------------*/
  2012. int MV_PlayVOC3D
  2013. (
  2014. char *ptr,
  2015. int pitchoffset,
  2016. int angle,
  2017. int distance,
  2018. int priority,
  2019. unsigned long callbackval
  2020. )
  2021. {
  2022. int left;
  2023. int right;
  2024. int mid;
  2025. int volume;
  2026. int status;
  2027. if ( !MV_Installed )
  2028. {
  2029. MV_SetErrorCode( MV_NotInstalled );
  2030. return( MV_Error );
  2031. }
  2032. if ( distance < 0 )
  2033. {
  2034. distance = -distance;
  2035. angle += MV_NumPanPositions / 2;
  2036. }
  2037. volume = MIX_VOLUME( distance );
  2038. // Ensure angle is within 0 - 31
  2039. angle &= MV_MaxPanPosition;
  2040. left = MV_PanTable[ angle ][ volume ].left;
  2041. right = MV_PanTable[ angle ][ volume ].right;
  2042. mid = max( 0, 255 - distance );
  2043. status = MV_PlayVOC( ptr, pitchoffset, mid, left, right, priority,
  2044. callbackval );
  2045. return( status );
  2046. }
  2047. /*---------------------------------------------------------------------
  2048. Function: MV_PlayVOC
  2049. Begin playback of sound data with the given sound levels and
  2050. priority.
  2051. ---------------------------------------------------------------------*/
  2052. int MV_PlayVOC
  2053. (
  2054. char *ptr,
  2055. int pitchoffset,
  2056. int vol,
  2057. int left,
  2058. int right,
  2059. int priority,
  2060. unsigned long callbackval
  2061. )
  2062. {
  2063. int status;
  2064. status = MV_PlayLoopedVOC( ptr, -1, -1, pitchoffset, vol, left, right,
  2065. priority, callbackval );
  2066. return( status );
  2067. }
  2068. /*---------------------------------------------------------------------
  2069. Function: MV_PlayLoopedVOC
  2070. Begin playback of sound data with the given sound levels and
  2071. priority.
  2072. ---------------------------------------------------------------------*/
  2073. int MV_PlayLoopedVOC
  2074. (
  2075. char *ptr,
  2076. long loopstart,
  2077. long loopend,
  2078. int pitchoffset,
  2079. int vol,
  2080. int left,
  2081. int right,
  2082. int priority,
  2083. unsigned long callbackval
  2084. )
  2085. {
  2086. VoiceNode *voice;
  2087. int status;
  2088. if ( !MV_Installed )
  2089. {
  2090. MV_SetErrorCode( MV_NotInstalled );
  2091. return( MV_Error );
  2092. }
  2093. // Make sure it's a valid VOC file.
  2094. status = strncmp( ptr, "Creative Voice File", 19 );
  2095. if ( status != 0 )
  2096. {
  2097. MV_SetErrorCode( MV_InvalidVOCFile );
  2098. return( MV_Error );
  2099. }
  2100. // Request a voice from the voice pool
  2101. voice = MV_AllocVoice( priority );
  2102. if ( voice == NULL )
  2103. {
  2104. MV_SetErrorCode( MV_NoVoices );
  2105. return( MV_Error );
  2106. }
  2107. voice->wavetype = VOC;
  2108. voice->bits = 8;
  2109. voice->GetSound = MV_GetNextVOCBlock;
  2110. voice->NextBlock = ptr + *( unsigned short int * )( ptr + 0x14 );
  2111. voice->DemandFeed = NULL;
  2112. voice->LoopStart = NULL;
  2113. voice->LoopCount = 0;
  2114. voice->BlockLength = 0;
  2115. voice->PitchScale = PITCH_GetScale( pitchoffset );
  2116. voice->length = 0;
  2117. voice->next = NULL;
  2118. voice->prev = NULL;
  2119. voice->priority = priority;
  2120. voice->callbackval = callbackval;
  2121. voice->LoopStart = ( char * )loopstart;
  2122. voice->LoopEnd = ( char * )loopend;
  2123. voice->LoopSize = loopend - loopstart + 1;
  2124. if ( loopstart < 0 )
  2125. {
  2126. voice->LoopStart = NULL;
  2127. voice->LoopEnd = NULL;
  2128. }
  2129. MV_SetVoiceVolume( voice, vol, left, right );
  2130. MV_PlayVoice( voice );
  2131. return( voice->handle );
  2132. }
  2133. /*---------------------------------------------------------------------
  2134. Function: MV_LockEnd
  2135. Used for determining the length of the functions to lock in memory.
  2136. ---------------------------------------------------------------------*/
  2137. static void MV_LockEnd
  2138. (
  2139. void
  2140. )
  2141. {
  2142. }
  2143. /*---------------------------------------------------------------------
  2144. Function: MV_CreateVolumeTable
  2145. Create the table used to convert sound data to a specific volume
  2146. level.
  2147. ---------------------------------------------------------------------*/
  2148. void MV_CreateVolumeTable
  2149. (
  2150. int index,
  2151. int volume,
  2152. int MaxVolume
  2153. )
  2154. {
  2155. int val;
  2156. int level;
  2157. int i;
  2158. level = ( volume * MaxVolume ) / MV_MaxTotalVolume;
  2159. if ( MV_Bits == 16 )
  2160. {
  2161. for( i = 0; i < 65536; i += 256 )
  2162. {
  2163. val = i - 0x8000;
  2164. val *= level;
  2165. val /= MV_MaxVolume;
  2166. MV_VolumeTable[ index ][ i / 256 ] = val;
  2167. }
  2168. }
  2169. else
  2170. {
  2171. for( i = 0; i < 256; i++ )
  2172. {
  2173. val = i - 0x80;
  2174. val *= level;
  2175. val /= MV_MaxVolume;
  2176. MV_VolumeTable[ volume ][ i ] = val;
  2177. }
  2178. }
  2179. }
  2180. /*---------------------------------------------------------------------
  2181. Function: MV_CalcVolume
  2182. Create the table used to convert sound data to a specific volume
  2183. level.
  2184. ---------------------------------------------------------------------*/
  2185. void MV_CalcVolume
  2186. (
  2187. int MaxVolume
  2188. )
  2189. {
  2190. int volume;
  2191. for( volume = 0; volume < 128; volume++ )
  2192. {
  2193. MV_HarshClipTable[ volume ] = 0;
  2194. MV_HarshClipTable[ volume + 384 ] = 255;
  2195. }
  2196. for( volume = 0; volume < 256; volume++ )
  2197. {
  2198. MV_HarshClipTable[ volume + 128 ] = volume;
  2199. }
  2200. // For each volume level, create a translation table with the
  2201. // appropriate volume calculated.
  2202. for( volume = 0; volume <= MV_MaxVolume; volume++ )
  2203. {
  2204. MV_CreateVolumeTable( volume, volume, MaxVolume );
  2205. }
  2206. }
  2207. /*---------------------------------------------------------------------
  2208. Function: MV_CalcPanTable
  2209. Create the table used to determine the stereo volume level of
  2210. a sound located at a specific angle and distance from the listener.
  2211. ---------------------------------------------------------------------*/
  2212. void MV_CalcPanTable
  2213. (
  2214. void
  2215. )
  2216. {
  2217. int level;
  2218. int angle;
  2219. int distance;
  2220. int HalfAngle;
  2221. int ramp;
  2222. HalfAngle = ( MV_NumPanPositions / 2 );
  2223. for( distance = 0; distance <= MV_MaxVolume; distance++ )
  2224. {
  2225. level = ( 255 * ( MV_MaxVolume - distance ) ) / MV_MaxVolume;
  2226. for( angle = 0; angle <= HalfAngle / 2; angle++ )
  2227. {
  2228. ramp = level - ( ( level * angle ) /
  2229. ( MV_NumPanPositions / 4 ) );
  2230. MV_PanTable[ angle ][ distance ].left = ramp;
  2231. MV_PanTable[ HalfAngle - angle ][ distance ].left = ramp;
  2232. MV_PanTable[ HalfAngle + angle ][ distance ].left = level;
  2233. MV_PanTable[ MV_MaxPanPosition - angle ][ distance ].left = level;
  2234. MV_PanTable[ angle ][ distance ].right = level;
  2235. MV_PanTable[ HalfAngle - angle ][ distance ].right = level;
  2236. MV_PanTable[ HalfAngle + angle ][ distance ].right = ramp;
  2237. MV_PanTable[ MV_MaxPanPosition - angle ][ distance ].right = ramp;
  2238. }
  2239. }
  2240. }
  2241. /*---------------------------------------------------------------------
  2242. Function: MV_SetVolume
  2243. Sets the volume of digitized sound playback.
  2244. ---------------------------------------------------------------------*/
  2245. void MV_SetVolume
  2246. (
  2247. int volume
  2248. )
  2249. {
  2250. volume = max( 0, volume );
  2251. volume = min( volume, MV_MaxTotalVolume );
  2252. MV_TotalVolume = volume;
  2253. // Calculate volume table
  2254. MV_CalcVolume( volume );
  2255. }
  2256. /*---------------------------------------------------------------------
  2257. Function: MV_GetVolume
  2258. Returns the volume of digitized sound playback.
  2259. ---------------------------------------------------------------------*/
  2260. int MV_GetVolume
  2261. (
  2262. void
  2263. )
  2264. {
  2265. return( MV_TotalVolume );
  2266. }
  2267. /*---------------------------------------------------------------------
  2268. Function: MV_SetCallBack
  2269. Set the function to call when a voice stops.
  2270. ---------------------------------------------------------------------*/
  2271. void MV_SetCallBack
  2272. (
  2273. void ( *function )( unsigned long )
  2274. )
  2275. {
  2276. MV_CallBackFunc = function;
  2277. }
  2278. /*---------------------------------------------------------------------
  2279. Function: MV_SetReverseStereo
  2280. Set the orientation of the left and right channels.
  2281. ---------------------------------------------------------------------*/
  2282. void MV_SetReverseStereo
  2283. (
  2284. int setting
  2285. )
  2286. {
  2287. MV_SwapLeftRight = setting;
  2288. }
  2289. /*---------------------------------------------------------------------
  2290. Function: MV_GetReverseStereo
  2291. Returns the orientation of the left and right channels.
  2292. ---------------------------------------------------------------------*/
  2293. int MV_GetReverseStereo
  2294. (
  2295. void
  2296. )
  2297. {
  2298. return( MV_SwapLeftRight );
  2299. }
  2300. /*---------------------------------------------------------------------
  2301. Function: MV_TestPlayback
  2302. Checks if playback has started.
  2303. ---------------------------------------------------------------------*/
  2304. int MV_TestPlayback
  2305. (
  2306. void
  2307. )
  2308. {
  2309. unsigned flags;
  2310. long time;
  2311. int start;
  2312. int status;
  2313. int pos;
  2314. if ( MV_SoundCard == UltraSound )
  2315. {
  2316. return( MV_Ok );
  2317. }
  2318. flags = DisableInterrupts();
  2319. _enable();
  2320. status = MV_Error;
  2321. start = MV_MixPage;
  2322. time = clock() + CLOCKS_PER_SEC * 2;
  2323. while( clock() < time )
  2324. {
  2325. if ( MV_MixPage != start )
  2326. {
  2327. status = MV_Ok;
  2328. }
  2329. }
  2330. RestoreInterrupts( flags );
  2331. if ( status != MV_Ok )
  2332. {
  2333. // Just in case an error doesn't get reported
  2334. MV_SetErrorCode( MV_DMAFailure );
  2335. switch( MV_SoundCard )
  2336. {
  2337. case SoundBlaster :
  2338. case Awe32 :
  2339. pos = BLASTER_GetCurrentPos();
  2340. break;
  2341. case ProAudioSpectrum :
  2342. case SoundMan16 :
  2343. pos = PAS_GetCurrentPos();
  2344. break;
  2345. case SoundScape :
  2346. pos = SOUNDSCAPE_GetCurrentPos();
  2347. break;
  2348. #ifndef SOUNDSOURCE_OFF
  2349. case SoundSource :
  2350. case TandySoundSource :
  2351. MV_SetErrorCode( MV_SoundSourceFailure );
  2352. pos = -1;
  2353. break;
  2354. #endif
  2355. default :
  2356. MV_SetErrorCode( MV_UnsupportedCard );
  2357. pos = -2;
  2358. break;
  2359. }
  2360. if ( pos > 0 )
  2361. {
  2362. MV_SetErrorCode( MV_IrqFailure );
  2363. }
  2364. else if ( pos == 0 )
  2365. {
  2366. if ( MV_Bits == 16 )
  2367. {
  2368. MV_SetErrorCode( MV_DMA16Failure );
  2369. }
  2370. else
  2371. {
  2372. MV_SetErrorCode( MV_DMAFailure );
  2373. }
  2374. }
  2375. }
  2376. return( status );
  2377. }
  2378. /*---------------------------------------------------------------------
  2379. Function: MV_Init
  2380. Perform the initialization of variables and memory used by
  2381. Multivoc.
  2382. ---------------------------------------------------------------------*/
  2383. int MV_Init
  2384. (
  2385. int soundcard,
  2386. int MixRate,
  2387. int Voices,
  2388. int numchannels,
  2389. int samplebits
  2390. )
  2391. {
  2392. char *ptr;
  2393. int status;
  2394. int buffer;
  2395. int index;
  2396. if ( MV_Installed )
  2397. {
  2398. MV_Shutdown();
  2399. }
  2400. MV_SetErrorCode( MV_Ok );
  2401. status = MV_LockMemory();
  2402. if ( status != MV_Ok )
  2403. {
  2404. return( status );
  2405. }
  2406. MV_TotalMemory = Voices * sizeof( VoiceNode ) + sizeof( HARSH_CLIP_TABLE_8 );
  2407. status = USRHOOKS_GetMem( ( void ** )&ptr, MV_TotalMemory );
  2408. if ( status != USRHOOKS_Ok )
  2409. {
  2410. MV_UnlockMemory();
  2411. MV_SetErrorCode( MV_NoMem );
  2412. return( MV_Error );
  2413. }
  2414. status = DPMI_LockMemory( ptr, MV_TotalMemory );
  2415. if ( status != DPMI_Ok )
  2416. {
  2417. USRHOOKS_FreeMem( ptr );
  2418. MV_UnlockMemory();
  2419. MV_SetErrorCode( MV_DPMI_Error );
  2420. return( MV_Error );
  2421. }
  2422. MV_Voices = ( VoiceNode * )ptr;
  2423. MV_HarshClipTable = ptr + ( MV_TotalMemory - sizeof( HARSH_CLIP_TABLE_8 ) );
  2424. // Set number of voices before calculating volume table
  2425. MV_MaxVoices = Voices;
  2426. LL_Reset( &VoiceList, next, prev );
  2427. LL_Reset( &VoicePool, next, prev );
  2428. for( index = 0; index < Voices; index++ )
  2429. {
  2430. LL_Add( &VoicePool, &MV_Voices[ index ], next, prev );
  2431. }
  2432. // Allocate mix buffer within 1st megabyte
  2433. status = DPMI_GetDOSMemory( ( void ** )&ptr, &MV_BufferDescriptor,
  2434. 2 * TotalBufferSize );
  2435. if ( status )
  2436. {
  2437. DPMI_UnlockMemory( MV_Voices, MV_TotalMemory );
  2438. USRHOOKS_FreeMem( MV_Voices );
  2439. MV_Voices = NULL;
  2440. MV_TotalMemory = 0;
  2441. MV_UnlockMemory();
  2442. MV_SetErrorCode( MV_NoMem );
  2443. return( MV_Error );
  2444. }
  2445. MV_SetReverseStereo( FALSE );
  2446. // Initialize the sound card
  2447. switch( soundcard )
  2448. {
  2449. case UltraSound :
  2450. status = GUSWAVE_Init( 2 );
  2451. if ( status != GUSWAVE_Ok )
  2452. {
  2453. //JIM
  2454. MV_SetErrorCode( MV_BlasterError );
  2455. }
  2456. break;
  2457. case SoundBlaster :
  2458. case Awe32 :
  2459. status = BLASTER_Init();
  2460. if ( status != BLASTER_Ok )
  2461. {
  2462. MV_SetErrorCode( MV_BlasterError );
  2463. }
  2464. if ( ( BLASTER_Config.Type == SBPro ) ||
  2465. ( BLASTER_Config.Type == SBPro2 ) )
  2466. {
  2467. MV_SetReverseStereo( TRUE );
  2468. }
  2469. break;
  2470. case ProAudioSpectrum :
  2471. case SoundMan16 :
  2472. status = PAS_Init();
  2473. if ( status != PAS_Ok )
  2474. {
  2475. MV_SetErrorCode( MV_PasError );
  2476. }
  2477. break;
  2478. case SoundScape :
  2479. status = SOUNDSCAPE_Init();
  2480. if ( status != SOUNDSCAPE_Ok )
  2481. {
  2482. MV_SetErrorCode( MV_SoundScapeError );
  2483. }
  2484. break;
  2485. #ifndef SOUNDSOURCE_OFF
  2486. case SoundSource :
  2487. case TandySoundSource :
  2488. status = SS_Init( soundcard );
  2489. if ( status != SS_Ok )
  2490. {
  2491. MV_SetErrorCode( MV_SoundSourceError );
  2492. }
  2493. break;
  2494. #endif
  2495. default :
  2496. MV_SetErrorCode( MV_UnsupportedCard );
  2497. break;
  2498. }
  2499. if ( MV_ErrorCode != MV_Ok )
  2500. {
  2501. status = MV_ErrorCode;
  2502. DPMI_UnlockMemory( MV_Voices, MV_TotalMemory );
  2503. USRHOOKS_FreeMem( MV_Voices );
  2504. MV_Voices = NULL;
  2505. MV_TotalMemory = 0;
  2506. DPMI_FreeDOSMemory( MV_BufferDescriptor );
  2507. MV_UnlockMemory();
  2508. MV_SetErrorCode( status );
  2509. return( MV_Error );
  2510. }
  2511. MV_SoundCard = soundcard;
  2512. MV_Installed = TRUE;
  2513. MV_CallBackFunc = NULL;
  2514. MV_RecordFunc = NULL;
  2515. MV_Recording = FALSE;
  2516. MV_ReverbLevel = 0;
  2517. MV_ReverbTable = NULL;
  2518. // Set the sampling rate
  2519. MV_RequestedMixRate = MixRate;
  2520. // Set Mixer to play stereo digitized sound
  2521. MV_SetMixMode( numchannels, samplebits );
  2522. MV_ReverbDelay = MV_BufferSize * 3;
  2523. // Make sure we don't cross a physical page
  2524. if ( ( ( unsigned long )ptr & 0xffff ) + TotalBufferSize > 0x10000 )
  2525. {
  2526. ptr = ( char * )( ( ( unsigned long )ptr & 0xff0000 ) + 0x10000 );
  2527. }
  2528. MV_MixBuffer[ MV_NumberOfBuffers ] = ptr;
  2529. for( buffer = 0; buffer < MV_NumberOfBuffers; buffer++ )
  2530. {
  2531. MV_MixBuffer[ buffer ] = ptr;
  2532. ptr += MV_BufferSize;
  2533. }
  2534. // Calculate pan table
  2535. MV_CalcPanTable();
  2536. MV_SetVolume( MV_MaxTotalVolume );
  2537. // Start the playback engine
  2538. status = MV_StartPlayback();
  2539. if ( status != MV_Ok )
  2540. {
  2541. // Preserve error code while we shutdown.
  2542. status = MV_ErrorCode;
  2543. MV_Shutdown();
  2544. MV_SetErrorCode( status );
  2545. return( MV_Error );
  2546. }
  2547. if ( MV_TestPlayback() != MV_Ok )
  2548. {
  2549. status = MV_ErrorCode;
  2550. MV_Shutdown();
  2551. MV_SetErrorCode( status );
  2552. return( MV_Error );
  2553. }
  2554. return( MV_Ok );
  2555. }
  2556. /*---------------------------------------------------------------------
  2557. Function: MV_Shutdown
  2558. Restore any resources allocated by Multivoc back to the system.
  2559. ---------------------------------------------------------------------*/
  2560. int MV_Shutdown
  2561. (
  2562. void
  2563. )
  2564. {
  2565. int buffer;
  2566. unsigned flags;
  2567. if ( !MV_Installed )
  2568. {
  2569. return( MV_Ok );
  2570. }
  2571. flags = DisableInterrupts();
  2572. MV_KillAllVoices();
  2573. MV_Installed = FALSE;
  2574. // Stop the sound recording engine
  2575. if ( MV_Recording )
  2576. {
  2577. MV_StopRecord();
  2578. }
  2579. // Stop the sound playback engine
  2580. MV_StopPlayback();
  2581. // Shutdown the sound card
  2582. switch( MV_SoundCard )
  2583. {
  2584. case UltraSound :
  2585. GUSWAVE_Shutdown();
  2586. break;
  2587. case SoundBlaster :
  2588. case Awe32 :
  2589. BLASTER_Shutdown();
  2590. break;
  2591. case ProAudioSpectrum :
  2592. case SoundMan16 :
  2593. PAS_Shutdown();
  2594. break;
  2595. case SoundScape :
  2596. SOUNDSCAPE_Shutdown();
  2597. break;
  2598. #ifndef SOUNDSOURCE_OFF
  2599. case SoundSource :
  2600. case TandySoundSource :
  2601. SS_Shutdown();
  2602. break;
  2603. #endif
  2604. }
  2605. RestoreInterrupts( flags );
  2606. // Free any voices we allocated
  2607. DPMI_UnlockMemory( MV_Voices, MV_TotalMemory );
  2608. USRHOOKS_FreeMem( MV_Voices );
  2609. MV_Voices = NULL;
  2610. MV_TotalMemory = 0;
  2611. LL_Reset( &VoiceList, next, prev );
  2612. LL_Reset( &VoicePool, next, prev );
  2613. MV_MaxVoices = 1;
  2614. // Release the descriptor from our mix buffer
  2615. DPMI_FreeDOSMemory( MV_BufferDescriptor );
  2616. for( buffer = 0; buffer < NumberOfBuffers; buffer++ )
  2617. {
  2618. MV_MixBuffer[ buffer ] = NULL;
  2619. }
  2620. return( MV_Ok );
  2621. }
  2622. /*---------------------------------------------------------------------
  2623. Function: MV_UnlockMemory
  2624. Unlocks all neccessary data.
  2625. ---------------------------------------------------------------------*/
  2626. void MV_UnlockMemory
  2627. (
  2628. void
  2629. )
  2630. {
  2631. PITCH_UnlockMemory();
  2632. DPMI_UnlockMemoryRegion( MV_LockStart, MV_LockEnd );
  2633. DPMI_Unlock( MV_VolumeTable );
  2634. DPMI_Unlock( MV_PanTable );
  2635. DPMI_Unlock( MV_Installed );
  2636. DPMI_Unlock( MV_SoundCard );
  2637. DPMI_Unlock( MV_TotalVolume );
  2638. DPMI_Unlock( MV_MaxVoices );
  2639. DPMI_Unlock( MV_BufferSize );
  2640. DPMI_Unlock( MV_BufferLength );
  2641. DPMI_Unlock( MV_SampleSize );
  2642. DPMI_Unlock( MV_NumberOfBuffers );
  2643. DPMI_Unlock( MV_MixMode );
  2644. DPMI_Unlock( MV_Channels );
  2645. DPMI_Unlock( MV_Bits );
  2646. DPMI_Unlock( MV_Silence );
  2647. DPMI_Unlock( MV_SwapLeftRight );
  2648. DPMI_Unlock( MV_RequestedMixRate );
  2649. DPMI_Unlock( MV_MixRate );
  2650. DPMI_Unlock( MV_BufferDescriptor );
  2651. DPMI_Unlock( MV_MixBuffer );
  2652. DPMI_Unlock( MV_BufferEmpty );
  2653. DPMI_Unlock( MV_Voices );
  2654. DPMI_Unlock( VoiceList );
  2655. DPMI_Unlock( VoicePool );
  2656. DPMI_Unlock( MV_MixPage );
  2657. DPMI_Unlock( MV_VoiceHandle );
  2658. DPMI_Unlock( MV_CallBackFunc );
  2659. DPMI_Unlock( MV_RecordFunc );
  2660. DPMI_Unlock( MV_Recording );
  2661. DPMI_Unlock( MV_MixFunction );
  2662. DPMI_Unlock( MV_HarshClipTable );
  2663. DPMI_Unlock( MV_MixDestination );
  2664. DPMI_Unlock( MV_LeftVolume );
  2665. DPMI_Unlock( MV_RightVolume );
  2666. DPMI_Unlock( MV_MixPosition );
  2667. DPMI_Unlock( MV_ErrorCode );
  2668. DPMI_Unlock( MV_DMAChannel );
  2669. DPMI_Unlock( MV_BuffShift );
  2670. DPMI_Unlock( MV_ReverbLevel );
  2671. DPMI_Unlock( MV_ReverbDelay );
  2672. DPMI_Unlock( MV_ReverbTable );
  2673. }
  2674. /*---------------------------------------------------------------------
  2675. Function: MV_LockMemory
  2676. Locks all neccessary data.
  2677. ---------------------------------------------------------------------*/
  2678. int MV_LockMemory
  2679. (
  2680. void
  2681. )
  2682. {
  2683. int status;
  2684. int pitchstatus;
  2685. status = DPMI_LockMemoryRegion( MV_LockStart, MV_LockEnd );
  2686. status |= DPMI_Lock( MV_VolumeTable );
  2687. status |= DPMI_Lock( MV_PanTable );
  2688. status |= DPMI_Lock( MV_Installed );
  2689. status |= DPMI_Lock( MV_SoundCard );
  2690. status |= DPMI_Lock( MV_TotalVolume );
  2691. status |= DPMI_Lock( MV_MaxVoices );
  2692. status |= DPMI_Lock( MV_BufferSize );
  2693. status |= DPMI_Lock( MV_BufferLength );
  2694. status |= DPMI_Lock( MV_SampleSize );
  2695. status |= DPMI_Lock( MV_NumberOfBuffers );
  2696. status |= DPMI_Lock( MV_MixMode );
  2697. status |= DPMI_Lock( MV_Channels );
  2698. status |= DPMI_Lock( MV_Bits );
  2699. status |= DPMI_Lock( MV_Silence );
  2700. status |= DPMI_Lock( MV_SwapLeftRight );
  2701. status |= DPMI_Lock( MV_RequestedMixRate );
  2702. status |= DPMI_Lock( MV_MixRate );
  2703. status |= DPMI_Lock( MV_BufferDescriptor );
  2704. status |= DPMI_Lock( MV_MixBuffer );
  2705. status |= DPMI_Lock( MV_BufferEmpty );
  2706. status |= DPMI_Lock( MV_Voices );
  2707. status |= DPMI_Lock( VoiceList );
  2708. status |= DPMI_Lock( VoicePool );
  2709. status |= DPMI_Lock( MV_MixPage );
  2710. status |= DPMI_Lock( MV_VoiceHandle );
  2711. status |= DPMI_Lock( MV_CallBackFunc );
  2712. status |= DPMI_Lock( MV_RecordFunc );
  2713. status |= DPMI_Lock( MV_Recording );
  2714. status |= DPMI_Lock( MV_MixFunction );
  2715. status |= DPMI_Lock( MV_HarshClipTable );
  2716. status |= DPMI_Lock( MV_MixDestination );
  2717. status |= DPMI_Lock( MV_LeftVolume );
  2718. status |= DPMI_Lock( MV_RightVolume );
  2719. status |= DPMI_Lock( MV_MixPosition );
  2720. status |= DPMI_Lock( MV_ErrorCode );
  2721. status |= DPMI_Lock( MV_DMAChannel );
  2722. status |= DPMI_Lock( MV_BuffShift );
  2723. status |= DPMI_Lock( MV_ReverbLevel );
  2724. status |= DPMI_Lock( MV_ReverbDelay );
  2725. status |= DPMI_Lock( MV_ReverbTable );
  2726. pitchstatus = PITCH_LockMemory();
  2727. if ( ( pitchstatus != PITCH_Ok ) || ( status != DPMI_Ok ) )
  2728. {
  2729. MV_UnlockMemory();
  2730. MV_SetErrorCode( MV_DPMI_Error );
  2731. return( MV_Error );
  2732. }
  2733. return( MV_Ok );
  2734. }