Close() public method

Close the wave file
public Close ( ) : void
return void
Example #1
0
        static bool ExecDRC(string drcfile, string target, string outfile, string infileL, string infileR, int peakPosL, int peakPosR, string stereoImpulseFile)
        {
            GC.Collect();
            bool ok = false;
            string args;
            FastConvolver conv;
            WaveWriter wri;
            if (!File.Exists(drcfile))
            {
                stderr.WriteLine();
                stderr.WriteLine("{0} not found.", drcfile);
                return ok;
            }

            string tmpL;
            string tmpR;
            tmpL = Path.GetFileNameWithoutExtension(infileL) + ".tmp";
            tmpR = Path.GetFileNameWithoutExtension(infileR) + ".tmp";
            _tempFiles.Add(tmpL);
            _tempFiles.Add(tmpR);

            stderr.WriteLine("Exec DRC for {0}, left channel", drcfile);
            stderr.WriteLine();
            ok = RunDRC(drcfile, infileL, target, tmpL, peakPosL, out args);

            if (ok)
            {
                stderr.WriteLine();
                stderr.WriteLine("Exec DRC for {0}, right channel", drcfile);
                stderr.WriteLine();
                ok = RunDRC(drcfile, infileR, target, tmpR, peakPosR, out args);
            }

            if (ok)
            {
                stderr.WriteLine();
                if (_noSkew)
                {
                    stderr.WriteLine("Creating stereo filter {0}", outfile + ".wav" );
                }
                else
                {
                    stderr.WriteLine("Creating stereo filter {0} (skew {1} samples)", outfile + ".wav", peakPosR - peakPosL);
                }
                ISoundObj stereoFilter = Splice(tmpL, peakPosL, tmpR, peakPosR, outfile + ".wav");
                stderr.WriteLine();

                // Convolve noise with the stereo filter
                /*
                NoiseGenerator noise = new NoiseGenerator(NoiseType.WHITE_FLAT, 2, (int)131072, stereoFilter.SampleRate, 1.0);
                conv = new FastConvolver();
                conv.impulse = stereoFilter;
                conv.Input = noise;

                wri = new WaveWriter(drcfile + "_Test.wav");
                wri.Input = conv;
                wri.Format = WaveFormat.IEEE_FLOAT;
                wri.BitsPerSample = 32;
                wri.SampleRate = _sampleRate;
                wri.Normalization = -1;
                wri.Run();
                wri.Close();
                wri = null;
                conv = null;
                noise = null;
                 * */

                // Convolve filter with the in-room impulse response
                WaveReader rea = new WaveReader(stereoImpulseFile);
                conv = new FastConvolver();
                conv.impulse = rea;
                conv.Input = stereoFilter;

                if (_pcm)
                {
                    _impulseFiles.Add("LCorrected_" + outfile + ".pcm: corrected test convolution, raw data (32-bit float), left channel");
                    _impulseFiles.Add("RCorrected_" + outfile + ".pcm: corrected test convolution, raw data (32-bit float), right channel");
                    WriteImpulsePCM(conv, "LCorrected_" + outfile + ".pcm", "RCorrected_" + outfile + ".pcm");
                }

                wri = new WaveWriter(outfile + "_TestConvolution.wav");
                wri.Input = conv;
                wri.Format = WaveFormat.PCM;
                wri.Dither = DitherType.TRIANGULAR;
                wri.BitsPerSample = 16;
                wri.SampleRate = _sampleRate;
                wri.Normalization = -1;
                wri.Run();
                wri.Close();
                rea.Close();
                wri = null;
                rea = null;
                conv = null;

                GC.Collect();
            }
            return ok;
        }
Example #2
0
        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;
        }
