/* open -a 'QuickTime Player' mysound.wav 
   cf. @s/2015/11/09-keisan-1-genwav5 
*/

#define LA   440
#define LA_a  466.16
#define SI   493.88
#define DO   523.25
#define DO_a 554.37
#define LE   587.33
#define LE_a 622.25
#define MI   659.26
#define FA   698.46
#define FA_a 739.99
#define SO   783.99
#define SO_a 830.61

#include <stdio.h>
#include <math.h>
#define SECOND 16
#define SIZE  (4*44100*SECOND)

// http://www.ufret.jp/song.php?data=1378 きまぐれロマンチック. guitar code.
double Code1[SECOND]={SO/2, LA,LE/2,    SO/2,LA,  LE/2,  LA,SI,  MI/2,SO/2,FA_a/2,SI,  MI/2,LA,  MI/2,LE/2};
double Code2[SECOND]={SI,   DO_a,FA_a/2,SI,  DO_a,FA_a/2,DO,LE_a,SO/2,LA_a,LA,    LE,  SO/2,DO_a,SO/2,FA_a/2};
double Code3[SECOND]={LE,   MI,LA,      LE,  MI,  LA,    MI,FA_a,SI  ,LE,  DO_a,  FA_a,SI,  MI,  SI  ,LA};
double Code4[SECOND]={FA_a, 0,  0,      FA_a,   0,        0,LA*2,LE  ,0,   MI,    LA*2,0,   SO,  LE  ,0};

int setL(double hertz,unsigned char data[],int level,int from,int length);
int setR(double hertz,unsigned char data[],int level,int from,int length);
int  code(int tt,int ee,unsigned char data[]);

int main(int argc, char *argv[]) {
  FILE *fp2;
  char h[44]={0x52,0x49,0x46,0x46,
              0x84,0x56,0x8,0x0,
              0x57,0x41,0x56,0x45,
              0x66,0x6d,0x74,0x20,
              0x10,0x0,0x0,0x0,
              0x1,0x0,
              0x2,0x0,
              0x44,0xac,0x0,0x0,
              0x10,0xb1,0x2,0x0,
              0x4,0x0,
              0x10,0x0,
              0x64,0x61,0x74,0x61,
              0xb8,0x55,0x8,0x0};
  unsigned char data[SIZE];
  int c;
  int i;
  int filesize ;
  int datasize = SIZE;
  int second = SECOND;
  int tt;
  for (i=1; i<argc; i++) {
	sscanf(argv[i],"%d",&second);
  }
  datasize = 4*44100*second;
  if (datasize > SIZE) {
	fprintf(stderr,"Error: second <= 20\n");
	return(-1);
  }
  filesize = 44+datasize-8;
  fp2 = fopen("mysound.wav","w");
  h[4] = filesize % 0x100; h[5] = (filesize/0x100) % 0x100;
  h[6] = (filesize/0x10000) % 0x100; h[7] = (filesize/0x1000000) % 0x100;
  h[40] = datasize % 0x100; h[41] = (datasize/0x100) % 0x100;
  h[42] = (datasize/0x10000) % 0x100; h[43] = (datasize/0x1000000) % 0x100;

  /* set data in the array data */
  for (i=0; i<datasize; i++) data[i]=0;
  for (tt=0; tt<second; tt++) {
    code(tt,1,data);
  }

  for (i=0; i<44; i++) fputc(h[i],fp2);
  for (i=0; i<datasize; i++) fputc(data[i],fp2);
  fclose(fp2);
}

int setL(double hertz,unsigned char data[],int level,int from,int length) {
  int i,p;
  int w,w0;
  if (4*(from+length) > SIZE) {
    fprintf(stderr,"Error\n"); return(-1);
  }
  for (i=from; i< from+length; i++) {
    w = (int) level*sin(2*3.14*hertz*((double) i)/44100.0);
    p = i*4;
    /* printf("%d\n",w); */
    if (w < 0) w = w+0x10000;
    w0=data[p]+data[p+1]*0x100; // 現在のデータ
    w = w0+w; // w を足す. 和音を作ることに相当.
    data[p] = w % 0x100;
    data[p+1] = w/0x100;
  }
  return(0);
} 

int setR(double hertz,unsigned char data[],int level,int from,int length) {
  int i,p;
  int w,w0;
  if (4*(from+length) > SIZE) {
    fprintf(stderr,"Error\n"); return(-1);
  }
  for (i=from; i< from+length; i++) {
    w = (int) level*sin(2*3.14*hertz*((double) i)/44100.0);
    p = i*4;
    /* printf("%d\n",w); */
    if (w < 0) w = w+0x10000;
    w0=data[p+2]+data[p+3]*0x100; // 現在のデータ
    w = w0+w; // w を足す. 和音を作ることに相当.
    data[p+2] = w % 0x100;
    data[p+3] = w/0x100;
  }
  return(0);
} 

// Code* に格納されたデータに従い和音を作成
int  code(int tt,int ee,unsigned char data[]) {
  int from,length;
  if ((tt+ee)*44100*4 > SIZE) {
    fprintf(stderr,"Error\n"); return(-1);
  }
  from = tt*44100; length=ee*44100;
  if (Code1[tt] > 0) setL(Code1[tt],data,3000,from,length);
  if (Code2[tt] > 0) setR(Code2[tt],data,3000,from,length);
  if (Code3[tt] > 0) setR(Code3[tt],data,3000,from,length);
  if (Code4[tt] > 0) setR(Code4[tt],data,3000,from,length);
  return(0);
}

