MUS 177/267 – allpass filter

/ allpass filter, non-interpolating
float allpass(float input, int32_t delaySamps, float gain, float *apBuffer, int32_t *writePos, )
{
float readOut, writeIn;
int32_t i, readPos;
readPos = *(writePos);

/* read from delay line */
readOut =  *(apBuffer+readPos);
/* put data in */
writeIn = input + (readOut * gain);
*(apBuffer+readPos) = writeIn;

readPos++;
readPos = (readPos == delaySamps) ? 0 : readPos;
*writePos = readPos;

readOut -= (writeIn * gain);
return(readOut);
}

Music 177/267 – codec working….

Naturally the codec started to work correctly 5 minutes after class. My mistake? A gain of 100 drives it into hard distortion. I fixed the code by simply setting the codec output volume to 90.

This example uses input D0, D1, D2, D3 to play FM notes when those inputs are brought high. The notes are randomly selected from a small range, and frequencies looked up in a table. Some simple line~ emulation controls envelope and FM index.

 

f4-06 – download and enjoy!!! requires hard-fpu option in eclipse

Music 177/267 – week 6 frustration

unworking code from tuesday’s class

main.c for talking to the headphone codec

oscillator pseudo-code

/*

*  oscil.cpp

*  Created by Tom Erbe on 10/18/12.

*

*/

#include “Oscil.h”

#include <cmath>

// psuedo code table lookup oscillator

// this osc. uses power of two tableSize

Oscil::Oscil()

: tableSize(512)

{

uint32_t i;

twoPi = 8.0 * atan(1.0);

Pi = 4.0 * atan(1.0);

halfPi = 2.0 * atan(1.0);

nPi = -1.0 * Pi;

nHalfPi = -1.0 * halfPi;

nTwoPi = -1.0 * twoPi;

taylorA = 1.0f/6.0f;

taylorB = 1.0f/120.0f;

taylorC = 1.0f/5040.0f;

taylorD = 1.0f/362880.0f;

phase = 0.0;

phaseIncrement = 0.0;

dspFreq = 0.0f;

sinZ = 0.0;

cosZ = 1.0;

}

Oscil::~Oscil()

{

}

// this better get called before table playback!!!

void Oscil::SetTable(float *newtable, long size)

{

tableSize = size;

tableMask = tableSize – 1;

wavetable = newtable;

}

// with frequency as a block of floats, a new frequency for each sample

// method one – truncate phase

// we are using frequency from 0.0 to 1.0 for 0Hz to samplerate

void Oscil::WaveTruncate(float freq, float *freqBlock, float *output, long samplesPerBlock)

{

long sample;

long longPhase;

phaseIncrement = freq * tableSize;

for(sample = 0; sample<samplesPerBlock; sample++)

{

if(freqBlock)

phaseIncrement = *(freqBlock + sample) * tableSize;

longPhase = (long)phase;

longPhase = longPhase & tableMask;

*(output+sample) = *(wavetable+longPhase);

phase += phaseIncrement;

while(phase >= (float)tableSize)

phase = phase – (float)tableSize;

while(phase < 0.0)

phase = phase + (float)tableSize;

}

}

void Oscil::WaveInterpolate2(float freq, float *freqBlock, float *output, long samplesPerBlock)

{

long sample;

long longPhase;

float phaseMix;

phaseIncrement = freq * tableSize;

for(sample = 0; sample<samplesPerBlock; sample++)

{

if(freqBlock)

phaseIncrement = *(freqBlock + sample) * tableSize;

longPhase = (long)phase;

longPhase = longPhase & tableMask;

phaseMix = phase – (float)longPhase;

// Xa * (1.0 – pM) + Xb * pM = Xa – Xa*pM + Xb*pM = Xa + pM*(Xb – Xa)

*(output+sample) = *(wavetable+longPhase)

+ (phaseMix * (*(wavetable+((longPhase+1)&tableMask)) – *(wavetable+longPhase)));

phase += phaseIncrement;

while(phase >= (float)tableSize)

phase = phase – (float)tableSize;

while(phase < 0.0)

phase = phase + (float)tableSize;

}

}

// method two – interpolate phase

void Oscil::WaveInterpolate4(float freq, float *freqBlock, float *output, long samplesPerBlock)

