public static void Execute(Arguments arguments) { MainEntry.WarnIfDeveloperEntryUsed(); string title = "# EVENT PATTERN RECOGNITION."; string date = "# DATE AND TIME: " + DateTime.Now; Log.WriteLine(title); Log.WriteLine(date); Log.Verbosity = 1; string targetName = arguments.Target; // prefix of name of created files var input = arguments.Source; string recordingFileName = input.Name; string recordingDirectory = input.DirectoryName; DirectoryInfo outputDir = arguments.Config.ToFileInfo().Directory; FileInfo targetPath = outputDir.CombineFile(targetName + "_target.txt"); FileInfo targetNoNoisePath = outputDir.CombineFile(targetName + "_targetNoNoise.txt"); FileInfo noisePath = outputDir.CombineFile(targetName + "_noise.txt"); FileInfo targetImagePath = outputDir.CombineFile(targetName + "_target.png"); FileInfo paramsPath = outputDir.CombineFile(targetName + "_params.txt"); Log.WriteIfVerbose("# Output folder =" + outputDir); //i: GET RECORDING AudioRecording recording = new AudioRecording(input.FullName); //if (recording.SampleRate != 22050) recording.ConvertSampleRate22kHz(); THIS METHOD CALL IS OBSOLETE int sr = recording.SampleRate; //ii: READ PARAMETER VALUES FROM INI FILE var config = new ConfigDictionary(arguments.Config); Dictionary <string, string> dict = config.GetTable(); // framing parameters //double frameOverlap = FeltTemplates_Use.FeltFrameOverlap; // default = 0.5 double frameOverlap = double.Parse(dict["FRAME_OVERLAP"]); //frequency band int minHz = int.Parse(dict["MIN_HZ"]); int maxHz = int.Parse(dict["MAX_HZ"]); // oscillation OD parameters double dctDuration = double.Parse(dict[OscillationRecogniser.key_DCT_DURATION]); // 2.0; // seconds double dctThreshold = double.Parse(dict[OscillationRecogniser.key_DCT_THRESHOLD]); // 0.5; int minOscilFreq = int.Parse(dict[OscillationRecogniser.key_MIN_OSCIL_FREQ]); // 4; int maxOscilFreq = int.Parse(dict[OscillationRecogniser.key_MAX_OSCIL_FREQ]); // 5; bool normaliseDCT = false; // iii initialize the sonogram config class. SonogramConfig sonoConfig = new SonogramConfig(); //default values config sonoConfig.SourceFName = recording.BaseName; //sonoConfig.WindowSize = windowSize; sonoConfig.WindowOverlap = frameOverlap; // iv: generate the sonogram BaseSonogram sonogram = new SpectrogramStandard(sonoConfig, recording.WavReader); Log.WriteLine("Frames: Size={0}, Count={1}, Duration={2:f1}ms, Overlap={5:f2}%, Offset={3:f1}ms, Frames/s={4:f1}", sonogram.Configuration.WindowSize, sonogram.FrameCount, sonogram.FrameDuration * 1000, sonogram.FrameStep * 1000, sonogram.FramesPerSecond, frameOverlap); int binCount = (int)(maxHz / sonogram.FBinWidth) - (int)(minHz / sonogram.FBinWidth) + 1; Log.WriteIfVerbose("Freq band: {0} Hz - {1} Hz. (Freq bin count = {2})", minHz, maxHz, binCount); // v: extract the subband energy array Log.WriteLine("# Start extracting target event."); double[] dBArray = SNR.DecibelsInSubband(sonogram.Data, minHz, maxHz, sonogram.FBinWidth); for (int i = 0; i < sonogram.FrameCount; i++) { dBArray[i] /= binCount; // get average dB energy } double Q = 0.0; double SD = 0.0; throw new NotImplementedException("Mike changed the API here, I don't know how to fix it."); dBArray = new[] { 0.0 }; // SNR.NoiseSubtractMode(dBArray, out Q, out SD); double maxDB = 6.0; double dBThreshold = 2 * SD / maxDB; //set dB threshold to 2xSD above background noise dBArray = SNR.NormaliseDecibelArray_ZeroOne(dBArray, maxDB); dBArray = DataTools.filterMovingAverage(dBArray, 7); //Log.WriteLine("Q ={0}", Q); //Log.WriteLine("SD={0}", SD); //Log.WriteLine("Th={0}", dBThreshold); //normalised threshhold // ############################################################################################################################################# // vi: look for oscillation at required OR for ground parrots. double[] odScores = Oscillations2010.DetectOscillationsInScoreArray(dBArray, dctDuration, sonogram.FramesPerSecond, dctThreshold, normaliseDCT, minOscilFreq, maxOscilFreq); //odScores = SNR.NoiseSubtractMode(odScores, out Q, out SD); double maxOD = 1.0; odScores = SNR.NormaliseDecibelArray_ZeroOne(odScores, maxOD); odScores = DataTools.filterMovingAverage(odScores, 5); //odScores = DataTools.NormaliseMatrixValues(odScores); //NormaliseMatrixValues 0 - 1 //double odThreshold = (10 * SD) / maxOD; //set od threshold to 2xSD above background noise //double odThreshold = dctThreshold; double odThreshold = 0.4; Log.WriteLine("Max={0}", odScores.Max()); //Log.WriteLine("Q ={0}", Q); //Log.WriteLine("SD ={0}", SD); Log.WriteLine("Th ={0}", dctThreshold); //normalised threshhold // ############################################################################################################################################# // vii: LOOK FOR GROUND PARROTS USING TEMPLATE var template = GroundParrotRecogniser.ReadGroundParrotTemplateAsList(sonogram); double[] gpScores = DetectEPR(template, sonogram, odScores, odThreshold); gpScores = DataTools.normalise(gpScores); //NormaliseMatrixValues 0 - 1 // ############################################################################################################################################# // iv: SAVE extracted event as matrix of dB intensity values //FileTools.WriteMatrix2File(template, targetPath); // write template values to file PRIOR to noise removal. //FileTools.WriteMatrix2File(templateMinusNoise, targetNoNoisePath); // write template values to file AFTER to noise removal. //FileTools.WriteArray2File(noiseSubband, noisePath); // v: SAVE image of extracted event in the original sonogram string sonogramImagePath = outputDir + Path.GetFileNameWithoutExtension(recordingFileName) + ".png"; //DrawSonogram(sonogram, sonogramImagePath, dBArray, dBThreshold / maxDB, odScores, dctThreshold, gpScores, template); }
FrogRibbitRecognizer(AudioRecording recording, string filterName, int midBandFreq, double windowDuration = 5.0, double windowOverlap = 0.5, double dctDuration = 0.5, double dctThreshold = 0.4, bool normaliseDCT = false, int minOscilRate = 11, int maxOscilRate = 17, double maxOscilScore = 20.0) { int sr = recording.SampleRate; int windowSize = (int)(windowDuration * sr / 1000.0); double frameStep = windowDuration * (1 - windowOverlap); double framesPerSecond = 1000 / frameStep; //i: Apply filter Log.WriteLine("# Filter: " + filterName); var filteredRecording = AudioRecording.Filter_IIR(recording, filterName); //return new filtered audio recording. int signalLength = filteredRecording.WavReader.Samples.Length; //ii: FRAMING int[,] frameIDs = DSP_Frames.FrameStartEnds(signalLength, windowSize, windowOverlap); int frameCount = frameIDs.GetLength(0); //iii: EXTRACT ENVELOPE and ZERO-CROSSINGS Log.WriteLine("# Extract Envelope and Zero-crossings."); var results2 = DSP_Frames.ExtractEnvelopeAndZeroCrossings(filteredRecording.WavReader.Samples, sr, windowSize, windowOverlap); //double[] average = results2.Item1; double[] envelope = results2.Item2; double[] zeroCrossings = results2.Item3; //double[] sampleZCs = results2.Item4; double[] sampleStd = results2.Item5; Log.WriteLine("# Normalize values."); //iv: FRAME ENERGIES double StandardDeviationCount = 0.1; // number of noise SDs to calculate noise threshold - determines severity of noise reduction var results3 = SNR.SubtractBackgroundNoiseFromWaveform_dB(SNR.Signal2Decibels(envelope), StandardDeviationCount); var dBarray = SNR.TruncateNegativeValues2Zero(results3.NoiseReducedSignal); //v: CONVERSIONS: ZERO CROSSINGS to herz - then NORMALIZE to Fuzzy freq int[] freq = DSP_Frames.ConvertZeroCrossings2Hz(zeroCrossings, windowSize, sr); int sideBand = (int)(midBandFreq * 0.1); var fuzzyFreq = FuzzyFrequency(freq, midBandFreq, sideBand); //vi: CONVERSIONS: convert sample std deviations to milliseconds - then NORMALIZE to PROBs double[] tsd = DSP_Frames.ConvertSamples2Milliseconds(sampleStd, sr); //time standard deviation //for (int i = 0; i < tsd.Length; i++) if (tsd[i]) LoggedConsole.WriteLine(i + " = " + tsd[i]); //filter the freq array to remove values derived from frames with high standard deviation double[] tsdScores = NormalDist.Values2Probabilities(tsd); //vii: GET OSCILLATION SCORE AND NORMALIZE double[] rawOscillations = Oscillations2010.DetectOscillationsInScoreArray(dBarray, dctDuration, framesPerSecond, dctThreshold, normaliseDCT, minOscilRate, maxOscilRate); //NormaliseMatrixValues oscillation scores wrt scores obtained on a training. //double maxOscillationScore = rawOscillations[DataTools.GetMaxIndex(rawOscillations)]; //LoggedConsole.WriteLine("maxOscillationScore=" + maxOscillationScore); var oscillations = new double[dBarray.Length]; for (int i = 0; i < dBarray.Length; i++) { oscillations[i] = rawOscillations[i] / maxOscilScore; if (oscillations[i] > 1.0) { oscillations[i] = 1.0; } } //viii: COMBINE the SCORES Log.WriteLine("# Combine Scores."); var combinedScores = new double[dBarray.Length]; for (int i = 0; i < dBarray.Length; i++) { combinedScores[i] = fuzzyFreq[i] * tsdScores[i] * oscillations[i]; } //ix: fill in the oscillation scores combinedScores = Oscillations2010.FillScoreArray(combinedScores, dctDuration, framesPerSecond); return(Tuple.Create(combinedScores, filteredRecording, dBarray, tsd)); }