DSPRelated.com

Flanger Audio Effect

Gabriel Rivas April 22, 2011 Coded in C
/*******************FLANGER.C******************************/

#include "Delay.h"
#include "Flanger.h"

static short samp_freq;
static double var_delay;
static short counter;
static short counter_limit;
static short control;
static short max_delay;
static short min_delay;
static double mix_vol;
static double delay_step;

/*
This is the initialization function, basically
it passes the initialization parameters to the delay block
and initializes the flanger control variables.
*/
void Flanger_init(short effect_rate,short sampling,short maxd,short mind,double fwv,double stepd,double fbv) {
	Delay_Init(2,fbv,fwv,1);
 
	samp_freq = sampling;
	counter = effect_rate;
	control = 1;
	var_delay = mind;

	//User Parameters
	counter_limit = effect_rate;
	max_delay =  maxd;
	min_delay = mind;
	mix_vol = 1;
	delay_step = stepd;
}

/*This is the flanging process task
that uses the delay task inside*/
double Flanger_process(double xin) {
	double yout;

	yout = Delay_task(xin); 	
	return yout;
}

/*
This sweep function creates a slow frequency
ramp that will go up and down changing the
delay value at the same time. The counter
variable is a counter of amount of samples that 
the function waits before it can change the delay.
*/
void Flanger_sweep(void) {
	if (!--counter) {			
	    var_delay+=control*delay_step;
  
	    if (var_delay > max_delay) {
	        control = -1;
            } 

            if (var_delay < min_delay) {
	        control = 1;
            }

	    Delay_set_delay(var_delay);
	    counter = counter_limit;
	}
}

/*****************FLANGER.H********************************/
#ifndef __FLANGER_H__
#define __FLANGER_H__

extern void Flanger_init(short effect_rate,short sampling,short maxd,short mind,double fwv,double stepd,double fbv);
extern double Flanger_process(double xin);
extern void Flanger_sweep(void);

#endif

/*****USAGE EXAMPLE****************************************/
#include "Flanger.h"

void main(void) {
    double xin;
    double yout;
    Flanger_init(500,16000,70,2,0.3,1,0.3);

    while(1) {
        if (new_sample_flag()) {
            /*When there's new sample at your ADC or CODEC input*/
            /*Read the sample*/
            xin = read_sample();
            /*Apply the Flanger_process function to the sample*/
            yout = Flanger_process(0.7*xin);

            /*Send the output value to your DAC or codec output*/
            write_output(yout);
            /*Makes the delay vary*/
            Flanger_sweep();
        }                              
    }
}

TI F281x PWM Configuration

Emmanuel April 18, 2011 Coded in C for the TI F28x
/**********************************************************************/
#include "DSP281x_Device.h"
/***********************************************************************/

