static void WriteImpulsePCM(ISoundObj stereoImpulse, string fileNameL, string fileNameR) { ISoundObj sb; WaveWriter writer; ushort bits = 32; int nTot = 196607; int nBef = 98300; // need padding before the sample. // window the sample first, then pad it. // Total length 65536, includes nPad and _peakPosL before impulse int nPad = nBef - _peakPosL; int usableLength = nTot - nPad; int windowCenter = usableLength / 2; int windowSide = _peakPosL * 2 / 3; int windowFlat = windowCenter - windowSide; ISoundObj ch = new SingleChannel(stereoImpulse, 0); ISoundObj wn = new BlackmanHarris(windowCenter, windowSide, windowFlat); wn.Input = ch; sb = new SampleBuffer(wn).PaddedSubset(-nPad, nTot); writer = new WaveWriter(fileNameL); writer.Input = sb; writer.Format = WaveFormat.IEEE_FLOAT; writer.BitsPerSample = bits; writer.SampleRate = _sampleRate; writer.Raw = true; writer.Normalization = -6.0; writer.NormalizationType = NormalizationType.PEAK_DBFS; writer.Run(); writer.Close(); double g = writer.Gain; writer = null; nPad = nBef - _peakPosR; usableLength = nTot - nPad; windowCenter = usableLength / 2; windowSide = _peakPosR * 2 / 3; windowFlat = windowCenter - windowSide; ch = new SingleChannel(stereoImpulse, 1); wn = new BlackmanHarris(windowCenter, windowSide, windowFlat); wn.Input = ch; sb = new SampleBuffer(wn).PaddedSubset(-nPad, nTot); writer = new WaveWriter(fileNameR); writer.Input = sb; writer.Format = WaveFormat.IEEE_FLOAT; writer.BitsPerSample = bits; writer.SampleRate = _sampleRate; writer.Raw = true; writer.Gain = g; writer.Run(); writer.Close(); writer = null; }
static ISoundObj Splice(string infileL, int peakPosL, string infileR, int peakPosR, string outfile) { //int tmp1; //bool tmp2; WaveReader reader1 = new WaveReader(infileL, WaveFormat.IEEE_FLOAT, 32, 1); // reader1.Skip(peakPosL, out tmp1, out tmp2); SoundBuffer buff1 = new SoundBuffer(reader1); buff1.ReadAll(); // Normalize loudness for each channel double g = Loudness.WeightedVolume(buff1); buff1.ApplyGain(1/g); WaveReader reader2 = new WaveReader(infileR, WaveFormat.IEEE_FLOAT, 32, 1); // reader2.Skip(peakPosR, out tmp1, out tmp2); SoundBuffer buff2 = new SoundBuffer(reader2); buff2.ReadAll(); g = Loudness.WeightedVolume(buff2); buff2.ApplyGain(1/g); ChannelSplicer splicer = new ChannelSplicer(); splicer.Add(buff1); splicer.Add(buff2); // General-purpose: // Find the extremities of the DRC impulse, // window asymmetrically. // // But, since we specifically used linear-phase filters on target and mic, // we know that the impulse is centered. // We want an impulse length (_filterLen) // so window the 2048 samples at each end (which are pretty low to begin with - less than -100dB) ISoundObj output; int nCount = (int)(buff1.Count / 2); if (nCount > _filterLen/2) { BlackmanHarris bhw = new BlackmanHarris(nCount, 2048, (nCount / 2) - 2048); bhw.Input = splicer; SampleBuffer sb = new SampleBuffer(bhw); output = sb.Subset(_filterLen/2, _filterLen); } else { output = splicer; } ISoundObj result = output; if (!_noSkew) { // Apply skew to compensate for time alignment in the impulse responses Skewer skewer = new Skewer(true); skewer.Input = output; skewer.Skew = peakPosL - peakPosR; result = skewer; } WaveWriter writer = new WaveWriter(outfile); writer.Input = result; writer.Dither = DitherType.NONE; writer.Format = WaveFormat.IEEE_FLOAT; writer.BitsPerSample = 32; writer.SampleRate = _sampleRate; writer.NumChannels = splicer.NumChannels; if (Double.IsNaN(_gain)) { writer.Normalization = 0; } else { writer.Gain = MathUtil.gain(_gain); } writer.Run(); writer.Close(); reader1.Close(); reader2.Close(); return result; }