Ejemplo n.º 1
0
        public void Seek(int position)
        {
            if (position >= 0)
            {
                cycles = position / samples.Length;
            }
            else
            {
                cycles = (position - samples.Length + 1) / samples.Length;
            }

            this.position = position - cycles * samples.Length;

            partial = Complex64.FromPolarCoordinates(
                magnitude: 1.0,
                phase: cycles * cyclePartial);
        }
Ejemplo n.º 2
0
        private IEnumerable <ComplexCarrierTone> ExpCarrierToneSideBands(
            double depth,
            ComplexCarrierTone carrierTone,
            Dictionary <int, double> sideBandAmplitudeCache,
            double modulationRate,
            double spectralPhase)
        {
            const int bandBounds = 5;

            for (int band = -1 * bandBounds; band <= bandBounds; band++)
            {
                yield return(new ComplexCarrierTone(
                                 frequency: carrierTone.frequency + band * modulationRate,
                                 amplitude: carrierTone.amplitude * Complex64.FromPolarCoordinates(
                                     magnitude: GetExpBandAmplitude(depth, sideBandAmplitudeCache, band),
                                     phase: band * spectralPhase + GetBandPhase(band))));
            }
        }
        public AnalyticFrequencyModulationFilter(
            IAnalyticStream stream,
            double modRate,
            double modDepth)
            : base(stream)
        {
            modulatorPeriodSamples = (int)Abs(Round(SamplingRate / modRate));
            modRate = Sign(modRate) * SamplingRate / modulatorPeriodSamples;

            modulator = new Complex64[modulatorPeriodSamples];

            for (int i = 0; i < modulatorPeriodSamples; i++)
            {
                modulator[i] = Complex64.FromPolarCoordinates(
                    magnitude: 1.0,
                    phase: (modDepth / modRate) * Sin(2.0 * PI * i / modulatorPeriodSamples));
            }
        }
Ejemplo n.º 4
0
        public override int Read(Complex64[] data, int offset, int count)
        {
            int samplesRead = stream.Read(data, offset, count);

            for (int i = 0; i < samplesRead; i++)
            {
                data[offset + i] *= shifterSamples[position++] * partial;
                if (position == shifterSamples.Length)
                {
                    position = 0;
                    cycles++;
                    partial = Complex64.FromPolarCoordinates(
                        magnitude: 1.0,
                        phase: cycles * cyclePartial);
                }
            }

            return(samplesRead);
        }
Ejemplo n.º 5
0
        protected override void _Initialize()
        {
            Complex64[] samples      = stream.ComplexSamples();
            int         bufferLength = samples.Length;

            Fourier.Forward(samples);

            IEnumerator <double> distribution = frequencyDistribution.GetEnumerator();

            distribution.MoveNext();

            int lowerBound = FrequencyDomain.GetComplexFrequencyBin(bufferLength, distribution.Current);

            while (distribution.MoveNext())
            {
                int upperBound = FrequencyDomain.GetComplexFrequencyBin(bufferLength, distribution.Current);

                //Generate random offset for the range
                double offset = 2 * Math.PI * randomizer.NextDouble();

                for (int i = lowerBound; i < upperBound; i++)
                {
                    samples[i] *= Complex64.FromPolarCoordinates(2.0, i * offset);
                }

                lowerBound = upperBound;
            }

            for (int i = bufferLength / 2; i < bufferLength; i++)
            {
                samples[i] = 0.0;
            }

            Fourier.Inverse(samples);

            Samples = new float[bufferLength];

            for (int i = 0; i < bufferLength; i++)
            {
                Samples[i] = (float)samples[i].Real;
            }
        }
        private void TimeShift(Complex64[] samples, double timeShift)
        {
            int length = samples.Length;

            Fourier.Forward(samples);
            double offset = 2 * Math.PI * stream.SamplingRate * timeShift / length;

            for (int i = 1; i < (length / 2) - 1; i++)
            {
                //Double and rotate
                samples[i] *= Complex64.FromPolarCoordinates(2.0, -i * offset);
            }

            //Clear negative frequencies
            Array.Clear(
                array: samples,
                index: length / 2 + 1,
                length: length / 2 - 1);

            Fourier.Inverse(samples);
        }
