/* Overtones, a timbre spectral analysis program.
 *
 * (c) 2007 Karel 'Clock' Kulhavy of Twibright Labs
 * This program is free software released under the GNU Public License version
 * 3 or later. */

/* Takes an ASCII spectrum from Audacity and fundamental frequency and sums the
 * energy of all/part of frequencies into appropriate bins for the overtones,
 * and then prints out the result in a format suitable for inclusion in the
 * Syntring ASCII tablature. */

#include <stdio.h> 
#include <math.h>
#include <stdlib.h>

#define NOVERT 50

float fundamental;
float overtones[NOVERT]; /* Energy */
float background[NOVERT]; /* Energy */
float BANDWIDTH=0.4;
unsigned char *string_spec;
float sub_multiply;

void process_file(float *overtones, unsigned char *filename)
{
	int c;
	FILE *filehandle;
	float frequency, a;
	int nearest;

	filehandle=fopen((char *)filename,"r");
	if (!filehandle){
		fprintf(stderr,"overtones: error: cannot open file %s\n",
			filename);
		exit(1);
	}
	while((c=fgetc(filehandle))!='\n');
	ungetc(c, filehandle);
	while(fscanf(filehandle, "%f %f", &frequency, &a)==2){
		frequency/=fundamental;
		nearest=floor(frequency+0.5);
		if (fabs(frequency-nearest)<BANDWIDTH){
			if (nearest<=NOVERT&&nearest>=1){
				float val=pow(10,a/10);
				if (val>overtones[nearest-1])
					overtones[nearest-1]=val;
			}
		}
	}
	fclose(filehandle);
}

int main(int argc, char **argv)
{
	int overtone;
	float max;

	if (argc<4){
		fprintf(stderr,"Usage: overtones <fundamental_frequency> "
			"[ string_index | start_string_index/end_string_index ]"
			" <spectrum_from_audacity> "
			"[spectrum_before_pluck_from_audacity "
			"before_coefficient ]\n");
		exit(1);
	}
	fundamental=atof(argv[1]);
	string_spec=(unsigned char *)(argv[2]);

	process_file(overtones,(unsigned char *)(argv[3]));
	if (argc>=6){
		process_file(background,(unsigned char *)(argv[4]));
		sub_multiply=atof(argv[5]);
	}

	max=0;
	for (overtone=0;overtone<NOVERT;overtone++){
		overtones[overtone]-=sub_multiply*background[overtone];
		if (overtones[overtone]>max) max=overtones[overtone];

	}

	for (overtone=0;overtone<NOVERT;overtone++){
		overtones[overtone]/=max; /* Normalize to 0dB for the strongest
					     overtone or fundamental */
		printf("overtone %s %d %d %G\n", string_spec, overtone
				, overtone+1, -10*log10(overtones[overtone]));
	}
	return 0;
}
