/// <summary> /// This method was set up as a TESTMETHOD in May 2017 but has not yet been debugged. /// It was transferred from Sandpit.cls. It is several years old. /// Updated May 2017. /// </summary> public static void TESTMETHOD_SpectralClustering(string wavFilePath, string outputDir, int frameSize) { string imageViewer = @"C:\Windows\system32\mspaint.exe"; var recording = new AudioRecording(wavFilePath); // get recording segment // test clustering using amplitude spectrogram // double binaryThreshold = 0.07; // An amplitude threshold of 0.03 = -30 dB. A threshold of 0.05 = -26dB. // double[,] spectrogramData = GetAmplitudeSpectrogramNoiseReduced(recording, frameSize); // test clustering using decibel spectrogram double binaryThreshold = DefaultBinaryThresholdInDecibels; // A decibel threshold for converting to binary double[,] spectrogramData = GetDecibelSpectrogramNoiseReduced(recording, frameSize); //####################################################################################################################################### int nyquistFreq = recording.Nyquist; int frameCount = spectrogramData.GetLength(0); int freqBinCount = spectrogramData.GetLength(1); double binWidth = nyquistFreq / (double)freqBinCount; // We only use the midband of the Spectrogram, i.e. the band between lowerBinBound and upperBinBound. // int lowFreqBound = 1000; // int upperBinBound = freqBinCount - 5; // In June 2016, the mid-band was set to lowerBound=1000Hz, upperBound=8000hz, because this band contains most bird activity, i.e. it is the Bird-Band // This was done in order to make the cluster summary indices more reflective of bird call activity. // int lowerFreqBound = 482; int lowerFreqBound = 1000; int lowerBinBound = (int)Math.Ceiling(lowerFreqBound / binWidth); int upperFreqBound = 8000; int upperBinBound = (int)Math.Ceiling(upperFreqBound / binWidth); var midBandSpectrogram = MatrixTools.Submatrix(spectrogramData, 0, lowerBinBound, spectrogramData.GetLength(0) - 1, upperBinBound); var clusterInfo = ClusterTheSpectra(midBandSpectrogram, lowerBinBound, upperBinBound, binaryThreshold); // transfer cluster info to spectral index results var clusterSpectrum1 = RestoreFullLengthSpectrum(clusterInfo.ClusterSpectrum, freqBinCount, lowerBinBound); Console.WriteLine("Lower BinBound=" + lowerBinBound); Console.WriteLine("Upper BinBound=" + upperBinBound); Console.WriteLine("Binary Threshold=" + binaryThreshold); Console.WriteLine("Cluster Count =" + clusterInfo.ClusterCount); Console.WriteLine("Three Gram Count=" + clusterInfo.TriGramUniqueCount); // ################################################################################### // Now repeat the entire process again. This time we want to get intermediate results to superimpose on spectrogram // Need to specify additional parameters. ACTIVITY THRESHOLD - require activity in at least N bins to include spectrum for training double rowSumThreshold = DefaultRowSumThreshold; var parameters = new ClusteringParameters(lowerBinBound, upperBinBound, binaryThreshold, rowSumThreshold); TrainingDataInfo data = GetTrainingDataForClustering(midBandSpectrogram, parameters); // make a normal standard decibel spectogram on which to superimpose cluster results var stdSpectrogram = GetStandardSpectrogram(recording, frameSize); var image = DrawSonogram(stdSpectrogram, null, null, 0.0, null); SaveAndViewSpectrogramImage(image, outputDir, "test0Spectrogram.png", imageViewer); // Debug.Assert(data.TrainingDataAsSpectrogram != null, "data.TrainingDataAsSpectrogram != null"); double[,] overlay = ConvertOverlayToSpectrogramSize(data.TrainingDataAsSpectrogram, lowerBinBound, frameCount, freqBinCount); image = DrawSonogram(stdSpectrogram, null, null, 0.0, overlay); SaveAndViewSpectrogramImage(image, outputDir, "test1Spectrogram.png", imageViewer); // Return if no suitable training data for clustering if (data.TrainingData.Count <= 8) { Console.WriteLine("Abort clustering. Only {0} spectra available for training data. Must be at least 9.", data.TrainingData.Count); } else { // the following are pruning parameters double wtThreshold = rowSumThreshold; // used to remove wt vectors whose sum of wts <= threshold int hitThreshold = DefaultHitThreshold; // used to remove wt vectors which have < N hits, i.e. cluster size < N clusterInfo = ClusterAnalysis(data.TrainingData, wtThreshold, hitThreshold, data.SelectedFrames); Console.WriteLine("Binary Threshold=" + binaryThreshold); Console.WriteLine("Weight Threshold=" + wtThreshold); Console.WriteLine("Hit Threshold=" + hitThreshold); Console.WriteLine("Cluster Count=" + clusterInfo.ClusterCount); Console.WriteLine("Three Gram Count=" + clusterInfo.TriGramUniqueCount); image = DrawClusterSpectrogram(stdSpectrogram, clusterInfo, data, lowerBinBound); SaveAndViewSpectrogramImage(image, outputDir, "test2Spectrogram.png", imageViewer); // transfer cluster info to spectral index results var clusterSpectrum2 = RestoreFullLengthSpectrum(clusterInfo.ClusterSpectrum, freqBinCount, lowerBinBound); TestTools.CompareTwoArrays(clusterSpectrum1, clusterSpectrum2); } }