Skip to content

Commit

Permalink
Calculating spectral indices per band
Browse files Browse the repository at this point in the history
  • Loading branch information
aroelo authored and atruskie committed Jan 17, 2018
1 parent 0e1cb1c commit 88771ea
Show file tree
Hide file tree
Showing 9 changed files with 1,373 additions and 142 deletions.
716 changes: 716 additions & 0 deletions AudioAnalysis/AnalysisPrograms/AcousticIndices - Copy (2).cs

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions AudioAnalysis/AnalysisPrograms/AnalysisPrograms.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="AcousticHiResIndicesPlusRecognizers.cs" />
<Compile Include="AcousticIndices - Copy %282%29.cs" />
<Compile Include="AcousticWorkbench.Orchestration\EventMetadataResolver.cs" />
<Compile Include="AcousticWorkbench.Orchestration\RemoteSegment.cs" />
<Compile Include="AED.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,10 @@ public override AnalysisResult2 Analyze<T>(AnalysisSettings analysisSettings, Se
var recording = new AudioRecording(audioFile.FullName);
var outputDirectory = segmentSettings.SegmentOutputDirectory;

//double epsilon = recording.Epsilon;
//int sampleRate = recording.WavReader.SampleRate;
//int nyquist = sampleRate / 2;

//// Fileinfo class for the index properties configuration file
//FileInfo IndexPropertiesConfig = new FileInfo(configuration.IndexPropertiesConfig);
//var indexProperties = IndexProperties.GetIndexProperties(IndexPropertiesConfig);
//TimeSpan IndexCalculationDuration = new TimeSpan(0, 0, (int)configuration.IndexCalculationDuration);
FileInfo IndexPropertiesConfig = new FileInfo(configuration.IndexPropertiesConfig);
var indexProperties = IndexProperties.GetIndexProperties(IndexPropertiesConfig);
TimeSpan IndexCalculationDuration = new TimeSpan(0, 0, (int)configuration.IndexCalculationDuration);

