Skip to content

Commit

Permalink
added a new method for peak tracking
Browse files Browse the repository at this point in the history
  • Loading branch information
mkholghi authored and atruskie committed Feb 4, 2019
1 parent 01054f2 commit 2af60bf
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,12 @@ public static void Execute(Arguments arguments)

// Noise Reduction to be added

var output = SpectralPeakTracking2018.SpectralPeakTracking(energySpectrogram.Data, configuration.SptSettings, hertzPerFreqBin);
//var output = SpectralPeakTracking2018.SpectralPeakTracking(energySpectrogram.Data, configuration.SptSettings, hertzPerFreqBin);

// draw the local peaks
double[,] hits = SpectralPeakTracking2018.MakeHitMatrix(energySpectrogram.Data, output.TargetPeakBinsIndex, output.BandIndex);
var image = SpectralPeakTracking2018.DrawSonogram(decibelSpectrogram, hits);
image.Save(imagePath, ImageFormat.Bmp);
//double[,] hits = SpectralPeakTracking2018.MakeHitMatrix(energySpectrogram.Data, output.TargetPeakBinsIndex, output.BandIndex);
//var image = SpectralPeakTracking2018.DrawSonogram(decibelSpectrogram, hits);
//image.Save(imagePath, ImageFormat.Bmp);
}
}
}
105 changes: 95 additions & 10 deletions src/AudioAnalysisTools/SpectralPeakTracking2018.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ namespace AudioAnalysisTools
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using Accord.Statistics.Kernels;
using Acoustics.Shared.Csv;
using StandardSpectrograms;
using TowseyLibrary;

Expand All @@ -21,10 +24,12 @@ public class Output

public int[][] BandIndex { get; set; }

public List<SpectralTrack> SpecTracks { get; set; }
public object[][] peakTrackInfoList { get; set; }

//public List<SpectralTrack> SpecTracks { get; set; }
}

