Channel-shuffle (LR to MS or vice versa) Requires two-channel input.
Inheritance: SoundObj
Exemplo n.º 1
0
        static ISoundObj DecodeBFormatBlumlein(ISoundObj source)
        {
            // Pure fig-8 Blumlein decode is simply a shuffle of the X (front-back) and Y (left-right) channels
            // W and Z are ignored.
            // No shelf filtering or distance compensation.

            TwoChannel xy = new TwoChannel(source, 1, 2);
            Shuffler blum = new Shuffler();
            blum.DeltaGain = 1.0;
            blum.SigmaGain = 1.0;
            blum.Input = xy;
            return blum;
        }
Exemplo n.º 2
0
        static SoundObj GetMatrixImpulse()
        {
            // Load the stereo-matrix filter, if there is one

            // The matrix impulse needs to be shuffled before we use it
            Shuffler filterShuffler = new Shuffler();

            if (!String.IsNullOrEmpty(_matrixFilter))
            {
                string ignore;
                WaveReader matrixReader = GetAppropriateImpulseReader(_matrixFilter, out ignore);
                if (matrixReader != null)
                {
                    filterShuffler.Input = matrixReader;

                    // Calculate loudness-adjusted volume of the matrix impulse
                    double matrixVolume = Loudness.WeightedVolume(filterShuffler);
                    if (Math.Abs(1 - matrixVolume) > 0.001)
                    {
                        // Adjust the main gain by this
                        for (int j = 0; j < _impulseVolumes.Count; j++)
                        {
                            _impulseVolumes[j] *= matrixVolume;
                        }
                    }
                }
            }

            return filterShuffler;
        }