Ejemplo n.º 7
0
        public SineWave(double amplitude, double frequency, double initialPhase = 0.0)
        {
            this.amplitude = amplitude;

            double sampleCount    = SamplingRate / frequency;
            int    intSampleCount = (int)Ceiling(sampleCount) - 1;

            cyclePartial = (2 * PI * frequency / SamplingRate) * (intSampleCount - sampleCount);

            cycles  = 0;
            partial = Complex64.FromPolarCoordinates(
                magnitude: 1.0,
                phase: cycles * cyclePartial);

            samples = new Complex64[intSampleCount];

            for (int i = 0; i < samples.Length; i++)
            {
                samples[i] = Complex64.FromPolarCoordinates(
                    magnitude: amplitude,
                    phase: initialPhase + 2 * PI * i / sampleCount);
            }
        }
Ejemplo n.º 8
0
        public override int Read(float[] data, int offset, int count)
        {
            int samplesRemaining = count;

            while (samplesRemaining > 0)
            {
                int maxReadCount = Min(2 * samplesRemaining, BUFFER_SIZE);

                int sampleReadCount = convStream.Read(buffer, 0, maxReadCount);

                if (sampleReadCount == 0)
                {
                    break;
                }

                sampleReadCount /= 2;

                for (int i = 0; i < sampleReadCount; i++)
                {
                    data[offset + i] = (float)(new Complex64(buffer[2 * i], buffer[2 * i + 1]) * partial).RealProduct(shifterSamples[shifterPosition++]);
                    if (shifterPosition == shifterSamples.Length)
                    {
                        shifterPosition = 0;
                        cycles++;
                        partial = Complex64.FromPolarCoordinates(
                            magnitude: 1.0,
                            phase: cycles * cyclePartial);
                    }
                }

                samplesRemaining -= sampleReadCount;
                offset           += sampleReadCount;
            }

            return(count - samplesRemaining);
        }
Ejemplo n.º 9
0
        public FrequencyShiftFilter(
            IBGCStream stream,
            double frequencyShift)
            : base(stream)
        {
            if (stream.Channels != 1)
            {
                throw new StreamCompositionException(
                          $"FrequencyShiftFilter requires a mono input stream.  Input stream has {stream.Channels} channels");
            }

            this.frequencyShift = frequencyShift;

            double[] realConvolutionFilter = new double[FILTER_LENGTH];
            double[] imagConvolutionFilter = new double[FILTER_LENGTH];

            const double twoPiSq = 2.0 * PI * PI;
            const double fourASq = 4.0 * A * A;
            const double piSq    = PI * PI;
            const double piOv4   = PI / 4.0;
            const double piOv4A  = PI / (4.0 * A);
            double       N_0     = (FILTER_LENGTH - 1.0) / 2.0;

            for (int i = 1; i < FILTER_LENGTH - 1; i++)
            {
                if (i == N_0)
                {
                    continue;
                }

                double t         = 2.0 * PI * (i - N_0);
                double prefactor = twoPiSq * Cos(A * t) / (t * (fourASq * t * t - piSq));

                realConvolutionFilter[i] = prefactor * (Sin(W_1 * t + piOv4) - Sin(W_2 * t + piOv4));
            }

            realConvolutionFilter[0] = A * (Sin(piOv4A * (A - 2.0 * W_1)) - Sin(piOv4A * (A - 2.0 * W_2)));
            realConvolutionFilter[FILTER_LENGTH - 1] = A * (Sin(piOv4A * (A + 2.0 * W_2)) - Sin(piOv4A * (A + 2.0 * W_1)));

            if (FILTER_LENGTH % 2 == 1)
            {
                realConvolutionFilter[(int)N_0] = Sqrt(2.0) * (W_2 - W_1);
            }

            for (int i = 0; i < FILTER_LENGTH; i++)
            {
                imagConvolutionFilter[i] = realConvolutionFilter[FILTER_LENGTH - 1 - i];
            }

            convStream = new MultiConvolutionFilter(stream, realConvolutionFilter, imagConvolutionFilter);

            double sampleCount    = Abs(SamplingRate / this.frequencyShift);
            int    intSampleCount = (int)Ceiling(sampleCount) - 1;

            cyclePartial = (2 * PI * this.frequencyShift / SamplingRate) * (intSampleCount - sampleCount);

            cycles  = 0;
            partial = Complex64.FromPolarCoordinates(
                magnitude: 1.0,
                phase: cycles * cyclePartial);

            shifterSamples = new Complex64[intSampleCount];

            for (int i = 0; i < intSampleCount; i++)
            {
                shifterSamples[i] = Complex64.FromPolarCoordinates(
                    magnitude: 1.0,
                    phase: Sign(this.frequencyShift) * 2 * PI * i / sampleCount);
            }
        }
