Audio wave functions

I started implementing a small audio library for Arduino. It uses the PWM to generate different kinds of waves:

  • square
  • sinus
  • saw
  • white noise

The sinus wave sounds quite bad, but the rest is pretty good, especially the saw wav.

Here is the code with a small example:
<code>
void audioInit();
void playWhiteNoise(int amp, unsigned long t, int pin);
void playSine(int amp, int freq, unsigned long t, int pin);
void playSaw(boolean up, int amp, int freq, unsigned long t, int pin);
void playSquare(int amp, int freq, unsigned long t, int pin);

  1. define AUDIO_OUTPUT 9

void setup() {
audioInit();
randomSeed(analogRead(9));
}

void loop() {
Serial.println("SAW up");
playSaw(true, 127, currentFrequency, 1000, AUDIO_OUTPUT);
delay(1000);
Serial.println("SAW down");
playSaw(false, 127, currentFrequency, 1000, AUDIO_OUTPUT);
delay(1000);
Serial.println("SINE");
playSine(127, currentFrequency, 1000, AUDIO_OUTPUT);
delay(1000);
Serial.println("SQUARE");
playSquare(127, currentFrequency, 1000, AUDIO_OUTPUT);
delay(1000);
}

void audioInit() {
// Make sure the PWM is at its maximum frequency.
TCCR1A = 1;
TCCR1B = 9;
}

  1. define WAVE_RESOLUTION 32

void playWhiteNoise(int amp, unsigned long t, int pin) {
unsigned long startTime = millis();
while (startTime + t >= millis()) {
analogWrite(pin, (int)random(255));
}
}

unsigned char valueTable[WAVE_RESOLUTION];
void playSine(int amp, int freq, unsigned long t, int pin) {
amp = constrain(amp, 0, 127);
// reuse t -> convert to number of cycles
t = ((long)freq * (long)t) / 1000;
// reuse freq -> convert to period
freq = (1000000 / freq) - 7; // subtract 7 us to make up for digitalWrite overhead - determined empirically
int i;
for (i=0; i<WAVE_RESOLUTION; i++) {
valueTable[i] = (unsigned char) ( ( (sin((2 * PI * i) / (float) (WAVE_RESOLUTION-1))) + 1.0) * amp );
}
while (t--) {
for (i=0; i<WAVE_RESOLUTION; i++) {
analogWrite(pin, (int)valueTable[i]);
delayMicroseconds(freq / WAVE_RESOLUTION);
}
}
}

void playSaw(boolean up, int amp, int freq, unsigned long t, int pin) {
amp = constrain(amp, 0, 127);
// reuse t -> convert to number of cycles
t = ((long)freq * (long)t) / 1000;
// reuse freq -> convert to period
freq = (1000000 / freq) - 7; // subtract 7 us to make up for digitalWrite overhead - determined empirically
int i;
for (i=0; i<WAVE_RESOLUTION; i++) {
valueTable[i] = (unsigned char) ( (up ? i : WAVE_RESOLUTION - i - 1) * 2 * amp / (WAVE_RESOLUTION-1));
// Serial.println((int)valueTable[i]);
}
while (t--) {
for (i=0; i<WAVE_RESOLUTION; i++) {
analogWrite(pin, (int)valueTable[i]);
delayMicroseconds(freq / WAVE_RESOLUTION);
}
}
}

void playSquare(int amp, int freq, unsigned long t, int pin)
{

amp = constrain(amp, 0, 127);
// reuse t -> convert to number of cycles
t = ((long)freq * (long)t) / 1000;
// reuse freq -> convert to period
freq = (500000 / freq) - 7; // subtract 7 us to make up for digitalWrite overhead - determined empirically

while (t--) {
analogWrite(pin, 127 + amp);
delayMicroseconds(freq);
analogWrite(pin, 127 - amp);
delayMicroseconds(freq - 1); // - 1 to make up for fractional microsecond in digitaWrite overhead
}
}
</code>

Audio favorites

My favorites are the white noise and the saw wave. However, we can't really "mix" them. It would be great to be able to add/multiply those waves. I'm thinking about a real audio processing library... wouldn't that be nice?