void InitPwm(void)
{

asm( "EALLOW");	//Enable write operations in protected registers

/*** Independent Compare Output Enable	*/

	EvaRegs.EXTCONA.bit.INDCOE= 1;

/********************************************************************
*	Write values in the two following registers until all the other
*	registers have been written, as their value depends on the other
*	registers. 							*
********************************************************************/

/*** Timer 1 Period Regiser	*/

	EvaRegs.T1PR = 0xB71A;			//use this value for a frequency of 200 Hz assuming
								    //sysclkout=150 MHz and its pre-scaler=16
								    
/*** CMPR1 Register Configuration */

	EvaRegs.CMPR1= 0x493D;		//to get 60% of duty cycle this value equals the 1-0.6= 40% period
		
/********************************************************************/

	EvaRegs.GPTCONA.all= 0x0050;
	
// bit 15 		0		Reserved 
// bit 14 		0		T2STAT GP timer 2 Status. 
// bit 13 		0		T1STAT GP timer 1 Status. 
// bit 12 		0		T2CTRIPE T2CTRIP Enable. 
// bit 11 		0		T1CTRIPE T1CTRIP Enable. 
// bit 10-9 	00		T2TOADC Start ADC with timer 2 event
// bit 8-7 		00		T1TOADC Start ADC with timer 1 event
// bit 6 		1		TCMPOE Timer compare output enable. 
// bit 5		0		T2CMPOE Timer 2 compare output enable. 
// bit 4 		1		T1CMPOE Timer 1 Compare Output Enable. 
// bit 3-2 		00		T2PIN Polarity of GP timer 2 compare output
// bit 1-0 		00		T1PIN Polarity of GP timer 1 compare output
	

/*** COMCONA Register Configuration*/

	EvaRegs.COMCONA.all = 0x8020;
	
// bit 15 		1:		CENABLE: Compare Enable
// bit 14-13 	00:		CLD1, CLD0: CMPRx Reload Condition
// bit 12 		0:		SVENABLE: PWM Vector Enable
// bit 11-10 	00:		ACTRLD1,ACTRLD0: Action Control Regiser Reload Condition
// bit 9 		0:		FCMPOE: Full Compare Output Enable
// bit 8 		0:		PDPINTA: PDPINTA Status
// bit 7 		0:		FCMP3OE: Compare 3 Output Enable
// bit 6 		0:		FCMP2OE: Compare 2 Output Enable
// bit 5 		1:		FCMP1OE: Compare 1 Output Enable
// bit 4-3 		00:		Reserved
// bit 2 		0:		C3TRIPE: C3TRIP Enable 
// bit 1 		0:		C2TRIPE: C2TRIP Enable 
// bit 0 		0:		C1TRIPE: C1TRIP Enable 

/** ACTRA Register Configuration*/

	EvaRegs.ACTRA.all = 0x0002;
	
// bit 15 		0:		SVRDIR: PWM Vector rotate direction 
// bit 14-12 	000:	D2-D: PWM Vector basic bits
// bit 11-10 	00:		CMP6ACT1-0 Compare Action in pin 6, CMP6.
// bit 9-8 		00:		CMP5ACT1-0 Compare Action in pin 5, CMP5.
// bit 7-6 		00:		CMP4ACT1-0 Compare Action in pin 4, CMP4.
// bit 5-4 		00:		CMP3ACT1-0 Compare Action in pin 3, CMP3
// bit 3-2 		00:		CMP2ACT1-0 Compare Action in pin 2, CMP2
// bit 1-0 		10		CMP1ACT1-0 Compare Action in el pin 1, CMP1

/*** T1CON Register Configuration*/

	EvaRegs.T1CON.all = 0x9442;
	
// bit 15:14 	10:		Emulation Control bits
// bit 13 		0:		Reserved
// bit 12-11 	10:		TMODE1-TMODE0 Counter Mode Selection
// bit 10-8 	100:	TPS2-TPS0 Pre-scaler: 100= HSPCLK/16
// bit 7 		0:		T2SWT1 Timer 2 trigger by timer 1
// bit 6 		1:		TENABLE Timer Enable
// bit 5-4 		00:		TCLKS(1,0) Clock Source Selection
// bit 3-2 		00:		TCLD(1,0) Timer Compare Register Reload Condition
// bit 1 		1:		TECMPR Compare Operations Enable
// bit 0		0:		SELT1PR: Period Register Selection
						

asm( "EDIS");	//Protected Registers Write Disabled

}

/**End of function*/

IIR Bandstop Filter

Ron April 1, 2011 Coded in C for the TI C67x
// Include the filter coefficients and corresponding variables
#include "IIRBSF.h"

// The intermediate values in the Direct Form II filter
float delay_w[MWSPT_NSEC][3];	// delay_w[i][j] <=> w_i(n-j), j=0,1,2	
				// i is the section, j the delay
						
float sectionOut;		// yk[n] <=> sectionout

interrupt void isr()	 	//Interrupt function t=125us, f = 8kHz
{	
  short i; 			// i loops through the MWSPT_NSEC number of sections

  //  Do the filtering if DIP switch 1 up
  if (get_DIP1() == 1) {
			
	// In the first section, read in the x-value, apply the first stage gain
	sectionOut = NUM[0][0] * get_sample();

	for (i=1; i<MWSPT_NSEC; i++) { // Loop through all the sections
	
		// Get the new delay_w[0];
		delay_w[i][0] = sectionOut - DEN[i][1]*delay_w[i][1] - DEN[i][2]*delay_w[i][2];

		// Get the output of this section		
		sectionOut = NUM[i][0]*delay_w[i][0] + NUM[i][1]*delay_w[i][1] + NUM[i][2]*delay_w[i][2];
	
		// Delay the w's for the next interrupt
		delay_w[i][2] = delay_w[i][1];
		delay_w[i][1] = delay_w[i][0];

	}

	// Apply the gain, convert to short and send out
	send_output((short)(2 * sectionOut));
	// Gain of 2 chosen heuristically for speech from PC

  } else { // If DIP switch 1 down, == 0, then just pass through signal.

	send_output(get_sample());
  }
 	return;	//interrupt done
}

void main()
{
	short i,j;
 	for (i=0; i<MWSPT_NSEC; i++)
 		for (j=0; j<3; j++) 
			delay_w[i][j] = 0;      // init intermediate array			
	init_all();                  	// init all
	while(1);    		   	// infinite loop
}

IIR FIlter and add tone

Ron April 1, 2011 Coded in C for the TI C67x
//iirFilter.c  

// Include the filter coefficients and corresponding variables
#include "IIRLPF.h"
#define A 1		//The amplitude of added wave
#define FREQ 1000	//The frequency of the sine wave in Hz