public static Output SpectralPeakTracking(double[,] spectrogram, SpectralPeakTrackingSettings settings, double hertzPerFreqBin)
public static Output SpectralPeakTracking(double[,] spectrogram, SpectralPeakTrackingSettings settings, double hertzPerFreqBin, double timePerFrame)
{
if (spectrogram == null)
{
Expand All @@ -47,22 +52,26 @@ public static Output SpectralPeakTracking(double[,] spectrogram, SpectralPeakTra
// make an array of the index of local peaks. Zero means there is no local peak identified.
int[] SpectralPeakArray = MakeSpectralPeakArray(spectrogram, localPeaksAndBands.Item1);

var peakTrackInfo = SpectralPeakTracking(spectrogram, SpectralPeakArray, timePerFrame, hertzPerFreqBin);

/*
// Do Spectral Peak Tracking
// debug this
double frameDuration = (1024 * (1 - 0.2)) / 22050;
double framesPerSecond = 1 / frameDuration;
int herzOffset = 0;
TimeSpan minDuration = TimeSpan.FromMilliseconds(40);
TimeSpan maxIntraSyllableGap = TimeSpan.FromMilliseconds(350);
int maxFreq = 6000; //???
// debug this
// Do Spectral Peak Tracking
var spectralTracks = SpectralTrack.GetSpectralTracks(SpectralPeakArray, framesPerSecond, hertzPerFreqBin, herzOffset, minDuration, maxIntraSyllableGap, maxFreq);

*/
var output = new Output()
{
TargetPeakBinsIndex = localPeaksAndBands.Item1,
BandIndex = localPeaksAndBands.Item2,
SpecTracks = spectralTracks,
//SpecTracks = spectralTracks,
peakTrackInfoList = peakTrackInfo,
};

return output;
Expand Down Expand Up @@ -116,27 +125,28 @@ public static Tuple<int[][], int[][]> FindLocalSpectralPeaks(double[,] matrix, i
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;
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;
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 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);
//var peakEnergyInDb = 10 * Math.Log10(peakEnergy);

// record the peak if the peak energy is higher than a threshold
if (peakEnergyInDb > threshold)
Expand All @@ -158,6 +168,59 @@ public static Tuple<int[][], int[][]> FindLocalSpectralPeaks(double[,] matrix, i
return Tuple.Create(targetPeakBinsIndex.ToArray(), bandIndex.ToArray());
}

public static object[][] SpectralPeakTracking(double[,] spectrogram, int[] SpectralPeakArray, double timePerFrame, double hertzPerFreqBin)
{
int startX;
int endX;
int startY;
int endY;
int peakCount = 0;
var score = 0;
List<object[]> peakTrackInfoList = new List<object[]>();

for (int i = 0; i < SpectralPeakArray.Length; i++)
{
if (SpectralPeakArray[i] != 0)
{
object[] peakTrackInfo = new object[6];
startX = i;
startY = SpectralPeakArray[i] - 2;
endX = startX + 17;
endY = startY + 4;
//double[,] targetMatrix = GetArbitraryMatrix(spectrogram, startY, endY, startX, endX);
for (int j = startX; j < endX; j++)
{
if (SpectralPeakArray[j] >= startY && SpectralPeakArray[j] <= endY)
{
peakCount++;
}
}

score = peakCount / 18;

peakTrackInfo[0] = i; // frame number
peakTrackInfo[1] = i * timePerFrame;
peakTrackInfo[2] = SpectralPeakArray[i]; // bin number
peakTrackInfo[3] = SpectralPeakArray[i] * hertzPerFreqBin;
peakTrackInfo[4] = score;

if (score >= 4 / 18)
{
peakTrackInfo[5] = "Yes";
}
else
{
peakTrackInfo[5] = "No";
}

peakTrackInfoList.Add(peakTrackInfo);
}
}

return peakTrackInfoList.ToArray();

}

/// <summary>
/// outputs the average energy within a specified band
/// </summary>
Expand Down Expand Up @@ -198,6 +261,28 @@ public static double CalculateAverageEnergy(double[] spectrum, int minInd, int m
return outputMatrix;
}

/// <summary>
/// outputs a matrix with arbitrary boundaries to Y (freq) and X (time) axes.
/// </summary>
public static double[,] GetArbitraryMatrix(double[,] matrix, int startY, int endY, int startX, int endX)
{
double[,] outputMatrix = new double[endX - startX + 1, endY - startY + 1];

int minColumnIndex = startY - 1;
int maxColumnIndex = endY - 1;

// copying a part of the original matrix with pre-defined boundaries to X and Y axes to a new matrix
for (int row = startX; row <= endX; row++)
{
for (int col = startY; col <= endY; col++)
{
outputMatrix[row - startX, col - startY] = matrix[row, col];
}
}

return outputMatrix;
}

/// <summary>
/// outputs a matrix with the same size of the input matrix.
/// all values are zero, except the points of interest (i.e., local spectral peaks).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,10 @@ public void FindLocalSpectralPeaksTest()
public void LocalSpectralPeakTest()
{
var configPath = @"C:\Users\kholghim\Mahnoosh\Night_parrot\SpectralPeakTrackingConfig.yml";
var recordingPath = @"C:\Users\kholghim\Mahnoosh\Night_parrot\JY-(cleaned)-3-Night_Parrot-pair.Western_Qld_downsampled.wav"; //"C:\Users\kholghim\Mahnoosh\Night_parrot\SM16 24 Sep 2018 6.30 am.wav"; //"C:\Users\kholghim\Mahnoosh\Night_parrot\S4A07296_20180419_050023_11-12min.wav"; //"M:\Postdoc\Night_parrot\S4A07296_20180419_050023_Ch1.wav"; //
var imagePath = @"C:\Users\kholghim\Mahnoosh\Night_parrot\image.bmp"; //image_NP_SM16 24 Sep 2018 6.30 am.bmp";
var trackImagePath = @"C:\Users\kholghim\Mahnoosh\Night_parrot\trackImage.bmp";
var recordingPath = @"Y:\RichardSeaton\NP Monitoring\Kalamurina May18\Night Parrot calls Kala 2018\SM7 24 Sep 2018 5.30 am.wav";// "Y:\RichardSeaton\NP Monitoring\Kalamurina May18\Night Parrot calls Kala 2018\SM27 22 Sep 2018 3.30 am.wav"; //"Y:\RichardSeaton\NP Monitoring\Kalamurina May18\Night Parrot calls Kala 2018\SM16 24 Sep 2018 6.30 am.wav"; //"Y:\RichardSeaton\NP Monitoring\Kalamurina May18\Night Parrot calls Kala 2018\SM16 23 Sep 2018 6.30 am.wav"; //"Y:\RichardSeaton\NP Monitoring\Kalamurina May18\Night Parrot calls Kala 2018\SM7 24 Sep 2018 6.30 am.wav"; //"Y:\RichardSeaton\NP Monitoring\Kalamurina May18\Night Parrot calls Kala 2018\SM7 24 Sep 2018 5.30 am.wav";// "Y:\RichardSeaton\NP Monitoring\Kalamurina May18\Night Parrot calls Kala 2018\SM4 24 Sep 2018 6.30 am.wav"; //"C:\Users\kholghim\Mahnoosh\Night_parrot\Night Parrot call-WA-hollow whistle-didit.wav";//"Y:\RichardSeaton\NP Monitoring\Kalamurina May18\Night Parrot calls Kala 2018\SM3 24 Sep 2018 6.30 am.wav"; //"C:\Users\kholghim\Mahnoosh\Night_parrot\JY-(cleaned)-3-Night_Parrot-pair.Western_Qld_downsampled.wav"; //"C:\Users\kholghim\Mahnoosh\Night_parrot\SM16 24 Sep 2018 6.30 am.wav"; //"C:\Users\kholghim\Mahnoosh\Night_parrot\S4A07296_20180419_050023_11-12min.wav"; //"M:\Postdoc\Night_parrot\S4A07296_20180419_050023_Ch1.wav"; //
var imagePath = @"C:\Users\kholghim\Mahnoosh\Night_parrot\image_whistle_peaks_SM7 24 Sep 2018 5.30 am_1500_3500_100_250_3.bmp"; //image_NP_SM16 24 Sep 2018 6.30 am.bmp";
//var trackImagePath = @"C:\Users\kholghim\Mahnoosh\Night_parrot\trackImage.bmp";
var pathToCsvFile = @"C:\Users\kholghim\Mahnoosh\Night_parrot\PeakTrackInfo.csv";

var configFile = configPath.ToFileInfo();

Expand Down Expand Up @@ -109,6 +110,10 @@ public void LocalSpectralPeakTest()
NoiseReductionType = NoiseReductionType.None,
};

var frameStep = frameSize - (frameSize / frameOverlap);
var secondsPerFrame = frameSize / (nyquist * 2);
var timePerFrame = frameStep * secondsPerFrame;

//var sonogram = new SpectrogramStandard(sonoConfig, recording.WavReader);
var amplitudeSpectrogram = new AmplitudeSonogram(sonoConfig, recording.WavReader);
var energySpectrogram = new EnergySpectrogram(amplitudeSpectrogram);
Expand All @@ -117,16 +122,18 @@ public void LocalSpectralPeakTest()
// Noise Reduction to be added
//var noiseReducedSpectrogram = SNR.NoiseReduce_Standard(energySpectrogram.Data);

var output = SpectralPeakTracking2018.SpectralPeakTracking(energySpectrogram.Data, configuration.SptSettings, hertzPerFreqBin);
var output = SpectralPeakTracking2018.SpectralPeakTracking(energySpectrogram.Data, configuration.SptSettings, hertzPerFreqBin, timePerFrame);

// draw the local peaks
double[,] hits = SpectralPeakTracking2018.MakeHitMatrix(energySpectrogram.Data, output.TargetPeakBinsIndex, output.BandIndex);
var image = SpectralPeakTracking2018.DrawSonogram(decibelSpectrogram, hits);
image.Save(imagePath, ImageFormat.Bmp);

Csv.WriteToCsv(pathToCsvFile.ToFileInfo(), output.peakTrackInfoList);

// draw spectral tracks
var trackImage = SpectralPeakTracking2018.DrawTracks(decibelSpectrogram, hits, output.SpecTracks);
trackImage.Save(trackImagePath, ImageFormat.Bmp);
//var trackImage = SpectralPeakTracking2018.DrawTracks(decibelSpectrogram, hits, output.SpecTracks);
//trackImage.Save(trackImagePath, ImageFormat.Bmp);

}
}
Expand Down

0 comments on commit 2af60bf

Please sign in to comment.