Beispiel #1
0
 public virtual void Reset()
 {
     if (_input == null)
     {
         return;
     }
     _input.Reset();
 }
Beispiel #2
0
        /// <summary>
        /// Calculate the weighted volume of a sound source.
        /// NB: this consumes lots of memory for long sources.
        /// </summary>
        /// <param name="src"></param>
        /// <param name="dbSPL"></param>
        /// <returns>Volume (units, not dB)</returns>
        public static double WeightedVolume(ISoundObj src, double dbSPL, double dbSPLBase)
        {
            double wv = 0;

            for (ushort c = 0; c < src.NumChannels; c++)
            {
                SingleChannel channel = src.Channel(c);
                wv += Loudness.WeightedVolume1(channel, dbSPL, dbSPLBase);
            }
            src.Reset();
            wv = wv / src.NumChannels;
            return(wv);
        }
Beispiel #3
0
 /// <summary>
 /// Calculate the weighted volume of a sound source.
 /// NB: this consumes lots of memory for long sources.
 /// </summary>
 /// <param name="src"></param>
 /// <param name="dbSPL"></param>
 /// <returns>Volume (units, not dB)</returns>
 public static double WeightedVolume(ISoundObj src, double dbSPL, double dbSPLBase)
 {
     double wv = 0;
     for (ushort c = 0; c < src.NumChannels; c++)
     {
         SingleChannel channel = src.Channel(c);
         wv += Loudness.WeightedVolume1(channel, dbSPL, dbSPLBase);
     }
     src.Reset();
     wv = wv / src.NumChannels;
     return wv;
 }
Beispiel #4
0
        static ISoundObj SlidingLowPass(ISoundObj impulse, int peakPos)
        {
            // Filter the impulse response with a sliding lowpass filter
            // - Take the first (peakpos) samples unchanged
            // - Take the next 2.5ms (~110 samples @ 44100) unchanged
            // - Fade to a lowpass-filtered version

            uint sampleRate = impulse.SampleRate;
            int startpos1 = (int)(sampleRate * 0.0025);     // 2.5mS, 110 samples
            int startpos2 = (int)(sampleRate * 0.0050);
            int startpos3 = (int)(sampleRate * 0.0100);
            int startpos4 = (int)(sampleRate * 0.0200);
            int startpos5 = (int)(sampleRate * 0.0400);

            List<IEnumerator<ISample>> filters = null;
            int nFilter = 0;
            int nFilters = 0;
            int x = 0;
            int f0len = 0;
            ISoundObj filteredImpulse = new CallbackSource(1, sampleRate, delegate(long j)
            {
                if(j==0)
                {
                    // initialize the list of filters
                    impulse.Reset();
                    filters = new List<IEnumerator<ISample>>(6);
                    ISoundObj f0 = LowPassFiltered(impulse, 20, 0);
                    f0len = f0.Iterations;
                    filters.Add(f0.Samples);        // unfiltered
                    filters.Add(LowPassFiltered(impulse, 640, -10).Samples);      // LPF from 640Hz, kick in at +110
                    filters.Add(LowPassFiltered(impulse, 320, -20).Samples);       // LPF from 320Hz, kick in at +220 (etc)
                    filters.Add(LowPassFiltered(impulse, 160, -30).Samples);       // +440
                    filters.Add(LowPassFiltered(impulse, 80, -40).Samples);        // +880
                    filters.Add(LowPassFiltered(impulse, 40, -50).Samples);        // +1760 = 40ms
                    nFilter = 0;
                    nFilters = filters.Count;
                }

                // Move the filters along a notch.
                // (or, right at the beginning, move all the filters along by a lot, compensating for their center)
                // For perf, we don't need to keep enumerating the filters we've finished using.
                bool moreData = true;
                int nSkip = 1;
                if (j == 0)
                {
                    nSkip = (f0len/2)+1;
                }
                for (int skip = 0; skip < nSkip; skip++)
                {
                    int nStart = (nFilter == 0) ? 0 : nFilter - 1;    // Keep moving even the old filters along so mixing works later
                    for (int f = nStart; f < nFilters; f++)
                    {
                        moreData &= filters[f].MoveNext();
                    }
                }
                if (!moreData) return null;

                // Decide which filter we'll use
                x++;
                if (j == peakPos + startpos1) { nFilter = 1; x = 0; }
                if (j == peakPos + startpos2) { nFilter = 2; x = 0; }
                if (j == peakPos + startpos3) { nFilter = 3; x = 0; }
                if (j == peakPos + startpos4) { nFilter = 4; x = 0; }
                if (j == peakPos + startpos5) { nFilter = 5; x = 0; }

                // Pick the sample from the current filter
                ISample s = filters[nFilter].Current;

                // For a short region after switch-over, mix slowly with the sample from the previous filter
                int w = 20;
                if (x < w && nFilter > 0)
                {
                    ISample sPrev = filters[nFilter-1].Current;
                    for (int c = 0; c < s.NumChannels; c++)
                    {
                        s[c] = ((double)x/w)*s[c] + ((double)(w-x)/w)*sPrev[c];
                    }
                }
                return s;
            });
            return filteredImpulse;
        }
Beispiel #5
0
 public void Reset()
 {
     _obj.Reset();
     _enum = _obj.Samples;
 }
Beispiel #6
0
        private static ISoundObj GenerateFlatnessFilter(string impulsePath, ISoundObj impulseObj, double nFlatness)
        {
            // Flatness-filters are single channel
            // nFlatness is from 0 to 100
            // 0: follow the contours of the impulse
            // 100: completely flat

            DateTime dtStart = DateTime.Now;
            ISoundObj filterImpulse = null;
            uint nSR = impulseObj.SampleRate;
            uint nSR2 = nSR / 2;
            string sPath = FlatnessFilterPath(impulsePath, nSR, nFlatness);

            // Low flatness values (to 0) => very un-smooth
            // High flatness values (to 100) => very smooth
            double detail = (nFlatness / 50) + 0.05;

            // Get profile of the impulse
            FilterProfile lfg = new FilterProfile(impulseObj, detail);

            // Scale by the flatness values
            lfg = lfg * ((100 - nFlatness) / 100);

            // Invert
            lfg = lfg.Inverse(20);

            // Zero at HF
            lfg.Add(new FreqGain(nSR2 - 100, 0));

            // Build the flatness filter
            filterImpulse = new FilterImpulse(8192, lfg, FilterInterpolation.COSINE, nSR);

            try
            {
                // Write the filter impulse to disk
                WaveWriter wri = new WaveWriter(sPath);
                wri.Input = filterImpulse;
                wri.Format = WaveFormat.IEEE_FLOAT;
                wri.BitsPerSample = 64;
                wri.Run();
                wri.Close();

                if (_debug)
                {
                    // DEBUG: Write the flatness impulse as wav16
                    wri = new WaveWriter(sPath + ".wav");
                    wri.Input = filterImpulse;
                    wri.Format = WaveFormat.PCM;
                    wri.BitsPerSample = 16;
                    wri.Normalization = -1.0;
                    wri.Dither = DitherType.NONE;//.TRIANGULAR;
                    wri.Run();
                    wri.Close();
                }
            }
            catch (Exception e)
            {
                if (_debug)
                {
                    Trace.WriteLine("GenerateFlatnessFilter: " + e.Message);
                }
            }

            impulseObj.Reset();
            if (_debug)
            {
                TimeSpan ts = DateTime.Now.Subtract(dtStart);
                Trace.WriteLine("GenerateFlatnessFilter " + ts.TotalMilliseconds);
            }
            return filterImpulse;
        }