Ejemplo n.º 10
0
        public PhaseVocoder(
            IBGCStream stream,
            double speed,
            TransformRMSBehavior rmsBehavior = TransformRMSBehavior.Passthrough)
            : base(stream)
        {
            baseFFTSamples     = (int)Math.Pow(2, BASE_FFT_SIZE);
            expandedFFTSamples = 2 * baseFFTSamples;
            halfFFTSamples     = baseFFTSamples / 2;

            stepSize = baseFFTSamples / OVERLAP_FACTOR;
            overlap  = baseFFTSamples - stepSize;

            outputStep    = ((int)(baseFFTSamples / speed)) / OVERLAP_FACTOR;
            outputSamples = outputStep * OVERLAP_FACTOR;

            effectiveSpeed = stepSize / (double)outputStep;

            localSampleBuffer  = new float[Channels * stepSize];
            cachedSampleBuffer = new float[Channels * outputSamples];

            phasors            = new Complex64[halfFFTSamples + 1];
            phasorDeltas       = new Complex64[halfFFTSamples + 1];
            inputBuffers       = new float[Channels][];
            outputAccumulation = new float[Channels * expandedFFTSamples];

            fftBuffer  = new Complex64[baseFFTSamples];
            ifftBuffer = new Complex64[expandedFFTSamples];

            if (stream.ChannelSamples == int.MaxValue)
            {
                ChannelSamples = int.MaxValue;
                TotalSamples   = int.MaxValue;
            }
            else
            {
                ChannelSamples = (int)(stream.ChannelSamples / effectiveSpeed);
                TotalSamples   = Channels * ChannelSamples;
            }

            for (int i = 0; i < Channels; i++)
            {
                inputBuffers[i] = new float[baseFFTSamples];
            }

            int deltaSteps = outputStep - stepSize;

            for (int i = 0; i <= halfFFTSamples; i++)
            {
                //Initialize phasors to 2 so that it doubles the amplitudes on copy and rotation
                phasors[i]      = 2f;
                phasorDeltas[i] = Complex64.FromPolarCoordinates(1.0, -i * deltaSteps / (double)baseFFTSamples);
            }

            //inputScalar = Math.Sqrt(baseFFTSamples);
            inputScalar  = 1.0;
            outputScalar = 1.0 / OVERLAP_FACTOR;

            windowInput  = new double[baseFFTSamples];
            windowOutput = new double[outputSamples];

            for (int i = 0; i < baseFFTSamples; i++)
            {
                //Hamming
                windowInput[i] = 0.54 - 0.46 * Math.Cos(2.0 * Math.PI * i / (baseFFTSamples - 1));
            }

            for (int i = 0; i < outputSamples; i++)
            {
                //Square
                windowOutput[i] = 1.0;
            }

            this.rmsBehavior = rmsBehavior;
        }
        public FrequencyModulationFilter(
            IBGCStream stream,
            double modRate,
            double modDepth)
            : base(stream)
        {
            if (stream.Channels != 1)
            {
                throw new StreamCompositionException(
                          $"FrequencyModulationFilter requires a mono input stream.  Input stream has {stream.Channels} channels");
            }

            double[] realConvolutionFilter = new double[FILTER_LENGTH];
            double[] imagConvolutionFilter = new double[FILTER_LENGTH];

            const double twoPiSq = 2.0 * PI * PI;
            const double fourASq = 4.0 * A * A;
            const double piSq    = PI * PI;
            const double piOv4   = PI / 4.0;
            const double piOv4A  = PI / (4.0 * A);
            double       N_0     = (FILTER_LENGTH - 1.0) / 2.0;

            for (int i = 1; i < FILTER_LENGTH - 1; i++)
            {
                if (i == N_0)
                {
                    continue;
                }

                double t         = 2 * PI * (i - N_0);
                double prefactor = twoPiSq * Cos(A * t) / (t * (fourASq * t * t - piSq));

                realConvolutionFilter[i] = prefactor * (Sin(W_1 * t + piOv4) - Sin(W_2 * t + piOv4));
            }

            realConvolutionFilter[0] = A * (Sin(piOv4A * (A - 2.0 * W_1)) - Sin(piOv4A * (A - 2.0 * W_2)));
            realConvolutionFilter[FILTER_LENGTH - 1] = A * (Sin(piOv4A * (A + 2.0 * W_2)) - Sin(piOv4A * (A + 2.0 * W_1)));

            if (FILTER_LENGTH % 2 == 1)
            {
                realConvolutionFilter[(int)N_0] = Sqrt(2.0) * (W_2 - W_1);
            }

            for (int i = 0; i < FILTER_LENGTH; i++)
            {
                imagConvolutionFilter[i] = realConvolutionFilter[FILTER_LENGTH - 1 - i];
            }

            convStream = new MultiConvolutionFilter(stream, realConvolutionFilter, imagConvolutionFilter);

            modulatorPeriodSamples = (int)Abs(Round(SamplingRate / modRate));
            modRate = Sign(modRate) * SamplingRate / (double)modulatorPeriodSamples;

            modulator = new Complex64[modulatorPeriodSamples];

            for (int i = 0; i < modulatorPeriodSamples; i++)
            {
                modulator[i] = Complex64.FromPolarCoordinates(
                    magnitude: 1.0,
                    phase: (modDepth / modRate) * Sin(2.0 * PI * i / modulatorPeriodSamples));
            }
        }
        public FramedPhaseReencoder(
            IBGCStream stream,
            double timeShift,
            int frameSize     = (1 << 11),
            int overlapFactor = 8)
            : base(stream)
        {
            UnityEngine.Debug.LogWarning("FramedPhaseReencoder isn't really ready... use at your own risk.");

            this.frameSize     = frameSize;
            this.overlapFactor = overlapFactor;

            halfFrameSize = frameSize / 2;

            stepSize = frameSize / this.overlapFactor;
            overlap  = frameSize - stepSize;

            Channels = stream.Channels;

            if (stream.ChannelSamples == int.MaxValue)
            {
                TotalSamples = int.MaxValue;
            }
            else
            {
                TotalSamples = Channels * stream.ChannelSamples;
            }

            localSampleBuffer  = new float[Channels * stepSize];
            cachedSampleBuffer = new float[Channels * stepSize];

            phasors            = new Complex64[Channels][];
            inputBuffers       = new float[Channels][];
            outputAccumulation = new float[Channels * frameSize];

            fftBuffer = new Complex64[frameSize];

            timeShifts = Enumerable.Repeat(timeShift, Channels).ToArray();
            for (int i = 0; i < Channels; i++)
            {
                inputBuffers[i] = new float[frameSize];

                double rotationFactor = -2.0 * PI * SamplingRate * timeShifts[i] / frameSize;
                for (int j = 1; j < halfFrameSize; j++)
                {
                    //Initialize phasors to 2 so that it doubles the amplitudes on copy and rotation
                    phasors[i][j] = Complex64.FromPolarCoordinates(2.0, j * rotationFactor);
                }

                phasors[i][0] = 1.0;
            }

            outputScalar = 1.0 / (this.overlapFactor);

            windowInput = new double[frameSize];

            for (int i = 0; i < frameSize; i++)
            {
                //Hamming
                windowInput[i] = 0.54 - 0.46 * Cos(2.0 * PI * i / (frameSize - 1));
            }
        }
 public ComplexCarrierTone WithNewPhase(double newPhase) => new ComplexCarrierTone(
     frequency: frequency,
     amplitude: Complex64.FromPolarCoordinates(
         magnitude: amplitude.Magnitude,
         phase: newPhase));
 public ComplexCarrierTone GetCarrier(double fundamentalFreq) =>
 new ComplexCarrierTone(
     frequency: fundamentalFreq * freqRatio,
     amplitude: Complex64.FromPolarCoordinates(
         magnitude: amplitude,
         phase: 2.0 * PI * CustomRandom.NextDouble()));
