thraudioproc.c

来自「DSP体系结构实现与应用源代码」· C语言 代码 · 共 329 行

C
329
字号
/*
 *  Copyright 2003 by Texas Instruments Incorporated.
 *  All rights reserved. Property of Texas Instruments Incorporated.
 *  Restricted rights to use, duplicate or disclose this code are
 *  granted through contract.
 *
 */
/* "@(#) ReferenceFrameworks 2.20.00.08 07-18-03 (swat-f02)" */
/*
 *  ======== thrAudioproc.c ========
 *
 *  Static and dynamic initialization of thread Audioproc,
 *  and its runtime procedure
 */
#include <std.h>
#include <pip.h>
#include <utl.h>            /* debug/diagnostics utility functions */
#include <dsplib.h>
#include <intrindefs.h>

#include "appResources.h"   /* application-wide common info */
#include "appThreads.h"     /* thread-wide common info */
#include "vol.h"            /* interface for VOL algorithm */
#include "thrAudioproc.h"   /* definition of thrAudioproc objects */

// 5 band FIR equalizer 
Void FIR_equalizer(DATA *in, DATA *out);

// declaration of the data buffers used in the fir() in dsplib
#pragma DATA_SECTION(dataBuf0, ".dataBuf0");
#pragma DATA_SECTION(dataBuf1, ".dataBuf1");
#pragma DATA_SECTION(dataBuf2, ".dataBuf2");
#pragma DATA_SECTION(dataBuf3, ".dataBuf3");
#pragma DATA_SECTION(dataBuf4, ".dataBuf4");

DATA dataBuf0[FILTORDER0];
DATA dataBuf1[FILTORDER1];
DATA dataBuf2[FILTORDER2];
DATA dataBuf3[FILTORDER3];
DATA dataBuf4[FILTORDER4];

// pointers to the delay buffers for fir()
DATA *dbptr0 = &dataBuf0[0];
DATA *dbptr1 = &dataBuf1[0];
DATA *dbptr2 = &dataBuf2[0];
DATA *dbptr3 = &dataBuf3[0];
DATA *dbptr4 = &dataBuf4[0];

// filter coefficients used in the 5 band equalizer
#pragma DATA_SECTION(filterBand0, ".filterBand0");
#pragma DATA_SECTION(filterBand1, ".filterBand1");
#pragma DATA_SECTION(filterBand2, ".filterBand2");
#pragma DATA_SECTION(filterBand3, ".filterBand3");
#pragma DATA_SECTION(filterBand4, ".filterBand4");

#pragma DATA_SECTION(audioBuffer, ".audioBuffer");
DATA audioBuffer[FRAMELEN * NUMBANDS];

DATA filterBand0[FILTORDER0] = {
     -212,     -6,     82,    211,    340,    420,    408,    285,     71,
     -175,   -371,   -436,   -327,    -58,    291,    594,    720,    576,
      160,   -430,  -1001,  -1318,  -1171,   -445,    828,   2461,   4147,
     5535,   6317,   6317,   5535,   4147,   2461,    828,   -445,  -1171,
    -1318,  -1001,   -430,    160,    576,    720,    594,    291,    -58,
     -327,   -436,   -371,   -175,     71,    285,    408,    420,    340,
      211,     82,     -6,   -212
};


DATA filterBand1[FILTORDER1] = {
     -132,    254,    281,    141,    -83,   -152,    -45,    -32,   -270,
     -448,   -101,    676,   1101,    546,   -577,  -1148,   -661,    105,
      109,   -444,   -201,   1399,   2785,   1663,  -1996,  -5036,  -4002,
      941,   5560,   5560,    941,  -4002,  -5036,  -1996,   1663,   2785,
     1399,   -201,   -444,    109,    105,   -661,  -1148,   -577,    546,
     1101,    676,   -101,   -448,   -270,    -32,    -45,   -152,    -83,
      141,    281,    254,   -132
};

DATA filterBand2[FILTORDER2] = {
      159,    287,   -258,   -170,    182,    132,    -67,     64,   -184,
     -355,    500,    667,   -778,   -873,    877,    831,   -668,   -437,
       83,   -332,    849,   1392,  -1990,  -2559,   3119,   3592,  -3991,
    -4260,   4404,   4404,  -4260,  -3991,   3592,   3119,  -2559,  -1990,
     1392,    849,   -332,     83,   -437,   -668,    831,    877,   -873,
     -778,    667,    500,   -355,   -184,     64,    -67,    132,    182,
     -170,   -258,    287,    159
};


DATA filterBand3[FILTORDER3] = {
      332,   -195,    -63,    313,   -289,     47,     80,     44,   -115,
     -201,    680,   -642,   -179,   1095,  -1122,    189,    678,   -611,
       61,   -204,   1151,  -1379,   -437,   3210,  -3899,    793,   3965,
    -5922,   2813,   2813,  -5922,   3965,    793,  -3899,   3210,   -437,
    -1379,   1151,   -204,     61,   -611,    678,    189,  -1122,   1095,
     -179,   -642,    680,   -201,   -115,     44,     80,     47,   -289,
      313,    -63,   -195,    332
};

