void Process()
        {
            task.UpdateProgressBar(0);
            task.UpdateStatus("Reading headers...");
            if (string.IsNullOrEmpty(path) || !Directory.Exists(path))
            {
                ProcessError("No valid path was selected.");
                return;
            }
            string bassPath = Path.Combine(path, "bass.wav"), drumsPath = Path.Combine(path, "drums.wav"),
                   otherPath = Path.Combine(path, "other.wav"), pianoPath = Path.Combine(path, "piano.wav"),
                   vocalsPath = Path.Combine(path, "vocals.wav");

            if (!File.Exists(bassPath) || !File.Exists(drumsPath) || !File.Exists(otherPath) || !File.Exists(vocalsPath))
            {
                ProcessError("Essence files not found. Please export with at least 4 parts.");
                return;
            }
            RIFFWaveReader bassReader = null, drumsReader = null, otherReader = null, pianoReader = null, vocalsReader = null;

            try {
                bassReader = new RIFFWaveReader(new BinaryReader(File.Open(bassPath, FileMode.Open)));
                bassReader.ReadHeader();
                drumsReader = new RIFFWaveReader(new BinaryReader(File.Open(drumsPath, FileMode.Open)));
                drumsReader.ReadHeader();
                otherReader = new RIFFWaveReader(new BinaryReader(File.Open(otherPath, FileMode.Open)));
                otherReader.ReadHeader();
                vocalsReader = new RIFFWaveReader(new BinaryReader(File.Open(vocalsPath, FileMode.Open)));
                vocalsReader.ReadHeader();
                if (File.Exists(pianoPath))
                {
                    pianoReader = new RIFFWaveReader(new BinaryReader(File.Open(pianoPath, FileMode.Open)));
                    pianoReader.ReadHeader();
                }
            } catch (IOException ex) {
                if (bassReader != null)
                {
                    bassReader.Dispose();
                }
                if (drumsReader != null)
                {
                    drumsReader.Dispose();
                }
                if (pianoReader != null)
                {
                    pianoReader.Dispose();
                }
                if (otherReader != null)
                {
                    otherReader.Dispose();
                }
                if (vocalsReader != null)
                {
                    vocalsReader.Dispose();
                }
                ProcessError(ex.Message);
                return;
            }

            float[] finalMix = new float[bassReader.Length * 8];
            float[] source   = Read(bassReader, "bass", pianoReader == null ? .1 : .08);
            Render(source, finalMix, GetMatrix(bass), GetLFE(bassLFE), "bass", pianoReader == null ? .1 : .08);
            source = Read(drumsReader, "drums", pianoReader == null ? .1 : .08);
            Render(source, finalMix, GetMatrix(drums), GetLFE(drumsLFE), "drums", pianoReader == null ? .1 : .08);
            if (pianoReader != null)
            {
                source = Read(pianoReader, "piano", .08);
                Render(source, finalMix, GetMatrix(piano), GetLFE(pianoLFE), "piano", .08);
            }
            source = Read(otherReader, "other", pianoReader == null ? .1 : .08);
            Render(source, finalMix, GetMatrix(other), GetLFE(otherLFE), "other", pianoReader == null ? .1 : .08);
            source = Read(vocalsReader, "vocals", pianoReader == null ? .1 : .08);
            Render(source, finalMix, GetMatrix(vocals), GetLFE(vocalsLFE), "vocals", pianoReader == null ? .1 : .08);

            task.UpdateProgressBar(.8);
            task.UpdateStatus("Checking peaks...");
            float peak = 1;

            for (long i = 0; i < finalMix.LongLength; ++i)
            {
                if (peak < Math.Abs(finalMix[i]))
                {
                    peak = Math.Abs(finalMix[i]);
                }
            }

            if (peak != 1)
            {
                task.UpdateProgressBar(.85);
                task.UpdateStatus("Normalizing...");
                float mul = 1 / peak;
                for (long i = 0; i < finalMix.LongLength; ++i)
                {
                    finalMix[i] *= mul;
                }
            }

            task.UpdateProgressBar(.9);
            task.UpdateStatus("Exporting to render.wav (0.00%)...");
            using (RIFFWaveWriter writer = new RIFFWaveWriter(new BinaryWriter(File.Open(Path.Combine(path, "render.wav"), FileMode.Create)),
                                                              8, bassReader.Length, bassReader.SampleRate, BitDepth.Int16)) {
                writer.WriteHeader();
                const long blockSize = 8192;
                for (long sample = 0; sample < finalMix.LongLength;)
                {
                    double progress = sample / (double)finalMix.LongLength;
                    writer.WriteBlock(finalMix, sample, Math.Min(sample += blockSize, finalMix.LongLength));
                    task.UpdateProgressBar(.9 + .1 * progress);
                    task.UpdateStatusLazy(string.Format("Exporting to render.wav ({0})...", progress.ToString("0.00%")));
                }
            }

            task.UpdateProgressBar(1);
            task.UpdateStatus("Finished!");
        }