Example #3
0
        private void init()
        {
            _running = true;

            ComputeImpulseFFT();

            nChannels = NumChannels;
            // Size for work area
            N = _impulseLength;
            nImpulseChannels = _impulse.NumChannels;
            Nh = N << 1;

            K = (_partitions <= 0) ? N : (N / _partitions);
            L = MathUtil.NextPowerOfTwo(K << 1);
            P = (int)Math.Ceiling((double)N / (double)K);

            //              Trace.WriteLine("{0} partitions of size {1}, chunk size {2}", P, L, K);

            // Allocate buffers for the source and output
            src    = new Complex[nChannels][];
            output = new Complex[nChannels][];
            for (ushort c = 0; c < nChannels; c++)
            {
                src[c]    = new Complex[Nh];
                output[c] = new Complex[Nh];
            }

            // For partitioned convolution, allocate arrays for the fft accumulators
            if (_partitions > 0)
            {
                accum = new Complex[nChannels][][];
                for (ushort c = 0; c < nChannels; c++)
                {
                    accum[c] = new Complex[P][];
                    for (p = 0; p < P; p++)
                    {
                        accum[c][p] = new Complex[L];
                    }
                }
            }

            if (IsPersistTail)
            {
                // If there's any *unprocessed* leftover from a previous convolution,
                // load it into prevTailSamples before we begin
                if (System.IO.File.Exists(_persistFile))
                {
                    WaveReader tailReader = null;
                    try
                    {
                        tailReader      = new WaveReader(_persistFile);
                        prevTailSamples = new List <ISample>(tailReader.Iterations);
                        //                            Trace.WriteLine("Read {0} tail samples", tailReader.Iterations);
                        if (tailReader.NumChannels == NumChannels)
                        {
                            foreach (ISample s in tailReader)
                            {
                                prevTailSamples.Add(s);
                            }
                        }
                        prevTailEnum = prevTailSamples.GetEnumerator();
                    }
                    catch (Exception e)
                    {
                        Trace.WriteLine("Could not read tail {0}: {1}", _persistFile.Replace(_persistPath, ""), e.Message);
                    }
                    // finally...
//                    ThreadPool.QueueUserWorkItem(delegate(object o)
//                    {
                    try
                    {
                        if (tailReader != null)
                        {
                            tailReader.Close();
                            tailReader = null;
                        }
                        System.IO.File.Delete(_persistFile);
                    }
                    catch (Exception)
                    {
                        // ignore, we're done
                    }
//                    });
                }
            }
//              Trace.WriteLine("{0} partitions of size {1}, chunk size {2}", P, L, K);
        }