{

long sample;

for(sample = 0; sample<samplesPerBlock; sample++)

{

if(freqBlock)

phaseIncrement = *(freqBlock + sample) * tableSize;

else

phaseIncrement = freq * tableSize;

{

long truncphase = (long) phase;

float fr = phase – (float)truncphase;

float inm1 = wavetable[(truncphase – 1) & tableMask];

float in   = wavetable[(truncphase + 0) & tableMask];

float inp1 = wavetable[(truncphase + 1) & tableMask];

float inp2 = wavetable[(truncphase + 2) & tableMask];

*(output+sample) = in + 0.5 * fr * (inp1 – inm1 +

fr * (4.0 * inp1 + 2.0 * inm1 – 5.0 * in – inp2 +

fr * (3.0 * (in – inp1) – inm1 + inp2)));

}

phase = phase + phaseIncrement;

while(phase >= tableSize)

phase = phase – tableSize;

while(phase < 0.0)

phase = phase + tableSize;

}

}

// method three – direct calculation

void Oscil::SinDirect(float freq, float *freqBlock, float *output, long samplesPerBlock)

{

long sample;

for(sample = 0; sample<samplesPerBlock; sample++)

{

if(freqBlock)

phaseIncrement = *(freqBlock + sample);

else

phaseIncrement = freq;

*(output+sample) = sinf(twoPi*phase);

phase = phase + phaseIncrement;

while(phase >= 1.0)

phase = phase – 1.0f;

while(phase < 0.0)

phase = phase + 1.0f;

}

}

// method four – resonant network

void Oscil::SinResonant(float freq, float *freqBlock, float *output, long samplesPerBlock)

{

long sample;

float freqAngle;

freqAngle = twoPi * freq;

for(sample = 0; sample<samplesPerBlock; sample++)

{

//if(freqBlock)

//freqAngle = twoPi * *(freqBlock + sample);

*(output+sample) = sinZ = sinZ + freqAngle * cosZ;

cosZ = cosZ – freqAngle * sinZ;

}

}

// method five – taylor expansion sin

void Oscil::SinTaylor(float freq, float *freqBlock, float *output, long samplesPerBlock)

{

long sample;

float radPhase, radPhaseSq;

float freqInc;

freqInc = ((freq*twoPi) – dspFreq)/4000.f;

for(sample = 0; sample<samplesPerBlock; sample++)

{

phaseIncrement = dspFreq;

if(freqBlock)

phaseIncrement = *(freqBlock + sample);

radPhase = phase;

if(radPhase > halfPi) // if greater than .5 look at equivalent point between 0 and .5

radPhase = Pi – radPhase;

elseif(radPhase < nHalfPi) // if less than -.5 look at equivalent point between -.5 and 0

radPhase = nPi – radPhase;

radPhaseSq = radPhase*radPhase; // precalc squared term

//Taylor expansion out to x**9/9! factored  into multiply-adds

// *(output+sample) = radPhase*(radPhaseSq*(radPhaseSq*(radPhaseSq*(radPhaseSq*(1.0/362880.0) – (1.0/5040.0))

// + (1.0/120.0)) – (1.0/6.0)) + 1.0f);

*(output+sample) = radPhase*(radPhaseSq*(radPhaseSq*(radPhaseSq*(radPhaseSq*taylorD – taylorC)

+ taylorB) – taylorA) + 1.0f);

phase = phase + phaseIncrement;

while(phase >= Pi)

phase = phase – twoPi;

while(phase < nPi)

phase = phase + twoPi;

dspFreq += freqInc;

}

}

// method six – complex multiply sin

void Oscil::SinComplex(float freq, float *freqBlock, float *output, long samplesPerBlock)

{

long sample;

float freqAngle, angleReal, angleImag;

freqAngle = twoPi * freq;

angleReal = cos(freqAngle);

angleImag = sin(freqAngle);

for(sample = 0; sample<samplesPerBlock; sample++)

{

if(freqBlock)

{

freqAngle = twoPi * *(freqBlock + sample);

angleReal = cos(freqAngle);

}

*(output+sample) = angleReal * sinZ – angleImag * cosZ;

cosZ = angleReal * cosZ + angleImag * sinZ;

sinZ = *(output+sample);

if(sinZ > 1.0f)

sinZ = 1.0f;

}

}

Music 267/177 – ADC, DAC and DMA

Code from the 4th week which adds the 12 bit built in ADC and DAC. Both are using DMA to transfer their data to and from the ARM memory. The ADC is being used to read potentiometer values in class, and the DAC is computing a pseudo-random series and sending them out with “transfer-complete” and “half-transfer-complete” call backs.

A great deal of the ADC,DAC and DMA configuration is in the MSP file.

Download here: w4stmcode