/**************************************************************************/ /* File: snr_compute.cc */ /**************************************************************************/ /* Project: Computing SNR of a given signal Class: EE 8993 Spring 96 */ /* Author: Neeraj Deshmukh Date: February 19, 1996 */ /**************************************************************************/ /*======================================================================== This file defines the various functions in the SNR_detector class for the signal-to-noise computation of any given signal ========================================================================*/ /*------------------------------------------------------------------------ system and ISIP include files ------------------------------------------------------------------------*/ #include "snr_prms.h" /*------------------------------------------------------------------------ global function definition ------------------------------------------------------------------------*/ // opening files and testing for validity // FILE * open_file_cc (String name, String mode) { FILE *file; file = fopen (name, mode); if (file == NULL) { fprintf (stderr,"Cannot open file %s \n", name); exit (1); } return (file); } /*------------------------------------------------------------------------ class function definitions ------------------------------------------------------------------------*/ // definitions for functions in class SNR_Detector // /*-------------------------- constructors & destructors --------------------------*/ // constructor // SNR_Detector :: SNR_Detector () { // initialize elements of SNR detector // frame_dur_d = (int_2) (SAMPLE_FREQUENCY * FRAME_DURATION); signal_frame_d = new int_2[frame_dur_d]; window_dur_d = (int_2) (SAMPLE_FREQUENCY * WINDOW_DURATION); ham_window_d = new float[window_dur_d]; win_offset_d = (window_dur_d - frame_dur_d) / 2; frame_offset_d = win_offset_d; if (frame_offset_d < 0) frame_offset_d = 0; energy_var_d = new float[MAX_FRAMES]; } // destructor // SNR_Detector :: ~SNR_Detector () { // free memory // delete [] signal_frame_d; delete [] ham_window_d; delete [] energy_var_d; } /*---------------------------- internal calculation methods ----------------------------*/ // create the Hamming window // void SNR_Detector :: ham_window_cc () { // construct a hamming window of specified duration // float const_factor_l = 2.0 * PI / (window_dur_d - 1); for (int i = 0; i < window_dur_d; i++) ham_window_d[i] = 0.54 - 0.46 * cos (const_factor_l * i); } // compute the energy content in the pre-emphasized frame // float SNR_Detector :: compute_energy_cc () { // preemphasize the signal frame // float *frame_sample_l = new float[frame_dur_d]; float prev_sample_l = 0; frame_sample_l[0] = prev_sample_l; float this_sample_l; // loop through all the samples in frame // for (int i = 0; i < frame_dur_d; i++) { // scale the sample by appropriate factor // this_sample_l = (float) signal_frame_d[i] * SAMPLE_SCALE_FACTOR; frame_sample_l[i] = this_sample_l - PREEMPHASIS * prev_sample_l; prev_sample_l = this_sample_l; } // now compute the energy distribution // float sum_sq_l = 0; float average_l = 0; // center window over frame, even when window is longer // loop over the whole frame duration // for (int i = window_dur_d - frame_offset_d - 1; i >= frame_offset_d; i--) { // multiply the sample value by the window scaling factor // frame_sample_l[i - win_offset_d] *= ham_window_d[i]; // calculate the average signal value and sum of squares in frame // average_l += frame_sample_l[i - win_offset_d]; sum_sq_l += frame_sample_l[i - win_offset_d] * frame_sample_l[i - win_offset_d]; } // free memory // delete frame_sample_l; // compute energy variance and check if it is a permissible value // the 1.05 scaling factor is to compensate for error due to overlap // of frames in window // float energy_var_l = (sum_sq_l - average_l * average_l / window_dur_d); energy_var_l *= 1.05; // return // return (energy_var_l); } // compute the cumulative distribution of energy // float SNR_Detector :: cumul_energy_dist_cc (int num_frames_l) { // compute cumulative energy distribution values // int *energy_index_l = new int[NUM_BINS]; // keep track of frames and how many bins actually get filled up // int fr_count_l = 0; int bin_count_l = NUM_BINS; float bin_size_l = 1.0 / NUM_BINS; energy_index_l[1] = 0; // increment bins to compute distribution of energy // for (int i = 1; i < NUM_BINS; i++) { for (int j = 0; j < num_frames_l; j++) { if ((energy_var_d[j] >= (i-1) * bin_size_l) && (energy_var_d[j] < i * bin_size_l)) { energy_index_l[i] ++; fr_count_l ++; } } // initialize next cumulative bin // if (i < NUM_BINS - 1) energy_index_l[i + 1] = energy_index_l[i]; // if all frames done, break // if (fr_count_l == num_frames_l) { bin_count_l = i + 1; break; } } // find the threshold values // int sig_noise_l = 0; int noise_l = 0; for (int i = bin_count_l - 1; i >= 0; i--) { if (energy_index_l[i] < (int) ceil (NOMINAL_SIG_NOISE * num_frames_l)) { sig_noise_l = i + 1; break; } } for (int i = bin_count_l - 1; i >= 0; i--) { if (energy_index_l[i] < (int) ceil (NOMINAL_NOISE * num_frames_l)) { noise_l = i + 1; break; } } // calculate the ratio // float snr_l = ((float) sig_noise_l / (float) noise_l) - 1.0; // free memory // delete energy_index_l; // return // return (snr_l); } /*----------------------------- main SNR computation function -----------------------------*/ void SNR_Detector :: compute_snr_cc () { // initialize frame count // int frame_count_l = 0; // create the Hamming window // ham_window_cc (); // float max_energy_l = MIN_ENERGY_LEVEL; // read in the signal frame by frame and compute energy // while (fread (signal_frame_d, sizeof (int_2), frame_dur_d, stdin) > 0) { // preemphasize the signal and compute energy variance for this frame // energy_var_d[frame_count_l] = compute_energy_cc (); // increment the frame count and pointers // frame_count_l ++; } // calculate the SNR in dB // float snr_db_l = DB_CONSTANT * log10 (cumul_energy_dist_cc (frame_count_l)); // print to output // fprintf (stdout, "The SNR for the given signal is %.4f dB.\n", snr_db_l); }