Example #2
0
        private void LoadFiles(object sender, RoutedEventArgs e)
        {
            AudioReader responseReader = Import("Response.wav");

            if (responseReader == null)
            {
                return;
            }
            AudioReader impulseReader = Import("Impulse.wav");

            if (impulseReader == null)
            {
                return;
            }

            float[] response = responseReader.Read(),
            impulse = impulseReader.Read();
            if (responseReader.SampleRate != impulseReader.SampleRate)
            {
                Error("The sample rate of the two clips don't match.");
                return;
            }
            int responseChannels = responseReader.ChannelCount,
                impulseChannels  = impulseReader.ChannelCount;

            if (impulseChannels != 1 && impulseChannels != responseChannels)
            {
                Error("The channel count of the two clips don't match. A single-channel impulse is also acceptable.");
                return;
            }

            int fftSize = Math.Max(
                QMath.Base2Ceil((int)responseReader.Length),
                QMath.Base2Ceil((int)impulseReader.Length)
                );

            if (padding.IsChecked.Value)
            {
                Array.Resize(ref response, fftSize + response.Length);
                Array.Copy(response, 0, response, fftSize, response.Length - fftSize);
                Array.Clear(response, 0, fftSize);

                fftSize = Math.Max(fftSize, QMath.Base2Ceil(response.Length));
            }

            Complex[] impulseFFT = new Complex[fftSize],
            responseFFT = new Complex[fftSize];
            FFTCache cache = new FFTCache(fftSize);

            float[] responseChannel = new float[response.Length / responseChannels];
            for (int channel = 0; channel < responseChannels; ++channel)
            {
                if (channel < impulseChannels)   // After the channel count check this runs once or for each channel
                {
                    float[] impulseChannel = impulse;
                    if (impulseChannels != 1)
                    {
                        impulseChannel = new float[impulseReader.Length];
                        WaveformUtils.ExtractChannel(impulse, impulseChannel, channel, impulseChannels);
                        Array.Clear(impulseFFT, 0, fftSize);
                    }
                    for (int sample = 0; sample < impulseChannel.Length; ++sample)
                    {
                        impulseFFT[sample].Real = impulseChannel[sample];
                    }
                    Measurements.InPlaceFFT(impulseFFT, cache);
                }

                if (responseChannels == 1)
                {
                    responseChannel = response;
                }
                else
                {
                    WaveformUtils.ExtractChannel(response, responseChannel, channel, responseChannels);
                }
                if (channel != 1)
                {
                    Array.Clear(responseFFT, 0, fftSize);
                }
                for (int sample = 0; sample < responseChannel.Length; ++sample)
                {
                    responseFFT[sample].Real = responseChannel[sample];
                }
                Measurements.InPlaceFFT(responseFFT, cache);

                for (int sample = 0; sample < fftSize; ++sample)
                {
                    responseFFT[sample].Divide(impulseFFT[sample]);
                }
                Measurements.InPlaceIFFT(responseFFT, cache);
                for (int i = 0, channels = responseChannels; i < responseChannel.Length; ++i)
                {
                    response[channels * i + channel] = responseFFT[i].Real;
                }
            }

            exporter.FileName = "Deconvolved.wav";
            if (exporter.ShowDialog().Value)
            {
                BinaryWriter handler = new BinaryWriter(File.OpenWrite(exporter.FileName));
                using RIFFWaveWriter writer = new RIFFWaveWriter(handler, responseChannels, responseReader.Length,
                                                                 responseReader.SampleRate, responseReader.Bits);
                writer.Write(response);
            }
        }