#! /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 2 (of 6)."
# Contents:  break.asm cintr.c dxget.c dxput.c transcri.c tuning.c
# Wrapped by lee@uhccux on Wed Mar 29 09:58:08 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'break.asm' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'break.asm'\"
else
echo shar: Extracting \"'break.asm'\" \(7973 characters\)
sed "s/^X//" >'break.asm' <<'END_OF_FILE'
X	title BREAK - handle ctrl-break
X;*****************************************************************************
X;	    Change Log
X;  Date	    | Change
X;-----------+-----------------------------------------------------------------
X; 11-Aug-85 | Created
X;  1-Sep-85 | Rearranged so _clrctl precedes its call (needed in P model)
X; 31-Dec-85 | Made special copy for Adagio support.  Stripped out most stuff
X;	    | and handle DOS ctrl-break exit
X;  1-Jan-86 | Use 1 for control-break and 2 for control-C
X;  1-Jan-86 | Cause return to skip over sub instruction (forcing ignore code
X;	    | acceptance) on PC/AT
X;  2-Jan-86 | take out m: from include m:dos.mac
X;****************************************************************************/
X	include dos.mac
Xdebug=0
X	subttl Documentation
X;*****************************************************************************
X; This code uses the standard Lattice interface.  The logical device 'm:'
X; represents the memory model being used.  Supply your own path to dos.mac
X;
X; This code is intended to allow me to break out of various perverse
X; loops in my application code.	 
X;
X;		      * * * W A R N I N G * * *
X;
X; This code is an extreme *HACK*.  It solves my problem.  It may not solve
X; yours.  I make no guarantees.	 Use at your own risk!
X;
X;			     Restrictions
X;
X; Failure to clear the handler before exiting the program will lead to
X; various bizarre behavior.  Calling the initialization more than once
X; will confuse the world beyond practical recovery.
X;
X;			       Abstract
X;
X; A procedure is called to establish the existence of the control-break 
X; handler (interrupt 1BH).  If a control-break is taken during program
X; the flag _CBREAK is set to true
X;
X; This code is to be linked into the user's application.
X;
X; This code also sets up a handler for the DOS ctrl-brk exit; this is called
X; if DOS sees a C-C character come by.
X; 
X;		       * * * B E W A R E * * *
X;
X; This code is delicate and high-risk.	It works well enough for my one
X; application.	I may have missed all sorts of bizarre DOS or BIOS hacks.
X;
X; It is not guaranteed to be bug-free.	The user assumes all risk in using
X; it.  This is code that should be used only if you understand enough of
X; DOS/BIOS hacking to be sure it will work for you.
X;
X;
X
X	subttl Interface specifications
X;-----------------------------------------------------------------------------
X; extern void _setctl();
X;	
X; Effects: 
X;	Establishes a Ctrl-brk abort handler
X;
X; Limitations:
X;	May only be called once; subsequent calls may damage universe
X; 
X;-----------------------------------------------------------------------------
X; extern void _clrctl();
X;
X; Effects: 
X;	Resets the Ctrl-brk abort handler
X;
X; Limitations:
X;	Should be called only if _setctl() has been called.  However, if
X;	_setctl has not already been called, nothing will happen.
X;
X;*****************************************************************************
X
X	subttl Working storage
Xextrn	_CBREAK:word
X; This storage is in the data segment
X;	public	_CBREAK
X	DSEG
X	even
X;_CBREAK	dw	0
XOLD_BIOS label	DWORD		; we store former 1BH vector here
XOLD_BIP DW	0		; 0, not ?
XOLD_BCS DW	0		; 0, not ?
X
XOLD_DOS label	DWORD		; we store former 23H vector here
XOLD_DIP DW	0
XOLD_DCS dw	0		
X
X	ENDDS
X
X
X	subttl Vector locations
XVECTORS SEGMENT AT 0H
X	ORG	1BH*4		; BIOS ctrl-brk interrupt vector
XCTLBRK	LABEL	DWORD
XCTLBRK_IP DW	?		; IP of BIOS control-break vector
XCTLBRK_CS DW	?		; CS of BIOS control-break vector
X
X	ORG	23H*4		; DOS ctrl-brk interrupt vector
XDOSCBRK LABEL	DWORD
XDOSC_IP	 DW	?
XDOSC_CS	 DW	?
XVECTORS ENDS
X
X
X
X	subttl	Code segment storage 
X;
X; This is in the code segment because I don't know how to make it addressible
X; in the data segment
X;
X	PSEG
X
X
X	subttl	CTLSEEN - CTRL-BREAK handler
X;-----------------------------------------------------------------------------
X;				    ctlseen
X; Inputs:
X;	None; called as interrupt routine via interrupt 1BH
X;
X; Result:
X;	AL=0FFH
X;
X; Effects:
X;	sets _CBREAK to true.  
X;-----------------------------------------------------------------------------
X
XCTLSEEN PROC FAR
X
X
Xif debug
X	int  3
Xendif
X	push	ax
X	push	ds
X	mov	ax,seg _CBREAK
X	mov	ds,ax
X	mov	ds:_CBREAK,1
X	pop	ds
X	pop	ax
X	push	es
X	mov	AX,0F000H	; from the ROM, 
X	mov	ES,AX		; we want pc ID
X	mov	AH,ES:0FFFEH	; The Peter Norton Programmer's Guide to the
X				; IBM PC, page 60
X	cmp	AH,0FCH		;  PC/AT?
X	jnz	no
Xif debug
X	int	3		; WARNING!  If you have this debug trap
X				; enabled, and continue from it, the
X				; ctrl-key-up transition is lost (because
X				; the key went up to talk to the debugger)
X				; this confuses the world; you will have to
X				; hit the control-key once to get the
X				; world resynchronized.
X
Xendif
X; We increment the return address by 2
X;
X;	+-------------------+
X;  SS	|      (ES)	    |  ES:0[BP]
X;	+-------------------+
X;	|      (BP)	    |  ES:2[BP]
X;	+-------------------+
X;	|	IP	    |  ES:4[BP]
X;	+-------------------+
X;	|	CS	    |  ES:6[BP]
X;	+-------------------+
X	mov	AX,SS	
X	mov	ES,AX
X	push	BP
X	mov	BP,SP
X	inc	WORD PTR ES:4[BP]
X	inc	WORD PTR ES:4[BP]
X	pop	BP
Xno:	mov	AX,-1
X			; "ignore" character
X			; PC/XT ref page A-31 lines 2090-2091, page A-33
X			; lines 2217-2219
X			; PC/AT ref page 5-118 loc 2AE..285 indicates this
X			; has no effect for the /AT, which is why we did
X			; the above hack
X	pop	ES
X	iret				;return 
X
XCTLSEEN ENDP
X
XCTLC	PROC	FAR		; Control-C handler
X	push	ax
X	push	ds
X	mov	ax,seg _CBREAK
X	mov	ds,ax
X	mov	ds:_CBREAK,2
X	pop	ds
X	pop	ax
X	iret				;return 
XCTLC	ENDP
X
X	subttl	_clrctl - Clear CTL-BRK vector
X;-----------------------------------------------------------------------------
X; extern void _clrctl();
X;
X; Resets the ctrl-break interrupt vector
X;-----------------------------------------------------------------------------
X	PUBLIC	_clrctl
X	IF	LPROG
X_clrctl PROC FAR
X	ELSE
X_clrctl PROC NEAR
X	ENDIF
X
X; OldES := ES;
X
X	push	ES		; save old ES
X	push	AX		; save old AX
X	push	BX
X
Xif debug
X	int 3
X	mov	AH,62H
X	int	21H		; get program segment prefix
X	mov	PSP,BX		; save it
Xendif
X
X; ES := Segment(&Vectors);
X
X	mov	AX,VECTORS
X	mov	ES,AX		
X	ASSUME ES:VECTORS
X
X; Disable_Interrupts();
X
X	CLI			; turn off interrupts
X
X; if(OLD_BIOS == 0) goto NoVectorStored
X
X	mov	AX,WORD PTR OLD_BIOS
X	cmp	AX,0		; is it zero?
X	je	NoBIOSStored
X
X; CTLBRK.IP := OLD_BIOS.IP
X
X	mov	WORD PTR CTLBRK,AX
X
X; CTLBRK.CS := OLD_BIOS.CS
X
X	mov	AX,WORD PTR OLD_BIOS[2]
X	mov	WORD PTR CTLBRK[2],AX
X
XNoBIOSStored:
X
X	mov	AX,WORD PTR OLD_DOS
X	cmp	AX,0		; initialized?
X	je	NoDOSStored	; no, no dos vector
X
X; DOSCBRK.IP = OLD_DOS.IP
X
X	mov	WORD PTR DOSCBRK,AX
X
X; DOSCBRK.CS := OLD_DOS.CS
X
X	mov	AX,WORD PTR OLD_DOS[2]
X	mov	WORD PTR DOSCBRK[2],AX
X
XNoDOSStored:
X
X; Enable_interrupts();
X
X	STI		; allow interrupts
X
X; ES := OldES;
X
X	pop	BX
X	pop	AX
X	pop	ES	
X
X	ret		; return to caller
X
XPSP:	DW	?
X_clrctl	ENDP
X
X	subttl	_setctl - Set CTL-BRK vector
X;-----------------------------------------------------------------------------
X; extern void _setctl()
X;-----------------------------------------------------------------------------
X
X	PUBLIC	_setctl
X	IF LPROG
X_setctl	PROC	FAR
X	ELSE
X_setctl	PROC NEAR			; set CTL-BRK interrupt
X	ENDIF
X	push	BP			; C prolog
X	mov	BP,SP			; ...
X
Xif debug
X	int	3
Xendif
X
X	ASSUME ES:VECTORS
X
X; OldES := ES;
X
X	push	ES		; save old ES
X	push	AX		; save old AX
X
X; ES := Segment(&Vectors);
X
X	mov	AX,VECTORS
X	mov	ES,AX		
X
X; Disable_Interrupts();
X
X	CLI			; turn off interrupts
X
X; OLD_BIOS.IP := CTLBRK.IP
X
X	mov	AX,WORD PTR CTLBRK
X	mov	WORD PTR OLD_BIOS,AX
X
X; OLD_BIOS.CS := CTLBRK.CS
X
X	mov	AX,WORD PTR CTLBRK[2]
X	mov	WORD PTR OLD_BIOS[2],AX
X
X; CTLBRK := &CTLSEEN
X
X	mov	CTLBRK_IP,OFFSET CTLSEEN
X	mov	CTLBRK_CS,CS
X
X; OLD_DOS.IP := DOSCBRK.IP
X
X	mov	AX,WORD PTR DOSCBRK
X	mov	WORD PTR OLD_DOS,AX
X
X; OLD_DOS.CS := DOSCBRK.CS
X
X	mov	AX,WORD PTR DOSCBRK[2]
X	mov	WORD PTR OLD_DOS[2],AX
X
X; DOSCBRK := &CTLC
X
X	mov	DOSC_IP,OFFSET CTLC
X	mov	DOSC_CS,CS
X
X; Enable_interrupts();
X
X	STI		; allow interrupts
X
X; ES := OldES;
X
X	pop	AX
X	pop	ES	
X
X; return;
X	pop	BP	; C epilog
X	ret		; return to caller
X
X_setctl	ENDP
X
X	ENDPS
X	END
END_OF_FILE
if test 7973 -ne `wc -c <'break.asm'`; then
    echo shar: \"'break.asm'\" unpacked with wrong size!
