/// <summary>
        /// DoSnr = true;
        /// DoFullBandwidth = false;
        /// </summary>
        /// <param name="config">read from file</param>
        private void Initialize(ConfigDictionary config)
        {
            if (config == null)
            {
                throw new ArgumentNullException(nameof(config));
            }

            this.CallName    = config.GetString(ConfigKeys.Recording.Key_RecordingCallName);
            this.SourceFName = config.GetString(ConfigKeys.Recording.Key_RecordingFileName);
            var duration = config.GetDoubleNullable("WAV_DURATION");

            if (duration != null)
            {
                this.Duration = TimeSpan.FromSeconds(duration.Value);
            }

            //FRAMING PARAMETERS
            this.WindowSize    = config.GetInt(ConfigKeys.Windowing.Key_WindowSize);
            this.WindowOverlap = config.GetDouble(ConfigKeys.Windowing.Key_WindowOverlap);

            //NOISE REDUCTION PARAMETERS
            this.DoSnr = true; // set false if only want to
            string noisereduce = config.GetString(AnalysisKeys.NoiseReductionType);

            //this.NoiseReductionType = (NoiseReductionType)Enum.Parse(typeof(NoiseReductionType), noisereduce.ToUpperInvariant());
            this.NoiseReductionType = (NoiseReductionType)Enum.Parse(typeof(NoiseReductionType), noisereduce);

            //FREQ BAND PARAMETERS
            this.DoFullBandwidth = false; // set true if only want to
            this.MinFreqBand     = config.GetIntNullable(ConfigKeys.Mfcc.Key_MinFreq);
            this.MaxFreqBand     = config.GetIntNullable(ConfigKeys.Mfcc.Key_MaxFreq);
            this.MidFreqBand     = this.MinFreqBand + ((this.MaxFreqBand - this.MinFreqBand) / 2);

            //SEGMENTATION PARAMETERS
            EndpointDetectionConfiguration.SetConfig(config);

            //MFCC PARAMETERS
            this.DoMelScale = config.GetBoolean(ConfigKeys.Mfcc.Key_DoMelScale);
            this.mfccConfig = new MfccConfiguration(config);
            this.DeltaT     = config.GetInt(ConfigKeys.Mfcc.Key_DeltaT); // Frames between acoustic vectors

            // for generating only spectrogram.
        }
        public virtual void Save(TextWriter writer)
        {
            writer.WriteLine("#**************** INFO ABOUT FRAMES");
            writer.WriteConfigValue(ConfigKeys.Windowing.Key_WindowSize, this.WindowSize);
            writer.WriteConfigValue(ConfigKeys.Windowing.Key_WindowOverlap, this.WindowOverlap);
            EndpointDetectionConfiguration.Save(writer);
            writer.WriteLine("#**************** INFO ABOUT SONOGRAM");
            writer.WriteConfigValue("MIN_FREQ", this.MinFreqBand);
            writer.WriteConfigValue("MAX_FREQ", this.MaxFreqBand);
            writer.WriteConfigValue("MID_FREQ", this.MidFreqBand); //=3500
            writer.WriteConfigValue(AnalysisKeys.NoiseReductionType, this.NoiseReductionType.ToString());
            if (this.NoiseReductionParameter > 1.0)
            {
                writer.WriteConfigValue(SNR.KeyDynamicRange, this.NoiseReductionParameter.ToString("F1"));
            }

            writer.WriteLine("#");
            writer.WriteLine("#**************** INFO ABOUT FEATURE EXTRACTION");
            writer.WriteLine("FEATURE_TYPE=mfcc");
            this.mfccConfig.Save(writer);
            writer.WriteConfigValue(ConfigKeys.Mfcc.Key_DeltaT, this.DeltaT);
            writer.WriteLine("#");
            writer.Flush();
        }
Example #3
0
        /// <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);
             * }
             */
        }