2
$\begingroup$

I'm working through exercises in a book called The Audio Programming Book and have been doing okay for nearly 300 pages, but have just got stuck. (I'm a musician, not programmer or audio specialist BTW, so sorry if this is a dumb question…)

I understand what pulse-width modulation is, and I've managed to write some C code to apply it to a square-wave. The book suggests using a function prototype that includes a frequency parameter; I assumed this would be the same as the frequency of the square-wave. But now I'm thinking that this frequency parameter may be for a LFO that constantly changes the level of pulse-width modulation. Does dynamic pulse-width modulation suggest a constantly changing level of pulse-width modulation, governed by a LFO? The next exercise in the book asks for "breakpoint" control over this function - but the values put into this would be dependent upon whether the frequency of pulse-width modulation change is changing, or just pulse-width modulation is changing.

I suspect I may have coded so far for static pulse-width modulation of a square wave.

EDIT: here's some code…

The following struct holds oscillator information, it is from code in the book (although I added curPWMod):

typedef struct t_oscil
{
    double twoPiOvrSR;
    double curFreq;
    double curPWMod;
    double curPhase;
    double incr;
} OSCIL;

The following macro updates values if the frequency value passed into functions changes (I wrote this as an exercise from the book, originally code for this was in every function):

#define UPDATE_FREQ \
        if (p_osc->curFreq != freq) \
            do { \
                p_osc->curFreq = freq; \
                p_osc->incr = p_osc->twoPiOvrSR * freq; \
            } while (0)

The following function is from the book, used to create values for a square wave (originally values set were 1.0, I changed to 0.99 as my audio files were clipping):

double squareTick(OSCIL *p_osc, double freq)
{
    double val;
    UPDATE_FREQ;
    if (p_osc->curPhase <= M_PI) {
        val = 0.99; // to avoid clipping
    } else {
        val = -0.99; // to avoid clipping
    }
    p_osc->curPhase += p_osc->incr;
    if (p_osc->curPhase >= TWO_PI) {
        p_osc->curPhase -= TWO_PI;
    }
    if (p_osc->curPhase < 0.0) {
        p_osc->curPhase += TWO_PI;
    }
    return val;
}

Here is my similar function to return values for a pulse-width modulated square wave (the constant value of 0.02 is used, because a pwMod value of 50 should give a square-wave):

// the next function is for pulse-width-modulated square wave
double pwmTick(OSCIL *p_osc, double freq, double pwMod)
{
    // this should BASICALLY be the same as the square wave function, but adjusting for the pwMod input
    double val;
    UPDATE_FREQ;
    if (p_osc->curPWMod != pwMod) {
        p_osc->curPWMod = pwMod;
        if (p_osc->curPWMod < 1.0) {
            p_osc->curPWMod = 1.0;
        }
        if (p_osc->curPWMod > 99.0) {
            p_osc->curPWMod = 99.0;
        }
    } // only changed if pwMod value has changed

    if (p_osc->curPhase <= (M_PI * p_osc->curPWMod * 0.02)) {
        val = 0.99; // to avoid clipping
    } else {
        val = -0.99;
    }

    // the next 7 lines are the same in every function - so should probably be replaced with a macro
    p_osc->curPhase += p_osc->incr;
    if (p_osc->curPhase >= TWO_PI) {
        p_osc->curPhase -= TWO_PI;
    }
    if (p_osc->curPhase < 0.0) {
        p_osc->curPhase += TWO_PI;
    }

    return val;
}

This function does exactly what I expected, but I have no idea if this is what the exercise in the book is asking me to do! Is this dynamic pulse-width modulation? My solution uses a different oscillator (and oscillator function), rather than applying another oscillator (sine?) and oscillator function to the pwMod argument passed into this function (which I suspect I'm supposed to do…)

This book doesn't mention pulse-width modulation before this point, and then gives no explanation of what it is; I don't mind this, it requires the reader to find information themselves, but it is hard work! The only clue given by the book, as to what this exercise requires, is the given function prototype:

double pwmtick(OSCIL* p_osc, double freq, double pwmod);

As I say above, I've managed to write a function using this prototype, but am now not sure if the freq parameter refers to the same frequency as in the square-wave function above (which is how I've interpreted it), or if it should be interpreted as a frequency for changing the amount of pwMod applied...

$\endgroup$
  • $\begingroup$ I think we need a little more information here. What is this function whose parameter is supposed to be a frequency? $\endgroup$ – Phonon Jun 23 '14 at 2:12
  • $\begingroup$ Hi @Phonon, I added loads of extra info and code. I'm now thinking I have followed the right process, and any periodic change to the pwMod value passed in would itself be produced by another oscillator function first... $\endgroup$ – Bob Broadley Jun 23 '14 at 14:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.