fi
# end of 'break.asm'
fi
if test -f 'cintr.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'cintr.c'\"
else
echo shar: Extracting \"'cintr.c'\" \(9579 characters\)
sed "s/^X//" >'cintr.c' <<'END_OF_FILE'
X/* cintr.c -- code for interrupt management */
X
X/*****************************************************************************
X*	    Change Log
X*  Date	    | Change
X*-----------+-----------------------------------------------------------------
X* 31-Dec-85 | Created changelog
X* 31-Dec-85 | Add c:\ to include directives
X* 31-Dec-85 | Save actual interrupt vector data; don't use constants
X*	    | (different on PC/AT and PC/XT)
X* 31-Dec-85 | Added intr_init
X* 31-Dec-85 | Handle secondary interrupt port for AT
X* 26-May-86 | Use cmdline.c to get debug switch
X*  6-Aug-86 | Modified for Lattice 3.0 -- use "void" to type some routines
X*****************************************************************************/
X/*
X *	I think this came from Dale Amon, but we had some problems
X *	getting it to work with Lattice C and hacked away to get
X *	something to do the job.  
X */
X
X#include "stdio.h"
X#include "dos.h"
X/* note: dos.h typedefs byte to unsigned char */
X/*  cext.h #defines byte to unsigned char     */
X#include "cext.h"
X#include "cmdline.h"
X#include "cintr.h"
X#include "atxt.h"
X
X/*
X * IBM-XT and IBM-AT interrupt information
X */
X
X#define NIRQS 16		/* Maximum number of IRQ levels */
X
Xshort defpc[NIRQS];		/* restore the vector to this PC */
Xshort defseg[NIRQS];		/* and this segment */
X
X#define VECTOR(irq)		(0x20 + 4 * (irq))
X					/* Maps interrupt request number
X					   to the address of the vector */
X
X/*   CAUTION!	 CAUTION!   CAUTION!   CAUTION!	  CAUTION!   CAUTION!	
X     The above "vector" computation DOES NOT WORK for a PC/AT for
X     values higher than 7.  IRQ8..15 are vectored starting at 70.
X     The proper AT computation, should higher IRQ values be required,
X     is 
X
X	(0x20 + ((irq) < 8 ? 0x20 + 4*(irq) : 0x70 + 4 * ((irq) - 8)))
X
X     but that is much too complicated to want to do in the restricted
X     case of having only an IRQ2 device.  But you have now been warned.
X
X     Note also that devices which on the PC or XT interrupt on IRQ2 will
X     interrupt on the AT at IRQ9, but the software in the BIOS redirects
X     this interrupt (PC/AT Tech Ref page 5-71) via the IRQ2 vector.
X     
X				*** HOWEVER ***
X
X     If the program masks off interrupts by twiddling the mask bit for IRQ2
X     it will also mask off the realtime clock interrupt, coprocessor
X     interrupt, and *FIXED DISK INTERRUPT*.  Therefore, any attempt to
X     manipulate the interrupt masks must be done to the secondary 8259
X     controller channel chip, located at locations 0xA0 and 0xA1.
X
X     Mask bits in primary mask register:
X
X     Bit	XT*			AT**
X	7	Printer			Parallel Port 1
X	6	Diskette		Diskette controller
X	5	Fixed Disk		Parallel Port 2
X	4	Serial Port 1		Serial Port 1
X	3	Serial Port 2		Serial Port 2
X	2	IRQ2			IRQ2 (OR of IRQ8..IRQ15)
X	1	Keyboard		Keyboard
X	0	Timer			Timer
X
X     Mask bits in secondary mask register (AT only)
X
X	7				IRQ15
X	6				Fixed disk controller
X	5				Coprocessor
X	4				IRQ12
X	3				IRQ11
X	2				IRQ10
X	1				IRQ9 (Bus IRQ2)
X	0				Realtime clock
X
X     Source:
X
X     * PC/XT Technical Ref page 1-9
X     ** PC/AT Technical Ref page 1-11
X
X*/
X
X#define INT_0_CONTROL_PORT	0x20	/* Interrupt chip I/0 port (PC, XT)*/
X#define INT_1_CONTROL_PORT	0x21	/*     "      "	   "	"      "   */
X#define INT2_0_CONTROL_PORT	0xA0	/* Interrupt chip 2 I/O port (AT)  */
X#define INT2_1_CONTROL_PORT	0xA1	/*     "      "	   "	"      "   */
X
X#define EOI(irq)		(0x60 | (irq))
X					/* End of interrupt command to
X					   send to PORT1 */
X
X#define ndsw 2
Xprivate char *dsw[ndsw] = { "-d", "-debug" };
X
Xint enabled;	/* flag to tell if interrupts are on */
Xint debug_intr; /* set for debugging */
Xint IsAT;	/* AT or XT?, initialized here, read-only to others */
X
X/****************************************************************************
X*	Routines local to this module
X****************************************************************************/
Xprivate	void	print_intr();
X
X/****************************************************************************
X*				   intr_init
X* Effect: 
X*	Initializes the interrupt routines
X****************************************************************************/
X
Xvoid intr_init()
X{
X    int i;
X    debug_intr = (cl_nswitch(dsw, ndsw) != NULL);
X    IsAT = (ATXT() == ISAT);
X    if (debug_intr) printf("IsAT is %d\n", IsAT);
X    for (i = 0; i < NIRQS; i++) defpc[i] = defseg[i] = 0;
X}
X
X/****************************************************************************
X*				  intr_enable
X* Inputs:
X*	int irq: Interrupt level to enable 
X* Effect: 
X*	Enables the interrupt in the control port, sets enabled flag true
X****************************************************************************/
X
Xvoid intr_enable(irq)
X    int irq;
X{
X    int pv;
X
X    if (IsAT && irq == 2) { /* AT on irq2 */
X	pv = inp(INT2_1_CONTROL_PORT);
X	if (debug_intr)
X	    printf("intr_enable/AT: (before) %02x = %02x\n",
X		   INT2_1_CONTROL_PORT, pv);
X	pv &= ~(1<<1);
X	outp(INT2_1_CONTROL_PORT, pv);
X	if (debug_intr) { /* report */
X	    pv = inp(INT2_1_CONTROL_PORT);
X	    printf("intr_enable/AT: (after) %02x = %02x\n",
X		   INT2_1_CONTROL_PORT, pv);
X	} /* report */
X    } /* AT on irq2 */ else { /* PC or XT or AT not IRQ2 */
X	pv = inp(INT_1_CONTROL_PORT);
X	pv &= ~(1<<irq);
X	outp(INT_1_CONTROL_PORT, pv);
X    } /* PC or XT or AT not IRQ2 */
X    enabled = true;
X}
X
X/****************************************************************************
X*				 intr_disable
X* Inputs:
X*	int irq: irq level to disable
X* Effect: 
X*	Disables the interrupt in the control registers, sets enabled false
X****************************************************************************/
X
Xvoid intr_disable(irq)
X    int irq;
X{
X    int pv;
X
X    if(IsAT && irq == 2)
X       { /* AT	*/
X	 /* On the AT, we mask the interrupt in the secondary register */
X	 pv = inp(INT2_1_CONTROL_PORT);
X	 if(debug_intr)
X	     printf("intr_disable/AT: (before) %02x = %02x\n",INT2_1_CONTROL_PORT,pv);
X	 pv |= (1<<1);
X	 outp(INT2_1_CONTROL_PORT,pv);
X       } /* AT	*/
X    else
X       { /* PC or XT */
X	pv = inp(INT_1_CONTROL_PORT);
X	pv |= (1<<irq);
X	outp(INT_1_CONTROL_PORT,  pv);
X	if(debug_intr)
X	   { /* report */
X	    pv = inp(INT2_1_CONTROL_PORT);
X	    printf("intr_enable/XTAT: (after) %02x = %02x\n",INT2_1_CONTROL_PORT,pv);
X	   } /* report */
X       } /* PC or XT */
X    enabled = 0;
X}
X
X/****************************************************************************
X*				 intr_routine
X* Inputs:
X*	int irq: interrupt level
X* Effect: 
X*	Set up vector and aintr (assembler code) globals so that
X*	the function a_intr is called when an interrupt occurs
X* Notes:
X*	Possible bug: The segment numbers (esp. ds) may not be correct and 
X*	probably should be passed as arguments
X****************************************************************************/
X
Xint a_irq, a_intr(), a_dsreg;
X
Xvoid intr_routine(irq)
X    int irq;
X{
X    struct SREGS s;
X
X    segread(&s);
X    a_irq = irq;
X    intr_set_vector(irq, s.cs, a_intr, 1);
X    a_dsreg = s.ds;
X    if (debug_intr) printf("cs = %x\tds = %x\n", s.cs,  s.ds);
X}
X
X/****************************************************************************
X*				 intr_cleanup
X* Inputs:
X*	int irq: irq level to restore interrupt for
X* Effect: 
X*	Restores the interrupt vector for the irq
X****************************************************************************/
X
Xvoid intr_cleanup(irq)
X    int irq;
X{
X    if (defseg[irq] != 0)
X	intr_set_vector(irq, defseg[irq], defpc[irq],0);
X    if (debug_intr)
X	print_intr("After cleanup",irq);
X}
X
X/****************************************************************************
X*				   intr_eoi
X* Inputs:
X*	int irq: interrupt level to do this to
X* Effect: 
X*	Sends end of interrupt command to the port for the indicated
X*	interrupt level
X*
X*	On the AT, the IRQ2 interrupt really came in on vector 71, but
X*	EOI has been sent to the secondary I/O port and the interrupt has
X*	been revectored to 0A.	See BIOS listing for the AT page 5-71.
X****************************************************************************/
X
Xvoid intr_eoi(irq)
X    int irq;
X{
X    outp(INT_0_CONTROL_PORT, EOI(irq));
X}
X
X/****************************************************************************
X*				intr_set_vector
X* Inputs:
X*	int irq: interrupt vector level to set
X*	short seg: segment value to store in interrupt level
X*	short pc:  pc value to store in interrupt level
X*	boolean save: true to save the old value, false to just overwrite
X*			it
X* Effect: 
X*	Sets the interrupt vector cs:ip to the indicated values
X****************************************************************************/
X
Xvoid intr_set_vector(irq, seg, pc, save)
X    int irq;
X    short seg;
X    short pc;
X    int save;
X{
X    short s[2];
X    short o[2];
X
X    s[0] = pc;
X    s[1] = seg;
X    if (debug_intr)
X	print_intr("Before poking new vector",irq);	
X    peek(0, VECTOR(irq), (char *) o, sizeof(o));
X    poke(0, VECTOR(irq), (char *) s, sizeof(s));
X    if (save) { /* save vector */
X	defseg[irq] = o[1];
X	defpc[irq] = o[0];
X    } /* save vector */
X    if (debug_intr) print_intr("After poking new vector",irq);	
X}
X
X/****************************************************************************
X*				  print_intr
X* Inputs:
X*	char * msg: Identifying message
X*	int irq: Interrupt to print
X* Effect: 
X*	Prints the contents of the interrupt vector
X****************************************************************************/
X
Xprivate void print_intr(msg,irq)
X    char * msg;
X    int irq;
X{
X    short s[2];
X
X    peek(0, VECTOR(irq), (char *) s, sizeof(s));
X    printf(
X	"%s: vector %d, address %x, pc = %x, seg = %x, defpc=%x, defseg=%x\n",
X	msg, irq, VECTOR(irq), s[0], s[1],defpc[irq],defseg[irq]);
X}
END_OF_FILE
if test 9579 -ne `wc -c <'cintr.c'`; then
    echo shar: \"'cintr.c'\" unpacked with wrong size!
