home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 19 / CD_ASCQ_19_010295.iso / dos / prg / midas / modload.c < prev    next >
C/C++ Source or Header  |  1994-08-06  |  23KB  |  667 lines

  1. /*      MODLOAD.C
  2.  *
  3.  * ProTracker Module loader
  4.  *
  5.  * Copyright 1994 Petteri Kangaslampi and Jarno Paananen
  6.  *
  7.  * This file is part of the MIDAS Sound System, and may only be
  8.  * used, modified and distributed under the terms of the MIDAS
  9.  * Sound System license, LICENSE.TXT. By continuing to use,
  10.  * modify or distribute this file you indicate that you have
  11.  * read the license and understand and accept it fully.
  12. */
  13.  
  14. #include "lang.h"
  15. #include "mtypes.h"
  16. #include "errors.h"
  17. #include "mglobals.h"
  18. #include "mmem.h"
  19. #include "file.h"
  20. #include "sdevice.h"
  21. #include "mplayer.h"
  22. #include "mod.h"
  23. #include "ems.h"
  24. #include "vu.h"
  25.  
  26. #define NULL 0L
  27.  
  28.  
  29.  
  30.  
  31. /****************************************************************************\
  32. *
  33. * Function:     int CompMem(void *a, void *b, size_t numBytes)
  34. *
  35. * Description:  Compares two memory areas
  36. *
  37. * Input:        void *a                 memory area #1
  38. *               void *b                 memory area #2
  39. *               size_t numBytes         number of bytes to compare
  40. *
  41. * Returns:      1 if memory areas are equal, 0 if not
  42. *
  43. \****************************************************************************/
  44.  
  45. static int CompMem(void *a, void *b, size_t numBytes)
  46. {
  47.     uchar       *m1 = a, *m2 = b;
  48.     size_t      i;
  49.  
  50.     for ( i = 0; i < numBytes; i++ )
  51.         if ( m1[i] != m2[i] )
  52.             return 0;
  53.  
  54.     return 1;
  55. }
  56.  
  57.  
  58.  
  59.  
  60. /****************************************************************************\
  61. *
  62. * Function:     void CopyMem(void *dest, void *source, size_t numBytes)
  63. *
  64. * Description:  Copies a memory area
  65. *
  66. * Input:        void *dest              pointer to destination
  67. *               void *source            pointer to source
  68. *               size_t numBytes         number of bytes to copy
  69. *
  70. \****************************************************************************/
  71.  
  72. static void CopyMem(void *dest, void *source, size_t numBytes)
  73. {
  74.     uchar       *src = source, *dst = dest;
  75.     size_t      i;
  76.  
  77.     for ( i = 0; i < numBytes; i++ )
  78.         dst[i] = src[i];
  79. }
  80.  
  81.  
  82.  
  83.  
  84. /* Macro for endianness-swap. DANGEROUS - references the argument x
  85.    twice */
  86. #define SWAP16(x) ( ((x << 8) & 0xFF00) | ( (x >> 8) & 0x00FF) )
  87.  
  88. /* Size of temporary memory area used for avoiding memory fragmentation
  89.    if EMS is used */
  90. #define TEMPSIZE 8192
  91.  
  92. /* Pass error code in variable "error" on, used in modLoadModule(). */
  93. #define MODLOADPASSERROR { modLoadError(SD); PASSERROR(ID_modLoadModule) }
  94.  
  95.  
  96. /****************************************************************************\
  97. *       Module loader buffers and file pointer. These variables are static
  98. *       instead of local so that a separate deallocation can be used which
  99. *       will be called before exiting in error situations
  100. \****************************************************************************/
  101. static fileHandle f;
  102. static int      fileOpened;
  103. static mpModule *mmod;
  104. static ulong    *pattBuf;
  105. static ulong    *trackBuf;
  106. static uchar    *smpBuf;
  107. static void     *tempmem;
  108.  
  109.  
  110.  
  111. /****************************************************************************\
  112. *
  113. * Function:     int modFreeModule(mpModule *module, SoundDevice *SD);
  114. *
  115. * Description:  Deallocates a Protracker module
  116. *
  117. * Input:        mpModule *module        module to be deallocated
  118. *               SoundDevice *SD         Sound Device that has stored the
  119. *                                       samples
  120. *
  121. * Returns:      MIDAS error code
  122. *
  123. \****************************************************************************/
  124.  
  125. int CALLING modFreeModule(mpModule *module, SoundDevice *SD)
  126. {
  127.     int         i, error;
  128.  
  129.     if ( module == NULL )               /* valid module? */
  130.     {
  131.         ERROR(errUndefined, ID_modFreeModule);
  132.         return errUndefined;
  133.     }
  134.  
  135.  
  136.     /* deallocate pattern orders if allocated: */
  137.     if ( module->orders != NULL )
  138.         if ( (error = memFree(module->orders)) != OK )
  139.             PASSERROR(ID_modFreeModule)
  140.  
  141.     /* deallocate instrument used flags is allocated: */
  142.     if ( module->instsUsed != NULL )
  143.         if ( (error = memFree(module->instsUsed)) != OK )
  144.             PASSERROR(ID_modFreeModule)
  145.  
  146.     if ( module->insts != NULL )        /* instruments? */
  147.     {
  148.         for ( i = 0; i < module->numInsts; i++ )
  149.         {
  150.             /* If the instrument has been added to Sound Device, remove
  151.                it, otherwise just deallocate the sample if allocated */
  152.  
  153.             if ( (module->insts[i].sdInstHandle != 0) && (SD != NULL) )
  154.             {
  155.                 if ( (error = SD->RemInstrument(
  156.                     module->insts[i].sdInstHandle)) != OK )
  157.                     PASSERROR(ID_modFreeModule)
  158.             }
  159.             else
  160.                 if ( module->insts[i].sample != NULL )
  161.                     if ( (error = memFree(module->insts[i].sample)) != OK )
  162.                         PASSERROR(ID_modFreeModule)
  163.  
  164.             #ifdef REALVUMETERS
  165.             /* remove VU meter information if used: */
  166.             if ( realVU )
  167.             {
  168.                 if (module->insts[i].sdInstHandle != 0)
  169.                     if ( (error = vuRemove(module->insts[i].sdInstHandle))
  170.                         != OK )
  171.                         PASSERROR(ID_modFreeModule)
  172.             }
  173.             #endif
  174.  
  175.         }
  176.         /* deallocate instrument structures: */
  177.         if ( (error = memFree(module->insts)) != OK )
  178.             PASSERROR(ID_modFreeModule)
  179.     }
  180.  
  181.     if ( (module->patterns != NULL) && (module->pattEMS != NULL) )
  182.     {
  183.         for ( i = 0; i < module->numPatts; i++ )
  184.         {
  185.             if ( module->patterns[i] != NULL )
  186.             {
  187.                 /* if the pattern has been allocate, deallocate it - either
  188.                    from conventional memory or from EMS */
  189.  
  190.                 if ( module->pattEMS[i] == 1 )
  191.                 {
  192.                     if ( (error = emsFree((emsBlock*) module->patterns[i]))
  193.                         != OK )
  194.                         PASSERROR(ID_modFreeModule)
  195.                 }
  196.                 else
  197.                     if ( (error = memFree(module->patterns[i])) != OK )
  198.                         PASSERROR(ID_modFreeModule)
  199.             }
  200.         }
  201.         /* deallocate pattern pointers: */
  202.         if ( (error = memFree(module->patterns)) != OK )
  203.             PASSERROR(ID_modFreeModule)
  204.  
  205.         /* deallocate pattern EMS flags: */
  206.         if ( (error = memFree(module->pattEMS)) != OK )
  207.             PASSERROR(ID_modFreeModule)
  208.     }
  209.  
  210.     /* deallocate the module: */
  211.     if ( (error = memFree(module)) != OK)
  212.         PASSERROR(ID_modFreeModule)
  213.  
  214.     return OK;
  215. }
  216.  
  217.  
  218.  
  219. /****************************************************************************\
  220. *
  221. * Function:     void modLoadError(SoundDevice *SD)
  222. *
  223. * Description:  Stops loading the module, deallocates all buffers and closes
  224. *               the file.
  225. *
  226. * Input:        SoundDevice *SD         Sound Device that has been used for
  227. *                                       loading.
  228. *
  229. \****************************************************************************/
  230.  
  231. static void modLoadError(SoundDevice *SD)
  232. {
  233.     /* Close file if opened. Do not process errors. */
  234.     if ( fileOpened )
  235.         if ( fileClose(f) != OK )
  236.             return;
  237.  
  238.     /* Attempt to deallocate module if allocated. Do not process errors. */
  239.     if ( mmod != NULL )
  240.         if ( modFreeModule(mmod, SD) != OK )
  241.             return;
  242.  
  243.     /* Deallocate buffers if allocated. Do not process errors. */
  244.     if ( pattBuf != NULL )
  245.         if ( memFree(pattBuf) != OK )
  246.             return;
  247.     if ( trackBuf != NULL )
  248.         if ( memFree(trackBuf) != OK )
  249.             return;
  250.     if ( smpBuf != NULL )
  251.         if ( memFree(smpBuf) != OK )
  252.             return;
  253.     if ( tempmem != NULL )
  254.         if ( memFree(tempmem) != OK )
  255.             return;
  256. }
  257.  
  258.  
  259.  
  260. /****************************************************************************\
  261. *
  262. * Function:     int modLoadModule(char *fileName, SoundDevice *SD,
  263. *                   mpModule **module);
  264. *
  265. * Description:  Loads a Protracker module into memory
  266. *
  267. * Input:        char *fileName          name of module file to be loaded
  268. *               SoundDevice *SD         Sound Device which will store the
  269. *                                       samples
  270. *               mpModule **module       pointer to variable which will store
  271. *                                       the module pointer.
  272. *
  273. * Returns:      MIDAS error code.
  274. *               Pointer to module structure is stored in *module.
  275. *
  276. \****************************************************************************/
  277.  
  278. int CALLING modLoadModule(char *fileName, SoundDevice *SD, mpModule **module)
  279. {
  280.     int             error;              /* MIDAS error code */
  281.     modHeader       modh;
  282.     modInstHdr      *modi;
  283.     mpInstrument    *inst;
  284.     mpPattern       *pattData;
  285.  
  286.     ushort          trackLen;
  287.  
  288.     int             i, c, r;
  289.     ushort          chans;
  290.     ushort          numPatts;
  291.     ulong           foffset;
  292.  
  293.     ushort          slength;            /* sample length */
  294.     ushort          loopStart;          /* sample loop start */
  295.     ushort          loopLength;         /* sample loop length */
  296.  
  297.     ulong           maxSmpLength;
  298.     uchar           instx;
  299.     char            temp[4];
  300.  
  301.     void            *p;
  302.  
  303.  
  304.     /* point buffers to NULL and set fileOpened to 0 so that modLoadError()
  305.        can be called at any point: */
  306.     fileOpened = 0;
  307.     mmod = NULL;
  308.     pattBuf = NULL;
  309.     trackBuf = NULL;
  310.     smpBuf = NULL;
  311.     tempmem = NULL;
  312.  
  313.  
  314.     /* Open module file: */
  315.     if ( (error = fileOpen(fileName, fileOpenRead, &f)) != OK )
  316.         MODLOADPASSERROR
  317.  
  318.     /* Allocate memory for the module structure: */
  319.     if ( (error = memAlloc(sizeof(mpModule), (void**) &mmod)) != OK )
  320.         MODLOADPASSERROR
  321.  
  322.     mmod->orders = NULL;                 /* clear module structure so that */
  323.     mmod->insts = NULL;                  /* it can be deallocated with */
  324.     mmod->patterns = NULL;               /* modFree() at any point */
  325.     mmod->pattEMS = NULL;
  326.     mmod->instsUsed = NULL;
  327.  
  328.     /* read Protracker module header: */
  329.     if ( (error = fileRead(f, &modh, sizeof(modHeader))) != OK )
  330.         MODLOADPASSERROR
  331.  
  332.     chans = 0;
  333.  
  334.     /* Check the module signature to determine number of channels: */
  335.  
  336.     if ( CompMem(&modh.sign[0], "M.K.", 4) ) chans = 4;
  337.     if ( CompMem(&modh.sign[0], "M!K!", 4) ) chans = 4;
  338.     if ( CompMem(&modh.sign[0], "FLT4", 4) ) chans = 4;
  339.     if ( CompMem(&modh.sign[0], "OCTA", 4) ) chans = 8;
  340.  
  341.     if ( CompMem(&modh.sign[1], "CHN", 3) )
  342.     {
  343.         /* xCHN, where x is the number of channels */
  344.         chans = modh.sign[0] - '0';
  345.     }
  346.  
  347.     if ( CompMem(&modh.sign[2], "CH", 2) )
  348.     {
  349.         /* xxCHN, where xx is the number of channels */
  350.         chans = (modh.sign[0] - '0') * 10 + (modh.sign[1] - '0');
  351.     }
  352.  
  353.     if ( CompMem(&modh.sign[0], "TDZ", 3) )
  354.     {
  355.         /* TDZx, where x is the number of channels */
  356.         chans = modh.sign[3] - '0';
  357.     }
  358.  
  359.  
  360.     /* If number of channels is undetermined, the signature is invalid. */
  361.     if ( chans == 0 )
  362.     {
  363.         ERROR(errInvalidModule, ID_modLoadModule);
  364.         modLoadError(SD);
  365.         return errInvalidModule;
  366.     }
  367.  
  368.     mmod->numChans = chans;              /* store number of channels */
  369.  
  370.     CopyMem(&mmod->songName[0], &modh.songName[0], 20); /* copy song name */
  371.     mmod->songName[20] = 0;                 /* force terminating '\0' */
  372.     mmod->songLength = modh.songLength;     /* copy song length */
  373.     mmod->numInsts = 31;                    /* set number of instruments */
  374.  
  375.     CopyMem(&mmod->ID, &modh.sign[0], 4);   /* copy module signature */
  376.     mmod->IDnum = idMOD;                    /* Protracker module */
  377.  
  378.  
  379.     for( i = 0; i < mmod->numChans; i++)
  380.     {
  381.         if( ((i & 3) == 0) || ((i & 3) == 3) )
  382.             mmod->chanSettings[i] = -64;
  383.         else
  384.             mmod->chanSettings[i] = 64;
  385.     }
  386.  
  387.     /* find number of patterns in file: */
  388.     numPatts = 0;
  389.     for ( i = 0; i < 128; i++ )         /* search all song data */
  390.         if ( modh.orders[i] >= numPatts )
  391.             numPatts = modh.orders[i] + 1;
  392.  
  393.     mmod->numPatts = numPatts * chans;   /* store number of tracks */
  394.  
  395.     /* allocate memory for pattern orders: */
  396.     if ( (error = memAlloc(mmod->songLength, (void**) &mmod->orders)) != OK )
  397.         MODLOADPASSERROR
  398.  
  399.     /* copy pattern orders */
  400.     CopyMem(mmod->orders, &modh.orders[0], mmod->songLength);
  401.  
  402.     /* allocate memory for pattern (actually track) pointers */
  403.     if ( (error = memAlloc((mmod->numPatts) * sizeof(mpPattern*),
  404.         (void**) &mmod->patterns)) != OK )
  405.         MODLOADPASSERROR
  406.  
  407.     /* allocate memory for pattern EMS flags */
  408.     if ( (error = memAlloc(mmod->numPatts, (void**) &mmod->pattEMS)) != OK )
  409.         MODLOADPASSERROR
  410.  
  411.     for ( i = 0; i < mmod->numPatts; i++ ) /* point all unallocated patterns */
  412.         mmod->patterns[i] = NULL;          /* to NULL for safety */
  413.  
  414.     foffset = sizeof(modHeader);        /* point foffset to first pattern */
  415.  
  416.  
  417.     /* allocate memory for instrument used flags: */
  418.     if ( (error = memAlloc(mmod->numInsts, (void**) &mmod->instsUsed)) != OK )
  419.         MODLOADPASSERROR
  420.  
  421.     /* Mark all instruments unused */
  422.     for ( i = 0; i < mmod->numInsts; i++ )
  423.         mmod->instsUsed[i] = 0;
  424.  
  425.     /* allocate memory for instrument structures: */
  426.     if ( (error = memAlloc(mmod->numInsts * sizeof(mpInstrument),
  427.         (void**) &mmod->insts)) != OK )
  428.         MODLOADPASSERROR
  429.  
  430.     /* clear all instruments and find maximum instrument length: */
  431.     maxSmpLength = 0;
  432.     for ( i = 0; i < mmod->numInsts; i++ )
  433.     {
  434.         mmod->insts[i].sample = NULL;
  435.         mmod->insts[i].sdInstHandle = 0;
  436.         if ( maxSmpLength < ( 2 * SWAP16(modh.instruments[i].slength) ) )
  437.             maxSmpLength = 2 * SWAP16(modh.instruments[i].slength);
  438.     }
  439.  
  440.     /* check that none of the instruments is too long: */
  441.     if ( maxSmpLength > SMPMAX )
  442.     {
  443.         ERROR(errInvalidInst, ID_modLoadModule);
  444.         modLoadError(SD);
  445.         return errInvalidInst;
  446.     }
  447.  
  448.     /* allocate memory for pattern loading buffer */
  449.     if ( (error = memAlloc(chans * 256, (void**) &pattBuf)) != OK )
  450.         MODLOADPASSERROR
  451.  
  452.     /* allocate memory for track conversion buffer */
  453.     if ( (error = memAlloc(256, (void**) &trackBuf)) != OK )
  454.         MODLOADPASSERROR
  455.  
  456.     /* convert all patterns: */
  457.  
  458.     for ( i = 0; i < numPatts; i++ )
  459.     {
  460.         /* seek to pattern beginning */
  461.         if ( (error = fileSeek(f, foffset, fileSeekAbsolute)) != OK )
  462.             MODLOADPASSERROR
  463.  
  464.         /* read pattern data */
  465.         if ( (error = fileRead(f, pattBuf, 256 * chans)) != OK )
  466.             MODLOADPASSERROR
  467.  
  468.         /* convert all tracks of the pattern */
  469.         for ( c = 0; c < chans; c++ )
  470.         {
  471.             /* copy track data to track buffer: */
  472.             for ( r = 0; r < 64; r++)
  473.                 trackBuf[r] = pattBuf[r * chans + c];
  474.  
  475.             /* check used instruments */
  476.             for ( r = 0; r < 64; r++)
  477.             {
  478.                 instx = ((trackBuf[r] & 0x10) | ((trackBuf[r] >> 20) & 0xF));
  479.                 if ((instx > 0) && (instx < 32))
  480.                     mmod->instsUsed[instx-1] = 1;
  481.             }
  482.  
  483.             /* convert track to internal format: */
  484.             if ( (error = modConvertTrack(trackBuf, 0, &trackLen)) != OK )
  485.                 MODLOADPASSERROR
  486.  
  487.             if ( useEMS == 1 )          /* is EMS memory used? */
  488.             {
  489.                 /* try to allocate EMS memory for track */
  490.                 if ( (error = emsAlloc(trackLen, (emsBlock**) &p)) != OK )
  491.                 {
  492.                     /* failed - if only EMS memory should be used, or the
  493.                        error is other than out of EMS memory, pass the error
  494.                        on */
  495.                     if ( (forceEMS == 1) || (error != errOutOfEMS) )
  496.                         MODLOADPASSERROR
  497.                     else
  498.                     {
  499.                         /* track not in EMS */
  500.                         mmod->pattEMS[i * chans + c] = 0;
  501.  
  502.                         /* try to allocate conventional memory instead */
  503.                         if ( (error = memAlloc(trackLen, &p)) != OK )
  504.                             MODLOADPASSERROR
  505.                         pattData = p;
  506.                     }
  507.                 }
  508.                 else
  509.                 {
  510.                     /* EMS memory allocated succesfully - track in EMS */
  511.                     mmod->pattEMS[i * chans + c] = 1;
  512.  
  513.                     /* map EMS block to conventional memory and point pattData
  514.                        to the memory area: */
  515.                     if ( (error = emsMap((emsBlock*) p, (void**) &pattData))
  516.                         != OK )
  517.                         MODLOADPASSERROR
  518.                 }
  519.             }
  520.             else
  521.             {
  522.                 /* EMS memory not in use - allocate conventional memory */
  523.                 mmod->pattEMS[i * chans + c] = 0;
  524.  
  525.                 if ( (error = memAlloc(trackLen, &p)) != OK )
  526.                     MODLOADPASSERROR
  527.  
  528.                 pattData = p;
  529.             }
  530.  
  531.             mmod->patterns[i * chans + c] = p;
  532.  
  533.             /* copy track data from buffer to the correct memory area */
  534.             CopyMem(pattData, trackBuf, trackLen);
  535.         }
  536.  
  537.         foffset += chans * 256;         /* point foffset to next pattern */
  538.     }
  539.  
  540.     /* deallocate pattern loading buffers: */
  541.     if ( (error = memFree(trackBuf)) != OK )
  542.         MODLOADPASSERROR
  543.     trackBuf = NULL;
  544.  
  545.     if ( (error = memFree(pattBuf)) != OK )
  546.         MODLOADPASSERROR
  547.     pattBuf = NULL;
  548.  
  549.  
  550.     /* If EMS is used, allocate TEMPSIZE bytes of memory before the sample
  551.        buffer and deallocate it after allocating the sample buffer to
  552.        minimize memory fragmentation */
  553.     if ( useEMS )
  554.     {
  555.         if ( (error = memAlloc(TEMPSIZE, &tempmem)) != OK )
  556.             MODLOADPASSERROR
  557.     }
  558.  
  559.     /* allocate memory for sample loading buffer: */
  560.     if ( (error = memAlloc(maxSmpLength, (void**) &smpBuf)) != OK )
  561.         MODLOADPASSERROR
  562.  
  563.     if ( useEMS )
  564.     {
  565.         if ( (error = memFree(tempmem)) != OK )
  566.             MODLOADPASSERROR
  567.         tempmem = NULL;
  568.     }
  569.  
  570.  
  571.     /* point file offset to start of samples */
  572.     foffset = (ulong) (chans * 256) * (ulong) numPatts + sizeof(modHeader);
  573.  
  574.     for ( i = 0; i < mmod->numInsts; i++ )
  575.     {
  576.         inst = &mmod->insts[i];          /* point inst to current instrument
  577.                                             structure */
  578.  
  579.         modi = &modh.instruments[i];    /* point modi to current Protracker
  580.                                             module instrument */
  581.  
  582.         /* Convert sample length, loop start and loop end. They are stored
  583.            as big-endian words, and refer to number of words instead of
  584.            bytes */
  585.         slength = 2 * SWAP16(modi->slength);
  586.         loopStart = 2 * SWAP16(modi->loopStart);
  587.         loopLength = 2 * SWAP16(modi->loopLength);
  588.  
  589.         CopyMem(&inst->iname[0], &modi->iname[0], 22);  /* copy inst name */
  590.         inst->iname[22] = 0;            /* force terminating '\0' */
  591.         inst->loopStart = loopStart;    /* copy sample loop start */
  592.         inst->loopEnd = loopStart + loopLength; /* sample loop end */
  593.  
  594.         /* If sample loop end is past byte 2, the sample is looping
  595.            (Protracker uses loop start = 0, length = 2 for no loop,
  596.            Fasttracker start = 0, end = 0 */
  597.         if (inst->loopEnd > 2)
  598.         {
  599.             inst->looping = 1;
  600.             inst->length = inst->loopEnd;  /* use loop end as sample length */
  601.         }                               /* if looping to avoid loading */
  602.         else                            /* unnecessary sample data */
  603.         {
  604.             inst->looping = 0;
  605.             inst->loopEnd = 0;          /* set loop end to 0 if no loop */
  606.             inst->length = slength;     /* use sample length */
  607.         }
  608.  
  609.         inst->volume = modi->volume;        /* copy default volume */
  610.         inst->finetune = modi->finetune;    /* copy finetune */
  611.  
  612.         if (mmod->instsUsed[i] == 1)        /* if not used, don't load */
  613.         {
  614.             if ( inst->length != 0 )        /* is there a sample for this inst? */
  615.             {
  616.                 /* seek to sample start position: */
  617.                 if ( (error = fileSeek(f, foffset, fileSeekAbsolute)) != OK )
  618.                     MODLOADPASSERROR
  619.  
  620.                 /* read sample to buffer: */
  621.                 if ( (error = fileRead(f, smpBuf, inst->length)) != OK )
  622.                     MODLOADPASSERROR
  623.             }
  624.  
  625.             /* Point inst->sample to NULL, as the instrument is not available
  626.                - only the Sound Device has it */
  627.             inst->sample = NULL;
  628.  
  629.             /* convert sample from signed to unsigned: */
  630.             if ( (error = modConvertSample(smpBuf, inst->length)) != OK )
  631.                 MODLOADPASSERROR
  632.  
  633.             /* add the instrument to Sound Device: */
  634.             error = SD->AddInstrument(smpBuf, smp8bit, inst->length,
  635.                 inst->loopStart, inst->loopEnd, inst->volume, inst->looping,
  636.                 &inst->sdInstHandle);
  637.             if ( error != OK )
  638.                 MODLOADPASSERROR
  639.  
  640.             #ifdef REALVUMETERS
  641.             /* if real VU meters are used, prepare VU meter information
  642.                 for this instrument */
  643.             if ( realVU )
  644.             {
  645.                 if ( (error = vuPrepare(inst->sdInstHandle, smpBuf, inst->length,
  646.                     inst->loopStart, inst->loopEnd)) != OK )
  647.                     MODLOADPASSERROR
  648.             }
  649.             #endif
  650.         }
  651.         foffset += slength;             /* point foffset to next sample */
  652.     }
  653.  
  654.     /* deallocate sample loading buffer: */
  655.     if ( (error = memFree(smpBuf)) != OK )
  656.         MODLOADPASSERROR
  657.     smpBuf = NULL;
  658.  
  659.  
  660.     if ( (error = fileClose(f)) != OK )
  661.         MODLOADPASSERROR
  662.     fileOpened = 0;
  663.  
  664.     *module = mmod;                     /* return module ptr in *module */
  665.     return OK;
  666. }
  667.