Example #4
0
        static void Prep(string infileL, string infileR, string stereoImpulseFile, string outFile)
        {
            // Input files are complex
            // 0=mag, 1=phase/pi (so it looks OK in a wave editor!)
            // FFTs of the room impulse response

            // Take two half-FFT-of-impulse WAV files
            // Average them, into an array

            int n;
            SoundBuffer buff;
            WaveWriter wri;
            //          NoiseGenerator noise;
            FastConvolver conv;

            /*
            // Convolve noise with the in-room impulse
            noise = new NoiseGenerator(NoiseType.WHITE_FLAT, 2, (int)131072, stereoImpulse.SampleRate, 1.0);
            conv = new FastConvolver();
            conv.impulse = stereoImpulse;
            conv.Input = noise;

            wri = new WaveWriter("ImpulseResponse_InRoom.wav");
            wri.Input = conv;
            wri.Format = WaveFormat.IEEE_FLOAT;
            wri.BitsPerSample = 32;
            wri.Normalization = 0;
            wri.Run();
            wri.Close();
            wri = null;
            conv = null;
            */

            WaveReader rdrL = new WaveReader(infileL);
            buff = new SoundBuffer(rdrL);
            n = (int)buff.ReadAll();
            uint sampleRate = buff.SampleRate;
            uint nyquist = sampleRate / 2;

            double binw = (nyquist / (double)n);

            WaveReader rdrR = new WaveReader(infileR);

            IEnumerator<ISample> enumL = buff.Samples;
            IEnumerator<ISample> enumR = rdrR.Samples;

            // For easier processing and visualisation
            // read this in to an ERB-scale (not quite log-scale) array
            // then we can smooth by convolving with a single half-cosine.
            //

            int nn = (int)ERB.f2bin(nyquist, sampleRate) + 1;

            double[] muff = new double[nn];

            int prevbin = 0;
            int nbin = 0;
            double v = 0;
            int j = 0;
            while (true)
            {
                double f = (double)j * binw;    // equiv freq, Hz

                int bin = (int)ERB.f2bin(f, sampleRate); // the bin we drop this sample in
                if (bin > nn)
                {
                    // One of the channels has more, but we're overrun so stop now
                    break;
                }

                j++;
                bool more = false;
                more |= enumL.MoveNext();
                more |= enumR.MoveNext();
                if (!more)
                {
                    muff[prevbin] = v / nbin;
                    break;
                }

                v += enumL.Current[0];  // magnitude
                v += enumR.Current[0];  // magnitude
                nbin++;

                if (bin > prevbin)
                {
                    muff[prevbin] = v / nbin;
                    v = 0;
                    nbin = 0;
                    prevbin = bin;
                }
            }

            double[] smoo = ERB.smooth(muff, 38);

            // Pull out the freq response at ERB centers
            FilterProfile lfg = ERB.profile(smoo, sampleRate);

            // Write this response as a 'target' file
            /*
            FileStream fs = new FileStream("target_full.txt", FileMode.Create);
            StreamWriter sw = new StreamWriter(fs, Encoding.ASCII);
            foreach (FreqGain fg in lfg)
            {
                sw.WriteLine("{0} {1:f4}", Math.Round(fg.Freq), fg.Gain);
            }
            sw.Close();
            */
            /*
            fs = new FileStream("target_half.txt", FileMode.Create);
            sw = new StreamWriter(fs, Encoding.ASCII);
            foreach (FreqGain fg in lfg)
            {
                sw.WriteLine("{0} {1:f4}", Math.Round(fg.Freq), fg.Gain/2);
            }
            sw.Close();
            */

            // Create a filter to invert this response
            FilterProfile ifg = new FilterProfile();
            foreach (FreqGain fg in lfg)
            {
                ifg.Add(new FreqGain(fg.Freq, -fg.Gain));
            }

            ISoundObj filterImpulse = new FilterImpulse(0, ifg, FilterInterpolation.COSINE, sampleRate);
            filterImpulse.SampleRate = sampleRate;

            // Write the filter impulse to disk
            string sNoCorr = outFile + ".wav";
            wri = new WaveWriter(sNoCorr);
            wri.Input = filterImpulse; // invertor;
            wri.Format = WaveFormat.IEEE_FLOAT;
            wri.BitsPerSample = 32;
            wri.SampleRate = _sampleRate;
            wri.Normalization = -1;
            wri.Run();
            wri.Close();
            _filterFiles.Add(sNoCorr);

            /*
            // Convolve noise with the NoCorrection filter
            noise = new NoiseGenerator(NoiseType.WHITE_FLAT, 2, (int)131072, stereoImpulse.SampleRate, 1.0);
            conv = new FastConvolver();
            conv.impulse = invertor;
            conv.Input = noise;

            wri = new WaveWriter("NoCorrection_Test.wav");
            wri.Input = conv;
            wri.Format = WaveFormat.IEEE_FLOAT;
            wri.BitsPerSample = 32;
            wri.SampleRate = _sampleRate;
            wri.Normalization = 0;
            wri.Run();
            wri.Close();
            wri = null;
            conv = null;
            */

            // Convolve this with the in-room impulse response

            WaveReader rea = new WaveReader(outFile + ".wav");
            conv = new FastConvolver();
            conv.impulse = rea;
            conv.Input = new WaveReader(stereoImpulseFile);
            wri = new WaveWriter(outFile + "_TestConvolution.wav");
            wri.Input = conv;
            wri.Format = WaveFormat.PCM;
            wri.Dither = DitherType.TRIANGULAR;
            wri.BitsPerSample = 16;
            wri.SampleRate = _sampleRate;
            wri.Normalization = -1;
            wri.Run();
            wri.Close();
            rea.Close();
            wri = null;
            conv = null;
        }
