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

extern STATS stats;
float divisor;

void
do_vu()
{
  int best = 0, counter, flag = TRUE, channel;
  short holder[MAX_CHANNELS], temp_holder;
  static char *scale = "    |    |    |    |    |    |    |    |    |    <";
  static char *message1 =	"***** CLIP *****", *message_foo;
  static char message2[20], message3[20];
  static char canvas[100];
  float peak_amp, crude, average = 0;
  long time = 0;
  long block_duration;
  char stereo_flip_flop = 0;
  int esd;
  
  /*   connect to the esd   */
  esd = esd_open_sound( (char *)0 );

	/***** REALLY THE MAX ALLOWABLE AMPLITUDE *****/
	divisor = pow(2, (float)stats.sample_width ) / 2.0 - 1.0;

	/***** READ TO END OF INPUT *****/
	while(flag == TRUE){

		best = 0;

		/***** DO A VISUAL BLOCK *****/
		for(counter = 0; counter <= (int)((float)stats.sample_rate / stats.display_rate); ++counter){

			/***** DO A SAMPLE FRAME *****/
			for(channel = 0; channel < stats.num_channels; ++channel){
				holder[channel] = 0;
				/***** READ A SAMPLE *****/
				if(fread(holder + channel , (stats.sample_width / 8), 1, stdin) != 1){
					flag = FALSE;
					break;
				}
				time++; 

				/***** CORRECT SAMPLE AND TEST FOR GREATEST VALUE SO FAR *****/
				temp_holder = (stats.sample_width == 8 ? holder[channel] - 128 : holder[channel]);
				if(temp_holder < -divisor){
					temp_holder = -divisor;
				}
				if( abs(temp_holder) > best){
					best = abs(temp_holder);
				}

				/***** INVERT CHANNELS IF REQUESTED *****/
				holder[channel] *= stats.invert_channel[channel];
			}

			/***** TEST FOR GATE THRESHOLD *****/
			if( (!stats.threshold && !stats.decay_length) || service_timer(abs(temp_holder)) ){
				/***** TO WRITE... *****/
				for(channel = 0; channel < stats.num_channels; ++channel){
					/***** WRITE THE SAMPLE BACK OUT *****/
					if(fwrite(&holder[channel] , stats.sample_width / 8, 1, stdout) != 1){
						flag = FALSE;
						break;
					}
				}
			} else {
				/***** OR NOT TO WRITE... *****/
				--counter;
			}

		}


		/***** FIND FRACTION OF MAX AMPLITUDE *****/
		crude = sqrt( (float)(best * stats.graph_gain) / divisor) ;

		/***** FACTOR IN GAIN FROM -g *****/
		if(crude > 1){
			crude = 1;
		}

		/***** CREATE DISPLAY BAR INFORMATION *****/
		strcpy(canvas, scale);
		memset(canvas, 'O', (int)(crude * 50.0));
		sprintf(message2, "%2d%%", (int)(crude * (100.0 / stats.graph_gain) ) );
		sprintf(message3, "%d", best); 

		/***** OUTPUT DISPLAY BAR *****/
		if(stats.show_graph){
			fprintf(stderr, "%s ", canvas);
		}
		if(stats.show_time){
			fprintf(stderr, "T:%-7.4g ", ((float)time / (float)stats.sample_rate) / stats.num_channels);
		}

		/***** CLIP! IF TOO HIGH *****/
		message_foo = stats.show_percent ? message2 : "";
		fprintf(stderr, "%s ", best >= divisor ? message1 : message_foo);

		if(stats.show_raw){
			fprintf(stderr, "%s ", ((best >= divisor) ? "" : message3));
		}
		ramp_handler(best,esd);
		fprintf(stderr, "\n");
	}
	esd_close(esd);
}

int
service_timer(int current_amp)
{

	if(sqrt((float)current_amp / divisor) * 100 > stats.threshold){
		stats.decay_position = stats.decay_length;
	}
	if(stats.decay_position){
		return stats.decay_position--;
	} else {
		return 0;
	}


}







