#include #include #include "fmt_chunk.h" #define DEPTH 11000 int depth; float decay; int read_chars(FILE *in, char *s, int n) { int t,ch; for (t=0; t>8)&255),out); putc(((n>>16)&255),out); putc(((n>>24)&255),out); return 0; } int write_word(FILE *out, int n) { putc((n&255),out); putc(((n>>8)&255),out); return 0; } unsigned int read_long(FILE *in) { unsigned int t; t=getc(in); t=(getc(in)<<8)+t; t=(getc(in)<<16)+t; t=(getc(in)<<24)+t; return t; } unsigned short int read_word(FILE *in) { unsigned short int t; t=getc(in); t=(getc(in)<<8)+t; return t; } int parse_header(FILE *in, FILE *out) { int length; char riff_type[5]; length=read_long(in); read_chars(in,riff_type,4); printf("RIFF Header\n"); printf("----------------------------\n"); printf(" Length: %d\n",length); printf(" Type: %s\n",riff_type); printf("----------------------------\n"); /* Write RIFF Header */ if (out!=0) { fprintf(out,"RIFF"); write_long(out,4); fprintf(out,"WAVE"); } return 0; } int parse_fmt(FILE *in, struct fmt_chunk_t *fmt_chunk, FILE *out) { int length; length=read_long(in); fmt_chunk->format_type=read_word(in); fmt_chunk->channel_numbers=read_word(in); fmt_chunk->sample_rate=read_long(in); fmt_chunk->bytes_per_second=read_long(in); fmt_chunk->bytes_per_sample=read_word(in); fmt_chunk->bits_per_sample=read_word(in); printf("FMT Chunk\n"); printf("----------------------------\n"); printf(" Length: %d\n",length); printf(" Format Type: "); if (fmt_chunk->format_type==0) { printf("Mono\n"); } else if (fmt_chunk->format_type==1) { printf("Stereo\n"); } else { printf("unknown\n"); } printf(" Channel Numbers: %d\n",fmt_chunk->channel_numbers); printf(" Sample Rate: %d\n",fmt_chunk->sample_rate); printf("Bytes Per Second: %d\n",fmt_chunk->bytes_per_second); printf("Bytes Per Sample: "); if (fmt_chunk->bytes_per_sample==1) { printf("8 bit mono (%d)\n",fmt_chunk->bytes_per_sample); } else if (fmt_chunk->bytes_per_sample==2) { printf("8 bit stereo or 16 bit mono (%d)\n",fmt_chunk->bytes_per_sample); } else if (fmt_chunk->bytes_per_sample==4) { printf("16 bit stereo (%d)\n",fmt_chunk->bytes_per_sample); } printf(" Bits Per Sample: %d\n",fmt_chunk->bits_per_sample); printf("----------------------------\n"); /* Write FMT Chunk */ if (out!=0) { fprintf(out,"fmt "); write_long(out,16); write_word(out,fmt_chunk->format_type); write_word(out,fmt_chunk->channel_numbers); write_long(out,fmt_chunk->sample_rate); write_long(out,fmt_chunk->bytes_per_second); write_word(out,fmt_chunk->bytes_per_sample); write_word(out,fmt_chunk->bits_per_sample); } return 0; } int parse_data(FILE *in, struct fmt_chunk_t *fmt_chunk, FILE *out) { int length,deepest; short int reverb_buffer[depth]; int t,ptr; char h,oldh; short int r,oldr; deepest=0; length=read_long(in); for (t=0; tbits_per_sample==16) { for (t=0; t=depth) ptr=0; } for (t=0; t>1; ptr++; if (ptr>=depth) ptr=0; } } else if (fmt_chunk->bits_per_sample==8) { printf("This program only works with 16 bit samples.\n"); return 1; } return 0; } int reverb(char *inname,char *outname) { FILE *in,*out; char chunk_name[5]; struct fmt_chunk_t fmt_chunk; int t,marker; in=fopen(inname,"rb"); if (in==0) { printf("Couldn't open file for reading: %s\n",inname); return -1; } if (outname[0]!=0) { out=fopen(outname,"wb"); if (out==0) { printf("Could not open file for writing: %s\n",outname); return 0; } } else { out=0; } while(1) { if (read_chars(in,chunk_name,4)!=0) break; if (strcasecmp(chunk_name,"RIFF")==0) { parse_header(in,out); } else if (strcasecmp(chunk_name,"fmt ")==0) { parse_fmt(in,&fmt_chunk,out); } else if (strcasecmp(chunk_name,"data")==0) { parse_data(in,&fmt_chunk,out); } else { printf("Unknown chunk: '%s'\n",chunk_name); return -1; } } marker=ftell(out); fseek(out,4,SEEK_SET); write_word(out,marker); fseek(out,marker,SEEK_SET); if (out!=0) fclose(out); fclose(in); return 0; } int main(int argc, char *argv[]) { char inname[1024]; char outname[1024]; printf("\nreverb - Copyright 2002 Michael Kohn (mike@naken.cc)\n"); if (argc<3) { printf("Usage: reverb \n"); printf(" depth: optional. defaults to %d\n",DEPTH); printf(" decay: optional. defaults to 0.5 (must be 1 or less)\n"); exit(1); } depth=DEPTH; decay=0.5; strcpy(inname,argv[1]); strcpy(outname,argv[2]); if (argc>3) { depth=atoi(argv[3]); } if (argc>4) { decay=atof(argv[4]); } reverb(inname,outname); return 0; }