fi
# end of 'cintr.c'
fi
if test -f 'dxget.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'dxget.c'\"
else
echo shar: Extracting \"'dxget.c'\" \(6563 characters\)
sed "s/^X//" >'dxget.c' <<'END_OF_FILE'
X/* dxget.c -- program to get Yamaha exclusive messages and write to file */
X
X/*****************************************************************************
X*	    Change Log
X*  Date	    | Change
X*-----------+-----------------------------------------------------------------
X* 13-Jun-86 | Created Change Log
X*****************************************************************************/
X
X#include "cext.h"
X#include "stdio.h"
X#include "mpu.h"
X#include "midicode.h"
X#include "userio.h"
X#include "cmdline.h"
X
X#define buffsize 17000
Xbyte midibuff[buffsize];
X
Xextern int xbufftai;
Xextern int xbuffmask;
Xextern byte *xbuff;
Xextern byte *buff;
X
Xint xflag;	/* for debugging */
X
Xint debptr;
X
X/****************************************************************************
X* Data for command line parsing
X****************************************************************************/
X#define nswitches 8
Xprivate char *switches[nswitches] = 
X    { "-help", "-miditrace", "-m", "-trace", "-t", "-block", "-d", "-debug" };
X
X#define noptions 1
Xprivate char *options[noptions] = { "-tune" };
X
X/*****************************************************************************
X*	Routines local to this module
X*****************************************************************************/
Xprivate void instruct();
Xprivate boolean output();
X
X/****************************************************************************
X*				instruct
X* Effect: prints instructions for this routine
X****************************************************************************/
X
Xprivate void instruct()
X{
Xprintf("This program will let you save DX7 and TX816 voice programs.\n");
Xprintf("To save DX7 programs, you must connect\n");
Xprintf("	DX7 MIDI OUT to MPU 401 MIDI IN.\n");
Xprintf("For TX816 programs, connect TX816 MIDI OUT to MPU 401 MIDI IN,\n");
Xprintf("	and set the OUT SLOT (leftmost display) to the module\n");
Xprintf("	from which you want data.\n");
Xprintf("For DX7: push the orange FUNCTION key, then the green 8.  Push 8\n");
Xprintf("	repeatedly until the display says SYS INFO AVAIL or\n");
Xprintf("	SYS INFO UNAVAIL.  If the display says SYS INFO UNAVAIL,\n");
Xprintf("	push YES to change the display to SYS INFO AVAIL.\n");
Xprintf("	Now, select a voice with the INTERNAL or CARTRIDGE button\n");
Xprintf("	followed by a (green) number.\n");
Xprintf("For ALL DX7 voices: after getting the SYS INFO AVAIL display,\n");
Xprintf("	push 8 again to get MIDI TRANSMIT ?.  Push YES.\n");
Xprintf("For TX816: Hold down SELECT until you see UT in the display.\n");
Xprintf("	Let up on SELECT and then push it once more to get the\n");
Xprintf("	flashing dU.  Push YES to dump all data from this module.\n");
Xprintf("	Hold down SELECT until you see digits in the display.\n");
Xprintf("After data is dumped, dxget will tell you what it got and write\n");
Xprintf("	data to a file.	 Use dxput to copy a file to a dx module.\n");
X}
X
X/****************************************************************************
X*				main
X* Effect: main program -- prompt user for information and get data
X****************************************************************************/
Xvoid main(argc, argv)
X    int argc;
X    char *argv[];
X{
X    FILE *fp;		/* the output file */
X    int done = false;	/* flag is true when user is done */
X    byte *msg;		/* message pointer */
X    char filename[100];	/* the output file name */
X    char *s;		/* the file name in the command line */
X
X    cl_init(switches, nswitches, options, noptions, argv, argc);
X    if (cl_switch("-help")) instruct();
X    /* get input file name: */
X	filename[0] = 0;	/* empty string */
X	if ((s = cl_arg(1)) != NULL) strcpy(filename, s);
X
X    while (!done) {
X	if (askbool("Do you want instructions", true)) instruct();
X	
X	fp = fileopen(filename, "dx7", "w", "file name");
X
X	musicinit();
X	if (!midi_buffer(midibuff, buffsize)) printf("midi_buffer error\n");
X	while (getkey(false) != -1) ;
X	exclusive(true);	/* tell mpu401 to send exclusive data */
X
X	printf("\nReady for your data. Type space when you are done...\n");
X
X	done = false;
X	while (!done) {
X	    if (kbhit()) done = (getch() == ' ');
X	    mpu_error_check();	/* look for buffer overflow */
X	}
X
X	musicterm();
X
X	msg = midibuff;
X	if (xbufftai == 0) printf("No data!  Please start again.\n");
X	else while (output(fp, &msg, midibuff + xbufftai))
X	     /* write messages */;
X	fclose(fp);
X	printf("DONE\n");
X
X	done = !askbool("Do you want to send another file", false);
X	filename[0] = 0;	/* force prompt for new file name */
X    }
X}
X
X/****************************************************************************
X*				output
X* Inputs:
X*	FILE *fp: the file to write
X*	byte **msg: pointer to the message to write
X*	byte *msg_tail: points to byte after last byte of recorded data
X* Outputs:
X**	byte **msg: is advanced to byte after the last byte of the message
X*	returns true if there is more data to output
X* Effect: 
X*	write data file using recorded data
X* Assumes:
X*	fp is opened for writing
X*	msg_tail > *msg
X****************************************************************************/
X
Xprivate boolean output(fp, msg, msg_tail)
X    FILE *fp;
X    byte **msg;
X    byte *msg_tail;
X{
X    byte *this_msg = *msg;	/* local message pointer */
X    int datalen;		/* number of bytes in message */
X    int cksum;			/* check sum of message */
X    int n;			/* counts bytes printed on one line */
X
X/*	printf("*msg %x, this_msg %x, msg_tail %x\n",
X *		*msg, this_msg, msg_tail);
X *	printf("%d bytes to go.\n", msg_tail - this_msg);
X */
X    excldesc(this_msg);
X/*	for (i = *base; i < how_many; i+=4) {
X *	    if (kbhit() && (getch() == ' ')) break;
X *	    printf("%d: %x %x %x %x\n",
X *		i, 
X *		midibuff[i],
X *		midibuff[i+1],
X *		midibuff[i+2],
X *		midibuff[i+3]);
X *	}
X */
X	this_msg = *msg;
X/*	printf("parity check\n");*/
X    datalen = (this_msg[4] << 7) + this_msg[5];
X/*	printf("datalen %x\n", datalen);*/
X    cksum = 0;
X    for (n = 6; n < datalen+6; n++) {
X	cksum = (cksum + this_msg[n]) & 0x7f;
X    }
X/*	printf("computed check sum %x, actual check sum %x\n",
X		cksum, midibuff[datalen+6]);*/
X    if ((cksum + this_msg[datalen+6]) & 0x7f != 0) {
X	fprintf(stderr, "Data has been garbled -- please start over.\n");
X	return false;
X    }
X    n = 0;
X    do {	/* always print first byte, */
X		/* then terminate after printing MIDI_EOX */
X	fprintf(fp, "%x ", *this_msg);
X	if (n >= 15) {		/* print 16 bytes per line */
X	    n = 0;
X	    fprintf(fp, "\n");
X	} else n++;
X	this_msg++;
X    } while (this_msg < msg_tail && *(this_msg-1) != MIDI_EOX) ;
X    fprintf(fp, "\n\n");
X    *msg = this_msg;
X    return this_msg < msg_tail;
X}
END_OF_FILE
if test 6563 -ne `wc -c <'dxget.c'`; then
    echo shar: \"'dxget.c'\" unpacked with wrong size!
