home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Audio Version 4.94
/
audioversion4.94knowledgemediaresourcelibraryoctober1994.iso
/
msdos
/
midi
/
k1patche
/
k1patche.sha
/
pe.c
< prev
Wrap
C/C++ Source or Header
|
1994-03-16
|
44KB
|
1,760 lines
#include <stdio.h>
char *st_copyright[] = {
" *********************************************************************",
" * Copyright 1989 by H. Edward Hall *",
" * *",
" * Permission is hereby granted to copy and to give away this *",
" * software as long as this notice is preserved in its entirety. *",
" * You may modify the software or use it for any purpose just as *",
" * long as you preserve this notice and do not sell the software. *",
" * No warranty of any kind is made for this software. The holder *",
" * of this copyright reserves the right to enhance and/or sell *",
" * this software with no obligation to provide updates or further *",
" * free copies; if this should happen you may still use this version *",
" * of the software under the terms you received it with. *",
" *********************************************************************",
NULL};
/*
* [That said, I expect subsequent versions to remain freeware
* unless starvation sets it.]
*/
/*
* Kawai K-1 Patch Editor V0.1
*
* This editor is a first (and only slightly successful) attempt
* to make a hardware-independent patch editor. I expect a great
* deal more evolution will take place as I adapt it for the
* Yamaha DX-7II (almost finished!) and other synths.
*
* The features are currently rather sparse, but certainly an order
* of magnitude better than using Kawai's user interface.
*/
/*
* Patch parameter descriptor structure
*/
struct param
{
unsigned char p_flags; /* special attributes of this field */
unsigned char p_type; /* data conversion for this field */
unsigned char p_byte; /* byte within patch */
unsigned char p_bit; /* starting bit within byte */
unsigned char p_nbits; /* number of bits in field */
unsigned char p_secbyte; /* secondary byte within patch */
unsigned char p_secbit; /* starting bit within byte */
unsigned char p_secnbits; /* number of bits in field */
unsigned char p_row; /* row on display screen */
unsigned char p_col; /* column on display screen */
int p_bias; /* minimum value */
int p_limit; /* maximum value */
char **p_names; /* strings for ENUM type */
};
/*
* Enumeration strings for SINGLE display
*/
char *st_src[] = {"2", "4"};
char *st_poly[] = {"Poly-1", "Poly-2", "Solo "};
char *st_am12[] = {"off", "1>2", "2>1"};
char *st_am34[] = {"off", "3>4", "4>3"};
char *st_vshp[] = {"TRI", "SAW", "SQR", "RND"};
char *st_vwhl[] = {"DEP", "SPD"};
char *st_mute[] = {" ", "*"};
char *st_trkg[] = {"No ", "Yes"};
char *st_onof[] = {"off", "On "};
char *st_wave[] =
{" 1 Sin 1st ", " 2 Sin 2nd ", " 3 Sin 3rd ", " 4 Sin 4th ",
" 5 Sin 5th ", " 6 Sin 6th ", " 7 Sin 7th ", " 8 Sin 8th ",
" 9 Sin 9th ", " 10 Sin 10th ", " 11 Sin 11th ", " 12 Sin 12th ",
" 13 Sin 16th ", " 14 Saw 1 ", " 15 Saw 2 ", " 16 Saw 3 ",
" 17 Saw 4 ", " 18 Saw 5 ", " 19 Saw 6 ", " 20 Saw 7 ",
" 21 Saw 8 ", " 22 Saw 9 ", " 23 Saw 10 ", " 24 Saw 11 ",
" 25 Saw 12 ", " 26 Saw 13 ", " 27 Saw 14 ", " 28 Saw 15 ",
" 29 Saw 16 ", " 30 Saw 17 ", " 31 Saw 18 ", " 32 Saw 19 ",
" 33 Square 1 ", " 34 Square 2 ", " 35 Square 3 ", " 36 Square 4 ",
" 37 Square 5 ", " 38 Invrse Saw", " 39 Triangle ", " 40 Random ",
" 41 Frnch Horn", " 42 String 1 ", " 43 String 2 ", " 44 String Pad",
" 45 Piano 1 ", " 46 El. Grand ", " 47 E. Piano 1", " 48 E. Piano 2",
" 49 E. Piano 3", " 50 Clavi ", " 51 Vibe ", " 52 A. Guitar ",
" 53 F. Guitar ", " 54 F. Guitar ", " 55 A. Bass ", " 56 A. Bass ",
" 57 Dig Bass 1", " 58 Pick Bass ", " 59 Dig Bass 2", " 60 Round Bass",
" 61 Fretless 1", " 62 Fretless 2", " 63 Flute ", " 64 Pan Flute ",
" 65 Harmonica ", " 66 Glocken ", " 67 Tine ", " 68 Harp ",
" 69 Marimba ", " 70 E. Tom ", " 71 Log Drum ", " 72 Jazz Org 1",
" 73 Mello Pad ", " 74 Synth Solo", " 75 Synth 2 ", " 76 Frnch Horn",
" 77 Frnch Horn", " 78 Brass ", " 79 Brass ", " 80 Brass ",
" 81 Brass ", " 82 Trumpet ", " 83 Trumpet ", " 84 Violin ",
" 85 String ", " 86 Piano 1 ", " 87 Piano 2 ", " 88 Piano 3 ",
" 89 Piano 2 ", " 90 Piano 3 ", " 91 Piano 4 ", " 92 Piano 4 ",
" 93 El. Grand ", " 94 E. Piano 1", " 95 E. Piano 2", " 96 E. Piano 2",
" 97 Clavi ", " 98 Harpschord", " 99 Vibe ", "100 A. Guitar ",
"101 F. Guitar ", "102 Strat ", "103 Strat ", "104 A. Bass ",
"105 Pull Bass ", "106 Pull Bass ", "107 Round Bass", "108 Slap Bass ",
"109 Slap Bass ", "110 Slap Bass ", "111 Fretless ", "112 Fretless ",
"113 Synth Bass", "114 Synth Bass", "115 Harmonica ", "116 Clarinet ",
"117 Clarinet ", "118 Oboe ", "119 Oboe ", "120 Shakuhachi",
"121 Orient Bel", "122 Orient Bel", "123 Bell ", "124 Koto ",
"125 Sitar ", "126 E. Tom ", "127 Log Drum ", "128 Log Drum ",
"129 Steel Drum", "130 Steel Drum", "131 Voice 1 ", "132 Voice 2 ",
"133 Accordion ", "134 Accordion ", "135 Jazz Org 2", "136 Rock Org 1",
"137 Draw Bar 1", "138 Draw Bar 2", "139 Pipe Org 1", "140 Pipe Org 2",
"141 Rock Org 2", "142 Synth Solo", "143 Synth Solo", "144 Synth 2 ",
"145 Synth 2 ", "146 Synth 3 ", "147 Brass ", "148 Brass ",
"149 Orchestra ", "150 Piano 1 ", "151 Piano 4 ", "152 E. Piano 1",
"153 E. Piano 1", "154 E. Piano 2", "155 E. Piano 3", "156 Clavi ",
"157 Harpschord", "158 Harpschord", "159 Vibe ", "160 Dig Bass 1",
"161 Dig Bass 2", "162 Dig Bass 2", "163 Pick bass ", "164 Glocken ",
"165 Glocken ", "166 Tine ", "167 Tine ", "168 Tine ",
"169 Tube Bell ", "170 Tube Bell ", "171 Tube Bell ", "172 Xylophone ",
"173 Xylophone ", "174 Harp ", "175 Koto ", "176 Sitar ",
"177 Sitar ", "178 Kalimbra ", "179 Kalimbra ", "180 Kalimbra ",
"181 Log Drum ", "182 Steel Drum", "183 Pipe Org 3", "184 Pipe Org 3",
"185 Synth 1 ", "186 Synth 2 ", "187 Synth 3 ", "188 Synth 3 ",
"189 Synth 4 ", "190 Synth 4 ", "191 Clavi ", "192 Dig Bass 1",
"193 Dig Bass 1", "194 Pick Bass ", "195 Pick Bass ", "196 Round Bass",
"197 Round Bass", "198 Harmonica ", "199 Harmonica ", "200 Harp ",
"201 Koto ", "202 Sitar ", "203 Marimba ", "204 Synth 1 ",
"205 Bass Drum ", "206 A. Snare ", "207 Tite Snare", "208 E. Snare ",
"209 Rim ", "210 A. Tom ", "211 High Hat ", "212 Crash ",
"213 Ride ", "214 Strat Guit", "215 Fuzz Mute ", "216 A. Guitar ",
"217 F. Guitar ", "218 Guit Harmo", "219 Pull Bass ", "220 Bass Harmo",
"221 Bowd Strng", "222 Strng Attk", "223 String Sus", "224 Pizzicato ",
"225 Piano ", "226 El. Grand ", "227 Piano Nois", "228 Trumpet ",
"229 Shak Attck", "230 Shak Sustn", "231 PanFl Attk", "232 PanFl Sust",
"233 Voice ", "234 White Nois", "235 Strng Loop", "236 Shak Loop ",
"237 PanFl Loop", "238 Voice Loop", "239 WhtNois Lp", "240 Snare Loop",
"241 F. Guit Lp", "242 PulBass Lp", "243 OmniLoop 1", "244 OmniLoop 2",
"245 OmniLoop 3", "246 OmniLoop 4", "247 OmniLoop 5", "248 OmniLoop 6",
"249 OmniLoop 7", "250 OmniLoop 8", "251 Snare Rev ", "252 Tom Rev ",
"253 F. Guit Rv", "254 Hi Hat Alt", "255 Crash Alt ", "256 PnoNois Al"};
char *st_note[] =
{"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"};
/*
* data types
*/
#define LSTR 1 /* literal string */
#define ENUM 2 /* enumeration */
#define SNUM 3 /* signed number */
#define UNUM 4 /* unsigned number */
#define SPL1 5 /* coarse frequency display */
#define SPL2 6 /* SINGLE name */
#define SPL3 7 /* MIDI note name */
#define PEND 15 /* end-of-parameters sentinel */
#define FNRM 0x00 /* normal flag */
#define FSC4 0x10 /* display only if SRC == 4 */
#define FSGL 0x20 /* SINGLE component of a MULTIPLE */
#define G(x) (FSGL|x) /* a specific SINGLE component */
#define FRDW 0x40 /* redraw if value changed */
/*
* SINGLE parameter list
*/
struct param params[] =
{ {FNRM, LSTR, 0, 0, 8, 0, 0, 0, 1, 21, 0, 10, NULL},
{FRDW, ENUM, 11, 2, 1, 0, 0, 0, 1, 39, 0, 1, st_src},
{FNRM, UNUM, 10, 0, 8, 0, 0, 0, 1, 47, 0, 100, NULL},
{FNRM, ENUM, 11, 0, 2, 0, 0, 0, 1, 53, 0, 2, st_poly},
{FNRM, ENUM, 11, 3, 2, 0, 0, 0, 1, 65, 0, 2, st_am12},
{FNRM, ENUM, 11, 5, 2, 0, 0, 0, 1, 74, 0, 2, st_am34},
{FNRM, SNUM, 13, 0, 8, 0, 0, 0, 2, 23, -50, 50, NULL},
{FNRM, UNUM, 16, 0, 8, 0, 0, 0, 2, 35, 0, 100, NULL},
{FNRM, ENUM, 17, 0, 2, 0, 0, 0, 2, 50, 0, 3, st_vshp},
{FNRM, SNUM, 14, 0, 8, 0, 0, 0, 2, 63, -50, 50, NULL},
{FNRM, ENUM, 17, 5, 2, 0, 0, 0, 2, 75, 0, 1, st_vwhl},
{FNRM, UNUM, 17, 2, 3, 0, 0, 0, 3, 7, 1, 5, NULL},
{FNRM, SNUM, 18, 0, 8, 0, 0, 0, 3, 23, -50, 50, NULL},
{FNRM, UNUM, 19, 0, 8, 0, 0, 0, 3, 34, 0, 100, NULL},
{FNRM, SNUM, 20, 0, 8, 0, 0, 0, 3, 45, -50, 50, NULL},
{FNRM, SNUM, 21, 0, 8, 0, 0, 0, 3, 54, -50, 50, NULL},
{FNRM, SNUM, 12, 0, 8, 0, 0, 0, 3, 63, -50, 50, NULL},
{FNRM, UNUM, 15, 0, 4, 0, 0, 0, 3, 75, 0, 12, NULL},
/*S1*/ {FNRM, ENUM, 22, 0, 1, 0, 0, 0, 5, 3, 0, 1, st_mute},
{FNRM, ENUM, 31, 0, 7, 35, 0, 1, 5, 9, 0, 255, st_wave},
{FNRM, ENUM, 35, 1, 1, 0, 0, 0, 5, 25, 0, 1, st_trkg},
{FNRM, SPL1, 27, 0, 8, 0, 0, 0, 5, 33, 0, 127, NULL},
{FNRM, SNUM, 23, 0, 8, 0, 0, 0, 5, 39, -50, 50, NULL},
{FNRM, SNUM, 83, 0, 8, 0, 0, 0, 5, 44, -50, 50, NULL},
{FNRM, ENUM, 35, 2, 1, 0, 0, 0, 5, 49, 0, 1, st_onof},
{FNRM, ENUM, 35, 3, 1, 0, 0, 0, 5, 54, 0, 1, st_onof},
/*S2*/ {FNRM, ENUM, 22, 1, 1, 0, 0, 0, 6, 3, 0, 1, st_mute},
{FNRM, ENUM, 32, 0, 7, 36, 0, 1, 6, 9, 0, 255, st_wave},
{FNRM, ENUM, 36, 1, 1, 0, 0, 0, 6, 25, 0, 1, st_trkg},
{FNRM, SPL1, 28, 0, 8, 0, 0, 0, 6, 33, 0, 127, NULL},
{FNRM, SNUM, 24, 0, 8, 0, 0, 0, 6, 39, -50, 50, NULL},
{FNRM, SNUM, 84, 0, 8, 0, 0, 0, 6, 44, -50, 50, NULL},
{FNRM, ENUM, 36, 2, 1, 0, 0, 0, 6, 49, 0, 1, st_onof},
{FNRM, ENUM, 36, 3, 1, 0, 0, 0, 6, 54, 0, 1, st_onof},
/*S3*/ {FSC4, ENUM, 22, 2, 1, 0, 0, 0, 7, 3, 0, 1, st_mute},
{FSC4, ENUM, 33, 0, 7, 37, 0, 1, 7, 9, 0, 255, st_wave},
{FSC4, ENUM, 37, 1, 1, 0, 0, 0, 7, 25, 0, 1, st_trkg},
{FSC4, SPL1, 29, 0, 8, 0, 0, 0, 7, 33, 0, 127, NULL},
{FSC4, SNUM, 25, 0, 8, 0, 0, 0, 7, 39, -50, 50, NULL},
{FSC4, SNUM, 85, 0, 8, 0, 0, 0, 7, 44, -50, 50, NULL},
{FSC4, ENUM, 37, 2, 1, 0, 0, 0, 7, 49, 0, 1, st_onof},
{FSC4, ENUM, 37, 3, 1, 0, 0, 0, 7, 54, 0, 1, st_onof},
/*S4*/ {FSC4, ENUM, 22, 3, 1, 0, 0, 0, 8, 3, 0, 1, st_mute},
{FSC4, ENUM, 34, 0, 7, 38, 0, 1, 8, 9, 0, 255, st_wave},
{FSC4, ENUM, 38, 1, 1, 0, 0, 0, 8, 25, 0, 1, st_trkg},
{FSC4, SPL1, 30, 0, 8, 0, 0, 0, 8, 33, 0, 127, NULL},
{FSC4, SNUM, 26, 0, 8, 0, 0, 0, 8, 39, -50, 50, NULL},
{FSC4, SNUM, 86, 0, 8, 0, 0, 0, 8, 44, -50, 50, NULL},
{FSC4, ENUM, 38, 2, 1, 0, 0, 0, 8, 49, 0, 1, st_onof},
{FSC4, ENUM, 38, 3, 1, 0, 0, 0, 8, 54, 0, 1, st_onof},
/*S1*/ {FNRM, UNUM, 39, 0, 8, 0, 0, 0, 10, 11, 0, 100, NULL},
{FNRM, UNUM, 43, 0, 8, 0, 0, 0, 10, 15, 0, 100, NULL},
{FNRM, UNUM, 47, 0, 8, 0, 0, 0, 10, 19, 0, 100, NULL},
{FNRM, UNUM, 51, 0, 8, 0, 0, 0, 10, 23, 0, 100, NULL},
{FNRM, UNUM, 55, 0, 8, 0, 0, 0, 10, 27, 0, 100, NULL},
{FNRM, UNUM, 59, 0, 8, 0, 0, 0, 10, 31, 0, 100, NULL},
{FNRM, SNUM, 63, 0, 8, 0, 0, 0, 10, 36, -50, 50, NULL},
{FNRM, UNUM, 35, 4, 3, 0, 0, 0, 10, 43, 1, 8, NULL},
{FNRM, SNUM, 67, 0, 8, 0, 0, 0, 10, 48, -50, 50, NULL},
{FNRM, SNUM, 71, 0, 8, 0, 0, 0, 10, 55, -50, 50, NULL},
{FNRM, SNUM, 75, 0, 8, 0, 0, 0, 10, 62, -50, 50, NULL},
{FNRM, SNUM, 79, 0, 8, 0, 0, 0, 10, 68, -50, 50, NULL},
/*S2*/ {FNRM, UNUM, 40, 0, 8, 0, 0, 0, 11, 11, 0, 100, NULL},
{FNRM, UNUM, 44, 0, 8, 0, 0, 0, 11, 15, 0, 100, NULL},
{FNRM, UNUM, 48, 0, 8, 0, 0, 0, 11, 19, 0, 100, NULL},
{FNRM, UNUM, 52, 0, 8, 0, 0, 0, 11, 23, 0, 100, NULL},
{FNRM, UNUM, 56, 0, 8, 0, 0, 0, 11, 27, 0, 100, NULL},
{FNRM, UNUM, 60, 0, 8, 0, 0, 0, 11, 31, 0, 100, NULL},
{FNRM, SNUM, 64, 0, 8, 0, 0, 0, 11, 36, -50, 50, NULL},
{FNRM, UNUM, 36, 4, 3, 0, 0, 0, 11, 43, 1, 8, NULL},
{FNRM, SNUM, 68, 0, 8, 0, 0, 0, 11, 48, -50, 50, NULL},
{FNRM, SNUM, 72, 0, 8, 0, 0, 0, 11, 55, -50, 50, NULL},
{FNRM, SNUM, 76, 0, 8, 0, 0, 0, 11, 62, -50, 50, NULL},
{FNRM, SNUM, 80, 0, 8, 0, 0, 0, 11, 68, -50, 50, NULL},
/*S3*/ {FSC4, UNUM, 41, 0, 8, 0, 0, 0, 12, 11, 0, 100, NULL},
{FSC4, UNUM, 45, 0, 8, 0, 0, 0, 12, 15, 0, 100, NULL},
{FSC4, UNUM, 49, 0, 8, 0, 0, 0, 12, 19, 0, 100, NULL},
{FSC4, UNUM, 53, 0, 8, 0, 0, 0, 12, 23, 0, 100, NULL},
{FSC4, UNUM, 57, 0, 8, 0, 0, 0, 12, 27, 0, 100, NULL},
{FSC4, UNUM, 61, 0, 8, 0, 0, 0, 12, 31, 0, 100, NULL},
{FSC4, SNUM, 65, 0, 8, 0, 0, 0, 12, 36, -50, 50, NULL},
{FSC4, UNUM, 37, 4, 3, 0, 0, 0, 12, 43, 1, 8, NULL},
{FSC4, SNUM, 69, 0, 8, 0, 0, 0, 12, 48, -50, 50, NULL},
{FSC4, SNUM, 73, 0, 8, 0, 0, 0, 12, 55, -50, 50, NULL},
{FSC4, SNUM, 77, 0, 8, 0, 0, 0, 12, 62, -50, 50, NULL},
{FSC4, SNUM, 81, 0, 8, 0, 0, 0, 12, 68, -50, 50, NULL},
/*S4*/ {FSC4, UNUM, 42, 0, 8, 0, 0, 0, 13, 11, 0, 100, NULL},
{FSC4, UNUM, 46, 0, 8, 0, 0, 0, 13, 15, 0, 100, NULL},
{FSC4, UNUM, 50, 0, 8, 0, 0, 0, 13, 19, 0, 100, NULL},
{FSC4, UNUM, 54, 0, 8, 0, 0, 0, 13, 23, 0, 100, NULL},
{FSC4, UNUM, 58, 0, 8, 0, 0, 0, 13, 27, 0, 100, NULL},
{FSC4, UNUM, 62, 0, 8, 0, 0, 0, 13, 31, 0, 100, NULL},
{FSC4, SNUM, 66, 0, 8, 0, 0, 0, 13, 36, -50, 50, NULL},
{FSC4, UNUM, 38, 4, 3, 0, 0, 0, 13, 43, 1, 8, NULL},
{FSC4, SNUM, 70, 0, 8, 0, 0, 0, 13, 48, -50, 50, NULL},
{FSC4, SNUM, 74, 0, 8, 0, 0, 0, 13, 55, -50, 50, NULL},
{FSC4, SNUM, 78, 0, 8, 0, 0, 0, 13, 62, -50, 50, NULL},
{FSC4, SNUM, 82, 0, 8, 0, 0, 0, 13, 68, -50, 50, NULL},
{FNRM, PEND, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL}};
/*
* MULTIPLE enumeration strings
*/
char *st_vlsw[] = {"All ", "Soft", "Loud"};
char *st_mmod[] = {"Kybd", "Midi", "Mix "};
char *st_chan[] = {"R ", "L+R", "L "};
char *st_mply[] = {"VR", "0 ", "1 ", "2 ", "3 ", "4 ", "5 ", "6 ", "7 ", "8 "};
/*
000000000111111111122222222223333333333444444444455555555556666666666777777
123456789012345678901234567890123456789012345678901234567890123456789012345
Source Levl Tran Tune Out Poly Chan ZnLo ZnHi VSwch Mode
S1 IA-1 xxxxxxxxxx 100 -24 -50 L+R VR 1 127 127 Loud MIDI
*/
/*
* MULTIPLE parameter list
*/
struct param mparams[] = {
{FNRM, LSTR, 0, 0, 8, 0, 0, 0, 15, 23, 0, 10, NULL},
{FNRM, UNUM, 10, 0, 8, 0, 0, 0, 15, 43, 1, 100, NULL},
/*S1*/ {G(1), SPL2, 11, 0, 6, 0, 0, 0, 17, 4, 0, 63, NULL},
{G(1), UNUM, 67, 0, 8, 0, 0, 0, 17, 20, 0, 100, NULL},
{G(1), SNUM, 51, 0, 6, 0, 0, 0, 17, 25, -24, 24, NULL},
{G(1), SNUM, 59, 0, 8, 0, 0, 0, 17, 30, -50, 50, NULL},
{G(1), ENUM, 35, 4, 2, 0, 0, 0, 17, 35, 0, 2, st_chan},
{FRDW, ENUM, 35, 0, 4, 0, 0, 0, 17, 40, 0, 9, st_mply},
{G(1), UNUM, 43, 0, 4, 0, 0, 0, 17, 45, 1, 16, NULL},
{G(1), SPL3, 19, 0, 8, 0, 0, 0, 17, 49, 0, 127, NULL},
{G(1), SPL3, 27, 0, 8, 0, 0, 0, 17, 54, 0, 127, NULL},
{G(1), ENUM, 43, 4, 2, 0, 0, 0, 17, 59, 0, 2, st_vlsw},
{G(1), ENUM, 35, 6, 1, 43, 6, 1, 17, 65, 0, 2, st_mmod},
/*S2*/ {G(2), SPL2, 12, 0, 6, 0, 0, 0, 18, 4, 0, 63, NULL},
{G(2), UNUM, 68, 0, 8, 0, 0, 0, 18, 20, 0, 100, NULL},
{G(2), SNUM, 52, 0, 6, 0, 0, 0, 18, 25, -24, 24, NULL},
{G(2), SNUM, 60, 0, 8, 0, 0, 0, 18, 30, -50, 50, NULL},
{G(2), ENUM, 36, 4, 2, 0, 0, 0, 18, 35, 0, 2, st_chan},
{FRDW, ENUM, 36, 0, 4, 0, 0, 0, 18, 40, 0, 9, st_mply},
{G(2), UNUM, 44, 0, 4, 0, 0, 0, 18, 45, 1, 16, NULL},
{G(2), SPL3, 20, 0, 8, 0, 0, 0, 18, 49, 0, 127, NULL},
{G(2), SPL3, 28, 0, 8, 0, 0, 0, 18, 54, 0, 127, NULL},
{G(2), ENUM, 44, 4, 2, 0, 0, 0, 18, 59, 0, 2, st_vlsw},
{G(2), ENUM, 36, 6, 1, 44, 6, 1, 18, 65, 0, 2, st_mmod},
/*S3*/ {G(3), SPL2, 13, 0, 6, 0, 0, 0, 19, 4, 0, 63, NULL},
{G(3), UNUM, 69, 0, 8, 0, 0, 0, 19, 20, 0, 100, NULL},
{G(3), SNUM, 53, 0, 6, 0, 0, 0, 19, 25, -24, 24, NULL},
{G(3), SNUM, 61, 0, 8, 0, 0, 0, 19, 30, -50, 50, NULL},
{G(3), ENUM, 37, 4, 2, 0, 0, 0, 19, 35, 0, 2, st_chan},
{FRDW, ENUM, 37, 0, 4, 0, 0, 0, 19, 40, 0, 9, st_mply},
{G(3), UNUM, 45, 0, 4, 0, 0, 0, 19, 45, 1, 16, NULL},
{G(3), SPL3, 21, 0, 8, 0, 0, 0, 19, 49, 0, 127, NULL},
{G(3), SPL3, 29, 0, 8, 0, 0, 0, 19, 54, 0, 127, NULL},
{G(3), ENUM, 45, 4, 2, 0, 0, 0, 19, 59, 0, 2, st_vlsw},
{G(3), ENUM, 37, 6, 1, 45, 6, 1, 19, 65, 0, 2, st_mmod},
/*S4*/ {G(4), SPL2, 14, 0, 6, 0, 0, 0, 20, 4, 0, 63, NULL},
{G(4), UNUM, 70, 0, 8, 0, 0, 0, 20, 20, 0, 100, NULL},
{G(4), SNUM, 54, 0, 6, 0, 0, 0, 20, 25, -24, 24, NULL},
{G(4), SNUM, 62, 0, 8, 0, 0, 0, 20, 30, -50, 50, NULL},
{G(4), ENUM, 38, 4, 2, 0, 0, 0, 20, 35, 0, 2, st_chan},
{FRDW, ENUM, 38, 0, 4, 0, 0, 0, 20, 40, 0, 9, st_mply},
{G(4), UNUM, 46, 0, 4, 0, 0, 0, 20, 45, 1, 16, NULL},
{G(4), SPL3, 22, 0, 8, 0, 0, 0, 20, 49, 0, 127, NULL},
{G(4), SPL3, 30, 0, 8, 0, 0, 0, 20, 54, 0, 127, NULL},
{G(4), ENUM, 46, 4, 2, 0, 0, 0, 20, 59, 0, 2, st_vlsw},
{G(4), ENUM, 38, 6, 1, 46, 6, 1, 20, 65, 0, 2, st_mmod},
/*S5*/ {G(5), SPL2, 15, 0, 6, 0, 0, 0, 21, 4, 0, 63, NULL},
{G(5), UNUM, 71, 0, 8, 0, 0, 0, 21, 20, 0, 100, NULL},
{G(5), SNUM, 55, 0, 6, 0, 0, 0, 21, 25, -24, 24, NULL},
{G(5), SNUM, 63, 0, 8, 0, 0, 0, 21, 30, -50, 50, NULL},
{G(5), ENUM, 39, 4, 2, 0, 0, 0, 21, 35, 0, 2, st_chan},
{FRDW, ENUM, 39, 0, 4, 0, 0, 0, 21, 40, 0, 9, st_mply},
{G(5), UNUM, 47, 0, 4, 0, 0, 0, 21, 45, 1, 16, NULL},
{G(5), SPL3, 23, 0, 8, 0, 0, 0, 21, 49, 0, 127, NULL},
{G(5), SPL3, 31, 0, 8, 0, 0, 0, 21, 54, 0, 127, NULL},
{G(5), ENUM, 47, 4, 2, 0, 0, 0, 21, 59, 0, 2, st_vlsw},
{G(5), ENUM, 39, 6, 1, 47, 6, 1, 21, 65, 0, 2, st_mmod},
/*S6*/ {G(6), SPL2, 16, 0, 6, 0, 0, 0, 22, 4, 0, 63, NULL},
{G(6), UNUM, 72, 0, 8, 0, 0, 0, 22, 20, 0, 100, NULL},
{G(6), SNUM, 56, 0, 6, 0, 0, 0, 22, 25, -24, 24, NULL},
{G(6), SNUM, 64, 0, 8, 0, 0, 0, 22, 30, -50, 50, NULL},
{G(6), ENUM, 40, 4, 2, 0, 0, 0, 22, 35, 0, 2, st_chan},
{FRDW, ENUM, 40, 0, 4, 0, 0, 0, 22, 40, 0, 9, st_mply},
{G(6), UNUM, 48, 0, 4, 0, 0, 0, 22, 45, 1, 16, NULL},
{G(6), SPL3, 24, 0, 8, 0, 0, 0, 22, 49, 0, 127, NULL},
{G(6), SPL3, 32, 0, 8, 0, 0, 0, 22, 54, 0, 127, NULL},
{G(6), ENUM, 48, 4, 2, 0, 0, 0, 22, 59, 0, 2, st_vlsw},
{G(6), ENUM, 40, 6, 1, 48, 6, 1, 22, 65, 0, 2, st_mmod},
/*S7*/ {G(7), SPL2, 17, 0, 6, 0, 0, 0, 23, 4, 0, 63, NULL},
{G(7), UNUM, 73, 0, 8, 0, 0, 0, 23, 20, 0, 100, NULL},
{G(7), SNUM, 57, 0, 6, 0, 0, 0, 23, 25, -24, 24, NULL},
{G(7), SNUM, 65, 0, 8, 0, 0, 0, 23, 30, -50, 50, NULL},
{G(7), ENUM, 41, 4, 2, 0, 0, 0, 23, 35, 0, 2, st_chan},
{FRDW, ENUM, 41, 0, 4, 0, 0, 0, 23, 40, 0, 9, st_mply},
{G(7), UNUM, 49, 0, 4, 0, 0, 0, 23, 45, 1, 16, NULL},
{G(7), SPL3, 25, 0, 8, 0, 0, 0, 23, 49, 0, 127, NULL},
{G(7), SPL3, 33, 0, 8, 0, 0, 0, 23, 54, 0, 127, NULL},
{G(7), ENUM, 49, 4, 2, 0, 0, 0, 23, 59, 0, 2, st_vlsw},
{G(7), ENUM, 41, 6, 1, 49, 6, 1, 23, 65, 0, 2, st_mmod},
/*S8*/ {G(8), SPL2, 18, 0, 6, 0, 0, 0, 24, 4, 0, 63, NULL},
{G(8), UNUM, 74, 0, 8, 0, 0, 0, 24, 20, 0, 100, NULL},
{G(8), SNUM, 58, 0, 6, 0, 0, 0, 24, 25, -24, 24, NULL},
{G(8), SNUM, 66, 0, 8, 0, 0, 0, 24, 30, -50, 50, NULL},
{G(8), ENUM, 42, 4, 2, 0, 0, 0, 24, 35, 0, 2, st_chan},
{FRDW, ENUM, 42, 0, 4, 0, 0, 0, 24, 40, 0, 9, st_mply},
{G(8), UNUM, 50, 0, 4, 0, 0, 0, 24, 45, 1, 16, NULL},
{G(8), SPL3, 26, 0, 8, 0, 0, 0, 24, 49, 0, 127, NULL},
{G(8), SPL3, 34, 0, 8, 0, 0, 0, 24, 54, 0, 127, NULL},
{G(8), ENUM, 50, 4, 2, 0, 0, 0, 24, 59, 0, 2, st_vlsw},
{G(8), ENUM, 42, 6, 1, 50, 6, 1, 24, 65, 0, 2, st_mmod},
{FNRM, PEND, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL}
};
/*
* Fixed part of display
*/
char *st_scrn[] = {
/*
000000000111111111122222222223333333333444444444455555555556666666666777777
123456789012345678901234567890123456789012345678901234567890123456789012345
*/
"SINGLE Patch : \" \" | Src | Vol | | AM | AM",
" KS | Vibrato: Depth | Speed | Shape | AT | Wheel",
"Curve | Bend: Depth | Time | Vel | KS | AT | Range",
"SOURCES: Wave Trkng Coarse Fine f/KS Bend f/AT",
" S1",
" S2",
" S3",
" S4",
"Envelope: Lev Del Att Dec Sus Rel Lev/V V/Cur Lev/AT Lev/KS Dur/V Dur/KS",
" S1",
" S2",
" S3",
" S4",
"------------------------------------------------------------------------",
"MULTIPLE Patch : \" \" | Vol",
" Source Levl Tran Tune Out Poly Chan ZnLo ZnHi VSwch Mode",
"S1",
"S2",
"S3",
"S4",
"S5",
"S6",
"S7",
"S8",
NULL
};
/*
000000000111111111122222222223333333333444444444455555555556666666666777777
123456789012345678901234567890123456789012345678901234567890123456789012345
Source Levl Tran Tune Out Poly Chan ZnLo ZnHi VSwch Mode
S1 IA-1 xxxxxxxxxx 100 -24 -50 L+R VR 1 127 127 Loud MIDI
*/
unsigned char dump[64][88]; /* 64 SINGLE patch array */
unsigned char mdump[32][76]; /* 32 MULTIPLE patch array */
int curpatch; /* current SINGLE patch number */
int curmpatch; /* current MULTIPLE patch number */
int curparam; /* current SINGLE patch parameter */
int curmparam; /* current MULTIPLE patch parameter */
int single; /* true if SINGLE display active; false if MULTIPLE active */
int echo; /* MIDI echo if true */
/*
* Show fixed part of screen
*/
void
distemplate(screen)
char *screen[];
{
register int n, i;
char str[82];
clrscr();
for (n = 0; st_scrn[n] != NULL; n++)
{
(void)strcpy(str, screen[n]);
for (i = strlen(str); i < 79; i++)
str[i] = ' ';
str[i] = '\0';
gotoxy(1, n+1);
cprintf("%s", str);
}
}
/*
* display patch from data at ``dp''
*/
void
dispatch(dp)
unsigned char *dp;
{
register struct param *pp;
int cur;
void showparam();
void eraseparam();
void showid();
for (pp = single?params:mparams; pp->p_type != PEND; pp++)
if (visible(pp, dp))
showparam(pp, dp);
else
eraseparam(pp);
if (single)
{
gotoxy(14, 1);
cur = curpatch;
pp = ¶ms[curparam];
}
else
{
gotoxy(16, 15);
cur = curmpatch;
pp = &mparams[curmparam];
}
showid(cur);
gotoxy((int)pp->p_col, (int)pp->p_row);
}
/*
* refresh screen
*/
void
refresh()
{
int snglsv = single;
distemplate();
single = 1;
dispatch(&dump[curpatch][0]);
single = 0;
dispatch(&mdump[curmpatch][0]);
single = snglsv;
}
char *st_plet[] = {"IA", "IB", "IC", "ID", "iA", "iB", "iC", "iD"};
/*
* returns Kawai patch ID
*/
char *
idstr(n)
int n;
{
static char tstr[10];
n &= 0x3f;
(void)sprintf(tstr, "%s-%d", st_plet[n>>3], 1+(n&0x7));
return tstr;
}
/*
* displays, at current position, Kawai patch ID
*/
void
showid(n)
{
highvideo();
cprintf("%s", idstr(n));
normvideo();
}
/*
* extract the value (integer) of a given parameter, given a pointer
* of its descriptor and the patch data
*/
int bitmask[] = {0, 1, 3, 7, 15, 31, 63, 127, 255};
int
getvalue(pp, dp)
register struct param *pp;
unsigned char *dp;
{
int val;
val = (dp[pp->p_byte]>>pp->p_bit)&bitmask[pp->p_nbits];
if (pp->p_secnbits > 0)
val |= ((dp[pp->p_secbyte]>>pp->p_secbit)
&bitmask[pp->p_secnbits])<<pp->p_nbits;
val += pp->p_bias;
return val;
}
/*
* set the value (integer) of a given parameter, given a pointer
* of its descriptor, the value, and a pointer to the patch data
*/
void
setvalue(pp, val, dp)
register struct param *pp;
int val;
unsigned char *dp;
{
int oval;
if (val > pp->p_limit)
val = pp->p_limit;
val -= pp->p_bias;
if (val < 0)
val = 0;
oval = dp[pp->p_byte]&~(bitmask[pp->p_nbits]<<pp->p_bit);
dp[pp->p_byte] = oval|((val&bitmask[pp->p_nbits])<<pp->p_bit);
if (pp->p_secnbits == 0)
return;
oval = dp[pp->p_secbyte]&~(bitmask[pp->p_secnbits]<<pp->p_secbit);
dp[pp->p_secbyte] = oval|
(((val>>pp->p_nbits)&bitmask[pp->p_secnbits])<<pp->p_secbit);
return;
}
void
showparam(pp, dp)
register struct param *pp;
unsigned char *dp;
{
int val;
void showval();
void showstr();
if (pp->p_type == LSTR)
{
showval(pp, 0, dp);
return;
}
val = getvalue(pp, dp);
if (val > pp->p_limit)
showstr(pp, "#");
else
showval(pp, val, dp);
}
/*
* convert the integer value of a parameter to its display form
*/
char *
valstr(pp, val, dp)
register struct param *pp;
int val;
unsigned char *dp;
{
static char str[40];
switch (pp->p_type)
{
case LSTR:
(void)strncpy(str, (char *)&dp[pp->p_byte], pp->p_limit);
str[pp->p_limit] = '\0';
break;
case ENUM:
(void)strcpy(str, pp->p_names[val]);
break;
case UNUM:
(void)sprintf(str, "%d ", val);
if (pp->p_limit > 99)
str[3] = '\0';
else if (pp->p_limit > 9)
str[2] = '\0';
else
str[1] = '\0';
break;
case SPL1:
if ((dp[pp->p_byte+8]&02) == 0)
(void)sprintf(str, "%s%d ", st_note[val%12], val/12-4);
else
{
if (val >= 84)
(void)sprintf(str, "+%d ", val-84);
else
(void)sprintf(str, "-%d ", 84-val);
}
str[4] = '\0';
break;
case SPL2:
(void)sprintf(str, "%s ", idstr(val));
(void)strncpy(str+5, (char *)&dump[val][0], 10);
str[15] = '\0';
break;
case SPL3:
(void)sprintf(str, "%s%d ", st_note[val%12], val/12-2);
str[4] = '\0';
break;
case SNUM:
if (val < 0)
{
str[0] = '-';
val = -val;
}
else
str[0] = '+';
(void)sprintf(str+1, "%d ", val);
if (pp->p_limit > 99)
str[4] = '\0';
else if (pp->p_limit > 9)
str[3] = '\0';
else
str[2] = '\0';
break;
}
return str;
}
/*
* erase the screen area occupied by a given parameter
*/
void
eraseparam(pp)
register struct param *pp;
{
int n;
char estr[40];
switch (pp->p_type)
{
case LSTR:
n = pp->p_limit;
break;
case ENUM:
n = strlen(pp->p_names[0]);
break;
case UNUM:
if (pp->p_limit > 99)
n = 3;
else if (pp->p_limit > 9)
n = 2;
else
n = 1;
break;
case SPL1:
n = 6;
break;
case SPL2:
n = 15;
break;
case SPL3:
n = 4;
break;
case SNUM:
if (pp->p_limit > 99)
n = 4;
else if (pp->p_limit > 9)
n = 3;
else
n = 2;
break;
}
estr[n] = '\0';
while (--n >= 0)
estr[n] = ' ';
gotoxy((int)pp->p_col, (int)pp->p_row);
cprintf("%s", estr);
}
/*
* given a parameter desc., value, and patch, display at the appropriate
* screen position
*/
void
showval(pp, val, dp)
struct param *pp;
int val;
unsigned char *dp;
{
char *valstr();
void showstr();
showstr(pp, valstr(pp, val, dp));
}
/*
* given a parameter desc. and a string, display the string at the
* appropriate place on the screen
*/
void
showstr(pp, str)
register struct param *pp;
char *str;
{
gotoxy((int)pp->p_col, (int)pp->p_row);
highvideo();
cprintf("%s", str);
normvideo();
}
/*
* given a parameter desc. and patch, return true of the parameter is
* visible, and false if it is not
*/
int
visible(pp, dp)
struct param *pp;
unsigned char *dp;
{
int flags;
flags = pp->p_flags;
if (single)
{
if ((flags&FSC4) != 0 && (dp[11]&0x4) == 0)
return 0;
else
return 1;
}
else
{
if ((flags&FSGL) != 0 && (dp[34+(flags&0x0f)]&0x0f) == 1)
return 0;
else
return 1;
}
/*NOTREACHED*/
}
/*
* MIDI routines; calls the following low-level routines defined in io401.c:
*/
extern int getdata();
extern int putdata();
extern int putcmd();
#include "mpu401.h"
/*
* Many routines call tstesc() to see if an abort is requested. This is
* useful if the interface hangs, the K-1 doesn't (or can't) answer,
* and so forth.
*/
int is_midiinit = 0; /* set if MPU401 initialized */
/*
* put the MPU401 into UART mode
*/
void
rawmidi()
{
void flushmidi();
void tstesc();
if (is_midiinit)
return;
flushmidi();
while (putcmd(RESET) < 0)
tstesc();
while (putcmd(UART) < 0)
tstesc();
is_midiinit = 1;
}
/*
* echo any incoming MIDI data
*/
void
midiecho()
{
int j;
rawmidi();
while ((j = getdata()) != -1)
putdata(j);
}
/*
* eat up any incoming MIDI data; echo if that option is on
*/
void
flushmidi()
{
int j;
while ((j = getdata()) != -1)
{
if (echo)
(void) putdata(j);
tstesc();
}
}
/*
* send a MIDI byte; retries and tests for abort
*/
void
sendmidi(x)
int x;
{
void tstesc();
while (putdata(x) < 0)
tstesc();
}
/*
* wait for a particular MIDI byte
*/
waitmidi(x)
int x;
{
int j;
void tstesc();
while ((j = getdata()) != x)
{
if (echo)
sendmidi(j);
tstesc();
}
}
/*
* complains if the next MIDI byte isn't the one given.
*/
void
expectmidi(x)
int x;
{
int j;
void errpnt();
if ((j = getdata()) != x)
errpnt("Got 0x%x, expected 0x%x", j, x, 0);
}
/*
* sound a MIDI note at a given velocity. velocity 0 turns off.
*/
midinote(n, v)
int n;
int v;
{
flushmidi();
sendmidi(0x90);
sendmidi(n);
sendmidi(v);
}
/*
* do a MIDI program change to a given program (i.e. patch) number.
*/
midipgm(n)
int n;
{
flushmidi();
sendmidi(0xc0);
sendmidi(n);
}
/*
* get a positive MIDI byte; ignore all others except choke on a
* (premature) EOX.
*/
int
getposdata()
{
int j;
void errpnt();
while ((j = getdata()) > 0x7f)
if (j == 0xf7)
{
errpnt("Unexpected EOX", 0, 0, 0);
}
return j;
}
/*
* if there is a character typed at the keyboard, see if it is an ESC.
* If so, longjmp() to abort the current high-level MIDI routine.
*/
#include <setjmp.h>
jmp_buf esccontext;
void
tstesc()
{
void longjmp();
if (kbhit())
if (getch() == 033)
longjmp(esccontext, 1);
}
/*
* have K-1 dump all internal patches into our buffers
*/
void
recvdump()
{
void recvmidi();
void errpnt();
if (setjmp(esccontext))
{
errpnt("MIDI operation aborted", 0, 0, 0);
return;
}
rawmidi();
recvmidi(0x01, 0x00, 0x00, 88, 32, &dump[0][0]);
recvmidi(0x01, 0x00, 0x20, 88, 32, &dump[32][0]);
recvmidi(0x01, 0x00, 0x40, 76, 32, &mdump[0][0]);
}
/*
* dump our buffers into the K-1
*/
void
trandump()
{
void xmitmidi();
void errpnt();
if (setjmp(esccontext))
{
errpnt("MIDI operation aborted", 0, 0, 0);
return;
}
rawmidi();
xmitmidi(0x21, 0x00, 0x00, 88, 32, &dump[0][0]);
xmitmidi(0x21, 0x00, 0x20, 88, 32, &dump[32][0]);
xmitmidi(0x21, 0x00, 0x40, 76, 32, &mdump[0][0]);
}
/*
* have K-1 dump the current patch
*/
void
recvpatch()
{
if (single)
recvmidi(0x00, 0x00, curpatch, 88, 1, &dump[curpatch][0]);
else
recvmidi(0x00, 0x00, curmpatch+0x40, 76, 1, &mdump[curmpatch][0]);
}
/*
* dump the current patch into the K-1
*/
void
tranpatch()
{
if (single)
xmitmidi(0x20, 0x00, curpatch, 88, 1, &dump[curpatch][0]);
else
xmitmidi(0x20, 0x00, curmpatch+0x40, 76, 1, &mdump[curmpatch][0]);
}
/*
* generic K-1 dump receive routine
*/
void
recvmidi(func, sub1, sub2, size, howmany, data)
int func;
int sub1;
int sub2;
int size;
int howmany;
unsigned char *data;
{
int i, n, j;
int checksum;
void errpnt();
flushmidi();
sendmidi(0xf0);
sendmidi(0x40);
sendmidi(0x00);
sendmidi(func);
sendmidi(0x00);
sendmidi(0x03);
sendmidi(sub1);
sendmidi(sub2);
sendmidi(0xf7);
waitmidi(0xf0);
expectmidi(0x40);
expectmidi(0x00);
expectmidi(func|0x20);
expectmidi(0x00);
expectmidi(0x03);
expectmidi(sub1);
expectmidi(sub2);
for (n = 0; n < howmany; n++)
{
checksum = 0xa5;
for (i = 0; i < size-1; i++)
{
j = getposdata();
checksum += j;
*data++ = j;
}
j = getposdata();
*data++ = j;
if (j != (checksum&0x7f))
errpnt("Checksum(%d) %x != %x", n, checksum&0x7f, j);
}
expectmidi(0xf7);
}
/*
* generic K-1 dump transmit routine
*/
void
xmitmidi(func, sub1, sub2, size, howmany, data)
int func;
int sub1;
int sub2;
int size;
int howmany;
unsigned char *data;
{
int i, n, j;
int checksum;
void errpnt();
flushmidi();
sendmidi(0xf0);
sendmidi(0x40);
sendmidi(0x00);
sendmidi(func);
sendmidi(0x00);
sendmidi(0x03);
sendmidi(sub1);
sendmidi(sub2);
for (n = 0; n < howmany; n++)
{
checksum = 0xa5;
for (i = 0; i < size-1; i++)
{
j = *data++;
checksum += j;
sendmidi(j);
}
data++;
sendmidi(checksum&0x7f);
while (getdata() != -1)
tstesc();
}
sendmidi(0xf7);
waitmidi(0xf0);
expectmidi(0x40);
expectmidi(0x00);
j = getdata();
expectmidi(0x00);
expectmidi(0x03);
expectmidi(0xf7);
if (j != 0x40)
errpnt("Write error %d", j-0x40, 0, 0);
}
/*
* display an error message on the status line
*/
void
errpnt(str, a1, a2, a3)
char *str;
{
gotoxy(1, 25);
cprintf(str, a1, a2, a3);
sleep(2);
}
/*
* save buffers into named file
*/
void
savedump(file)
char *file;
{
FILE *fp = fopen(file, "wb");
if (fp == NULL)
errpnt("Can't create file %s", file, 0, 0);
else
{
if (fwrite((char *)&dump[0][0], 88, 64, fp) != 64)
errpnt("Trouble writing %s", file, 0, 0);
else if (fwrite((char *)&mdump[0][0], 76, 32, fp) != 32)
errpnt("Trouble writing %s", file, 0, 0);
}
}
/*
* load buffers from named file
*/
void
loaddump(file)
char *file;
{
FILE *fp = fopen(file, "rb");
if (fp == NULL)
errpnt("Can't open file %s", file, 0, 0);
else
{
if (fread((char *)&dump[0][0], 88, 64, fp) != 64)
errpnt("Trouble reading %s", file, 0, 0);
else if (fread((char *)&mdump[0][0], 76, 32, fp) != 32)
errpnt("Trouble reading %s", file, 0, 0);
}
}
/*
* If TurboC's getch() routine returns a 0 first to indicate a special
* code, we turn on bit 7 in our representation of the code.
*/
#define cHOME 0xc7 /* HOME key code */
#define cUP 0xc8 /* UP " " */
#define cPGUP 0xc9 /* PgUP " " */
#define cLEFT 0xcb /* LEFT " " */
#define cRGHT 0xcd /* RIGHT " " */
#define cEND 0xcf /* END " " */
#define cDOWN 0xd0 /* DOWN " " */
#define cPGDN 0xd1 /* PgDOWN " " */
#define cINS 0xd2 /* INSERT " " */
#define cDEL 0xd3 /* DELETE " " */
#define cF1 0xbb /* F1 " " */
#define cF8 0xc2 /* F2 " " */
#define cF10 0xc4 /* F10 " " */
#define cFORM 0x0c /* ^L " " */
#define INROW 25 /* row used for input prompt */
/*
* Display prompt string and then grab typed value into buffer.
* Buffer contents displayed, and may be edited.
*/
char *
getinput(prompt, str)
char *prompt;
char *str;
{
int cursor, stcur;
int c;
int insert;
gotoxy(1, INROW);
cprintf("%s: %s", prompt, str);
stcur = 3+strlen(prompt);
cursor = 0;
insert = 0;
gotoxy(cursor+stcur, INROW);
for (;;)
{
while (kbhit() == 0)
if (echo)
midiecho();
c = getch();
if (c == 0)
c = 0x80|getch();
switch(c)
{
case cLEFT:
if (cursor > 0)
cursor--;
break;
case '\b':
case '\177':
if (cursor > 0)
{
cursor--;
gotoxy(cursor+stcur, INROW);
cprintf("%s ", str+cursor+1);
(void)strcpy(str+cursor, str+cursor+1);
}
else
{
str[0] = '\0';
clreol();
}
break;
case cRGHT:
if (str[cursor] != '\0')
cursor++;
break;
case cDEL:
if (str[cursor] != '\0')
{
gotoxy(cursor+stcur, INROW);
cprintf("%s ", str+cursor+1);
(void)strcpy(str+cursor, str+cursor+1);
}
break;
case cINS:
insert = !insert;
break;
case '\33':
gotoxy(1, INROW);
clreol();
return NULL;
case '\n':
case '\r':
gotoxy(1, INROW);
clreol();
return str;
default:
if (c > 0x7f)
break;
if (insert)
{
char *cp, *op;
for (cp = str+cursor; *cp; cp++)
;
op = cp;
cp++;
while (op >= str+cursor)
*cp-- = *op--;
}
if (str[cursor] == '\0')
str[cursor+1] = '\0';
str[cursor] = c;
cprintf("%s ", str+cursor);
cursor++;
break;
}
gotoxy(stcur+cursor, INROW);
}
/*NOTREACHED*/
}
char noteon[8]; /* true if note is currently on */
/*
* Top-level command routine.
*/
void
docommand()
{
int c, cur, size, len, row, col, *curpch, *curprm;
char str[80];
unsigned char *dp, *altdp;
struct param *pp, *altpp, *svpp;
void strsetval();
if (setjmp(esccontext))
{
errpnt("MIDI operation aborted", 0, 0, 0);
return;
}
if (single)
{
dp = &dump[curpatch][0];
altdp = &mdump[curmpatch][0];
size = 88;
curpch = &curpatch;
curprm = &curparam;
len = 64;
pp = ¶ms[curparam];
altpp = &mparams[curmparam];
}
else
{
altdp = &dump[curpatch][0];
dp = &mdump[curmpatch][0];
size = 76;
curpch = &curmpatch;
curprm = &curmparam;
len = 32;
pp = &mparams[curmparam];
altpp = ¶ms[curparam];
}
while (kbhit() == 0)
if (echo)
midiecho();
c = getch();
if (c == 0)
{
c = 0x80|getch();
/* F1 - F8 play tritone-spaced notes at midling velocity */
if (is_midiinit && c >= cF1 && c <= cF8)
{
c -= cF1;
if (noteon[c])
{
midinote(36+c*6, 0);
noteon[c] = 0;
}
else
{
midinote(36+c*6, 72);
noteon[c] = 1;
}
return;
}
}
switch (c)
{
/* Save buffers in file */
case 's':
case 'S':
str[0] = '\0';
if (getinput("Save file name", str) != NULL && str[0] != '\0')
savedump(str);
break;
/* Load buffered from file */
case 'l':
case 'L':
str[0] = '\0';
if (getinput("Load file name", str) != NULL && str[0] != '\0')
loaddump(str);
refresh();
break;
/* receive single patch from K-1 */
case 'r':
recvpatch();
midipgm(single?(*curpch):(*curpch|0x40));
refresh();
break;
/* Receive all patches from of K-1 */
case 'R':
recvdump();
midipgm(single?(*curpch):(*curpch|0x40));
refresh();
break;
/* transmit single patch to K-1 */
case 't':
tranpatch();
midipgm(single?(*curpch):(*curpch|0x40));
break;
/* Transmit all patches to K-1 */
case 'T':
trandump();
midipgm(single?(*curpch):(*curpch|0x40));
break;
/* Quit patch editor */
case 'q':
case 'Q':
(void)strcpy(str, "Yes");
if (getinput("Confirm (Y/N)", str) != NULL && (str[0]|0x20) == 'y')
{
gotoxy(1, 25);
exit(0);
}
break;
/* toggle MIDI echo */
case 'e':
echo = !echo;
break;
/* switch between SINGLE and MULTI */
case cF10:
single = !single;
dp = altdp;
pp = altpp;
dispatch(dp);
if (is_midiinit)
midipgm(single?(*curpch):(*curpch|0x40));
break;
/* refresh screen */
case cFORM:
refresh();
break;
/* show previous patch */
case cPGUP:
if (*curpch > 0)
{
(*curpch)--;
dp -= size;
}
dispatch(dp);
if (!visible(pp, dp))
{
pp -= *curprm;
*curprm = 0;
}
if (is_midiinit)
midipgm(single?(*curpch):(*curpch|0x40));
break;
/* show next patch */
case cPGDN:
if (*curpch < len-1)
{
(*curpch)++;
dp += size;
}
dispatch(dp);
if (!visible(pp, dp))
{
pp -= *curprm;
*curprm = 0;
}
if (is_midiinit)
midipgm(single?(*curpch):(*curpch|0x40));
break;
/* move to previous parameter */
case cLEFT:
do
{
if (*curprm > 0)
{
(*curprm)--;
pp--;
}
else
break;
} while (!visible(pp, dp));
break;
/* move to next parameter */
case cRGHT:
do
{
if ((pp+1)->p_type != PEND)
{
(*curprm)++;
pp++;
}
else
{ pp -= *curprm;
*curprm = 0;
}
} while (!visible(pp, dp));
break;
/* move up one row */
case cUP:
row = pp->p_row;
col = pp->p_col;
do
{
if (*curprm > 0)
{
(*curprm)--;
pp--;
}
else
break;
} while (pp->p_row >= row
|| pp->p_col > col+3 || !visible(pp, dp));
break;
/* move down one row */
case cDOWN:
row = pp->p_row;
col = pp->p_col;
cur = *curprm;
svpp = pp;
do
{
if ((pp+1)->p_type != PEND)
{
(*curprm)++;
pp++;
}
else
{
*curprm = cur;
pp = svpp;
break;
}
} while (pp->p_row <= row
|| pp->p_col < col-3 || !visible(pp, dp));
break;
/* move to first parameter */
case cHOME:
pp -= *curprm;
*curprm = 0;
break;
/* move to last parameter */
case cEND:
svpp = pp;
cur = *curprm;
while ((pp+1)->p_type != PEND)
{
curparam++;
pp++;
if (visible(pp, dp))
{
svpp = pp;
cur = *curprm;
}
}
pp = svpp;
*curprm = cur;
break;
/* add one to parameter value */
case '+':
if (pp->p_type == LSTR)
break;
setvalue(pp, getvalue(pp, dp)+1, dp);
if (pp->p_flags&FRDW)
dispatch(dp);
break;
/* subtract one from parameter value */
case '-':
if (pp->p_type == LSTR)
break;
setvalue(pp, getvalue(pp, dp)-1, dp);
if (pp->p_flags&FRDW)
dispatch(dp);
break;
/* allow typein of parameter value */
case '\n':
case '\r':
(void)strcpy(str, valstr(pp, getvalue(pp, dp), dp));
if (getinput("Enter value", str) == NULL || str[0] == '\0')
break;
strsetval(pp, str, dp);
if (pp->p_flags&FRDW)
dispatch(dp);
break;
/* ignore other keystrokes */
default:
break;
}
if (visible(pp, dp))
showparam(pp, dp);
gotoxy((int)pp->p_col, (int)pp->p_row);
}
/*
* set a parameter from a string
*/
void
strsetval(pp, str, dp)
struct param *pp;
char *str;
unsigned char *dp;
{
char **cpp;
char tmp[80];
int len, val;
int match();
int notecv();
val = -9999;
switch(pp->p_type)
{
case LSTR:
(void)strcpy(tmp, str);
len = strlen(tmp);
while (len < pp->p_limit)
tmp[len++] = ' ';
(void)strncpy((char *)&dp[pp->p_byte], tmp, pp->p_limit);
return;
case SNUM:
case UNUM:
val = atoi(str);
break;
case ENUM:
val = getvalue(pp, dp);
for (cpp = pp->p_names; *cpp != NULL; cpp++)
if (match(str, *cpp))
{
val = (cpp-pp->p_names)+pp->p_bias;
break;
}
break;
case SPL1:
if ((dp[pp->p_byte+8]&02) != 0)
val = atoi(str);
else
{
val = notecv(str);
if (val == -99)
return;
val += 24;
}
break;
case SPL3:
val = notecv(str);
if (val == -99)
return;
break;
}
setvalue(pp, val, dp);
}
/*
* convert string into MIDI note value
*/
unsigned char notval[] = {9, 11, 0, 2, 4, 5, 7};
int
notecv(str)
char *str;
{
int val, c;
c = (int)(str[0]&~0x20)-'A';
if (c < 0 || c > 6)
return -99;
val = notval[c];
c = 1;
if (str[1] == '#')
{
val++;
c++;
}
if (str[c] != '-' && (str[c] < '0' || str[c] > '9'))
return -99;
else
return val+12*(atoi(str+c)+2);
}
/*
* oddball string match; match on first two characters unless digits,
* then look at up to 3. This allows type-in of waveform numbers,
* while two characters are unambiguous for the other stuff.
*
* Ignore case in the simplest way possible, and ignore the possible
* synonyms this creates for other chars.
*/
int
match(r, t)
char *r, *t;
{
while (*r == ' ')
r++;
while (*t == ' ')
t++;
if ((*r++&0x3f) != (*t++&0x3f))
return 0;
if ((*r++&0x3f) != (*t++&0x3f))
return 0;
if (*r < '0' || *r > '9')
return 1;
return (*r == *t);
}
/*
* Main program -- at end, and I don't even *like* PASCAL...
*/
void
main(argc, argv)
int argc;
char **argv;
/*ARGSUSED*/
{
textmode(7);
window(1, 1, 80, 25);
/*
* Note: you may remove the next two lines for your personal
* use but you must replace them before distributing any copies
* of this software.
*/
distemplate(st_copyright);
sleep(5);
distemplate(st_screen);
curpatch = 0;
curparam = 0;
curmpatch = 0;
curmparam = 0;
echo = 0;
single = 0;
dispatch(&mdump[curmpatch][0]);
single = 1;
dispatch(&dump[curpatch][0]);
showparam(¶ms[curparam], &dump[curpatch][0]);
for (;;)
docommand();
/*NOTREACHED*/
}