Construct_WAV

 
  1  #include <stdio.h>
  2  #include <string.h>
  3  #include <stdlib.h>
  4  #include <math.h>
  5
  6  typedef union{
  7          unsigned int integer;
  8          char byte[4];
  9  }intStruct;
 10
 11
 12  typedef struct _octaveTable{
 13          char symbol[3];
 14          float frequency;
 15          struct _octaveTable *next;
 16  } octaveTable;
 17  octaveTable octaveTableHead;
 18
 19
 20  void insertOctave(char *symbol,float frequency){
 21          octaveTable *node=(octaveTable*)malloc(sizeof(octaveTable));
 22          strcpy(node->symbol,symbol);
 23          node->frequency=frequency;
 24          node->next=octaveTableHead.next;
 25          octaveTableHead.next=node;
 26  }
 27
 28  float getFrequency(char *symbol){
 29          octaveTable *node=octaveTableHead.next;
 30          do{
 31                  if(!strcmp(node->symbol,symbol))return node->frequency;
 32                  node=node->next;
 33          }while(node!=NULL);
 34          return -1;
 35  }
 36
 37  void destroySymbolTable(){
 38          octaveTable *node=octaveTableHead.next;
 39          octaveTable *tmp;
 40          do{
 41                  tmp=node;
 42                  node=node->next;
 43                  if(tmp==NULL)break;
 44                  free(tmp);
 45          }while(node!=NULL);
 46  }
 47
 48
 49
 50  //The Global variables used in the program
 51  FILE *tempFile=NULL;
 52  FILE *outputFile=NULL;
 53  FILE *octave=NULL;
 54  FILE *music=NULL;
 55  intStruct waveLength;
 56  unsigned char waveHeader[40]={
 57          0x52,0x49,0x46,0x46,//RIFF
 58          0xFC,0x31,0x02,0x00,
 59          0x57,0x41,0x56,0x45,//WAVE
 60          0x66,0x6D,0x74,0x20,//fmt 
 61          0x10,0x00,0x00,0x00,//fmt chunck size
 62          0x01,0x00,//This is uncompressed
 63          0x02,0x00,//This is stereo pal!
 64          0x44,0xAC,0x00,0x00,//44100 samples per second
 65          0x88,0x58,0x01,0x00,//88200 bytes per second
 66          0x02,0x00,//Block align=2
 67          0x08,0x00,//8 bits per sample
 68          0x64,0x61,0x74,0x61//data
 69  };
 70  //////////////////////////////////////////////////////
 71  //The macros used in the program
 72  #define SAMPLING_RATE 44100.0
 73  #define PI 3.14
 74  #define RADIAN(x) ((PI*(x))/180.0)
 75  ///////////////////////////////////////////////////////
 76
 77
 78
 79  void error(char *msg){
 80          printf("%s\nAborting!\n",msg);
 81          exit(0);
 82  }
 83
 84  void addWave(float frequency,int ticks,int volume){//tick=0.1Second
 85          float radian;
 86          float step=(float)((360.0/SAMPLING_RATE)*frequency);
 87          int numberOfSamples=(int)(SAMPLING_RATE*ticks/100);
 88          float degree;
 89          int i,j;
 90          char sample;
 91          float attack=.2,decay=.2,sustain=.4,release=.2;
 92          float tempVolume;
 93          float attackFactor;
 94          float decayFactor;
 95          float releaseFactor;
 96
 97          int numberOfAttackSamples=attack*numberOfSamples;
 98          int numberOfDecaySamples=decay*numberOfSamples;
 99          int numberOfSustainSamples=sustain*numberOfSamples;
100          int numberOfReleaseSamples=release*numberOfSamples;
101
102          int attackSamplesLimit=numberOfAttackSamples;
103          int decaySamplesLimit=numberOfDecaySamples+attackSamplesLimit;
104          int sustainSamplesLimit=numberOfSustainSamples+decaySamplesLimit;
105          int releaseSamplesLimit=numberOfReleaseSamples+sustainSamplesLimit;
106
107          attackFactor=volume/(float)numberOfAttackSamples;
108          decayFactor=volume/((float)numberOfDecaySamples*2);
109          releaseFactor=volume/((float)numberOfReleaseSamples*2);
110
111
112          tempVolume=0;
113
114
115
116
117          degree=0;
118          for(i=0;i<numberOfSamples;i++){
119                  if(i<attackSamplesLimit){
120                          tempVolume+=attackFactor;
121                  }else if(i<decaySamplesLimit){
122                          tempVolume-=decayFactor;
123                  }else if(i<sustainSamplesLimit){
124
125                  }else if(i<releaseSamplesLimit){
126                          tempVolume-=releaseFactor;
127                  }
128                  radian=RADIAN(degree);
129                  sample=(char)(tempVolume*sin(radian));
130                  sample+=(char)((tempVolume)*sin(RADIAN(degree+30)));
131                  sample+=127;
132                  fprintf(tempFile,"%c%c",sample,sample);
133                  degree+=step;
134                  waveLength.integer+=2;
135          }
136  }
137  void generateWave(){
138          int i;
139          char byte;
140          for(i=0;i<40;i++){
141                  fprintf(outputFile,"%c",waveHeader[i]);
142          }
143          for(i=0;i<4;i++){
144                  fprintf(outputFile,"%c",waveLength.byte[i]);
145          }
146          tempFile=fopen("temp","r");
147          while(1){
148                  fscanf(tempFile,"%c",&byte);
149                  if(feof(tempFile))break;
150                  fprintf(outputFile,"%c",byte);
151          }
152          fclose(tempFile);
153  }
154
155  int main(int argc, char* argv[]){
156          char octaveSignature[5];
157          char symbol[3];
158          float frequency;
159          float chord[6];
160
161          int ticks;
162          char line[1024];
163          int volume;
164          if(argc<2){
165                  printf("Usage:\n\t play MusicFile [volume]\n\n",argv[0]);
166                  error("You have not specified the music file!");
167          }
168          volume=50;
169          if(argc==3){
170                  volume=atoi(argv[2]);
171          }
172          printf("BlueScorpion presents...Play!\n");
173          printf("Author: kashyap\n");
174          printf("Varifying octave...");
175          octave=fopen("octave","r");
176          if(octave==NULL){
177                  error("Could not find octave!");
178          }
179          fscanf(octave,"%s\n",octaveSignature);
180          if(octaveSignature[0]!='M'||octaveSignature[1]!='U'||octaveSignature[2]!='S'||octaveSignature[3]!='I'||octaveSignature[4]!='C')error("Bad octave file");
181          printf("Setting up the Octave table...\n");
182          while(!feof(octave)){
183                  fgets(line,1024,octave);
184                  if(line[0]=='#')continue;
185                  sscanf(line,"%s %f\n",symbol,&frequency);
186                  if(feof(octave))break;
187                  insertOctave(symbol,frequency);
188                  printf("%s=%fHz\n",symbol,frequency);
189          }
190          music=fopen(argv[1],"r");
191          if(music==NULL){
192                  error("Could not open the specified music file!");
193          }
194          tempFile=fopen("temp","w");
195          while(!feof(music)){
196                  fgets(line,1024,music);
197                  if(line[0]=='#')continue;
198                  sscanf(line,"%s %d\n",symbol,&ticks);
199                  frequency=getFrequency(symbol);
200                  if(frequency==-1)error("Invalid symbol encountered in the music file!");
201                  if(feof(music))break;
202                  addWave(frequency,ticks,volume);
203          }
204
205          fclose(tempFile);
206
207          outputFile=fopen("output.wav","w");
208          if(outputFile==NULL){
209                  error("Error opening output.wav for writing!");
210          }
211          generateWave();
212          fclose(outputFile);
213          destroySymbolTable();
214          return 0;
215  }
216
217
218