fi
# end of 'dxget.c'
fi
if test -f 'dxput.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'dxput.c'\"
else
echo shar: Extracting \"'dxput.c'\" \(7309 characters\)
sed "s/^X//" >'dxput.c' <<'END_OF_FILE'
X/* dxput.c -- program to send Yamaha exclusive messages from file */
X
X/*****************************************************************************
X*	    Change Log
X*  Date	    | Change
X*-----------+-----------------------------------------------------------------
X* 13-Jun-86 | Created Change Log
X*  6-Aug-86 | Adapted to Lattice C V3.00
X*****************************************************************************/
X
X#include "cext.h"
X#include "stdio.h"
X#include "midicode.h"
X#include "mpu.h"
X#include "userio.h"
X#include "cmdline.h"
X
X#define buffsize 17000
Xbyte midibuff[buffsize];
X
Xextern int miditrace;
X
Xint xflag;	/* for debugging */
X
Xint debptr;
X
X/****************************************************************************
X* Data for command line parsing
X****************************************************************************/
X#define nswitches 8
Xprivate char *switches[nswitches] = 
X    { "-help", "-miditrace", "-m", "-trace", "-t", "-block", "-d", "-debug" };
X
X#define noptions 1
Xprivate char *options[noptions] = { "-tune" };
X
X/*****************************************************************************
X*	Routines local to this module
X*****************************************************************************/
Xprivate void	instruct();
Xprivate boolean isdangerous();
Xprivate boolean output();
Xprivate	boolean	readbuff();
X
X/****************************************************************************
X*				instruct
X* Effect: prints instructions for this routine
X****************************************************************************/
X
Xprivate void instruct()
X{
Xprintf("This program will let you send voice programs to a DX7 or TX816.\n");
Xprintf("You must send a file previously created by the dxget program.\n");
Xprintf("To send DX7 programs, you must connect\n");
Xprintf("	MPU 401 MIDI OUT to DX7 MIDI IN.\n");
Xprintf("For TX816 programs, connect MPU 401 MIDI OUT to TX816 MIDI IN.\n");
Xprintf("For a DX7 voice: push the orange FUNCTION key, then the green 8.\n");
Xprintf("	Push 8 repeatedly until the display says SYS INFO AVAIL\n");
Xprintf("	or SYS INFO UNAVAIL.  If the display says SYS INFO\n");
Xprintf("	UNAVAIL, push YES to change to SYS INFO AVAIL.\n");
Xprintf("	Next, push MEMORY PROTECT/INTERNAL, then NO, and then\n");
Xprintf("	then MEMORY SELECT/INTERNAL. Now, type the name of a file\n");
Xprintf("	created by dxget and then the space bar to send data.\n");
Xprintf("	To store the voice program on the DX7, hold down STORE\n");
Xprintf("	while you push a (green) number.  The current voice at\n");
Xprintf("	this number will be erased and replaced by the new voice.\n");
Xprintf("For ALL DX7 voices: Same as for a single DX7 voice, but all 32\n");
Xprintf("	voice programs on the DX7 will be replaced whey you type\n");
Xprintf("	Y in response to `Are you sure?' on the computer.\n");
Xprintf("For all TX816 voices: To store into one module, push NO until the\n");
Xprintf("	MEMORY PROTECT light goes out.	Make sure other MEMORY\n");
Xprintf("	PROTECT lights are ON.	Type Y in response to 'Are you\n");
Xprintf("	sure?' on the computer.\n");
X}
X
X/****************************************************************************
X*				isdangerous
X* Inputs:
X*	byte *msg: pointer message to check
X* Outputs:
X*	returns true if message can destroy lots of info (block data message)
X****************************************************************************/
X
Xprivate boolean isdangerous(msg)
Xbyte *msg;
X{
X    /* look for 32 voice and 64 performance data msgs */
X    return (msg[1] == 0x43 && (msg[3] == 2 || msg[3] == 9));
X}
X
X/****************************************************************************
X*				main
X* Effect: main program -- prompt user for information and put data
X****************************************************************************/
X
Xvoid main(argc, argv)
X    int argc;
X    char *argv[];
X{
X    FILE *fp;		/* the input file */
X    int count;		/* length of data in file */
X    byte *msg;		/* message pointer */
X    int done = false;	/* flag is true when user is done */
X    char filename[100];	/* the output file name */
X    char *s;		/* the file name in the command line */
X
X    cl_init(switches, nswitches, options, noptions, argv, argc);
X    if (cl_switch("-help")) instruct();
X    /* get input file name: */
X	filename[0] = 0;	/* empty string */
X	if ((s = cl_arg(1)) != NULL) strcpy(filename, s);
X
X
X    while (!done) {
X	if (askbool("Do you want instructions", true)) instruct();
X
X	fp = fileopen(filename, "dx7", "r", "file name");
X
X	if (!readbuff(fp, midibuff, &count)) {
X	    printf("Something is wrong with your data or you typed the\n");
X	    printf("wrong file name.  Please try again.\n");
X	    exit(1);
X	}
X
X	printf("\nReady with your data. Type space when you are ready...\n");
X	while (true) {
X	    if (kbhit() && getch() == ' ') break;
X	}
X	musicinit();
X	exclusive(true);
X	msg = midibuff;
X	while (output(&msg, midibuff + count))
X	     /* write messages */;
X	musicterm();
X	fclose(fp);
X	printf("DONE\n");
X
X	done = !askbool("Do you want to send another file", false);
X	filename[0] = 0;	/* force prompt for new file name */
X    }	
X}
X
X/****************************************************************************
X*				output
X* Inputs:
X*	byte **msg: pointer to message to send
X*	byte *msg_tail: pointer to byte after last message byte
X* Outputs:
X*	*msg is set to byte after last byte of the message sent
X*	returns true if there is more data to send
X* Effect: sends exclusive messages using recorded data
X* Assumes: msg_tail > *msg
X* Implementation:
X****************************************************************************/
X
Xprivate boolean output(msg, msg_tail)
X    byte **msg;
X    byte *msg_tail;
X{
X    byte *this_msg = *msg;
X    int datalen;
X    int cksum;
X    int n;		/* counts bytes printed on one line */
X    int OK;		/* OK to send message */
X/*	printf("*msg %x, this_msg %x, msg_tail %x\n",
X		*msg, this_msg, msg_tail);
X	printf("%d bytes to go.\n", msg_tail - this_msg);
X*/
X    excldesc(this_msg);
X    this_msg = *msg;
X    datalen = (this_msg[4] << 7) + this_msg[5];
X/*	printf("datalen %x\n", datalen);*/
X    cksum = 0;
X    for (n = 6; n < datalen+6; n++) {
X	cksum = (cksum + this_msg[n]) & 0x7f;
X    }
X    if (datalen == 0 || (cksum + this_msg[datalen+6]) & 0x7f != 0) {
X	printf("Data in your file is garbled.\n");
X	return false;
X    }
X    if (isdangerous(this_msg)) {
X	OK = askbool("Are you sure", false);
X    } else OK = true;
X    if (OK) midi_exclusive(this_msg);
X
X    do {	/* always skip first byte, */
X		/* then terminate after finding MIDI_EOX */
X	this_msg++;
X    } while (this_msg < msg_tail && *(this_msg-1) != MIDI_EOX) ;
X    *msg = this_msg;
X    return this_msg < msg_tail;
X}
X
X/****************************************************************************
X*				readbuff
X* Inputs:
X*	FILE *fp: file from which to read
X* Outputs:
X*	byte *buff: where to put the data
X*	int *count: count is set to the number of of bytes read
X* Effect: 
X*	read midi exclusive data from a file into buff
X* Assumes:
X*	fp is open for reading
X****************************************************************************/
X
Xprivate boolean readbuff(fp, buff, count)
X    FILE *fp;
X    byte *buff;
X    int *count; /* result */
X{
X    int i;
X    *count = 0;
X    while (fscanf(fp, "%x", &i) > 0) {
X	*buff = i;
X	buff++;
X	(*count)++;
X    }
X    return *count != 0;
X}
END_OF_FILE
if test 7309 -ne `wc -c <'dxput.c'`; then
    echo shar: \"'dxput.c'\" unpacked with wrong size!
