Go Down

Topic: Sampled sound function (Read 4452 times) previous topic - next topic

smeezekitty

Jan 18, 2011, 09:51 am Last Edit: Jan 18, 2011, 08:07 pm by smeezekitty Reason: 1
I created a function to play low quality sampled sound out a speaker attached to an Arduino.
It plays 4000 1 bit per sample sound through a digital pin.
Maximum 50 seconds in atmega 328 memory.
It stores the data bit packed in an array.
It is enough to play short sounds at low quality.
Here is the function:
Code: [Select]

#include <avr/pgmspace.h>
void playSound(prog_uchar input[], long len, int soundpin){
   long arrayc=0;
   while(arrayc < len){
       unsigned char s = pgm_read_byte_near(array + arrayc);
       for(unsigned char bs = 1;bs < 128;bs *= 2){
           digitalWrite(soundpin, s & bs);
           delayMicroseconds(250);
       }
   arrayc++;
   }
}

Syntax:
Code: [Select]

void playSound(prog_uchar input, long len, int sound)
where
input is a bit packed program space array of the samples to be played.
len is the length of the array in bytes
soundpin is the pin to play the sound out

The following program converts 8000hz 8 bit mono files to bit packed arrays for the function to play:
Code: [Select]

#include <stdio.h>
#include <stdlib.h>
#define N(x) ((x) > 130)? 1:0
int main(int argc, char *argv[]){
printf("Note: The input file must be in 8000 8 bit samples per second mono\n");
if(argc != 3){printf("Usage: %s <input.wav> <output.c>\n", argv[0]);}
FILE *f = fopen(argv[1], "rb");
FILE *o = fopen(argv[2], "w");
unsigned char a,b,c,d,e,byte;
fprintf(o, "#include <avr/pgmspace.h>\nprog_uchar array[] PROGMEM = {");
unsigned int cnt=0,_cnt=0;
while(!feof(f)){
fread(&a, 1, 1, f);
fread(&e, 1, 1, f);
fread(&b, 1, 1, f);
fread(&e, 1, 1, f);
fread(&c, 1, 1, f);
fread(&e, 1, 1, f);
fread(&d, 1, 1, f);
a = N(a);
b = N(b);
c = N(c);
d = N(d);
byte = (a | b << 1 | c << 2 | d << 3);
fread(&a, 1, 1, f);
fread(&e, 1, 1, f);
fread(&b, 1, 1, f);
fread(&e, 1, 1, f);
fread(&c, 1, 1, f);
fread(&e, 1, 1, f);
fread(&d, 1, 1, f);
a = N(a);
b = N(b);
c = N(c);
d = N(d);
byte |= (a << 4 | b << 5 | c << 6 | d << 7);
fprintf(o, "%d,", byte);
cnt++;
_cnt++;
if(cnt > 60){fprintf(o, "\n"); cnt = 0;}
}
fprintf(o, "0};");
fclose(o);
fclose(f);
printf("\nOutput array of %d bytes\n", _cnt);
return 0;
}

My code sucks but it works.
Avoid throwing electronics out as you or someone else might need them for parts or use.
Solid state rectifiers are the only REAL rectifiers.
Resistors for LEDS!

PaulS

Quote
My code sucks but it works.

I'll agree with the first part, and take your word for the second part.
In this code
Code: [Select]
while(arrayc < len){
long arrayc=0;
unsigned char s = pgm_read_byte_near(array + arrayc);
for(unsigned char bs = 1;bs < 128;bs *= 2){
 digitalWrite(soundpin, s & bs);
 delayMicroseconds(250);
}
arrayc++;
}

arrayc is both a global variable and a local variable. It is also not an array.

There are no comments to explain what is going on, and the (lack of) indenting makes it very hard to follow.

There is nothing in your post defining how to get the data into PROGMEM.

But, the concept is neat. Thank you for taking time to post this.

smeezekitty

Avoid throwing electronics out as you or someone else might need them for parts or use.
Solid state rectifiers are the only REAL rectifiers.
Resistors for LEDS!

Go Up