DATA filterBand4[FILTORDER4] = {
     -240,    191,   -189,    121,      8,   -169,    313,   -385,    349,
     -200,    -23,    245,   -380,    360,   -166,   -155,    499,   -728,
      725,   -437,    -89,    701,  -1179,   1290,   -861,   -152,   1638,
    -3343,   4925,  -6044,   6447,  -6044,   4925,  -3343,   1638,   -152,
     -861,   1290,  -1179,    701,    -89,   -437,    725,   -728,    499,
     -155,   -166,    360,   -380,    245,    -23,   -200,    349,   -385,
      313,   -169,      8,    121,   -189,    191,   -240
};

/*
 *  Initialization of the thread resources structure:
 *  NULL for algorithm handles, addresses of appropriate
 *  pipe objects for input and output pipes,
 *  NULL for globally visible temporary pointers to pipe frames,
 *  addresses of intermediate buffers for this thread,
 *  and everything else thread-specific.
 */
ThrAudioproc thrAudioproc[ NUMCHANNELS ] = {
    { /* channel #0 */
        /* algorithm handle(s) (to be initialized in runtime) */
        {NULL, NULL, NULL, NULL, NULL}, /* algVOL */

        /* input pipe(s) */
        &pipRx,                /* pipIn */

        /* output pipe(s) */
        &pipTx,                /* pipOut */

        /* buffer(s) */
        {bufAudioproc0, bufAudioproc1, bufAudioproc2, bufAudioproc3, bufAudioproc4}

        /* everything else private for the thread */

    }, /* end channel # 0 */
};

/*
 *  Dynamic part of thread initialization
 */

/*
 *  ========= thrAudioprocInit ========
 *  Initialization of data structures for the thread(s), called from
 *  appThreads.c:thrInit() at init time.
 *
 *  Here we create one instance of FIR algorithm per channel and
 *  one instance of VOL algorithm per channel. In a loop, we create
 *  parameters for algorithm instance for each channel by using the
 *  default parameters and modifying fields that are different.
 *  (If the parameters are the same across channels, they can be
 *  created outside of the loop.)
 */
Void thrAudioprocInit( Void )
{
    /* declaration of volume parameter structure */
    VOL_Params volParams;
    Int i;
    Int j;

	// reset the data buffers for the filters
	/*for (i = 0; i < FILTORDER4; i++) {
		if(i < FILTORDER0){
			dataBuf0[i] = 0;
			dataBuf1[i] = 0;
			dataBuf2[i] = 0;
			dataBuf3[i] = 0;
		}
		dataBuf4[i] = 0;
	}*/

    for (i = 0; i < NUMCHANNELS; i++) {
        /*create parameters structure for VOL algorithm*/
		for ( j = 0; j < NUMBANDS; j++ ) {
			volParams = VOL_PARAMS;             /* default parameters */
        	volParams.frameSize  = FRAMELEN;    /* size in samples */
        	volParams.gainPercentage = 0;     /* default gain */

        	/* create instance, confirm creation success, show memory usage */
        	thrAudioproc[i].algVOL[j] = VOL_create( &VOL_IVOL, &volParams );
        	UTL_assert( thrAudioproc[i].algVOL[j] != NULL );
        	UTL_showAlgMem( thrAudioproc[i].algVOL[j] );
		}
    }
}

/*
 *  Runtime thread code, invoked by the appropriate SWI object
 *  every time the object is posted
 */

/*
 *  ========= thrAudioprocRun ========
 *  The "body" of the swiAudioproc0, swiAudioproc1,... threads.
 *
 *  The single argument of this function is the channel number:
 *  0, 1, 2 etc. up to NUM_CHANNELS - 1. All the SWI objects
 *  that invoke this function pass the channel number as the
 *  argument.
 *
 *  Based on the channel number, the thread -- the procedure --
 *  decides which thread resource object to access.
 */
Void thrAudioprocRun( Arg aChan )
{
    DATA 	*src;
    DATA	*dst;
    Int     size;       /* in samples */
    Int     chan;

    /*
     *  cast 'Arg' types to 'Int'. This is required on 55x large data model
     *  since Arg is not the same size as Int and Ptr in that model.
     *  On all other devices (54x, 55x small, 6x) ArgToInt is a simple cast
     */
    chan = ArgToInt( aChan );

    /*
     *  Check that the preconditions are met, that is the in-pipe
     *  has a ready-to-consume buffer of data and the out-pipe
     *  has a free buffer, in other words that this thread has
     *  not been posted in error.
     */
    UTL_assert( PIP_getReaderNumFrames( thrAudioproc[chan].pipIn  ) > 0 );
    UTL_assert( PIP_getWriterNumFrames( thrAudioproc[chan].pipOut ) > 0 );

    /* get the full buffer from the input pipe */
    PIP_get( thrAudioproc[chan].pipIn );
    src = (DATA *)PIP_getReaderAddr( thrAudioproc[chan].pipIn );
    /* get the size in samples (the function below returns it in words) */
    size = sizeInSamples( PIP_getReaderSize( thrAudioproc[chan].pipIn ) );

    /* get the empty buffer from the out-pipe */
    PIP_alloc( thrAudioproc[chan].pipOut );
    dst = (DATA *)PIP_getWriterAddr( thrAudioproc[chan].pipOut );

	// Start measuring execution time
	UTL_stsStart(stsTime0);
	// perform the 5 band FIR equalization operation
	FIR_equalizer(src, dst);
	// Stop measuring execution time
	UTL_stsStop(stsTime0);

    /* Record the amount of actual data being sent */
    PIP_setWriterSize( thrAudioproc[chan].pipOut, sizeInWords( size ) );

    /* Free the receive buffer, put the transmit buffer */
    PIP_free( thrAudioproc[chan].pipIn  );
    PIP_put ( thrAudioproc[chan].pipOut );
}