fi
# end of 'dxput.c'
fi
if test -f 'transcri.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'transcri.c'\"
else
echo shar: Extracting \"'transcri.c'\" \(4900 characters\)
sed "s/^X//" >'transcri.c' <<'END_OF_FILE'
X/* transcribe.c -- keyboard to adagio recorder */
X
X/*****************************************************************************
X*	    Change Log
X*  Date	    | Change
X*-----------+-----------------------------------------------------------------
X* 23-Feb-86 | Created changelog
X*	    | Use pedal information when computing durations
X*  5-May-86 | Changed data structure for speed
X* 21-May-86 | Use record.c to implement record functions
X* 26-May-86 | Incorporate cmdline.c
X*  6-Aug-86 | Adapted to Lattice V3.00
X*****************************************************************************/
X
X#include "cext.h"
X#include "stdio.h"
X#include "cmdline.h"
X#include "mpu.h"
X#include "userio.h"
X#include "record.h"
X
X#define STOP_CC 1
X#define STOP_CBRK 2
X#define STOP_KEY 3
X#define STOP_SPACE 4
X
X#define num_voices 16
X
X#define stop_code ' '
Xchar stop_explanation[] = "Space bar";
X
Xextern int musictrace;
Xextern int miditrace;
Xextern int CBREAK;
Xextern int debug_intr;
Xextern int debug_rec;
Xboolean poll = false;		/* true if poll, false if interrupt */
X
X#define nswitches 8
Xchar *switches[nswitches] =
X    { "-debug", "-d", "-help", "-miditrace", "-m", "-trace", "-t", "-block" };
X
X#define noptions 3
Xchar *options[noptions] = { "-c", "-control", "-tune" };
X
X/****************************************************************************
X*	Routines local to this module
X****************************************************************************/
Xprivate	void	cmdline_help();
Xprivate boolean stop_check();
X
X/****************************************************************************
X*				 cmdline_help
X* Effect: 
X*	Prints out command line help
X****************************************************************************/
X
Xprivate void cmdline_help()
X{
X    fprintf(stderr,"transcri [options] filename [options]\n");
X    fprintf(stderr,"	 Options are below.\n");
X    fprintf(stderr,"	   -block	     disable MIDI thru\n");
X    fprintf(stderr,"	   -control (-c) on  record control info\n");
X    fprintf(stderr,"	   -control (-c) off do not record control info\n");
X    fprintf(stderr,"	   -debug (-d)	     enable verbose debug mode\n");
X    fprintf(stderr,"	   -help	     this message\n");
X    fprintf(stderr,"	   -miditrace (-m)   turn on MIDI command trace\n");
X    fprintf(stderr,"	   -trace (-t)	     trace music\n");
X}
X
X/****************************************************************
X*			main
X* Effect:
X*	transcribe from keyboard
X****************************************************************/
X
Xvoid main(argc,argv)
X   int argc;
X   char *argv[];
X{
X    long time;			/* current time */
X    boolean done = false;	/* set when recording is finished */
X    int stop_reason;		/* reason recording is finished */
X    char score_na[100];		/* score name */
X    int i;			/* used to scan command line */
X    char *strptr;		/* string pointer used to get file name */
X    int ctrlflag;		/* record control info? */
X
X    score_na[0] = 0;		/* null string */
X
X    cl_init(switches, nswitches, options, noptions, argv, argc);
X
X    if (cl_switch("-help")) {
X	cmdline_help(); 
X	return;
X    }
X
X    if ((strptr = cl_arg(1)) != NULL)
X	strcpy(score_na, strptr);
X
X    if ((strptr = cl_noption(options, noptions)) != NULL) {
X	ctrlflag = (strcmp(strptr, "on") == 0);
X    } else {
X	ctrlflag = askbool("Pitch bend, etc. on", false);
X    }
X    musicinit();
X
X    /* reset all channels to MIDI program 1: */
X    for (i = 0; i < num_voices; i++) {
X	midi_program(i, 1);
X    }
X
X    if (!rec_init(score_na, ctrlflag)) {
X	printf("No space for recording, use a smaller adagio file.\n");
X	musicterm();
X	exit(1);
X    }
X
X    printf("Transcribe ready.  Type space bar to stop.\n");
X
X    timereset();
X    while (!done) {
X	time = gettime()/* delay everything by offset */;
X	if (rec_poll(time)) {	/* record anything that's there */
X	    done = true;
X	    stop_reason = STOP_SPACE;
X	}
X	if (CBREAK || kbhit()) {
X	    done |= stop_check(&stop_reason);
X	}
X	mpu_error_check();	/* look for buffer overflow */
X    }
X    rec_final(false);	/* write out recorded data, */
X			/* suppress time of first event*/
X    musicterm();
X}
X
X/****************************************************************************
X*				     stop_check
X* Outputs:
X*	*reason is set to reason for stop
X*	true is returned iff play should stop
X* Effect: 
X*	Checks for break character or stop code from kbd
X****************************************************************************/
X
Xprivate boolean stop_check(reason)
X    int *reason;
X{
X    boolean done = false;
X    switch(CBREAK) { /* stop reason */
X	case 0: /* no stop code, try keyboard */
X	    done = (getch() == stop_code);
X	    if (done) *reason = STOP_KEY;
X	    break;
X	case 1: /* ctrl-break */
X	    done = true;
X	    if (kbhit()) getch();
X	    *reason = STOP_CBRK;
X	    break;
X	case 2: /* ctrl-C */
X	    done = true;
X	    *reason = STOP_CC;
X	    if (kbhit()) getch();
X	    break;
X    } /* stop reason */
X    return done;
X}
END_OF_FILE
if test 4900 -ne `wc -c <'transcri.c'`; then
    echo shar: \"'transcri.c'\" unpacked with wrong size!
