AUD_DSoundDriver.cpp 55 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188
  1. /*
  2. ** Command & Conquer Generals(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /********************************************************************* Code **
  19. ** **
  20. ** Westwood Studios Pacific. **
  21. ** **
  22. ** Confidential Information **
  23. ** Copyright (C) 1998 - All Rights Reserved **
  24. ** **
  25. ******************************************************************************
  26. ** **
  27. ** Project: WAUDIO Library **
  28. ** **
  29. ** Module: Audio (AUD_) **
  30. ** **
  31. ** Version: $ID$ **
  32. ** **
  33. ** File name: wn32/dsound/r2/drv_dsnd.c **
  34. ** **
  35. ** Created by: 06/26/96 TR **
  36. ** **
  37. ** Description: Audio device driver for Win'95 Direct Sound **
  38. ** **
  39. ** **
  40. ** audioLoad : load system **
  41. ** audioUnload : unload system **
  42. ** audioOpen : open a unit **
  43. ** audioClose : close a unit **
  44. ** **
  45. ** audioOpenChannel : open an audio channel **
  46. ** audioCloseChannel : close an audio channel **
  47. ** audioStart : satrt a sample **
  48. ** audioStop : stop a sample **
  49. ** audioPause : pause a sample **
  50. ** audioResume : resume a sample **
  51. ** audioCheck : check if a sample is playing **
  52. ** audioUpdate : update sample attributes **
  53. ** audioQueueIt : queue up sample to play next **
  54. ** AUD_command : driver specific command **
  55. *****************************************************************************/
  56. #include <wpaudio/altypes.h> /* Always include this header first. */
  57. #define WIN32_LEAN_AND_MEAN
  58. #include <windows.h>
  59. #pragma warning ( disable: 4706 )
  60. #pragma warning(disable:4201)
  61. #include <mmsystem.h>
  62. //
  63. // Colin: I'm taking the INITGUID stuff out here because we are now linking
  64. // the main RTS.exe to dxguid.lib, having this defined here causes duplicate
  65. // symbols when linking
  66. //
  67. // #define INITGUID // see comment above
  68. #include <dsound.h>
  69. // #undef INITGUID // see comment above
  70. #include <windows.h>
  71. #include "asimp3\mss.h"
  72. #include "asimp3\mp3dec.h"
  73. #include <wpaudio/profiler.h>
  74. #include <wpaudio/device.h>
  75. #include <wpaudio/channel.h>
  76. #include <wpaudio/thread.h>
  77. #include <wpaudio/win32.h>
  78. /*****************************************************************************
  79. ** Includes **
  80. *****************************************************************************/
  81. #include <wpaudio/driver.h> /* prototypes for driver code */
  82. /*****************************************************************************
  83. ** Externals **
  84. *****************************************************************************/
  85. /*****************************************************************************
  86. ** Defines **
  87. *****************************************************************************/
  88. #define vAUD_DRV_MAX_CHANNELS 100 /* this is arbitrary */
  89. #define vAUD_DRV_POLL_INTERVAL (SECONDS(1)/30) /* this frequency will determine the buffer sizes */
  90. #define vAUD_DRV_OVER_SAMPLE 8
  91. #define vAUD_DRV_FRAMES 4 // this must be at least 2
  92. #define vAUD_DRV_LAG_FRAMES 0 // follow behind play frame by this many frames
  93. #define vAUD_DRV_DBHALF -1000 // -10dB
  94. /*****************************************************************************
  95. ** Private Types **
  96. *****************************************************************************/
  97. #define STATE_READ_BLOCK 0
  98. #define STATE_WRITE_BLOCK 1
  99. #define STATE_DECODE_BLOCK 2
  100. #define STATE_INIT_BLOCK 3
  101. typedef struct
  102. {
  103. int previousValue;
  104. int index;
  105. } IMA_DATA;
  106. typedef struct
  107. {
  108. int idelta;
  109. short iCoef[2];
  110. } MS_DATA;
  111. typedef struct
  112. {
  113. ASISTREAM *asi;
  114. int in_pos; // start of data in in buffer
  115. } MP3_DATA;
  116. typedef int (CB_DECODE) ( struct AudioDriverChannelTag *);
  117. typedef struct _transfer
  118. {
  119. int state; // current state
  120. int next_state; //
  121. uint8 *in; // input buffer
  122. int in_bytes; // bytes to read
  123. int in_bytes_left; // bytes left to read
  124. int in_size; // current size of input buffer
  125. int in_size_needed; // required size of input buffer
  126. uint8 *out; // output buffer
  127. int out_bytes; // bytes to write
  128. int out_bytes_left; // bytes left to write
  129. int out_size; // current size of output buffer
  130. int out_size_needed; // required size of output buffer
  131. int channels; // number of channels
  132. int pending; // there is buffered data that still needs servicing
  133. int block_size;
  134. CB_DECODE *decode; // code to decode block
  135. IMA_DATA ima[2];
  136. MS_DATA ms[2];
  137. MP3_DATA mp3;
  138. } TRANSFER;
  139. typedef int (CB_TRANSFER) ( struct AudioDriverChannelTag *, uint8 *dst, int *dst_bytes, uint8 *src , int *src_bytes );
  140. typedef struct AudioDriverChannelTag
  141. {
  142. AudioChannel *chan; /* WCORE channel we belong to */
  143. volatile uint flags;
  144. /* play */
  145. volatile int pcm_pos; /* pcm playback position relative to the end of the sample */
  146. volatile uint frame; /* current frame position of play back */
  147. volatile TimeStamp last_poll; /* time of last poll */
  148. volatile TimeStamp poll_interval; /* time between polls */
  149. /* source data */
  150. volatile uint8 *src_start; /* start of source data */
  151. volatile int src_size; /* size of source (bytes) */
  152. /* transfer */
  153. volatile uint8 *src_pos; /* source sample data read pos*/
  154. volatile int src_left; /* number of bytes of source left */
  155. volatile ulong dst_pos; /* current write posistion in buffer */
  156. volatile ulong write_pos; /* current write posistion in buffer according to DS */
  157. volatile int dst_left; /* bytes left to write befor wrap round */
  158. volatile int silence_left; /* bytes of silence left to fill */
  159. int min_fill; /* debug */
  160. /* buffer */
  161. AudioFormat format; /* current buffer format */
  162. LPDIRECTSOUNDBUFFER dsbuf; /* Direct sound buffer interface */
  163. int buf_size; /* size of active area in bytes*/
  164. int frame_bytes; /* frame size in bytes */
  165. CB_TRANSFER *transfer; /* code to read sample data */
  166. TRANSFER transfer_data;
  167. volatile int next_frame_called;
  168. volatile int service_count;
  169. volatile int frames_played;
  170. volatile int original_frame;
  171. volatile int original_dst_pos;
  172. } AUD_DRV_CHAN;
  173. /*****************************************************************************
  174. ** Private Data **
  175. *****************************************************************************/
  176. static AUD_Thread *thread = NULL;
  177. static Lock drv_ref;
  178. #ifdef _DEBUG
  179. int mixer_skip = 0;
  180. #endif
  181. static AudioDriver _AUD_driver =
  182. {
  183. NULL, /* use for extended data */
  184. audioOpenChannel,
  185. audioCloseChannel,
  186. audioStart,
  187. audioStop,
  188. audioPause,
  189. audioResume,
  190. audioCheck,
  191. audioUpdate,
  192. audioQueueIt,
  193. audioLock,
  194. audioUnlock
  195. };
  196. static AudioSystemMaster _AUD_system_master =
  197. {
  198. "Direct Sound Driver V2.0",
  199. 0x0, /* reserved, do not change ! */
  200. mAUDIO_SYS_PROP_NONE,
  201. AUDIO_SYSTEM_MASTER_INIT_STATE, // do not change this !
  202. AUDIO_STAMP_SYSTEM_MASTER, // struct id, do not change this !
  203. audioLoad,
  204. audioUnload,
  205. audioOpen,
  206. audioClose,
  207. &_AUD_driver
  208. };
  209. /* direct sound */
  210. LPDIRECTSOUND AUD_sound_object = NULL;
  211. LPDIRECTSOUNDBUFFER AUD_primary_buffer = NULL;
  212. // Table was generated with the function 1000*LOG2(n/100) where n is the range 0..100
  213. // 0 = no volume, 100 = full volume, and the range is linear ( 50 is half volume).
  214. // LOG2() is log to the base 2
  215. static int AUD_log_table[101] ={ //1....2.....3......4....5......6.....7....8.....9......0
  216. -10000,-6644,-5644,-5059,-4644,-4322,-4059,-3837,-3644,-3474,
  217. -3322,-3184,-3059,-2943,-2837,-2737,-2644,-2556,-2474,-2396,
  218. -2322,-2252,-2184,-2120,-2059,-2000,-1943,-1889,-1837,-1786,
  219. -1737,-1690,-1644,-1599,-1556,-1515,-1474,-1434,-1396,-1358,
  220. -1322,-1286,-1252,-1218,-1184,-1152,-1120,-1089,-1059,-1029,
  221. -1000, -971, -943, -916, -889, -862, -837, -811, -786, -761,
  222. -737, -713, -690, -667, -644, -621, -599, -578, -556, -535,
  223. -515, -494, -474, -454, -434, -415, -396, -377, -358, -340,
  224. -322, -304, -286, -269, -252, -234, -218, -201, -184, -168,
  225. -152, -136, -120, -105, -89, -74, -59, -44, -29, -14,
  226. 0
  227. };
  228. /*****************************************************************************
  229. ** Public Data **
  230. *****************************************************************************/
  231. AudioSystemMaster *AudioSystemDSD = &_AUD_system_master;
  232. /*****************************************************************************
  233. ** Private Prototypes **
  234. *****************************************************************************/
  235. static void AUD_pcm_service ( AudioChannel *chan );
  236. static void AUD_init_buffer ( AUD_DRV_CHAN *ci );
  237. static int AUD_create_pcm_buffer ( AUD_DRV_CHAN *ci, AudioFormat *format );
  238. static void AUD_destroy_pcm_buffer ( AUD_DRV_CHAN *ci );
  239. static void AUD_set_buffer_src ( AUD_DRV_CHAN *ci );
  240. static void AUD_new_buffer_src ( AUD_DRV_CHAN *ci );
  241. static int AUD_fill_buffer ( AUD_DRV_CHAN *ci, int bytes );
  242. static void AUD_update_buffer ( AUD_DRV_CHAN *ci );
  243. static void AUD_reset_buffer ( AUD_DRV_CHAN *ci );
  244. static void AUD_channel_stop ( AudioChannel *chan );
  245. static uint AUD_get_current_frame ( AUD_DRV_CHAN *ci );
  246. static void AUD_set_wave_format ( WAVEFORMATEX *pcmwf, AudioFormat *format );
  247. static int AUD_same_format ( AudioFormat *format1, AudioFormat *format2 );
  248. static AUD_ThreadCB AUD_service_device;
  249. static int AUD_service_device ( AudioDevice *dev );
  250. static int AUD_restore_primary ( void );
  251. static int AUD_restore_buffer ( AUD_DRV_CHAN *ci );
  252. static CB_TRANSFER PCM_transfer;
  253. static CB_DECODE IMA_decode_block;
  254. static CB_DECODE MS_decode_block;
  255. //static int AUD_set_dev_format ( AudioDevice *dev, AudioFormat *format );
  256. /*****************************************************************************
  257. ** Private Functions **
  258. *****************************************************************************/
  259. /******************************************************************/
  260. /* */
  261. /* */
  262. /******************************************************************/
  263. static void transfer_init ( TRANSFER *trans )
  264. {
  265. memset ( trans, 0, sizeof (TRANSFER));
  266. }
  267. /******************************************************************/
  268. /* */
  269. /* */
  270. /******************************************************************/
  271. static void transfer_deinit ( TRANSFER *trans )
  272. {
  273. if ( trans->in )
  274. {
  275. free ( trans->in );
  276. trans->in = NULL;
  277. trans->in_size = 0;
  278. }
  279. if ( trans->out )
  280. {
  281. free ( trans->out );
  282. trans->out = NULL;
  283. trans->out_size = 0;
  284. }
  285. if ( trans->mp3.asi )
  286. {
  287. ASI_stream_close ( (HASISTREAM) trans->mp3.asi );
  288. }
  289. }
  290. /******************************************************************/
  291. /* */
  292. /* */
  293. /******************************************************************/
  294. static int NULL_transfer ( AUD_DRV_CHAN *, uint8 *, int *, uint8 *, int *)
  295. {
  296. return FALSE;
  297. }
  298. /******************************************************************/
  299. /* */
  300. /* */
  301. /******************************************************************/
  302. static int PCM_transfer ( AUD_DRV_CHAN *, uint8 *dst, int *dst_bytes, uint8 *src, int *src_bytes )
  303. {
  304. int transfer;
  305. if ( (transfer = *dst_bytes ) > *src_bytes )
  306. {
  307. transfer = *src_bytes;
  308. }
  309. if ( transfer )
  310. {
  311. memcpy ( dst, src, transfer );
  312. *dst_bytes = transfer;
  313. *src_bytes = transfer;
  314. }
  315. return TRUE;
  316. }
  317. /******************************************************************/
  318. /* */
  319. /* */
  320. /******************************************************************/
  321. static int ADPCM_transfer ( AUD_DRV_CHAN *ci, uint8 *dst, int *dst_bytes, uint8 *src, int *src_bytes )
  322. {
  323. int sbytes = 0;
  324. int dbytes = 0;
  325. int stransfered = 0;
  326. int dtransfered = 0;
  327. int bytes;
  328. int done = FALSE;
  329. TRANSFER *data = &ci->transfer_data;
  330. if ( !data->out || !data->in )
  331. {
  332. return FALSE;
  333. }
  334. if ( src_bytes )
  335. {
  336. sbytes = *src_bytes;
  337. }
  338. if ( dst_bytes )
  339. {
  340. dbytes = *dst_bytes;
  341. }
  342. while ( !done )
  343. {
  344. switch ( data->state )
  345. {
  346. case STATE_READ_BLOCK:
  347. {
  348. if ( !data->in_bytes_left || src == NULL)
  349. {
  350. // have read in the src
  351. data->state = data->next_state;
  352. data->in_bytes_left = 0;
  353. break;
  354. }
  355. // ok, read in as much as we can
  356. if ( (bytes = data->in_bytes_left ) > sbytes )
  357. {
  358. bytes = sbytes;
  359. }
  360. if ( bytes == 0 )
  361. {
  362. // no more data to read at this time
  363. done = TRUE;
  364. break;
  365. }
  366. memcpy ( &data->in[ data->in_bytes - data->in_bytes_left], src, bytes );
  367. src += bytes;
  368. stransfered+= bytes;
  369. sbytes -= bytes;
  370. data->in_bytes_left -= bytes;
  371. data->pending = TRUE;
  372. break;
  373. }
  374. case STATE_WRITE_BLOCK:
  375. {
  376. if ( !data->out_bytes_left )
  377. {
  378. // have written out to dst
  379. data->state = data->next_state;
  380. data->pending = FALSE;
  381. break;
  382. }
  383. // ok, write out as much as we can
  384. if ( (bytes = data->out_bytes_left ) > dbytes )
  385. {
  386. bytes = dbytes;
  387. }
  388. if ( bytes == 0 )
  389. {
  390. // no more data to write at this time
  391. done = TRUE;
  392. break;
  393. }
  394. memcpy ( dst, &data->out[ data->out_bytes - data->out_bytes_left], bytes );
  395. dst += bytes;
  396. dtransfered+= bytes;
  397. dbytes -= bytes;
  398. data->out_bytes_left -= bytes;
  399. break;
  400. }
  401. case STATE_DECODE_BLOCK:
  402. {
  403. if ( !data->decode ( ci ) )
  404. {
  405. return FALSE;
  406. }
  407. data->state = STATE_WRITE_BLOCK;
  408. data->out_bytes_left = data->out_bytes;
  409. data->next_state = STATE_INIT_BLOCK;
  410. break;
  411. }
  412. case STATE_INIT_BLOCK:
  413. {
  414. if ( src != NULL )
  415. {
  416. data->in_bytes = data->block_size;
  417. data->in_bytes_left = data->block_size;
  418. data->state = STATE_READ_BLOCK;
  419. data->next_state = STATE_DECODE_BLOCK;
  420. }
  421. else
  422. {
  423. done = TRUE;
  424. }
  425. break;
  426. }
  427. }
  428. }
  429. if ( src_bytes )
  430. {
  431. *src_bytes = stransfered;
  432. }
  433. if ( dst_bytes )
  434. {
  435. *dst_bytes = dtransfered;
  436. }
  437. return TRUE;
  438. }
  439. /******************************************************************/
  440. /* */
  441. /* */
  442. /******************************************************************/
  443. static S32 AILCALLBACK fetch_CB ( U32 user, void FAR *dest, S32 bytes, S32 offset)
  444. {
  445. TRANSFER *data = (TRANSFER *) user ;
  446. if ( bytes)
  447. {
  448. if ( bytes > data->in_bytes_left )
  449. {
  450. bytes = data->in_bytes_left;
  451. }
  452. memcpy ( dest, &data->in[data->mp3.in_pos], bytes);
  453. data->mp3.in_pos += bytes;
  454. data->in_bytes_left -= bytes;
  455. }
  456. return bytes;
  457. }
  458. /******************************************************************/
  459. /* */
  460. /* */
  461. /******************************************************************/
  462. static int MP3_transfer ( AUD_DRV_CHAN *ci, uint8 *dst, int *dst_bytes, uint8 *src, int *src_bytes )
  463. {
  464. int sbytes = 0;
  465. int dbytes = 0;
  466. int stransfered = 0;
  467. int dtransfered = 0;
  468. int bytes;
  469. //int done = FALSE;
  470. TRANSFER *data = &ci->transfer_data;
  471. if ( !data->in )
  472. {
  473. return FALSE;
  474. }
  475. if ( src_bytes )
  476. {
  477. sbytes = *src_bytes;
  478. }
  479. if ( dst_bytes )
  480. {
  481. dbytes = *dst_bytes;
  482. *dst_bytes = 0;
  483. }
  484. // make sure existing in data is at the start of the buffer
  485. if ( data->in_bytes_left && data->mp3.in_pos > 0 )
  486. {
  487. //copy the data down to the start of the buffer
  488. memcpy ( data->in, &data->in[data->mp3.in_pos], data->in_bytes_left );
  489. }
  490. data->mp3.in_pos = 0;
  491. // make sure the in buffer is full
  492. if ( data->in_bytes_left < data->in_size_needed && src )
  493. {
  494. // ok, read in as much as we can
  495. if ( (bytes = data->in_size_needed - data->in_bytes_left ) > sbytes )
  496. {
  497. bytes = sbytes;
  498. }
  499. if ( bytes == 0 )
  500. {
  501. // no more data to read at this time
  502. return TRUE;
  503. }
  504. memcpy ( &data->in[ data->in_bytes_left], src, bytes );
  505. src += bytes;
  506. stransfered+= bytes;
  507. sbytes -= bytes;
  508. data->in_bytes_left += bytes;
  509. data->pending = TRUE;
  510. if ( data->in_bytes_left < data->in_size_needed )
  511. {
  512. return TRUE; // not enough data to continue
  513. }
  514. }
  515. if ( !data->mp3.asi )
  516. {
  517. // start MP3 streamer
  518. if ( ! ( data->mp3.asi = (ASISTREAM *) ASI_stream_open ( (U32) data, fetch_CB, 0 )))
  519. {
  520. // bad MP3 stream
  521. return FALSE;
  522. }
  523. }
  524. // decode more of the stream
  525. if ( dbytes > 16*1024)
  526. {
  527. dbytes = 16*1024;
  528. }
  529. dtransfered = ASI_stream_process ( (HASISTREAM) data->mp3.asi, dst, dbytes );
  530. data->pending = data->in_bytes_left || (data->mp3.asi->output_cursor < data->mp3.asi->frame_size);
  531. if ( src_bytes )
  532. {
  533. *src_bytes = stransfered;
  534. }
  535. if ( dst_bytes )
  536. {
  537. *dst_bytes = dtransfered;
  538. }
  539. return dtransfered>0;
  540. }
  541. /******************************************************************/
  542. /* */
  543. /* */
  544. /******************************************************************/
  545. static int AUD_service_device ( AUD_Thread *thread, void *data )
  546. {
  547. AudioChannel *chan;
  548. AudioSearch sh;
  549. AudioDevice *dev = (AudioDevice*) data;
  550. if ( !dev )
  551. {
  552. return TRUE;
  553. }
  554. #ifdef _DEBUG
  555. if ( mixer_skip )
  556. {
  557. mixer_skip--;
  558. if ( mixer_skip < 0 )
  559. {
  560. mixer_skip = 0;
  561. }
  562. return TRUE;
  563. }
  564. #endif
  565. if ( NotLocked ( &dev->channelAccess) )
  566. {
  567. TimeStamp now = AudioGetTime () ;
  568. AudioServicePerform ( &dev->mixerUpdate, now );
  569. chan = AudioDeviceFirstChannel ( dev, &sh );
  570. while ( chan )
  571. {
  572. if ( chan->Control.Status & mAUDIO_CTRL_PLAYING )
  573. {
  574. if ( audioCheck ( chan ))
  575. {
  576. chan->drvData->poll_interval = now - chan->drvData->last_poll;
  577. chan->drvData->last_poll = now;
  578. AUD_update_buffer ( chan->drvData );
  579. }
  580. else
  581. {
  582. AUD_channel_stop ( chan );
  583. }
  584. }
  585. chan = AudioDeviceNextChannel ( &sh );
  586. }
  587. AudioDeviceService ( dev );
  588. return TRUE;
  589. }
  590. return FALSE;
  591. }
  592. /******************************************************************/
  593. /* */
  594. /* */
  595. /******************************************************************/
  596. static int AUD_same_format ( AudioFormat *f1, AudioFormat *f2 )
  597. {
  598. return ( f1->Channels == f2->Channels
  599. && f1->Rate == f2->Rate
  600. && f1->SampleWidth == f2->SampleWidth );
  601. }
  602. /******************************************************************/
  603. /* */
  604. /* */
  605. /******************************************************************/
  606. void AUD_set_wave_format ( WAVEFORMATEX *pcmwf, AudioFormat *format )
  607. {
  608. memset ( pcmwf, 0, sizeof(WAVEFORMATEX) );
  609. pcmwf->wFormatTag = WAVE_FORMAT_PCM;
  610. pcmwf->nChannels = (unsigned short ) format->Channels;
  611. pcmwf->nSamplesPerSec = format->Rate;
  612. pcmwf->nBlockAlign = (unsigned short ) format->Channels*format->SampleWidth;
  613. pcmwf->nAvgBytesPerSec = pcmwf->nSamplesPerSec * pcmwf->nBlockAlign;
  614. pcmwf->wBitsPerSample = (unsigned short ) format->SampleWidth<<3;
  615. pcmwf->cbSize = 0;
  616. }
  617. /******************************************************************/
  618. /* */
  619. /* */
  620. /******************************************************************/
  621. static int AUD_create_pcm_buffer ( AUD_DRV_CHAN *ci, AudioFormat *format )
  622. {
  623. DSBUFFERDESC desc;
  624. WAVEFORMATEX pcmwf;
  625. DBG_Function ("DSND2:AUD_create_pcm_buffer");
  626. AudioChannelSetFormat ( ci->chan, format );
  627. if ( ci->dsbuf )
  628. {
  629. if ( AUD_same_format ( &ci->format, format ) )
  630. {
  631. ci->chan->drv_format_changed = FALSE;
  632. /* we already have a buffer of the required format */
  633. return NO_ERROR;
  634. }
  635. ci->chan->drv_format_changed = TRUE;
  636. }
  637. /* we need to recreate the buffer */
  638. AUD_destroy_pcm_buffer ( ci );
  639. // Set up wave format structure.
  640. AUD_set_wave_format ( &pcmwf, format );
  641. ci->format = *format;
  642. // Set up DSBUFFERDESC structure.
  643. memset ( &desc, 0, sizeof(DSBUFFERDESC) );
  644. desc.dwSize = sizeof(DSBUFFERDESC);
  645. desc.dwFlags = (DSBCAPS_CTRLVOLUME |DSBCAPS_CTRLPAN|DSBCAPS_CTRLFREQUENCY) ; // Need default controls vol, pan, pitch
  646. /* now we work out the size that the buffer needs to be. This is based on the polling interval and
  647. the number of frames.
  648. A frame size is the that size that when played back will take X polling intervals ( over sampling). This ensures that
  649. the polling code will not miss any frames. A frame is also the minimum update size.
  650. frame size = ((bytes per second) * (poll interval per second) * over sample
  651. */
  652. ci->frame_bytes = ((pcmwf.nAvgBytesPerSec * (vAUD_DRV_POLL_INTERVAL/10) )/(TIMER_HZ/10)) * vAUD_DRV_OVER_SAMPLE;
  653. ci->frame_bytes = ((ci->frame_bytes+1024-1)/1024) * 1024;
  654. // DBGPRINTF (("Sound frame size = %d bytes\n", ci->frame_bytes ));
  655. desc.dwBufferBytes = vAUD_DRV_FRAMES * ci->frame_bytes;
  656. desc.lpwfxFormat = (LPWAVEFORMATEX)&pcmwf;
  657. // Create buffer.
  658. if ( AUD_sound_object->CreateSoundBuffer ( &desc, &ci->dsbuf, NULL) != DS_OK)
  659. {
  660. ci->dsbuf = NULL ;
  661. return ERROR_CODE_FAIL;
  662. }
  663. #ifdef _DEBUG
  664. DSBCAPS caps = {0};
  665. caps.dwSize = sizeof(caps);
  666. if ( ci->dsbuf->GetCaps ( &caps ) != DS_OK )
  667. {
  668. msg_assert ( FALSE, ("Error trying to get caps of secondary buffer"));
  669. }
  670. msg_assert ( caps.dwBufferBytes == desc.dwBufferBytes , ("Error: Asked for buffer of %d bytes, but got %d bytes", desc.dwBufferBytes, caps.dwBufferBytes ));
  671. #endif
  672. ci->buf_size = desc.dwBufferBytes;
  673. // DBGPRINTF (("Sound buffer size = %d bytes\n", ci->buf_size ));
  674. return vNO_ERROR;
  675. }
  676. /******************************************************************/
  677. /* */
  678. /* */
  679. /******************************************************************/
  680. static void AUD_destroy_pcm_buffer ( AUD_DRV_CHAN *ci )
  681. {
  682. if ( ci->dsbuf )
  683. {
  684. ci->dsbuf->Release ();
  685. ci->dsbuf = NULL;
  686. }
  687. }
  688. /******************************************************************/
  689. /* */
  690. /* */
  691. /******************************************************************/
  692. static int AUD_restore_primary ( void )
  693. {
  694. if ( AUD_primary_buffer->Restore ( ) == DS_OK )
  695. {
  696. return TRUE;
  697. }
  698. return FALSE;
  699. }
  700. /******************************************************************/
  701. /* */
  702. /* */
  703. /******************************************************************/
  704. static int AUD_restore_buffer ( AUD_DRV_CHAN *ci )
  705. {
  706. if ( ci->dsbuf->Restore () == DS_OK )
  707. {
  708. AUD_init_buffer ( ci );
  709. return TRUE;
  710. }
  711. return FALSE;
  712. }
  713. /******************************************************************/
  714. /* */
  715. /* */
  716. /******************************************************************/
  717. static uint AUD_get_current_frame ( AUD_DRV_CHAN *ci )
  718. {
  719. ulong pos;
  720. ci->dsbuf->GetCurrentPosition ( &pos, (ulong*) &ci->write_pos );
  721. return pos / ci->frame_bytes;
  722. }
  723. /******************************************************************/
  724. /* */
  725. /* */
  726. /******************************************************************/
  727. static void AUD_init_buffer ( AUD_DRV_CHAN *ci )
  728. {
  729. ci->src_left = 0;
  730. ci->pcm_pos = 0;
  731. ci->silence_left = ci->frame_bytes*4;
  732. ci->dsbuf->SetCurrentPosition ( 0 );
  733. ci->frame = AUD_get_current_frame ( ci );
  734. ci->last_poll = AudioGetTime ( );
  735. ci->min_fill = ci->buf_size;
  736. ci->dsbuf->GetCurrentPosition ( (ulong*) &ci->dst_pos, (ulong*) &ci->write_pos );
  737. ci->dst_left = ci->buf_size - ci->dst_pos;
  738. ci->service_count = 0;
  739. ci->original_frame = ci->frame;
  740. ci->frames_played = 0;
  741. ci->original_dst_pos = ci->dst_pos;
  742. }
  743. /******************************************************************/
  744. /* */
  745. /* */
  746. /******************************************************************/
  747. static void AUD_reset_buffer ( AUD_DRV_CHAN *ci )
  748. {
  749. ci->dst_pos = 0;
  750. ci->dst_left = ci->buf_size;
  751. }
  752. /******************************************************************/
  753. /* */
  754. /* */
  755. /******************************************************************/
  756. static void AUD_set_buffer_src ( AUD_DRV_CHAN *ci )
  757. {
  758. ci->next_frame_called = FALSE;
  759. ci->src_pos = (uint8 *) ci->chan->frameData;
  760. ci->src_start = (uint8 *) ci->chan->frameData;
  761. ci->src_left = ci->src_size = ci->chan->bytesInFrame;
  762. }
  763. /******************************************************************/
  764. /* */
  765. /* */
  766. /******************************************************************/
  767. static void AUD_new_buffer_src ( AUD_DRV_CHAN *ci )
  768. {
  769. AudioSample *sample = ci->chan->sample;
  770. AudioFormat *format;
  771. TRANSFER *data = &ci->transfer_data;
  772. if ( !sample )
  773. {
  774. return;
  775. }
  776. if ( !( format = ci->chan->sample->Format ) )
  777. {
  778. format = &ci->chan->Device->DefaultFormat;
  779. }
  780. #ifdef _DEBUG
  781. msg_assert ( AUD_same_format ( &ci->format, format ), ("Sample \"%s\" has incompatible format with the previous sample.\nCannot seamlessly merge samples of differing playback parameters!!", ci->chan->sample_name));
  782. #endif //_DEBUG
  783. data->out_bytes_left = 0;
  784. data->in_bytes_left = 0;
  785. data->in_bytes = 0;
  786. data->state = STATE_INIT_BLOCK;
  787. data->in_size_needed = 0;
  788. data->out_size_needed = 0;
  789. data->channels = format->Channels;
  790. data->pending = FALSE;
  791. if ( data->mp3.asi )
  792. {
  793. ASI_stream_close ( (HASISTREAM) data->mp3.asi );
  794. }
  795. data->mp3.asi = NULL;
  796. switch ( format->Compression )
  797. {
  798. case AUDIO_COMPRESS_NONE :
  799. ci->transfer = PCM_transfer;
  800. break;
  801. case AUDIO_COMPRESS_IMA_ADPCM:
  802. ci->transfer = ADPCM_transfer;
  803. data->decode = IMA_decode_block;
  804. data->block_size = format->cdata.adpcm.BlockSize;
  805. data->in_size_needed = data->block_size;
  806. data->out_size_needed = (data->block_size+32)*4;
  807. break;
  808. case AUDIO_COMPRESS_MS_ADPCM:
  809. ci->transfer = ADPCM_transfer;
  810. data->decode = MS_decode_block;
  811. data->block_size = format->cdata.adpcm.BlockSize;
  812. data->in_size_needed = data->block_size;
  813. data->out_size_needed = (data->block_size+32)*4;
  814. break;
  815. case AUDIO_COMPRESS_MP3:
  816. ci->transfer = MP3_transfer;
  817. data->in_size_needed = STREAM_BUFSIZE + 1024;
  818. data->mp3.in_pos = 0;
  819. data->in_bytes = data->in_size_needed;
  820. break;
  821. #ifdef _DEBUG
  822. default:
  823. ci->transfer = NULL_transfer;
  824. msg_assert ( FALSE , ("Unknown compression format"));
  825. break;
  826. #endif
  827. }
  828. if ( data->in_size < data->in_size_needed )
  829. {
  830. if ( data->in )
  831. {
  832. free ( data->in );
  833. }
  834. data->in = (uint8*) malloc ( data->in_size_needed );
  835. msg_assert ( data->in, ("Failed to create new in buffer"));
  836. if ( !data->in )
  837. {
  838. data->in_size = 0;
  839. }
  840. else
  841. {
  842. data->in_size = data->in_size_needed;
  843. }
  844. }
  845. if ( data->out_size < data->out_size_needed )
  846. {
  847. if ( data->out )
  848. {
  849. free ( data->out );
  850. }
  851. data->out = (uint8*) malloc ( data->out_size_needed );
  852. msg_assert ( data->out, ("Failed to create new out buffer"));
  853. if ( !data->out )
  854. {
  855. data->out_size = 0;
  856. }
  857. else
  858. {
  859. data->out_size = data->out_size_needed;
  860. }
  861. }
  862. }
  863. /******************************************************************/
  864. /* */
  865. /* */
  866. /******************************************************************/
  867. static int AUD_lock_buffer ( AUD_DRV_CHAN *ci, ulong pos, ulong transfer, uint8 **dst, ulong *bytes1, uint8 **dst2, ulong *bytes2 )
  868. {
  869. int retval;
  870. int retry_count = 3;
  871. retry:
  872. if ( (retval = ci->dsbuf->Lock ( pos, transfer, (void **) dst, bytes1, (void **)dst2, bytes2, 0)) != DS_OK )
  873. {
  874. if ( retval = DSERR_BUFFERLOST )
  875. {
  876. if ( !AUD_restore_buffer ( ci ) )
  877. {
  878. DBGPRINTF (("Failed to restore buffer\n"));
  879. return FALSE;
  880. }
  881. DBGPRINTF (("Restored buffer\n"));
  882. if ( retry_count-- )
  883. {
  884. goto retry;
  885. }
  886. }
  887. DBGPRINTF (("Failed to lock buffer\n"));
  888. return FALSE;
  889. }
  890. return TRUE;
  891. }
  892. static int AUD_fill_buffer ( AUD_DRV_CHAN *ci, int total_bytes )
  893. {
  894. ulong transfer, bytes_transfer;
  895. ulong bytes;
  896. uint8 *lpos1 = NULL,*lpos2=NULL;
  897. ulong lbytes1 = 0,lbytes2 = 0;
  898. uint8 *dst;
  899. int locked =FALSE;
  900. int result = FALSE;
  901. DBG_Function ("DSND2:AUD_fill_buffer");
  902. while ( total_bytes > 0 )
  903. {
  904. /* check for buffer wrap roun */
  905. if ( ci->dst_left <= 0)
  906. {
  907. AUD_reset_buffer ( ci );
  908. }
  909. bytes_transfer = 0;
  910. /* check for buffer overflow and adjust transfer accordingly */
  911. if ( (bytes = (ulong) total_bytes) > (ulong ) ci->dst_left )
  912. {
  913. bytes = ci->dst_left;
  914. }
  915. if ( locked )
  916. {
  917. ci->dsbuf->Unlock ( lpos1, lbytes1, lpos2, lbytes2 );
  918. locked = FALSE;
  919. }
  920. if ( !AUD_lock_buffer ( ci, ci->dst_pos, bytes, &lpos1, &lbytes1, &lpos2, &lbytes2) )
  921. {
  922. goto done;
  923. }
  924. locked = TRUE;
  925. if ( (lpos2 != NULL) || (lbytes1 != bytes) || (lbytes2 != 0))
  926. {
  927. DBGPRINTF (("Buffer management out by %d bytes\n", lbytes2));
  928. goto done;
  929. }
  930. dst = lpos1;
  931. while ( bytes )
  932. {
  933. transfer = bytes;
  934. /* is there any source data left */
  935. if ( ci->src_left == 0 )
  936. {
  937. /* call up to higher level to see if more source is going to be supplied */
  938. ci->src_left = -1; /* unless the call back adds new source we assume no more data */
  939. if ( !ci->next_frame_called )
  940. {
  941. ci->chan->drvCBNextFrame ( ci->chan );
  942. ci->next_frame_called = TRUE;
  943. }
  944. if ( !ci->chan->bytesInFrame )
  945. {
  946. // no more data for this sample
  947. if ( !ci->transfer_data.pending)
  948. {
  949. ci->chan->drvCBNextSample ( ci->chan );
  950. if ( ci->chan->bytesInFrame )
  951. {
  952. // we have a new sample
  953. AUD_new_buffer_src ( ci );
  954. }
  955. }
  956. }
  957. if ( ci->chan->bytesInFrame )
  958. {
  959. AUD_set_buffer_src ( ci );
  960. }
  961. if ( ci->src_left == 0 )
  962. {
  963. ci->src_left = -1;
  964. }
  965. }
  966. if ( ci->src_left <= 0 && !ci->transfer_data.pending )
  967. {
  968. if ( ci->chan->current_format.SampleWidth == 2)
  969. {
  970. memset ( dst, 0x0000, transfer );
  971. }
  972. else
  973. {
  974. memset ( dst, 0x80, transfer );
  975. }
  976. ci->silence_left -= transfer ;
  977. }
  978. else
  979. {
  980. int src_bytes;
  981. if ( (src_bytes = ci->src_left) <= 0 )
  982. {
  983. // flush buffered transfer
  984. if ( !ci->transfer ( ci, dst, (int*) &transfer, NULL, NULL ) )
  985. {
  986. goto done;
  987. }
  988. src_bytes = 0;
  989. ci->src_left = 0; // try to read more source
  990. }
  991. else
  992. {
  993. if ( !ci->transfer ( ci, dst, (int*) &transfer, (uint8 *)ci->src_pos, &src_bytes ) )
  994. {
  995. goto done;
  996. }
  997. }
  998. ci->src_pos+= src_bytes;
  999. ci->src_left -= src_bytes;
  1000. ci->pcm_pos += transfer;
  1001. }
  1002. dst += transfer;
  1003. ci->dst_pos += transfer;
  1004. ci->dst_left -= transfer;
  1005. bytes -= transfer;
  1006. bytes_transfer += transfer;
  1007. }
  1008. total_bytes -= bytes_transfer;
  1009. }
  1010. result = TRUE;
  1011. done:
  1012. if ( locked )
  1013. {
  1014. ci->dsbuf->Unlock ( lpos1, lbytes1, lpos2, lbytes2 );
  1015. locked = FALSE;
  1016. }
  1017. return result;
  1018. }
  1019. /******************************************************************/
  1020. /* */
  1021. /* */
  1022. /******************************************************************/
  1023. static void AUD_update_buffer ( AUD_DRV_CHAN *ci )
  1024. {
  1025. uint frame;
  1026. int dif;
  1027. int filled;
  1028. frame = AUD_get_current_frame ( ci );
  1029. if ( ( dif = (frame - ci->frame )))
  1030. {
  1031. /* pcm address has moved on */
  1032. if ( dif < 0 )
  1033. {
  1034. /* pcm has wraped round to start of buffer */
  1035. dif = frame + (vAUD_DRV_FRAMES - ci->frame);
  1036. }
  1037. if ( (dif -= vAUD_DRV_LAG_FRAMES ) > 0 )
  1038. {
  1039. if ( (ci->frame += dif) >= vAUD_DRV_FRAMES)
  1040. {
  1041. ci->frame %= vAUD_DRV_FRAMES;
  1042. }
  1043. ci->frames_played += dif;
  1044. dif = dif * ci->frame_bytes;
  1045. filled = AUD_fill_buffer ( ci, dif );
  1046. if ( ci->min_fill > dif )
  1047. {
  1048. ci->min_fill = dif;
  1049. }
  1050. if ( (ci->pcm_pos -= dif) <=0 || !filled )
  1051. {
  1052. ci->dsbuf->Stop();
  1053. }
  1054. }
  1055. }
  1056. ci->service_count++;
  1057. }
  1058. /******************************************************************/
  1059. /* */
  1060. /* */
  1061. /******************************************************************/
  1062. static void AUD_channel_stop ( AudioChannel *chan )
  1063. {
  1064. AUD_DRV_CHAN *ci;
  1065. ci = (AUD_DRV_CHAN *) chan->drvData;
  1066. /* put stop call here */
  1067. if ( ci->dsbuf )
  1068. {
  1069. ci->dsbuf->Stop();
  1070. }
  1071. if ( chan->drvCBSampleDone )
  1072. {
  1073. chan->drvCBSampleDone ( chan );
  1074. }
  1075. }
  1076. /******************************************************************/
  1077. /* */
  1078. /* */
  1079. /******************************************************************/
  1080. static int audioLoad ( AudioSystem *system )
  1081. {
  1082. int result;
  1083. ASI_startup();
  1084. result = DirectSoundCreate(NULL, &AUD_sound_object, NULL);
  1085. if (result != DS_OK)
  1086. {
  1087. //Print_Sound_Error(Fetch_String(TXT_DSOUND_NO_COOP) );
  1088. return ERROR_CODE_FAIL;
  1089. }
  1090. assert ( AUD_sound_object );
  1091. result = AUD_sound_object->SetCooperativeLevel( AudioGetWindowsHandle () , DSSCL_PRIORITY);
  1092. system->numUnits = 1; /* tell WCORE that there is only 1 audio unit */
  1093. if ( !thread )
  1094. {
  1095. LockInit ( &drv_ref );
  1096. if (!(thread = AUD_ThreadCreate ( "Audio Service Thread", AUD_THREAD_PRI_REALTIME, AUD_service_device )) )
  1097. {
  1098. return ERROR_CODE_FAIL;
  1099. }
  1100. LockAcquire ( &drv_ref );
  1101. AUD_ThreadSetInterval ( thread, vAUD_DRV_POLL_INTERVAL );
  1102. }
  1103. else
  1104. {
  1105. LockAcquire ( &drv_ref );
  1106. }
  1107. return vNO_ERROR;
  1108. }
  1109. /******************************************************************/
  1110. /* */
  1111. /* */
  1112. /******************************************************************/
  1113. static void audioUnload ( AudioSystem * )
  1114. {
  1115. /* put in code to uninitialize audio system */
  1116. if ( AUD_sound_object )
  1117. {
  1118. AUD_sound_object->Release();
  1119. AUD_sound_object = NULL ;
  1120. }
  1121. if ( thread )
  1122. {
  1123. LockRelease ( &drv_ref );
  1124. if ( NotLocked ( &drv_ref ))
  1125. {
  1126. AUD_ThreadDestroy ( thread );
  1127. thread = NULL;
  1128. }
  1129. }
  1130. ASI_shutdown ();
  1131. }
  1132. /******************************************************************/
  1133. /* */
  1134. /* */
  1135. /******************************************************************/
  1136. static int audioOpen ( AudioDevice *dev )
  1137. {
  1138. /* put in code to instance a device */
  1139. dev->maxChannels = vAUD_DRV_MAX_CHANNELS;
  1140. AudioServiceSetInterval ( &dev->mixerUpdate, vAUD_DRV_POLL_INTERVAL );
  1141. AudioServiceSetMustServiceInterval ( &dev->mixerUpdate, vAUD_DRV_POLL_INTERVAL * vAUD_DRV_OVER_SAMPLE * vAUD_DRV_FRAMES );
  1142. AudioServiceSetResetInterval ( &dev->mixerUpdate, vAUD_DRV_POLL_INTERVAL * vAUD_DRV_OVER_SAMPLE * vAUD_DRV_FRAMES * 3 );
  1143. AUD_ThreadSetData ( thread, dev);
  1144. /* start the primary buffer playing */
  1145. {
  1146. DSBUFFERDESC dsbdesc;
  1147. WAVEFORMATEX pcmwf;
  1148. AUD_set_wave_format ( &pcmwf, &dev->DefaultFormat );
  1149. memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); // Zero it out.
  1150. dsbdesc.dwSize = sizeof(DSBUFFERDESC);
  1151. dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER;
  1152. dsbdesc.dwBufferBytes = 0;
  1153. if ( AUD_sound_object->CreateSoundBuffer ( &dsbdesc, &AUD_primary_buffer, NULL) != DS_OK )
  1154. {
  1155. AUD_primary_buffer = NULL;
  1156. return ERROR_CODE_FAIL;
  1157. }
  1158. if ( AUD_primary_buffer->SetFormat ( &pcmwf ) != DS_OK )
  1159. {
  1160. DBGPRINTF (("Unable to set the desired primary format\n"));
  1161. }
  1162. DSCAPS caps = {0};
  1163. caps.dwSize = sizeof( caps );
  1164. AUD_sound_object->GetCaps ( &caps );
  1165. if (caps.dwFlags & DSCAPS_EMULDRIVER)
  1166. {
  1167. //msg_assert ( FALSE, ("Audio Emulation"));
  1168. }
  1169. AUD_primary_buffer->Play ( 0, 0, DSBPLAY_LOOPING );
  1170. }
  1171. dev->frames = vAUD_DRV_FRAMES;
  1172. dev->over_sample = vAUD_DRV_OVER_SAMPLE;
  1173. dev->frame_lag = vAUD_DRV_LAG_FRAMES;
  1174. return vNO_ERROR;
  1175. }
  1176. /******************************************************************/
  1177. /* */
  1178. /* */
  1179. /******************************************************************/
  1180. static void audioClose ( AudioDevice * )
  1181. {
  1182. /* put in code to close up a device */
  1183. AUD_ThreadSetData ( thread, NULL );
  1184. if ( AUD_primary_buffer )
  1185. {
  1186. AUD_primary_buffer->Stop ();
  1187. AUD_primary_buffer->Release ();
  1188. AUD_primary_buffer = NULL;
  1189. }
  1190. }
  1191. /******************************************************************/
  1192. /* */
  1193. /* */
  1194. /******************************************************************/
  1195. static int audioOpenChannel ( AudioChannel *chan )
  1196. {
  1197. AUD_DRV_CHAN *ci;
  1198. DBG_Function ("DSND2:audioOpenChannel");
  1199. /* put in code to instance a channel */
  1200. MEM_ALLOC_STRUCT ( ci, AUD_DRV_CHAN, vMEM_ANY|mMEM_INTERNAL );
  1201. chan->drvData = ci;
  1202. ci->chan = chan;
  1203. chan->time_min_frame = vAUD_DRV_POLL_INTERVAL * vAUD_DRV_OVER_SAMPLE;
  1204. chan->time_buffer = vAUD_DRV_FRAMES * chan->time_min_frame;
  1205. transfer_init ( &ci->transfer_data );
  1206. AudioChannelSetFormat ( ci->chan, &ci->chan->Device->DefaultFormat ); /* initially create sound buffer with default format */
  1207. return vNO_ERROR;
  1208. }
  1209. /******************************************************************/
  1210. /* */
  1211. /* */
  1212. /******************************************************************/
  1213. static int audioCloseChannel ( AudioChannel *chan )
  1214. {
  1215. AUD_DRV_CHAN *ci;
  1216. DBG_Function ("DSND2:audioCloseChannel");
  1217. /* put in code to close a channel*/
  1218. if ( (ci = chan->drvData) )
  1219. {
  1220. transfer_deinit ( &ci->transfer_data );
  1221. AUD_destroy_pcm_buffer ( ci );
  1222. MEM_Free ( ci );
  1223. chan->drvData = NULL;
  1224. }
  1225. return vNO_ERROR;
  1226. }
  1227. /******************************************************************/
  1228. /* */
  1229. /* */
  1230. /******************************************************************/
  1231. static int audioStart ( AudioChannel *chan )
  1232. {
  1233. AUD_DRV_CHAN *ci;
  1234. AudioFormat *format;
  1235. AudioSample *sample;
  1236. DBG_Function ("DSND2:audioStart");
  1237. DBG_ASSERT ( !audioCheck ( chan ));
  1238. ci = chan->drvData;
  1239. sample = chan->sample;
  1240. if ( !( format = sample->Format ) )
  1241. {
  1242. format = &chan->Device->DefaultFormat;
  1243. }
  1244. /* recreate buffer if format changed */
  1245. if ( AUD_create_pcm_buffer ( ci, format ) != vNO_ERROR)
  1246. {
  1247. DBGPRINTF (("Failed to create playback buffer\n"));
  1248. return ERROR_CODE_FAIL;
  1249. }
  1250. AUD_init_buffer ( ci ); /* initialise buffer for play back */
  1251. AUD_new_buffer_src ( ci );
  1252. AUD_set_buffer_src ( ci ); /* attach source to buffer */
  1253. if ( !AUD_fill_buffer ( ci, ci->buf_size )) /* pre-fill buffer to max */
  1254. {
  1255. DBGPRINTF (( "Failed to prefill buffer\n"));
  1256. return ERROR_CODE_FAIL;
  1257. }
  1258. /* update buffer attributes */
  1259. audioUpdate ( chan );
  1260. /* start playing */
  1261. if ( ci->dsbuf->Play ( 0, 0, DSBPLAY_LOOPING ) != DS_OK) /* must do looping or things will go horribly wrong */
  1262. {
  1263. DBGPRINTF (("Failed to start playback\n"));
  1264. return ERROR_CODE_FAIL;
  1265. }
  1266. DBG_ASSERT ( audioCheck ( chan ));
  1267. return vNO_ERROR;
  1268. }
  1269. /******************************************************************/
  1270. /* */
  1271. /* */
  1272. /******************************************************************/
  1273. static int audioStop ( AudioChannel *chan )
  1274. {
  1275. if ( chan->Control.Status & (mAUDIO_CTRL_ACTIVE) )
  1276. {
  1277. AUD_channel_stop ( chan );
  1278. }
  1279. return vNO_ERROR;
  1280. }
  1281. /******************************************************************/
  1282. /* */
  1283. /* */
  1284. /******************************************************************/
  1285. static int audioPause ( AudioChannel *chan )
  1286. {
  1287. AUD_DRV_CHAN *ci = chan->drvData;
  1288. if ( ci->dsbuf )
  1289. {
  1290. ci->dsbuf->Stop ();
  1291. }
  1292. return vNO_ERROR;
  1293. }
  1294. /******************************************************************/
  1295. /* */
  1296. /* */
  1297. /******************************************************************/
  1298. static int audioResume ( AudioChannel *chan )
  1299. {
  1300. AUD_DRV_CHAN *ci = chan->drvData;
  1301. if ( ci->dsbuf )
  1302. {
  1303. if ( ci->dsbuf->Play ( 0, 0, DSBPLAY_LOOPING ) == DS_OK) /* must do looping or things will go horribly wrong */
  1304. {
  1305. return vNO_ERROR;
  1306. }
  1307. }
  1308. return ERROR_CODE_FAIL;
  1309. }
  1310. /******************************************************************/
  1311. /* */
  1312. /* */
  1313. /******************************************************************/
  1314. static int audioCheck ( AudioChannel *chan )
  1315. {
  1316. AUD_DRV_CHAN *ci = chan->drvData;
  1317. DWORD status;
  1318. if ( ci->dsbuf && (ci->dsbuf->GetStatus ( &status ) == DS_OK) )
  1319. {
  1320. if ( status & (DSBSTATUS_PLAYING|DSBSTATUS_LOOPING) == (DSBSTATUS_PLAYING|DSBSTATUS_LOOPING) )
  1321. {
  1322. return TRUE;
  1323. }
  1324. else
  1325. {
  1326. return FALSE;
  1327. }
  1328. }
  1329. return FALSE;
  1330. }
  1331. /******************************************************************/
  1332. /* */
  1333. /* */
  1334. /******************************************************************/
  1335. static int audioUpdate ( AudioChannel *chan )
  1336. {
  1337. AUD_DRV_CHAN *ci;
  1338. int vol;
  1339. int pitch;
  1340. HRESULT stat;
  1341. ci = chan->drvData;
  1342. vol = AudioLevelApply ( &chan->attribs.VolumeLevel, 100 );
  1343. ci->dsbuf->SetVolume ( AUD_log_table[vol]);
  1344. #if 1
  1345. {
  1346. int pos;
  1347. pos = AudioLevelApply ( &chan->attribs.PanPosition, 200 ) - 100;
  1348. if ( pos < 0 )
  1349. {
  1350. stat = ci->dsbuf->SetPan ( AUD_log_table[100+pos]);
  1351. }
  1352. else
  1353. {
  1354. stat = ci->dsbuf->SetPan ( -AUD_log_table[100-pos]);
  1355. }
  1356. }
  1357. #endif
  1358. pitch = AudioAttribsCalcPitch ( &chan->attribs, ci->chan->current_format.Rate );
  1359. ci->dsbuf->SetFrequency ( pitch);
  1360. return vNO_ERROR;
  1361. }
  1362. /******************************************************************/
  1363. /* */
  1364. /* */
  1365. /******************************************************************/
  1366. static int audioQueueIt ( AudioChannel *)
  1367. {
  1368. return ERROR_CODE_FAIL;
  1369. }
  1370. /******************************************************************/
  1371. /* */
  1372. /* */
  1373. /******************************************************************/
  1374. static int audioLock ( AudioChannel *)
  1375. {
  1376. AUD_ThreadBeginCriticalSection ( thread );
  1377. return vNO_ERROR;
  1378. }
  1379. /******************************************************************/
  1380. /* */
  1381. /* */
  1382. /******************************************************************/
  1383. static int audioUnlock ( AudioChannel *)
  1384. {
  1385. AUD_ThreadEndCriticalSection ( thread );
  1386. return vNO_ERROR;
  1387. }
  1388. /* command functions */
  1389. #if 0
  1390. static int AUD_set_dev_format ( AudioDevice *, AudioFormat *format )
  1391. {
  1392. WAVEFORMATEX wf;
  1393. int err = ERROR_CODE_FAIL;
  1394. if ( AUD_primary_buffer )
  1395. {
  1396. // Set up wave format structure.
  1397. AUD_primary_buffer->Stop ();
  1398. AUD_set_wave_format ( &wf, format );
  1399. if ( AUD_primary_buffer->SetFormat ( &wf ) == DS_OK )
  1400. {
  1401. err = vNO_ERROR;
  1402. }
  1403. AUD_primary_buffer->Play ( 0, 0, DSBPLAY_LOOPING );
  1404. }
  1405. return err;
  1406. }
  1407. #endif
  1408. /*****************************************************************************
  1409. ** Public Functions **
  1410. *****************************************************************************/
  1411. /* :NOTICE:
  1412. There are no public functions in a driver. If you have any then you are doing
  1413. something wrong. -Tr
  1414. */
  1415. void *GetDirectSoundObject ( void )
  1416. {
  1417. return (void *) AUD_sound_object;
  1418. }
  1419. void *GetPrimaryBuffer ( void )
  1420. {
  1421. return (void *) AUD_primary_buffer ;
  1422. }
  1423. void AudioLoseFocus ( void )
  1424. {
  1425. if ( AUD_primary_buffer )
  1426. {
  1427. AUD_primary_buffer->Stop ();
  1428. }
  1429. }
  1430. void AudioRegainFocus ( void )
  1431. {
  1432. if ( AUD_primary_buffer )
  1433. {
  1434. DWORD status;
  1435. AUD_primary_buffer->GetStatus ( &status );
  1436. if ( (status & DSBSTATUS_BUFFERLOST) )
  1437. {
  1438. AUD_restore_primary ( );
  1439. }
  1440. if ( !(status & DSBSTATUS_PLAYING) )
  1441. {
  1442. AUD_primary_buffer->Play ( 0, 0, DSBPLAY_LOOPING );
  1443. }
  1444. }
  1445. }
  1446. /* debug function. Not part of API */
  1447. #ifdef _DEBUG
  1448. void AudioCauseMixerDelay ( void )
  1449. {
  1450. mixer_skip = (vAUD_DRV_OVER_SAMPLE * vAUD_DRV_FRAMES -1) * 2;
  1451. }
  1452. #include <stdio.h>
  1453. void AudioDeviceDumpDXSNDDriver ( AudioDevice *dev, void (*print) ( const char *) )
  1454. {
  1455. char string[200];
  1456. AudioChannel *chan;
  1457. AudioSearch sh;
  1458. DBG_Function ("AudioDeviceDumpChannels");
  1459. DBG_ASSERT_TYPE ( dev, AudioDevice );
  1460. LockAcquire ( &dev->channelAccess);
  1461. sprintf ( string, " \nDXSND Channels\n");
  1462. print ( string );
  1463. chan = AudioDeviceFirstChannel ( dev, &sh );
  1464. while (chan)
  1465. {
  1466. sprintf ( string, "Channel 0x%0x, F=%6d, P=%d, I=%04d, T=%6d, B=%6d\n",
  1467. chan,
  1468. chan->drvData->frame_bytes,
  1469. chan->drvData->frame,
  1470. chan->drvData->poll_interval,
  1471. chan->drvData->min_fill,
  1472. chan->drvData->buf_size
  1473. );
  1474. print ( string );
  1475. chan = AudioDeviceNextChannel( &sh );
  1476. }
  1477. LockRelease ( &dev->channelAccess);
  1478. }
  1479. #endif
  1480. // IMA ADPCM Support
  1481. /*
  1482. *
  1483. * Lookup tables for IMA ADPCM format
  1484. *
  1485. */
  1486. static int imaIndexAdjustTable[16] = {
  1487. -1, -1, -1, -1, /* +0 - +3, decrease the step size */
  1488. 2, 4, 6, 8, /* +4 - +7, increase the step size */
  1489. -1, -1, -1, -1, /* -0 - -3, decrease the step size */
  1490. 2, 4, 6, 8, /* -4 - -7, increase the step size */
  1491. };
  1492. static int imaStepSizeTable[89] = {
  1493. 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34,
  1494. 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143,
  1495. 157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, 494,
  1496. 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552,
  1497. 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327, 3660, 4026,
  1498. 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493, 10442,
  1499. 11487, 12635, 13899, 15289, 16818, 18500, 20350, 22385, 24623,
  1500. 27086, 29794, 32767
  1501. };
  1502. /******************************************************************/
  1503. /* */
  1504. /* */
  1505. /******************************************************************/
  1506. /****************************************************************************/
  1507. /* IMA ADPCM Support Functions Section */
  1508. /****************************************************************************/
  1509. /*
  1510. *
  1511. * MsAdpcmDecode - Decode a given sample and update state tables
  1512. *
  1513. */
  1514. static short ImaAdpcmDecode( uint8 deltaCode, IMA_DATA *state )
  1515. {
  1516. /* Get the current step size */
  1517. int step;
  1518. int difference;
  1519. step = imaStepSizeTable[state->index];
  1520. /* Construct the difference by scaling the current step size */
  1521. /* This is approximately: difference = (deltaCode+.5)*step/4 */
  1522. difference = step>>3;
  1523. if ( deltaCode & 1 ) difference += step>>2;
  1524. if ( deltaCode & 2 ) difference += step>>1;
  1525. if ( deltaCode & 4 ) difference += step;
  1526. if ( deltaCode & 8 ) difference = -difference;
  1527. /* Build the new sample */
  1528. state->previousValue += difference;
  1529. if (state->previousValue > 32767) state->previousValue = 32767;
  1530. else if (state->previousValue < -32768) state->previousValue = -32768;
  1531. /* Update the step for the next sample */
  1532. state->index += imaIndexAdjustTable[deltaCode];
  1533. if (state->index < 0) state->index = 0;
  1534. else if (state->index > 88) state->index = 88;
  1535. return (short) state->previousValue;
  1536. }
  1537. static int IMA_decode_block ( AUD_DRV_CHAN *ci )
  1538. {
  1539. int i,j;
  1540. TRANSFER *data = &ci->transfer_data;
  1541. int bytes = data->in_bytes - data->in_bytes_left;
  1542. uint8 *in = data->in;
  1543. // set up output
  1544. data->out_bytes = 0;
  1545. ushort *out = (ushort *) data->out;
  1546. if ( bytes < data->channels*4 )
  1547. {
  1548. return FALSE;
  1549. }
  1550. for ( i=0; i < data->channels; i++)
  1551. {
  1552. data->ima[i].previousValue = (int) (in[1] <<8) + (int) in[0];
  1553. if (data->ima[i].previousValue & 0x8000)
  1554. data->ima[i].previousValue -= 0x10000;
  1555. if ((data->ima[i].index = in[2]) > 88)
  1556. {
  1557. msg_assert(FALSE, ("IMA ADPCM Format Error (bad index value) in wav file %s",ci->chan->sample_name));
  1558. return FALSE;
  1559. }
  1560. if (in[3])
  1561. {
  1562. msg_assert (FALSE, ("IMA ADPCM Format Error (synchronization error) in wav file %s ", ci->chan->sample_name));
  1563. return FALSE;
  1564. }
  1565. in+=4;
  1566. bytes -=4;
  1567. *out++ = (unsigned short ) data->ima[i].previousValue;
  1568. data->out_bytes += 2;
  1569. }
  1570. if ( data->channels == 1 )
  1571. {
  1572. // 99.99% of the samples being played are mono
  1573. while ( bytes > 0 )
  1574. {
  1575. ushort *out = (ushort *) &data->out[data->out_bytes];
  1576. j = 4;
  1577. while ( j-- )
  1578. {
  1579. uint8 b = *in++;
  1580. *out++ = (ushort ) ImaAdpcmDecode(b & 0x0f,&data->ima[0]);
  1581. *out++ = (ushort ) ImaAdpcmDecode((b>>4) & 0x0f,&data->ima[0]);
  1582. }
  1583. data->out_bytes += 16;
  1584. bytes -= 4;
  1585. }
  1586. }
  1587. else
  1588. {
  1589. while ( bytes > 0 )
  1590. {
  1591. for ( i = 0; i < data->channels ; i++)
  1592. {
  1593. short *out = (short *) &data->out[data->out_bytes+(i<<1)];
  1594. for (j=0;j<4;j++)
  1595. {
  1596. uint8 b = *in++;
  1597. *out = ImaAdpcmDecode(b & 0x0f,&data->ima[i]);
  1598. out += data->channels;
  1599. *out = ImaAdpcmDecode((b>>4) & 0x0f,&data->ima[i]);
  1600. out += data->channels;
  1601. }
  1602. }
  1603. data->out_bytes += data->channels<<4;
  1604. bytes -= data->channels<<2;
  1605. }
  1606. }
  1607. if ( bytes != 0 )
  1608. {
  1609. msg_assert ( FALSE, ("bad block"));
  1610. return FALSE;
  1611. }
  1612. return TRUE;
  1613. }
  1614. /****************************************************************************/
  1615. /* Microsoft ADPCM Support Functions Section */
  1616. /****************************************************************************/
  1617. static const int adaptionTable[] = {
  1618. 230, 230, 230, 230, 307, 409, 512, 614,
  1619. 768, 614, 512, 409, 307, 230, 230, 230
  1620. };
  1621. static short MSAdpcmDecode( unsigned char nibble, MS_DATA *ms, int sample1, int sample2)
  1622. {
  1623. int newsample;
  1624. int predsample;
  1625. predsample = ((sample1 * ms->iCoef[0]) + ( sample2 * ms->iCoef[1]))>>8;
  1626. newsample = predsample + (ms->idelta * (nibble - ((nibble&0x08) << 1)));
  1627. ms->idelta = (ms->idelta * adaptionTable[nibble])>>8;
  1628. if ( ms->idelta < 16 )
  1629. {
  1630. ms->idelta = 16;
  1631. }
  1632. if (newsample > 0x7fff)
  1633. {
  1634. newsample = 0x7fff;
  1635. }
  1636. else if (newsample < -0x8000)
  1637. {
  1638. newsample = -0x8000;
  1639. }
  1640. return (short) newsample;
  1641. }
  1642. static int MS_decode_block ( AUD_DRV_CHAN *ci )
  1643. {
  1644. int i;
  1645. TRANSFER *data = &ci->transfer_data;
  1646. int bytes = data->in_bytes - data->in_bytes_left;
  1647. uint8 *in = data->in;
  1648. unsigned char bpredictor;
  1649. int hsize = data->channels*(1+2+2+2);
  1650. int channels = data->channels;
  1651. int hi,lo;
  1652. // set up output
  1653. data->out_bytes = 0;
  1654. short *out = (short *) data->out;
  1655. if ( (bytes -= hsize) < 0 )
  1656. {
  1657. return FALSE;
  1658. }
  1659. for ( i=0; i < channels; i++)
  1660. {
  1661. bpredictor = *in++;
  1662. if (bpredictor >= 7) {
  1663. msg_assert(FALSE, ("MS-ADPCM bpredictor out of range"));
  1664. return FALSE;
  1665. }
  1666. data->ms[i].iCoef[0] = MSADPCM_StdCoef[bpredictor][0];
  1667. data->ms[i].iCoef[1] = MSADPCM_StdCoef[bpredictor][1];
  1668. }
  1669. for ( i=0; i < channels; i++)
  1670. {
  1671. lo = *in++;
  1672. hi = *in++;
  1673. data->ms[i].idelta = (hi<<8) | lo;
  1674. }
  1675. for ( i=0; i < channels; i++)
  1676. {
  1677. lo = *in++;
  1678. hi = *in++;
  1679. out[channels+i] = (hi<<8) | lo;
  1680. }
  1681. for ( i=0; i < channels; i++)
  1682. {
  1683. lo = *in++;
  1684. hi = *in++;
  1685. out[i] = (hi<<8) | lo;
  1686. }
  1687. /* already have 1st 2 samples from block-header */
  1688. out += 2*data->channels;
  1689. data->out_bytes += 4*data->channels;
  1690. if ( channels == 1 )
  1691. {
  1692. unsigned char byte;
  1693. while ( bytes )
  1694. {
  1695. byte = *in++;
  1696. *out++ = MSAdpcmDecode(byte >> 4, &data->ms[0], out[-1], out[-2]);
  1697. *out++ = MSAdpcmDecode(byte&0x0f, &data->ms[0], out[-1], out[-2]);
  1698. bytes--;
  1699. data->out_bytes += 4;
  1700. }
  1701. }
  1702. else
  1703. {
  1704. int chan = 0;
  1705. unsigned char byte;
  1706. int channels2 = 2*channels;
  1707. int out_bytes = 4*channels;
  1708. while ( bytes )
  1709. {
  1710. byte = *in++;
  1711. *out++ = MSAdpcmDecode(byte >> 4, &data->ms[chan], out[-channels], out[-channels2]);
  1712. if (++chan == channels )
  1713. {
  1714. chan = 0;
  1715. }
  1716. *out++ = MSAdpcmDecode(byte&0x0f, &data->ms[chan], out[-channels], out[-channels2]);
  1717. if (++chan == channels)
  1718. {
  1719. chan = 0;
  1720. }
  1721. bytes--;
  1722. data->out_bytes += out_bytes;;
  1723. }
  1724. }
  1725. return TRUE;
  1726. }
  1727. // Stubs
  1728. DXDEC void FAR * AILCALL AIL_mem_alloc_lock(U32 size)
  1729. {
  1730. return AudioMemAlloc ( size );
  1731. }
  1732. DXDEC void AILCALL AIL_mem_free_lock (void FAR *ptr)
  1733. {
  1734. AudioMemFree ( ptr );
  1735. }
  1736. DXDEC U32 AILCALL AIL_MMX_available (void)
  1737. {
  1738. return 0;
  1739. }