home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / genmidi.zip / genmidi.INF (.txt) < prev    next >
OS/2 Help File  |  1995-08-04  |  21KB  |  515 lines

  1.  
  2. ΓòÉΓòÉΓòÉ 1. Introduction ΓòÉΓòÉΓòÉ
  3.  
  4.                            GENMIDI Programmer's Manual
  5.  
  6. General MIDI is a specification that standardizes the setup of sound modules 
  7. such that a MIDI file (containing Program Change, Controller, Pitch Wheel, and 
  8. Note events) designed to be played upon one GM module should sound relatively 
  9. similiar upon another GM module, even an entirely different model made by 
  10. another manufacturer.  For a lengthy description of General MIDI, please read 
  11. my "MIDI Book" (a collection of OS/2 INF files to be read by VIEW, detailing 
  12. the MIDI spec).  This manual assumes that you're familiar with General MIDI. 
  13.  
  14. Since many MIDI applications need to deal with General MIDI, often displaying 
  15. those 128 GM Patch names, defined Controller names, and the GM Drum Key names, 
  16. it made sense to put all of those ascii strings into one shared dynamic link 
  17. library.  But more than that, I found that I was using several related routines 
  18. in all of my MIDI apps.  For example, frequently I needed to look up the 
  19. program number that was associated with a given GM Patch name.  For example, if 
  20. the user typed "Grand Piano" into some entry control, I needed to look up what 
  21. program number that was (ie, 0), in order to construct a MIDI Program Change 
  22. message to select the Grand Piano patch.  So, I decided that, in addition to 
  23. putting the full set of GM Patch names, defined MIDI Controller names, and GM 
  24. Drum Key names in the DLL, I also would put some related routines in the DLL. 
  25. There's a routine to look up a program number based upon a GM Patch name. 
  26. There's a complementary routine to look up a GM Patch name based upon a program 
  27. number.  There's a routine to look up a controller number based upon a defined 
  28. Controller name.  There's a complementary routine to look up a Controller name 
  29. based upon a controller number.  There's a routine to look up a note number 
  30. based upon a GM Drum Key name.  There's a complementary routine to look up a GM 
  31. Drum Key name based upon a note number.  In addition, there are two 
  32. complementary routines; one takes a MIDI note number and returns a note name 
  33. (as a musician might specify it, with a note letter and octave, for example 
  34. "C3"), and the other takes a note name and returns its respective MIDI note 
  35. number. 
  36.  
  37. GENMIDI.DLL is an OS/2 2.X Dynamic Link Library (DLL) that a programmer can use 
  38. to simplify writing OS/2 applications that deal with General MIDI and MIDI 
  39. Controllers. 
  40.  
  41. Many programs can be using that one copy of the DLL simultaneously, thus 
  42. reducing redundant code that eats up RAM needlessly.  Furthermore, the DLL 
  43. helps to eliminate discrepancies and incompatibilities in the way that two 
  44. programs name GM Patches, GM Drum Keys, and MIDI Controllers, as well as 
  45. assigning note names to MIDI note number, if both programs use this DLL, since 
  46. both will be using the same ascii strings and look-up routines. 
  47.  
  48. To avoid source code name conflicts with DLL functions and data, avoid naming 
  49. any of your functions and data starting with the letters Midi. 
  50.  
  51.  
  52. ΓòÉΓòÉΓòÉ 2. Copyright Notice ΓòÉΓòÉΓòÉ
  53.  
  54. This OS/2 Online Book and the related files, GENMIDI.DLL, GENMIDI.H, 
  55. GENMIDI.LIB, and examples for using GENMIDI.DLL are all copyright 1995 by Jeff 
  56. Glatt.  These files are freely redistributable, and may be used by and 
  57. distributed along with any software, be it commercial or otherwise, provided 
  58. that these files are not internally modified, nor specifically sold as a 
  59. complete product by themselves.  The only price that you have to pay is the one 
  60. that you're already paying by spending all of your time in front of a computer 
  61. instead of developing healthier outlets. 
  62.  
  63. NOT SO STANDARD DISCLAIMER: 
  64.  
  65. These programs are provided "as is" without warranty of any kind either 
  66. expressed or implied or tatooed in a place that only a few people have ever 
  67. seen, including but not limited to the implied warranties of merchantability, 
  68. fitness for a particular purpose, and the dubious assumption that the software 
  69. has been created by a sane individual who would never do anything that may hurt 
  70. you. The entire risk as to the results and performance of the programs is 
  71. assumed by you or someone who looks exactly like you.  Jeff Glatt does not 
  72. guarantee that the functions in these programs will meet your requirements, 
  73. especially if your requirements involve lots of latex and some docile, 
  74. domesticated animal.  Nor does Jeff Glatt warranty the programs to be 
  75. uninterruptable or error-free, although mercifully free of "General Protection 
  76. Faults".  If you use said programs, you can not say anything nasty about the 
  77. author, even if the programs inadvertently cause the erasure of your collection 
  78. of X-rated GIFs of a conservative, overweight and overrated TV "personality" 
  79. plooking himself vigorously with his royalty checks from some rancid paperback. 
  80. Jeff Glatt is not responsible for any damages as a result of anything that he 
  81. has done, or hasn't done, or was supposed to do but never got around to it, and 
  82. furthermore, he doesn't even care so leave him alone, ratface.  You may have 
  83. more or less protections in certain states of the union, depending upon how far 
  84. your local politician is willing to bend over for some bribe from a business 
  85. lobbyist.  Just remember that Jeff Glatt has no money, so don't bother suing 
  86. him as a result of any damages caused by this OS/2 program.  Tell your greasy 
  87. lawyer to go after IBM, and make sure that you pick 12 really stupid pinheads 
  88. for the jury.  If swallowed, induce vomiting immediately by contemplating the 
  89. asthetics of Microsoft Windows. 
  90.  
  91. OS/2 is a trademark of International Business Machines Corporation. 
  92.  
  93. Windows is a trademark of Microsoft Incorporated, and furthermore, Bill Gates 
  94. is to blame for it. 
  95.  
  96. If you have suggestions, comments, criticisms, and anything else other than 
  97. dollar bills, then send them to someone else because you got it for free, and 
  98. you know what you get for nothing?  But, if you do need to contact the author, 
  99. then either phone some of the more prominent psychiatrict clinics in central 
  100. New York state, or try this: 
  101.  
  102. Jeff Glatt 
  103. 6 Sycamore Drive East 
  104. New Hartford, NY 13413 
  105. (315) 735-5350 
  106.  
  107.  
  108. ΓòÉΓòÉΓòÉ 3. Archive ΓòÉΓòÉΓòÉ
  109.  
  110. The GENMIDI archive consists of the DLL and several example applications with 
  111. source code.  The DLL itself is named GENMIDI.DLL, and must be copied to one of 
  112. the directories specified by the LIBPATH statement in your config.sys file. 
  113. Usually, one of the specified directories is .;, which means that the DLL can 
  114. be placed in the same directory as the applications.  The applications will not 
  115. run if the DLL isn't placed somewhere in your LIBPATH.  These applications are 
  116. designed to be run from an OS/2 command line. 
  117.  
  118. For compiling apps, you'll need GENMIDI.H and GENMIDI.LIB copied to where you 
  119. keep your C include files and C link libraries respectively, although these 
  120. files aren't needed by the executables you produce.  Of course, GENMIDI.DLL 
  121. should be included with your executable if you distribute that executable, and 
  122. the user should be instructed to copy GENMIDI.DLL to his LIBPATH. 
  123.  
  124.  
  125. ΓòÉΓòÉΓòÉ 4. Functions for GM Patches ΓòÉΓòÉΓòÉ
  126.  
  127. There are two functions dealing with GM Patches.  MidiGetPgmNum() looks up a 
  128. program number based upon a GM Patch name passed to it.  MidiGetPgmStr() looks 
  129. up a GM Patch name based upon a program number passed to it. 
  130.  
  131.  
  132. ΓòÉΓòÉΓòÉ 4.1. MidiGetPgmNum() ΓòÉΓòÉΓòÉ
  133.  
  134. Template 
  135.  
  136. UCHAR MidiGetPgmNum(UCHAR * PgmName); 
  137.  
  138. Description 
  139.  
  140. This is passed a null-terminated string containing a Patch name, for example 
  141. "Grand Piano".  It tries to find a match to one of the defined GM Patch names, 
  142. and returns the respective Program number (ie, to be used in a MIDI Program 
  143. Change message) for that Patch.  Leading and trailing blanks upon the string 
  144. are ignored.  Also, upper or lower case is irrelevant.  Furthermore, the string 
  145. can be a substring of a GM Patch name.  For example, if the string is simply 
  146. "Clav", then the DLL considers this to match the first GM Patch with "Clav" 
  147. somewhere in its name, which would be "Clavinet".  Or, if the string is "Bell", 
  148. then the DLL would match this with "Tubular Bells".  Note that the GM Patch 
  149. name containing the substring closest to the beginning of the GM name is 
  150. matched.  For example, "Harp" matches "Harpsichord" rather than "Orch. Harp". 
  151.  
  152. If the passed string does not match any GM Patch name (or isn't a substring of 
  153. one), then a Program number of 0xFF is returned.  Being that allowable MIDI 
  154. Program numbers are 0 to 127, 0xFF can only be construed as "no matching GM 
  155. Patch found". 
  156.  
  157. Example 
  158.  
  159. printf("Grand Piano is Program %d\n", MidiGetPgmNum("Grand")); 
  160.  
  161. The example PGMNUM.C demonstrates using MidiGetPgmNum(). 
  162.  
  163.  
  164. ΓòÉΓòÉΓòÉ 4.2. MidiGetPgmStr() ΓòÉΓòÉΓòÉ
  165.  
  166. Template 
  167.  
  168. UCHAR * MidiGetPgmStr(UCHAR PgmNumber); 
  169.  
  170. Description 
  171.  
  172. This is passed a program number (ie, 0 to 127 inclusive), and it returns a 
  173. null-terminated string containing the respective GM Patch name, for example a 
  174. program number of 0 returns "Grand Piano".  Program numbers > 127 return a null 
  175. string (ie, pointer to a null byte). 
  176.  
  177. Example 
  178.  
  179. printf("Program 1 is %s\n", MidiGetPgmStr(1)); 
  180.  
  181. The example PGMNAME.C demonstrates using MidiGetPgmStr().  It also can be used 
  182. to display all 128 GM Patch names (ie, the ascii strings) within GENMIDI.DLL. 
  183.  
  184.  
  185. ΓòÉΓòÉΓòÉ 5. Functions for GM Drum Keys ΓòÉΓòÉΓòÉ
  186.  
  187. There are two functions dealing with GM Drum Keys.  MidiGetDrumNum() looks up a 
  188. note number based upon a GM Drum Key name passed to it.  MidiGetDrumStr() looks 
  189. up a GM Drum Key name based upon a note number passed to it. 
  190.  
  191.  
  192. ΓòÉΓòÉΓòÉ 5.1. MidiGetDrumNum() ΓòÉΓòÉΓòÉ
  193.  
  194. Template 
  195.  
  196. UCHAR MidiGetDrumNum(UCHAR * DrumArray, UCHAR  * DrumKeyName); 
  197.  
  198. Description 
  199.  
  200. This is passed a null-terminated string containing a Drum Key name, for example 
  201. "Kick 1".  It tries to find a match to one of the defined GM Drum Key names, 
  202. and returns the respective note number (ie, to be used in MIDI note messages to 
  203. play that drum sound).  Leading and trailing blanks upon the string are 
  204. ignored.  Also, upper or lower case is irrelevant.  Furthermore, the string can 
  205. be a substring of a Drum Key name.  For example, if the string is simply 
  206. "Snare", then the DLL considers this to match the first Drum Key with "Snare" 
  207. somewhere in its name, which would be "Snare 1".  Or, if the string is "Tom", 
  208. then the DLL would match this with "Low 2 Tom".  Note that the GM Drum Key name 
  209. containing the substring closest to the beginning of the GM name is matched. 
  210. For example, "HiHat" matches "Open HiHat" rather than "Closed HiHat" or "Pedal 
  211. HiHat". 
  212.  
  213. Not all 128 possible MIDI note numbers have a defined drum sound assigned to 
  214. them.  For example, note numbers below 35 and above 81 have no drum sounds 
  215. assigned to them by the GM specification.  On the other hand, many 
  216. manufacturers make modules that have a larger drum kit than the GM spec, and 
  217. they use these unassigned note numbers to play the extra drum sounds. 
  218. MidiGetDrumNum() therefore allows a second parameter to be passed to it, 
  219. pointing to an array that defines the names of any extra Drum Keys (ie, sounds) 
  220. in a kit, plus their note numbers.  This is useful if your software is used for 
  221. a specific module that extends the GM Drum Kit.  For each drum sound, there is 
  222. a length byte of its name, (counting the terminating null), then a byte 
  223. representing the MIDI Note number that the sound is mapped to, and then the 
  224. null-terminated name.  After the last drum sound, an extra null byte ends the 
  225. array. 
  226.  
  227. For example, assume that you have a module with 2 extra drum sounds which you 
  228. wish to name "Big Boom" and "Little Boom".  These are assigned to MIDI note 
  229. numbers 126 and 127 respectively.  You would make an array as so: 
  230.  
  231. UCHAR my_array[] = { 9,126,'B','i','g',' ','B','o','o','m',0, 
  232. 12,127,'L','i','t','t','l','e',' ','B','o','o','m',0,  0 }; 
  233.  
  234. Now you can pass this to MidiGetDrumNum(), which will search this array first 
  235. when matching any passed string.  For example, the following call returns a 
  236. note number of 127. 
  237.  
  238. note_number = MidiGetDrumNum(&my_array[0], "Little"); 
  239.  
  240. Note that substring matching and case-insensitivity applies to matching the 
  241. contents of your array. 
  242.  
  243. Because the contents of the array are searched before the standard GM Drum Key 
  244. names, you can even replace any of the standard names.  For example, in the 
  245. standard Kit, note number 43 is "Low 1 Tom".  Perhaps you have a module that 
  246. has various drum kits.  Switching to an "Orchestral Kit" causes the Low 1 Tom 
  247. sound to be replaced by a Timpani, but the rest of the Kit's Drum Keys remain 
  248. the same as the standard kit.  Therefore, you can replace just the Low 1 Tom by 
  249. passing an array that sets note number 43 to "Timpani", as so: 
  250.  
  251. UCHAR my_array[] = { 8,43,'T','i','m','p','a','n','i',0,  0 }; 
  252. note_number = MidiGetDrumNum(&my_array[0], "TIMPANI");  /* returns note number 
  253. 43 */ 
  254.  
  255. If you have no extensions or replacements to the GM Kit, then simply pass a 0 
  256. instead of a pointer to an array. 
  257.  
  258. If the passed string does not match any GM Drum Key name (or isn't a substring 
  259. of one), then a note number of 0xFF is returned.  Being that allowable MIDI 
  260. note numbers are 0 to 127, 0xFF can only be construed as "no matching GM Drum 
  261. Key found". 
  262.  
  263. Example 
  264.  
  265. The example DRUMNUM.C demonstrates using MidiGetDrumNum(). 
  266.  
  267.  
  268. ΓòÉΓòÉΓòÉ 5.2. MidiGetDrumStr() ΓòÉΓòÉΓòÉ
  269.  
  270. Template 
  271.  
  272. UCHAR * MidiGetDrumStr(UCHAR * DrumArray, UCHAR NoteNumber); 
  273.  
  274. Description 
  275.  
  276. This is passed a note number (ie, 0 to 127 inclusive), and it returns a 
  277. null-terminated string containing the respective Drum Key name, for example a 
  278. note number of 36 returns "Kick 1".  Note numbers > 127, or a note number for 
  279. which there is no defined Drum Key in the GM Kit, return a null string (ie, 
  280. pointer to a null byte). 
  281.  
  282. A pointer to an array that defines the names of any extra Drum Keys (ie, 
  283. sounds) in a kit, plus their note numbers, may be passed as well.  See the 
  284. discussion in MidiGetDrumNum() for the purpose and setup of the array.  If 
  285. passed a 0, then only the standard GM Drum Kit is considered. 
  286.  
  287. Example 
  288.  
  289. printf("Drum Key 36 is %s\n", MidiGetDrumStr(0, 36)); 
  290.  
  291. The example DRUMKEY.C demonstrates using MidiGetDrumStr().  It also can be used 
  292. to display all defined GM Drum Key names (ie, the ascii strings) within 
  293. GENMIDI.DLL. 
  294.  
  295.  
  296. ΓòÉΓòÉΓòÉ 6. Functions for MIDI Controllers ΓòÉΓòÉΓòÉ
  297.  
  298. There are four functions dealing with MIDI Controllers.  MidiGetCtlNum() or 
  299. MidiGetCtlNum2() looks up a controller number based upon a Controller name 
  300. passed to it.  MidiGetCtlStr() or MidiGetCtlStr2() looks up a Controller name 
  301. based upon a controller number passed to it. 
  302.  
  303.  
  304. ΓòÉΓòÉΓòÉ 6.1. MidiGetCtlNum() ΓòÉΓòÉΓòÉ
  305.  
  306. Template 
  307.  
  308. UCHAR MidiGetCtlNum(UCHAR * CtlName); 
  309.  
  310. Description 
  311.  
  312. This is passed a null-terminated string containing a Controller name, for 
  313. example "Mod H".  It tries to find a match to one of the defined MIDI 
  314. Controller names, and returns the respective controller number (ie, to be used 
  315. in a MIDI Controller message).  Leading and trailing blanks upon the string are 
  316. ignored.  Also, upper or lower case is irrelevant.  Furthermore, the string can 
  317. be a substring of the Controller name.  For example, if the string is simply 
  318. "Mod", then the DLL considers this to match the first Controller whose name 
  319. begins with "Mod", which would be "Mod H".  The substring match must be at the 
  320. head of the string.  For example, "+" does not match "Data +", but "Dat" does. 
  321.  
  322. If the passed string does not match any MIDI Controller name (or isn't a 
  323. substring of one), then a controller number of 0xFF is returned.  Being that 
  324. allowable MIDI controller numbers are 0 to 127, 0xFF can only be construed as 
  325. "no matching Controller found". 
  326.  
  327. Example 
  328.  
  329. printf("The Mod H Controller is #%d\n", MidiGetCtlNum("Mod")); 
  330.  
  331. The example CTLNUM.C demonstrates using MidiGetCtlNum(). 
  332.  
  333.  
  334. ΓòÉΓòÉΓòÉ 6.2. MidiGetCtlStr() ΓòÉΓòÉΓòÉ
  335.  
  336. Template 
  337.  
  338. UCHAR * MidiGetCtlStr(UCHAR CtlNumber); 
  339.  
  340. Description 
  341.  
  342. This is passed a controller number (ie, 0 to 127 inclusive), and it returns a 
  343. null-terminated string containing the respective MIDI Controller name, for 
  344. example a controller number of 1 returns "Mod H".  Controller numbers > 127, or 
  345. a controller number for which there is no defined Controller assigned to it, 
  346. return a null string (ie, pointer to a null byte). 
  347.  
  348. Example 
  349.  
  350. printf("Controller #1 is %s\n", MidiGetCtlStr(1)); 
  351.  
  352. The example CTLNAME.C demonstrates using MidiGetCtlStr().  It also can be used 
  353. to display all defined Controller names (ie, the ascii strings) within 
  354. GENMIDI.DLL. 
  355.  
  356.  
  357. ΓòÉΓòÉΓòÉ 6.3. MidiGetCtlNum2() ΓòÉΓòÉΓòÉ
  358.  
  359. Template 
  360.  
  361. UCHAR MidiGetCtlNum2(UCHAR * CtlArray, UCHAR  * CtlName); 
  362.  
  363. Description 
  364.  
  365. Not all 128 possible MIDI controller numbers have a defined parameter assigned 
  366. to them.  For example, controller number 105 has no defined parameter assigned 
  367. to it by the MIDI specification.  On the other hand, many manufacturers make 
  368. modules that allow these unassigned controller numbers to be used to control 
  369. some parameter.  MidiGetCtlNum2() therefore allows a second parameter to be 
  370. passed to it, pointing to an array that defines the names of any extra 
  371. controllers, plus their controller numbers.  This is useful if your software is 
  372. used for a specific module that uses these extra controller numbers.  For each 
  373. controller, there is a length byte of its name, (counting the terminating 
  374. null), then a byte representing its MIDI controller number, and then the 
  375. null-terminated name.  After the last controller, an extra null byte ends the 
  376. array. 
  377.  
  378. For example, assume that you have a module with 2 extra controllers which you 
  379. wish to name "Filt Cutoff" and "Filt Res".  You want these assigned to MIDI 
  380. controller numbers 105 and 106 respectively.  You would make an array as so: 
  381.  
  382. UCHAR my_array[] = { 12,105,'F','i','l','t',' ','C','u','t','o','f','f',0, 
  383. 9,106,'F','i','l','t',' ','R','e','s',0,  0 }; 
  384.  
  385. Now you can pass this to MidiGetCtlNum2(), which will search this array first 
  386. when matching any passed string.  For example, the following call returns a 
  387. controller number of 105. 
  388.  
  389. note_number = MidiGetDrumNum(&my_array[0], "Cutoff"); 
  390.  
  391. Note that substring matching and case-insensitivity applies to matching the 
  392. contents of your array.  Furthermore, substring matching is not limited to the 
  393. head of the Controller name (for your array names only). 
  394.  
  395. Because the contents of the array are searched before the defined Controller 
  396. names, you can even replace any of the defined names.  For example, controller 
  397. number 16 is "Genr 1", a general purpose slider.  Perhaps you have a module 
  398. that allows that to control LFO Rate.  Therefore, you can replace just the Genr 
  399. 1 name by passing an array that sets controller number 16 to "LFO Rate", as so: 
  400.  
  401. UCHAR my_array[] = { 9,16,'L','F','O',' ','R','a','t','e',0,  0 }; 
  402. ctl_number = MidiGetCtlNum2(&my_array[0], "LFO");  /* returns controller number 
  403. 16 */ 
  404.  
  405. If you have no extensions or replacements to the defined Controllers, then 
  406. simply pass a 0 instead of a pointer to an array. 
  407.  
  408.  
  409. ΓòÉΓòÉΓòÉ 6.4. MidiGetCtlStr2() ΓòÉΓòÉΓòÉ
  410.  
  411. Template 
  412.  
  413. UCHAR * MidiGetCtlStr2(UCHAR * CtlArray, UCHAR CtlNumber); 
  414.  
  415. Description 
  416.  
  417. MidiGetCtlStr2() allows a second parameter to be passed to it, pointing to an 
  418. array that defines the names of any extra controllers, plus their controller 
  419. numbers.  See the discussion in MidiGetCtlNum2() for the purpose and setup of 
  420. the array. 
  421.  
  422.  
  423. ΓòÉΓòÉΓòÉ 7. Functions for MIDI Note names ΓòÉΓòÉΓòÉ
  424.  
  425. There are two functions dealing with MIDI note names and numbers. 
  426. MidiGetNoteStr() returns a note name based upon a MIDI note number passed to 
  427. it.  MidiGetNoteNum() returns a MIDI note number for a given note name. 
  428.  
  429.  
  430. ΓòÉΓòÉΓòÉ 7.1. MidiGetNoteStr() ΓòÉΓòÉΓòÉ
  431.  
  432. Template 
  433.  
  434. ULONG MidiGetNoteStr(UCHAR * Buffer, UCHAR NoteNumber, CHAR Key); 
  435.  
  436. Description 
  437.  
  438. This is passed a MIDI note number (ie, 0 to 127 inclusive), as well as a 
  439. pointer to a buffer into which MidiGetNoteStr() places a null-terminated string 
  440. representing the respective note name.  For example, a note number of 60 
  441. returns "C 3" (meaning the C in the third octave of a piano).  The buffer 
  442. should be at least 5 characters long to hold the largest possible returned 
  443. string.  MidiGetNoteStr() returns the length the note name (not counting the 
  444. null byte). 
  445.  
  446. The Key arg is a negative number if flats are desired, or a positive number if 
  447. sharps are desired, whenever an accidental is used. 
  448.  
  449. A program should display MIDI notes with their respective note names (rather 
  450. than numbers), as this is how a musician names notes. 
  451.  
  452. Example 
  453.  
  454. ULONG Len; 
  455. UCHAR Buffer[5]; 
  456.  
  457. Len = MidiGetNoteStr(&Buffer[0], 60, 0); 
  458.  
  459. The example NOTENAME.C demonstrates using MidiGetNoteStr(). 
  460.  
  461.  
  462. ΓòÉΓòÉΓòÉ 7.2. MidiGetNoteNum() ΓòÉΓòÉΓòÉ
  463.  
  464. Template 
  465.  
  466. UCHAR MidiGetNoteNum(UCHAR * NoteName, UCHAR * DefaultOct, UCHAR ** EndPtr); 
  467.  
  468. Description 
  469.  
  470. This is passed a string (does not have to be null-terminated, but there should 
  471. definitely be a non-numeric character after the note name, whether it be a 
  472. space, null, or some other non-numeric value) containing a note name, for 
  473. example "C 3".  It returns the respective MIDI note number (ie, 0 to 127).  If 
  474. the passed note name is an illegal one (ie, H4), then the value 0xFE is 
  475. returned.  If the note name is out of range (ie, the lowest note is C-2 and the 
  476. highest note is G8, so "C9" would be out of range), then the value 0xFF is 
  477. returned. 
  478.  
  479. If the passed handle EndPtr is not null, then MidiGetNoteNum() returns a 
  480. pointer to where the note name ends in the buffer.  This is handy if you have 
  481. one long string containing numerous note names, and you wish to repeatedly call 
  482. MidiGetNoteNum() to extract each respective note number from that string.  You 
  483. can use the updated handle to pass back to MidiGetNoteNum(), to extract the 
  484. next note name in the string.  When there are no more note names, 
  485. MidiGetNoteNum() will end up returning 0xFE. 
  486.  
  487. MidiGetNoteNum() requires a pointer to a UCHAR containing the default octave to 
  488. be used if the note name omits the octave.  For example, the user can simply 
  489. specify "E".  If the default octave is 60 (ie, middle C octave), then the note 
  490. number returned will be for the E above middle C (ie, 64).  MidiGetNoteNum() 
  491. updates the passed default octave whenever the octave is specified upon the 
  492. passed note name. 
  493.  
  494. Example 
  495.  
  496. Here we pull the four note names out of MyNames[] and stuff the 4 respective 
  497. MIDI note numbers in MyNumbers[].  (Note that # is used to denote "sharp" and 
  498. b, a small B, is used to denote flat.  Double sharps or flats are also 
  499. supported.  Also, any amount of blank space may be used in between each note 
  500. name.  Lower or upper case letters may be used.  Spaces may appear inbetween 
  501. the note letter, any sharp or flat, and the octave.  Octaves can be omitted, in 
  502. which case the default octave is used). 
  503.  
  504. UCHAR  MyNames[] = "G#2  A -1 d5  E b"; 
  505. UCHAR  MyNumbers[5]; 
  506. UCHAR  Cnt; 
  507. UCHAR  DefOct; 
  508. UCHAR * EndPtr; 
  509.  
  510. Cnt = DefOct = 0; 
  511. EndPtr = &MyNames[0]; 
  512. while ( ( MyNumbers[Cnt] = MidiGetNoteNum(EndPtr, &DefOct, &EndPtr) ) < 128 ) 
  513. Cnt++; 
  514.  
  515. The example NOTENAME.C demonstrates using MidiGetNoteNum().