home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Audio 4.94 - Over 11,000 Files
/
audio-11000.iso
/
amiga
/
midi
/
obrst103.lha
/
OberSuite-1.03
/
SourceCode
/
patchinfo.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-23
|
6KB
|
230 lines
/**************************************************************************
* patchinfo.c: Functions for initializing, filling, printing, and
* destroying PATCHINFO structures.
* A part of OberSuite for the Commodore Amiga.
*
* Author: Daniel Barrett, barrett@cs.umass.edu.
* Version: 1.0.
* Copyright: None! This program is in the Public Domain.
* Please share it with others.
***************************************************************************/
#include "decl.h"
#include "midi.h"
#include "oberheim.h"
#include "patchinfo.h"
/*****************************************************************************
* Initializing patchinfo data.
*****************************************************************************/
void InitPatchInfo(PATCHINFO *pi)
{
pi->actualSize = (long)0;
pi->data = NULL;
pi->firstSingleOffset = (long)0;
pi->mode = (UBYTE)0;
pi->nameOffset = (long)0;
pi->numPatches = (long)0;
pi->numSinglesInside = (long)0;
pi->patchNum = (UBYTE)0;
pi->rightSize = (long)0;
pi->source = 0;
strcpy(pi->instrument, "UNKNOWN");
strcpy(pi->modeName, "UNKNOWN");
}
/*****************************************************************************
* Allocate patchinfo data.
*****************************************************************************/
BOOL AllocPatchInfo(PATCHINFO *pi)
{
return((BOOL)
(pi->data = (UBYTE *)malloc(pi->rightSize * pi->numPatches)));
}
/*****************************************************************************
* Freeing patchinfo data.
*****************************************************************************/
void FreePatchInfo(PATCHINFO *pi)
{
if (pi->data)
free(pi->data);
pi->data = NULL;
}
/*****************************************************************************
* Printing patchinfo data (for diagnostic purposes).
*****************************************************************************/
/*
* Print information about the patch data found at address
* pi->data + offset. The data MUST be valid before calling this function.
*/
void PrintPatchInfo(PATCHINFO *pi, long offset)
{
int num;
if ((pi->data) && (pi->rightSize == pi->actualSize))
{
num = pi->data[offset + BYTE_PATCHNUMBER];
printf("%s %s patch %02d: ", pi->instrument, pi->modeName,
num);
PrintPatchName(pi->data + offset, pi->nameOffset);
if (pi->mode == MODE_MULTI)
PrintSinglesInMulti(pi->data + offset,
pi->numSinglesInside, pi->firstSingleOffset);
printf("\n");
}
else
fprintf(stderr, "No data to print.\n");
}
/*
* Print the name of the given patch. The patch name data starts at the
* address patch + startHere.
* Each byte of the patch name is followed by a 0 byte.
*/
void PrintPatchName(UBYTE *patch, long startHere)
{
int i;
if (patch)
for (i=0; i<NAME_LENGTH; i++)
putchar(patch[startHere + (2 * i)]);
}
/*
* Given the data for a multi patch, print the single patch numbers that
* make up that multi patch. The relevant data begins at address
* patch + startHere. Each patch number byte is followed by a 0 byte.
*/
void PrintSinglesInMulti(UBYTE *patch, long howMany, long startHere)
{
int i;
UBYTE data;
if (patch)
{
printf(" <%02d", patch[startHere]);
for (i=1; i<howMany; i++)
{
data = patch[startHere + (2*i)];
printf(" %02d", data);
}
printf(">");
}
}
/*****************************************************************************
* Verifying patchinfo data.
*****************************************************************************/
/*
* Verify that some data is a legal patch. The data begins at address
* pi->data + offset, and certain bytes must match those expected for
* an Xpander/Matrix-12 patch dump.
* Return TRUE if the patch data is valid (else FALSE).
*/
BOOL VerifyPatch(PATCHINFO *pi, long offset)
{
UBYTE *startHere = pi->data + offset;
if (startHere[BYTE_SYSEX] != SYSEX_BEGIN)
ErrorMsg(ERROR_NOTSYSEX);
else if (startHere[BYTE_ID] != OBERHEIM_SYSEX_ID)
ErrorMsg(ERROR_NOTOBERHEIM);
else if (!FigureOutInstrument(pi, startHere[BYTE_DEVICE]))
ErrorMsg(ERROR_NOTXPMATRIX);
else if (pi->actualSize != pi->rightSize)
{
if (pi->actualSize < pi->rightSize)
ErrorMsg(ERROR_DATATOOSMALL);
else
ErrorMsg(ERROR_DATATOOBIG);
if (ERR_OUTPUT_ALLOWED)
fprintf(stderr,
"(%ld bytes were expected, but we have %ld.)\n",
pi->rightSize, pi->actualSize);
}
else if (startHere[BYTE_DATADUMP] != DUMP_FOLLOWS)
ErrorMsg(ERROR_NOTPATCHDATA);
else if (startHere[BYTE_PATCHTYPE] != pi->mode)
ErrorMsg(ERROR_UNKNOWNVOICEDATA);
else if (startHere[pi->rightSize - 1] != SYSEX_END)
ErrorMsg(ERROR_NOEOX);
else
return(TRUE);
return(FALSE);
}
/*
* Which instrument did the given PATCHINFO data come from?
* Only the "mode" is known (single or multi) at this point.
* Single patch data is identical in (and compatible between) the Xpander
* and Matrix-12, so we can calculate its expected size, name offset, and
* instrument name immediately.
* For a multi patch, we must look at the value of "instrument" to determine
* if the data is from an Xpander or a Matrix-12, and we fill in the
* remaining data from there.
* Return TRUE on success (else FALSE).
*/
BOOL FigureOutInstrument(PATCHINFO *pi, UBYTE instrument)
{
if (pi->mode == MODE_SINGLE)
{
if (instrument == OBERHEIM_DEVICE_NUMBER)
{
pi->rightSize = (long)SINGLE_SIZE;
pi->nameOffset = (long)SINGLE_NAMELOC;
strcpy(pi->instrument, NAME_BOTH);
}
else
return(FALSE);
}
else if (pi->mode == MODE_MULTI)
{
if (instrument == XPANDER_MULTI_ID)
{
pi->rightSize = (long)XPANDER_MULTI_SIZE;
pi->nameOffset = (long)XPANDER_MULTI_NAMELOC;
strcpy(pi->instrument, NAME_XPANDER);
pi->numSinglesInside = (long)XPANDER_MULTI_SINGLES;
pi->firstSingleOffset = (long)XPANDER_SINGLE_OFFSET;
}
else if (instrument == MATRIX12_MULTI_ID)
{
pi->rightSize = (long)MATRIX12_MULTI_SIZE;
pi->nameOffset = (long)MATRIX12_MULTI_NAMELOC;
strcpy(pi->instrument, NAME_MATRIX12);
pi->numSinglesInside = (long)MATRIX12_MULTI_SINGLES;
pi->firstSingleOffset = (long)MATRIX12_SINGLE_OFFSET;
}
else
return(FALSE);
}
else
return(FALSE);
return(TRUE);
}