Example #5
0
        static WaveReader TryGetAppropriateImpulseReader(string filePath, bool allowResample, out string actualPath)
        {
            WaveReader rdr = null;
            bool isExtensibleFormat = false;
            WaveFormat format = WaveFormat.ANY;
            bool needResample = false;
            string resamplePath = GetResampledImpulsePath(filePath);
            actualPath = null;

            // Check the impulse file.
            if (File.Exists(filePath))
            {
                try
                {
                    rdr = new WaveReader(filePath);
                    actualPath = filePath;
                    if (rdr.SampleRate != 0 && rdr.SampleRate != _inputSampleRate)
                    {
                        Trace.WriteLine("Can't use {0}: its sample rate is {1} not {2}", CleanPath(_dataFolder, filePath), rdr.SampleRate, _inputSampleRate);
                        isExtensibleFormat = (rdr.FormatEx != null);
                        format = rdr.Format;
                        rdr.Close();
                        rdr = null;
                        actualPath = null;
                        needResample = true;
                    }
                }
                catch (Exception e)
                {
                    Trace.WriteLine("Can't use {0}: {1}", CleanPath(_dataFolder, filePath), e.Message);
                }
            }
            else
            {
                Trace.WriteLine("Can't use {0}: not found", CleanPath(_dataFolder, filePath));
            }

            if (rdr == null)
            {
                // No luck there.  Check for an already-resampled version.
                if (File.Exists(resamplePath))
                {
                    try
                    {
                        rdr = new WaveReader(resamplePath);
                        if (rdr.SampleRate != 0 && rdr.SampleRate != _inputSampleRate)
                        {
                            // Oh dear! This shouldn't happen; after all, the resampled file's name is designed to match sample rates
                            Trace.WriteLine("Can't use {0}: its sample rate is {1} not {2}", CleanPath(_dataFolder, resamplePath), rdr.SampleRate, _inputSampleRate);
                            rdr.Close();
                            rdr = null;
                        }
                        else
                        {
                            actualPath = resamplePath;
                            Trace.WriteLine("Using resampled version {0} instead", CleanPath(_dataFolder, resamplePath));
                            needResample = false;
                        }
                    }
                    catch (Exception e)
                    {
                        Trace.WriteLine("Can't use {0}: {1}", CleanPath(_dataFolder, resamplePath), e.Message);
                    }
                }
                else if(allowResample)
                {
                    Trace.WriteLine("Can't use {0}: not found", CleanPath(_dataFolder, resamplePath));
                }
            }

            if (needResample && allowResample)
            {
                // If 'sox' is available,
                // use it to resample the filter we're trying to use
                //  sox <input.wav> -r <new_sample_rate> <output.wav> polyphase
                //
                // The sox application might be either
                // - in the same folder as this application (quite likely...), or
                // - somewhere else on the path
                // and it might be called "sox" or "sox.exe", depending on the operating system (of course).
                //

                if (true || isExtensibleFormat)
                {
                    // sox can't handle the WaveFormatExtensible file type, so we need to save a clean copy of the file first
                    // ALSO: sox goes very wrong if the original is near 0dBfs
                    // so we normalize ALWAYS before resample.
                    rdr = new WaveReader(filePath);
                    string newFile = "RE" + filePath.GetHashCode().ToString("x10").ToUpperInvariant() + ".wav";
                    string newPath = Path.Combine(_tempFolder, newFile);
                    WaveWriter tempWriter = new WaveWriter(newPath);
                    tempWriter.Input = rdr;
                    tempWriter.Format = rdr.Format;
                    tempWriter.BitsPerSample = rdr.BitsPerSample;
                    tempWriter.Normalization = -6;
                    tempWriter.Run();
                    tempWriter.Close();
                    rdr.Close();
                    rdr = null;
                    filePath = newPath;
                }

                // _soxExe = "sox";
                string exeName = _soxExe;
                if(File.Exists(Path.Combine(_pluginFolder, _soxExe + ".exe")))
                {
                    exeName = "\"" + Path.Combine(_pluginFolder, _soxExe + ".exe") + "\"";
                }
                else if (File.Exists(Path.Combine(_pluginFolder, _soxExe)))
                {
                    exeName = Path.Combine(_pluginFolder, _soxExe);
                }

                // _soxFmt = "\"{0}\" -r {1} \"{2}\" polyphase";
                string soxArgs = String.Format(_soxFmt, filePath, _inputSampleRate, resamplePath);

                Trace.WriteLine("Trying {0} {1}", exeName, soxArgs);

                System.Diagnostics.Process soxProcess = new System.Diagnostics.Process();
                System.Diagnostics.ProcessStartInfo soxInfo = new System.Diagnostics.ProcessStartInfo();
                soxInfo.Arguments = soxArgs;
                soxInfo.FileName = exeName;
                soxInfo.UseShellExecute = false;
                soxInfo.RedirectStandardError = true;

                soxProcess.StartInfo = soxInfo;
                try
                {
                    soxProcess.Start();

                    // Wait for the sox process to finish!
                    string err = soxProcess.StandardError.ReadToEnd();
                    soxProcess.WaitForExit(500);
                    if (soxProcess.HasExited)
                    {
                        int n = soxProcess.ExitCode;
                        if (n != 0)
                        {
                            Trace.WriteLine("No, that didn't seem to work: {0}", err);
                        }
                        else
                        {
                            Trace.WriteLine("Yes, that seemed to work.");
                            rdr = TryGetAppropriateImpulseReader(resamplePath, false, out actualPath);
                        }
                    }
                }
                catch (Exception e)
                {
                    Trace.WriteLine("That didn't seem to work: {0}", e.Message);
                }
            }
            if (rdr == null)
            {
                Trace.WriteLine("No suitable impulse found ({0}).", filePath);
            }
            return rdr;
        }