public static FilterProfile Profile(ISoundObj impulse, SmoothingType type, double resolution) { uint nSR = impulse.SampleRate; uint nSR2 = nSR / 2; ushort nChannels = impulse.NumChannels; for (ushort c = 0; c < nChannels; c++) { // Read channel into a buffer SingleChannel channel = impulse.Channel(c); SoundBuffer buff = new SoundBuffer(channel); buff.ReadAll(); // And then double in length to prevent wraparound buff.PadTo(buff.Count * 2); // Pad to next higher power of two buff.PadToPowerOfTwo(); // Read out into array of complex Complex[][] data = buff.ToComplexArray(); Complex[] cdata = data[0]; // Then we're done with the buffer for this channel buff = null; GC.Collect(); // FFT in place Fourier.FFT(cdata.Length, cdata); int n = cdata.Length / 2; // Now we have an array of complex, from 0Hz to Nyquist and back again. // We really only care about the first half of the cdata buffer, but // treat it as circular anyway (i.e. wrap around for negative values). // // We're only working with magnitudes from here on, // so we can save some space by computing mags right away and storing them in the // real part of the complex array; then we can use the imaginary portion for the // smoothed data. for (int j = 0; j < cdata.Length; j++) { cdata[j].Re = cdata[j].Magnitude; cdata[j].Im = 0; } // Take a rectangular window of width (resolution)*(octave or ERB band) // Add up all magnitudes falling within this window // // Move the window forward by one thingummajig //double wMid = 0; // center of the window //double wLen = 0; } return(new FilterProfile()); // temp }
/// <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); }
/// <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; }
public static FilterProfile Profile(ISoundObj impulse, SmoothingType type, double resolution) { uint nSR = impulse.SampleRate; uint nSR2 = nSR / 2; ushort nChannels = impulse.NumChannels; for (ushort c = 0; c < nChannels; c++) { // Read channel into a buffer SingleChannel channel = impulse.Channel(c); SoundBuffer buff = new SoundBuffer(channel); buff.ReadAll(); // And then double in length to prevent wraparound buff.PadTo(buff.Count * 2); // Pad to next higher power of two buff.PadToPowerOfTwo(); // Read out into array of complex Complex[][] data = buff.ToComplexArray(); Complex[] cdata = data[0]; // Then we're done with the buffer for this channel buff = null; GC.Collect(); // FFT in place Fourier.FFT(cdata.Length, cdata); int n = cdata.Length / 2; // Now we have an array of complex, from 0Hz to Nyquist and back again. // We really only care about the first half of the cdata buffer, but // treat it as circular anyway (i.e. wrap around for negative values). // // We're only working with magnitudes from here on, // so we can save some space by computing mags right away and storing them in the // real part of the complex array; then we can use the imaginary portion for the // smoothed data. for (int j = 0; j < cdata.Length; j++) { cdata[j].Re = cdata[j].Magnitude; cdata[j].Im = 0; } // Take a rectangular window of width (resolution)*(octave or ERB band) // Add up all magnitudes falling within this window // // Move the window forward by one thingummajig //double wMid = 0; // center of the window //double wLen = 0; } return new FilterProfile(); // temp }
private static double[] magbands(ISoundObj impulse, double bins) { uint nSR = impulse.SampleRate; uint nSR2 = nSR / 2; int nn = (int)bins + 1; double[] muff = new double[nn]; ushort nChannels = impulse.NumChannels; for (ushort c = 0; c < nChannels; c++) { // Read channel into a buffer SingleChannel channel = impulse.Channel(c); SoundBuffer buff = new SoundBuffer(channel); buff.ReadAll(); // And then double in length to prevent wraparound buff.PadTo(buff.Count * 2); // Pad to next higher power of two buff.PadToPowerOfTwo(); // Read out into array of complex Complex[][] data = buff.ToComplexArray(); Complex[] cdata = data[0]; // Then we're done with the buffer for this channel buff = null; GC.Collect(); // FFT in place Fourier.FFT(cdata.Length, cdata); int n = cdata.Length / 2; // Drop the FFT magnitudes into the 'muff' array // according to an ERB-based scale (near-logarithmic). // Then smoothing is easy. double binw = (nSR2 / (double)n); int prevbin = 0; int nbin = 0; double v = 0; for (int j = 0; j < n; j++) { double f = (double)j * binw; // equiv freq, Hz int bin = (int)ERB.f2bin(f, nSR, bins); // the bin we drop this sample in v += cdata[j].Magnitude; nbin++; if ((bin > prevbin) || (j == n - 1)) { muff[prevbin] += (v / nbin); v = 0; nbin = 0; prevbin = bin; } } } // Now muff is sum(all channels) of average-magnitude-per-bin. // Divide it all by the number of channels, so our gains are averaged... for (int j = 0; j < muff.Length; j++) { muff[j] = muff[j] / nChannels; } return(muff); }