/// <summary> /// Returns a HISTORGRAM OF THE DISTRIBUTION of SPECTRAL maxima. /// </summary> public static Tuple <int[], int[]> HistogramOfSpectralPeaks(double[,] spectrogram) { if (spectrogram == null) { throw new ArgumentNullException(nameof(spectrogram)); } int frameCount = spectrogram.GetLength(0); int freqBinCount = spectrogram.GetLength(1); int[] peakBins = new int[frameCount]; // store bin id of peaks int[] histogram = new int[freqBinCount]; // histogram of peak locations // for all frames in dB array for (int r = 0; r < frameCount; r++) { double[] spectrum = DataTools.GetRow(spectrogram, r); //locate maximum peak int j = DataTools.GetMaxIndex(spectrum); //if (spectrogram[r, j] > peakThreshold) //{ histogram[j]++; //store bin of peak peakBins[r] = j; //} } return(Tuple.Create(histogram, peakBins)); }
/// <summary> /// (2) LOWEST PERCENTILE FRAMES METHOD /// Assumes the passed matrix is a spectrogram and that all values in the data matrix are positive. /// Returns the noise profile over freq bins. i.e. one noise value per freq bin. /// First calculate the frame averages, sort in ascending order and accumulate the first N% of frames. /// WARNING: This method should NOT be used for short recordings i.e LT approx 10-15 seconds long. /// </summary> /// <param name="matrix">the spectrogram whose rows=frames, cols=freq bins.</param> /// <param name="lowPercentile">The percent of lowest energy frames to be included in calculation of the noise profile.</param> /// <returns>Returns a noise profile consisting of averaged values from the selected X% of low energy frames.</returns> public static double[] GetNoiseProfile_fromLowestPercentileFrames(double[,] matrix, int lowPercentile) { int rowCount = matrix.GetLength(0); int colCount = matrix.GetLength(1); int cutoff = lowPercentile * rowCount / 100; if (cutoff == 0) { throw new Exception("Illegal zero value for cutoff in method NoiseRemoval_Briggs.GetNoiseProfile_LowestPercentile()"); } double[] frameEnergyLevels = MatrixTools.GetRowAverages(matrix); var sorted = DataTools.SortArrayInAscendingOrder(frameEnergyLevels); int[] order = sorted.Item1; // sum the lowest percentile frames double[] noiseProfile = new double[colCount]; for (int i = 0; i < cutoff; i++) { double[] row = DataTools.GetRow(matrix, order[i]); for (int c = 0; c < colCount; c++) { noiseProfile[c] += row[c]; } } // get average of the lowest percentile frames for (int c = 0; c < colCount; c++) { noiseProfile[c] /= cutoff; } return(noiseProfile); }
/// <summary> /// THIS METHOD CALLED FROM ULTIMATELY UP LINE FROM AcousticIndicesCalculate class. /// returns an array showing which freq bin in each frame has the maximum amplitude /// </summary> /// <param name="spectrogram"></param> /// <param name="threshold"></param> /// <returns></returns> public static int[] GetSpectralMaxima(double[,] spectrogram, double threshold) { int rowCount = spectrogram.GetLength(0); int colCount = spectrogram.GetLength(1); var maxFreqArray = new int[rowCount]; //array (one element per frame) indicating which freq bin has max amplitude. //var hitsMatrix = new double[rowCount, colCount]; for (int r = 0; r < rowCount; r++) { double[] spectrum = DataTools.GetRow(spectrogram, r); spectrum = DataTools.filterMovingAverage(spectrum, 3); // smoothing to remove noise //find local freq maxima and store in freqArray & hits matrix. int maxFreqbin = DataTools.GetMaxIndex(spectrum); if (spectrum[maxFreqbin] > threshold) //only record spectral peak if it is above threshold. { maxFreqArray[r] = maxFreqbin; //hitsMatrix[r + nh, maxFreqbin] = 1.0; } } return(maxFreqArray); } // GetSpectralMaxima()
public static double[] GetAvSpectrum_HighestPercentile(double[,] matrix, int highPercentile) { double[] energyLevels = MatrixTools.GetRowAverages(matrix); var sorted = DataTools.SortArray(energyLevels); // sorts array in descending order int[] order = sorted.Item1; int colCount = matrix.GetLength(1); int cutoff = (int)(highPercentile * matrix.GetLength(0) / 100D); double[] avSpectrum = new double[colCount]; // sum the lowest percentile frames for (int i = 0; i < cutoff; i++) { double[] row = DataTools.GetRow(matrix, order[i]); for (int c = 0; c < colCount; c++) { avSpectrum[c] += row[c]; } } // get average of the lowest percentile frames for (int c = 0; c < colCount; c++) { avSpectrum[c] /= cutoff; } return(avSpectrum); }
//******************************************************************************************************************** //******************************************************************************************************************** //******************************************************************************************************************** //******************************* CEPTRA COEFFICIENTS USING DCT AND COSINES public static double[,] Cepstra(double[,] spectra, int coeffCount) { int frameCount = spectra.GetLength(0); //number of frames int binCount = spectra.GetLength(1); //number of filters in filter bank //set up the cosine coefficients. Need one extra to compensate for DC coeff. double[,] cosines = Cosines(binCount, coeffCount + 1); //following two lines write matrix of cos values for checking. //string fPath = @"C:\SensorNetworks\Sonograms\cosines.txt"; //FileTools.WriteMatrix2File_Formatted(cosines, fPath, "F3"); //following two lines write bmp image of cos values for checking. //string fPath = @"C:\SensorNetworks\Sonograms\cosines.bmp"; //ImageTools.DrawMatrix(cosines, fPath); double[,] op = new double[frameCount, coeffCount]; for (int i = 0; i < frameCount; i++) { double[] spectrum = DataTools.GetRow(spectra, i); //transfer matrix row=i to vector double[] cepstrum = DCT(spectrum, cosines); for (int j = 0; j < coeffCount; j++) { op[i, j] = cepstrum[j + 1]; //+1 in order to skip first DC value } } //end of all frames return(op); }
public static byte[,] IdentifySpectralRidgesInFreqDirection(double[,] matrix, double threshold) { int rows = matrix.GetLength(0); int cols = matrix.GetLength(1); //A: CONVERT MATRIX to BINARY FORM INDICATING SPECTRAL RIDGES var binary = new byte[rows, cols]; // row at a time, each row = one frame. for (int r = 0; r < rows; r++) { double[] row = DataTools.GetRow(matrix, r); row = DataTools.filterMovingAverage(row, 3); //## SMOOTH FREQ BIN - high value breaks up vertical tracks for (int c = 3; c < cols - 3; c++) { double d1 = row[c] - row[c - 1]; double d2 = row[c] - row[c + 1]; double d3 = row[c] - row[c - 2]; double d4 = row[c] - row[c + 2]; double d5 = row[c] - row[c - 3]; double d6 = row[c] - row[c + 3]; //identify a peak if (d1 > threshold && d2 > threshold && d3 > threshold && d4 > threshold && d5 > threshold && d6 > threshold) { binary[r, c] = 1; } } //end for every col } //end for every row return(binary); }
/// <summary> /// Given a DataTools object where the query is set to grab the appropriate keys, /// put the ContextSpecific keys into ConfigKeys /// </summary> /// <param name="db"></param> protected void InitConfigKeys(DataTools db) { if (ConfigKeys != null) { while (!db.EOF) { var row = db.GetRow(); var nm = row["value"]; ConfigKeys.Add(new KeyValuePair <string, string>("endpoint", nm.ToString())); db.NextRow(); } } }
/// <summary> /// First convert spectrogram to Binary using threshold. An amplitude threshold of 0.03 = -30 dB. An amplitude threhold of 0.05 = -26dB. /// </summary> public static TrainingDataInfo GetTrainingDataForClustering(double[,] spectrogram, ClusteringParameters cp) { int frameCount = spectrogram.GetLength(0); int freqBinCount = spectrogram.GetLength(1); var trainingData = new List <double[]>(); // training data that will be used for clustering double[,] trainingDataAsSpectrogram = new double[frameCount, freqBinCount]; // training data represented in spectrogram bool[] selectedFrames = new bool[frameCount]; for (int r = 0; r < frameCount; r++) { double[] spectrum = DataTools.GetRow(spectrogram, r); spectrum = DataTools.VectorReduceLength(spectrum, cp.ReductionFactor); // reduce length of the vector by factor of N and convert to binary for (int i = 0; i < spectrum.Length; i++) { if (spectrum[i] >= cp.IntensityThreshold) { spectrum[i] = 1.0; } else { spectrum[i] = 0.0; } } // remove isolated peaks. //for (int i = 1; i < spectrum.Length - 1; i++) //{ // if ((spectrum[i] == 1.0) && (spectrum[i - 1] == 0.0) && (spectrum[i + 1] == 0.0)) // { // spectrum[i] = 0.0; // } //} // only include frames where activity exceeds threshold if (spectrum.Sum() > cp.RowSumThreshold) { trainingData.Add(spectrum); IncludeSpectrumInSpectrogram(trainingDataAsSpectrogram, r, spectrum, cp.ReductionFactor); selectedFrames[r] = true; } } return(new TrainingDataInfo(trainingDataAsSpectrogram, trainingData, selectedFrames, cp.LowBinBound, cp.UpperBinBound, cp.IntensityThreshold)); }
/// <summary> /// use this version when want to make matrix of Cosines only one time. /// </summary> public static double[,] Cepstra(double[,] spectra, int coeffCount, double[,] cosines) { int frameCount = spectra.GetLength(0); //number of frames double[,] op = new double[frameCount, coeffCount]; for (int i = 0; i < frameCount; i++) { double[] spectrum = DataTools.GetRow(spectra, i); //transfer matrix row=i to vector double[] cepstrum = DCT(spectrum, cosines); for (int j = 0; j < coeffCount; j++) { op[i, j] = cepstrum[j + 1]; //+1 in order to skip first DC value } } //end of all frames return(op); }
public static double[,] MakeAcousticVectors(SonogramConfig config, double[,] matrix, double[] decibels, int sampleRate) { int ccCount = config.mfccConfig.CcCount; bool includeDelta = config.mfccConfig.IncludeDelta; bool includeDoubleDelta = config.mfccConfig.IncludeDoubleDelta; int deltaT = config.DeltaT; Log.WriteIfVerbose(" MakeAcousticVectors(matrix, decibels, includeDelta=" + includeDelta + ", includeDoubleDelta=" + includeDoubleDelta + ", deltaT=" + deltaT + ")"); var tuple = MakeCepstrogram(config, matrix, decibels, sampleRate); double[,] m = tuple.Item1; //this.SnrData.ModalNoiseProfile = tuple.Item2; //store the full bandwidth modal noise profile //initialise feature vector for template - will contain three acoustic vectors - for T-dT, T and T+dT int frameCount = m.GetLength(0); int cepstralL = m.GetLength(1); // length of cepstral vector int featurevL = 3 * cepstralL; // to accomodate cepstra for T-2, T and T+2 double[,] acousticM = new double[frameCount, featurevL]; //init the matrix of acoustic vectors for (int i = deltaT; i < frameCount - deltaT; i++) { double[] rowTm2 = DataTools.GetRow(m, i - deltaT); double[] rowT = DataTools.GetRow(m, i); double[] rowTp2 = DataTools.GetRow(m, i + deltaT); for (int j = 0; j < cepstralL; j++) { acousticM[i, j] = rowTm2[j]; } for (int j = 0; j < cepstralL; j++) { acousticM[i, cepstralL + j] = rowT[j]; } for (int j = 0; j < cepstralL; j++) { acousticM[i, cepstralL + cepstralL + j] = rowTp2[j]; } } return(acousticM); }
/// <summary> /// Simply get a user from the localDb /// </summary> /// <param name="username"></param> /// <returns></returns> public Dictionary <string, string> GetUser(string username) { Dictionary <string, string> retVal = new Dictionary <string, string>(); //$$$ Centalize this - without locking up a connection DataTools dt = new DataTools(); dt.Provider = provider; dt.ConnectionString = connectionString; dt.OpenConnection(); string[] parameter = { UsernameCol, username }; //!!! What is wrong with parameterized query? //dt.GetResultSet(findUserQuery, parameter); dt.GetResultSet(string.Format(findUserQueryTok, username)); while (!dt.EOF) { var row = dt.GetRow(); var nm = row[UsernameCol]; retVal.Add(UsernameCol, nm.ToString()); dt.NextRow(); } return(retVal); }
/// <summary> /// find spectral peaks per frame by subtracting the average energy of top and bottom band from the syllable band energy. /// then if it is higher than a dB threshold, the index of the peak bin will be returned. /// </summary> public static Tuple <int[][], int[][]> FindLocalSpectralPeaks(double[,] matrix, int[] peakBinsIndex, int widthMidBand, int topBufferSize, int bottomBufferSize, double threshold) { int frameCount = matrix.GetLength(0); // save the target peak bins index [frameCount, freqBinCount] List <int[]> targetPeakBinsIndex = new List <int[]>(); // save the bands' boundaries in each frame List <int[]> bandIndex = new List <int[]>(); // for all frames of the input spectrogram for (int r = 0; r < frameCount; r++) { // retrieve each frame double[] spectrum = DataTools.GetRow(matrix, r); // smoothing to remove noise //spectrum = DataTools.filterMovingAverage(spectrum, 3); //find the boundaries of middle frequency band: the min bin index and the max bin index int minMid = peakBinsIndex[r] - (widthMidBand / 2); int maxMid = peakBinsIndex[r] + (widthMidBand / 2); // find the average energy double midBandAvgEnergy = CalculateAverageEnergy(spectrum, minMid, maxMid); //find the boundaries of top frequency band: the min bin index and the max bin index int minTop = maxMid + 1; //maxMid + 2; // int maxTop = minTop + topBufferSize; // find the average energy double topBandAvgEnergy = CalculateAverageEnergy(spectrum, minTop, maxTop); //find the boundaries of top frequency band: the min bin index and the max bin index int maxBottom = minMid - 1; //minMid - 2; // int minBottom = maxBottom - bottomBufferSize; // find the average energy double bottomBandAvgEnergy = CalculateAverageEnergy(spectrum, minBottom, maxBottom); // peak energy in each spectrum //double peakEnergy = midBandAvgEnergy - ((topBandAvgEnergy + bottomBandAvgEnergy) / 2); double peakEnergyInDb = 10 * Math.Log10(midBandAvgEnergy / ((topBandAvgEnergy + bottomBandAvgEnergy) / 2)); int[] ind = new int[2]; int[] bandInd = new int[5]; // convert avg energy to decibel values //var peakEnergyInDb = 10 * Math.Log10(peakEnergy); // record the peak if the peak energy is higher than a threshold if (peakEnergyInDb > threshold) { ind[0] = r; ind[1] = peakBinsIndex[r]; targetPeakBinsIndex.Add(ind); } // saving the index of top, mid, and bottom band boundaries bandInd[0] = r; bandInd[1] = minBottom; bandInd[2] = minMid; bandInd[3] = maxMid; bandInd[4] = maxTop; bandIndex.Add(bandInd); } return(Tuple.Create(targetPeakBinsIndex.ToArray(), bandIndex.ToArray())); }