/* VU.H * * Real VU meter routines * * $Id: vu.c,v 1.2 1997/01/16 18:41:59 pekangas Exp $ * * Copyright 1996,1997 Housemarque Inc. * * This file is part of the MIDAS Sound System, and may only be * used, modified and distributed under the terms of the MIDAS * Sound System license, LICENSE.TXT. By continuing to use, * modify or distribute this file you indicate that you have * read the license and understand and accept it fully. */ #include "lang.h" #include "mtypes.h" #include "errors.h" #include "mmem.h" #include "sdevice.h" #include "vu.h" #include "mutils.h" RCSID(const char *vu_rcsid = "$Id: vu.c,v 1.2 1997/01/16 18:41:59 pekangas Exp $";) /* VU meter calculation block size in bytes: */ #define VUBLOCK 128 /* Amount to shift right to convert from bytes to blocks: (log2 VUBLOCK) */ #define VUBSHIFT 7 sdSample *vuSamples; /* VU sample information */ /****************************************************************************\ * * Function: int vuInit(void); * * Description: Initializes VU-meters, allocating room for MAXSAMPLES * samples. * * Returns: MIDAS error code * \****************************************************************************/ int CALLING vuInit(void) { int error, i; /* Allocate memory for sample information structures: */ if ( (error = memAlloc(MAXSAMPLES * sizeof(sdSample), (void**) &vuSamples)) != OK ) PASSERROR(ID_vuInit) /* Point all sample VU information initially to NULL to mark it unallocated: */ for ( i = 0; i < MAXSAMPLES; i++ ) vuSamples[i].sample = NULL; return OK; } /****************************************************************************\ * * Function: int vuClose(void); * * Description: Uninitializes VU-meters * * Returns: MIDAS error code * \****************************************************************************/ int CALLING vuClose(void) { int error, i; /* Deallocate all sample VU information that is still allocated: */ for ( i = 0; i < MAXSAMPLES; i++ ) { if ( vuSamples[i].sample != NULL ) { if ( (error = memFree(vuSamples[i].sample)) != OK ) PASSERROR(ID_vuClose) vuSamples[i].sample = NULL; } } /* Deallocate sample information structures: */ if ( (error = memFree(vuSamples)) != OK ) PASSERROR(ID_vuClose); return OK; } /****************************************************************************\ * * Function: int vuPrepare(sdSample *sample, unsigned sampleNumber); * * Description: Prepares the VU information for a sample * * Input: sdSample *sample pointer to Sound Device sample * structure for this sample * unsigned sampleNumber sample number (0 - (MAXSAMPLES-1)), * usually sound device sample handle * * Returns: MIDAS error code. * \****************************************************************************/ int CALLING vuPrepare(sdSample *sample, unsigned sampleNumber) { sdSample *vuSample = &vuSamples[sampleNumber]; int error; uchar *src, *dest; int min, max; unsigned i, bleft; /* Copy sample information: */ mMemCopy(vuSample, sample, sizeof(sdSample)); /* If there is no sample data or the sample type is unknown, mark there is no VU-meter information for this sample and exit: */ if ( (vuSample->sampleLength == 0) || (vuSample->sampleType != smp8bit) || (vuSample->samplePos != sdSmpConv) ) { vuSample->sample = NULL; return OK; } /* FIXME - only 8-bit samples supported! */ /* Allocate memory for VU information: */ if ( (error = memAlloc((vuSample->sampleLength + (VUBLOCK-1)) >> VUBSHIFT, (void**) &vuSample->sample)) != OK ) PASSERROR(ID_vuPrepare) /* Point dest to destination buffer and src to sample data: */ dest = vuSample->sample; src = sample->sample; bleft = sample->sampleLength; /* Process all VU information blocks: */ while ( bleft ) { /* Process VUBLOCK bytes maximum: */ if ( bleft > VUBLOCK ) i = VUBLOCK; else i = bleft; /* Decrease bytes left: */ bleft -= i; /* Reset minimum and maximum values found: */ min = 255; max = 0; /* Go through all sample bytes belonging to this block to find the minimum and maximum values: */ while ( i ) { if ( *src < min ) min = *src; if ( *src > max ) max = *src; src++; i--; } /* Calculate VU-meter value for this block ((max-min)/4, rounded up), and store it in *dest: */ *(dest++) = (uchar) ((max - min + 2) / 4); } return OK; } /****************************************************************************\ * * Function: int vuRemove(unsigned sampleNumber); * * Description: Removes and deallocates the VU information for a sample * * Input: unsigned sampleNumbe sample number * * Returns: MIDAS error code * \****************************************************************************/ int CALLING vuRemove(unsigned sampleNumber) { int error; /* Deallocate VU information for this sample if allocated: */ if ( vuSamples[sampleNumber].sample != NULL ) { if ( (error = memFree(vuSamples[sampleNumber].sample)) != OK ) PASSERROR(ID_vuRemove) } /* Mark VU information unallocated: */ vuSamples[sampleNumber].sample = NULL; return OK; } /****************************************************************************\ * * Function: int vuMeter(unsigned sampleNumber, ulong rate, * unsigned position, unsigned volume, unsigned *meter); * * Description: Calculates the VU-meter value (0-64) for the next 1/50th of * a second * * Input: unsigned sampleNumber sample number * ulong rate playing rate * unsigned position sample playing position * unsigned volume playing volume (0-64) * unsigned *meter pointer to VU-meter value * * Returns: MIDAS error code. * VU-meter value (0-64) is stored in *meter * \****************************************************************************/ int CALLING vuMeter(unsigned sampleNumber, ulong rate, unsigned position, unsigned volume, unsigned *meter) { sdSample *sample = &vuSamples[sampleNumber]; unsigned clippos; /* Make sure that there is VU information for this sample: */ if ( (sample->sample == NULL) || (sampleNumber >= MAXSAMPLES) ) { *meter = 0; return OK; } /* Make sure the position is inside the sample: */ if ( position >= sample->sampleLength ) clippos = sample->sampleLength - 1; else clippos = position; /* Just take the VU meter value for current block and scale it with volume (FIXME?) */ *meter = ((unsigned) sample->sample[clippos >> VUBSHIFT]) * volume / 64; return OK; } /* * $Log: vu.c,v $ * Revision 1.2 1997/01/16 18:41:59 pekangas * Changed copyright messages to Housemarque * * Revision 1.1 1996/05/22 20:49:33 pekangas * Initial revision * */