[comp.sources.misc] v06i113: glib part 12 of 15

allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) (05/15/89)

Posting-number: Volume 6, Issue 113
Submitted-by: lee@uhccux.uhcc.Hawaii.Edu (Greg Lee )
Archive-name: glib/part12

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 12 (of 15)."
# Contents:  cz1.mnu
# Wrapped by lee@uhccux on Sun May  7 00:40:19 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'cz1.mnu' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'cz1.mnu'\"
else
echo shar: Extracting \"'cz1.mnu'\" \(33418 characters\)
sed "s/^X//" >'cz1.mnu' <<'END_OF_FILE'
X/* $Id: cz1.mnu,v 1.6 89/05/06 17:13:14 lee Exp $
X * GLIB - a Generic LIBrarian and editor for synths
X *
X * CZ-1 routines
X * Mark Rinfret
X * modified by Greg Lee
X * $Log:	cz1.mnu,v $
X * Revision 1.6  89/05/06  17:13:14  lee
X * rel. to comp.sources.misc
X * 
X */
X
X#define OVERLAY1
X
X#include "glib.h"
X#include <ctype.h>
X
X#ifdef AMIGA
X#define CZ1
X#else
Xvoid sendmulti();
X#endif
X
X#include "cz.h"
X
X#define RING    1
X#define NOISE   2
X
Xchar *visnum(), *visonoff();
Xchar *visczdet(), *visczflag(), *visczline(), *visczmod(), *viscznum2();
X/* char *visczoct(); */
X
Xstatic void getenvelope();
Xstatic void getwaveforms();
Xstatic void setenvelope();
Xstatic void setwaveforms();
X
X#define RESERVESIZE 0
X/* This array contains arbitrary screen labels */
Xstruct labelinfo Lcz1[] = {
X#MENU
XName:                  Line:%       Mod:%        Octave   Vibrato Wave:%
X                                                  %              Delay:%
X                   Envelope                                       Rate:%
X       w1 w2       1   2   3   4   5   6   7   8                 Depth:%
XDCO1    %  %      % @ % @ % @ % @ % @ % @ % @ % @  <-Rate  S=SUS E=END
X                  %   %   %   %   %   %   %   %    <-Level
XDCW1  follow: %   % @ % @ % @ % @ % @ % @ % @ % @
X                  %   %   %   %   %   %   %   %     Level  VA VW VP
XDCA1  follow: %   % @ % @ % @ % @ % @ % @ % @ % @    %     %  %  %
X                  %   %   %   %   %   %   %   %
X-------------------------------------------------  Detune
XDCO2    %  %      % @ % @ % @ % @ % @ % @ % @ % @  % Oct:%  Note:%  Fine: %
X                  %   %   %   %   %   %   %   %
XDCW2  follow: %   % @ % @ % @ % @ % @ % @ % @ % @
X                  %   %   %   %   %   %   %   %     Level  VA VW VP
XDCA2  follow: %   % @ % @ % @ % @ % @ % @ % @ % @    %     %  %  %
X                  %   %   %   %   %   %   %   %
XPortamento    Glide     Bend   Mod. Wheel        Amp.
XSweep: %      Note: %     %    Depth:        %   Aftertouch: %
X Time: %      Time: %          Aftertouch:   %
X
X   Pitch %    Vol  %
X   Dur   %    Chan %
X
X#END
X-1,-1,NULL
X};
X
Xstruct paraminfo  Pcz1[] =  {
X/*
XNAME		TYPE	POS	MAX	OFFSET	MASK	SHIFT	ADHOC
X */
X#O line		czline	%%	3	0
X#O mod		czmod	%%	2	0
X#O vwave	num	%%	4	0			*5
X#O oct		num	%%	1	0			*5
X#O vdelay	cznum2	%%	99	0
X#O vrate	cznum2	%%	99	0
X#O vdepth	cznum2	%%	99	0
X#O o1w1		num	%%	8	0			*5
X#O o1w2		num	%%	8	0
X#O 8o1r		cznum2	%%	99	0
X#O 8o1f		czflag	@@	2	0
X#O 8o1l		cznum2	%%	99	0
X#O wf1		num	%%	9	0
X#O 8w1r		cznum2	%%	99	0
X#O 8w1f		czflag	@@	2	0
X#O 8w1l		cznum2	%%	99	0
X#O af1		num	%%	9	0
X#O 8a1r		cznum2	%%	99	0
X#O 8a1f		czflag	@@	2	0
X#O level1	cznum2	%%	15	0			*5
X#O va1		cznum2	%%	15	0
X#O vw1		cznum2	%%	15	0
X#O vo1		cznum2	%%	15	0
X#O 8a1l		cznum2	%%	99	0
X#O o2w1		num	%%	8	0			*5
X#O o2w2		num	%%	8	0			*5
X#O 8o2r		cznum2	%%	99	0
X#O 8o2f		czflag	@@	2	0
X#O detsign	czdet	%%	1	0
X#O detoct	num	%%	3	0
X#O detnote	cznum2	%%	11	0
X#O detfine	cznum2	%%	60	0
X#O 8o2l		cznum2	%%	99	0
X#O wf2		num	%%	9	0
X#O 8w2r		cznum2	%%	99	0
X#O 8w2f		czflag	@@	2	0
X#O 8w2l		cznum2	%%	99	0
X#O af2		num	%%	9	0
X#O 8a2r		cznum2	%%	99	0
X#O 8a2f		czflag	@@	2	0
X#O level2	cznum2	%%	15	0			*5
X#O va2		cznum2	%%	15	0
X#O vw2		cznum2	%%	15	0
X#O vo2		cznum2	%%	15	0
X#O 8a2l		cznum2	%%	99	0
X#O psweep	cznum2	%%	1	0
X#O gnote	num	%%	12	0
X#O bend		cznum2	%%	12	0
X#O mdepth	cznum2	%%	99	0
X#O amptouch	cznum2	%%	99	0
X#O ptime	cznum2	%%	99	0
X#O gtime	cznum2	%%	99	0
X#O mtouch	cznum2	%%	99	0
X#O autopitch	num	%%	127	-60
X#O autovol	num	%%	127	-63
X#O autodur	num	%%	20	-5			*5
X#O autochan	num	%%	16	-1			*5
XNULL,NULL,-1,-1,-1,-1,visnum,0,0,0,0
X};
X
X
X/*  The following table converts AMP level visual values into
X    MIDI values 00 - 5F.
X */
XUBYTE ampLevelMIDI[10] = {
X    0x00, 0x08, 0x11, 0x1a, 0x24, 0x2f, 0x3a, 0x45, 0x52, 0x5f
X    };
X
X/*  The following table converts WAVE key follow visual values 0-9 into
X    MIDI values 00 - FF.
X */
XUBYTE keyFollowMIDI[10] = {
X    0x00, 0x19, 0x33, 0x4e, 0x6a, 0x86, 0xa3, 0xc1, 0xdf, 0xff
X    };
X
X/*  The following table converts a simple VIBRATO depth value (0..99)
X    into a word representing bytes 1-2 of the vibrato depth group. */
XUSHORT vDepthTable[100] = {
X/* 00 */    0x0001, 0x0002, 0x0003, 0x0004, 0x0005,
X/* 05 */    0x0006, 0x0007, 0x0008, 0x0009, 0x000a,
X/* 10 */    0x000b, 0x000c, 0x000e, 0x000e, 0x000f,
X/* 15 */    0x0010, 0x0011, 0x0012, 0x0013, 0x0014,
X/* 20 */    0x0015, 0x0016, 0x0017, 0x0018, 0x0019,
X/* 25 */    0x001a, 0x001b, 0x001c, 0x001d, 0x001e,
X/* 30 */    0x001f, 0x0020, 0x0023, 0x0025, 0x0027,
X/* 35 */    0x0029, 0x002b, 0x002d, 0x002f, 0x0031,
X/* 40 */    0x0033, 0x0035, 0x0037, 0x0039, 0x003b,
X/* 45 */    0x003d, 0x003f, 0x0041, 0x0047, 0x004b,
X/* 50 */    0x004f, 0x0053, 0x0057, 0x005b, 0x005f,
X/* 55 */    0x0063, 0x0067, 0x006b, 0x006f, 0x0073,
X/* 60 */    0x0077, 0x007b, 0x007f, 0x0083, 0x008f,
X/* 65 */    0x0097, 0x009f, 0x00a7, 0x00af, 0x00b7,
X/* 70 */    0x00bf, 0x00c7, 0x00cf, 0x00d7, 0x00df,
X/* 75 */    0x00e7, 0x00ef, 0x00f7, 0x00ff, 0x0107,
X/* 80 */    0x011f, 0x012f, 0x013f, 0x014f, 0x015f,
X/* 85 */    0x016f, 0x017f, 0x018f, 0x019f, 0x01af,
X/* 90 */    0x01bf, 0x01cf, 0x01df, 0x01ef, 0x01ff,
X/* 95 */    0x020f, 0x023f, 0x025f, 0x027f, 0x0300
X};
X
X
X/*  The following table converts a simple VIBRATO delay time index
X    (0..99) into a word representing the second two bytes of the
X    vibrato delay group.  As usual, this represents some really wierd
X    encoding.
X*/
X
XUSHORT vDelayTable[100] = {
X/* 00 */    0x0000, 0x0001, 0x0002, 0x0003, 0x0004,
X/* 05 */    0x0005, 0x0006, 0x0007, 0x0008, 0x0009,
X/* 10 */    0x000a, 0x000b, 0x000c, 0x000d, 0x000e,
X/* 15 */    0x000f, 0x0010, 0x0011, 0x0012, 0x0013,
X/* 20 */    0x0014, 0x0015, 0x0016, 0x0017, 0x0018,
X/* 25 */    0x0019, 0x001a, 0x001b, 0x001c, 0x001d,
X/* 30 */    0x001e, 0x001f, 0x0021, 0x0023, 0x0025, /* <== change begins */
X/* 35 */    0x0027, 0x0029, 0x002b, 0x002d, 0x002f,
X/* 40 */    0x0031, 0x0033, 0x0035, 0x0037, 0x0039,
X/* 45 */    0x003b, 0x003d, 0x003f, 0x0043, 0x0047,
X/* 50 */    0x004b, 0x004f, 0x0053, 0x0057, 0x005b,
X/* 55 */    0x005f, 0x0063, 0x0067, 0x006b, 0x006f,
X/* 60 */    0x0073, 0x0077, 0x007b, 0x007f, 0x0087,
X/* 65 */    0x008f, 0x0097, 0x009f, 0x00a7, 0x00af,
X/* 70 */    0x00b7, 0x00bf, 0x00c7, 0x00d7, 0x00df,
X/* 75 */    0x00e7, 0x00ef, 0x00f7, 0x00ff, 0x000f,
X/* 80 */    0x010f, 0x011f, 0x012f, 0x013f, 0x014f,
X/* 85 */    0x015f, 0x016f, 0x017f, 0x018f, 0x019f,
X/* 90 */    0x01af, 0x01bf, 0x01cf, 0x01df, 0x01ef,
X/* 95 */    0x01ff, 0x021f, 0x023f, 0x025f, 0x017f
X};
X
X/*  The following table converts a simple VIBRATO rate index (0..99)
X    into the value of bytes 1-2 of the vibrato rate group. */
XUSHORT vRateTable[100] = {
X/* 00 */    0x0020, 0x0040, 0x0060, 0x0080, 0x00a0,
X/* 05 */    0x00c0, 0x00e0, 0x0100, 0x0120, 0x0140,
X/* 10 */    0x0160, 0x0180, 0x01a0, 0x01c0, 0x01e0,
X/* 15 */    0x0200, 0x0220, 0x0240, 0x0260, 0x0280,
X/* 20 */    0x02a0, 0x02c0, 0x02e0, 0x0300, 0x0320,
X/* 25 */    0x0340, 0x0360, 0x0380, 0x03a0, 0x03c0,
X/* 30 */    0x03e0, 0x0400, 0x0460, 0x04a0, 0x04e0,
X/* 35 */    0x0520, 0x0560, 0x05a0, 0x05e0, 0x0620,
X/* 40 */    0x0660, 0x06a0, 0x06e0, 0x0720, 0x0760,
X/* 45 */    0x07a0, 0x07e0, 0x0820, 0x08e0, 0x0960,
X/* 50 */    0x09e0, 0x0a60, 0x0ae0, 0x0b60, 0x0be0,
X/* 55 */    0x0c60, 0x0ce0, 0x0d60, 0x0de0, 0x0e60,
X/* 60 */    0x0ee0, 0x0f60, 0x0fe0, 0x1060, 0x11e0,
X/* 65 */    0x12e0, 0x13e0, 0x14e0, 0x15e0, 0x16e0,
X/* 70 */    0x17e0, 0x18e0, 0x19e0, 0x1ae0, 0x1be0,
X/* 75 */    0x1ce0, 0x1de0, 0x1ee0, 0x1fe0, 0x20e0,
X/* 80 */    0x23e0, 0x25e0, 0x27e0, 0x29e0, 0x2be0,
X/* 85 */    0x2d30, 0x2fe0, 0x31e0, 0x33e0, 0x35e0,
X/* 90 */    0x37e0, 0x39e0, 0x3be0, 0x3de0, 0x3fe0,
X/* 95 */    0x41e0, 0x47e0, 0x4be0, 0x4fe0, 0x53e0
X};
X
X
X
X/*  FUNCTION
X        cz1din - convert CZ1 data to program format.
X
X    SYNOPSIS
X        int cz1din(data)
X                struct ToneData *data;
X
X    DESCRIPTION
X        Take info from <data> and stuff values into the P array, using
X        the setval and setopval functions.
X*/
Xint
Xcz1din(data)
X    struct ToneData *data;
X{
X    register int     value;
X
X    setval("line", (INT16)data->lineAndOctave & 3);
X    value = (data->waveForms1[1] >> 3) & 7;
X    if (value == 4)
X        value = RING;
X    else if (value == 3)
X        value = NOISE;
X    setval("mod", (INT16)value);
X    value = (data->lineAndOctave >> 2) & 3;
X    if (value == 2) value = -1;     /* 2 => -1 */
X    setval("oct", (INT16)value);
X
X    /* Extract the DETUNE information: */
X    setval("detsign", (INT16)data->detuneSign);
X
X    /* The FINE detune info must have a correction factor applied: */
X    value = data->detuneFine >> 2;
X    if (value > 47) value -= 3;
X    else if (value > 31) value -= 2;
X    else if (value > 15) value -= 1;
X    setval("detfine", (INT16)value);
X
X    /* The NOTE and OCTAVE detune info are obtained by factoring the
X       semitone info in detuneCoarse: */
X
X    setval("detnote", (INT16)data->detuneCoarse % 12);
X    setval("detoct", (INT16)data->detuneCoarse / 12);
X
X    /* Get the VIBRATO info: */
X    value = data->vibratoWave & 0x2E;
X    switch (value) {
X    case 2:
X        value = 4;
X        break;
X    case 4:
X        value = 2;
X        break;
X    case 8:
X        value = 1;
X        break;
X
X    case 32:
X        value = 3;
X        break;
X
X    default:
X        value = 1;
X        break;
X
X    }
X    setval("vwave",     (INT16)value);
X    setval("vdelay",    (INT16)data->vibratoTime[0]);
X    setval("vrate",     (INT16)data->vibratoRate[0]);
X    setval("vdepth",    (INT16)data->vibratoDepth[0]);
X
X    /* Set onscreen parameters for patch area 1. */
X    setwaveforms("o1", data->waveForms1);
X
X    /* setenvelope sets all rates and levels for an envelope. */
X    setenvelope("o1", data->DCO_Envelope1, data->DCO_EndStep1);
X    setenvelope("w1", data->DCW_Envelope1, data->DCW_EndStep1);
X    setenvelope("a1", data->DCA_Envelope1, data->DCA_EndStep1);
X
X    /* Set key follow parameters for area 1. */
X
X    setval("wf1", (INT16)data->DCW1_KeyFollow[0] & 0xf);
X    setval("af1", (INT16)data->DCA1_KeyFollow[0] & 0xf);
X
X    value = 15 - (data->DCA1_KeyFollow[0] >> 4);
X    setval("level1", (INT16)value);
X
X    /* Set onscreen parameters for patch area 2. */
X    setwaveforms("o2", data->waveForms2);
X
X    /* Set the envelope parameters for patch area 2. */
X    setenvelope("o2", data->DCO_Envelope2, data->DCO_EndStep2);
X    setenvelope("w2", data->DCW_Envelope2, data->DCW_EndStep2);
X    setenvelope("a2", data->DCA_Envelope2, data->DCA_EndStep2);
X
X    /* Set key follow parameters for area 2. */
X
X    setval("wf2", (INT16)data->DCW2_KeyFollow[0] & 0xf);
X    setval("af2", (INT16)data->DCA2_KeyFollow[0] & 0xf);
X
X    value = 15 - (data->DCA2_KeyFollow[0] >> 4);
X    setval("level2", (INT16)value);
X    return 0;
X}
X
X/*  FUNCTION
X        cz1dout - convert program data to CZ1 format.
X
X    SYNOPSIS
X        int cz1dout(data)
X                struct ToneData *data;
X
X    DESCRIPTION
X        Cz1dout takes data from the P array and converts it to CZ1 format,
X        storing it in the patch area defined by <data>.
X
X*/
Xint
Xcz1dout(data)
X    struct ToneData *data;
X{
X    int value, value2;
X
X    value = getval("oct");          /* Get, correct octave value. */
X    if (value < 0) value = 2;
X    data->lineAndOctave = getval("line") | (value << 2);
X    data->detuneSign = getval("detsign");
X    /* The DETUNE coarse data is converted from OCT and NOTE into a
X       semitone value ranging from 0 to 47(2F).  It is then stored
X       in the high byte of the pair.
X    */
X    value = getval("detoct") * 12 + getval("detnote");
X    data->detuneCoarse = value;
X
X    /* The DETUNE fine data has a correction factor applied to it,
X       and is then shifted to fit into bits 7-2 of the the low byte.
X    */
X    value = getval("detfine");
X    if (value > 45) value += 3;
X    else if (value > 30) value += 2;
X    else if (value > 15) value += 1;
X    data->detuneFine = value << 2;
X
X    value = getval("detnote");
X    value += getval("detoct") * 12;
X    data->detuneCoarse = value;
X
X    /* VIBRATO information: */
X    value = getval("vwave");
X    switch (value) {
X    case 1:
X        value = 8;
X        break;
X    case 2:
X        value = 4;
X        break;
X    case 3:
X        value = 32;
X        break;
X    default:
X        break;
X    }
X    data->vibratoWave = data->vibratoWave = value;
X
X    /* Get vibrato delay. */
X    value = getval("vdelay");
X    data->vibratoTime[0] = value;
X    value = vDelayTable[value];
X    data->vibratoTime[1] = value;
X    data->vibratoTime[2] = value>>8;
X
X    /* Get vibrato rate. */
X    value = getval("vrate");
X    data->vibratoRate[0] = value;
X    value = vRateTable[value];
X    data->vibratoRate[1] = value;
X    data->vibratoRate[2] = value >> 8 ;
X
X    /* Get vibrato depth. */
X    value = getval("vdepth");
X    data->vibratoDepth[0] = value;
X    value = vDepthTable[value];     /* Get bytes 1, 2 from table. */
X    data->vibratoDepth[1] = value;
X    data->vibratoDepth[2] = value >> 8;
X
X    /* Get envelope values: */
X    getenvelope("o1", data->DCO_Envelope1, &data->DCO_EndStep1);
X    getenvelope("w1", data->DCW_Envelope1, &data->DCW_EndStep1);
X    getenvelope("a1", data->DCA_Envelope1, &data->DCA_EndStep1);
X    getwaveforms("o1", data->waveForms1);
X    value = getval("wf1");
X    data->DCW1_KeyFollow[0] = value;
X    data->DCW1_KeyFollow[1] = keyFollowMIDI[value];
X
X    /* The amp level and key follow values share the DCAx_KeyFollow
X       field.                                                       */
X
X    value = getval("af1");
X    value2 = getval("level1");
X    value2 = (15 - value2) << 4;
X    data->DCA1_KeyFollow[0] = value | value2;
X    data->DCA1_KeyFollow[1] = ampLevelMIDI[value];
X
X    getenvelope("o2", data->DCO_Envelope2, &data->DCO_EndStep2);
X    getenvelope("w2", data->DCW_Envelope2, &data->DCW_EndStep2);
X    getenvelope("a2", data->DCA_Envelope2, &data->DCA_EndStep2);
X    getwaveforms("o2", data->waveForms2);
X    data->DCW2_KeyFollow[0] = value = getval("wf2");
X    data->DCW2_KeyFollow[1] = keyFollowMIDI[value];
X
X    value = getval("af2");
X    value2 = getval("level2");
X    value2 = (15 - value2) << 4;
X    data->DCA2_KeyFollow[0] = value | value2;
X    data->DCA2_KeyFollow[1] = ampLevelMIDI[value];
X
X    return 0;
X}
X
X/*  FUNCTION
X        cz1nof - return a pointer to a patch internal name.
X
X    SYNOPSIS
X        char *cz1nof(data)
X              struct ToneData *data;
X
X    DESCRIPTION
X        Cz1nof extracts a local copy of the voice name (in <data>) and
X        returns a pointer to it.
X
X*/
X
Xchar *
Xcz1nof(data)
X    struct ToneData *data;
X{
X    static char name[17];
X    UBYTE *n;
X    int i;
X
X    for (i=0, n = data->name; i < 16; ++i)
X        name[i] = *n++;
X
X    name[16] = '\0';
X    return name;
X}
X
X/*  FUNCTION
X        cz1snof - store a voice name.
X
X    SYNOPSIS
X        int cz1snof(data, name)
X                struct ToneData *data, *name;
X
X    DESCRIPTION
X        Cz1snof stores the new voice <name> into the patch area defined
X        by <data>.
X
X*/
Xint
Xcz1snof(data, name)
X    struct ToneData *data; char *name;
X
X{
X    int     i;
X    UBYTE   *n;
X
X    for (i = 0, n = data->name; (i < 16) && *name; ++i)
X        *n++ = *name++;
X
X    while (i < 16) {
X        *n++ = ' ';
X        ++i;
X    }
X}
X
X#ifdef CZ1SBULK
X/*  FUNCTION
X        cz1sbulk - send bulk patch data to the CZ1.
X
X    SYNOPSIS
X        int cz1sbulk(data)
X                struct ToneData *data;
X
X    DESCRIPTION
X        Cz1sbulk sends 64 voice patches to the CZ1.
X
X*/
X
Xint
Xcz1sbulk(data)
X    struct ToneData *data;
X{
X    return 0;
X}
X#endif
X
X/*  FUNCTION
X        cz1gbulk - get bulk patch data from CZ1.
X
X    SYNOPSIS
X        int cz1gbulk(data)
X                char *data;
X
X    DESCRIPTION
X        Cz1gbulk reads 64 voices of patch data from the CZ1 into <data>.
X
X*/
Xint
Xcz1gbulk(data)
X    char *data;
X{
X    char    *addr;
X    int     i;
X    char    msg[40];
X    int     result, voice;
X
X    /* !!! I want to change this so we can access the cartridge pack
X     * !!! as well.  A simple flag should do it.
X     */
X
X    for (voice = FIRST_INTERNAL; voice <= LAST_INTERNAL; ++voice) {
X        addr = data + voice * sizeof(struct ToneData);
X        (void)sprintf(msg, "Reading CZ1 voice %d.", voice);
X        windgoto(3,10);
X        windstr(msg);
X        windrefresh();
X        if (result = ReceiveCZPatch((struct ToneData *)addr,
X					(UBYTE)Channel, (UBYTE)voice)) {
X            (void)sprintf(msg, "Failed to read CZ1 voice %d!", voice);
X            windgoto(3, 10);
X            windstr(msg);
X            windrefresh();
X            return result;
X        }
X    }
X    for (i = 0; i < 39; ++i) msg[i] = ' ';
X    msg[i] = '\0';
X    windgoto(3, 10);
X    windstr(msg);
X    windrefresh();
X    return 0;
X}
X
X/*  FUNCTION
X        cz1sedit - send a single voice to the CZ1 edit buffer.
X
X    SYNOPSIS
X        int cz1sedit(data)
X                struct ToneData *data;
X
X    DESCRIPTION
X        Cz1sedit sends a single voice to the CZ1 edit buffer.
X
X*/
X
Xint
Xcz1sedit(data)
X    struct ToneData *data;
X{
X    return SendCZPatch(data, Channel, SOUND_DATA);
X}
X
X/*  FUNCTION
X        cz1sone - send one voice to the CZ1.
X
X    SYNOPSIS
X        int cz1sone(vx, data)
X                    int             vx;
X                    struct ToneData *data;
X
X    DESCRIPTION
X        Cz1sone sends one voice (number specified by <vx>) to the CZ1.
X        The <data> argument points to the patch data to be sent.
X
X        Cz1sone returns 0 on success, -1 on failure.
X
X*/
X
Xint
Xcz1sone(vx, data)
X    int     vx;
X    char    *data;
X{
X    return SendCZPatch((struct ToneData *)data, Channel, vx);
X}
X
X/*  FUNCTION
X        GetCZSysEx - wait for system exclusive byte or time-out.
X
X    SYNOPSIS
X        int GetCZEndSysEx();
X
X    DESCRIPTION
X        GetCZSysEx waits for a system exclusive byte from the CZ1.
X        If the next byte received is a system exclusive, a zero
X        result is returned, indicating success.  If the byte received
X        is not a sysex, or if a timeout occurs, a one (1) is returned
X        and the error reason, Reason, is set appropriately.
X
X*/
Xint
XGetCZEndSysEx()
X{
X    unsigned char    c;
X    long    begin, toolong;
X    static char    msg[40];
X
X    begin = milliclock();
X    toolong = begin + 2000;     /* Wait for 2 seconds. */
X
X    while (milliclock() < toolong) {
X        if (STATMIDI) {
X            c = getmidi() & 0xFF;
X            if (c != END_SYSTEM_EXCLUSIVE) {
X                (void)sprintf(msg,"Waited for %02xx, got %02xx",
X                        END_SYSTEM_EXCLUSIVE, c & 0xFF);
X                Reason = msg;
X                return 1;
X            }
X            return 0;
X        }
X    }
X    Reason = "Timed out waiting for end sysex.";
X    return 1;
X}
X
X/*  FUNCTION
X        SendCZPatch - send one voice to the CZ1
X
X    SYNOPSIS
X        int SendCZPatch(tonedata, channel, voice)
X                        struct ToneData *tonedata;
X                        int channel, voice;
X
X    DESCRIPTION
X        SendCzPatch sends one voice patch (<tonedata>) to the CZ1,
X        using the specified <channel>.  The <voice> argument determines
X        which synthesizer program area the data will be sent to.
X
X        Note that the CZ family behaves in a wierd way, splitting all
X        tone data bytes into two pieces.  SendToneData splits the bytes
X        to a local buffer prior to transmitting them.
X*/
Xstatic int
XSendCZPatch(tonedata, channel, voice)
Xstruct ToneData *tonedata;
Xint channel,voice;
X{
X    long    begin, toolong;             /* timer values */
X
X#ifdef CZ101
X/* Receive request 1 system exclusive */
X
Xstatic UBYTE receive_request[] = {
X    0xF0,0x44,0x00,0x00,0x70,0x20,0x00 };
X#endif
X
X#ifdef CZ1
Xstatic UBYTE receive_request[] = {
X        0xF0,0x44,0x00,0x00,0x70,0x21,0x00 };
X#endif
X
X    UBYTE data[512];
X    UBYTE *ptr;
X
X    int i;
X
X    /* Clear the serial buffer of any unread data */
X  if (!synthoutfileflag)
X    flushmidi();
X
X    /* Fill in channel and voice, then send request. */
X
X    receive_request [4] = 0x70 | ((channel - 1) & 0x0F);
X    receive_request [6] = voice;
X
X    sendmulti(receive_request, sizeof(receive_request));
X
X    /* Get the reply message. It's six bytes consisting of:
X            F0 44 00 00 7N 30  where N is the channel number.
X     */
X
X    begin = milliclock();
X    toolong = begin + 5000L;
X  if (!synthoutfileflag)
X    for (i = 0; i < 6; ) {
X        if (STATMIDI) {                 /* Something available? */
X            data[i++] = getmidi();
X        }
X        else if (milliclock() > toolong) {
X            Reason = "Timeout waiting for receive request 1 reply.";
X            return 1;
X        }
X    }
X
X    /* Split the data into 4-bit nybbles. */
X
X    ptr = (UBYTE *) tonedata;
X
X    for (i=0; i<sizeof(struct ToneData)*2; i+=2) {
X        data[i] = *ptr & 0x0F;
X        data[i+1] = (*ptr >> 4) & 0x0F;
X        ++ptr;
X    }
X
X    /* Add "end-system-exclusive" to tone data buffer */
X
X    data[i] = END_SYSTEM_EXCLUSIVE;
X
X    /* Send tone data to synth */
X
X    sendmulti(data, sizeof(struct ToneData) * 2 + 1);
X
X    /* Read "end-system-exclusive" from synth */
X
X  if (!synthoutfileflag)
X    return GetCZEndSysEx();
X  else return 0;
X}
X
X/*  FUNCTION
X        ReceiveCZPatch - receive one CZ1 voice patch.
X
X    SYNOPSIS
X        int ReceiveCZPatch(tonedata, channel, voice);
X                           struct ToneData *tonedata;
X                           int channel, voice;
X
X    DESCRIPTION
X        ReceiveCZPatch requests one CZ1 voice patch. It combines the
X        voice nybbles sent by the CZ1 into a normal ToneData structure.
X
X        ReceiveCZPatch returns zero on success.  On failure, it returns
X        one (1) after setting Reason to a string describing the failure.
X*/
X
Xint
XReceiveCZPatch(tonedata, channel, voice)
Xstruct ToneData *tonedata;
XUBYTE channel,voice;
X{
X#ifdef CZ101
X/* Send Request 1 system exclusive data */
X
Xstatic UBYTE send_request_1A [] = {
X    0xF0,0x44,0x00,0x00,0x70,0x10,0x00 };
X
Xstatic UBYTE send_request_1B [] = {
X    0x70,0x31 };
X#endif
X
X#ifdef CZ1
Xstatic UBYTE send_request_1A [] = {
X        0xF0,0x44,0x00,0x00,0x70,0x11,0x00 };
X
Xstatic UBYTE send_request_1B [] = {
X        0x70,0x31 };
X#endif
X
X    long    begin, toolong;
X    UBYTE   data[512];
X    UBYTE   *ptr;
X
X    int i;
X
X    /* Clear the serial buffer of any unread data */
X
X    flushmidi();
X
X    /* Set channel and voice info, then send the request to the CZ1. */
X
X    send_request_1A [4] = 0x70 | ((channel - 1) & 0x0F);
X    send_request_1A [6] = voice;
X
X    sendmulti(send_request_1A, sizeof(send_request_1A));
X
X    /* Get the reply message. It's six bytes consisting of:
X            F0 44 00 00 7N 30  where N is the channel number.
X     */
X
X    begin = milliclock();
X    toolong = begin + 5000L;
X    for (i = 0; i < 6; ) {
X        if (STATMIDI) {                 /* Something available? */
X            data[i++] = getmidi();
X        }
X        else if (milliclock() > toolong) {
X            Reason = "Timeout waiting for send request 1 reply.";
X            return 1;
X        }
X    }
X	/* if from file, one more byte of header to read -- gl */
X	if (synthinfileflag) (void)getmidi();
X
X    /* Send secondary request */
X
X    send_request_1B [0] = 0x70 | ((channel - 1) & 0x0F);
X    sendmulti(send_request_1B, sizeof(send_request_1B));
X
X    /* Read tone data and "end-system-exclusive" from synth */
X
X    begin = milliclock();
X    toolong = begin + TIMEOUT*1000;
X    for (i = 0; i < (sizeof(struct ToneData) * 2) + 1; ) {
X        if (STATMIDI) {
X            data[i++] = getmidi();
X        }
X        else if (milliclock() > toolong) {
X            Reason = "Timed out waiting for patch data.";
X            return 1;
X        }
X    }
X
X    /* Pack the 4-bit nybbles into a ToneData structure. */
X
X    ptr = (UBYTE *) tonedata;
X
X    for (i=0; i<sizeof(struct ToneData)*2; i+=2)
X        *(ptr++) = (data[i] | (data[i+1] << 4));
X
X    /* Echo "end-system-exclusive" */
X
X    sendmidi(END_SYSTEM_EXCLUSIVE);
X    return 0;
X}
X
X
X/*******************************
X * Screen Formatting Functions *
X *******************************/
X
Xchar *
Xvisczdet(v)
X{
X    if (v == 0 || v == 1) return (v ? "-" : "+");
X    else return("*");
X}
X
Xchar *
Xvisczflag(v)
X    int v;
X{
X    static char *flags[3] = {" ", "S", "E"};
X
X    if (v >= 0 && v < 3) return flags[v];
X    else return("*");
X}
X
Xchar *
Xvisczline(v)
X    int v;
X{
X    static char *modes[4] = {"1", "2", "1+1'", "1+2'"};
X
X    return modes[v & 3];
X}
X
Xchar *
Xvisczmod(v)
X    int v;
X{
X    static char *modValues[] = { "Off", "Ring", "Noise" };
X
X    if (v > 2) v = 0;
X    if (v >= 0) return modValues[v];
X    else return("*");
X}
X
Xchar *
Xviscznum2(v)
X{
X    static char num[4];
X
X    if (v >= 0 && v < 100) {
X	(void)sprintf(num,"%02d",v);
X	return num;
X    }
X    return("*");
X}
X
X/* not used
Xchar *
Xvisczoct(v)
X    int v;
X{
X    static char *octaves[3] = {"0", "+1", "-1"};
X
X    if (v >= 0 && v < 3) return octaves[v];
X    else return("*");
X}
X*/
X
X/*  FUNCTION
X        getenvelope - get rate, level pairs for one envelope
X
X    SYNOPSIS
X        static void getenvelope(prefix, envelope, endStep)
X                                char    *prefix;
X                                UBYTE   *envelope;
X                                UBYTE   *endStep;
X
X    DESCRIPTION
X        getenvelope() retrieves data values from the P array and stuffs
X        them back into the synthesizer patch record.  The <prefix>
X        argument describes the envelope being retrieved, while the
X        <envelope> argument is a pointer to the envelope data.  <endStep>
X        points to the appropriate end-of-step byte.
X*/
Xstatic void
Xgetenvelope(prefix, envelope, endStep)
X    char    *prefix;
X    UBYTE   *envelope;
X    UBYTE   *endStep;
X{
X    int     prevLevel = 0;
X    UBYTE   sign;
X    int     step, sx;
X    int     flag, level, rate;
X    char    varName[32];
X    UBYTE   velocity;
X
X    for (step = 0, sx = 0; step < 8; ++step, sx += 2) {
X        /* Retrieve RATE value: */
X        (void)sprintf(varName, "%sr%d", prefix, step + 1);
X        rate = getval(varName);
X
X        /* Now, get LEVEL value: */
X        (void)sprintf(varName,"%sl%d", prefix, step+1);
X        level = getval(varName);
X
X        /* Get flag (SUS/END): */
X        (void)sprintf(varName, "%sf%d", prefix, step+1);
X        flag = getval(varName);
X
X        /* The next statement depends upon the velocity parameters
X           being named "vo1", "vw1", "va1", etc. */
X
X        (void)sprintf(varName, "v%s", prefix);
X        velocity = getval(varName);
X
X        /* Convert rate,level to MIDI value: */
X        switch (*prefix) {
X        case 'o':
X            if (rate == 99)
X                rate = 127;
X            else if (rate != 0)
X                rate = (127 * rate) / 99;
X
X            if (level > 63) level += 4;
X            break;
X        case 'w':
X            rate = (119 * rate) / 99 + 8;
X            level = (127 * level) / 99;
X            break;
X        case 'a':
X            rate = (119 * rate) / 99;
X            if (level) level += 28;
X            break;
X        default:
X            rate = 127;
X            level = 0;
X            break;
X        }
X
X        /* For RATE bytes, if the current level is less than the
X           previous level, set the sign bit: */
X        sign = (level < prevLevel ? 0x80 : 0);
X        envelope[sx] = rate | sign;
X
X        /* If this is step 7 and the flag does not indicate the end
X           step, we must force the end step now: */
X
X        if ((step == 7) && flag != 2) {
X            Redraw = 1;
X            flag = 2;
X            (void)sprintf(varName,"%sf8",prefix);
X            setval(varName, (INT16)flag);
X        }
X        if (flag == 2)  {                /* Is this the end step? */
X            level = 0;
X            *endStep = step | (velocity << 4);
X            break;
X        }
X
X        /* For LEVEL bytes, set the sign bit if the current step is
X           a SUSTAIN step: */
X
X        sign = (flag == 1 ? 0x80 : 0);
X        envelope[sx+1] = level | sign;
X        prevLevel = level;
X        if (flag == 2) break;
X    }
X
X}
X
X/*  FUNCTION
X        getwaveforms - stuff waveform info into patch area.
X
X    SYNOPSIS
X        static void getwaveforms(prefix, waveForms)
X                char    *prefix;
X                UBYTE   *waveForms;
X
X    DESCRIPTION
X        getwaveforms() converts the local representation of the
X        waveform data into the CZ1 representation. The <prefix>
X        argument determines if the waveforms to be converted are
X        for DCO1 (prefix = "o1") or DCO2 (prefix = "o2").
X*/
X
Xstatic void
Xgetwaveforms(prefix, waveForms)
X    char *prefix; UBYTE *waveForms;
X{
X    USHORT      modulation;
X    USHORT      second, waveWord, w1, w2;
X    char        varName[32];
X
X    (void)sprintf(varName,"%sw1", prefix);
X    w1 = getval(varName);
X    if (w1) --w1;               /* Do "normalization" */
X    (void)sprintf(varName,"%sw2", prefix);
X    w2 = getval(varName);
X    if (w2) {
X        --w2;
X        second = 0x200;         /* Indicate second waveform present. */
X    }
X    else
X        second = 0;
X
X    modulation = getval("mod");
X    if (modulation == RING)
X        modulation = 0x20;
X    else if (modulation == NOISE)
X        modulation = 0x18;
X
X    /* Save bits 8-6 (resonance?) of the old waveForms word. */
X    waveWord = ((waveForms[0] << 8) | waveForms[1]) & 0x1c0;
X    waveWord |= modulation;
X
X    /* Perform an inclusive OR with the new waveform components. */
X    waveWord |= ((w1<<13) | (w2<<10) | second);
X    waveForms[1] = waveWord;
X    waveForms[0] = waveWord >> 8;
X}
X
X/*  FUNCTION
X        setenvelope - set rate, level pairs for one envelope.
X
X    SYNOPSIS
X        static void setenvelope(prefix, envelope, endStep)
X                                char    *prefix;
X                                UBYTE   *envelope;
X                                UBYTE   endStep;
X
X    DESCRIPTION
X        setenvelope stuffs the P array with the <envelope> values.  It
X        uses the <prefix> string to compute the variable names that
X        are to be set.  Typical values for the <prefix> string are:
X
X            "o1"    - DCO1
X            "w1"    - DCW1
X            "a2"    - DCA2
X
X        Of course, they must match the names used in the P array.
X*/
Xstatic void
Xsetenvelope(prefix, envelope, endStep)
X            char *prefix; UBYTE *envelope; UBYTE endStep;
X{
X    int     step, sx, value;
X    char    varName[32];
X
X    for (step = 0, sx = 0; step < 8; ++step, sx += 2) {
X        (void)sprintf(varName, "%sr%d", prefix, step + 1);
X        value = envelope[sx] & 0x7f;
X        /* Perform rate value conversion, based on envelope name: */
X        switch (*prefix) {
X        case 'o':
X            if (value == 127)
X                value = 99;
X            else if (value != 0)
X                value = (value * 99) / 127 + 1;
X            break;
X        case 'w':
X            value -= 8;         /* Nice stuff! :-( */
X            if (value == 0x77)
X                value = 99;
X            else if (value != 0)
X                value = (value * 99) / 119 + 1;
X            break;
X        case 'a':
X            if (value == 0x77)
X                value = 99;
X            else if (value != 0)
X                value = (99 * value) / 119 + 1;
X            break;
X        default:
X            break;
X        }
X        setval(varName, (INT16)value);
X
X        (void)sprintf(varName, "%sl%d", prefix, step + 1);
X        value = envelope[sx+1] & 0x7f;
X        /* Perform nasty conversion on level value: */
X        switch (*prefix) {
X        case 'o':
X            if (value > 63) value -= 4; /* Sure! Why not? Grrr... */
X            break;
X        case 'w':
X            if (value == 0x7f)
X                value = 99;
X            else if (value != 0)
X                value = (value * 99) / 127 + 1;
X            break;
X        case 'a':
X            if (value) value -= 28;     /* Makes sense to me! Phht! */
X            break;
X        default:
X            break;
X        }
X        setval(varName, (INT16)value);
X
X        /* Set SUS/END flag. */
X        (void)sprintf(varName, "%sf%d", prefix, step+1);
X        if ((endStep & 7) == step)
X            value = 2;
X        else if (envelope[sx+1] & 0x80)
X            value = 1;
X        else
X            value = 0;
X        setval(varName, (INT16)value);
X
X        /* Get VELOCITY parameter. */
X        (void)sprintf(varName, "v%s", prefix);
X        setval( varName, (INT16)endStep >> 4 );
X    }
X}
X
X/*  FUNCTION
X        setwaveforms - extract waveform data from patch area.
X
X    SYNOPSIS
X        static void setwaveforms(prefix, waveForms)
X                        char    *prefix;
X                        UBYTE   *waveForms;
X
X    DESCRIPTION
X        setwaveforms extracts the waveform data from a CZ1 patch
X        and converts it to the on-screen representation.
X
X*/
Xstatic void
Xsetwaveforms(prefix, waveForms)
X    char *prefix; UBYTE *waveForms;
X{
X    char    varName[33];
X    USHORT  waveWord;
X    USHORT  w1, w2;
X
X    waveWord = waveForms[0] << 8 | waveForms[1];
X    w1 = ((waveWord >> 13) & 7) + 1;
X    w2 = ((waveWord >> 10) & 7);
X    if (waveWord & 0x200)           /* Second waveform is present? */
X        w2 += 1;
X    else
X        w2 = 0;
X    (void)sprintf(varName,"%sw1", prefix);
X    setval(varName, (INT16)w1);
X    (void)sprintf(varName,"%sw2", prefix);
X    setval(varName, (INT16)w2);
X}
X
X
X#ifndef AMIGA
X/*  FUNCTION
X        sendmulti - send multiple bytes to midi device
X
X    SYNOPSIS
X        void sendmulti(buffer, count)
X                char    *buffer;
X                int     count;
X
X    DESCRIPTION
X        sendmulti transfers <count> bytes from <buffer> to the currently
X        open midi device.
X
X*/
X
Xvoid
Xsendmulti(buffer, count)
X    UBYTE *buffer; int count;
X{
X	while (count--) sendmidi((int)*buffer++);
X}
X#endif
X
END_OF_FILE
if test 33418 -ne `wc -c <'cz1.mnu'`; then
    echo shar: \"'cz1.mnu'\" unpacked with wrong size!
fi
# end of 'cz1.mnu'
fi
echo shar: End of archive 12 \(of 15\).
cp /dev/null ark12isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 15 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0