home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_progs
/
sound
/
algorhyt.lha
/
source
/
MusicSerial.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-02-21
|
9KB
|
332 lines
/* MusicSerial.c
Copyright (c) 1990,1991,1992 by Thomas E. Janzen
All Rights Reserved
THIS SOFTWARE IS FURNISHED FREE OF CHARGE FOR STUDY AND USE AND MAY
BE COPIED ONLY FOR PERSONAL USE OR COMPLETELY AS OFFERED WITH NO
CHANGES FOR FREE DISTRIBUTION. NO TITLE TO AND OWNERSHIP OF THE
SOFTWARE IS HEREBY TRANSFERRED. THOMAS E. JANZEN ASSUMES NO
RESPONSBILITY FOR THE USE OR RELIABILITY OF THIS SOFTWARE.
Thomas E. Janzen
58A School St. Apt. 2-L
Hudson, MA 01749
(508)562-1295
*/
/*
** FACILITY:
**
** AlgoRhythms music improviser on Commodore (TM) Amiga (TM)
** compiled with SAS/C V5.10b
**
** ABSTRACT:
**
** MusicSerial.c manages the serial device at the MIDI bit rate.
** All sends to MIDI occur here.
**
** AUTHORS: Thomas E. Janzen
**
** CREATION DATE: 26-MAR-1990
**
** MODIFICATION HISTORY:
** DATE NAME DESCRIPTION
** 7 Dec 90 T. Janzen Used SendIO rather than DoIO - didn't up performance
** 4 Nov 91 T. Janzen incorporate MIDI running status; delete SendNoteOff
** 8 DEC 91 T. Janzen conform to SAS/C 5.10b remove extern from functs
** 4 Jan 92 TEJ last changes for 2.0
**--
*/
#include "exec/types.h"
#include "exec/nodes.h"
#include "exec/lists.h"
#include "exec/ports.h"
#include "exec/libraries.h"
#include "exec/devices.h"
#include "devices/serial.h"
#include "exec/io.h"
#include "intuition/intuition.h"
#include <proto/dos.h>
#include <proto/graphics.h>
#include <proto/exec.h>
#include <proto/mathffp.h>
#include <proto/intuition.h>
#ifdef CLI
#include <stdio.h>
#endif
#include "Window.h"
#include "AlgoRhythms.h"
#include "MusicSerial.h"
#include "Record.h"
#define NOTEON (0x90) /* MIDI Spec note on flag */
#define NOTEOFF (0x80) /* MIDI Spec note off flag */
#define NOTEONCMD (0x90) /* MIDI Note on byte */
#define NOTEOFFCMD (0x80) /* MIDI Note off byte */
#define START (0xFA) /* MIDI Start play byte */
#define STOP (0xFC) /* MIDI Stop play byte */
#define CONTINUE (0xFB) /* MIDI Continue play byte */
#define TIMINGCLOCK (0xF8) /* MIDI Timing clock byte */
int Response;
static struct IOExtSer *IORser; /* Amiga Devices structures for serial */
static struct MsgPort *port;
extern struct IORequest *CreateExtIO();
extern void DeletePort(struct MsgPort *);
/* strings for error alerts */
static char QuitStr[] = "Quit",
SerErrStr[] = "Serial Device Error",
PrtErrStr[] = "Port Error",
IOErrStr[] = "Create ExtIO Error",
DevErrStr[] = "Serial Device Error",
PrmErrStr[] = "Set Parm Error",
WrtErrStr[] = "Serial.device write error";
#ifndef CLI
struct IntuiText QuitTxt = {2, 1, JAM1, 5, 4, &font_choice, QuitStr, NULL};
#endif
static char playbuffer[4]; /* MIDI note message buffer */
#ifdef MEASURE
extern unsigned int NotesTotalMeasure = 0;
#endif
int SetParams (struct IOExtSer *io, unsigned long rbuf_len,
unsigned char rlen, unsigned char wlen, unsigned long brk,
unsigned long baud, unsigned char sf,
unsigned long ta0, unsigned long ta1)
{
/* set parameters of serial device */
#ifndef CLI
struct IntuiText SerErrTxt = {2, 1, JAM1, 5, 15, &font_choice,SerErrStr,
NULL};
#endif
int error;
io->io_ReadLen = rlen;
io->io_BrkTime = brk; /*length of break timej (irrelevant)*/
io->io_Baud = baud;
io->io_WriteLen = wlen;
io->io_StopBits = 0x01;
io->io_RBufLen = rbuf_len;
io->io_SerFlags = (1 << SERB_RAD_BOOGIE);
io->IOSer.io_Command = SDCMD_SETPARAMS;
io->io_TermArray.TermArray0 = ta0;
io->io_TermArray.TermArray1 = ta1;
if ((error = DoIO (io)) != 0)
{
quit = TRUE;
fubar = TRUE;
#ifdef CLI
puts (SerErrStr);
#else
Response = AutoRequest ( w, &SerErrTxt, &QuitTxt, &QuitTxt,
0L, 0L, 300L, 60L);
#endif
}
return error;
}
void Open_MIDI_Port (void)
{
#ifndef CLI
struct IntuiText PrtErrTxt = {2, 1, JAM1, 5, 15,
&font_choice, PrtErrStr, NULL},
IOErrTxt = {2, 1, JAM1, 5, 15,
&font_choice, IOErrStr, NULL},
DevErrTxt = {2, 1, JAM1, 5, 15,
&font_choice, DevErrStr, NULL},
PrmErrTxt = {2, 1, JAM1, 5, 15,
&font_choice, PrmErrStr, NULL};
#endif
int error;
unsigned long rbl = 512, /*read buffer length*/
brk = 750000,
/* length of break in usec, usu. 750000 */
baud = 31250, /* MIDI baud rate 31.25k bits/sec*/
t0 = 0x51040303, /*termination characters*/
t1 = 0x03030303;
unsigned char rwl = 0x08, /*bits per read char */
wwl = 0x08, /*bits per write char */
sf = 0x00; /*serial flags cf D-124 in libs devices*/
/* Try to get to the serial device. */
/* page 396 of Libraries and Devices
was the example*/
port = CreatePort (SERIALNAME, 0);
if (port == NULL)
{
quit = TRUE;
fubar = TRUE;
#ifdef CLI
puts (PrtErrStr);
#else
Response = AutoRequest (w, &PrtErrTxt, &QuitTxt, &QuitTxt,
0L, 0L, 300L, 60L);
#endif
}
IORser =
(struct IOExtSer *)CreateExtIO(port, sizeof(struct IOExtSer));
if (IORser == NULL)
{
quit = TRUE;
fubar = TRUE;
#ifdef CLI
puts (IOErrStr);
#else
Response = AutoRequest (w, &IOErrTxt,
&QuitTxt, &QuitTxt, 0L, 0L, 300L, 60L);
#endif
}
open:
if ((error = OpenDevice(SERIALNAME, 0, IORser, 0)) != 0)
{
quit = TRUE;
fubar = TRUE;
#ifdef CLI
puts (DevErrStr);
#else
Response = AutoRequest (w, &DevErrTxt,
&QuitTxt, &QuitTxt, 0L, 0L, 300L, 60L);
#endif
}
if ((error
= SetParams (IORser, rbl, rwl, wwl, brk, baud, sf, t0, t1)) != 0)
{
fubar = TRUE;
quit = TRUE;
#ifdef CLI
puts (PrmErrStr);
#else
Response = AutoRequest (w, &PrmErrTxt,
&QuitTxt, &QuitTxt, 0L, 0L, 300L, 60L);
#endif
}
return;
/* The serial device is open, so go ahead and play music.*/
}
int WriteSer (struct IOExtSer *io, char *data, int length)
{
int error;
#ifndef CLI
struct IntuiText WrtErrTxt = {2, 1, JAM1, 5, 15, &font_choice,
WrtErrStr, NULL};
#endif
io->IOSer.io_Data = (APTR)data;
io->IOSer.io_Length = length;
io->IOSer.io_Command = CMD_WRITE;
if((error = WaitIO(io)) != 0)
{
quit = TRUE; /* flag to get out of program */
fubar = TRUE; /* flag to dump out of program with error*/
#ifdef CLI
puts (WrtErrStr);
#else
Response = AutoRequest (w, &WrtErrTxt,
&QuitTxt, &QuitTxt, 0L, 0L, 300L, 60L);
#endif
}
SendIO (io);
return error;
}
void PlayNoteOn (const NOTEEVENT *PlayEvent)
{
static unsigned char Running_Status = 0X00;
if (PlayEvent->Channel < 0)
{
Running_Status = 0;
return;
}
playbuffer[0] = (unsigned char)(PlayEvent->Channel | NOTEONCMD);
playbuffer[2] = (unsigned char)(PlayEvent->Dynamic);
if (playbuffer[2])
{
playbuffer[1] = (unsigned char)(scale[PlayEvent->Pitch]);
#ifdef MEASURE
NotesTotalMeasure++;
#endif
}
else
{
playbuffer[1] = (unsigned char)(PlayEvent->CurPitch);
}
if (playbuffer[0] == Running_Status)
{
WriteSer (IORser, &playbuffer[1], 2); /* send it out MIDI */
}
else
{
WriteSer (IORser, playbuffer, 3); /* send it out MIDI */
Running_Status = playbuffer[0];
}
return;
}
void SendFunction (int Function)
{
playbuffer[1] = 0;
switch (Function)
{
case STARTFUNCT:
playbuffer[0] = (unsigned char)START;
break;
case STOPFUNCT:
playbuffer[0] = (unsigned char)STOP;
break;
case CLOCKFUNCT:
playbuffer[0] = (unsigned char)TIMINGCLOCK;
break;
case CONTFUNCT:
playbuffer[0] = (unsigned char)CONTINUE;
break;
default:
break;
}
WriteSer (IORser, playbuffer, 1); /* send it out MIDI */
return;
}
void StopAllNotes (NOTEEVENT NotestoStop[])
{
int i;
for (i = 0; i < 16; i++)
{
if (NotestoStop[i].Playing)
{
NotestoStop[i].Dynamic = 0;
PlayNoteOn (&NotestoStop[i]);
if (Recording)
{
Record_Note_Event (&NotestoStop[i]);
}
NotestoStop[i].Playing = 0;
Delay (1);
if (fubar == TRUE)
{
break;
}
}
}
SendFunction (STOPFUNCT);
return;
}
void StopMIDI (void)
{
/* close up shop */
if (port) DeletePort (port);
if (IORser) CloseDevice (IORser);
return;
}