MV1.C 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133
  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 "dpmi.h"
  25. #include "usrhooks.h"
  26. #include "interrup.h"
  27. #include "dpmi.h"
  28. #include "ll_man.h"
  29. #include "sndcards.h"
  30. #include "blaster.h"
  31. #include "sndsrc.h"
  32. #include "pas16.h"
  33. #include "pitch.h"
  34. #include "multivoc.h"
  35. #include "_multivc.h"
  36. static signed char MV_VolumeTable[ sizeof( VOLUME_TABLE_16BIT ) ];
  37. static VOLUME_TABLE_8BIT *MV_8BitVolumeTable = &MV_VolumeTable[ 0 ];
  38. static VOLUME_TABLE_16BIT *MV_16BitVolumeTable = &MV_VolumeTable[ 0 ];
  39. static Pan MV_PanTable[ MV_NumPanPositions ][ MV_MaxVolume + 1 ];
  40. static int MV_Installed = FALSE;
  41. static int MV_SoundCard = SoundBlaster;
  42. static int MV_TotalVolume = MV_MaxTotalVolume;
  43. static int MV_MaxVoices = 1;
  44. static int MV_BufferSize = MixBufferSize;
  45. static int MV_SampleSize = 1;
  46. static int MV_NumberOfBuffers = NumberOfBuffers;
  47. static int MV_MixMode = MONO_8BIT;
  48. static int MV_Silence = SILENCE_8BIT;
  49. static int MV_SwapLeftRight = FALSE;
  50. static int MV_RequestedMixRate;
  51. static int MV_MixRate;
  52. static int MV_BufferDescriptor;
  53. static char *MV_MixBuffer[ NumberOfBuffers ];
  54. static VoiceNode *MV_Voices = NULL;
  55. //static VoiceNode MV_Voices[ 16 ];
  56. static volatile VList VoiceList = { NULL, NULL };
  57. static volatile VList VoicePool = { NULL, NULL };
  58. static int MV_MixPage = 0;
  59. static int MV_PlayPage = 0;
  60. static int MV_VoiceHandle = MV_MinVoiceHandle;
  61. static void ( *MV_CallBackFunc )( unsigned long ) = NULL;
  62. //char HarshClipTable[ 8 * 256 ];
  63. //unsigned short HarshClipTable16[ 8 * 256 * 16 ];
  64. char *HarshClipTable;
  65. unsigned short *HarshClipTable16;
  66. short *HarshClipTable16s;
  67. int MV_ErrorCode = MV_Ok;
  68. #define MV_SetErrorCode( status ) \
  69. MV_ErrorCode = ( status );
  70. /*---------------------------------------------------------------------
  71. Function: MV_ErrorString
  72. Returns a pointer to the error message associated with an error
  73. number. A -1 returns a pointer the current error.
  74. ---------------------------------------------------------------------*/
  75. char *MV_ErrorString
  76. (
  77. int ErrorNumber
  78. )
  79. {
  80. char *ErrorString;
  81. switch( ErrorNumber )
  82. {
  83. case MV_Warning :
  84. case MV_Error :
  85. ErrorString = MV_ErrorString( MV_ErrorCode );
  86. break;
  87. case MV_Ok :
  88. ErrorString = "Multivoc ok.";
  89. break;
  90. case MV_UnsupportedCard :
  91. ErrorString = "Selected sound card is not supported by Multivoc.";
  92. break;
  93. case MV_NotInstalled :
  94. ErrorString = "Multivoc not installed.";
  95. break;
  96. case MV_NoVoices :
  97. ErrorString = "No free voices available to Multivoc.";
  98. break;
  99. case MV_NoMem :
  100. ErrorString = "Out of memory in Multivoc.";
  101. break;
  102. case MV_VoiceNotFound :
  103. ErrorString = "No voice with matching handle found.";
  104. break;
  105. case MV_BlasterError :
  106. ErrorString = BLASTER_ErrorString( BLASTER_Error );
  107. break;
  108. case MV_PasError :
  109. ErrorString = PAS_ErrorString( PAS_Error );
  110. break;
  111. #ifndef SOUNDSOURCE_OFF
  112. case MV_SoundSourceError :
  113. ErrorString = SS_ErrorString( SS_Error );
  114. break;
  115. #endif
  116. case MV_DPMI_Error :
  117. ErrorString = "DPMI Error in Multivoc.";
  118. break;
  119. default :
  120. ErrorString = "Unknown Multivoc error code.";
  121. break;
  122. }
  123. return( ErrorString );
  124. }
  125. /**********************************************************************
  126. Memory locked functions:
  127. **********************************************************************/
  128. #define MV_LockStart MV_Mix8bitMono
  129. /*---------------------------------------------------------------------
  130. Function: MV_Mix8bitMono
  131. Mixes the sound into the buffer as an 8 bit mono sample.
  132. ---------------------------------------------------------------------*/
  133. void MV_Mix8bitMono
  134. (
  135. VoiceNode *voice,
  136. int buffer
  137. )
  138. {
  139. // MONO8 *to;
  140. char *to;
  141. VOLUME8 *VolumeTable;
  142. char *start;
  143. char *from;
  144. unsigned long position;
  145. int length;
  146. unsigned long rate;
  147. int samp;
  148. to = ( MONO8 * )MV_MixBuffer[ buffer ];
  149. VolumeTable = ( VOLUME8 * )&( *MV_8BitVolumeTable )[ voice->Volume ];
  150. start = voice->sound;
  151. rate = voice->RateScale;
  152. position = voice->position;
  153. length = MixBufferSize;
  154. // Add this voice to the mix
  155. while( length > 0 )
  156. {
  157. if ( position >= voice->length )
  158. {
  159. voice->position = position;
  160. MV_GetNextVOCBlock( voice );
  161. if ( voice->Playing )
  162. {
  163. start = voice->sound;
  164. rate = voice->RateScale;
  165. position = voice->position;
  166. }
  167. else
  168. {
  169. break;
  170. }
  171. }
  172. // from = start + ( position >> 16 );
  173. // *to += ( *VolumeTable )[ *from ];
  174. from = start + ( position >> 16 );
  175. samp = ( ( int )*to ) + ( *VolumeTable )[ *from ];
  176. *to = HarshClipTable[ 4 * 256 + samp - 0x80 ];
  177. to++;
  178. position += rate;
  179. length--;
  180. }
  181. voice->position = position;
  182. }
  183. /*---------------------------------------------------------------------
  184. Function: MV_Mix8bitStereo
  185. Mixes the sound into the buffer as an 8 bit stereo sample.
  186. ---------------------------------------------------------------------*/
  187. void MV_Mix8bitStereo
  188. (
  189. VoiceNode *voice,
  190. int buffer
  191. )
  192. {
  193. STEREO8 *to;
  194. VOLUME8 *LeftVolumeTable;
  195. VOLUME8 *RightVolumeTable;
  196. char *start;
  197. unsigned long position;
  198. int length;
  199. // int sample;
  200. unsigned long rate;
  201. char *from;
  202. int samp;
  203. to = ( STEREO8 * )MV_MixBuffer[ buffer ];
  204. LeftVolumeTable = ( VOLUME8 * )&( *MV_8BitVolumeTable )[ voice->LeftVolume ];
  205. RightVolumeTable = ( VOLUME8 * )&( *MV_8BitVolumeTable )[ voice->RightVolume ];
  206. start = voice->sound;
  207. rate = voice->RateScale;
  208. position = voice->position;
  209. length = MixBufferSize;
  210. // Add this voice to the mix
  211. while( length > 0 )
  212. {
  213. if ( position >= voice->length )
  214. {
  215. voice->position = position;
  216. MV_GetNextVOCBlock( voice );
  217. if ( voice->Playing )
  218. {
  219. start = voice->sound;
  220. rate = voice->RateScale;
  221. position = voice->position;
  222. }
  223. else
  224. {
  225. break;
  226. }
  227. }
  228. // sample = ( int )*( start + ( position >> 16 ) );
  229. // to->left += ( *LeftVolumeTable )[ sample ];
  230. // to->right += ( *RightVolumeTable )[ sample ];
  231. from = start + ( position >> 16 );
  232. samp = ( ( int )to->left ) + ( *LeftVolumeTable )[ *from ];
  233. to->left = HarshClipTable[ 4 * 256 + samp - 0x80 ];
  234. samp = ( ( int )to->right ) + ( *RightVolumeTable )[ *from ];
  235. to->right = HarshClipTable[ 4 * 256 + samp - 0x80 ];
  236. to++;
  237. position += rate;
  238. length--;
  239. }
  240. voice->position = position;
  241. }
  242. /*---------------------------------------------------------------------
  243. Function: MV_Mix16bitUnsignedMono
  244. Mixes the sound into the buffer as an 16 bit mono sample.
  245. ---------------------------------------------------------------------*/
  246. void MV_Mix16bitUnsignedMono
  247. (
  248. VoiceNode *voice,
  249. int buffer
  250. )
  251. {
  252. // MONO16 *to;
  253. unsigned short *to;
  254. VOLUME16 *VolumeTable;
  255. char *start;
  256. char *from;
  257. unsigned long position;
  258. int length;
  259. unsigned long rate;
  260. int samp;
  261. // to = ( MONO16 * )MV_MixBuffer[ buffer ];
  262. to = ( unsigned short * )MV_MixBuffer[ buffer ];
  263. VolumeTable = ( VOLUME16 * )&( *MV_16BitVolumeTable )[ voice->Volume ];
  264. start = voice->sound;
  265. rate = voice->RateScale;
  266. position = voice->position;
  267. length = MixBufferSize;
  268. // Add this voice to the mix
  269. while( length > 0 )
  270. {
  271. if ( position >= voice->length )
  272. {
  273. voice->position = position;
  274. MV_GetNextVOCBlock( voice );
  275. if ( voice->Playing )
  276. {
  277. start = voice->sound;
  278. rate = voice->RateScale;
  279. position = voice->position;
  280. }
  281. else
  282. {
  283. break;
  284. }
  285. }
  286. // from = start + ( position >> 16 );
  287. // *to += ( *VolumeTable )[ *from ];
  288. from = start + ( position >> 16 );
  289. samp = ( ( *to - 0x8000 ) >> 4 ) +
  290. ( *VolumeTable )[ *from ];
  291. *to = HarshClipTable16[ 4 * 256 * 16 + samp ];// << 4;
  292. to++;
  293. position += rate;
  294. length--;
  295. }
  296. voice->position = position;
  297. }
  298. /*---------------------------------------------------------------------
  299. Function: MV_Mix16bitUnsignedStereo
  300. Mixes the sound into the buffer as an 16 bit stereo sample.
  301. ---------------------------------------------------------------------*/
  302. void MV_Mix16bitUnsignedStereo
  303. (
  304. VoiceNode *voice,
  305. int buffer
  306. )
  307. {
  308. STEREO16 *to;
  309. VOLUME16 *LeftVolumeTable;
  310. VOLUME16 *RightVolumeTable;
  311. char *start;
  312. unsigned long position;
  313. int length;
  314. // int sample;
  315. unsigned long rate;
  316. char *from;
  317. int samp;
  318. to = ( STEREO16 * )MV_MixBuffer[ buffer ];
  319. LeftVolumeTable = ( VOLUME16 * )&( *MV_16BitVolumeTable )[ voice->LeftVolume ];
  320. RightVolumeTable = ( VOLUME16 * )&( *MV_16BitVolumeTable )[ voice->RightVolume ];
  321. start = voice->sound;
  322. rate = voice->RateScale;
  323. position = voice->position;
  324. length = MixBufferSize;
  325. // Add this voice to the mix
  326. while( length > 0 )
  327. {
  328. if ( position >= voice->length )
  329. {
  330. voice->position = position;
  331. MV_GetNextVOCBlock( voice );
  332. if ( voice->Playing )
  333. {
  334. start = voice->sound;
  335. rate = voice->RateScale;
  336. position = voice->position;
  337. }
  338. else
  339. {
  340. break;
  341. }
  342. }
  343. // sample = ( int )*( start + ( position >> 16 ) );
  344. // to->left += ( *LeftVolumeTable )[ sample ];
  345. // to->right += ( *RightVolumeTable )[ sample ];
  346. from = start + ( position >> 16 );
  347. samp = ( ( to->left - 0x8000 ) >> 4 ) +
  348. ( *LeftVolumeTable )[ *from ];
  349. to->left = HarshClipTable16[ 4 * 256 * 16 + samp ];// << 4;
  350. // to->left = ( length & 127 ) << 8;
  351. samp = ( ( to->right - 0x8000 ) >> 4 ) +
  352. ( *RightVolumeTable )[ *from ];
  353. to->right = HarshClipTable16[ 4 * 256 * 16 + samp ];// << 4;
  354. // to->right = ( length & 127 ) << 8;
  355. to++;
  356. position += rate;
  357. length--;
  358. }
  359. voice->position = position;
  360. }
  361. /*---------------------------------------------------------------------
  362. Function: MV_PrepareBuffer
  363. Initializes the current buffer and mixes the currently active
  364. voices.
  365. ---------------------------------------------------------------------*/
  366. void MV_PrepareBuffer
  367. (
  368. int page
  369. )
  370. {
  371. VoiceNode *voice;
  372. // Initialize buffer
  373. ClearBuffer_DW( MV_MixBuffer[ page ], MV_Silence, MV_BufferSize >> 2 );
  374. voice = VoiceList.start;
  375. while( voice != NULL )
  376. {
  377. switch( MV_MixMode )
  378. {
  379. case MONO_8BIT :
  380. MV_Mix8bitMono( voice, page );
  381. break;
  382. case STEREO_8BIT :
  383. MV_Mix8bitStereo( voice, page );
  384. break;
  385. case MONO_16BIT :
  386. MV_Mix16bitUnsignedMono( voice, page );
  387. break;
  388. case STEREO_16BIT :
  389. MV_Mix16bitUnsignedStereo( voice, page );
  390. break;
  391. }
  392. if ( voice->Playing )
  393. {
  394. voice->Active[ page ] = TRUE;
  395. }
  396. else
  397. {
  398. voice->Active[ page ] = FALSE;
  399. }
  400. voice = voice->next;
  401. }
  402. }
  403. /*---------------------------------------------------------------------
  404. Function: MV_DeleteDeadVoices
  405. Removes any voices that have finished playing.
  406. ---------------------------------------------------------------------*/
  407. void MV_DeleteDeadVoices
  408. (
  409. int page
  410. )
  411. {
  412. VoiceNode *voice;
  413. VoiceNode *next;
  414. unsigned flags;
  415. flags = DisableInterrupts();
  416. voice = VoiceList.start;
  417. while( voice != NULL )
  418. {
  419. next = voice->next;
  420. // Is this voice done?
  421. if ( !voice->Active[ page ] )
  422. {
  423. // Yes, move it from the play list into the free list
  424. LL_Remove( VoiceNode, &VoiceList, voice );
  425. LL_AddToTail( VoiceNode, &VoicePool, voice );
  426. if ( MV_CallBackFunc )
  427. {
  428. MV_CallBackFunc( voice->callbackval );
  429. }
  430. }
  431. voice = next;
  432. }
  433. RestoreInterrupts( flags );
  434. }
  435. /*---------------------------------------------------------------------
  436. Function: MV_ServiceVoc
  437. Starts playback of the waiting buffer and mixes the next one.
  438. ---------------------------------------------------------------------*/
  439. void MV_ServiceVoc
  440. (
  441. void
  442. )
  443. {
  444. int ErasePage;
  445. ErasePage = MV_PlayPage;
  446. // Delete any voices that are done playing
  447. MV_DeleteDeadVoices( ErasePage );
  448. // Set which buffer is currently being played.
  449. MV_PlayPage = MV_MixPage;
  450. // Toggle which buffer we'll mix next
  451. MV_MixPage++;
  452. if ( MV_MixPage >= MV_NumberOfBuffers )
  453. {
  454. MV_MixPage = 0;
  455. }
  456. // Play any waiting voices
  457. MV_PrepareBuffer( MV_MixPage );
  458. }
  459. /*---------------------------------------------------------------------
  460. Function: MV_GetVoice
  461. Locates the voice with the specified handle.
  462. ---------------------------------------------------------------------*/
  463. VoiceNode *MV_GetVoice
  464. (
  465. int handle
  466. )
  467. {
  468. VoiceNode *voice;
  469. unsigned flags;
  470. flags = DisableInterrupts();
  471. voice = VoiceList.start;
  472. while( voice != NULL )
  473. {
  474. if ( handle == voice->handle )
  475. {
  476. break;
  477. }
  478. voice = voice->next;
  479. }
  480. RestoreInterrupts( flags );
  481. if ( voice == NULL )
  482. {
  483. MV_SetErrorCode( MV_VoiceNotFound );
  484. }
  485. return( voice );
  486. }
  487. /*---------------------------------------------------------------------
  488. Function: MV_VoicePlaying
  489. Checks if the voice associated with the specified handle is
  490. playing.
  491. ---------------------------------------------------------------------*/
  492. int MV_VoicePlaying
  493. (
  494. int handle
  495. )
  496. {
  497. VoiceNode *voice;
  498. if ( !MV_Installed )
  499. {
  500. MV_SetErrorCode( MV_NotInstalled );
  501. return( FALSE );
  502. }
  503. voice = MV_GetVoice( handle );
  504. if ( voice == NULL )
  505. {
  506. return( FALSE );
  507. }
  508. return( TRUE );
  509. }
  510. /*---------------------------------------------------------------------
  511. Function: MV_KillAllVoices
  512. Stops output of all currently active voices.
  513. ---------------------------------------------------------------------*/
  514. int MV_KillAllVoices
  515. (
  516. void
  517. )
  518. {
  519. if ( !MV_Installed )
  520. {
  521. MV_SetErrorCode( MV_NotInstalled );
  522. return( MV_Error );
  523. }
  524. // Remove all the voices from the list
  525. while( VoiceList.start != NULL )
  526. {
  527. MV_Kill( VoiceList.start->handle );
  528. }
  529. return( MV_Ok );
  530. }
  531. /*---------------------------------------------------------------------
  532. Function: MV_Kill
  533. Stops output of the voice associated with the specified handle.
  534. ---------------------------------------------------------------------*/
  535. int MV_Kill
  536. (
  537. int handle
  538. )
  539. {
  540. VoiceNode *voice;
  541. unsigned flags;
  542. unsigned long callbackval;
  543. if ( !MV_Installed )
  544. {
  545. MV_SetErrorCode( MV_NotInstalled );
  546. return( MV_Error );
  547. }
  548. flags = DisableInterrupts();
  549. voice = MV_GetVoice( handle );
  550. if ( voice == NULL )
  551. {
  552. RestoreInterrupts( flags );
  553. MV_SetErrorCode( MV_VoiceNotFound );
  554. return( MV_Error );
  555. }
  556. callbackval = voice->callbackval;
  557. // move the voice from the play list to the free list
  558. LL_Remove( VoiceNode, &VoiceList, voice );
  559. LL_AddToTail( VoiceNode, &VoicePool, voice );
  560. RestoreInterrupts( flags );
  561. if ( MV_CallBackFunc )
  562. {
  563. MV_CallBackFunc( callbackval );
  564. }
  565. MV_SetErrorCode( MV_Ok );
  566. return( MV_Ok );
  567. }
  568. /*---------------------------------------------------------------------
  569. Function: MV_VoicesPlaying
  570. Determines the number of currently active voices.
  571. ---------------------------------------------------------------------*/
  572. int MV_VoicesPlaying
  573. (
  574. void
  575. )
  576. {
  577. VoiceNode *voice;
  578. int NumVoices = 0;
  579. unsigned flags;
  580. if ( !MV_Installed )
  581. {
  582. MV_SetErrorCode( MV_NotInstalled );
  583. return( 0 );
  584. }
  585. flags = DisableInterrupts();
  586. voice = VoiceList.start;
  587. while( voice != NULL )
  588. {
  589. NumVoices++;
  590. voice = voice->next;
  591. }
  592. RestoreInterrupts( flags );
  593. return( NumVoices );
  594. }
  595. /*---------------------------------------------------------------------
  596. Function: MV_AllocVoice
  597. Retrieve an inactive or lower priority voice for output.
  598. ---------------------------------------------------------------------*/
  599. VoiceNode *MV_AllocVoice
  600. (
  601. int priority
  602. )
  603. {
  604. VoiceNode *voice;
  605. VoiceNode *node;
  606. unsigned flags;
  607. flags = DisableInterrupts();
  608. // Check if we have any free voices
  609. if ( VoicePool.start == NULL )
  610. {
  611. // check if we have a higher priority than a voice that is playing.
  612. node = VoiceList.start;
  613. voice = node;
  614. while( node != NULL )
  615. {
  616. if ( node->priority < voice->priority )
  617. {
  618. voice = node;
  619. }
  620. node = node->next;
  621. }
  622. if ( priority >= voice->priority )
  623. {
  624. MV_Kill( voice->handle );
  625. }
  626. }
  627. // Check if any voices are in the voice pool
  628. if ( VoicePool.start == NULL )
  629. {
  630. // No free voices
  631. RestoreInterrupts( flags );
  632. return( NULL );
  633. }
  634. voice = VoicePool.start;
  635. LL_Remove( VoiceNode, &VoicePool, voice );
  636. RestoreInterrupts( flags );
  637. // Find a free voice handle
  638. do
  639. {
  640. MV_VoiceHandle++;
  641. if ( MV_VoiceHandle < MV_MinVoiceHandle )
  642. {
  643. MV_VoiceHandle = MV_MinVoiceHandle;
  644. }
  645. }
  646. while( MV_VoicePlaying( MV_VoiceHandle ) );
  647. voice->handle = MV_VoiceHandle;
  648. return( voice );
  649. }
  650. /*---------------------------------------------------------------------
  651. Function: MV_SetPitch
  652. Sets the pitch for the voice associated with the specified handle.
  653. ---------------------------------------------------------------------*/
  654. int MV_SetPitch
  655. (
  656. int handle,
  657. int pitchoffset
  658. )
  659. {
  660. VoiceNode *voice;
  661. if ( !MV_Installed )
  662. {
  663. MV_SetErrorCode( MV_NotInstalled );
  664. return( MV_Error );
  665. }
  666. voice = MV_GetVoice( handle );
  667. if ( voice == NULL )
  668. {
  669. MV_SetErrorCode( MV_VoiceNotFound );
  670. return( MV_Error );
  671. }
  672. voice->PitchScale = PITCH_GetScale( pitchoffset );
  673. voice->RateScale = ( voice->SamplingRate *
  674. voice->PitchScale ) / MV_MixRate;
  675. MV_SetErrorCode( MV_Ok );
  676. return( MV_Ok );
  677. }
  678. /*---------------------------------------------------------------------
  679. Function: MV_SetPan
  680. Sets the stereo and mono volume level of the voice associated
  681. with the specified handle.
  682. ---------------------------------------------------------------------*/
  683. int MV_SetPan
  684. (
  685. int handle,
  686. int vol,
  687. int left,
  688. int right
  689. )
  690. {
  691. VoiceNode *voice;
  692. if ( !MV_Installed )
  693. {
  694. MV_SetErrorCode( MV_NotInstalled );
  695. return( MV_Error );
  696. }
  697. voice = MV_GetVoice( handle );
  698. if ( voice == NULL )
  699. {
  700. MV_SetErrorCode( MV_VoiceNotFound );
  701. return( MV_Warning );
  702. }
  703. voice->Volume = MIX_VOLUME( vol );
  704. if ( MV_SwapLeftRight )
  705. {
  706. // SBPro uses reversed panning
  707. voice->LeftVolume = MIX_VOLUME( right );
  708. voice->RightVolume = MIX_VOLUME( left );
  709. }
  710. else
  711. {
  712. voice->LeftVolume = MIX_VOLUME( left );
  713. voice->RightVolume = MIX_VOLUME( right );
  714. }
  715. MV_SetErrorCode( MV_Ok );
  716. return( MV_Ok );
  717. }
  718. /*---------------------------------------------------------------------
  719. Function: MV_Pan3D
  720. Set the angle and distance from the listener of the voice associated
  721. with the specified handle.
  722. ---------------------------------------------------------------------*/
  723. int MV_Pan3D
  724. (
  725. int handle,
  726. int angle,
  727. int distance
  728. )
  729. {
  730. int left;
  731. int right;
  732. int mid;
  733. int volume;
  734. int status;
  735. if ( distance < 0 )
  736. {
  737. distance = -distance;
  738. angle += MV_NumPanPositions / 2;
  739. }
  740. volume = MIX_VOLUME( distance );
  741. // Ensure angle is within 0 - 31
  742. angle &= MV_MaxPanPosition;
  743. left = MV_PanTable[ angle ][ volume ].left;
  744. right = MV_PanTable[ angle ][ volume ].right;
  745. mid = max( 0, 255 - distance );
  746. status = MV_SetPan( handle, mid, left, right );
  747. return( status );
  748. }
  749. /*---------------------------------------------------------------------
  750. Function: MV_SetMixMode
  751. Prepares Multivoc to play stereo of mono digitized sounds.
  752. ---------------------------------------------------------------------*/
  753. int MV_SetMixMode
  754. (
  755. int mode
  756. )
  757. {
  758. if ( !MV_Installed )
  759. {
  760. MV_SetErrorCode( MV_NotInstalled );
  761. return( MV_Error );
  762. }
  763. switch( MV_SoundCard )
  764. {
  765. case SoundBlaster :
  766. case Awe32 :
  767. MV_MixMode = BLASTER_SetMixMode( mode );
  768. break;
  769. case ProAudioSpectrum :
  770. case SoundMan16 :
  771. MV_MixMode = PAS_SetMixMode( mode );
  772. break;
  773. #ifndef SOUNDSOURCE_OFF
  774. case SoundSource :
  775. case TandySoundSource :
  776. MV_MixMode = SS_SetMixMode( mode );
  777. break;
  778. #endif
  779. }
  780. MV_SampleSize = sizeof( MONO8 );
  781. MV_Silence = SILENCE_8BIT;
  782. switch( MV_MixMode )
  783. {
  784. case MONO_8BIT :
  785. MV_SampleSize = sizeof( MONO8 );
  786. MV_Silence = SILENCE_8BIT;
  787. break;
  788. case STEREO_8BIT :
  789. MV_SampleSize = sizeof( STEREO8 );
  790. MV_Silence = SILENCE_8BIT;
  791. break;
  792. case MONO_16BIT :
  793. MV_SampleSize = sizeof( MONO16 );
  794. // if ( ( MV_SoundCard == ProAudioSpectrum ) ||
  795. // ( MV_SoundCard == SoundMan16 ) )
  796. // {
  797. // MV_Silence = SILENCE_16BIT_PAS;
  798. // }
  799. // else
  800. // {
  801. MV_Silence = SILENCE_16BIT;
  802. // }
  803. break;
  804. case STEREO_16BIT :
  805. MV_SampleSize = sizeof( STEREO16 );
  806. // if ( ( MV_SoundCard == ProAudioSpectrum ) ||
  807. // ( MV_SoundCard == SoundMan16 ) )
  808. // {
  809. // MV_Silence = SILENCE_16BIT_PAS;
  810. // }
  811. // else
  812. // {
  813. MV_Silence = SILENCE_16BIT;
  814. // }
  815. break;
  816. }
  817. MV_BufferSize = MixBufferSize * MV_SampleSize;
  818. MV_NumberOfBuffers = TotalBufferSize / MV_BufferSize;
  819. return( MV_Ok );
  820. }
  821. /*---------------------------------------------------------------------
  822. Function: MV_StartPlayback
  823. Starts the sound playback engine.
  824. ---------------------------------------------------------------------*/
  825. int MV_StartPlayback
  826. (
  827. void
  828. )
  829. {
  830. int status;
  831. // Initialize the buffers
  832. ClearBuffer_DW( MV_MixBuffer[ 0 ], MV_Silence, TotalBufferSize >> 2 );
  833. // Set the mix buffer variables
  834. MV_PlayPage = 0;
  835. MV_MixPage = 1;
  836. // Start playback
  837. switch( MV_SoundCard )
  838. {
  839. case SoundBlaster :
  840. case Awe32 :
  841. status = BLASTER_BeginBufferedPlayback( MV_MixBuffer[ 0 ],
  842. TotalBufferSize, MV_NumberOfBuffers,
  843. MV_RequestedMixRate, MV_MixMode, MV_ServiceVoc );
  844. if ( status != BLASTER_Ok )
  845. {
  846. MV_SetErrorCode( MV_BlasterError );
  847. return( MV_Error );
  848. }
  849. MV_MixRate = BLASTER_GetPlaybackRate();
  850. break;
  851. case ProAudioSpectrum :
  852. case SoundMan16 :
  853. status = PAS_BeginBufferedPlayback( MV_MixBuffer[ 0 ],
  854. TotalBufferSize, MV_NumberOfBuffers,
  855. MV_RequestedMixRate, MV_MixMode, MV_ServiceVoc );
  856. if ( status != PAS_Ok )
  857. {
  858. MV_SetErrorCode( MV_PasError );
  859. return( MV_Error );
  860. }
  861. MV_MixRate = PAS_GetPlaybackRate();
  862. break;
  863. #ifndef SOUNDSOURCE_OFF
  864. case SoundSource :
  865. case TandySoundSource :
  866. SS_BeginBufferedPlayback( MV_MixBuffer[ 0 ],
  867. TotalBufferSize, MV_NumberOfBuffers,
  868. MV_ServiceVoc );
  869. MV_MixRate = SS_SampleRate;
  870. break;
  871. #endif
  872. }
  873. return( MV_Ok );
  874. }
  875. /*---------------------------------------------------------------------
  876. Function: MV_StopPlayback
  877. Stops the sound playback engine.
  878. ---------------------------------------------------------------------*/
  879. void MV_StopPlayback
  880. (
  881. void
  882. )
  883. {
  884. // Stop sound playback
  885. switch( MV_SoundCard )
  886. {
  887. case SoundBlaster :
  888. case Awe32 :
  889. BLASTER_StopPlayback();
  890. break;
  891. case ProAudioSpectrum :
  892. case SoundMan16 :
  893. PAS_StopPlayback();
  894. break;
  895. #ifndef SOUNDSOURCE_OFF
  896. case SoundSource :
  897. case TandySoundSource :
  898. SS_StopPlayback();
  899. break;
  900. #endif
  901. }
  902. }
  903. /*---------------------------------------------------------------------
  904. Function: MV_StartRecording
  905. Starts the sound recording engine.
  906. ---------------------------------------------------------------------*/
  907. int MV_StartRecording
  908. (
  909. int MixRate,
  910. void ( *function )( char *ptr, int length )
  911. )
  912. {
  913. return( MV_Ok );
  914. }
  915. /*---------------------------------------------------------------------
  916. Function: MV_StopRecord
  917. Stops the sound record engine.
  918. ---------------------------------------------------------------------*/
  919. void MV_StopRecord
  920. (
  921. void
  922. )
  923. {
  924. }
  925. /*---------------------------------------------------------------------
  926. Function: MV_StartDemandFeedPlayback
  927. Plays a digitized sound from a user controlled buffering system.
  928. ---------------------------------------------------------------------*/
  929. int MV_StartDemandFeedPlayback
  930. (
  931. int MixRate,
  932. int vol,
  933. int left,
  934. int right,
  935. void ( *function )( char **ptr, unsigned long *length )
  936. )
  937. {
  938. return( MV_Ok );
  939. }
  940. /*---------------------------------------------------------------------
  941. Function: MV_GetNextVOCBlock
  942. Interperate the information of a VOC format sound file.
  943. ---------------------------------------------------------------------*/
  944. void MV_GetNextVOCBlock
  945. (
  946. VoiceNode *voice
  947. )
  948. {
  949. unsigned char *ptr;
  950. int blocktype;
  951. int lastblocktype;
  952. unsigned long blocklength;
  953. unsigned long samplespeed;
  954. unsigned int tc;
  955. int packtype;
  956. int voicemode;
  957. int done;
  958. unsigned BitsPerSample;
  959. unsigned Channels;
  960. unsigned Format;
  961. if ( voice->BlockLength > 0 )
  962. {
  963. voice->sound += 0x8000;
  964. voice->position -= 0x80000000;
  965. voice->length = min( voice->BlockLength, 0x8000 );
  966. voice->BlockLength -= voice->length;
  967. voice->length <<= 16;
  968. return;
  969. }
  970. ptr = ( unsigned char * )voice->NextBlock;
  971. voice->Playing = TRUE;
  972. done = FALSE;
  973. while( !done )
  974. {
  975. blocktype = ( int )*ptr;
  976. blocklength = ( *( unsigned long * )( ptr + 1 ) ) & 0x00ffffff;
  977. ptr += 4;
  978. voicemode = 0;
  979. lastblocktype = 0;
  980. switch( blocktype )
  981. {
  982. case 0 :
  983. // End of data
  984. voice->Playing = FALSE;
  985. done = TRUE;
  986. break;
  987. case 1 :
  988. // Sound data block
  989. if ( lastblocktype != 8 )
  990. {
  991. tc = ( unsigned int )*ptr;
  992. packtype = *( ptr + 1 );
  993. }
  994. ptr += 2;
  995. blocklength -= 2;
  996. samplespeed = 256000000L / ( 65536 - ( tc << 8 ) );
  997. // Skip packed or stereo data
  998. if ( ( packtype != 0 ) || ( voicemode != 0 ) )
  999. {
  1000. ptr += blocklength;
  1001. }
  1002. else
  1003. {
  1004. done = TRUE;
  1005. }
  1006. break;
  1007. case 2 :
  1008. // Sound continuation block
  1009. samplespeed = voice->SamplingRate;
  1010. done = TRUE;
  1011. break;
  1012. case 3 :
  1013. // Silence
  1014. // Not implimented.
  1015. ptr += blocklength;
  1016. break;
  1017. case 4 :
  1018. // Marker
  1019. // Not implimented.
  1020. ptr += blocklength;
  1021. break;
  1022. case 5 :
  1023. // ASCII string
  1024. // Not implimented.
  1025. ptr += blocklength;
  1026. break;
  1027. case 6 :
  1028. // Repeat begin
  1029. voice->LoopCount = *( unsigned short * )ptr;
  1030. ptr += blocklength;
  1031. voice->LoopStart = ptr;
  1032. break;
  1033. case 7 :
  1034. // Repeat end
  1035. ptr += blocklength;
  1036. if ( lastblocktype == 6 )
  1037. {
  1038. voice->LoopCount = 0;
  1039. }
  1040. else
  1041. {
  1042. if ( ( voice->LoopCount > 0 ) && ( voice->LoopStart != NULL ) )
  1043. {
  1044. ptr = voice->LoopStart;
  1045. if ( voice->LoopCount < 0xffff )
  1046. {
  1047. voice->LoopCount--;
  1048. if ( voice->LoopCount == 0 )
  1049. {
  1050. voice->LoopStart = NULL;
  1051. }
  1052. }
  1053. }
  1054. }
  1055. break;
  1056. case 8 :
  1057. // Extended block
  1058. tc = *( unsigned short * )ptr;
  1059. packtype = *( ptr + 2 );
  1060. voicemode = *( ptr + 3 );
  1061. ptr += blocklength;
  1062. break;
  1063. case 9 :
  1064. // New sound data block
  1065. samplespeed = *( unsigned long * )ptr;
  1066. BitsPerSample = ( unsigned )*( ptr + 4 );
  1067. Channels = ( unsigned )*( ptr + 5 );
  1068. Format = ( unsigned )*( unsigned short * )( ptr + 6 );
  1069. if ( ( BitsPerSample == 8 ) && ( Channels == 1 ) &&
  1070. ( Format == 0 ) )
  1071. {
  1072. ptr += 12;
  1073. done = TRUE;
  1074. }
  1075. else
  1076. {
  1077. ptr += blocklength;
  1078. }
  1079. break;
  1080. default :
  1081. // Unknown data. Probably not a VOC file.
  1082. voice->Playing = FALSE;
  1083. done = TRUE;
  1084. break;
  1085. }
  1086. lastblocktype = blocktype;
  1087. }
  1088. if ( voice->Playing )
  1089. {
  1090. voice->NextBlock = ptr + blocklength;
  1091. voice->sound = ptr;
  1092. voice->SamplingRate = samplespeed;
  1093. voice->RateScale = ( voice->SamplingRate * voice->PitchScale ) / MV_MixRate;
  1094. voice->position = 0;
  1095. voice->length = min( blocklength, 0x8000 );
  1096. voice->BlockLength = blocklength - voice->length;
  1097. voice->length <<= 16;
  1098. }
  1099. }
  1100. /*---------------------------------------------------------------------
  1101. Function: MV_Play
  1102. Begin playback of sound data with the given sound levels and
  1103. priority.
  1104. ---------------------------------------------------------------------*/
  1105. int MV_Play
  1106. (
  1107. char *ptr,
  1108. int pitchoffset,
  1109. int vol,
  1110. int left,
  1111. int right,
  1112. int priority,
  1113. unsigned long callbackval
  1114. )
  1115. {
  1116. VoiceNode *voice;
  1117. int buffer;
  1118. unsigned flags;
  1119. if ( !MV_Installed )
  1120. {
  1121. MV_SetErrorCode( MV_NotInstalled );
  1122. return( MV_Error );
  1123. }
  1124. // Request a voice from the voice pool
  1125. voice = MV_AllocVoice( priority );
  1126. if ( voice == NULL )
  1127. {
  1128. MV_SetErrorCode( MV_NoVoices );
  1129. return( MV_Error );
  1130. }
  1131. voice->NextBlock = ptr + *( unsigned short int * )( ptr + 0x14 );
  1132. voice->LoopStart = NULL;
  1133. voice->LoopCount = 0;
  1134. voice->BlockLength = 0;
  1135. voice->PitchScale = PITCH_GetScale( pitchoffset );
  1136. MV_GetNextVOCBlock( voice );
  1137. voice->next = NULL;
  1138. voice->prev = NULL;
  1139. for( buffer = 0; buffer < NumberOfBuffers; buffer++ )
  1140. {
  1141. voice->Active[ buffer ] = TRUE;
  1142. }
  1143. voice->Volume = MIX_VOLUME( vol );
  1144. if ( MV_SwapLeftRight )
  1145. {
  1146. // SBPro uses reversed panning
  1147. voice->LeftVolume = MIX_VOLUME( right );
  1148. voice->RightVolume = MIX_VOLUME( left );
  1149. }
  1150. else
  1151. {
  1152. voice->LeftVolume = MIX_VOLUME( left );
  1153. voice->RightVolume = MIX_VOLUME( right );
  1154. }
  1155. voice->priority = priority;
  1156. voice->callbackval = callbackval;
  1157. flags = DisableInterrupts();
  1158. LL_AddToTail( VoiceNode, &VoiceList, voice );
  1159. RestoreInterrupts( flags );
  1160. MV_SetErrorCode( MV_Ok );
  1161. return( voice->handle );
  1162. }
  1163. /*---------------------------------------------------------------------
  1164. Function: MV_Play3D
  1165. Begin playback of sound data at specified angle and distance
  1166. from listener.
  1167. ---------------------------------------------------------------------*/
  1168. int MV_Play3D
  1169. (
  1170. char *ptr,
  1171. int pitchoffset,
  1172. int angle,
  1173. int distance,
  1174. int priority,
  1175. unsigned long callbackval
  1176. )
  1177. {
  1178. int left;
  1179. int right;
  1180. int mid;
  1181. int volume;
  1182. int status;
  1183. if ( !MV_Installed )
  1184. {
  1185. MV_SetErrorCode( MV_NotInstalled );
  1186. return( MV_Error );
  1187. }
  1188. if ( distance < 0 )
  1189. {
  1190. distance = -distance;
  1191. angle += MV_NumPanPositions / 2;
  1192. }
  1193. volume = MIX_VOLUME( distance );
  1194. // Ensure angle is within 0 - 31
  1195. angle &= MV_MaxPanPosition;
  1196. left = MV_PanTable[ angle ][ volume ].left;
  1197. right = MV_PanTable[ angle ][ volume ].right;
  1198. mid = max( 0, 255 - distance );
  1199. status = MV_Play( ptr, pitchoffset, mid, left, right, priority,
  1200. callbackval );
  1201. return( status );
  1202. }
  1203. /*---------------------------------------------------------------------
  1204. Function: MV_LockEnd
  1205. Used for determining the length of the functions to lock in memory.
  1206. ---------------------------------------------------------------------*/
  1207. static void MV_LockEnd
  1208. (
  1209. void
  1210. )
  1211. {
  1212. }
  1213. /*---------------------------------------------------------------------
  1214. Function: MV_CalcVolume
  1215. Create the table used to convert sound data to a specific volume
  1216. level.
  1217. ---------------------------------------------------------------------*/
  1218. void MV_CalcVolume
  1219. (
  1220. int MaxLevel
  1221. )
  1222. {
  1223. int volume;
  1224. int val;
  1225. int level;
  1226. int rate;
  1227. int i;
  1228. unsigned flags;
  1229. flags = DisableInterrupts();
  1230. // For each volume level, create a translation table with the
  1231. // appropriate volume calculated.
  1232. rate = ( MaxLevel << 16 ) / MV_MaxVolume;
  1233. level = 0;
  1234. if ( MV_MixMode & SIXTEEN_BIT )
  1235. {
  1236. for( volume = 0; volume <= MV_MaxVolume; volume++ )
  1237. {
  1238. for( i = 0; i < 256; i++ )
  1239. {
  1240. val = i - 128;
  1241. val *= level;
  1242. // val /= MV_MaxVoices;
  1243. // val >>= 16;
  1244. val >>= 20;
  1245. ( *MV_16BitVolumeTable )[ volume ][ i ] = val;
  1246. }
  1247. level += rate;
  1248. }
  1249. /*
  1250. // if ( ( MV_SoundCard == ProAudioSpectrum ) ||
  1251. // ( MV_SoundCard == SoundMan16 ) )
  1252. {
  1253. for( volume = 0; volume < 4 * 256 * 16; volume++ )
  1254. {
  1255. HarshClipTable16s[ volume ] = -0x8000;
  1256. HarshClipTable16s[ volume + 4 * 256 * 16 ] = 0xffff - 0x8000;
  1257. }
  1258. for( volume = 0; volume < 16 * 256; volume++ )
  1259. {
  1260. HarshClipTable16s[ volume + 4 * 256 * 16 - 0x800 ] =
  1261. volume * 16 - 0x8000;
  1262. }
  1263. }
  1264. else
  1265. {
  1266. */
  1267. for( volume = 0; volume < 4 * 256 * 16; volume++ )
  1268. {
  1269. HarshClipTable16[ volume ] = 0;
  1270. HarshClipTable16[ volume + 4 * 256 * 16 ] = 0xffff;
  1271. }
  1272. for( volume = 0; volume < 16 * 256; volume++ )
  1273. {
  1274. HarshClipTable16[ volume + 4 * 256 * 16 - 0x800 ] = volume * 16;
  1275. }
  1276. // }
  1277. }
  1278. else
  1279. {
  1280. for( volume = 0; volume <= MV_MaxVolume; volume++ )
  1281. {
  1282. for( i = 0; i < 256; i++ )
  1283. {
  1284. val = i - 128;
  1285. val *= level;
  1286. // DEBUG
  1287. // val /= MV_MaxVoices;
  1288. val >>= 24;
  1289. ( *MV_8BitVolumeTable )[ volume ][ i ] = val;
  1290. }
  1291. level += rate;
  1292. }
  1293. for( volume = 0; volume < 4 * 256; volume++ )
  1294. {
  1295. HarshClipTable[ volume ] = 0;
  1296. HarshClipTable[ volume + 4 * 256 ] = 255;
  1297. }
  1298. for( volume = 0; volume < 256; volume++ )
  1299. {
  1300. HarshClipTable[ volume + 4 * 256 - 128 ] = volume;
  1301. }
  1302. }
  1303. RestoreInterrupts( flags );
  1304. }
  1305. /*---------------------------------------------------------------------
  1306. Function: MV_CalcPanTable
  1307. Create the table used to determine the stereo volume level of
  1308. a sound located at a specific angle and distance from the listener.
  1309. ---------------------------------------------------------------------*/
  1310. void MV_CalcPanTable
  1311. (
  1312. void
  1313. )
  1314. {
  1315. int level;
  1316. int angle;
  1317. int distance;
  1318. int HalfAngle;
  1319. int ramp;
  1320. HalfAngle = ( MV_NumPanPositions / 2 );
  1321. for( distance = 0; distance <= MV_MaxVolume; distance++ )
  1322. {
  1323. level = ( 255 * ( MV_MaxVolume - distance ) ) / MV_MaxVolume;
  1324. for( angle = 0; angle <= HalfAngle / 2; angle++ )
  1325. {
  1326. ramp = level - ( ( level * angle ) /
  1327. ( MV_NumPanPositions / 4 ) );
  1328. MV_PanTable[ angle ][ distance ].left = ramp;
  1329. MV_PanTable[ HalfAngle - angle ][ distance ].left = ramp;
  1330. MV_PanTable[ HalfAngle + angle ][ distance ].left = level;
  1331. MV_PanTable[ MV_MaxPanPosition - angle ][ distance ].left = level;
  1332. MV_PanTable[ angle ][ distance ].right = level;
  1333. MV_PanTable[ HalfAngle - angle ][ distance ].right = level;
  1334. MV_PanTable[ HalfAngle + angle ][ distance ].right = ramp;
  1335. MV_PanTable[ MV_MaxPanPosition - angle ][ distance ].right = ramp;
  1336. }
  1337. }
  1338. }
  1339. /*---------------------------------------------------------------------
  1340. Function: MV_SetVolume
  1341. Sets the volume of digitized sound playback.
  1342. ---------------------------------------------------------------------*/
  1343. void MV_SetVolume
  1344. (
  1345. int volume
  1346. )
  1347. {
  1348. int maxlevel;
  1349. volume = max( 0, volume );
  1350. volume = min( volume, MV_MaxTotalVolume );
  1351. MV_TotalVolume = volume;
  1352. maxlevel = ( MV_MaxLevel * volume ) / MV_MaxTotalVolume;
  1353. //printf( "maxlevel = %d\n", maxlevel );
  1354. // Calculate volume table
  1355. MV_CalcVolume( maxlevel );
  1356. }
  1357. /*---------------------------------------------------------------------
  1358. Function: MV_GetVolume
  1359. Returns the volume of digitized sound playback.
  1360. ---------------------------------------------------------------------*/
  1361. int MV_GetVolume
  1362. (
  1363. void
  1364. )
  1365. {
  1366. return( MV_TotalVolume );
  1367. }
  1368. /*---------------------------------------------------------------------
  1369. Function: MV_SetCallBack
  1370. Set the function to call when a voice stops.
  1371. ---------------------------------------------------------------------*/
  1372. void MV_SetCallBack
  1373. (
  1374. void ( *function )( unsigned long )
  1375. )
  1376. {
  1377. MV_CallBackFunc = function;
  1378. }
  1379. /*---------------------------------------------------------------------
  1380. Function: MV_Init
  1381. Perform the initialization of variables and memory used by
  1382. Multivoc.
  1383. ---------------------------------------------------------------------*/
  1384. int MV_Init
  1385. (
  1386. int soundcard,
  1387. int MixRate,
  1388. int Voices,
  1389. int MixMode
  1390. )
  1391. {
  1392. char *ptr;
  1393. int status;
  1394. int buffer;
  1395. int index;
  1396. if ( MV_Installed )
  1397. {
  1398. MV_Shutdown();
  1399. }
  1400. MV_SetErrorCode( MV_Ok );
  1401. status = MV_LockMemory();
  1402. if ( status != MV_Ok )
  1403. {
  1404. return( status );
  1405. }
  1406. status = USRHOOKS_GetMem( &MV_Voices, Voices * sizeof( VoiceNode ) );
  1407. if ( status != USRHOOKS_Ok )
  1408. {
  1409. MV_UnlockMemory();
  1410. MV_SetErrorCode( MV_NoMem );
  1411. return( MV_Error );
  1412. }
  1413. if ( MixMode & SIXTEEN_BIT )
  1414. {
  1415. status = USRHOOKS_GetMem( &HarshClipTable, sizeof( HARSH_CLIP_TABLE_16 ) );
  1416. HarshClipTable16 = ( unsigned short * )HarshClipTable;
  1417. HarshClipTable16s = ( short * )HarshClipTable;
  1418. }
  1419. else
  1420. {
  1421. status = USRHOOKS_GetMem( &HarshClipTable, sizeof( HARSH_CLIP_TABLE_8 ) );
  1422. HarshClipTable16 = ( unsigned short * )HarshClipTable;
  1423. HarshClipTable16s = ( short * )HarshClipTable;
  1424. }
  1425. if ( status != USRHOOKS_Ok )
  1426. {
  1427. USRHOOKS_FreeMem( MV_Voices );
  1428. MV_SetErrorCode( MV_NoMem );
  1429. MV_UnlockMemory();
  1430. return( MV_Error );
  1431. }
  1432. // Set number of voices before calculating volume table
  1433. MV_MaxVoices = Voices;
  1434. VoiceList.start = NULL;
  1435. VoiceList.end = NULL;
  1436. VoicePool.start = NULL;
  1437. VoicePool.end = NULL;
  1438. for( index = 0; index < Voices; index++ )
  1439. {
  1440. LL_AddToTail( VoiceNode, &VoicePool, &MV_Voices[ index ] );
  1441. }
  1442. // Allocate mix buffer within 1st megabyte
  1443. status = DPMI_GetDOSMemory( &ptr, &MV_BufferDescriptor,
  1444. 2 * TotalBufferSize );
  1445. if ( status )
  1446. {
  1447. MV_SetErrorCode( MV_NoMem );
  1448. MV_UnlockMemory();
  1449. return( MV_Error );
  1450. }
  1451. MV_SwapLeftRight = FALSE;
  1452. // Initialize the sound card
  1453. switch( soundcard )
  1454. {
  1455. case SoundBlaster :
  1456. case Awe32 :
  1457. status = BLASTER_Init();
  1458. if ( status != BLASTER_Ok )
  1459. {
  1460. MV_SetErrorCode( MV_BlasterError );
  1461. }
  1462. if ( ( BLASTER_Config.Type == SBPro ) ||
  1463. ( BLASTER_Config.Type == SBPro2 ) )
  1464. {
  1465. MV_SwapLeftRight = TRUE;
  1466. }
  1467. break;
  1468. case ProAudioSpectrum :
  1469. case SoundMan16 :
  1470. status = PAS_Init();
  1471. if ( status != PAS_Ok )
  1472. {
  1473. MV_SetErrorCode( MV_PasError );
  1474. }
  1475. break;
  1476. #ifndef SOUNDSOURCE_OFF
  1477. case SoundSource :
  1478. case TandySoundSource :
  1479. status = SS_Init( soundcard );
  1480. if ( status != SS_Ok )
  1481. {
  1482. MV_SetErrorCode( MV_SoundSourceError );
  1483. }
  1484. break;
  1485. #endif
  1486. default :
  1487. MV_SetErrorCode( MV_UnsupportedCard );
  1488. break;
  1489. }
  1490. if ( MV_ErrorCode != MV_Ok )
  1491. {
  1492. DPMI_FreeDOSMemory( MV_BufferDescriptor );
  1493. MV_UnlockMemory();
  1494. return( MV_Error );
  1495. }
  1496. MV_SoundCard = soundcard;
  1497. MV_Installed = TRUE;
  1498. MV_CallBackFunc = NULL;
  1499. // Set the sampling rate
  1500. MV_RequestedMixRate = MixRate;
  1501. // Set Mixer to play stereo digitized sound
  1502. MV_SetMixMode( MixMode );
  1503. // Make sure we don't cross a physical page
  1504. if ( ( ( unsigned long )ptr & 0xffff ) + TotalBufferSize > 0x10000 )
  1505. {
  1506. ptr = ( char * )( ( ( unsigned long )ptr & 0xff0000 ) + 0x10000 );
  1507. }
  1508. for( buffer = 0; buffer < MV_NumberOfBuffers; buffer++ )
  1509. {
  1510. MV_MixBuffer[ buffer ] = ptr;
  1511. ptr += MV_BufferSize;
  1512. }
  1513. // Calculate pan table
  1514. MV_CalcPanTable();
  1515. MV_SetVolume( MV_MaxTotalVolume );
  1516. // Init pitch scaler
  1517. PITCH_Init();
  1518. // Start the playback engine
  1519. status = MV_StartPlayback();
  1520. if ( status != MV_Ok )
  1521. {
  1522. // Preserve error code while we shutdown.
  1523. status = MV_ErrorCode;
  1524. MV_Shutdown();
  1525. MV_SetErrorCode( status );
  1526. return( MV_Error );
  1527. }
  1528. return( MV_Ok );
  1529. }
  1530. /*---------------------------------------------------------------------
  1531. Function: MV_Shutdown
  1532. Restore any resources allocated by Multivoc back to the system.
  1533. ---------------------------------------------------------------------*/
  1534. int MV_Shutdown
  1535. (
  1536. void
  1537. )
  1538. {
  1539. int buffer;
  1540. unsigned flags;
  1541. if ( !MV_Installed )
  1542. {
  1543. MV_SetErrorCode( MV_NotInstalled );
  1544. return( MV_Error );
  1545. }
  1546. flags = DisableInterrupts();
  1547. MV_KillAllVoices();
  1548. MV_Installed = FALSE;
  1549. // Stop the sound playback engine
  1550. MV_StopPlayback();
  1551. // Shutdown the sound card
  1552. switch( MV_SoundCard )
  1553. {
  1554. case SoundBlaster :
  1555. case Awe32 :
  1556. BLASTER_Shutdown();
  1557. break;
  1558. case ProAudioSpectrum :
  1559. case SoundMan16 :
  1560. PAS_Shutdown();
  1561. break;
  1562. #ifndef SOUNDSOURCE_OFF
  1563. case SoundSource :
  1564. case TandySoundSource :
  1565. SS_Shutdown();
  1566. break;
  1567. #endif
  1568. }
  1569. RestoreInterrupts( flags );
  1570. // Free any voices we allocated
  1571. USRHOOKS_FreeMem( MV_Voices );
  1572. MV_Voices = NULL;
  1573. VoiceList.start = NULL;
  1574. VoiceList.end = NULL;
  1575. VoicePool.start = NULL;
  1576. VoicePool.end = NULL;
  1577. MV_MaxVoices = 1;
  1578. // Release the descriptor from our mix buffer
  1579. DPMI_FreeDOSMemory( MV_BufferDescriptor );
  1580. for( buffer = 0; buffer < NumberOfBuffers; buffer++ )
  1581. {
  1582. MV_MixBuffer[ buffer ] = NULL;
  1583. }
  1584. return( MV_Ok );
  1585. }
  1586. /*---------------------------------------------------------------------
  1587. Function: MV_UnlockMemory
  1588. Unlocks all neccessary data.
  1589. ---------------------------------------------------------------------*/
  1590. void MV_UnlockMemory
  1591. (
  1592. void
  1593. )
  1594. {
  1595. PITCH_UnlockMemory();
  1596. DPMI_UnlockMemoryRegion( MV_LockStart, MV_LockEnd );
  1597. DPMI_Unlock( MV_VolumeTable );
  1598. DPMI_Unlock( MV_8BitVolumeTable );
  1599. DPMI_Unlock( MV_16BitVolumeTable );
  1600. DPMI_Unlock( MV_PanTable );
  1601. DPMI_Unlock( MV_Installed );
  1602. DPMI_Unlock( MV_SoundCard );
  1603. DPMI_Unlock( MV_TotalVolume );
  1604. DPMI_Unlock( MV_MaxVoices );
  1605. DPMI_Unlock( MV_BufferSize );
  1606. DPMI_Unlock( MV_SampleSize );
  1607. DPMI_Unlock( MV_NumberOfBuffers );
  1608. DPMI_Unlock( MV_MixMode );
  1609. DPMI_Unlock( MV_Silence );
  1610. DPMI_Unlock( MV_SwapLeftRight );
  1611. DPMI_Unlock( MV_RequestedMixRate );
  1612. DPMI_Unlock( MV_MixRate );
  1613. DPMI_Unlock( MV_BufferDescriptor );
  1614. DPMI_Unlock( MV_MixBuffer );
  1615. DPMI_Unlock( MV_Voices );
  1616. DPMI_Unlock( VoiceList );
  1617. DPMI_Unlock( VoicePool );
  1618. DPMI_Unlock( MV_MixPage );
  1619. DPMI_Unlock( MV_PlayPage );
  1620. DPMI_Unlock( MV_VoiceHandle );
  1621. DPMI_Unlock( MV_CallBackFunc );
  1622. DPMI_Unlock( HarshClipTable );
  1623. DPMI_Unlock( HarshClipTable16 );
  1624. DPMI_Unlock( HarshClipTable16s );
  1625. DPMI_Unlock( MV_ErrorCode );
  1626. }
  1627. /*---------------------------------------------------------------------
  1628. Function: MV_LockMemory
  1629. Locks all neccessary data.
  1630. ---------------------------------------------------------------------*/
  1631. int MV_LockMemory
  1632. (
  1633. void
  1634. )
  1635. {
  1636. int status;
  1637. int pitchstatus;
  1638. status = DPMI_LockMemoryRegion( MV_LockStart, MV_LockEnd );
  1639. status |= DPMI_Lock( MV_VolumeTable );
  1640. status |= DPMI_Lock( MV_8BitVolumeTable );
  1641. status |= DPMI_Lock( MV_16BitVolumeTable );
  1642. status |= DPMI_Lock( MV_PanTable );
  1643. status |= DPMI_Lock( MV_Installed );
  1644. status |= DPMI_Lock( MV_SoundCard );
  1645. status |= DPMI_Lock( MV_TotalVolume );
  1646. status |= DPMI_Lock( MV_MaxVoices );
  1647. status |= DPMI_Lock( MV_BufferSize );
  1648. status |= DPMI_Lock( MV_SampleSize );
  1649. status |= DPMI_Lock( MV_NumberOfBuffers );
  1650. status |= DPMI_Lock( MV_MixMode );
  1651. status |= DPMI_Lock( MV_Silence );
  1652. status |= DPMI_Lock( MV_SwapLeftRight );
  1653. status |= DPMI_Lock( MV_RequestedMixRate );
  1654. status |= DPMI_Lock( MV_MixRate );
  1655. status |= DPMI_Lock( MV_BufferDescriptor );
  1656. status |= DPMI_Lock( MV_MixBuffer );
  1657. status |= DPMI_Lock( MV_Voices );
  1658. status |= DPMI_Lock( VoiceList );
  1659. status |= DPMI_Lock( VoicePool );
  1660. status |= DPMI_Lock( MV_MixPage );
  1661. status |= DPMI_Lock( MV_PlayPage );
  1662. status |= DPMI_Lock( MV_VoiceHandle );
  1663. status |= DPMI_Lock( MV_CallBackFunc );
  1664. status |= DPMI_Lock( HarshClipTable );
  1665. status |= DPMI_Lock( HarshClipTable16 );
  1666. status |= DPMI_Lock( HarshClipTable16s );
  1667. status |= DPMI_Lock( MV_ErrorCode );
  1668. pitchstatus = PITCH_LockMemory();
  1669. if ( ( pitchstatus != PITCH_Ok ) || ( status != DPMI_Ok ) )
  1670. {
  1671. MV_UnlockMemory();
  1672. MV_SetErrorCode( MV_DPMI_Error );
  1673. return( MV_Error );
  1674. }
  1675. return( MV_Ok );
  1676. }