home *** CD-ROM | disk | FTP | other *** search
/ CD-ROM Aktief 1995 #3 / CDA3.iso / sound / tnypl211.zip / MODLOAD.C < prev    next >
C/C++ Source or Header  |  1994-06-21  |  7KB  |  240 lines

  1. /*  modload.c - Tiny MOD Player V2.11 for Watcom C/C++ and DOS/4GW
  2.  
  3.     Module and Sample file loader routines.
  4.  
  5.     Copyright 1993,94 Carlos Hasan
  6. */
  7.  
  8. #include <stdio.h>
  9. #include <conio.h>
  10. #include <malloc.h>
  11. #include <io.h>
  12. #include <fcntl.h>
  13. #include "modplay.h"
  14.  
  15. /* MOD FileFormat */
  16.  
  17. #define ID_MK   0x2E4B2E4D
  18. #define ID_FLT4 0x34544C46
  19. #define ID_6CHN 0x4E484336
  20. #define ID_8CHN 0x4E484338
  21.  
  22. typedef struct {
  23.     byte        SampleName[22];
  24.     word        Length;
  25.     byte        FineTune;
  26.     byte        Volume;
  27.     word        LoopStart;
  28.     word        LoopLength;
  29. } MODSample;
  30.  
  31. typedef struct {
  32.     byte        SongName[20];
  33.     MODSample   Samples[31];
  34.     byte        OrderLength;
  35.     byte        ReStart;
  36.     byte        Orders[128];
  37.     dword       Sign;
  38. } MODHeader;
  39.  
  40. /* MOD PeriodTable */
  41. static word PeriodTable[12*7] = {
  42.     3424,3232,3048,2880,2712,2560,2416,2280,2152,2032,1920,1812,
  43.     1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,906,
  44.     856,808,762,720,678,640,604,570,538,508,480,453,
  45.     428,404,381,360,339,320,302,285,269,254,240,226,
  46.     214,202,190,180,170,160,151,143,135,127,120,113,
  47.     107,101,95,90,85,80,75,71,67,63,60,56,
  48.     53,50,47,45,42,40,37,35,33,31,30,28 };
  49.  
  50. /* WAV fileformat */
  51.  
  52. #define ID_RIFF 0x46464952
  53. #define ID_WAVE 0x45564157
  54. #define ID_FMT  0x20746D66
  55. #define ID_DATA 0x61746164
  56.  
  57. typedef struct {
  58.     dword   RIFFMagic;
  59.     dword   FileLength;
  60.     dword   FileType;
  61.     dword   FormMagic;
  62.     dword   FormLength;
  63.     word    SampleFormat;
  64.     word    NumChannels;
  65.     dword   PlayRate;
  66.     dword   BytesPerSec;
  67.     word    Pad;
  68.     word    BitsPerSample;
  69.     dword   DataMagic;
  70.     dword   DataLength;
  71. } WAVHeader;
  72.  
  73.  
  74. /* MOD Loader Routine */
  75.  
  76. #define Swap(w) (((dword)(w&0xff))<<8|((dword)(w>>8)))
  77.  
  78. Module *MODLoadModule(char *Path)
  79. {
  80.     int handle,NumTracks,NumPatts,i,j;
  81.     word Note,Period,Inst,Effect;
  82.     dword Length,LoopStart,LoopLength;
  83.     MODHeader Header;
  84.     MODSample *Sample;
  85.     Module *Song;
  86.     byte *Patt;
  87.  
  88.     if ((handle = open(Path,O_RDONLY | O_BINARY)) == -1)
  89.         return NULL;
  90.  
  91.     if (read(handle,&Header,sizeof(Header)) != sizeof(Header)) {
  92.         close(handle);
  93.         return NULL;
  94.     }
  95.  
  96.     if ((Header.Sign == ID_MK) || (Header.Sign == ID_FLT4))
  97.         NumTracks = 4;
  98.     else if (Header.Sign == ID_6CHN)
  99.         NumTracks = 6;
  100.     else if (Header.Sign == ID_8CHN)
  101.         NumTracks = 8;
  102.     else {
  103.         close(handle);
  104.         return NULL;
  105.     }
  106.  
  107.     if ((Song = calloc(1,sizeof(Module))) == NULL) {
  108.         close(handle);
  109.         return NULL;
  110.     }
  111.  
  112.     Song->NumTracks = NumTracks;
  113.     Song->OrderLength = Header.OrderLength;
  114.     for (NumPatts = i = 0; i < 128; i++) {
  115.         Song->Orders[i] = Header.Orders[i];
  116.         if (NumPatts < Header.Orders[i])
  117.             NumPatts = Header.Orders[i];
  118.     }
  119.     NumPatts++;
  120.  
  121.     for (i = 0; i < NumPatts; i++) {
  122.         if ((Song->Patterns[i] = malloc(256*NumTracks)) == NULL) {
  123.             MODFreeModule(Song);
  124.             close(handle);
  125.             return NULL;
  126.         }
  127.         if (read(handle,Song->Patterns[i],256*NumTracks) != 256*NumTracks) {
  128.             MODFreeModule(Song);
  129.             close(handle);
  130.             return NULL;
  131.         }
  132.         for (Patt = Song->Patterns[i], j = 0; j < 64*NumTracks; Patt += 4, j++) {
  133.             Period = ((word)(Patt[0] & 0x0F) << 8) | (Patt[1]);
  134.             Inst = (Patt[0] & 0xF0) | (Patt[2] >> 4);
  135.             Effect = ((word)(Patt[2] & 0x0F) << 8) | (Patt[3]);
  136.             for (Note = 0; Note < 12*7; Note++)
  137.                 if (Period >= PeriodTable[Note]) break;
  138.             if (Note == 12*7) Note = 0; else Note++;
  139.             Patt[0] = Note;
  140.             Patt[1] = Inst;
  141.             Patt[2] = Effect & 0xFF;
  142.             Patt[3] = Effect >> 8;
  143.         }
  144.     }
  145.  
  146.     for (i = 1; i <= 31; i++) {
  147.         Sample = &Header.Samples[i-1];
  148.         if (Sample->Length) {
  149.             Length = Swap(Sample->Length) << 1;
  150.             LoopStart = Swap(Sample->LoopStart) << 1;
  151.             LoopLength = Swap(Sample->LoopLength) << 1;
  152.             if ((Song->SampPtr[i] = malloc(Length)) == NULL) {
  153.                 MODFreeModule(Song);
  154.                 close(handle);
  155.                 return NULL;
  156.             }
  157.             if ((unsigned)read(handle,Song->SampPtr[i],Length) != Length) {
  158.                 MODFreeModule(Song);
  159.                 close(handle);
  160.                 return NULL;
  161.             }
  162.             if (LoopLength <= 2) {
  163.                 Song->SampLoop[i] = Song->SampPtr[i] + Length;
  164.                 Song->SampEnd[i] = Song->SampLoop[i];
  165.             }
  166.             else {
  167.                 Song->SampLoop[i] = Song->SampPtr[i] + LoopStart;
  168.                 Song->SampEnd[i] = Song->SampLoop[i] + LoopLength;
  169.             }
  170.             Song->SampVolume[i] = Sample->Volume;
  171.         }
  172.     }
  173.  
  174.     close(handle);
  175.     return Song;
  176. }
  177.  
  178. void MODFreeModule(Module *Song)
  179. {
  180.     int i;
  181.     if (Song) {
  182.         for (i = 0; i < 128; i++)
  183.             if (Song->Patterns[i]) free(Song->Patterns[i]);
  184.         for (i = 1; i <= 31; i++)
  185.             if (Song->SampPtr[i]) free(Song->SampPtr[i]);
  186.         free(Song);
  187.     }
  188. }
  189.  
  190.  
  191. /* RIFF/WAV Loader Routine */
  192.  
  193. Sample *MODLoadSample(char *Path)
  194. {
  195.     int handle;
  196.     WAVHeader Header;
  197.     Sample *Instr;
  198.     byte *ptr;
  199.     dword len;
  200.  
  201.     if ((handle = open(Path,O_RDONLY | O_BINARY)) == -1)
  202.         return NULL;
  203.     if (read(handle,&Header,sizeof(Header)) != sizeof(Header)) {
  204.         close(handle);
  205.         return NULL;
  206.     }
  207.     if (Header.RIFFMagic != ID_RIFF || Header.FileType != ID_WAVE ||
  208.         Header.FormMagic != ID_FMT || Header.DataMagic != ID_DATA ||
  209.         Header.SampleFormat != 1 || Header.NumChannels != 1 ||
  210.         Header.BitsPerSample != 8) {
  211.         close(handle);
  212.         return NULL;
  213.     }
  214.     if ((Instr = malloc(sizeof(Sample)+Header.DataLength)) == NULL) {
  215.         close(handle);
  216.         return NULL;
  217.     }
  218.     Instr->Period = (8363L*428L)/Header.PlayRate;
  219.     Instr->Volume = 64;
  220.     Instr->Length = Header.DataLength;
  221.     Instr->Data = (byte*)(Instr+1);
  222.     if ((unsigned)read(handle,Instr->Data,Instr->Length) != Instr->Length) {
  223.         free(Instr);
  224.         close(handle);
  225.         return NULL;
  226.     }
  227.     close(handle);
  228.  
  229.     for (ptr = Instr->Data, len = Instr->Length; len; len--)
  230.         *ptr++ ^= 0x80;
  231.  
  232.     return Instr;
  233. }
  234.  
  235. void MODFreeSample(Sample *Instr)
  236. {
  237.     if (Instr) free(Instr);
  238. }
  239.  
  240.