Exemplo n.º 3
0
        static void InguzDSP(bool doRun)
        {
            DateTime dtStartRun = DateTime.Now;
            string sigdesc = null;

            // We need a few convolvers, of course
            if (_slow)
            {
                _MatrixConvolver = new SlowConvolver();
                _MainConvolver = new SlowConvolver();
                _EQConvolver = new SlowConvolver();
            }
            else
            {
                _MatrixConvolver = new FastConvolver();
                _MainConvolver = new FastConvolver();
                _EQConvolver = new FastConvolver();
            }

            // Shuffler
            _widthShuffler = new Shuffler();

            // Two skewers
            _depthSkewer = new Skewer(true);
            _skewSkewer = new Skewer(true);

            // Writer
            if (_outPath == null)
            {
                _writer = new WaveWriter();  // stdout
            }
            else
            {
                _writer = new WaveWriter(_outPath);
            }
            _writer.NumChannels = _outChannels;
            if (_debug)
            {
                TimeSpan ts = DateTime.Now.Subtract(dtStartRun);
                Trace.WriteLine("Setup " + ts.TotalMilliseconds);
            }

            /*
            DateTime exp = DSPUtil.DSPUtil.EXPIRY;
            if (exp != null)
            {
                if (DateTime.Now.CompareTo(exp) >= 0)
                {
                    Trace.WriteLine("**** THIS EVALUATION VERSION EXPIRED {0}", DSPUtil.DSPUtil.EXPIRY);
                    Trace.WriteLine("**** SEE http://www.inguzaudio.com/DSP/ FOR DETAILS");
                    _MatrixConvolver.Enabled = false;
                    _MainConvolver.Enabled = false;
                    _EQConvolver.Enabled = false;
                    Show("", "InguzDSP has expired.", 2);
                }
                else
                {
                    Trace.WriteLine("This evaluation version will expire {0}", DSPUtil.DSPUtil.EXPIRY);
                }
            }
            */

            // Read the configuration file
            doRun = LoadConfig2();

            // Do any cleanup required before we start
            CleanUp();

            // The main convolver should persist and re-use its leftovers between invocations
            // under this user's (=squeezebox's) ID
            _MainConvolver.partitions = _partitions;
            if (_tail && !IsSigGenNonEQ())
            {
                _MainConvolver.PersistPath = _tempFolder;
                _MainConvolver.PersistTail = _userID;
            }

            // Construct a second convolver for the "tone" (EQ) control.
            _EQConvolver.partitions = _partitions;
            if (_tail && !IsSigGenNonEQ())
            {
                _EQConvolver.PersistPath = _tempFolder;
                _EQConvolver.PersistTail = _userID + ".eq";
            }

            // Make a reader
            // _inPath is the data stream
            WaveReader inputReader = null;
            bool ok = false;
            try
            {
                if (_inStream != null)
                {
                    inputReader = new WaveReader(_inStream);
                }
                else if (_isRawIn)
                {
                    inputReader = new WaveReader(_inPath, _rawtype, _rawbits, _rawchan, _startTime);
                }
                else
                {
                    inputReader = new WaveReader(_inPath, _startTime);
                }
                inputReader.BigEndian = _bigEndian;
                ok = true;
            }
            catch (Exception e)
            {
                Trace.WriteLine("Unable to read: " + e.Message);
                // Just stop (no need to report the stack)
            }

            if (ok)
            {
                if (inputReader.IsSPDIF)
                {
                    // The wave file is just a SPDIF (IEC61937) stream, we shouldn't touch it
                    _inputSPDIF = true;
                    _isBypass = true;
                }
                if (_isBypass)
                {
                    // The settings file says bypass, we shouldn't touch it
                    _gain = 0;
                    _dither = DitherType.NONE;
                }

                uint sr = _inputSampleRate; // Yes, the commandline overrides the source-file...
                if (sr == 0)
                {
                    sr = inputReader.SampleRate;
                }
                if (sr == 0)
                {
                    sr = 44100;
                }
                _inputSampleRate = sr;

                if (WaveFormatEx.AMBISONIC_B_FORMAT_IEEE_FLOAT.Equals(inputReader.FormatEx) ||
                    WaveFormatEx.AMBISONIC_B_FORMAT_PCM.Equals(inputReader.FormatEx))
                {
                    _isBFormat = true;
                }

            }

            ISoundObj source = inputReader;
            if (IsSigGen())
            {
                // Signal-generator source instead of music.
                _isBFormat = false;
                source = GetSignalGenerator(-12, out sigdesc);
                Show("Test signal", sigdesc, 20);
            }

            if (IsSigGenNonEQ() || _isBypass)
            {
                // Signal-generator mode.  Overrides everything else!
                _writer.Input = source;
            }
            else
            {
                if (ok)
                {
                    // Load the room correction impulse to the convolver
                    // (NB: don't do this until we've created the reader, otherwise we can't be user of the samplerate yet...)
                    LoadImpulse();
                    GC.Collect();
                }

                if (ok && _isBFormat)
                {
                    source = DecodeBFormat(source);
                }

                if (ok)
                {
                    ISoundObj nextSrc;

                    // Perform width (matrix) processing on the signal
                    // - Shuffle the channels
                    // - Convolve if there's a filter
                    // - Apply gain to boost or cut the 'side' channel
                    // - Shuffle back
                    _widthShuffler.Input = source;
                    nextSrc = _widthShuffler;

                    // Use a convolver for the matrix filter
                    if (_matrixFilter != null)
                    {
                        LoadMatrixFilter();
                        _MatrixConvolver.Input = TwoChannel(nextSrc);
                        nextSrc = _MatrixConvolver as ISoundObj;
                    }

                    //                if (_depth != 0)
                    //                {
                    //                    // Time-alignment between the LR and MS
                    //                    _depthSkewer.Input = nextSrc;
                    //                    nextSrc = _depthSkewer;
                    //                }

                    // Shuffle back again
                    Shuffler shMSLR = new Shuffler();
                    shMSLR.Input = nextSrc;
                    nextSrc = shMSLR;

                    // Do the room-correction convolution
                    _MainConvolver.Input = TwoChannel(shMSLR);
                    nextSrc = _MainConvolver;

                    if (_skew != 0)
                    {
                        // time-alignment between left and right
                        _skewSkewer.Input = nextSrc;
                        nextSrc = _skewSkewer;
                    }

                    // Splice EQ and non-EQ channels
                    if (IsSigGenEQ())
                    {
                        ChannelSplicer splice = new ChannelSplicer();
                        if (IsSigGenEQL())
                        {
                            splice.Add(new SingleChannel(nextSrc, 0));
                        }
                        else
                        {
                            splice.Add(new SingleChannel(source, 0));
                        }
                        if (IsSigGenEQR())
                        {
                            splice.Add(new SingleChannel(nextSrc, 1));
                        }
                        else
                        {
                            splice.Add(new SingleChannel(source, 1));
                        }
                        nextSrc = splice;
                    }

                    // Process externally with aften or equivalent?
                    if (_aftenNeeded && !_isBypass)
                    {
                        nextSrc = AftenProcess(nextSrc);
                        _outFormat = WaveFormat.PCM;
                        _outBits = 16;
                        _dither = DitherType.NONE;
                    }

                    // Finally pipe this to the writer
                    _writer.Input = nextSrc;
                }
            }
            if (ok)
            {
                //dt = System.DateTime.Now;       // time to here is approx 300ms

                // Dither and output raw-format override anything earlier in the chain
                _writer.Dither = _isBypass ? DitherType.NONE : _dither;
                _writer.Raw = _isRawOut;
                _writer.Format = (_outFormat == WaveFormat.ANY) ? inputReader.Format : _outFormat;
                _writer.BitsPerSample = (_outBits == 0 || _isBypass) ? inputReader.BitsPerSample : _outBits;
                _writer.SampleRate = (_outRate == 0 || _isBypass) ? _inputSampleRate : _outRate;
                SetWriterGain();
                if (IsSigGen())
                {
                    Trace.WriteLine("Test signal: {0}, -12dBfs, {1}/{2} {3} {4}", sigdesc, _writer.BitsPerSample, _writer.SampleRate, _writer.Format, _writer.Dither);
                }
                string amb1 = "";
                string amb2 = "";
                if(_isBFormat)
                {
                    amb1 = "B-Format ";
                    amb2 = _ambiType + " ";
                }
                string big = inputReader.BigEndian ? "(Big-Endian) " : "";
                if (_inputSPDIF)
                {
                    Trace.WriteLine("Stream is SPDIF-wrapped; passing through");
                }
                else if (_isBypass)
                {
                    Trace.WriteLine("Processing is disabled; passing through");
                }
                Trace.WriteLine("{0}/{1} {2}{3} {4}=> {5}/{6} {7}{8} {9}, gain {10} dB", inputReader.BitsPerSample, _inputSampleRate, amb1, inputReader.Format, big, _writer.BitsPerSample, _writer.SampleRate, amb2, _writer.Format, _writer.Dither, _gain);

                TimeSpan elapsedInit = System.DateTime.Now.Subtract(dtStartRun);
                int n = _writer.Run();

                TimeSpan elapsedTotal = System.DateTime.Now.Subtract(dtStartRun);
                double realtime = n / _writer.SampleRate;
                double runtime = elapsedTotal.TotalMilliseconds / 1000;
                Trace.WriteLine("{0} samples, {1} ms ({2} init), {3} * realtime, peak {4} dBfs", n, elapsedTotal.TotalMilliseconds, elapsedInit.TotalMilliseconds, Math.Round(realtime / runtime, 4), Math.Round(_writer.dbfsPeak, 4));

                StopConfigListening();

                _writer.Close();
            }
        }