Pages: [1]   Go Down
Author Topic: Sampled sound function  (Read 3960 times)
0 Members and 1 Guest are viewing this topic.
Washington
Offline Offline
God Member
*****
Karma: 38
Posts: 789
Firefox & Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
#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:
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:
#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.
« Last Edit: January 18, 2011, 02:07:58 pm by smeezekitty » Logged

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!

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48543
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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.
Logged

Washington
Offline Offline
God Member
*****
Karma: 38
Posts: 789
Firefox & Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Fixed.
Logged

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!

Pages: [1]   Go Up
Jump to: