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 >
C/C++ Source or Header  |  1993-01-23  |  6KB  |  230 lines

  1. /**************************************************************************
  2. * patchinfo.c:    Functions for initializing, filling, printing, and
  3. *        destroying PATCHINFO structures.
  4. *        A part of OberSuite for the Commodore Amiga.
  5. *
  6. * Author:    Daniel Barrett, barrett@cs.umass.edu.
  7. * Version:    1.0.
  8. * Copyright:    None!  This program is in the Public Domain.
  9. *        Please share it with others.
  10. ***************************************************************************/
  11.  
  12. #include "decl.h"
  13. #include "midi.h"
  14. #include "oberheim.h"
  15. #include "patchinfo.h"
  16.  
  17. /*****************************************************************************
  18. * Initializing patchinfo data.
  19. *****************************************************************************/
  20.  
  21. void InitPatchInfo(PATCHINFO *pi)
  22. {
  23.     pi->actualSize        = (long)0;
  24.     pi->data        = NULL;
  25.     pi->firstSingleOffset    = (long)0;
  26.     pi->mode        = (UBYTE)0;
  27.     pi->nameOffset        = (long)0;
  28.     pi->numPatches        = (long)0;
  29.     pi->numSinglesInside    = (long)0;
  30.     pi->patchNum        = (UBYTE)0;
  31.     pi->rightSize        = (long)0;
  32.     pi->source        = 0;
  33.  
  34.     strcpy(pi->instrument, "UNKNOWN");
  35.     strcpy(pi->modeName,   "UNKNOWN");
  36. }
  37.  
  38.  
  39. /*****************************************************************************
  40. * Allocate patchinfo data.
  41. *****************************************************************************/
  42.  
  43. BOOL AllocPatchInfo(PATCHINFO *pi)
  44. {
  45.     return((BOOL)
  46.         (pi->data = (UBYTE *)malloc(pi->rightSize * pi->numPatches)));
  47. }
  48.  
  49.  
  50. /*****************************************************************************
  51. * Freeing patchinfo data.
  52. *****************************************************************************/
  53.  
  54. void FreePatchInfo(PATCHINFO *pi)
  55. {
  56.     if (pi->data)
  57.         free(pi->data);
  58.     pi->data = NULL;
  59. }
  60.  
  61.  
  62. /*****************************************************************************
  63. * Printing patchinfo data (for diagnostic purposes).
  64. *****************************************************************************/
  65.  
  66. /*
  67.  * Print information about the patch data found at address 
  68.  * pi->data + offset.  The data MUST be valid before calling this function.
  69.  */
  70.  
  71. void PrintPatchInfo(PATCHINFO *pi, long offset)
  72. {
  73.     int num;
  74.  
  75.     if ((pi->data) && (pi->rightSize == pi->actualSize))
  76.     {
  77.         num = pi->data[offset + BYTE_PATCHNUMBER];
  78.         printf("%s %s patch %02d: ", pi->instrument, pi->modeName,
  79.             num);
  80.          PrintPatchName(pi->data + offset, pi->nameOffset);
  81.  
  82.         if (pi->mode == MODE_MULTI)
  83.             PrintSinglesInMulti(pi->data + offset,
  84.                 pi->numSinglesInside, pi->firstSingleOffset);
  85.  
  86.         printf("\n");
  87.     }
  88.     else
  89.         fprintf(stderr, "No data to print.\n");
  90. }
  91.  
  92.  
  93. /*
  94.  * Print the name of the given patch.  The patch name data starts at the
  95.  * address patch + startHere.
  96.  * Each byte of the patch name is followed by a 0 byte.
  97.  */
  98.  
  99. void PrintPatchName(UBYTE *patch, long startHere)
  100. {
  101.     int i;
  102.  
  103.     if (patch)
  104.         for (i=0; i<NAME_LENGTH; i++)
  105.             putchar(patch[startHere + (2 * i)]);
  106. }
  107.  
  108. /*
  109.  * Given the data for a multi patch, print the single patch numbers that
  110.  * make up that multi patch.  The relevant data begins at address
  111.  * patch + startHere.  Each patch number byte is followed by a 0 byte.
  112.  */
  113.  
  114. void PrintSinglesInMulti(UBYTE *patch, long howMany, long startHere)
  115. {
  116.     int i;
  117.     UBYTE data;
  118.  
  119.     if (patch)
  120.     {
  121.         printf("  <%02d", patch[startHere]);
  122.  
  123.         for (i=1; i<howMany; i++)
  124.         {
  125.             data = patch[startHere + (2*i)];
  126.             printf(" %02d", data);
  127.         }
  128.         printf(">");
  129.     }
  130. }
  131.  
  132.  
  133. /*****************************************************************************
  134. * Verifying patchinfo data.
  135. *****************************************************************************/
  136.  
  137. /*
  138.  * Verify that some data is a legal patch.  The data begins at address
  139.  *  pi->data + offset, and certain bytes must match those expected for
  140.  *  an Xpander/Matrix-12 patch dump.
  141.  * Return TRUE if the patch data is valid (else FALSE).
  142.  */
  143.  
  144. BOOL VerifyPatch(PATCHINFO *pi, long offset)
  145. {
  146.     UBYTE *startHere = pi->data + offset;
  147.  
  148.     if (startHere[BYTE_SYSEX] != SYSEX_BEGIN)
  149.         ErrorMsg(ERROR_NOTSYSEX);            
  150.     else if (startHere[BYTE_ID] != OBERHEIM_SYSEX_ID)
  151.         ErrorMsg(ERROR_NOTOBERHEIM);
  152.     else if (!FigureOutInstrument(pi, startHere[BYTE_DEVICE]))
  153.         ErrorMsg(ERROR_NOTXPMATRIX);
  154.     else if (pi->actualSize != pi->rightSize)
  155.     {
  156.         if (pi->actualSize < pi->rightSize)
  157.             ErrorMsg(ERROR_DATATOOSMALL);
  158.         else
  159.             ErrorMsg(ERROR_DATATOOBIG);
  160.  
  161.         if (ERR_OUTPUT_ALLOWED)
  162.             fprintf(stderr,
  163.                "(%ld bytes were expected, but we have %ld.)\n",
  164.                pi->rightSize, pi->actualSize);
  165.     }
  166.     else if (startHere[BYTE_DATADUMP] != DUMP_FOLLOWS)
  167.         ErrorMsg(ERROR_NOTPATCHDATA);
  168.     else if (startHere[BYTE_PATCHTYPE] != pi->mode)
  169.         ErrorMsg(ERROR_UNKNOWNVOICEDATA);
  170.     else if (startHere[pi->rightSize - 1] != SYSEX_END)
  171.         ErrorMsg(ERROR_NOEOX);
  172.     else
  173.         return(TRUE);
  174.  
  175.     return(FALSE);
  176. }
  177.  
  178.  
  179. /*
  180.  * Which instrument did the given PATCHINFO data come from?
  181.  * Only the "mode" is known (single or multi) at this point.
  182.  * Single patch data is identical in (and compatible between) the Xpander
  183.  *  and Matrix-12, so we can calculate its expected size, name offset, and
  184.  *  instrument name immediately.
  185.  * For a multi patch, we must look at the value of "instrument" to determine
  186.  *  if the data is from an Xpander or a Matrix-12, and we fill in the
  187.  *  remaining data from there.
  188.  * Return TRUE on success (else FALSE).
  189.  */
  190.  
  191. BOOL FigureOutInstrument(PATCHINFO *pi, UBYTE instrument)
  192. {
  193.     if (pi->mode == MODE_SINGLE)
  194.     {
  195.         if (instrument == OBERHEIM_DEVICE_NUMBER)
  196.         {
  197.             pi->rightSize = (long)SINGLE_SIZE;
  198.             pi->nameOffset = (long)SINGLE_NAMELOC;
  199.             strcpy(pi->instrument, NAME_BOTH);
  200.         }
  201.         else
  202.             return(FALSE);
  203.     }
  204.     else if (pi->mode == MODE_MULTI)
  205.     {
  206.         if (instrument == XPANDER_MULTI_ID)
  207.         {
  208.             pi->rightSize = (long)XPANDER_MULTI_SIZE;
  209.             pi->nameOffset = (long)XPANDER_MULTI_NAMELOC;
  210.             strcpy(pi->instrument, NAME_XPANDER);
  211.             pi->numSinglesInside = (long)XPANDER_MULTI_SINGLES;
  212.             pi->firstSingleOffset = (long)XPANDER_SINGLE_OFFSET;
  213.         }
  214.         else if (instrument == MATRIX12_MULTI_ID)
  215.         {
  216.             pi->rightSize = (long)MATRIX12_MULTI_SIZE;
  217.             pi->nameOffset = (long)MATRIX12_MULTI_NAMELOC;
  218.             strcpy(pi->instrument, NAME_MATRIX12);
  219.             pi->numSinglesInside = (long)MATRIX12_MULTI_SINGLES;
  220.             pi->firstSingleOffset = (long)MATRIX12_SINGLE_OFFSET;
  221.         }
  222.         else
  223.             return(FALSE);
  224.     }
  225.     else
  226.         return(FALSE);
  227.  
  228.     return(TRUE);
  229. }
  230.