// The intermediate values in the Direct Form II filter
float delay_w[MWSPT_NSEC][3];		
						// delay_w[i][j] <=> w_i(n-j), j=0,1,2
						// i is the section, j the delay
						
float sectionOut;		// yk[n] <=> sectionout

interrupt void isr()	 //Interrupt function t=125us, f = 8kHz
{	
  short i; 			// i loops through the MWSPT_NSEC number of sections
  int period = 8000 / FREQ;
  float rad = FREQ * 2 * pi;
  int j = 0;

  //  Do the filtering if DIP switch 1 up
  if (get_DIP1() == 1) {
			
	// In the first section, we read in the x-value, apply the first stage gain
	sectionOut = NUM[0][0] * get_sample();

	for (i=1; i<MWSPT_NSEC; i++) { // Loop through all the sections
	
		// Get the new delay_w[0];
		delay_w[i][0] = sectionOut - DEN[i][1]*delay_w[i][1] - DEN[i][2]*delay_w[i][2];

		// Get the output of this section		
		sectionOut = NUM[i][0]*delay_w[i][0] + NUM[i][1]*delay_w[i][1] + NUM[i][2]*delay_w[i][2];
	
		// Delay the w's for the next interrupt
		delay_w[i][2] = delay_w[i][1];
		delay_w[i][1] = delay_w[i][0];

	}

	//Add a tone to sectionOut
	sectionOut = sectionOut + A*sin(rad*j); //Add a sine wave of freq rad to sectionOut
	j = (j + 1) % period; //Increment the sine wave counter

	// Apply the gain, convert to short and send out
	send_output((short)(2 * sectionOut));
	// Gain of 2 chosen heuristically for speech from PC

  } else { // If DIP switch 1 down, == 0, then just pass through signal.

	send_output(get_sample());
  }

 	return;							// return from interrupt
}

void main()
{
	short i,j;

 	for (i=0; i<MWSPT_NSEC; i++)
 		for (j=0; j<3; j++) 
			delay_w[i][j] = 0;      // init intermediate array
			
	init_all();                  	// init all
	while(1);    		  	// infinite loop
}

Dual DIP-switched IIR Filter

Ron April 1, 2011 Coded in C for the TI C67x
//iirFilterSwitch.c  

// Include the filter coefficients and corresponding variables
#include "IIRLPF.h"
#include "IIRHPF.h"

// The intermediate values in the Direct Form II filter
float delay_w1[MWSPT_NSEC1][3];		
float delay_w2[MWSPT_NSEC2][3];
						// delay_w[i][j] <=> w_i(n-j), j=0,1,2
						// i is the section, j the delay
						
float sectionOut;		// yk[n] <=> sectionout

interrupt void isr()	 //Interrupt function
{	
  short i; 			// i loops through the MWSPT_NSEC number of sections

  //  Use the LPF if DIP switch 1 up
  if (get_DIP1() == 1) {
			
	// In the first section, we read in the x-value, apply the first stage gain
	sectionOut = NUM1[0][0] * get_sample();

	for (i=1; i<MWSPT_NSEC1; i++) { // Loop through all the sections
	
		// Get the new delay_w1[0];
		delay_w1[i][0] = sectionOut - DEN1[i][1]*delay_w1[i][1] - DEN1[i][2]*delay_w1[i][2];

		// Get the output of this section		
		sectionOut = NUM1[i][0]*delay_w1[i][0] + NUM1[i][1]*delay_w1[i][1] + NUM1[i][2]*delay_w1[i][2];
	
		// Delay the w's for the next interrupt
		delay_w1[i][2] = delay_w1[i][1];
		delay_w1[i][1] = delay_w1[i][0];

	}

	// Apply the gain, convert to short and send out
	send_output((short)(2 * sectionOut));
	// Gain of 2 chosen heuristically for speech from PC

  } else { // If DIP switch 1 down, == 0, then use HPF

	sectionOut = NUM2[0][0] * get_sample();

	for (i=1; i<MWSPT_NSEC2; i++) { // Loop through all the sections
	
		// Get the new delay_w2[0];
		delay_w2[i][0] = sectionOut - DEN2[i][1]*delay_w2[i][1] - DEN2[i][2]*delay_w2[i][2];

		// Get the output of this section		
		sectionOut = NUM2[i][0]*delay_w2[i][0] + NUM2[i][1]*delay_w2[i][1] + NUM2[i][2]*delay_w2[i][2];
	
		// Delay the w's for the next interrupt
		delay_w2[i][2] = delay_w2[i][1];
		delay_w2[i][1] = delay_w2[i][0];

	}

	// Apply the gain, convert to short and send out
	send_output((short)(2 * sectionOut));
	// Gain of 2 chosen heuristically for speech from PC

  }

 	return;							// return from interrupt
}

