public static Tuple <BaseSonogram, double[, ], double[], List <AcousticEvent>, double[], TimeSpan> Execute_ODDetect(FileInfo wavPath, bool doSegmentation, int minHz, int maxHz, double frameOverlap, double dctDuration, double dctThreshold, int minOscilFreq, int maxOscilFreq, double eventThreshold, double minDuration, double maxDuration) { //i: GET RECORDING AudioRecording recording = new AudioRecording(wavPath.FullName); //if (recording.SampleRate != 22050) recording.ConvertSampleRate22kHz(); // THIS METHOD CALL IS OBSOLETE int sr = recording.SampleRate; //ii: MAKE SONOGRAM Log.WriteLine("Start sonogram."); SonogramConfig sonoConfig = new SonogramConfig(); //default values config sonoConfig.WindowOverlap = frameOverlap; sonoConfig.SourceFName = recording.BaseName; BaseSonogram sonogram = new SpectrogramStandard(sonoConfig, recording.WavReader); Log.WriteLine("Signal: Duration={0}, Sample Rate={1}", sonogram.Duration, sr); Log.WriteLine("Frames: Size={0}, Count={1}, Duration={2:f1}ms, Overlap={5:f0}%, 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); Log.WriteIfVerbose("DctDuration=" + dctDuration + "sec. (# frames=" + (int)Math.Round(dctDuration * sonogram.FramesPerSecond) + ")"); Log.WriteIfVerbose("Score threshold for oscil events=" + eventThreshold); Log.WriteLine("Start OD event detection"); //iii: DETECT OSCILLATIONS bool normaliseDCT = true; List <AcousticEvent> predictedEvents; //predefinition of results event list double[] scores; //predefinition of score array double[,] hits; //predefinition of hits matrix - to superimpose on sonogram image double[] segments; //predefinition of segmentation of recording TimeSpan analysisTime; //predefinition of Time duration taken to do analysis on this file Oscillations2010.Execute((SpectrogramStandard)sonogram, doSegmentation, minHz, maxHz, dctDuration, dctThreshold, normaliseDCT, minOscilFreq, maxOscilFreq, eventThreshold, minDuration, maxDuration, out scores, out predictedEvents, out hits, out segments, out analysisTime); return(Tuple.Create(sonogram, hits, scores, predictedEvents, segments, analysisTime)); }//end CaneToadRecogniser
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); }
/// <summary> /// Wraps up the resources into a template.ZIP file /// and then runs a test on the source recording. /// </summary> public static void Execute(Arguments arguments) { if (arguments == null) { arguments = Dev(); } string title = "# EDIT TEMPLATE."; string date = "# DATE AND TIME: " + DateTime.Now; Log.WriteLine(title); Log.WriteLine(date); //ZIP THE OUTPUT FILES const bool ZipOutput = true; FileInfo iniPath = arguments.Config; string[] nameComponents = (Path.GetFileNameWithoutExtension(iniPath.Name)).Split('_'); string targetName = nameComponents[0] + "_" + nameComponents[1]; //i: Set up the file names DirectoryInfo outputDir = iniPath.Directory; FileInfo targetImagePath = outputDir.CombineFile(targetName + "_target.png"); // input image file FileInfo binaryOpPath = outputDir.CombineFile(targetName + "_binary.bmp"); FileInfo trinaryOpPath = outputDir.CombineFile(targetName + "_trinary.bmp"); FileInfo sprOpPath = outputDir.CombineFile(targetName + "_spr.txt"); // syntactic pattern recognition file //additional files to be zipped up with template FileInfo targetPath = outputDir.CombineFile(targetName + "_target.txt"); FileInfo targetNoNoisePath = outputDir.CombineFile(targetName + "_targetNoNoise.txt"); FileInfo noisePath = outputDir.CombineFile(targetName + "_noise.txt"); //ii: READ PARAMETER VALUES FROM INI FILE var config = new ConfigDictionary(iniPath); Dictionary <string, string> dict = config.GetTable(); string sourceFile = dict[FeltTemplate_Create.key_SOURCE_RECORDING]; string sourceDir = dict[FeltTemplate_Create.key_SOURCE_DIRECTORY]; double dB_Threshold = double.Parse(dict[FeltTemplate_Create.key_DECIBEL_THRESHOLD]); double maxTemplateIntensity = double.Parse(dict[FeltTemplate_Create.key_TEMPLATE_MAX_INTENSITY]); int neighbourhood = int.Parse(dict[FeltTemplate_Create.key_DONT_CARE_NH]); //the do not care neighbourhood int lineLength = int.Parse(dict[FeltTemplate_Create.key_LINE_LENGTH]); double templateThreshold = dB_Threshold / maxTemplateIntensity; int bitmapThreshold = (int)(255 - (templateThreshold * 255)); Log.WriteLine("#################################### WRITE THE BINARY TEMPLATE ##################################"); Bitmap bitmap = ImageTools.ReadImage2Bitmap(targetImagePath.FullName); var binaryBmp = Image2BinaryBitmap(bitmap, bitmapThreshold); binaryBmp.Save(binaryOpPath.FullName); Log.WriteLine("#################################### WRITE THE TRINARY TEMPLATE ##################################"); var trinaryBmp = Image2TrinaryBitmap(binaryBmp, neighbourhood); trinaryBmp.Save(trinaryOpPath.FullName); Log.WriteLine("#################################### WRITE THE SPR TEMPLATE ##################################"); double[,] matrix = ImageTools.GreyScaleImage2Matrix(bitmap); matrix = DataTools.MatrixRotate90Clockwise(matrix); //rows=time cols=freq. //ImageTools.DrawMatrix(matrix, @"C:\SensorNetworks\Output\FELT_LewinsRail1\SPR_output1.bmp"); //int smallLengthThreshold = 10; //var tuple = SPT.doSPT(matrix, templateThreshold, smallLengthThreshold); //matrix = tuple.Item1; //ImageTools.DrawMatrix(matrix, @"C:\SensorNetworks\Output\FELT_LewinsRail1\SPR_output2.bmp"); char[,] spr = SprTools.Target2SymbolicTracks(matrix, templateThreshold, lineLength); FileTools.WriteMatrix2File(spr, sprOpPath.FullName); var tuple1 = FindMatchingEvents.Execute_One_Spr_Match(spr, matrix, templateThreshold); double sprScore = tuple1.Item1; double dBScore = sprScore * maxTemplateIntensity; Log.WriteLine("#################################### WRITE THE OSCILATION TEMPLATE ##################################"); double[,] target = FileTools.ReadDoubles2Matrix(targetPath.FullName); // oscillations in time double[,] rotatedtarget = DataTools.MatrixRotate90Clockwise(target); var colSums = DataTools.GetColumnsAverages(rotatedtarget); double[] periods = Oscillations2010.PeriodicityAnalysis(colSums); // frame periodicity LoggedConsole.WriteLine("Periodicity (sec) = {0:f3}, {1:f3}, {2:f3}", periods[0] * FeltTemplates_Use.FeltFrameOffset, periods[1] * FeltTemplates_Use.FeltFrameOffset, periods[2] * FeltTemplates_Use.FeltFrameOffset); //double oscilFreq = indexOfMaxValue / dctDuration * 0.5; //Times 0.5 because index = Pi and not 2Pi // oscillations in freq i.e. harmonics colSums = DataTools.GetColumnsAverages(target); periods = Oscillations2010.PeriodicityAnalysis(colSums); LoggedConsole.WriteLine("Periodicity (Hz) = {0:f0}, {1:f0}, {2:f0}.", periods[0] * FeltTemplates_Use.FeltFreqBinWidth, periods[1] * FeltTemplates_Use.FeltFreqBinWidth, periods[2] * FeltTemplates_Use.FeltFreqBinWidth); //double oscilFreq = indexOfMaxValue / dctDuration * 0.5; //Times 0.5 because index = Pi and not 2Pi //FileTools.WriteMatrix2File(spr, sprOpPath); // ZIP THE OUTPUT Log.WriteLine("#################################### ZIP THE TEMPLATES ##################################"); if (ZipOutput == true) { var filenames = new[] { iniPath, targetImagePath, binaryOpPath, targetPath, targetNoNoisePath, noisePath }; string biOutZipFile = outputDir + targetName + "_binaryTemplate.zip"; //FileTools.ZipFiles(filenames, biOutZipFile); filenames = new[] { iniPath, targetImagePath, trinaryOpPath, targetPath, targetNoNoisePath, noisePath }; string triOutZipFile = outputDir + targetName + "_trinaryTemplate.zip"; //FileTools.ZipFiles(filenames, triOutZipFile); filenames = new[] { iniPath, targetImagePath, sprOpPath, targetPath, targetNoNoisePath, noisePath }; string sprOutZipFile = outputDir + targetName + "_syntacticTemplate.zip"; //FileTools.ZipFiles(filenames, sprOutZipFile); // Zipping files can be done by using standard .NET 4.6 System.IO.Compression // however, this code hasn't been used in years and I've opted to just comment out the lines above throw new NotImplementedException("Zipping template files intentionally broken"); } Log.WriteLine("\n\n#################################### TEST THE EXTRACTED EVENT ON SOURCE FILE ##################################"); //vi: TEST THE EVENT ON ANOTHER FILE //felt "C:\SensorNetworks\WavFiles\Canetoad\DM420010_128m_00s__130m_00s - Toads.mp3" C:\SensorNetworks\Output\FELT_CaneToad\FELT_CaneToad_Params.txt events.txt //string testRecording = @"C:\SensorNetworks\WavFiles\Gecko\Suburban_March2010\geckos_suburban_104.mp3"; //string testRecording = @"C:\SensorNetworks\WavFiles\Gecko\Suburban_March2010\geckos_suburban_18.mp3"; //string testRecording = @"C:\SensorNetworks\WavFiles\Currawongs\Currawong_JasonTagged\West_Knoll_Bees_20091102-170000.mp3"; //string testRecording = @"C:\SensorNetworks\WavFiles\Curlew\Curlew2\Top_Knoll_-_St_Bees_20090517-210000.wav"; string listOpDir = "C:\\SensorNetworks\\Output\\FELT_templateList\\"; string templateListPath = listOpDir + "templateTestList.txt"; var list = new List <string>(); list.Add("#" + outputDir + targetName + "_binaryTemplate.zip"); list.Add("#" + outputDir + targetName + "_trinaryTemplate.zip"); list.Add("#" + outputDir + targetName + "_syntacticTemplate.zip"); FileTools.Append2TextFile(templateListPath, list); //write the template.ZIP file //TEST THE TEMPLATE ON SOURCE FILE //string[] arguments = new string[3]; /* * var args = new FeltTemplates_Use.Arguments() * { * Source = "", * arguments[0] = sourceDir + "\\" + sourceFile; * arguments[1] = templateListPath; * arguments[2] = listOpDir; * * }*/ //FeltTemplates_Use.Dev(arguments); Log.WriteLine("# Finished everything!"); }
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)); }