GUSMIDI.C 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  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. file: GUSMIDI.C
  17. author: James R. Dose
  18. date: March 23, 1994
  19. General MIDI playback functions for the Gravis Ultrasound
  20. (c) Copyright 1994 James R. Dose. All Rights Reserved.
  21. **********************************************************************/
  22. // Module MUST be compiled with structure allignment set to a maximum
  23. // of 1 byte ( zp1 ).
  24. #include <conio.h>
  25. #include <dos.h>
  26. #include <stdio.h>
  27. #include <io.h>
  28. #include <fcntl.h>
  29. #include <string.h>
  30. #include <stdlib.h>
  31. #include "usrhooks.h"
  32. #include "interrup.h"
  33. #include "newgf1.h"
  34. #include "gusmidi.h"
  35. #define TRUE ( 1 == 1 )
  36. #define FALSE ( !TRUE )
  37. // size of DMA buffer for patch loading
  38. #define DMABUFFSIZE 2048U
  39. #define MAX_MEM_CONFIG 3
  40. // size of patch array (128 perc, 128 melodic)
  41. #define NUM_PATCHES 256
  42. // size of largest patch name
  43. #define BIGGEST_NAME 9
  44. #define UNUSED_PATCH -1
  45. static struct patch Patch[ NUM_PATCHES ];
  46. static unsigned char *PatchWaves[ NUM_PATCHES ];
  47. static int PatchMap[ NUM_PATCHES ][ MAX_MEM_CONFIG + 1 ];
  48. static char ProgramName[ NUM_PATCHES ][ BIGGEST_NAME ];
  49. static char PatchLoaded[ NUM_PATCHES ];
  50. static char ConfigFileName[] = "ULTRAMID.INI";
  51. static char ConfigDirectory[ 80 ] = { '\0' };
  52. // The name of the configuration directory
  53. static char InstrumentDirectory[ 80 ];
  54. extern struct gf1_dma_buff GUS_HoldBuffer;
  55. extern unsigned long GUS_TotalMemory;
  56. extern int GUS_MemConfig;
  57. static int GUSMIDI_Volume = 255;
  58. extern int GUS_AuxError;
  59. extern int GUS_ErrorCode;
  60. int GUSMIDI_Installed = FALSE;
  61. #define GUS_SetErrorCode( status ) \
  62. GUS_ErrorCode = ( status );
  63. /*---------------------------------------------------------------------
  64. Function: GUS_GetPatchMap
  65. Reads the patch map from disk.
  66. ---------------------------------------------------------------------*/
  67. int GUS_GetPatchMap
  68. (
  69. char *name
  70. )
  71. {
  72. char text[ 80 ];
  73. char *ud;
  74. int index;
  75. int ignore;
  76. FILE *fp;
  77. for( index = 0; index < NUM_PATCHES; index++ )
  78. {
  79. PatchMap[ index ][ 0 ] = UNUSED_PATCH;
  80. PatchMap[ index ][ 1 ] = UNUSED_PATCH;
  81. PatchMap[ index ][ 2 ] = UNUSED_PATCH;
  82. PatchMap[ index ][ 3 ] = UNUSED_PATCH;
  83. ProgramName[ index ][ 0 ] = 0;
  84. }
  85. ud = getenv( "ULTRADIR" );
  86. if ( ud == NULL )
  87. {
  88. GUS_SetErrorCode( GUS_ULTRADIRNotSet );
  89. return( GUS_Error );
  90. }
  91. strcpy( InstrumentDirectory, ud );
  92. strcat( InstrumentDirectory, "\\midi\\" );
  93. strcpy( ConfigDirectory, ud );
  94. strcat( ConfigDirectory, "\\midi\\" );
  95. strcpy( text, name );
  96. fp = fopen( text, "r" );
  97. if ( fp == NULL )
  98. {
  99. strcpy( text, InstrumentDirectory );
  100. strcat( text, name );
  101. fp = fopen( text, "r" );
  102. if ( fp == NULL )
  103. {
  104. GUS_SetErrorCode( GUS_MissingConfig );
  105. return( GUS_Error );
  106. }
  107. }
  108. while( 1 )
  109. {
  110. if ( fgets( text, 80, fp ) == NULL )
  111. {
  112. break;
  113. }
  114. if ( text[ 0 ] == '#' )
  115. {
  116. continue;
  117. }
  118. if ( sscanf( text, "%d", &index ) != 1 )
  119. {
  120. continue;
  121. }
  122. sscanf( text, "%d, %d, %d, %d, %d, %s\n", &ignore,
  123. &PatchMap[ index ][ 0 ],
  124. &PatchMap[ index ][ 1 ],
  125. &PatchMap[ index ][ 2 ],
  126. &PatchMap[ index ][ 3 ],
  127. ProgramName[ index ] );
  128. }
  129. fclose( fp );
  130. return( GUS_Ok );
  131. }
  132. /*---------------------------------------------------------------------
  133. Function: GUSMIDI_UnloadPatch
  134. Unloads a patch from the GUS's memory.
  135. ---------------------------------------------------------------------*/
  136. int GUSMIDI_UnloadPatch
  137. (
  138. int prognum
  139. )
  140. {
  141. int prog;
  142. unsigned flags;
  143. prog = PatchMap[ prognum ][ GUS_MemConfig ];
  144. if ( PatchLoaded[ prog ] )
  145. {
  146. flags = DisableInterrupts();
  147. gf1_unload_patch( &Patch[ prog ] );
  148. if ( PatchWaves[ prog ] != NULL )
  149. {
  150. USRHOOKS_FreeMem( PatchWaves[ prog ] );
  151. PatchWaves[ prog ] = NULL;
  152. }
  153. // just in case sequence is still playing
  154. Patch[ prog ].nlayers = 0;
  155. PatchLoaded[ prog ] = FALSE;
  156. RestoreInterrupts( flags );
  157. }
  158. return( GUS_Ok );
  159. }
  160. /*---------------------------------------------------------------------
  161. Function: GUSMIDI_LoadPatch
  162. Loads a patch into the GUS's memory.
  163. ---------------------------------------------------------------------*/
  164. int GUSMIDI_LoadPatch
  165. (
  166. int prognum
  167. )
  168. {
  169. int prog;
  170. char text[ 80 ];
  171. int ret;
  172. unsigned char *wave_buff;
  173. struct patchinfo patchi;
  174. int status;
  175. prog = PatchMap[ prognum ][ GUS_MemConfig ];
  176. if ( ( PatchLoaded[ prog ] ) || ( prog == UNUSED_PATCH ) )
  177. {
  178. return( GUS_Ok );
  179. }
  180. if ( !ProgramName[ prog ][ 0 ] )
  181. {
  182. return( GUS_Ok );
  183. }
  184. strcpy( text, InstrumentDirectory );
  185. strcat( text, ProgramName[ prog ] );
  186. strcat( text, ".pat" );
  187. ret = gf1_get_patch_info( text, &patchi );
  188. if ( ret != OK )
  189. {
  190. GUS_AuxError = ret;
  191. GUS_SetErrorCode( GUS_GF1Error );
  192. return( GUS_Error );
  193. }
  194. status = USRHOOKS_GetMem( &wave_buff, patchi.header.wave_forms *
  195. sizeof( struct wave_struct ) );
  196. if ( status != USRHOOKS_Ok )
  197. {
  198. GUS_SetErrorCode( GUS_OutOfMemory );
  199. return( GUS_Error );
  200. }
  201. ret = gf1_load_patch( text, &patchi, &Patch[ prog ], &GUS_HoldBuffer,
  202. DMABUFFSIZE, ( unsigned char * )wave_buff, PATCH_LOAD_8_BIT );
  203. if ( ret != OK )
  204. {
  205. USRHOOKS_FreeMem( wave_buff );
  206. GUS_AuxError = ret;
  207. GUS_SetErrorCode( GUS_GF1Error );
  208. return( GUS_Error );
  209. }
  210. PatchWaves[ prog ] = wave_buff;
  211. PatchLoaded[ prog ] = TRUE;
  212. return( GUS_Ok );
  213. }
  214. /*---------------------------------------------------------------------
  215. Function: GUSMIDI_ProgramChange
  216. Selects the instrument to use on the specified MIDI channel.
  217. ---------------------------------------------------------------------*/
  218. void GUSMIDI_ProgramChange
  219. (
  220. int channel,
  221. int prognum
  222. )
  223. {
  224. int prog;
  225. prog = PatchMap[ prognum ][ GUS_MemConfig ];
  226. if ( PatchLoaded[ prog ] )
  227. {
  228. gf1_midi_change_program( &Patch[ prog ], channel );
  229. }
  230. else
  231. {
  232. gf1_midi_change_program( NULL, channel );
  233. }
  234. }
  235. /*---------------------------------------------------------------------
  236. Function: GUSMIDI_NoteOn
  237. Plays a note on the specified channel.
  238. ---------------------------------------------------------------------*/
  239. void GUSMIDI_NoteOn
  240. (
  241. int chan,
  242. int note,
  243. int velocity
  244. )
  245. {
  246. int prog;
  247. if ( chan == 9 )
  248. {
  249. prog = PatchMap[ note + 128 ][ GUS_MemConfig ];
  250. if ( PatchLoaded[ prog ] )
  251. {
  252. gf1_midi_note_on( &Patch[ note + 128 ], 1,
  253. note, velocity, 9 );
  254. }
  255. }
  256. else
  257. {
  258. gf1_midi_note_on( 0L, 1, note, velocity, chan );
  259. }
  260. }
  261. /*---------------------------------------------------------------------
  262. Function: GUSMIDI_NoteOff
  263. Turns off a note on the specified channel.
  264. ---------------------------------------------------------------------*/
  265. #pragma warn -par
  266. void GUSMIDI_NoteOff
  267. (
  268. int chan,
  269. int note,
  270. int velocity
  271. )
  272. {
  273. gf1_midi_note_off( note, chan );
  274. }
  275. #pragma warn .par
  276. /*---------------------------------------------------------------------
  277. Function: GUSMIDI_ControlChange
  278. Sets the value of a controller on the specified channel.
  279. ---------------------------------------------------------------------*/
  280. void GUSMIDI_ControlChange
  281. (
  282. int channel,
  283. int number,
  284. int value
  285. )
  286. {
  287. gf1_midi_parameter( channel, number, value );
  288. }
  289. /*---------------------------------------------------------------------
  290. Function: GUSMIDI_PitchBend
  291. Sets the pitch bend on the specified MIDI channel.
  292. ---------------------------------------------------------------------*/
  293. void GUSMIDI_PitchBend
  294. (
  295. int channel,
  296. int lsb,
  297. int msb
  298. )
  299. {
  300. gf1_midi_pitch_bend( channel, lsb, msb );
  301. }
  302. /*---------------------------------------------------------------------
  303. Function: GUSMIDI_ReleasePatches
  304. Removes all the instruments from the GUS's memory.
  305. ---------------------------------------------------------------------*/
  306. void GUSMIDI_ReleasePatches
  307. (
  308. void
  309. )
  310. {
  311. int i;
  312. for( i = 0; i < 256; i++ )
  313. {
  314. GUSMIDI_UnloadPatch( i );
  315. }
  316. }
  317. /*---------------------------------------------------------------------
  318. Function: GUSMIDI_SetVolume
  319. Sets the total music volume.
  320. ---------------------------------------------------------------------*/
  321. void GUSMIDI_SetVolume
  322. (
  323. int volume
  324. )
  325. {
  326. // Set the minimum to 2 because 0 has a tremolo problem
  327. volume = max( 2, volume );
  328. volume = min( volume, 255 );
  329. GUSMIDI_Volume = volume;
  330. // range = 0 to 127
  331. gf1_midi_synth_volume( 0, volume >> 1 );
  332. }
  333. /*---------------------------------------------------------------------
  334. Function: GUSMIDI_GetVolume
  335. Returns the total music volume.
  336. ---------------------------------------------------------------------*/
  337. int GUSMIDI_GetVolume
  338. (
  339. void
  340. )
  341. {
  342. return( GUSMIDI_Volume );
  343. }
  344. /*---------------------------------------------------------------------
  345. Function: GUSMIDI_Init
  346. Initializes the Gravis Ultrasound for music playback.
  347. ---------------------------------------------------------------------*/
  348. int GUSMIDI_Init
  349. (
  350. void
  351. )
  352. {
  353. int ret;
  354. int i;
  355. int startmem;
  356. // unsigned long mem;
  357. extern int GUSWAVE_Installed;
  358. if ( GUSMIDI_Installed )
  359. {
  360. GUSMIDI_Shutdown();
  361. }
  362. ret = GUS_Init();
  363. if ( ret != GUS_Ok )
  364. {
  365. return( ret );
  366. }
  367. if ( GUS_MemConfig < 0 )
  368. {
  369. GUS_MemConfig = 0;
  370. }
  371. if ( GUS_MemConfig > MAX_MEM_CONFIG )
  372. {
  373. GUS_MemConfig = MAX_MEM_CONFIG;
  374. }
  375. for( i = 0; i < NUM_PATCHES; i++ )
  376. {
  377. ProgramName[ i ][ 0 ] = '\0';
  378. PatchWaves[ i ] = NULL;
  379. PatchLoaded[ i ] = FALSE;
  380. }
  381. GUSMIDI_SetVolume( 255 );
  382. GUSMIDI_Installed = TRUE;
  383. ret = GUS_GetPatchMap( ConfigFileName );
  384. if ( ret != GUS_Ok )
  385. {
  386. GUSMIDI_Shutdown();
  387. return( ret );
  388. }
  389. // if ( !GUSWAVE_Installed )
  390. // {
  391. // mem = gf1_malloc( 8192 );
  392. // }
  393. startmem = gf1_mem_avail();
  394. for( i = 0; i < NUM_PATCHES; i++ )
  395. {
  396. ret = GUSMIDI_LoadPatch( i );
  397. if ( ret != GUS_Ok )
  398. {
  399. }
  400. // if ( ret != GUS_Ok )
  401. // {
  402. // return( ret );
  403. // }
  404. }
  405. // if ( !GUSWAVE_Installed )
  406. // {
  407. // gf1_free( mem );
  408. // }
  409. GUSMIDI_Installed = TRUE;
  410. return( GUS_Ok );
  411. }
  412. /*---------------------------------------------------------------------
  413. Function: GUSMIDI_Shutdown
  414. Ends use of the Gravis Ultrasound for music playback.
  415. ---------------------------------------------------------------------*/
  416. void GUSMIDI_Shutdown
  417. (
  418. void
  419. )
  420. {
  421. GUSMIDI_ReleasePatches();
  422. GUS_Shutdown();
  423. GUSMIDI_Installed = FALSE;
  424. }