/// <summary> /// Initializes a new instance of the <see cref="AmplitudeSpectrogram"/> class. /// </summary> public AmplitudeSpectrogram(SpectrogramSettings config, WavReader wav) { this.Configuration = config; this.Attributes = new SpectrogramAttributes(); double minDuration = 1.0; if (wav.Time.TotalSeconds < minDuration) { LoggedConsole.WriteLine("Signal must at least {0} seconds long to produce a sonogram!", minDuration); return; } //set attributes for the current recording and spectrogram type this.Attributes.SampleRate = wav.SampleRate; this.Attributes.Duration = wav.Time; this.Attributes.NyquistFrequency = wav.SampleRate / 2; this.Attributes.Duration = wav.Time; this.Attributes.MaxAmplitude = wav.CalculateMaximumAmplitude(); this.Attributes.FrameDuration = TimeSpan.FromSeconds(this.Configuration.WindowSize / (double)wav.SampleRate); var recording = new AudioRecording(wav); var fftdata = DSP_Frames.ExtractEnvelopeAndFfts( recording, config.WindowSize, config.WindowOverlap, this.Configuration.WindowFunction); // now recover required data //epsilon is a signal dependent minimum amplitude value to prevent possible subsequent log of zero value. this.Attributes.Epsilon = fftdata.Epsilon; this.Attributes.WindowPower = fftdata.WindowPower; this.Attributes.FrameCount = fftdata.FrameCount; this.Data = fftdata.AmplitudeSpectrogram; // IF REQUIRED CONVERT TO MEL SCALE if (this.Configuration.DoMelScale) { // this mel scale conversion uses the "Greg integral" ! this.Data = MFCCStuff.MelFilterBank(this.Data, this.Configuration.MelBinCount, this.Attributes.NyquistFrequency, 0, this.Attributes.NyquistFrequency); } }
/// <summary> /// Initializes a new instance of the <see cref="BaseSonogram"/> class. /// BASE CONSTRUCTOR /// This constructor contains all steps required to prepare the amplitude spectrogram. /// The third boolean parameter is simply a place-filler to ensure a different Constructor signature. /// from the principle Constructor which follows. /// </summary> /// <param name="config">config file to use.</param> /// <param name="wav">wav.</param> /// <param name="dummy">filler boolean. Calculate in method.</param> public BaseSonogram(SonogramConfig config, WavReader wav, bool dummy) : this(config) { // As of 28 March 2017 drop capability to get sub-band of spectrogram because was not being used. // can be recovered later if desired. //bool doExtractSubband = this.SubBandMinHz > 0 || this.SubBandMaxHz < this.NyquistFrequency; this.Duration = wav.Time; double minDuration = 0.2; if (this.Duration.TotalSeconds < minDuration) { LoggedConsole.WriteLine("Signal must at least {0} seconds long to produce a sonogram!", minDuration); return; } //set config params to the current recording this.SampleRate = wav.SampleRate; this.Configuration.Duration = wav.Time; this.Configuration.SampleRate = wav.SampleRate; //also set the Nyquist this.MaxAmplitude = wav.CalculateMaximumAmplitude(); var recording = new AudioRecording(wav); var fftData = DSP_Frames.ExtractEnvelopeAndFfts( recording, config.WindowSize, config.WindowOverlap, this.Configuration.WindowFunction); // now recover required data //epsilon is a signal dependent minimum amplitude value to prevent possible subsequent log of zero value. this.Configuration.epsilon = fftData.Epsilon; this.Configuration.WindowPower = fftData.WindowPower; this.FrameCount = fftData.FrameCount; this.DecibelsPerFrame = fftData.FrameDecibels; //init normalised signal energy array but do nothing with it. This has to be done from outside this.DecibelsNormalised = new double[this.FrameCount]; this.Data = fftData.AmplitudeSpectrogram; // ENERGY PER FRAME and NORMALISED dB PER FRAME AND SNR // currently DoSnr = true by default if (config.DoSnr) { // If the FractionOfHighEnergyFrames PRIOR to noise removal exceeds SNR.FractionalBoundForMode, // then Lamel's noise removal algorithm may not work well. if (fftData.FractionOfHighEnergyFrames > SNR.FractionalBoundForMode) { Log.WriteIfVerbose("\nWARNING ##############"); Log.WriteIfVerbose( "\t############### BaseSonogram(): This is a high energy recording. Percent of high energy frames = {0:f0} > {1:f0}%", fftData.FractionOfHighEnergyFrames * 100, SNR.FractionalBoundForMode * 100); Log.WriteIfVerbose("\t############### Noise reduction algorithm may not work well in this instance!\n"); } //AUDIO SEGMENTATION/END POINT DETECTION - based on Lamel et al // Setting segmentation/endpoint detection parameters is broken as of September 2014. // The next line is a hack replacement EndpointDetectionConfiguration.SetDefaultSegmentationConfig(); this.SigState = EndpointDetectionConfiguration.DetermineVocalisationEndpoints(this.DecibelsPerFrame, this.FrameStep); } /* AS OF 30 MARCH 2017, NO LONGER IMPLEMENT SUB-BAND THINGS, because not being used for years. * // EXTRACT REQUIRED FREQUENCY BAND * if (doExtractSubband) * { * this.Data = SpectrogramTools.ExtractFreqSubband( * this.Data, * this.subBandMinHz, * this.subBandMaxHz, * this.Configuration.DoMelScale, * this.Configuration.FreqBinCount, * this.FBinWidth); * this.CalculateSubbandSNR(this.Data); * } */ }