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); }
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)); } }
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); }
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); }
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); } }
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); }
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); } }
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()));
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); }