Ejemplo n.º 15
0
        protected override void _Initialize()
        {
            int fftBufferSize = _channelSamples.CeilingToPowerOfTwo();

            fftBuffer = new Complex64[fftBufferSize];

            double effectiveDuration = fftBufferSize / SamplingRate;

            double t_step     = effectiveDuration / (2.0 * Math.Round(maxTemporalVelocity * effectiveDuration));
            int    t_env_size = 2 * (int)Math.Round(effectiveDuration / (2.0 * t_step));

            double[] carrierFrequencies;

            switch (componentSpacing)
            {
            case ComponentSpacing.Harmonic:
            {
                int componentLB = (int)Math.Round(lowestFrequency / frequencySpacing);
                int componentUB = (int)Math.Round(lowestFrequency * Math.Pow(2, componentBandwidth) / frequencySpacing) + 1;

                int componentCount = componentUB - componentLB;
                carrierFrequencies = new double[componentCount];

                for (int n = 0; n < componentCount; n++)
                {
                    carrierFrequencies[n] = frequencySpacing * (n + componentLB);
                }
            }
            break;

            case ComponentSpacing.Log:
            {
                int componentUB = (int)(Math.Round(2 * componentBandwidth / frequencySpacing) / 2);

                carrierFrequencies = new double[componentUB];

                for (int n = 0; n < componentUB; n++)
                {
                    carrierFrequencies[n] = lowestFrequency * Math.Pow(2.0, n * frequencySpacing);
                }
            }
            break;

            default:
                UnityEngine.Debug.LogError($"Unexpected ComponentSpacing: {componentSpacing}");
                goto case ComponentSpacing.Log;
            }

            int f_env_size = carrierFrequencies.Length;

            double[] t_env_phases_sin = new double[t_env_size];
            double[] t_env_phases_cos = new double[t_env_size];

            double t_env_phase;
            double t_env_phase_factor = 2.0 * Math.PI * temporalModulationRate;

            for (int t = 0; t < t_env_size; t++)
            {
                t_env_phase         = t * t_env_phase_factor * t_step;
                t_env_phases_sin[t] = Math.Sin(t_env_phase);
                t_env_phases_cos[t] = Math.Cos(t_env_phase);
            }

            double value;
            double f_env_phase;
            double f_env_phase_factor = 2.0 * Math.PI * spectralModulationRate;
            double f_env_phase_offset = 0.5 * Math.PI;
            double f_env_phase_sin;
            double f_env_phase_cos;

            Complex64[] complexProfile = new Complex64[t_env_size];
            for (int c = 0; c < f_env_size; c++)
            {
                int f_index = (int)Math.Round(carrierFrequencies[c] * effectiveDuration);
                f_env_phase     = Math.Log(carrierFrequencies[c] / lowestFrequency, 2.0) * f_env_phase_factor + f_env_phase_offset;
                f_env_phase_sin = Math.Sin(f_env_phase);
                f_env_phase_cos = Math.Cos(f_env_phase);

                for (int t = 0; t < t_env_size; t++)
                {
                    value             = f_env_phase_sin * t_env_phases_cos[t] + f_env_phase_cos * t_env_phases_sin[t];
                    complexProfile[t] = Math.Pow(10.0, modulationDepth * value / 20.0);
                }

                Fourier.Forward(complexProfile);
                FFTShift(complexProfile);

                double componentPhase = 2.0 * Math.PI * randomizer.NextDouble();
                for (int t = 0; t < t_env_size; t++)
                {
                    complexProfile[t] *= Complex64.FromPolarCoordinates(
                        magnitude: fftBufferSize / (2.0 * t_env_size),
                        phase: componentPhase);
                }

                int leftPad  = f_index - (t_env_size / 2) - 1;
                int rightPad = (fftBufferSize / 2) - f_index - (t_env_size / 2);

                if (leftPad >= 0 && rightPad >= 0)
                {
                    for (int i = 0; i < t_env_size; i++)
                    {
                        int index = i + leftPad + 1;
                        fftBuffer[index] += complexProfile[i];
                        fftBuffer[fftBufferSize - index] += complexProfile[i].Conjugate();
                    }
                }
                else if (leftPad < 0 && rightPad > 0)
                {
                    for (int i = -leftPad; i < t_env_size; i++)
                    {
                        int index = i + leftPad + 1;
                        fftBuffer[index] += complexProfile[i];
                        fftBuffer[fftBufferSize - index] += complexProfile[i].Conjugate();
                    }
                }
                else if (leftPad > 0 && rightPad < 0)
                {
                    for (int i = 0; i < t_env_size + rightPad; i++)
                    {
                        int index = i + leftPad + 1;
                        fftBuffer[index] += complexProfile[i];
                        fftBuffer[fftBufferSize - index] += complexProfile[i].Conjugate();
                    }
                }
            }

            Fourier.Inverse(fftBuffer);
        }