Music by Sampled Data


With only 32 kByte of FLASH you can only store a limited amount of data to play. Actually, to play sampled data is extremly easy: just initialize a pointer to the start of data in FLASH, get the length of the array and initialize the timers. For repeat, initialize again.

The main problem is: how to transform sampled data in a way, Arduino can work with.

  1. select only an amount of data that will fit into the FLASH
  2. convert Stereo to Mono
  3. convert 16 bit to 8 bit
  4. convert 44100 samples per second to 16000 samples per second (or even less)
  5. convert binary to ASCII
  6. add a comma after each value
1. to 5. can be done by some audio software. For 6., you have to write a little script.

Once all is done, this short program will do the rest:

const byte speakerPin  =  9; // PWM pin OC1A
const byte ctrlPin = A5;
const word sampleRate = 16000;

const byte samples[] PROGMEM = {
#include "take8bit16k2.h"
  128
};
int L = sizeof(samples);

void setup() {
  pinMode(speakerPin, OUTPUT);
  pinMode(ctrlPin, OUTPUT);
  TCCR1A = 0x81;
  TCCR1B = 1;
  setupTimer2();
}

void loop() {}

void setupTimer2() {
  TCCR2A =   2; // CTC mode
  TCCR2B =   2; // prescaler: 8
  byte PS = 8;
  OCR2A  = F_CPU / PS / sampleRate - 1; // --> 32 kHz
  TIMSK2 =   2; // Output Compare A Match Interrupt Enable
}

ISR(TIMER2_COMPA_vect) {
  static int w;
  PORTC = 32; // control
  OCR1A = pgm_read_byte(samples + w++);
  PORTC = 0; // control
  if (w > L) w = 0;
}

You data file should look like this:

128, 128, 131, 128, 127, 131, 131, 125, 131, 125, 
125, 127, 124, 127, 120, 118, 115, 117, 121, 125, 
125, 120, 124, 124, 127, 130, 134, 125, 127, 128, 
124, 123, 118, 118, 120, 127, 125, 127, 128, 125, 
...

Sample data take8bit16k2.h


contact: nji(at)gmx.de