/*
 *  ========= thrAudioprocSetOutputVolume ========
 *  Procedure that changes output volume for an Audioproc thread
 *
 *  This procedure is called from the likes of the Control thread.
 *  Instead of having the control thread directly write to
 *  thread Audioproc's variables, it calls this function which
 *  changes the state of the VOL algorithm instance for the
 *  given channel.
 */
Void thrAudioprocSetOutputVolume( Int chan, Int *volume )
{
    /* VOL algorithm control structure */
    IVOL_Status status;
    Int i;

    UTL_assert( chan < NUMCHANNELS );   /* sanity checking */

    /*
     *  Apply volume gain information to the appropriate alg. instance.
     *  Retrieve the current parameters, change the fields that need
     *  to be changed, and apply the new parameters. Volume gain is
     *  a percentage, a number from 0 to 200, 100 being the normal
     *  volume (100%).
     */

	for(i=0; i<NUMBANDS; i++) {
    	VOL_control( thrAudioproc[ chan ].algVOL[i], IVOL_GETSTATUS, &status );
    	status.gainPercentage = volume[i];
    	VOL_control( thrAudioproc[ chan ].algVOL[i], IVOL_SETSTATUS, &status );
    }
}

/*
 *  ========= FIR_equalizer ========
 *
 *  This function performs the audio equalization operation.
 *  5 bands of equalizer settings are made available to the
 *  user via the GEL menu. This equalizer is implemented
 *  with the fir() from TI DSPLIB.
 */
Void FIR_equalizer(DATA *in, DATA *out){
	DATA *audioOut0 = &audioBuffer[0];
	DATA *audioOut1 = &audioBuffer[FRAMELEN];
	DATA *audioOut2 = &audioBuffer[FRAMELEN * 2];
	DATA *audioOut3 = &audioBuffer[FRAMELEN * 3];
	DATA *audioOut4 = &audioBuffer[FRAMELEN * 4];
    Int		i;

	// perform the fir filtering for the 5 frequency bands 
  	fir(in,filterBand0, thrAudioproc[0].bufInterm[0], &dbptr0, FILTORDER0, FRAMELEN);
  	fir(in,filterBand1, thrAudioproc[0].bufInterm[1], &dbptr1, FILTORDER1, FRAMELEN);
  	fir(in,filterBand2, thrAudioproc[0].bufInterm[2], &dbptr2, FILTORDER2, FRAMELEN);
  	fir(in,filterBand3, thrAudioproc[0].bufInterm[3], &dbptr3, FILTORDER3, FRAMELEN);
  	fir(in,filterBand4, thrAudioproc[0].bufInterm[4], &dbptr4, FILTORDER4, FRAMELEN);

    // amplify the signal in the interm. buffer and store result in dst 
    VOL_apply( thrAudioproc[0].algVOL[0], thrAudioproc[0].bufInterm[0], audioOut0 );
    VOL_apply( thrAudioproc[0].algVOL[1], thrAudioproc[0].bufInterm[1], audioOut1 );
    VOL_apply( thrAudioproc[0].algVOL[2], thrAudioproc[0].bufInterm[2], audioOut2 );
    VOL_apply( thrAudioproc[0].algVOL[3], thrAudioproc[0].bufInterm[3], audioOut3 );
    VOL_apply( thrAudioproc[0].algVOL[4], thrAudioproc[0].bufInterm[4], audioOut4 );

	// Start measuring execution time
	//UTL_stsStart(stsTime1);
	// sum the 5 bands of audio signals together to obtain the processed audio signal
    for ( i = 0; i < FRAMELEN; i++ ){
    	out[i] = _sadd(audioOut0[i], audioOut1[i]);
    	out[i] = _sadd(out[i], audioOut2[i]);
    	out[i] = _sadd(out[i], audioOut3[i]);
    	out[i] = _sadd(out[i], audioOut4[i]);
    	out[i] = out[i] & 0xfffe;
    }
	// Stop measuring execution time
	//UTL_stsStop(stsTime1);
    
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?