var analysisResults = new AnalysisResult2(analysisSettings, segmentSettings, recording.Duration);
analysisResults.AnalysisIdentifier = this.Identifier;
Expand All @@ -103,60 +99,32 @@ public override AnalysisResult2 Analyze<T>(AnalysisSettings analysisSettings, Se
int frameSize = band.FftWindow;
int frameStep = frameSize;

//int freqBinCount = frameSize / 2;

//int midFreqBound = configuration.MidFreqBound;
//int lowFreqBound = configuration.LowFreqBound;

// EXTRACT ENVELOPE and SPECTROGRAM FROM SUBSEGMENT
var dspOutput1 = DSP_Frames.ExtractEnvelopeAndFfts(subsegmentRecording, frameSize, frameStep);

//var dspOutput2 = dspOutput1;

//// Linear or Octave frequency scale? Set Linear as default.
//var freqScale = new FrequencyScale(nyquist: nyquist, frameSize: frameSize, hertzLinearGridInterval: 1000);
//var freqScaleType = configuration.FrequencyScale;
//bool octaveScale = freqScaleType == "Octave";
//if (octaveScale)
//{
// // only allow one octave scale at the moment - for Jasco marine recordings.
// // ASSUME fixed Occtave scale - USEFUL ONLY FOR JASCO 64000sr MARINE RECORDINGS
// // If you wish to use other octave scale types then need to put in the config file and and set up recovery here.
// freqScale = new FrequencyScale(FreqScaleType.Linear125Octaves7Tones28Nyquist32000);

// // Recalculate the spectrogram according to octave scale. This option works only when have high SR recordings.
// dspOutput1.AmplitudeSpectrogram = OctaveFreqScale.AmplitudeSpectra(
// dspOutput1.AmplitudeSpectrogram,
// dspOutput1.WindowPower,
// sampleRate,
// epsilon,
// freqScale);
// dspOutput1.NyquistBin = dspOutput1.AmplitudeSpectrogram.GetLength(1) - 1; // ASSUMPTION!!! Nyquist is in top Octave bin - not necessarily true!!
//}

// Prepare amplitude spectrogram
double[,] amplitudeSpectrogramData = dspOutput1.AmplitudeSpectrogram; // get amplitude spectrogram.
double[,] m;
double[,] amplitudeSpectrogramData2;

// Transform from Frequency to Mel Scale
// band.Melscale defines the number of bins that will be reduced to
if (band.MelScale != 0)
{
m = MFCCStuff.MelFilterBank(amplitudeSpectrogramData, band.MelScale, recording.Nyquist, 0, recording.Nyquist);
amplitudeSpectrogramData2 = MFCCStuff.MelFilterBank(amplitudeSpectrogramData, band.MelScale, recording.Nyquist, 0, recording.Nyquist);
}
else
{
m = amplitudeSpectrogramData;
amplitudeSpectrogramData2 = amplitudeSpectrogramData;
}

// Select band determined by min and max bandwidth
int minBand = (int)(m.GetLength(1) * band.Bandwidth.Min);
int maxBand = (int)(m.GetLength(1) * band.Bandwidth.Max) - 1;
int minBand = (int)(amplitudeSpectrogramData2.GetLength(1) * band.Bandwidth.Min);
int maxBand = (int)(amplitudeSpectrogramData2.GetLength(1) * band.Bandwidth.Max) - 1;

double[,] mband = MatrixTools.Submatrix(m, 0, minBand, m.GetLength(0) - 1, maxBand);
double[,] amplitudeSpectrogramDataBand = MatrixTools.Submatrix(amplitudeSpectrogramData2, 0, minBand, amplitudeSpectrogramData2.GetLength(0) - 1, maxBand);

// Create image of amplitude spectrogram
var image = ImageTools.DrawReversedMatrix(MatrixTools.MatrixRotate90Anticlockwise(mband));
var image = ImageTools.DrawReversedMatrix(MatrixTools.MatrixRotate90Anticlockwise(amplitudeSpectrogramDataBand));

// Add image to list
list.Add(image);
Expand All @@ -167,103 +135,8 @@ public override AnalysisResult2 Analyze<T>(AnalysisSettings analysisSettings, Se
maxImageWidth = image.Width;
}

// // INITIALISE a RESULTS STRUCTURE TO return
// // initialize a result object in which to store SummaryIndexValues and SpectralIndexValues etc.
// var result = new IndexCalculateResult(freqBinCount, indexProperties, IndexCalculationDuration, subsegmentOffsetTimeSpan);
// SummaryIndexValues summaryIndices = result.SummaryIndexValues;
// SpectralIndexValues spectralIndices = result.SpectralIndexValues;

// // (B) ################################## EXTRACT SPECTRAL INDICES FROM THE AMPLITUDE SPECTROGRAM ##################################

// // i: CALCULATE SPECTRUM OF THE SUM OF FREQ BIN AMPLITUDES - used for later calculation of ACI
// spectralIndices.SUM = MatrixTools.SumColumns(m);

// // Calculate lower and upper boundary bin ids.
// // Boundary between low & mid frequency bands is to avoid low freq bins containing anthropogenic noise. These biased index values away from biophony.
// // Boundary of upper bird-band is to avoid high freq artefacts due to mp3.
// int lowerBinBound = (int)Math.Ceiling(lowFreqBound / dspOutput1.FreqBinWidth);
// int middleBinBound = (int)Math.Ceiling(midFreqBound / dspOutput1.FreqBinWidth);

// // calculate number of freq bins in the bird-band.
// int midBandBinCount = middleBinBound - lowerBinBound + 1;

// if (octaveScale)
// {
// // the above frequency bin bounds do not apply with octave scale. Need to recalculate them suitable for Octave scale recording.
// lowFreqBound = freqScale.LinearBound;
// lowerBinBound = freqScale.GetBinIdForHerzValue(lowFreqBound);

// midFreqBound = 8000; // This value appears suitable for Jasco Marine recordings. Not much happens above 8kHz.

// //middleBinBound = freqScale.GetBinIdForHerzValue(midFreqBound);
// middleBinBound = freqScale.GetBinIdInReducedSpectrogramForHerzValue(midFreqBound);
// midBandBinCount = middleBinBound - lowerBinBound + 1;
// }

// // IFF there has been UP-SAMPLING, calculate bin of the original audio nyquist. this will be less than SR/2.
// // original sample rate can be anything 11.0-44.1 kHz.
// int sampleRateOfOriginalAudioFile = segmentSettings.Segment.SourceMetadata.SampleRate;
// int originalNyquist = sampleRateOfOriginalAudioFile / 2;

// // if upsampling has been done
// if (dspOutput1.NyquistFreq > originalNyquist)
// {
// dspOutput1.NyquistFreq = originalNyquist;
// dspOutput1.NyquistBin = (int)Math.Floor(originalNyquist / dspOutput1.FreqBinWidth); // note that binwidth does not change
// }

// // ii: CALCULATE THE ACOUSTIC COMPLEXITY INDEX
// spectralIndices.DIF = AcousticComplexityIndex.SumOfAmplitudeDifferences(m);

// double[] aciSpectrum = AcousticComplexityIndex.CalculateACI(m);
// spectralIndices.ACI = aciSpectrum;

// // remove low freq band of ACI spectrum and store average ACI value
// double[] reducedAciSpectrum = DataTools.Subarray(aciSpectrum, lowerBinBound, midBandBinCount);
// summaryIndices.AcousticComplexity = reducedAciSpectrum.Average();

// // iii: CALCULATE the H(t) or Temporal ENTROPY Spectrum and then reverse the values i.e. calculate 1-Ht for energy concentration
// double[] temporalEntropySpectrum = AcousticEntropy.CalculateTemporalEntropySpectrum(m);
// for (int i = 0; i < temporalEntropySpectrum.Length; i++)
// {
// temporalEntropySpectrum[i] = 1 - temporalEntropySpectrum[i];
// }

// spectralIndices.ENT = temporalEntropySpectrum;

// // iv: remove background noise from the amplitude spectrogram
// // First calculate the noise profile from the amplitude sepctrogram
// double[] spectralAmplitudeBgn = NoiseProfile.CalculateBackgroundNoise(dspOutput2.AmplitudeSpectrogram);
// m = SNR.TruncateBgNoiseFromSpectrogram(m, spectralAmplitudeBgn);

// // AMPLITUDE THRESHOLD for smoothing background, nhThreshold, assumes background noise ranges around -40dB.
// // This value corresponds to approximately 6dB above backgorund.
// m = SNR.RemoveNeighbourhoodBackgroundNoise(m, nhThreshold: 0.015);
// ////ImageTools.DrawMatrix(spectrogramData, @"C:\SensorNetworks\WavFiles\Crows\image.png", false);
// ////DataTools.writeBarGraph(modalValues);

// // v: ENTROPY OF AVERAGE SPECTRUM & VARIANCE SPECTRUM - at this point the spectrogram is a noise reduced amplitude spectrogram
// var tuple = AcousticEntropy.CalculateSpectralEntropies(m, lowerBinBound, midBandBinCount);

// // ENTROPY of spectral averages - Reverse the values i.e. calculate 1-Hs and 1-Hv, and 1-Hcov for energy concentration
// summaryIndices.EntropyOfAverageSpectrum = 1 - tuple.Item1;

// // ENTROPY of spectrum of Variance values
// summaryIndices.EntropyOfVarianceSpectrum = 1 - tuple.Item2;

// // ENTROPY of spectrum of Coefficient of Variation values
// summaryIndices.EntropyOfCoVSpectrum = 1 - tuple.Item3;

// // vi: ENTROPY OF DISTRIBUTION of maximum SPECTRAL PEAKS.
// // First extract High band SPECTROGRAM which is now noise reduced
// double entropyOfPeaksSpectrum = AcousticEntropy.CalculateEntropyOfSpectralPeaks(m, lowerBinBound, middleBinBound);
// summaryIndices.EntropyOfPeaksSpectrum = 1 - entropyOfPeaksSpectrum;

// Calculate spectral indices

TimeSpan IndexCalculationDuration = new TimeSpan(0, 0, (int)configuration.IndexCalculationDuration);
FileInfo IndexPropertiesConfig = new FileInfo(configuration.IndexPropertiesConfig);

// calculate indices for each subsegment for each band
IndexCalculateResult[] subsegmentResults = Acoustic.CalculateIndicesInSubsegments(
recording,
Expand All @@ -280,6 +153,7 @@ public override AnalysisResult2 Analyze<T>(AnalysisSettings analysisSettings, Se

analysisResults.SummaryIndices = new SummaryIndexBase[subsegmentResults.Length];
analysisResults.SpectralIndices = new SpectralIndexBase[subsegmentResults.Length];

for (int i = 0; i < subsegmentResults.Length; i++)
{
var indexCalculateResult = subsegmentResults[i];
Expand All @@ -304,10 +178,17 @@ public override AnalysisResult2 Analyze<T>(AnalysisSettings analysisSettings, Se

if (analysisSettings.AnalysisDataSaveBehavior)
{
string FftWindowDescription = "FftWindow" + band.FftWindow.ToString();
string MelDescription = "Mel" + band.MelScale.ToString();
string BandWidthDescription = "BandWidth" + minBand.ToString() + "-" + maxBand.ToString();

string fileNameBase = Path.GetFileNameWithoutExtension(segmentSettings.SegmentAudioFile.Name) +
"_" + FftWindowDescription + "_" + MelDescription + "_" +
BandWidthDescription;
analysisResults.SpectraIndicesFiles =
this.WriteSpectrumIndicesFiles(
segmentSettings.SegmentSpectrumIndicesDirectory,
Path.GetFileNameWithoutExtension(segmentSettings.SegmentAudioFile.Name),
fileNameBase,
analysisResults.SpectralIndices);
}
}
Expand All @@ -322,6 +203,7 @@ public override AnalysisResult2 Analyze<T>(AnalysisSettings analysisSettings, Se
analysisResults.ImageFile = new FileInfo(imagePath);
LoggedConsole.WriteLine("See {0} for spectrogram pictures", imagePath);
}


return analysisResults;
}
Expand All @@ -345,7 +227,7 @@ public List<FileInfo> WriteSpectrumIndicesFilesCustom(DirectoryInfo destination,
foreach (var kvp in selectors)
{
// write spectrogram to disk as CSV file
var filename = FilenameHelpers.AnalysisResultPath(destination, fileNameBase, this.Identifier + "." + kvp.Key, "csv").ToFileInfo();
var filename = FilenameHelpers.AnalysisResultPath(destination, fileNameBase, this.Identifier + "." + kvp.Key, "csv", "banana", "Kiwi").ToFileInfo();
spectralIndexFiles.Add(filename);
Csv.WriteMatrixToCsv(filename, results, kvp.Value);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace AnalysisPrograms.StandardizedFeatures
using AudioAnalysisTools.Indices;

[Serializable]
public class StandardizedFeatureExtractionConfig
public class StandardizedFeatureExtractionConfigDelete
{
public string AnalysisName { get; set; }

Expand Down
3 changes: 3 additions & 0 deletions AudioAnalysis/AudioAnalysisTools/AudioAnalysisTools.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,8 @@
<Compile Include="EventStatistics\EventStatisticsCalculate.cs" />
<Compile Include="FrommoltProject.cs" />
<Compile Include="Indices\GapsAndJoins.cs" />
<Compile Include="Indices\ErroneousIndexSegments.cs" />
<Compile Include="Indices\IndexCalculate - Copy.cs" />
<Compile Include="Indices\IndexCalculate.cs" />
<Compile Include="Indices\IndexCalculateConfig.cs" />
<Compile Include="Indices\IndexDistributions.cs" />
Expand All @@ -270,6 +272,7 @@
<Compile Include="Indices\IndexProperties.cs" />
<Compile Include="Indices\SpectralIndexValues.cs" />
<Compile Include="Indices\SpectralIndicesToAndFromTable.cs" />
<Compile Include="Indices\StandardizedFeatureExtractionConfig.cs" />
<Compile Include="Indices\SummaryIndexValues.cs" />
<Compile Include="Indices\InitialiseIndexProperties.cs" />
<Compile Include="Indices\RainIndices.cs" />
Expand Down
Loading

0 comments on commit 88771ea

Please sign in to comment.