void main()
{
	short i,j;

 	for (i=0; i<MWSPT_NSEC1; i++)
 		for (j=0; j<3; j++) 
			delay_w1[i][j] = 0;      // init intermediate array

 	for (i=0; i<MWSPT_NSEC2; i++)
 		for (j=0; j<3; j++) 
			delay_w2[i][j] = 0;      // init intermediate array
			
	init_all();                  	// init all
	while(1);    			// infinite loop
}

Circular Buffer FIR Filter

Ron April 1, 20111 comment Coded in C for the TI C67x
// These coefficients are used to filter
#include "yourfiltercoeffs.h"

// scale factor, S_h = 2^K.
#define K	15

int	filterout = 0; // In fixed-point implementation, the accumulator is 32-bit int
short delay[LENGTH];  // Short is the 16-bit integer variable

interrupt void isr()	 // Interrupt function
{
	short 	i;
	int 	Sx = 1;
	
	//  Do the filtering as per fixfilt if DIP switch 1 up
	if (get_DIP1() == 1) {
		// Direct-Form FIR
		delay[0] = Sx * get_sample();     	// input for filter
		filterout = hMax[0] * delay[0];   	// Set up filter sum
		// Notice, C-arrays go from 0..LENGTH-1
		for (i = LENGTH-1; i > 0; i--){		// Get sum of products
     			filterout += hMax[i] * delay[i];	
		     	delay[i] = delay[i-1];      	// Renew input array
		}			
		filterout = (filterout>>K); //Move into the lower 16 bits, reverses scaling
			//Sign extension carries the upper bit down if negative
	 	send_output(filterout);		// output for filter
	} else { // If DIP switch 1 down, == 0, then just pass through signal.
		send_output(get_sample());
	}

 	return;						// return from interrupt
}

void main()
{
	short i;

 	for (i=0; i<= LENGTH-1; i++) { 
		delay[i] = 0;          	// init filter processing array
    	}
	init_all();            		// init all
	while(1);    		   	// infinite loop
}

Max Amplitude Sine Wave

Ron April 1, 2011 Coded in C for the TI C67x
#define ARRAY_LEN  8
short index = 0;
int sample[ARRAY_LEN] = {0,23170,32767,23170,0,-23170,-32767,-23170};
interrupt void isr()	 
{
  	send_output(sample[index]); 
  	index = (++index) % ARRAY_LEN;
	return;	//interrupt servicing complete
}

FIR 2kHz Bandstop Comb Filter

Ron April 1, 2011 Coded in C for the TI C67x
#define COMB_FILTER_ORDER		3	// Filter Order, i.e., M
#define DELAY_ARRAY_SIZE		9	// Number of (delayed) input samples to store

int   filtersum;			 	// Sum-of-products accumulator for calculating the filter output value
int   delay[DELAY_ARRAY_SIZE];			// Array for storing (delayed) input samples

static int gain1 = 1;				
static int gain2 = 4;				

interrupt void isr()	 			//Interrupt service routine
{							
     short i; 		 			// Loop counter	 
     delay[0] = get_sample() / gain1;		// Read filter input sample from ADC  and scale the sample		
     filtersum = delay[0];			// Initialize the accumulator
     for (i = COMB_FILTER_ORDER; i > 0; i--)
     {
     	filtersum += delay[i];			// Accumulate array elements
	delay[i] = delay[i-1];			// Shift delay elements by one sample
     }
     filtersum *= gain2;			// Scale the sum-of-products
     send_output(filtersum);			// write filter output sample to DAC
     return;					// interrupt servicing complete
}

void main()
{
     short i;	// loop counter
     for (i=0; i< DELAY_ARRAY_SIZE; i++)	// Initialize delay elements with 0
     { 
          delay[i] = 0;
     }
     init_all();                  		// global initialization
     while(1);    		   		// infinite loop
						// do nothing except wait for the interrupt	 
}

Passthrough a2d2a

Ron April 1, 2011 Coded in C for the TI C67x
int sample;            		       
interrupt void isr()	 //interrupt start
{
	sample = get_sample();	//input from A2D
 	send_output(sample);	//output to D2A
 	return;			//interrupt complete
}

Random Number Generator

February 27, 20112 comments Coded in C for the SHARC
// Random number generator that sounds pleasant in audio algorithms.
// The argument and return value is a 30-bit (positive nonzero) integer.
// This is Duttaro's 30-bit pseudorandom number generator, p.124 J.AES, vol 50 no 3 March 2002; 
// I found this 30-bit pseudorandom number generator sounds far superior to the 31-bit 
// pseudorandom number generator presented in the same article.
// To make result a signed fixed-point value, do not shift left into the sign bit;
// instead, subtract 0x20000000 then multiply by a scale factor.
#define NextRand(rr) (((((rr >> 16) ^ (rr >> 15) ^ (rr >> 1) ^ rr) & 1) << 29) | (rr >> 1))