home *** CD-ROM | disk | FTP | other *** search
/ Audio Version 4.94 / audioversion4.94knowledgemediaresourcelibraryoctober1994.iso / amiga / utils / exp_iv / load.c < prev    next >
C/C++ Source or Header  |  1991-05-16  |  14KB  |  572 lines

  1. /* load.c 
  2.  
  3. /* loads a soundtracker binary file
  4.  * into memory, using a more convenient format
  5.  */
  6.  
  7. /* $Author: Espie $
  8.  * $Date: 91/05/16 15:05:24 $
  9.  * $Revision: 1.34 $
  10.  * $Log:    load.c,v $
  11.  * Revision 1.34  91/05/16  15:05:24  Espie
  12.  * *** empty log message ***
  13.  * 
  14.  * Revision 1.33  91/05/12  19:56:39  Espie
  15.  * Shortened event structure.
  16.  * 
  17.  * Revision 1.32  91/05/12  16:00:39  Espie
  18.  * switched back to a char *.
  19.  * 
  20.  * Revision 1.31  91/05/07  12:13:36  Espie
  21.  * *** empty log message ***
  22.  * 
  23.  * Revision 1.30  91/05/06  23:39:31  Espie
  24.  * Now tries to load a WBArg.
  25.  * Changes for accomodating new finetune and external find_note.
  26.  * 
  27.  * Revision 1.29  91/05/06  15:15:06  Espie
  28.  * Some more error checking, still not enough probably.
  29.  * 
  30.  * Revision 1.28  91/05/05  19:06:41  Espie
  31.  * *** empty log message ***
  32.  * 
  33.  * Revision 1.27  91/05/05  03:59:37  Espie
  34.  * Corrected other problems. Added some measure of error recovery
  35.  * 
  36.  * 
  37.  * Revision 1.26  91/05/04  23:22:22  Espie
  38.  * Corrected a very small bug in the handling of dummy samples.
  39.  * 
  40.  * Revision 1.25  91/05/02  23:31:14  Espie
  41.  * Now uses standard amigados filehandles... Might come in handy.
  42.  * 
  43.  * Revision 1.24  91/05/02  11:20:48  Espie
  44.  * Can now unload() empty songs...
  45.  * 
  46.  * Revision 1.23  91/05/02  01:30:57  Espie
  47.  * Correction of some small bugs, added a dummy sample for the player.
  48.  * 
  49.  * Revision 1.22  91/04/30  16:52:09  Espie
  50.  * Suppressed every IO.
  51.  * Added channel tracks, should handle finetuned instruments.
  52.  * 
  53.  * Revision 1.21  91/04/30  01:48:58  Espie
  54.  * Corrected a BIG and stupid bug, there was two separate cleanups where
  55.  * there should have been one, so that cleaning up an old module only happened
  56.  * on exit of the program...
  57.  * 
  58.  * Revision 1.20  91/04/30  00:35:15  Espie
  59.  * Stable version III.
  60.  * 
  61.  * Revision 1.19  91/04/30  00:23:34  Espie
  62.  * New error checking, does still exit if not enough memory.
  63.  * 
  64.  * Revision 1.18  91/04/29  23:53:56  Espie
  65.  * Added unload_song(). Need a decent error recovery strategy right now.
  66.  * 
  67.  * Revision 1.17  91/04/29  02:22:06  Espie
  68.  * checkabort() added for user interruption,
  69.  * since there are no longer critical sections.
  70.  * 
  71.  * Revision 1.16  91/04/28  22:53:37  Espie
  72.  * More leeway in the period computation.
  73.  * 
  74.  * Revision 1.15  91/04/27  20:49:00  Espie
  75.  * Small bug in find_note (order was reversed)
  76.  * 
  77.  * Revision 1.14  91/04/27  16:45:56  Espie
  78.  * Rounding errors for note period.
  79.  * 
  80.  * Revision 1.13  91/04/24  15:27:19  Espie
  81.  * Minor changes ???
  82.  * 
  83.  * Revision 1.12  91/04/23  21:30:32  Espie
  84.  * Revised so that one song can be automatically cleaned out.
  85.  * 
  86.  * Revision 1.11  91/04/21  20:06:07  Espie
  87.  * The loader now precomputes notes.
  88.  * It does not yet precompiles the effects (next step ?).
  89.  * 
  90.  * Revision 1.10  91/04/21  12:11:43  Espie
  91.  * Stable version, known as bunch II.
  92.  * Also features ``right'' log description.
  93.  * 
  94.  * Revision 1.9  91/04/21  11:14:34
  95.  * Bug in st files: repeat start is sometimes double what it should be.
  96.  *
  97.  * Revision 1.8  91/04/20  18:14:24
  98.  *
  99.  * Revision 1.7  91/04/19  13:22:20
  100.  *
  101.  * Revision 1.6  91/04/19  02:20:07
  102.  * loader without error checking for last sample.
  103.  * added dummy sample for simplified check.
  104.  *
  105.  * Revision 1.5  91/04/18  02:25:41
  106.  * bunch I.
  107.  *
  108.  * Revision 1.4  91/04/17  18:50:42
  109.  * This is now a working module. Only the block translation is not yet debugged.
  110.  *
  111.  * Revision 1.3  91/04/14  22:02:32
  112.  * Playing version. This one knows how to play sample!
  113.  *
  114.  * Revision 1.2  91/04/14  18:06:52
  115.  * This version is able to load most soundtrackers files without apparent mistakes.
  116.  * I still have got to figure out how the audio hardware works.
  117.  * So this doesn't play any tune.
  118.  * Apparently no bug as long as I don't try anything with the hardware.
  119.  *
  120.  * Revision 1.1  91/04/11  18:39:23
  121.  * Initial revision.
  122.  * Not yet debugged or anything.
  123.  * No interface for other modules.
  124.  *
  125.  */
  126.   
  127. #include <exec/types.h>
  128. #include <exec/memory.h>
  129. #include <string.h>
  130. #include <stddef.h>
  131. #include <dos/dos.h>
  132. #include <workbench/startup.h>
  133. #include <proto/dos.h>
  134. #include <proto/exec.h>
  135. #include <custom/cleanup.h>
  136. #include "song.h"
  137. #include "proto.h"
  138. #include "periods.h"
  139.  
  140. #include <proto/exec.h>
  141. #include <stdlib.h>
  142.  
  143. /* definitions for the binary st file format 
  144.  */
  145.  
  146. #define MAX_BLOCKS 128
  147. #define SAMPLE_NAME 22
  148. #define SONG_NAME 20
  149. #define OLD_SAMPLES 15
  150. #define NEW_SAMPLES 31
  151.  
  152. struct binary_sample_info
  153.     {
  154.         char sample_name[SAMPLE_NAME];
  155.         UWORD length;
  156.         UBYTE finetune;
  157.         UBYTE volume;
  158.         UWORD rp_start;
  159.         UWORD rp_length;
  160.     };
  161.     
  162. struct binary_song_info
  163.     {
  164.         UBYTE length;
  165.         UBYTE thing;
  166.         UBYTE block_number[MAX_BLOCKS];
  167.     };
  168.  
  169. struct binary_event
  170.     {
  171.         UBYTE detail[4];
  172.     };
  173.     
  174. struct interleaved
  175.     {
  176.         struct binary_event track[NUMBER_TRACKS];
  177.     };
  178.             
  179. struct binary_block
  180.     {
  181.         struct interleaved data[BLOCK_LENGTH];
  182.     };
  183.  
  184.     
  185. /* a song is laid out like this:
  186.     char song_name[SONG_NAME];
  187.     struct sample_info samples[OLD_SAMPLES or NEW_SAMPLES];
  188.     struct song_info song;
  189.     (char sig[4] == "M.K." for new soundtrackers, with NEW_SAMPLES instruments)
  190.     struct block blocks[number of blocks];
  191.     UWORD sample0[length sample0];
  192.     UWORD sample1[length sample1];
  193.         ...
  194.     UWORD samplen[length samplen];     where n=OLD_SAMPLES or NEW_SAMPLES.
  195.  */
  196.  
  197. struct noisetracker_header
  198.     {
  199.         char song_name[SONG_NAME];
  200.         struct binary_sample_info sample_info[NEW_SAMPLES];
  201.         struct binary_song_info song_info;
  202.         ULONG sig;
  203.     };
  204.     
  205. struct old_st_header
  206.     {
  207.         char song_name[SONG_NAME];
  208.         struct binary_sample_info sample_info[OLD_SAMPLES];
  209.         struct binary_song_info song_info;
  210.             /* no sig */
  211.     };
  212.     
  213. struct other_stuff
  214.     {
  215.         ULONG sig;
  216.     };
  217.  
  218. #define MK_SIG(a, b, c, d) ((a<<24) | (b<< 16) | (c<<8) | d)     
  219.  
  220. union header
  221.     {
  222.         struct noisetracker_header nt;
  223.         struct old_st_header st;
  224.         struct other_stuff other;
  225.     } header;
  226.     
  227.  
  228.  
  229.  
  230. struct sample_info dummy =
  231.     {
  232.         "dummy sample",
  233.         0, 0, 0, 0, 0, 0, 0
  234.     };
  235.  
  236. int last_error;
  237.         
  238.     
  239. /* cstring(buffer, maxlength)
  240.  * converts a soundtracker string into a decent cstring
  241.  */
  242.  
  243. char *cstring(CLEAN clear, char buffer[], int maxlength)
  244.     {
  245.     char *st;
  246.     int i;
  247.         for (i = 0; i < maxlength; i++)
  248.             if (buffer[i] == 0)
  249.                 break;
  250.         st = malloc(i+1);
  251.         if (st)
  252.             ToCleanL(clear, free, st);
  253.         else
  254.             return NULL;
  255.         st[i] = 0;
  256.         return strncpy(st, buffer, i);
  257.     }
  258.     
  259.  
  260.  
  261. struct sample_info *extract_sample_info(CLEAN clear, struct binary_sample_info *i)
  262.     {
  263.     struct sample_info *new;
  264.         check_abort();
  265.         if (i->length <= 1)
  266.             return &dummy;
  267.         new = malloc(sizeof(struct sample_info));
  268.         if (new)
  269.             ToCleanL(clear, free, new);
  270.         else
  271.             return NULL;
  272.         new->length = i->length;
  273.         new->finetune = normalize_finetune(i->finetune);
  274.         new->volume = i->volume;
  275.         if (i->rp_start + i->rp_length - 1 > i->length)
  276.             {
  277.                 i->rp_start >>=1;
  278.             }
  279.         new->rp_offset = i->rp_start;
  280.         new->rp_length = i->rp_length;
  281.         new->name = cstring(clear, i->sample_name, SAMPLE_NAME);
  282.         if (new->finetune < 0)
  283.             {
  284.                 last_error = NOT_A_MOD;
  285.                 return NULL;
  286.             }
  287.         else
  288.             return new;
  289.     }
  290.     
  291. int find_max(UBYTE block_number[], int max_index)
  292.     {
  293.     int current, i;
  294.         for (current = -1, i = 0; i < max_index; i++)
  295.             if (block_number[i] > current)
  296.                 current = block_number[i];
  297.             /* a negative return indicates a problem */
  298.         if (current > 127)
  299.             return (-1);
  300.         return current;
  301.     }
  302.  
  303. struct block **map_blocks(CLEAN clear, UBYTE block_number[], int length, struct block array[])
  304.     {
  305.     int i;
  306.     struct block **pters;
  307.         pters = malloc(length * sizeof(struct block *));
  308.         if (pters)
  309.             ToCleanL(clear, free, pters);
  310.         else
  311.             return NULL;
  312.         for (i = 0; i < length; i++)
  313.             pters[i] = array+block_number[i];
  314.         return pters;
  315.     }
  316.  
  317. struct block *allocate_blocks(CLEAN clear, int number)
  318.     {
  319.     struct block *new;
  320.         new = malloc(number * sizeof(struct block));
  321.         if (new)
  322.             ToCleanL(clear, free, new);
  323.         else
  324.             return NULL;
  325.         return new;
  326.     }
  327.         
  328. struct song_info *extract_song_info(CLEAN clear, struct binary_song_info *b)
  329.     {
  330.     struct song_info *new;
  331.         new = malloc(sizeof(struct song_info));
  332.         if (new)
  333.             ToCleanL(clear, free, new);
  334.         else
  335.             return NULL;
  336.         new->length = b->length;
  337.         new->thing = b->thing;
  338.         new->total = find_max(b->block_number, 128)+1;
  339.         if (new->total < 0)
  340.             return NULL;
  341.         new->physical = allocate_blocks(clear, new->total);
  342.         if (!new->physical)
  343.             return NULL;
  344.         new->pblocks = map_blocks(clear, b->block_number, new->length, 
  345.             new->physical);
  346.         if (!new->pblocks)
  347.             return NULL;
  348.         return new;
  349.     }
  350.  
  351.  
  352. /* we will leave that alone for the time being */
  353.     
  354. struct sample_info *instr_channel[NUMBER_TRACKS];
  355. struct sample_info **sample_array;
  356. int current_max;
  357.  
  358. void parse_event(struct binary_event *b, struct event *e, int tn)
  359.     {
  360.     UWORD period;
  361.         e->sample_number = (b->detail[0]&~15) | (b->detail[2]>>4);
  362.         e->sample_number &= 31;
  363.         if (e->sample_number)
  364.             {
  365.                 instr_channel[tn] = sample_array[e->sample_number];
  366.                 if (e->sample_number > current_max)
  367.                     current_max = e->sample_number;
  368.             }
  369.         period = ((b->detail[0]&15)<<8) | b->detail[1];
  370.         e->note = find_note(period, instr_channel[tn]->finetune);
  371.         if (e->note > FINE_PERIOD)
  372.             last_error = NOTE_PROBLEM;
  373.         e->effect = b->detail[2]&15;
  374.         e->parameters = b->detail[3];
  375.     }
  376.     
  377. void parse_block(struct binary_block *b, struct block *d)
  378.     {
  379.     int i, j;
  380.         for (i = 0; i < BLOCK_LENGTH; i++)
  381.             for (j = 0; j < NUMBER_TRACKS; j++)
  382.                 parse_event(&b->data[i].track[j], &d->e[j][i], j);
  383.     }
  384.                 
  385. int read_blocks(CLEAN clear, BPTR f, int total, struct block *first)
  386.     {
  387.     struct binary_block b;
  388.     int i;
  389.         current_max = 0;
  390.         for (i = 0; i < NUMBER_TRACKS; i++)
  391.             instr_channel[i] = sample_array[0];
  392.         for (i = 0; i < total; i++)
  393.             {
  394.                 if (Read(f, &b, sizeof(b)) != sizeof(b))
  395.                     return 0;
  396.                 check_abort();
  397.                 parse_block(&b, first+i);
  398.             }
  399.         return current_max;
  400.     }
  401.  
  402. BOOL allocate_samples(CLEAN clear, struct song *s, int max_sn)
  403.     {
  404.     int i;
  405.     int length;
  406.     UWORD *p, *empty;        
  407.             /* so we don't have to multiply everything by 2
  408.              */
  409.                      
  410.             /* compute the total length
  411.              */
  412.         for (length = 1, i = 1 ; i <= max_sn; i++)
  413.             {
  414.                 if (s->samples[i] != &dummy)
  415.                     length += s->samples[i]->length;
  416.             }
  417.                 
  418.             /* allocate corresponding chip memory 
  419.              */
  420.         p = AllocMem(2 * length, MEMF_CHIP|MEMF_CLEAR);
  421.         if (p)
  422.             ToClean2L(clear, FreeMem, p, 2*length);
  423.         else
  424.             {
  425.                 last_error = OUT_OF_CHIP;
  426.                 return NULL;
  427.             }
  428.         empty = p++;
  429.         dummy.start = empty;
  430.         dummy.length = 1;
  431.         dummy.rp_start = empty;
  432.         dummy.rp_length = 1;
  433.             /* compute addresses information
  434.              */
  435.         for (i = 1; i <= max_sn; i++)
  436.             if (s->samples[i] != &dummy)
  437.                 {
  438.                     s->samples[i]->start = p;
  439.                     if (s->samples[i]->rp_length == 1)
  440.                         s->samples[i]->rp_start = empty;
  441.                     else
  442.                         s->samples[i]->rp_start = p + s->samples[i]->rp_offset;
  443.                     p+= s->samples[i]->length;
  444.                 }
  445.     }
  446.  
  447. BOOL read_sample(CLEAN clear, BPTR f, struct binary_sample_info *b, 
  448.     struct sample_info *s)
  449.     {
  450.         check_abort();
  451.         if (Read(f, s->start, b->length*2) != b->length*2 
  452.             && b->length > 1)
  453.                 {
  454.                     last_error = MISSING_SAMPLE;
  455.                     return TRUE;
  456.                 }
  457.         else
  458.             return TRUE;
  459.     }
  460.  
  461.  
  462. struct song *read_song(BPTR f)
  463.     {
  464.     struct song *s;
  465.     int i, sn, max_sn;
  466.     CLEAN clear;
  467.         last_error = OUT_OF_MEMORY;
  468.         clear = AllocClean(NIL);
  469.         if (!clear)
  470.             mayPanic("Couldn't allocate cleanup");
  471.         s = malloc(sizeof(struct song));
  472.         if (s)
  473.             {
  474.                 s->clear = clear;
  475.                 ToCleanL(clear, free, s);
  476.             }
  477.         else
  478.             {
  479.                 last_error = OUT_OF_MEMORY;
  480.                 return NULL;
  481.             }
  482.         if (Read(f, &header, sizeof(union header)) != sizeof(union header))
  483.             {
  484.                 last_error = NOT_A_MOD;
  485.                 return unload_song(s);
  486.             }
  487.                 /* fast recognize other formats */
  488.         if (header.other.sig == MK_SIG('M','M','D','0')
  489.             || header.other.sig == MK_SIG('S','M','O','D')
  490.             || header.other.sig == MK_SIG('F','C','1','4'))
  491.                 {
  492.                     last_error = UNSUPPORTED;
  493.                     return unload_song(s);
  494.                 }
  495.         if (header.nt.sig == MK_SIG('M','.','K','.'))
  496.             {
  497.                 sn = NEW_SAMPLES;
  498.                 s->info = extract_song_info(clear, &header.nt.song_info);
  499.             }
  500.         else
  501.             {
  502.                 sn = OLD_SAMPLES;
  503.                 s->info = extract_song_info(clear, &header.st.song_info);
  504.                 Seek(f, sizeof(struct old_st_header), OFFSET_BEGINNING);
  505.             }
  506.         if (!s->info)
  507.             return unload_song(s);
  508.  
  509.         s->title = cstring(clear, header.nt.song_name, SONG_NAME);
  510.         if (!s->title)
  511.             return unload_song(s);
  512.  
  513.                 /* so that we don't allocate memory for dummy samples */
  514.         dummy.length = 0;
  515.         for (i = 0; i < NUMBER_SAMPLES; i++)
  516.             s->samples[i] = &dummy;
  517.         for (i = 0; i < sn; i++)
  518.             {
  519.                 s->samples[i+1] = extract_sample_info(clear, 
  520.                     &header.nt.sample_info[i]);
  521.                 if (!s->samples[i+1])
  522.                     return unload_song(s);
  523.             }
  524.         sample_array = s->samples;
  525.         max_sn = read_blocks(clear, f, s->info->total, s->info->physical);
  526.         if (!max_sn)
  527.             return unload_song(s);
  528.         if (!allocate_samples(clear, s, max_sn))
  529.             return unload_song(s);
  530.         for (i = 0; i < max_sn; i++)
  531.             if (!read_sample(clear, f, &header.nt.sample_info[i], s->samples[i+1]))
  532.                 return unload_song(s);
  533.         return s;
  534.     }
  535.  
  536. int load_error(void)
  537.     {
  538.         return last_error;
  539.     }
  540.     
  541. struct song *unload_song(struct song *s)
  542.     {
  543.         if (s)
  544.             CleanUp(s->clear);
  545.         return NULL;
  546.     }
  547.  
  548. struct song *load_song(char *arg)
  549.     {
  550.     BPTR f;
  551.     CLEAN closefile;
  552.     struct song *s;
  553.     static char message[200];
  554.         closefile = AllocClean(NIL);
  555.         if (!arg)
  556.             return NULL;
  557.             /* check the precise length !!! */
  558.         sprintf(message, "Loading %s...", arg);
  559.         temporary_title(message);
  560.         ToClean0L(closefile, restore_title);
  561.         f = Open(arg, MODE_OLDFILE);
  562.         if (f)
  563.             {
  564.                 ToCleanL(closefile, Close, f);
  565.                 s = read_song(f);
  566.             }
  567.         else
  568.             s = NULL;
  569.         CleanUp(closefile);
  570.         return s;
  571.     }
  572.