fi
# end of 'transcri.c'
fi
if test -f 'tuning.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'tuning.c'\"
else
echo shar: Extracting \"'tuning.c'\" \(9694 characters\)
sed "s/^X//" >'tuning.c' <<'END_OF_FILE'
X/* tuning.c -- a scale definition program */
X
X/*****************************************************************************
X*	    Change Log
X*  Date	    | Change
X*-----------+-----------------------------------------------------------------
X* 16-Jun-86 | Created changelog
X* 12-Aug-86 | Fixed an off-by-12 indexing bug, use userio.h to open file
X*****************************************************************************/
X
X#include "cext.h"
X#include "stdio.h"
X#include "pitch.h"
X#include "userio.h"
X#include "cmdline.h"
X
X#define MINPITCH -12
X#define MAXPITCH 115
X
X/****************************************************************************
X*	Routines local to this module
X****************************************************************************/
Xprivate char	getcommand();
Xprivate	void	getoctave();
Xprivate	void	getonepitch();
Xprivate	void	getrange();
Xprivate	void	readpitch();
Xprivate	void	writepitch();
Xprivate void	ratio_to_cents();
X
X/****************************************************************************
X* Data for command line parsing
X****************************************************************************/
X#define nswitches 0
X#define switches NULL
X#define noptions 0
X#define options NULL
X
X/****************************************************************************
X*				getcommand
X* Outputs:
X*	returns char: character typed by user
X* Effect:
X*	prompts for command and gets it
X****************************************************************************/
X
Xprivate char getcommand()
X{
X    char result;
X
X    printf("\nr - enter a range of values\n");
X    printf("o - enter one octave (that will be generalized)\n");
X    printf("p - enter one pitch (you choose)\n");
X    printf("q - quit\n\n");
X    printf("Command >>");
X
X    while ((result = getchar()) == '\n') ;
X    readln(stdin);	/* flush the newline and any other chars */
X    return result;
X}
X
X/****************************************************************************
X*				getoctave
X* Outputs:
X*	pitch_table pit_tab[]: array of pitch data
X* Effect:
X*	prompts user for one octave of data, then transposes to get others
X****************************************************************************/
X
Xprivate void getoctave(pit_tab)
Xpitch_table pit_tab[];
X{
X    float ratio[12], num, denom;
X    int pitch[12], bend[12], base, key, i, j, count, choice;
X
X    printf("\n\nYou will input the information for one octave and that\n");
X    printf("  will be generalized for all octaves.\n");
X    printf("\nWould you like to enter the information as\n");
X    printf("   (1)  frequency ratios of notes to a tonic\n");
X    printf("or (2)  semitones (integer) + pitchbend (in cents)\n\n");
X    printf(" >>");
X    scanf("%d\n", &choice);
X    if (choice == 1) {
X	printf("Please enter ratio x/y as   x y	  where x and y are floating point numbers.\n\n");
X	printf("Note 0 (tonic)	ratio is  1/1  (1 1)\n");
X	ratio[0] = 1.0;
X	for (i = 1; i < 12; i++) {
X	    printf("note %d ratio >>", i);
X	    scanf("%f %f\n", &num,&denom);
X	    ratio[i] = num/denom;
X	    printf("ratio[%d] = %f\n",i,ratio[i]);
X	}
X	ratio_to_cents(ratio, bend, pitch);
X    } else {
X	printf("\n\nFor the given note number, enter the desired pitch\n");
X	printf("and the amount of pitchbend in cents based on given tonic\n");
X	printf("\n1 unit of pitch = 1 semitone -- the tonic (note 0) has pitch 0 and bend 0.\n");
X	printf("   Bend range =	 -100 .. 100 cents,  0 for no pitch bend\n");
X	printf("     (100 cents = 1 semitone)\n");
X	printf("\n\n");
X	bend[0] = pitch[0] = 0;
X	for (i = 1; i <12; i++)
X	{
X	    printf("Octave note %d\n", i);
X	    printf("   pitch >>");
X	    scanf("%d\n", &pitch[i]);
X	    printf("   bend >>");
X	    scanf("%d\n", &bend[i]);
X	}
X    }
X    printf("\nWhat note would you like your octave to start on?\n\n");
X    printf("C	C#  D	D#  E	F   F#	G   G#	A   A#	B\n");
X    printf("0	1   2	3   4	5   6	7   8	9   10	11\n");
X    printf(" >>");
X    scanf("%d\n", &key);
X    for (i = 0; i < 12; i++) {
X	base = i + key;
X	if (base > 11) {
X	    base -= 12; key -=12;
X	}
X	/* 0 <= base <= 11 */
X	/* remember that pitches range from -12 to 115: */
X	for (count = -1, j = base+MINPITCH; j <= MAXPITCH; j+=12) {
X	    pit_tab[j-MINPITCH].ppitch = key + pitch[i] + count*12;
X	    pit_tab[j-MINPITCH].pbend = bend[i];
X	    count++;
X	}
X    }
X}
X
X/****************************************************************************
X*				getonepitch
X* Inputs:
X*	pitch_table pit_tab[]: table to be modified
X* Outputs:
X*	pitch_table pit_tab[]: table with modifications is returned
X* Effect: 
X*	prompts user for a note to change, gets data, modifies table
X****************************************************************************/
X
Xprivate void getonepitch(pit_tab)
Xpitch_table pit_tab[128];
X{
X    int	 pitch, bend, index, finished = 0;
X
X    while (!finished) {
X	printf("Note range is -12..115.  Which note would you like to enter ?");
X	printf("\n (Q to quit)\n");
X	printf("Note >>");
X	if (scanf("%d\n", &index) == 0) {
X	    finished = true;
X	    readln(stdin);
X	} else {
X	    printf("\n\nFor the given pitch number, enter pitch paramaters\n");
X	    printf("   Bend range =  -100 .. 100 cents,	 0 for no pitch bend\n");
X	    printf("	 (100 cents = 1 semitone)\n");
X	    printf("   Pitch range = -12 .. 115, 48 is middle C\n\n\n");
X
X	    printf("Adagio note %d\n", index);
X	    printf("   pitch >>");
X	    scanf("%d\n", &pitch);
X	    printf("   bend >>");
X	    scanf("%d\n", &bend);
X	    pit_tab[index - MINPITCH].pbend = bend;
X	    pit_tab[index - MINPITCH].ppitch = pitch;
X	}
X    }
X}
X
X/****************************************************************************
X*				getrange
X* Inputs:
X*	pitch_table pit_tab[128]: a table of pitch info
X* Outputs:
X*	pitch_table pit_tab[128]: modified table of pitch info
X* Effect: 
X*	asks user for a range, then prompts for pitch data within that
X*	range
X****************************************************************************/
X
Xprivate void getrange(pit_tab)
X    pitch_table pit_tab[128];
X{
X    int i,low,high,bend,pitch;
X
X    printf("Adagio note range is 1..128\nWhat range of notes would you like to enter ?\n");
X    printf("From >>");
X    scanf("%d\n", &low);
X    printf("  To >>");
X    scanf("%d\n", &high);
X
X    printf("\n\nFor the given Adagio note number, enter the desired pitch\n");
X    printf("and the amount of pitchbend in cents\n");
X    printf("   Bend range =  -100 .. 100,  '0' for no pitch bend\n");
X    printf("	 (100 cents = 1 semitone)\n");
X    printf("   Pitch range = 1 .. 128, 48 is middle C\n");
X    printf("\n\n");
X    for (i = low; i <= high; i++)
X    {
X	printf("Adagio Note %d\n", i);
X	printf("   pitch >>");
X	scanf("%d\n", &pitch);
X	printf("   bend >>");
X	scanf("%d\n", &bend);
X	pit_tab[i - MINPITCH].pbend = bend;
X	pit_tab[i - MINPITCH].ppitch = pitch;
X    }
X}
X
X/****************************************************************************
X*				main
X* Inputs:
X*	int argc: number of command line arguments
X*	char *argv[]: vector of command line arguments
X* Effect: main program
X****************************************************************************/
X
Xvoid main(argc, argv)
X    int	 argc;
X    char *argv[];
X{
X    int i, done = 0;
X    FILE *fp;
X    char *s;	/* the filename argument, if any */
X    char filename[100];
X    pitch_table pit_tab[128];
X
X    cl_init(switches, nswitches, options, noptions, argv, argc);
X
X    /* get output file: */
X	if ((s = cl_arg(1)) != NULL) strcpy(filename, s);
X	else strcpy(filename, "");
X	fp = fileopen(filename, "tun", "w", "Name of tuning file");
X
X    for (i = MINPITCH; i <= MAXPITCH; i++) { /* initialize pit_tab */
X	pit_tab[i - MINPITCH].pbend = 0;
X	pit_tab[i - MINPITCH].ppitch = i;
X    }
X
X    printf("You will now create a pitch file.\n\n");
X    while (!done) {
X	switch (getcommand()) {
X	    case 'r': getrange(pit_tab); break;
X	    case 'p': getonepitch(pit_tab); break;
X	    case 'o': getoctave(pit_tab); break;
X	    case 'q': done = 1; break;
X	    default: continue;
X	}
X    }
X    writepitch(fp, pit_tab);
X}
X
X/****************************************************************************
X*				readpitch
X* Inputs:
X*	FILE *fp: file from which to read
X* Outputs:
X*	pitch_table pit_tab[128]: this table is initialized by reading fp
X****************************************************************************/
X
Xprivate void readpitch(fp, pit_tab)
XFILE *fp;
Xpitch_table pit_tab[128];
X{
X    int i, j, pitch, bend;
X
X    for ( j = MINPITCH; j <= MAXPITCH; j++)
X    {
X	fscanf(fp,"%d %d %d\n", &i, &pitch, &bend);
X	pit_tab[i].ppitch = pitch;
X	pit_tab[i].pbend = bend;
X    }
X}
X
X/****************************************************************************
X*				writepitch
X* Inputs:
X*	FILE *fp: the file to write
X*	pitch_table pit_tab[128]: the table to write
X* Effect: 
X*	writes pit_tab to file *fp
X****************************************************************************/
X
Xprivate void writepitch(fp, pit_tab)
X    FILE *fp;
X    pitch_table pit_tab[128];
X{
X    int i;
X
X    for ( i = MINPITCH; i <= MAXPITCH; i++) {
X	fprintf(fp,"%d %d %d\n", i, pit_tab[i-MINPITCH].ppitch,
X		pit_tab[i-MINPITCH].pbend);
X    }
X}
X
X/****************************************************************************
X*				ratio_to_cents
X* Inputs:
X*	float ratio[]: an octave of rations to convert
X* Outputs:
X*	int bend[]: an octave of pitch bends
X*	int pitch[]: an octave of pitches
X* Effect:
X*	converts 12 ratios to pitch + bend pairs
X****************************************************************************/
X
Xprivate void ratio_to_cents(ratio, bend, pitch)
Xfloat ratio[];
Xint bend[], pitch[];
X{
X    int i;
X    float cents;
X
X    for (i = 0; i < 12; i++) {
X	cents = 1200 * log(ratio[i])/log(2);
X	pitch[i] = (int)(cents/100);
X	bend[i] = (int)(cents - (pitch[i] * 100) + 0.5);
X    }
X}
END_OF_FILE
if test 9694 -ne `wc -c <'tuning.c'`; then
    echo shar: \"'tuning.c'\" unpacked with wrong size!
fi
# end of 'tuning.c'
fi
echo shar: End of archive 2 \(of 6\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 4 5 6 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 6 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
