MIDI.C 56 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266
  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: MIDI.C
  17. author: James R. Dose
  18. date: May 25, 1994
  19. Midi song file playback routines.
  20. (c) Copyright 1994 James R. Dose. All Rights Reserved.
  21. **********************************************************************/
  22. #include <stdlib.h>
  23. #include <time.h>
  24. #include <dos.h>
  25. #include <string.h>
  26. #include "sndcards.h"
  27. #include "interrup.h"
  28. #include "dpmi.h"
  29. #include "standard.h"
  30. #include "task_man.h"
  31. #include "ll_man.h"
  32. #include "usrhooks.h"
  33. #include "music.h"
  34. #include "_midi.h"
  35. #include "midi.h"
  36. #include "debugio.h"
  37. extern int MUSIC_SoundDevice;
  38. static const int _MIDI_CommandLengths[ NUM_MIDI_CHANNELS ] =
  39. {
  40. 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 1, 1, 2, 0
  41. };
  42. static int cdecl ( *_MIDI_RerouteFunctions[ NUM_MIDI_CHANNELS ] )
  43. (
  44. int event,
  45. int c1,
  46. int c2
  47. ) = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  48. NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
  49. static track *_MIDI_TrackPtr = NULL;
  50. static int _MIDI_TrackMemSize;
  51. static int _MIDI_NumTracks;
  52. static int _MIDI_SongActive = FALSE;
  53. static int _MIDI_SongLoaded = FALSE;
  54. static int _MIDI_Loop = FALSE;
  55. static task *_MIDI_PlayRoutine = NULL;
  56. static int _MIDI_Division;
  57. static int _MIDI_Tick = 0;
  58. static int _MIDI_Beat = 1;
  59. static int _MIDI_Measure = 1;
  60. static unsigned _MIDI_Time;
  61. static int _MIDI_BeatsPerMeasure;
  62. static int _MIDI_TicksPerBeat;
  63. static int _MIDI_TimeBase;
  64. static long _MIDI_FPSecondsPerTick;
  65. static unsigned _MIDI_TotalTime;
  66. static int _MIDI_TotalTicks;
  67. static int _MIDI_TotalBeats;
  68. static int _MIDI_TotalMeasures;
  69. static unsigned long _MIDI_PositionInTicks;
  70. static int _MIDI_Context;
  71. static int _MIDI_ActiveTracks;
  72. static int _MIDI_TotalVolume = MIDI_MaxVolume;
  73. static int _MIDI_ChannelVolume[ NUM_MIDI_CHANNELS ];
  74. static int _MIDI_UserChannelVolume[ NUM_MIDI_CHANNELS ] =
  75. {
  76. 256, 256, 256, 256, 256, 256, 256, 256,
  77. 256, 256, 256, 256, 256, 256, 256, 256
  78. };
  79. static midifuncs *_MIDI_Funcs = NULL;
  80. static int Reset = FALSE;
  81. int MIDI_Tempo = 120;
  82. char MIDI_PatchMap[ 128 ];
  83. /**********************************************************************
  84. Memory locked functions:
  85. **********************************************************************/
  86. #define MIDI_LockStart _MIDI_ReadNumber
  87. /*---------------------------------------------------------------------
  88. Function: _MIDI_ReadNumber
  89. Reads a variable length number from a MIDI track.
  90. ---------------------------------------------------------------------*/
  91. static long _MIDI_ReadNumber
  92. (
  93. void *from,
  94. size_t size
  95. )
  96. {
  97. unsigned char *FromPtr;
  98. long value;
  99. if ( size > 4 )
  100. {
  101. size = 4;
  102. }
  103. FromPtr = ( unsigned char * )from;
  104. value = 0;
  105. while( size-- )
  106. {
  107. value <<= 8;
  108. value += *FromPtr++;
  109. }
  110. return( value );
  111. }
  112. /*---------------------------------------------------------------------
  113. Function: _MIDI_ReadDelta
  114. Reads a variable length encoded delta delay time from the MIDI data.
  115. ---------------------------------------------------------------------*/
  116. static long _MIDI_ReadDelta
  117. (
  118. track *ptr
  119. )
  120. {
  121. long value;
  122. unsigned char c;
  123. GET_NEXT_EVENT( ptr, value );
  124. if ( value & 0x80 )
  125. {
  126. value &= 0x7f;
  127. do
  128. {
  129. GET_NEXT_EVENT( ptr, c );
  130. value = ( value << 7 ) + ( c & 0x7f );
  131. }
  132. while ( c & 0x80 );
  133. }
  134. return( value );
  135. }
  136. /*---------------------------------------------------------------------
  137. Function: _MIDI_ResetTracks
  138. Sets the track pointers to the beginning of the song.
  139. ---------------------------------------------------------------------*/
  140. static void _MIDI_ResetTracks
  141. (
  142. void
  143. )
  144. {
  145. int i;
  146. track *ptr;
  147. _MIDI_Tick = 0;
  148. _MIDI_Beat = 1;
  149. _MIDI_Measure = 1;
  150. _MIDI_Time = 0;
  151. _MIDI_BeatsPerMeasure = 4;
  152. _MIDI_TicksPerBeat = _MIDI_Division;
  153. _MIDI_TimeBase = 4;
  154. _MIDI_PositionInTicks = 0;
  155. _MIDI_ActiveTracks = 0;
  156. _MIDI_Context = 0;
  157. ptr = _MIDI_TrackPtr;
  158. for( i = 0; i < _MIDI_NumTracks; i++ )
  159. {
  160. ptr->pos = ptr->start;
  161. ptr->delay = _MIDI_ReadDelta( ptr );
  162. ptr->active = ptr->EMIDI_IncludeTrack;
  163. ptr->RunningStatus = 0;
  164. ptr->currentcontext = 0;
  165. ptr->context[ 0 ].loopstart = ptr->start;
  166. ptr->context[ 0 ].loopcount = 0;
  167. if ( ptr->active )
  168. {
  169. _MIDI_ActiveTracks++;
  170. }
  171. ptr++;
  172. }
  173. }
  174. /*---------------------------------------------------------------------
  175. Function: _MIDI_AdvanceTick
  176. Increment tick counters.
  177. ---------------------------------------------------------------------*/
  178. static void _MIDI_AdvanceTick
  179. (
  180. void
  181. )
  182. {
  183. _MIDI_PositionInTicks++;
  184. _MIDI_Time += _MIDI_FPSecondsPerTick;
  185. _MIDI_Tick++;
  186. while( _MIDI_Tick > _MIDI_TicksPerBeat )
  187. {
  188. _MIDI_Tick -= _MIDI_TicksPerBeat;
  189. _MIDI_Beat++;
  190. }
  191. while( _MIDI_Beat > _MIDI_BeatsPerMeasure )
  192. {
  193. _MIDI_Beat -= _MIDI_BeatsPerMeasure;
  194. _MIDI_Measure++;
  195. }
  196. }
  197. /*---------------------------------------------------------------------
  198. Function: _MIDI_SysEx
  199. Interpret SysEx Event.
  200. ---------------------------------------------------------------------*/
  201. static void _MIDI_SysEx
  202. (
  203. track *Track
  204. )
  205. {
  206. int length;
  207. length = _MIDI_ReadDelta( Track );
  208. Track->pos += length;
  209. }
  210. /*---------------------------------------------------------------------
  211. Function: _MIDI_MetaEvent
  212. Interpret Meta Event.
  213. ---------------------------------------------------------------------*/
  214. static void _MIDI_MetaEvent
  215. (
  216. track *Track
  217. )
  218. {
  219. int command;
  220. int length;
  221. int denominator;
  222. long tempo;
  223. GET_NEXT_EVENT( Track, command );
  224. GET_NEXT_EVENT( Track, length );
  225. switch( command )
  226. {
  227. case MIDI_END_OF_TRACK :
  228. Track->active = FALSE;
  229. _MIDI_ActiveTracks--;
  230. break;
  231. case MIDI_TEMPO_CHANGE :
  232. tempo = 60000000L / _MIDI_ReadNumber( Track->pos, 3 );
  233. MIDI_SetTempo( tempo );
  234. break;
  235. case MIDI_TIME_SIGNATURE :
  236. if ( ( _MIDI_Tick > 0 ) || ( _MIDI_Beat > 1 ) )
  237. {
  238. _MIDI_Measure++;
  239. }
  240. _MIDI_Tick = 0;
  241. _MIDI_Beat = 1;
  242. _MIDI_BeatsPerMeasure = (int)*Track->pos;
  243. denominator = (int)*( Track->pos + 1 );
  244. _MIDI_TimeBase = 1;
  245. while( denominator > 0 )
  246. {
  247. _MIDI_TimeBase += _MIDI_TimeBase;
  248. denominator--;
  249. }
  250. _MIDI_TicksPerBeat = ( _MIDI_Division * 4 ) / _MIDI_TimeBase;
  251. break;
  252. }
  253. Track->pos += length;
  254. }
  255. /*---------------------------------------------------------------------
  256. Function: _MIDI_InterpretControllerInfo
  257. Interprets the MIDI controller info.
  258. ---------------------------------------------------------------------*/
  259. static int _MIDI_InterpretControllerInfo
  260. (
  261. track *Track,
  262. int TimeSet,
  263. int channel,
  264. int c1,
  265. int c2
  266. )
  267. {
  268. track *trackptr;
  269. int tracknum;
  270. int loopcount;
  271. switch( c1 )
  272. {
  273. case MIDI_MONO_MODE_ON :
  274. Track->pos++;
  275. break;
  276. case MIDI_VOLUME :
  277. if ( !Track->EMIDI_VolumeChange )
  278. {
  279. _MIDI_SetChannelVolume( channel, c2 );
  280. }
  281. break;
  282. case EMIDI_INCLUDE_TRACK :
  283. case EMIDI_EXCLUDE_TRACK :
  284. break;
  285. case EMIDI_PROGRAM_CHANGE :
  286. if ( Track->EMIDI_ProgramChange )
  287. {
  288. _MIDI_Funcs->ProgramChange( channel, MIDI_PatchMap[ c2 & 0x7f ] );
  289. }
  290. break;
  291. case EMIDI_VOLUME_CHANGE :
  292. if ( Track->EMIDI_VolumeChange )
  293. {
  294. _MIDI_SetChannelVolume( channel, c2 );
  295. }
  296. break;
  297. case EMIDI_CONTEXT_START :
  298. break;
  299. case EMIDI_CONTEXT_END :
  300. if ( ( Track->currentcontext == _MIDI_Context ) ||
  301. ( _MIDI_Context < 0 ) ||
  302. ( Track->context[ _MIDI_Context ].pos == NULL ) )
  303. {
  304. break;
  305. }
  306. Track->currentcontext = _MIDI_Context;
  307. Track->context[ 0 ].loopstart = Track->context[ _MIDI_Context ].loopstart;
  308. Track->context[ 0 ].loopcount = Track->context[ _MIDI_Context ].loopcount;
  309. Track->pos = Track->context[ _MIDI_Context ].pos;
  310. Track->RunningStatus = Track->context[ _MIDI_Context ].RunningStatus;
  311. if ( TimeSet )
  312. {
  313. break;
  314. }
  315. _MIDI_Time = Track->context[ _MIDI_Context ].time;
  316. _MIDI_FPSecondsPerTick = Track->context[ _MIDI_Context ].FPSecondsPerTick;
  317. _MIDI_Tick = Track->context[ _MIDI_Context ].tick;
  318. _MIDI_Beat = Track->context[ _MIDI_Context ].beat;
  319. _MIDI_Measure = Track->context[ _MIDI_Context ].measure;
  320. _MIDI_BeatsPerMeasure = Track->context[ _MIDI_Context ].BeatsPerMeasure;
  321. _MIDI_TicksPerBeat = Track->context[ _MIDI_Context ].TicksPerBeat;
  322. _MIDI_TimeBase = Track->context[ _MIDI_Context ].TimeBase;
  323. TimeSet = TRUE;
  324. break;
  325. case EMIDI_LOOP_START :
  326. case EMIDI_SONG_LOOP_START :
  327. if ( c2 == 0 )
  328. {
  329. loopcount = EMIDI_INFINITE;
  330. }
  331. else
  332. {
  333. loopcount = c2;
  334. }
  335. if ( c1 == EMIDI_SONG_LOOP_START )
  336. {
  337. trackptr = _MIDI_TrackPtr;
  338. tracknum = _MIDI_NumTracks;
  339. }
  340. else
  341. {
  342. trackptr = Track;
  343. tracknum = 1;
  344. }
  345. while( tracknum > 0 )
  346. {
  347. trackptr->context[ 0 ].loopcount = loopcount;
  348. trackptr->context[ 0 ].pos = trackptr->pos;
  349. trackptr->context[ 0 ].loopstart = trackptr->pos;
  350. trackptr->context[ 0 ].RunningStatus = trackptr->RunningStatus;
  351. trackptr->context[ 0 ].active = trackptr->active;
  352. trackptr->context[ 0 ].delay = trackptr->delay;
  353. trackptr->context[ 0 ].time = _MIDI_Time;
  354. trackptr->context[ 0 ].FPSecondsPerTick = _MIDI_FPSecondsPerTick;
  355. trackptr->context[ 0 ].tick = _MIDI_Tick;
  356. trackptr->context[ 0 ].beat = _MIDI_Beat;
  357. trackptr->context[ 0 ].measure = _MIDI_Measure;
  358. trackptr->context[ 0 ].BeatsPerMeasure = _MIDI_BeatsPerMeasure;
  359. trackptr->context[ 0 ].TicksPerBeat = _MIDI_TicksPerBeat;
  360. trackptr->context[ 0 ].TimeBase = _MIDI_TimeBase;
  361. trackptr++;
  362. tracknum--;
  363. }
  364. break;
  365. case EMIDI_LOOP_END :
  366. case EMIDI_SONG_LOOP_END :
  367. if ( ( c2 != EMIDI_END_LOOP_VALUE ) ||
  368. ( Track->context[ 0 ].loopstart == NULL ) ||
  369. ( Track->context[ 0 ].loopcount == 0 ) )
  370. {
  371. break;
  372. }
  373. if ( c1 == EMIDI_SONG_LOOP_END )
  374. {
  375. trackptr = _MIDI_TrackPtr;
  376. tracknum = _MIDI_NumTracks;
  377. _MIDI_ActiveTracks = 0;
  378. }
  379. else
  380. {
  381. trackptr = Track;
  382. tracknum = 1;
  383. _MIDI_ActiveTracks--;
  384. }
  385. while( tracknum > 0 )
  386. {
  387. if ( trackptr->context[ 0 ].loopcount != EMIDI_INFINITE )
  388. {
  389. trackptr->context[ 0 ].loopcount--;
  390. }
  391. trackptr->pos = trackptr->context[ 0 ].loopstart;
  392. trackptr->RunningStatus = trackptr->context[ 0 ].RunningStatus;
  393. trackptr->delay = trackptr->context[ 0 ].delay;
  394. trackptr->active = trackptr->context[ 0 ].active;
  395. if ( trackptr->active )
  396. {
  397. _MIDI_ActiveTracks++;
  398. }
  399. if ( !TimeSet )
  400. {
  401. _MIDI_Time = trackptr->context[ 0 ].time;
  402. _MIDI_FPSecondsPerTick = trackptr->context[ 0 ].FPSecondsPerTick;
  403. _MIDI_Tick = trackptr->context[ 0 ].tick;
  404. _MIDI_Beat = trackptr->context[ 0 ].beat;
  405. _MIDI_Measure = trackptr->context[ 0 ].measure;
  406. _MIDI_BeatsPerMeasure = trackptr->context[ 0 ].BeatsPerMeasure;
  407. _MIDI_TicksPerBeat = trackptr->context[ 0 ].TicksPerBeat;
  408. _MIDI_TimeBase = trackptr->context[ 0 ].TimeBase;
  409. TimeSet = TRUE;
  410. }
  411. trackptr++;
  412. tracknum--;
  413. }
  414. break;
  415. default :
  416. if ( _MIDI_Funcs->ControlChange )
  417. {
  418. _MIDI_Funcs->ControlChange( channel, c1, c2 );
  419. }
  420. }
  421. return TimeSet;
  422. }
  423. /*---------------------------------------------------------------------
  424. Function: _MIDI_ServiceRoutine
  425. Task that interperates the MIDI data.
  426. ---------------------------------------------------------------------*/
  427. // NOTE: We have to use a stack frame here because of a strange bug
  428. // that occurs with Watcom. This means that we cannot access Task!
  429. //Turned off to test if it works with Watcom 10a
  430. //#pragma aux _MIDI_ServiceRoutine frame;
  431. /*
  432. static void test
  433. (
  434. task *Task
  435. )
  436. {
  437. _MIDI_ServiceRoutine( Task );
  438. _MIDI_ServiceRoutine( Task );
  439. _MIDI_ServiceRoutine( Task );
  440. _MIDI_ServiceRoutine( Task );
  441. }
  442. */
  443. static void _MIDI_ServiceRoutine
  444. (
  445. task *Task
  446. )
  447. {
  448. int event;
  449. int channel;
  450. int command;
  451. track *Track;
  452. int tracknum;
  453. int status;
  454. int c1;
  455. int c2;
  456. int TimeSet = FALSE;
  457. if ( !_MIDI_SongActive )
  458. {
  459. return;
  460. }
  461. Track = _MIDI_TrackPtr;
  462. tracknum = 0;
  463. while( tracknum < _MIDI_NumTracks )
  464. {
  465. while ( ( Track->active ) && ( Track->delay == 0 ) )
  466. {
  467. GET_NEXT_EVENT( Track, event );
  468. if ( GET_MIDI_COMMAND( event ) == MIDI_SPECIAL )
  469. {
  470. switch( event )
  471. {
  472. case MIDI_SYSEX :
  473. case MIDI_SYSEX_CONTINUE :
  474. _MIDI_SysEx( Track );
  475. break;
  476. case MIDI_META_EVENT :
  477. _MIDI_MetaEvent( Track );
  478. break;
  479. }
  480. if ( Track->active )
  481. {
  482. Track->delay = _MIDI_ReadDelta( Track );
  483. }
  484. continue;
  485. }
  486. if ( event & MIDI_RUNNING_STATUS )
  487. {
  488. Track->RunningStatus = event;
  489. }
  490. else
  491. {
  492. event = Track->RunningStatus;
  493. Track->pos--;
  494. }
  495. channel = GET_MIDI_CHANNEL( event );
  496. command = GET_MIDI_COMMAND( event );
  497. if ( _MIDI_CommandLengths[ command ] > 0 )
  498. {
  499. GET_NEXT_EVENT( Track, c1 );
  500. if ( _MIDI_CommandLengths[ command ] > 1 )
  501. {
  502. GET_NEXT_EVENT( Track, c2 );
  503. }
  504. }
  505. if ( _MIDI_RerouteFunctions[ channel ] != NULL )
  506. {
  507. status = _MIDI_RerouteFunctions[ channel ]( event, c1, c2 );
  508. if ( status == MIDI_DONT_PLAY )
  509. {
  510. Track->delay = _MIDI_ReadDelta( Track );
  511. continue;
  512. }
  513. }
  514. switch ( command )
  515. {
  516. case MIDI_NOTE_OFF :
  517. if ( _MIDI_Funcs->NoteOff )
  518. {
  519. _MIDI_Funcs->NoteOff( channel, c1, c2 );
  520. }
  521. break;
  522. case MIDI_NOTE_ON :
  523. if ( _MIDI_Funcs->NoteOn )
  524. {
  525. _MIDI_Funcs->NoteOn( channel, c1, c2 );
  526. }
  527. break;
  528. case MIDI_POLY_AFTER_TCH :
  529. if ( _MIDI_Funcs->PolyAftertouch )
  530. {
  531. _MIDI_Funcs->PolyAftertouch( channel, c1, c2 );
  532. }
  533. break;
  534. case MIDI_CONTROL_CHANGE :
  535. TimeSet = _MIDI_InterpretControllerInfo( Track, TimeSet,
  536. channel, c1, c2 );
  537. break;
  538. case MIDI_PROGRAM_CHANGE :
  539. if ( ( _MIDI_Funcs->ProgramChange ) &&
  540. ( !Track->EMIDI_ProgramChange ) )
  541. {
  542. _MIDI_Funcs->ProgramChange( channel, MIDI_PatchMap[ c1 & 0x7f ] );
  543. }
  544. break;
  545. case MIDI_AFTER_TOUCH :
  546. if ( _MIDI_Funcs->ChannelAftertouch )
  547. {
  548. _MIDI_Funcs->ChannelAftertouch( channel, c1 );
  549. }
  550. break;
  551. case MIDI_PITCH_BEND :
  552. if ( _MIDI_Funcs->PitchBend )
  553. {
  554. _MIDI_Funcs->PitchBend( channel, c1, c2 );
  555. }
  556. break;
  557. default :
  558. break;
  559. }
  560. Track->delay = _MIDI_ReadDelta( Track );
  561. }
  562. Track->delay--;
  563. Track++;
  564. tracknum++;
  565. if ( _MIDI_ActiveTracks == 0 )
  566. {
  567. _MIDI_ResetTracks();
  568. if ( _MIDI_Loop )
  569. {
  570. tracknum = 0;
  571. Track = _MIDI_TrackPtr;
  572. }
  573. else
  574. {
  575. _MIDI_SongActive = FALSE;
  576. break;
  577. }
  578. }
  579. }
  580. _MIDI_AdvanceTick();
  581. }
  582. /*---------------------------------------------------------------------
  583. Function: _MIDI_SendControlChange
  584. Sends a control change to the proper device
  585. ---------------------------------------------------------------------*/
  586. static int _MIDI_SendControlChange
  587. (
  588. int channel,
  589. int c1,
  590. int c2
  591. )
  592. {
  593. int status;
  594. if ( _MIDI_RerouteFunctions[ channel ] != NULL )
  595. {
  596. status = _MIDI_RerouteFunctions[ channel ]( 0xB0 + channel,
  597. c1, c2 );
  598. if ( status == MIDI_DONT_PLAY )
  599. {
  600. return( MIDI_Ok );
  601. }
  602. }
  603. if ( _MIDI_Funcs == NULL )
  604. {
  605. return( MIDI_Error );
  606. }
  607. if ( _MIDI_Funcs->ControlChange == NULL )
  608. {
  609. return( MIDI_Error );
  610. }
  611. _MIDI_Funcs->ControlChange( channel, c1, c2 );
  612. return( MIDI_Ok );
  613. }
  614. /*---------------------------------------------------------------------
  615. Function: MIDI_RerouteMidiChannel
  616. Sets callback function to reroute MIDI commands from specified
  617. function.
  618. ---------------------------------------------------------------------*/
  619. void MIDI_RerouteMidiChannel
  620. (
  621. int channel,
  622. int cdecl ( *function )( int event, int c1, int c2 )
  623. )
  624. {
  625. if ( ( channel >= 1 ) && ( channel <= 16 ) )
  626. {
  627. _MIDI_RerouteFunctions[ channel - 1 ] = function;
  628. }
  629. }
  630. /*---------------------------------------------------------------------
  631. Function: MIDI_AllNotesOff
  632. Sends all notes off commands on all midi channels.
  633. ---------------------------------------------------------------------*/
  634. int MIDI_AllNotesOff
  635. (
  636. void
  637. )
  638. {
  639. int channel;
  640. for( channel = 0; channel < NUM_MIDI_CHANNELS; channel++ )
  641. {
  642. _MIDI_SendControlChange( channel, 0x40, 0 );
  643. _MIDI_SendControlChange( channel, MIDI_ALL_NOTES_OFF, 0 );
  644. _MIDI_SendControlChange( channel, 0x78, 0 );
  645. }
  646. return( MIDI_Ok );
  647. }
  648. /*---------------------------------------------------------------------
  649. Function: _MIDI_SetChannelVolume
  650. Sets the volume of the specified midi channel.
  651. ---------------------------------------------------------------------*/
  652. static void _MIDI_SetChannelVolume
  653. (
  654. int channel,
  655. int volume
  656. )
  657. {
  658. int status;
  659. int remotevolume;
  660. _MIDI_ChannelVolume[ channel ] = volume;
  661. if ( _MIDI_RerouteFunctions[ channel ] != NULL )
  662. {
  663. remotevolume = volume * _MIDI_TotalVolume;
  664. remotevolume *= _MIDI_UserChannelVolume[ channel ];
  665. remotevolume /= MIDI_MaxVolume;
  666. remotevolume >>= 8;
  667. status = _MIDI_RerouteFunctions[ channel ]( 0xB0 + channel,
  668. MIDI_VOLUME, remotevolume );
  669. if ( status == MIDI_DONT_PLAY )
  670. {
  671. return;
  672. }
  673. }
  674. if ( _MIDI_Funcs == NULL )
  675. {
  676. return;
  677. }
  678. if ( _MIDI_Funcs->ControlChange == NULL )
  679. {
  680. return;
  681. }
  682. // For user volume
  683. volume *= _MIDI_UserChannelVolume[ channel ];
  684. if ( _MIDI_Funcs->SetVolume == NULL )
  685. {
  686. volume *= _MIDI_TotalVolume;
  687. volume /= MIDI_MaxVolume;
  688. }
  689. // For user volume
  690. volume >>= 8;
  691. _MIDI_Funcs->ControlChange( channel, MIDI_VOLUME, volume );
  692. }
  693. /*---------------------------------------------------------------------
  694. Function: MIDI_SetUserChannelVolume
  695. Sets the volume of the specified midi channel.
  696. ---------------------------------------------------------------------*/
  697. void MIDI_SetUserChannelVolume
  698. (
  699. int channel,
  700. int volume
  701. )
  702. {
  703. // Convert channel from 1-16 to 0-15
  704. channel--;
  705. volume = max( 0, volume );
  706. volume = min( volume, 256 );
  707. if ( ( channel >= 0 ) && ( channel < NUM_MIDI_CHANNELS ) )
  708. {
  709. _MIDI_UserChannelVolume[ channel ] = volume;
  710. _MIDI_SetChannelVolume( channel, _MIDI_ChannelVolume[ channel ] );
  711. }
  712. }
  713. /*---------------------------------------------------------------------
  714. Function: MIDI_ResetUserChannelVolume
  715. Sets the volume of the specified midi channel.
  716. ---------------------------------------------------------------------*/
  717. void MIDI_ResetUserChannelVolume
  718. (
  719. void
  720. )
  721. {
  722. int channel;
  723. for( channel = 0; channel < NUM_MIDI_CHANNELS; channel++ )
  724. {
  725. _MIDI_UserChannelVolume[ channel ] = 256;
  726. }
  727. _MIDI_SendChannelVolumes();
  728. }
  729. /*---------------------------------------------------------------------
  730. Function: _MIDI_SendChannelVolumes
  731. Sets the volume on all the midi channels.
  732. ---------------------------------------------------------------------*/
  733. static void _MIDI_SendChannelVolumes
  734. (
  735. void
  736. )
  737. {
  738. int channel;
  739. for( channel = 0; channel < NUM_MIDI_CHANNELS; channel++ )
  740. {
  741. _MIDI_SetChannelVolume( channel, _MIDI_ChannelVolume[ channel ] );
  742. }
  743. }
  744. /*---------------------------------------------------------------------
  745. Function: MIDI_Reset
  746. Resets the MIDI device to General Midi defaults.
  747. ---------------------------------------------------------------------*/
  748. int MIDI_Reset
  749. (
  750. void
  751. )
  752. {
  753. int channel;
  754. long time;
  755. unsigned flags;
  756. MIDI_AllNotesOff();
  757. flags = DisableInterrupts();
  758. _enable();
  759. time = clock() + CLOCKS_PER_SEC/24;
  760. while(clock() < time)
  761. ;
  762. RestoreInterrupts( flags );
  763. for( channel = 0; channel < NUM_MIDI_CHANNELS; channel++ )
  764. {
  765. _MIDI_SendControlChange( channel, MIDI_RESET_ALL_CONTROLLERS, 0 );
  766. _MIDI_SendControlChange( channel, MIDI_RPN_MSB, MIDI_PITCHBEND_MSB );
  767. _MIDI_SendControlChange( channel, MIDI_RPN_LSB, MIDI_PITCHBEND_LSB );
  768. _MIDI_SendControlChange( channel, MIDI_DATAENTRY_MSB, 2 ); /* Pitch Bend Sensitivity MSB */
  769. _MIDI_SendControlChange( channel, MIDI_DATAENTRY_LSB, 0 ); /* Pitch Bend Sensitivity LSB */
  770. _MIDI_ChannelVolume[ channel ] = GENMIDI_DefaultVolume;
  771. }
  772. _MIDI_SendChannelVolumes();
  773. Reset = TRUE;
  774. return( MIDI_Ok );
  775. }
  776. /*---------------------------------------------------------------------
  777. Function: MIDI_SetVolume
  778. Sets the total volume of the music.
  779. ---------------------------------------------------------------------*/
  780. int MIDI_SetVolume
  781. (
  782. int volume
  783. )
  784. {
  785. int i;
  786. if ( _MIDI_Funcs == NULL )
  787. {
  788. return( MIDI_NullMidiModule );
  789. }
  790. volume = min( MIDI_MaxVolume, volume );
  791. volume = max( 0, volume );
  792. _MIDI_TotalVolume = volume;
  793. if ( _MIDI_Funcs->SetVolume )
  794. {
  795. _MIDI_Funcs->SetVolume( volume );
  796. for( i = 0; i < NUM_MIDI_CHANNELS; i++ )
  797. {
  798. if ( _MIDI_RerouteFunctions[ i ] != NULL )
  799. {
  800. _MIDI_SetChannelVolume( i, _MIDI_ChannelVolume[ i ] );
  801. }
  802. }
  803. }
  804. else
  805. {
  806. _MIDI_SendChannelVolumes();
  807. }
  808. return( MIDI_Ok );
  809. }
  810. /*---------------------------------------------------------------------
  811. Function: MIDI_GetVolume
  812. Returns the total volume of the music.
  813. ---------------------------------------------------------------------*/
  814. int MIDI_GetVolume
  815. (
  816. void
  817. )
  818. {
  819. int volume;
  820. if ( _MIDI_Funcs == NULL )
  821. {
  822. return( MIDI_NullMidiModule );
  823. }
  824. if ( _MIDI_Funcs->GetVolume )
  825. {
  826. volume = _MIDI_Funcs->GetVolume();
  827. }
  828. else
  829. {
  830. volume = _MIDI_TotalVolume;
  831. }
  832. return( volume );
  833. }
  834. /*---------------------------------------------------------------------
  835. Function: MIDI_SetContext
  836. Sets the song context.
  837. ---------------------------------------------------------------------*/
  838. void MIDI_SetContext
  839. (
  840. int context
  841. )
  842. {
  843. if ( ( context > 0 ) && ( context < EMIDI_NUM_CONTEXTS ) )
  844. {
  845. _MIDI_Context = context;
  846. }
  847. }
  848. /*---------------------------------------------------------------------
  849. Function: MIDI_GetContext
  850. Returns the current song context.
  851. ---------------------------------------------------------------------*/
  852. int MIDI_GetContext
  853. (
  854. void
  855. )
  856. {
  857. return _MIDI_Context;
  858. }
  859. /*---------------------------------------------------------------------
  860. Function: MIDI_SetLoopFlag
  861. Sets whether the song should loop when finished or not.
  862. ---------------------------------------------------------------------*/
  863. void MIDI_SetLoopFlag
  864. (
  865. int loopflag
  866. )
  867. {
  868. _MIDI_Loop = loopflag;
  869. }
  870. /*---------------------------------------------------------------------
  871. Function: MIDI_ContinueSong
  872. Continues playback of a paused song.
  873. ---------------------------------------------------------------------*/
  874. void MIDI_ContinueSong
  875. (
  876. void
  877. )
  878. {
  879. if ( _MIDI_SongLoaded )
  880. {
  881. _MIDI_SongActive = TRUE;
  882. }
  883. }
  884. /*---------------------------------------------------------------------
  885. Function: MIDI_PauseSong
  886. Pauses playback of the current song.
  887. ---------------------------------------------------------------------*/
  888. void MIDI_PauseSong
  889. (
  890. void
  891. )
  892. {
  893. if ( _MIDI_SongLoaded )
  894. {
  895. _MIDI_SongActive = FALSE;
  896. MIDI_AllNotesOff();
  897. }
  898. }
  899. /*---------------------------------------------------------------------
  900. Function: MIDI_SongPlaying
  901. Returns whether a song is playing or not.
  902. ---------------------------------------------------------------------*/
  903. int MIDI_SongPlaying
  904. (
  905. void
  906. )
  907. {
  908. return( _MIDI_SongActive );
  909. }
  910. /*---------------------------------------------------------------------
  911. Function: MIDI_SetMidiFuncs
  912. Selects the routines that send the MIDI data to the music device.
  913. ---------------------------------------------------------------------*/
  914. void MIDI_SetMidiFuncs
  915. (
  916. midifuncs *funcs
  917. )
  918. {
  919. _MIDI_Funcs = funcs;
  920. }
  921. /*---------------------------------------------------------------------
  922. Function: MIDI_StopSong
  923. Stops playback of the currently playing song.
  924. ---------------------------------------------------------------------*/
  925. void MIDI_StopSong
  926. (
  927. void
  928. )
  929. {
  930. if ( _MIDI_SongLoaded )
  931. {
  932. TS_Terminate( _MIDI_PlayRoutine );
  933. _MIDI_PlayRoutine = NULL;
  934. _MIDI_SongActive = FALSE;
  935. _MIDI_SongLoaded = FALSE;
  936. MIDI_Reset();
  937. _MIDI_ResetTracks();
  938. if ( _MIDI_Funcs->ReleasePatches )
  939. {
  940. _MIDI_Funcs->ReleasePatches();
  941. }
  942. DPMI_UnlockMemory( _MIDI_TrackPtr, _MIDI_TrackMemSize );
  943. USRHOOKS_FreeMem( _MIDI_TrackPtr );
  944. _MIDI_TrackPtr = NULL;
  945. _MIDI_NumTracks = 0;
  946. _MIDI_TrackMemSize = 0;
  947. _MIDI_TotalTime = 0;
  948. _MIDI_TotalTicks = 0;
  949. _MIDI_TotalBeats = 0;
  950. _MIDI_TotalMeasures = 0;
  951. }
  952. }
  953. /*---------------------------------------------------------------------
  954. Function: MIDI_PlaySong
  955. Begins playback of a MIDI song.
  956. ---------------------------------------------------------------------*/
  957. int MIDI_PlaySong
  958. (
  959. unsigned char *song,
  960. int loopflag
  961. )
  962. {
  963. int numtracks;
  964. int format;
  965. long headersize;
  966. long tracklength;
  967. track *CurrentTrack;
  968. unsigned char *ptr;
  969. int status;
  970. if ( _MIDI_SongLoaded )
  971. {
  972. MIDI_StopSong();
  973. }
  974. _MIDI_Loop = loopflag;
  975. if ( _MIDI_Funcs == NULL )
  976. {
  977. return( MIDI_NullMidiModule );
  978. }
  979. if ( *( unsigned long * )song != MIDI_HEADER_SIGNATURE )
  980. {
  981. return( MIDI_InvalidMidiFile );
  982. }
  983. song += 4;
  984. headersize = _MIDI_ReadNumber( song, 4 );
  985. song += 4;
  986. format = _MIDI_ReadNumber( song, 2 );
  987. _MIDI_NumTracks = _MIDI_ReadNumber( song + 2, 2 );
  988. _MIDI_Division = _MIDI_ReadNumber( song + 4, 2 );
  989. if ( _MIDI_Division < 0 )
  990. {
  991. // If a SMPTE time division is given, just set to 96 so no errors occur
  992. _MIDI_Division = 96;
  993. }
  994. if ( format > MAX_FORMAT )
  995. {
  996. return( MIDI_UnknownMidiFormat );
  997. }
  998. ptr = song + headersize;
  999. if ( _MIDI_NumTracks == 0 )
  1000. {
  1001. return( MIDI_NoTracks );
  1002. }
  1003. _MIDI_TrackMemSize = _MIDI_NumTracks * sizeof( track );
  1004. status = USRHOOKS_GetMem( &_MIDI_TrackPtr, _MIDI_TrackMemSize );
  1005. if ( status != USRHOOKS_Ok )
  1006. {
  1007. return( MIDI_NoMemory );
  1008. }
  1009. status = DPMI_LockMemory( _MIDI_TrackPtr, _MIDI_TrackMemSize );
  1010. if ( status != DPMI_Ok )
  1011. {
  1012. USRHOOKS_FreeMem( _MIDI_TrackPtr );
  1013. _MIDI_TrackPtr = NULL;
  1014. _MIDI_TrackMemSize = 0;
  1015. _MIDI_NumTracks = 0;
  1016. // MIDI_SetErrorCode( MIDI_DPMI_Error );
  1017. return( MIDI_Error );
  1018. }
  1019. CurrentTrack = _MIDI_TrackPtr;
  1020. numtracks = _MIDI_NumTracks;
  1021. while( numtracks-- )
  1022. {
  1023. if ( *( unsigned long * )ptr != MIDI_TRACK_SIGNATURE )
  1024. {
  1025. DPMI_UnlockMemory( _MIDI_TrackPtr, _MIDI_TrackMemSize );
  1026. USRHOOKS_FreeMem( _MIDI_TrackPtr );
  1027. _MIDI_TrackPtr = NULL;
  1028. _MIDI_TrackMemSize = 0;
  1029. return( MIDI_InvalidTrack );
  1030. }
  1031. tracklength = _MIDI_ReadNumber( ptr + 4, 4 );
  1032. ptr += 8;
  1033. CurrentTrack->start = ptr;
  1034. ptr += tracklength;
  1035. CurrentTrack++;
  1036. }
  1037. if ( _MIDI_Funcs->GetVolume != NULL )
  1038. {
  1039. _MIDI_TotalVolume = _MIDI_Funcs->GetVolume();
  1040. }
  1041. _MIDI_InitEMIDI();
  1042. if ( _MIDI_Funcs->LoadPatch )
  1043. {
  1044. MIDI_LoadTimbres();
  1045. }
  1046. _MIDI_ResetTracks();
  1047. if ( !Reset )
  1048. {
  1049. MIDI_Reset();
  1050. }
  1051. Reset = FALSE;
  1052. _MIDI_PlayRoutine = TS_ScheduleTask( _MIDI_ServiceRoutine, 100, 1, NULL );
  1053. // _MIDI_PlayRoutine = TS_ScheduleTask( test, 100, 1, NULL );
  1054. MIDI_SetTempo( 120 );
  1055. TS_Dispatch();
  1056. _MIDI_SongLoaded = TRUE;
  1057. _MIDI_SongActive = TRUE;
  1058. return( MIDI_Ok );
  1059. }
  1060. /*---------------------------------------------------------------------
  1061. Function: MIDI_SetTempo
  1062. Sets the song tempo.
  1063. ---------------------------------------------------------------------*/
  1064. void MIDI_SetTempo
  1065. (
  1066. int tempo
  1067. )
  1068. {
  1069. long tickspersecond;
  1070. MIDI_Tempo = tempo;
  1071. tickspersecond = ( tempo * _MIDI_Division ) / 60;
  1072. if ( _MIDI_PlayRoutine != NULL )
  1073. {
  1074. TS_SetTaskRate( _MIDI_PlayRoutine, tickspersecond );
  1075. // TS_SetTaskRate( _MIDI_PlayRoutine, tickspersecond / 4 );
  1076. }
  1077. _MIDI_FPSecondsPerTick = ( 1 << TIME_PRECISION ) / tickspersecond;
  1078. }
  1079. /*---------------------------------------------------------------------
  1080. Function: MIDI_GetTempo
  1081. Returns the song tempo.
  1082. ---------------------------------------------------------------------*/
  1083. int MIDI_GetTempo
  1084. (
  1085. void
  1086. )
  1087. {
  1088. return( MIDI_Tempo );
  1089. }
  1090. /*---------------------------------------------------------------------
  1091. Function: _MIDI_ProcessNextTick
  1092. Sets the position of the song pointer.
  1093. ---------------------------------------------------------------------*/
  1094. static int _MIDI_ProcessNextTick
  1095. (
  1096. void
  1097. )
  1098. {
  1099. int event;
  1100. int channel;
  1101. int command;
  1102. track *Track;
  1103. int tracknum;
  1104. int status;
  1105. int c1;
  1106. int c2;
  1107. int TimeSet = FALSE;
  1108. Track = _MIDI_TrackPtr;
  1109. tracknum = 0;
  1110. while( ( tracknum < _MIDI_NumTracks ) && ( Track != NULL ) )
  1111. {
  1112. while ( ( Track->active ) && ( Track->delay == 0 ) )
  1113. {
  1114. GET_NEXT_EVENT( Track, event );
  1115. if ( GET_MIDI_COMMAND( event ) == MIDI_SPECIAL )
  1116. {
  1117. switch( event )
  1118. {
  1119. case MIDI_SYSEX :
  1120. case MIDI_SYSEX_CONTINUE :
  1121. _MIDI_SysEx( Track );
  1122. break;
  1123. case MIDI_META_EVENT :
  1124. _MIDI_MetaEvent( Track );
  1125. break;
  1126. }
  1127. if ( Track->active )
  1128. {
  1129. Track->delay = _MIDI_ReadDelta( Track );
  1130. }
  1131. continue;
  1132. }
  1133. if ( event & MIDI_RUNNING_STATUS )
  1134. {
  1135. Track->RunningStatus = event;
  1136. }
  1137. else
  1138. {
  1139. event = Track->RunningStatus;
  1140. Track->pos--;
  1141. }
  1142. channel = GET_MIDI_CHANNEL( event );
  1143. command = GET_MIDI_COMMAND( event );
  1144. if ( _MIDI_CommandLengths[ command ] > 0 )
  1145. {
  1146. GET_NEXT_EVENT( Track, c1 );
  1147. if ( _MIDI_CommandLengths[ command ] > 1 )
  1148. {
  1149. GET_NEXT_EVENT( Track, c2 );
  1150. }
  1151. }
  1152. if ( _MIDI_RerouteFunctions[ channel ] != NULL )
  1153. {
  1154. status = _MIDI_RerouteFunctions[ channel ]( event, c1, c2 );
  1155. if ( status == MIDI_DONT_PLAY )
  1156. {
  1157. Track->delay = _MIDI_ReadDelta( Track );
  1158. continue;
  1159. }
  1160. }
  1161. switch ( command )
  1162. {
  1163. case MIDI_NOTE_OFF :
  1164. break;
  1165. case MIDI_NOTE_ON :
  1166. break;
  1167. case MIDI_POLY_AFTER_TCH :
  1168. if ( _MIDI_Funcs->PolyAftertouch )
  1169. {
  1170. _MIDI_Funcs->PolyAftertouch( channel, c1, c2 );
  1171. }
  1172. break;
  1173. case MIDI_CONTROL_CHANGE :
  1174. TimeSet = _MIDI_InterpretControllerInfo( Track, TimeSet,
  1175. channel, c1, c2 );
  1176. break;
  1177. case MIDI_PROGRAM_CHANGE :
  1178. if ( ( _MIDI_Funcs->ProgramChange ) &&
  1179. ( !Track->EMIDI_ProgramChange ) )
  1180. {
  1181. _MIDI_Funcs->ProgramChange( channel, c1 );
  1182. }
  1183. break;
  1184. case MIDI_AFTER_TOUCH :
  1185. if ( _MIDI_Funcs->ChannelAftertouch )
  1186. {
  1187. _MIDI_Funcs->ChannelAftertouch( channel, c1 );
  1188. }
  1189. break;
  1190. case MIDI_PITCH_BEND :
  1191. if ( _MIDI_Funcs->PitchBend )
  1192. {
  1193. _MIDI_Funcs->PitchBend( channel, c1, c2 );
  1194. }
  1195. break;
  1196. default :
  1197. break;
  1198. }
  1199. Track->delay = _MIDI_ReadDelta( Track );
  1200. }
  1201. Track->delay--;
  1202. Track++;
  1203. tracknum++;
  1204. if ( _MIDI_ActiveTracks == 0 )
  1205. {
  1206. break;
  1207. }
  1208. }
  1209. _MIDI_AdvanceTick();
  1210. return( TimeSet );
  1211. }
  1212. /*---------------------------------------------------------------------
  1213. Function: MIDI_SetSongTick
  1214. Sets the position of the song pointer.
  1215. ---------------------------------------------------------------------*/
  1216. void MIDI_SetSongTick
  1217. (
  1218. unsigned long PositionInTicks
  1219. )
  1220. {
  1221. if ( !_MIDI_SongLoaded )
  1222. {
  1223. return;
  1224. }
  1225. MIDI_PauseSong();
  1226. if ( PositionInTicks < _MIDI_PositionInTicks )
  1227. {
  1228. _MIDI_ResetTracks();
  1229. MIDI_Reset();
  1230. }
  1231. while( _MIDI_PositionInTicks < PositionInTicks )
  1232. {
  1233. if ( _MIDI_ProcessNextTick() )
  1234. {
  1235. break;
  1236. }
  1237. if ( _MIDI_ActiveTracks == 0 )
  1238. {
  1239. _MIDI_ResetTracks();
  1240. if ( !_MIDI_Loop )
  1241. {
  1242. return;
  1243. }
  1244. break;
  1245. }
  1246. }
  1247. MIDI_SetVolume( _MIDI_TotalVolume );
  1248. MIDI_ContinueSong();
  1249. }
  1250. /*---------------------------------------------------------------------
  1251. Function: MIDI_SetSongTime
  1252. Sets the position of the song pointer.
  1253. ---------------------------------------------------------------------*/
  1254. void MIDI_SetSongTime
  1255. (
  1256. unsigned long milliseconds
  1257. )
  1258. {
  1259. unsigned long mil;
  1260. unsigned long sec;
  1261. unsigned long newtime;
  1262. if ( !_MIDI_SongLoaded )
  1263. {
  1264. return;
  1265. }
  1266. MIDI_PauseSong();
  1267. mil = ( ( milliseconds % 1000 ) << TIME_PRECISION ) / 1000;
  1268. sec = ( milliseconds / 1000 ) << TIME_PRECISION;
  1269. newtime = sec + mil;
  1270. if ( newtime < _MIDI_Time )
  1271. {
  1272. _MIDI_ResetTracks();
  1273. MIDI_Reset();
  1274. }
  1275. while( _MIDI_Time < newtime )
  1276. {
  1277. if ( _MIDI_ProcessNextTick() )
  1278. {
  1279. break;
  1280. }
  1281. if ( _MIDI_ActiveTracks == 0 )
  1282. {
  1283. _MIDI_ResetTracks();
  1284. if ( !_MIDI_Loop )
  1285. {
  1286. return;
  1287. }
  1288. break;
  1289. }
  1290. }
  1291. MIDI_SetVolume( _MIDI_TotalVolume );
  1292. MIDI_ContinueSong();
  1293. }
  1294. /*---------------------------------------------------------------------
  1295. Function: MIDI_SetSongPosition
  1296. Sets the position of the song pointer.
  1297. ---------------------------------------------------------------------*/
  1298. void MIDI_SetSongPosition
  1299. (
  1300. int measure,
  1301. int beat,
  1302. int tick
  1303. )
  1304. {
  1305. unsigned long pos;
  1306. if ( !_MIDI_SongLoaded )
  1307. {
  1308. return;
  1309. }
  1310. MIDI_PauseSong();
  1311. pos = RELATIVE_BEAT( measure, beat, tick );
  1312. if ( pos < RELATIVE_BEAT( _MIDI_Measure, _MIDI_Beat, _MIDI_Tick ) )
  1313. {
  1314. _MIDI_ResetTracks();
  1315. MIDI_Reset();
  1316. }
  1317. while( RELATIVE_BEAT( _MIDI_Measure, _MIDI_Beat, _MIDI_Tick ) < pos )
  1318. {
  1319. if ( _MIDI_ProcessNextTick() )
  1320. {
  1321. break;
  1322. }
  1323. if ( _MIDI_ActiveTracks == 0 )
  1324. {
  1325. _MIDI_ResetTracks();
  1326. if ( !_MIDI_Loop )
  1327. {
  1328. return;
  1329. }
  1330. break;
  1331. }
  1332. }
  1333. MIDI_SetVolume( _MIDI_TotalVolume );
  1334. MIDI_ContinueSong();
  1335. }
  1336. /*---------------------------------------------------------------------
  1337. Function: MIDI_GetSongPosition
  1338. Returns the position of the song pointer in Measures, beats, ticks.
  1339. ---------------------------------------------------------------------*/
  1340. void MIDI_GetSongPosition
  1341. (
  1342. songposition *pos
  1343. )
  1344. {
  1345. unsigned long mil;
  1346. unsigned long sec;
  1347. mil = ( _MIDI_Time & ( ( 1 << TIME_PRECISION ) - 1 ) ) * 1000;
  1348. sec = _MIDI_Time >> TIME_PRECISION;
  1349. pos->milliseconds = ( mil >> TIME_PRECISION ) + ( sec * 1000 );
  1350. pos->tickposition = _MIDI_PositionInTicks;
  1351. pos->measure = _MIDI_Measure;
  1352. pos->beat = _MIDI_Beat;
  1353. pos->tick = _MIDI_Tick;
  1354. }
  1355. /*---------------------------------------------------------------------
  1356. Function: MIDI_GetSongLength
  1357. Returns the length of the song.
  1358. ---------------------------------------------------------------------*/
  1359. void MIDI_GetSongLength
  1360. (
  1361. songposition *pos
  1362. )
  1363. {
  1364. unsigned long mil;
  1365. unsigned long sec;
  1366. mil = ( _MIDI_TotalTime & ( ( 1 << TIME_PRECISION ) - 1 ) ) * 1000;
  1367. sec = _MIDI_TotalTime >> TIME_PRECISION;
  1368. pos->milliseconds = ( mil >> TIME_PRECISION ) + ( sec * 1000 );
  1369. pos->measure = _MIDI_TotalMeasures;
  1370. pos->beat = _MIDI_TotalBeats;
  1371. pos->tick = _MIDI_TotalTicks;
  1372. pos->tickposition = 0;
  1373. }
  1374. /*---------------------------------------------------------------------
  1375. Function: MIDI_InitEMIDI
  1376. Sets up the EMIDI
  1377. ---------------------------------------------------------------------*/
  1378. static void _MIDI_InitEMIDI
  1379. (
  1380. void
  1381. )
  1382. {
  1383. int event;
  1384. int command;
  1385. int channel;
  1386. int length;
  1387. int IncludeFound;
  1388. track *Track;
  1389. int tracknum;
  1390. int type;
  1391. int c1;
  1392. int c2;
  1393. type = EMIDI_GeneralMIDI;
  1394. switch( MUSIC_SoundDevice )
  1395. {
  1396. case SoundBlaster :
  1397. type = EMIDI_SoundBlaster;
  1398. break;
  1399. case ProAudioSpectrum :
  1400. type = EMIDI_ProAudio;
  1401. break;
  1402. case SoundMan16 :
  1403. type = EMIDI_SoundMan16;
  1404. break;
  1405. case Adlib :
  1406. type = EMIDI_Adlib;
  1407. break;
  1408. case GenMidi :
  1409. type = EMIDI_GeneralMIDI;
  1410. break;
  1411. case SoundCanvas :
  1412. type = EMIDI_SoundCanvas;
  1413. break;
  1414. case Awe32 :
  1415. type = EMIDI_AWE32;
  1416. break;
  1417. case WaveBlaster :
  1418. type = EMIDI_WaveBlaster;
  1419. break;
  1420. case SoundScape :
  1421. type = EMIDI_Soundscape;
  1422. break;
  1423. case UltraSound :
  1424. type = EMIDI_Ultrasound;
  1425. break;
  1426. }
  1427. _MIDI_ResetTracks();
  1428. _MIDI_TotalTime = 0;
  1429. _MIDI_TotalTicks = 0;
  1430. _MIDI_TotalBeats = 0;
  1431. _MIDI_TotalMeasures = 0;
  1432. Track = _MIDI_TrackPtr;
  1433. tracknum = 0;
  1434. while( ( tracknum < _MIDI_NumTracks ) && ( Track != NULL ) )
  1435. {
  1436. _MIDI_Tick = 0;
  1437. _MIDI_Beat = 1;
  1438. _MIDI_Measure = 1;
  1439. _MIDI_Time = 0;
  1440. _MIDI_BeatsPerMeasure = 4;
  1441. _MIDI_TicksPerBeat = _MIDI_Division;
  1442. _MIDI_TimeBase = 4;
  1443. _MIDI_PositionInTicks = 0;
  1444. _MIDI_ActiveTracks = 0;
  1445. _MIDI_Context = -1;
  1446. Track->RunningStatus = 0;
  1447. Track->active = TRUE;
  1448. Track->EMIDI_ProgramChange = FALSE;
  1449. Track->EMIDI_VolumeChange = FALSE;
  1450. Track->EMIDI_IncludeTrack = TRUE;
  1451. memset( Track->context, 0, sizeof( Track->context ) );
  1452. while( Track->delay > 0 )
  1453. {
  1454. _MIDI_AdvanceTick();
  1455. Track->delay--;
  1456. }
  1457. IncludeFound = FALSE;
  1458. while ( Track->active )
  1459. {
  1460. GET_NEXT_EVENT( Track, event );
  1461. if ( GET_MIDI_COMMAND( event ) == MIDI_SPECIAL )
  1462. {
  1463. switch( event )
  1464. {
  1465. case MIDI_SYSEX :
  1466. case MIDI_SYSEX_CONTINUE :
  1467. _MIDI_SysEx( Track );
  1468. break;
  1469. case MIDI_META_EVENT :
  1470. _MIDI_MetaEvent( Track );
  1471. break;
  1472. }
  1473. if ( Track->active )
  1474. {
  1475. Track->delay = _MIDI_ReadDelta( Track );
  1476. while( Track->delay > 0 )
  1477. {
  1478. _MIDI_AdvanceTick();
  1479. Track->delay--;
  1480. }
  1481. }
  1482. continue;
  1483. }
  1484. if ( event & MIDI_RUNNING_STATUS )
  1485. {
  1486. Track->RunningStatus = event;
  1487. }
  1488. else
  1489. {
  1490. event = Track->RunningStatus;
  1491. Track->pos--;
  1492. }
  1493. channel = GET_MIDI_CHANNEL( event );
  1494. command = GET_MIDI_COMMAND( event );
  1495. length = _MIDI_CommandLengths[ command ];
  1496. if ( command == MIDI_CONTROL_CHANGE )
  1497. {
  1498. if ( *Track->pos == MIDI_MONO_MODE_ON )
  1499. {
  1500. length++;
  1501. }
  1502. GET_NEXT_EVENT( Track, c1 );
  1503. GET_NEXT_EVENT( Track, c2 );
  1504. length -= 2;
  1505. switch( c1 )
  1506. {
  1507. case EMIDI_LOOP_START :
  1508. case EMIDI_SONG_LOOP_START :
  1509. if ( c2 == 0 )
  1510. {
  1511. Track->context[ 0 ].loopcount = EMIDI_INFINITE;
  1512. }
  1513. else
  1514. {
  1515. Track->context[ 0 ].loopcount = c2;
  1516. }
  1517. Track->context[ 0 ].pos = Track->pos;
  1518. Track->context[ 0 ].loopstart = Track->pos;
  1519. Track->context[ 0 ].RunningStatus = Track->RunningStatus;
  1520. Track->context[ 0 ].time = _MIDI_Time;
  1521. Track->context[ 0 ].FPSecondsPerTick = _MIDI_FPSecondsPerTick;
  1522. Track->context[ 0 ].tick = _MIDI_Tick;
  1523. Track->context[ 0 ].beat = _MIDI_Beat;
  1524. Track->context[ 0 ].measure = _MIDI_Measure;
  1525. Track->context[ 0 ].BeatsPerMeasure = _MIDI_BeatsPerMeasure;
  1526. Track->context[ 0 ].TicksPerBeat = _MIDI_TicksPerBeat;
  1527. Track->context[ 0 ].TimeBase = _MIDI_TimeBase;
  1528. break;
  1529. case EMIDI_LOOP_END :
  1530. case EMIDI_SONG_LOOP_END :
  1531. if ( c2 == EMIDI_END_LOOP_VALUE )
  1532. {
  1533. Track->context[ 0 ].loopstart = NULL;
  1534. Track->context[ 0 ].loopcount = 0;
  1535. }
  1536. break;
  1537. case EMIDI_INCLUDE_TRACK :
  1538. if ( EMIDI_AffectsCurrentCard( c2, type ) )
  1539. {
  1540. //printf( "Include track %d on card %d\n", tracknum, c2 );
  1541. IncludeFound = TRUE;
  1542. Track->EMIDI_IncludeTrack = TRUE;
  1543. }
  1544. else if ( !IncludeFound )
  1545. {
  1546. //printf( "Track excluded %d on card %d\n", tracknum, c2 );
  1547. IncludeFound = TRUE;
  1548. Track->EMIDI_IncludeTrack = FALSE;
  1549. }
  1550. break;
  1551. case EMIDI_EXCLUDE_TRACK :
  1552. if ( EMIDI_AffectsCurrentCard( c2, type ) )
  1553. {
  1554. //printf( "Exclude track %d on card %d\n", tracknum, c2 );
  1555. Track->EMIDI_IncludeTrack = FALSE;
  1556. }
  1557. break;
  1558. case EMIDI_PROGRAM_CHANGE :
  1559. if ( !Track->EMIDI_ProgramChange )
  1560. //printf( "Program change on track %d\n", tracknum );
  1561. Track->EMIDI_ProgramChange = TRUE;
  1562. break;
  1563. case EMIDI_VOLUME_CHANGE :
  1564. if ( !Track->EMIDI_VolumeChange )
  1565. //printf( "Volume change on track %d\n", tracknum );
  1566. Track->EMIDI_VolumeChange = TRUE;
  1567. break;
  1568. case EMIDI_CONTEXT_START :
  1569. if ( ( c2 > 0 ) && ( c2 < EMIDI_NUM_CONTEXTS ) )
  1570. {
  1571. Track->context[ c2 ].pos = Track->pos;
  1572. Track->context[ c2 ].loopstart = Track->context[ 0 ].loopstart;
  1573. Track->context[ c2 ].loopcount = Track->context[ 0 ].loopcount;
  1574. Track->context[ c2 ].RunningStatus = Track->RunningStatus;
  1575. Track->context[ c2 ].time = _MIDI_Time;
  1576. Track->context[ c2 ].FPSecondsPerTick = _MIDI_FPSecondsPerTick;
  1577. Track->context[ c2 ].tick = _MIDI_Tick;
  1578. Track->context[ c2 ].beat = _MIDI_Beat;
  1579. Track->context[ c2 ].measure = _MIDI_Measure;
  1580. Track->context[ c2 ].BeatsPerMeasure = _MIDI_BeatsPerMeasure;
  1581. Track->context[ c2 ].TicksPerBeat = _MIDI_TicksPerBeat;
  1582. Track->context[ c2 ].TimeBase = _MIDI_TimeBase;
  1583. }
  1584. break;
  1585. case EMIDI_CONTEXT_END :
  1586. break;
  1587. }
  1588. }
  1589. Track->pos += length;
  1590. Track->delay = _MIDI_ReadDelta( Track );
  1591. while( Track->delay > 0 )
  1592. {
  1593. _MIDI_AdvanceTick();
  1594. Track->delay--;
  1595. }
  1596. }
  1597. _MIDI_TotalTime = max( _MIDI_TotalTime, _MIDI_Time );
  1598. if ( RELATIVE_BEAT( _MIDI_Measure, _MIDI_Beat, _MIDI_Tick ) >
  1599. RELATIVE_BEAT( _MIDI_TotalMeasures, _MIDI_TotalBeats,
  1600. _MIDI_TotalTicks ) )
  1601. {
  1602. _MIDI_TotalTicks = _MIDI_Tick;
  1603. _MIDI_TotalBeats = _MIDI_Beat;
  1604. _MIDI_TotalMeasures = _MIDI_Measure;
  1605. }
  1606. Track++;
  1607. tracknum++;
  1608. }
  1609. _MIDI_ResetTracks();
  1610. }
  1611. /*---------------------------------------------------------------------
  1612. Function: MIDI_LoadTimbres
  1613. Preloads the timbres on cards that use patch-caching.
  1614. ---------------------------------------------------------------------*/
  1615. void MIDI_LoadTimbres
  1616. (
  1617. void
  1618. )
  1619. {
  1620. int event;
  1621. int command;
  1622. int channel;
  1623. int length;
  1624. int Finished;
  1625. track *Track;
  1626. int tracknum;
  1627. Track = _MIDI_TrackPtr;
  1628. tracknum = 0;
  1629. while( ( tracknum < _MIDI_NumTracks ) && ( Track != NULL ) )
  1630. {
  1631. Finished = FALSE;
  1632. while ( !Finished )
  1633. {
  1634. GET_NEXT_EVENT( Track, event );
  1635. if ( GET_MIDI_COMMAND( event ) == MIDI_SPECIAL )
  1636. {
  1637. switch( event )
  1638. {
  1639. case MIDI_SYSEX :
  1640. case MIDI_SYSEX_CONTINUE :
  1641. length = _MIDI_ReadDelta( Track );
  1642. Track->pos += length;
  1643. break;
  1644. case MIDI_META_EVENT :
  1645. GET_NEXT_EVENT( Track, command );
  1646. GET_NEXT_EVENT( Track, length );
  1647. if ( command == MIDI_END_OF_TRACK )
  1648. {
  1649. Finished = TRUE;
  1650. }
  1651. Track->pos += length;
  1652. break;
  1653. }
  1654. if ( !Finished )
  1655. {
  1656. _MIDI_ReadDelta( Track );
  1657. }
  1658. continue;
  1659. }
  1660. if ( event & MIDI_RUNNING_STATUS )
  1661. {
  1662. Track->RunningStatus = event;
  1663. }
  1664. else
  1665. {
  1666. event = Track->RunningStatus;
  1667. Track->pos--;
  1668. }
  1669. channel = GET_MIDI_CHANNEL( event );
  1670. command = GET_MIDI_COMMAND( event );
  1671. length = _MIDI_CommandLengths[ command ];
  1672. if ( command == MIDI_CONTROL_CHANGE )
  1673. {
  1674. if ( *Track->pos == MIDI_MONO_MODE_ON )
  1675. {
  1676. length++;
  1677. }
  1678. if ( *Track->pos == EMIDI_PROGRAM_CHANGE )
  1679. {
  1680. _MIDI_Funcs->LoadPatch( *( Track->pos + 1 ) );
  1681. }
  1682. }
  1683. if ( channel == MIDI_RHYTHM_CHANNEL )
  1684. {
  1685. if ( command == MIDI_NOTE_ON )
  1686. {
  1687. _MIDI_Funcs->LoadPatch( 128 + *Track->pos );
  1688. }
  1689. }
  1690. else
  1691. {
  1692. if ( command == MIDI_PROGRAM_CHANGE )
  1693. {
  1694. _MIDI_Funcs->LoadPatch( *Track->pos );
  1695. }
  1696. }
  1697. Track->pos += length;
  1698. _MIDI_ReadDelta( Track );
  1699. }
  1700. Track++;
  1701. tracknum++;
  1702. }
  1703. _MIDI_ResetTracks();
  1704. }
  1705. /*---------------------------------------------------------------------
  1706. Function: MIDI_LockEnd
  1707. Used for determining the length of the functions to lock in memory.
  1708. ---------------------------------------------------------------------*/
  1709. static void MIDI_LockEnd
  1710. (
  1711. void
  1712. )
  1713. {
  1714. }
  1715. /*---------------------------------------------------------------------
  1716. Function: MIDI_UnlockMemory
  1717. Unlocks all neccessary data.
  1718. ---------------------------------------------------------------------*/
  1719. void MIDI_UnlockMemory
  1720. (
  1721. void
  1722. )
  1723. {
  1724. DPMI_UnlockMemoryRegion( MIDI_LockStart, MIDI_LockEnd );
  1725. DPMI_UnlockMemory( ( void * )&_MIDI_CommandLengths[ 0 ],
  1726. sizeof( _MIDI_CommandLengths ) );
  1727. DPMI_Unlock( _MIDI_TrackPtr );
  1728. DPMI_Unlock( _MIDI_NumTracks );
  1729. DPMI_Unlock( _MIDI_SongActive );
  1730. DPMI_Unlock( _MIDI_SongLoaded );
  1731. DPMI_Unlock( _MIDI_Loop );
  1732. DPMI_Unlock( _MIDI_PlayRoutine );
  1733. DPMI_Unlock( _MIDI_Division );
  1734. DPMI_Unlock( _MIDI_ActiveTracks );
  1735. DPMI_Unlock( _MIDI_TotalVolume );
  1736. DPMI_Unlock( _MIDI_ChannelVolume );
  1737. DPMI_Unlock( _MIDI_Funcs );
  1738. DPMI_Unlock( _MIDI_PositionInTicks );
  1739. DPMI_Unlock( _MIDI_Division );
  1740. DPMI_Unlock( _MIDI_Tick );
  1741. DPMI_Unlock( _MIDI_Beat );
  1742. DPMI_Unlock( _MIDI_Measure );
  1743. DPMI_Unlock( _MIDI_Time );
  1744. DPMI_Unlock( _MIDI_BeatsPerMeasure );
  1745. DPMI_Unlock( _MIDI_TicksPerBeat );
  1746. DPMI_Unlock( _MIDI_TimeBase );
  1747. DPMI_Unlock( _MIDI_FPSecondsPerTick );
  1748. DPMI_Unlock( _MIDI_Context );
  1749. DPMI_Unlock( _MIDI_TotalTime );
  1750. DPMI_Unlock( _MIDI_TotalTicks );
  1751. DPMI_Unlock( _MIDI_TotalBeats );
  1752. DPMI_Unlock( _MIDI_TotalMeasures );
  1753. DPMI_Unlock( MIDI_Tempo );
  1754. }
  1755. /*---------------------------------------------------------------------
  1756. Function: MIDI_LockMemory
  1757. Locks all neccessary data.
  1758. ---------------------------------------------------------------------*/
  1759. int MIDI_LockMemory
  1760. (
  1761. void
  1762. )
  1763. {
  1764. int status;
  1765. status = DPMI_LockMemoryRegion( MIDI_LockStart, MIDI_LockEnd );
  1766. status |= DPMI_LockMemory( ( void * )&_MIDI_CommandLengths[ 0 ],
  1767. sizeof( _MIDI_CommandLengths ) );
  1768. status |= DPMI_Lock( _MIDI_TrackPtr );
  1769. status |= DPMI_Lock( _MIDI_NumTracks );
  1770. status |= DPMI_Lock( _MIDI_SongActive );
  1771. status |= DPMI_Lock( _MIDI_SongLoaded );
  1772. status |= DPMI_Lock( _MIDI_Loop );
  1773. status |= DPMI_Lock( _MIDI_PlayRoutine );
  1774. status |= DPMI_Lock( _MIDI_Division );
  1775. status |= DPMI_Lock( _MIDI_ActiveTracks );
  1776. status |= DPMI_Lock( _MIDI_TotalVolume );
  1777. status |= DPMI_Lock( _MIDI_ChannelVolume );
  1778. status |= DPMI_Lock( _MIDI_Funcs );
  1779. status |= DPMI_Lock( _MIDI_PositionInTicks );
  1780. status |= DPMI_Lock( _MIDI_Division );
  1781. status |= DPMI_Lock( _MIDI_Tick );
  1782. status |= DPMI_Lock( _MIDI_Beat );
  1783. status |= DPMI_Lock( _MIDI_Measure );
  1784. status |= DPMI_Lock( _MIDI_Time );
  1785. status |= DPMI_Lock( _MIDI_BeatsPerMeasure );
  1786. status |= DPMI_Lock( _MIDI_TicksPerBeat );
  1787. status |= DPMI_Lock( _MIDI_TimeBase );
  1788. status |= DPMI_Lock( _MIDI_FPSecondsPerTick );
  1789. status |= DPMI_Lock( _MIDI_Context );
  1790. status |= DPMI_Lock( _MIDI_TotalTime );
  1791. status |= DPMI_Lock( _MIDI_TotalTicks );
  1792. status |= DPMI_Lock( _MIDI_TotalBeats );
  1793. status |= DPMI_Lock( _MIDI_TotalMeasures );
  1794. status |= DPMI_Lock( MIDI_Tempo );
  1795. if ( status != DPMI_Ok )
  1796. {
  1797. MIDI_UnlockMemory();
  1798. // MIDI_SetErrorCode( MIDI_DPMI_Error );
  1799. return( MIDI_Error );
  1800. }
  1801. return( MIDI_Ok );
  1802. }