Skip to content

Commit

Permalink
cleaned up the PreopusSpecies class
Browse files Browse the repository at this point in the history
REmoved a lot of unnecessary commented code.
Also improved call detection.
Next step is to add additional contraints to the call spectrum to match that of bat call.
  • Loading branch information
towsey authored and atruskie committed Aug 28, 2019
1 parent c86caaa commit aa85432
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 116 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ SegmentOverlap: 0
SaveIntermediateWavFiles: Never
SaveIntermediateCsvFiles: false
# Available options (case-sensitive): [False/Never | True/Always | WhenEventsDetected]
SaveSonogramImages: Never
SaveSonogramImages: True
# DisplayCsvImage is obsolete - ensure it remains set to: false
DisplayCsvImage: false
## End section for AnalyzeLongRecording
Expand Down
123 changes: 15 additions & 108 deletions src/AnalysisPrograms/Recognizers/PteropusSpecies.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,36 +103,14 @@ internal static RecognizerResults Gruntwork(AudioRecording audioRecording, Confi
int minHz = configuration.GetIntOrNull(AnalysisKeys.MinHz) ?? 500;
int maxHz = configuration.GetIntOrNull(AnalysisKeys.MaxHz) ?? 8000;

//var samples = audioRecording.WavReader.Samples;
//double minDuration = configuration.GetIntOrNull(AnalysisKeys.MinDuration) ?? 0.1;
//double maxDuration = configuration.GetIntOrNull(AnalysisKeys.MaxDuration) ?? 0.5;
var neighbourhoodDuration = TimeSpan.FromSeconds(0.05);

double intensityNormalisationMax = 12.0; // decibels
double intensityThreshold = 9.0; // decibels
var eventThreshold = intensityThreshold / intensityNormalisationMax;


// Get a value from the config file - without a string accessor, as a double
//double someExampleSettingA = configuration.GetDoubleOrNull("SomeExampleSettingA") ?? 0.0;

/*
* Examples of using profiles
// Examples of the APIs available. You don't need all of these commands! Pick and choose.
bool hasProfiles = ConfigFile.HasProfiles(configuration);
//Config profile = ConfigFile.GetProfile<Config, Aed.AedConfiguration>(configuration, "Groote");
Config profile2;
//bool success = ConfigFile.TryGetProfile(configuration, "FemaleRelease", out profile2);
//string[] profileNames = ConfigFile.GetProfileNames<Config>(configuration);
// IEnumerable<(string Name, object Profile)> allProfiles = ConfigFile.GetAllProfiles<IProfile<object>>(configuration);
// foreach (var profile in allProfiles)
// {
// object currentProfile = profile.Profile;
// Log.Info(profile.Name + ": " + ((int)currentProfile.MinHz).ToString());
// }
*/
double decibelsIntensityThreshold = configuration.GetDoubleOrNull(AnalysisKeys.NoiseBgThreshold) ?? 12.0;
double intensityNormalisationMax = 3 * decibelsIntensityThreshold;
var eventThreshold = decibelsIntensityThreshold / intensityNormalisationMax;

//######################
//2.Convert each segment to a spectrogram.
Expand All @@ -154,7 +132,7 @@ internal static RecognizerResults Gruntwork(AudioRecording audioRecording, Confi

//var data = sonogram.Data;
//var intensityArray = MatrixTools.GetRowAverages(data);
intensityArray = DataTools.NormaliseInZeroOne(intensityArray, 0, 12);
intensityArray = DataTools.NormaliseInZeroOne(intensityArray, 0, intensityNormalisationMax);
var plot = new Plot(speciesName, intensityArray, eventThreshold);
var plots = new List<Plot> { plot };

Expand All @@ -178,64 +156,27 @@ internal static RecognizerResults Gruntwork(AudioRecording audioRecording, Confi
ae.Name = abbreviatedSpeciesName;
});

var sonoImage = SpectrogramTools.GetSonogramPlusCharts(sonogram, acousticEvents, plots, null);
//var sonoImage = sonogram.GetImageFullyAnnotated("Test");
var sonoImage = SpectrogramTools.GetSonogramPlusCharts(sonogram, acousticEvents, plots, null);

//var opPath =
// outputDirectory.Combine(
// FilenameHelpers.AnalysisResultName(
// Path.GetFileNameWithoutExtension(recording.BaseName), speciesName, "png", "DebugSpectrogram"));
//sonoImage.Save(opPath.FullName);

string imageFilename = audioRecording.BaseName + ".png";
sonoImage.Save(Path.Combine(outputDirectory.FullName, imageFilename));

// get samples
//var samples = audioRecording.WavReader.Samples;

// Profile example: running the same algorithm on every profile with different settings (regional variation)
/*
List<AcousticEvent> allAcousticEvents = new List<AcousticEvent>();
Dictionary<string, Config> allProfiles = ConfigFile.GetAllProfiles(configuration);
foreach (var kvp in allProfiles)
{
string profileName = kvp.Key;
Log.Info($"Analyzing profile: {profileName}");
Config currentProfile = kvp.Value;
// extract parameters
int minHz = (int)configuration[AnalysisKeys.MinHz];
// ...
// run the algorithm
List<AcousticEvent> acousticEvents;
Oscillations2012.Execute( All the correct parameters, minHz);
// augment the returned events
acousticEvents.ForEach(ae =>
{
ae.SpeciesName = speciesName;
ae.Profile = profileName;
ae.AnalysisIdealSegmentDuration = recordingDuration;
ae.Name = abbreviatedSpeciesName;
});
// add events found in this profile to the total list
allAcousticEvents.AddRange(acousticEvents);
}
*/

// Profile example: running a different algorithm on different profiles
/*
bool hasProfiles = ConfigFile.HasProfiles(configuration);
if (hasProfiles)
return new RecognizerResults()
{
// add resulting events from each algorithm into the combined event list
allAcousticEvents.AddRange(RunFemaleProfile(...all the arguments));
allAcousticEvents.AddRange(RunMaleProfile(...all the arguments));
}
Events = acousticEvents,
Hits = null,
ScoreTrack = null,
Plots = plots,
Sonogram = sonogram,
};
}

/*
// example method
private static List<AcousticEvent> RunFemaleProfile(configuration, rest of arguments)
{
Expand Down Expand Up @@ -264,39 +205,5 @@ private static List<AcousticEvent> RunFemaleProfile(configuration, rest of argum
return acousticEvents;
}
*/


// get high resolution indices
/*
var foundEvents = new List<AcousticEvent>();
// some kind of loop where you scan through the audio
// 'find' a Flying Fox event - if you find an event, store the data in the AcousticEvent class
var anEvent = new AcousticEvent(
segmentStartOffset,
new Oblong(50, 50, 100, 100),
sonogram.NyquistFrequency,
sonogram.Configuration.FreqBinCount,
sonogram.FrameDuration,
sonogram.FrameStep,
sonogram.FrameCount)
{
Name = "Flying Fox",
};
foundEvents.Add(anEvent);
*/
return new RecognizerResults()
{
Events = acousticEvents,
Hits = null,
ScoreTrack = null,

//Plots = null,
Sonogram = sonogram,
};
}
}
}
18 changes: 11 additions & 7 deletions src/AudioAnalysisTools/AcousticEvent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1138,18 +1138,19 @@ public static List<AcousticEvent> GetEventsAroundMaxima(
// for all frames
for (int i = frameBuffer; i < count - frameBuffer; i++)
{
// skip if value below threshold
if (values[i] < thresholdValue)
// get the neighbourhood
var nhArray = DataTools.Subarray(values, i - frameBuffer, eventLength);
double avValue = nhArray.Average();

// skip if average value over the neighbourhood below threshold
if (avValue < thresholdValue)
{
continue;
}

// get the neighbourhood
var nhArray = DataTools.Subarray(values, i - frameBuffer, eventLength);
// if local maximum just prior to middle frame AND average of values > threshold, THEN have an event
int maxId = DataTools.GetMaxIndex(nhArray);

// if middle frame is a local maximum then have an event
if (maxId == frameBuffer)
if (maxId == (frameBuffer - 2))
{
double startTime = (i - frameBuffer) * frameOffset; // time in seconds
AcousticEvent ev = new AcousticEvent(segmentStartOffset, startTime, eventDuration, minHz, maxHz)
Expand All @@ -1162,6 +1163,9 @@ public static List<AcousticEvent> GetEventsAroundMaxima(
//obtain average intensity score.
ev.Score = nhArray.Average();
events.Add(ev);

// jump to end of event
i += eventLength;
}
}

Expand Down

0 comments on commit aa85432

Please sign in to comment.