public NoiseGateFilter( IBGCStream stream, double openThreshold = -26.0, double closeThreshold = -32.0, double attackDuration = 0.025, double holdDuration = 0.200, double releaseDuration = 0.150, TransformRMSBehavior rmsBehavior = TransformRMSBehavior.Passthrough) : base(stream) { this.openThreshold = Math.Pow(10.0, openThreshold / 20.0); this.closeThreshold = Math.Pow(10.0, closeThreshold / 20.0); attackRate = (float)(1.0 / (attackDuration * SamplingRate)); releaseRate = (float)(1.0 / (releaseDuration * SamplingRate)); double thresholdDiff = this.openThreshold - this.closeThreshold; double minDecayPeriod = (1.0 / 75.0) * SamplingRate; decayRate = thresholdDiff / minDecayPeriod; this.holdDuration = holdDuration; isOpen = false; attenuation = 0; level = 0; heldTime = 0; inverseSampleRate = 1.0 / SamplingRate; this.rmsBehavior = rmsBehavior; }
public static BiQuadFilter HighShelfFilter( IBGCStream stream, double criticalFrequency, double dbGain, TransformRMSBehavior rmsBehavior = TransformRMSBehavior.Recalculate) { double k = Math.Tan(Math.PI * criticalFrequency / stream.SamplingRate); double gainFactor = Math.Pow(10.0, Math.Abs(dbGain) / 20.0); double norm, a0, a1, a2, b1, b2; if (dbGain >= 0.0) { //Boost norm = 1.0 / (1.0 + Math.Sqrt(2.0) * k + k * k); a0 = (gainFactor + Math.Sqrt(2.0 * gainFactor) * k + k * k) * norm; a1 = 2.0 * (k * k - gainFactor) * norm; a2 = (gainFactor - Math.Sqrt(2.0 * gainFactor) * k + k * k) * norm; b1 = 2.0 * (k * k - 1.0) * norm; b2 = (1.0 - Math.Sqrt(2.0) * k + k * k) * norm; } else { //Cut norm = 1.0 / (gainFactor + Math.Sqrt(2.0 * gainFactor) * k + k * k); a0 = (1.0 + Math.Sqrt(2.0) * k + k * k) * norm; a1 = 2.0 * (k * k - 1.0) * norm; a2 = (1.0 - Math.Sqrt(2.0) * k + k * k) * norm; b1 = 2.0 * (k * k - gainFactor) * norm; b2 = (gainFactor - Math.Sqrt(2.0 * gainFactor) * k + k * k) * norm; } return(new BiQuadFilter(stream, a0, a1, a2, b1, b2, rmsBehavior)); }
public static IBGCStream Convolve( this IBGCStream stream, double[] filter, TransformRMSBehavior transformRMSBehavior = TransformRMSBehavior.Passthrough) { return(new ConvolutionFilter(stream, filter, transformRMSBehavior)); }
public static IBGCStream PhaseVocode( this IBGCStream stream, double speed, TransformRMSBehavior rmsBehavior = TransformRMSBehavior.Passthrough) { return(new PhaseVocoder(stream, speed, rmsBehavior)); }
public NoiseVocoder( IBGCStream stream, double freqLowerBound = 20.0, double freqUpperBound = 16000.0, int bandCount = 22, int fftSize = 4096, int overlapRatio = 4, TransformRMSBehavior rmsBehavior = TransformRMSBehavior.Passthrough, Random randomizer = null) : base(stream) { if (stream.Channels != 1) { throw new StreamCompositionException( $"Noise Vocoder requires a mono input stream. Input stream has {stream.Channels} channels."); } this.fftSize = fftSize; this.overlapRatio = overlapRatio; stepSize = fftSize / overlapRatio; overlapSize = fftSize - stepSize; inputBuffer = new float[fftSize]; noiseBuffer = new double[fftSize]; outputAccumulation = new double[fftSize]; cachedSampleBuffer = new float[stepSize]; noiseFFTBuffer = new Complex64[fftSize]; signalFFTBuffer = new Complex64[fftSize]; amplitudeBuffers = new Complex64[bandCount][]; noiseBandBuffers = new Complex64[bandCount][]; for (int i = 0; i < bandCount; i++) { amplitudeBuffers[i] = new Complex64[fftSize]; noiseBandBuffers[i] = new Complex64[fftSize]; } initialized = false; noiseScalarA = Math.Sqrt(1.0 / 3.0); noiseScalarB = 2.0 * noiseScalarA; double[] windowTemplate = Windowing.GetHalfWindow64(Windowing.Function.BlackmanHarris, fftSize / 2); window = new double[fftSize]; for (int i = 0; i < fftSize / 2; i++) { window[i] = windowTemplate[i]; window[fftSize - i - 1] = windowTemplate[i]; } this.randomizer = randomizer ?? new Random(CustomRandom.Next()); this.rmsBehavior = rmsBehavior; bandFrequencies = GetExponentialDistribution(freqLowerBound, freqUpperBound, bandCount).ToArray(); outputFactor = 0.5 * Math.Sqrt(fftSize) / overlapRatio; }
public CarlileShuffler( IBGCStream stream, double freqLowerBound = 20.0, double freqUpperBound = 16000.0, int bandCount = 22, TransformRMSBehavior rmsBehavior = TransformRMSBehavior.Passthrough, Random randomizer = null) : base(stream) { if (stream.Channels != 1) { throw new StreamCompositionException( $"Carlile Shuffler requires a mono input stream. Input stream has {stream.Channels} channels."); } if (stream.ChannelSamples == int.MaxValue) { throw new StreamCompositionException( $"Carlile Shuffler cannot be performed on a stream of infinite duration. Try truncating first."); } this.randomizer = randomizer ?? new Random(CustomRandom.Next()); this.rmsBehavior = rmsBehavior; frequencyDistribution = GetExponentialDistribution(freqLowerBound, freqUpperBound, bandCount); }
public ExpanderFilter( IBGCStream stream, double ratio = 2.0, double threshold = -40.0, double attackDuration = 0.010, double releaseDuration = 0.050, double outputGain = 0.0, TransformRMSBehavior rmsBehavior = TransformRMSBehavior.Passthrough) : base(stream) { this.threshold = threshold; attackGain = (float)Math.Exp(-1.0 / (SamplingRate * attackDuration)); releaseGain = (float)Math.Exp(-1.0 / (SamplingRate * releaseDuration)); this.outputGain = (float)Math.Pow(10.0, outputGain / 20.0); slope = 1.0 - ratio; lastGain = 0f; runningAverage = 0f; rmscoef = (float)Math.Pow(2, -100.0 / SamplingRate); this.rmsBehavior = rmsBehavior; }
public static IBGCStream Truncate( this IBGCStream stream, int totalChannelSamples, int offset = 0, TransformRMSBehavior transformRMSBehavior = TransformRMSBehavior.Passthrough) { return(new StreamTruncator(stream, totalChannelSamples, offset, transformRMSBehavior)); }
/// <summary> /// Returns of stream padded by <paramref name="prependSamples"/> and <paramref name="appendSamples"/> /// </summary> public static IBGCStream PadBy( this IBGCStream stream, int prependSamples, int appendSamples, TransformRMSBehavior rmsBehavior = TransformRMSBehavior.Passthrough) { return(new StreamPadder(stream, prependSamples, appendSamples, rmsBehavior)); }
public static IBGCStream Truncate( this IBGCStream stream, double totalDuration, int offset = 0, TransformRMSBehavior transformRMSBehavior = TransformRMSBehavior.Passthrough) { return(new StreamTruncator(stream, totalDuration, offset, transformRMSBehavior)); }
/// <summary> /// Returns of stream padded by <paramref name="prependDuration"/> and <paramref name="appendDuration"/> /// </summary> public static IBGCStream PadBy( this IBGCStream stream, double prependDuration, double appendDuration, TransformRMSBehavior rmsBehavior = TransformRMSBehavior.Passthrough) { return(new StreamPadder(stream, prependDuration, appendDuration, rmsBehavior)); }
/// <summary> /// Returns of stream <paramref name="duration"/> in duration, with the stream placed accordingly /// </summary> public static IBGCStream PadTo( this IBGCStream stream, double duration, StreamPadder.StimulusPlacement placement, TransformRMSBehavior rmsBehavior = TransformRMSBehavior.Passthrough) { return(new StreamPadder(stream, duration, placement, rmsBehavior)); }
public static IBGCStream MultiConvolve( this IBGCStream stream, float[] filter1, float[] filter2, TransformRMSBehavior transformRMSBehavior = TransformRMSBehavior.Passthrough) { return(new MultiConvolutionFilter(stream, filter1, filter2, transformRMSBehavior)); }
public MultiConvolutionFilter( IBGCStream stream, float[] filterL, float[] filterR, TransformRMSBehavior rmsBehavior = TransformRMSBehavior.Passthrough) : base(stream) { if (stream.Channels != 1) { throw new StreamCompositionException( $"MultiConvolutionFilter expects a mono input stream. Input stream had {stream.Channels} channels."); } if (filterL.Length != filterR.Length) { throw new StreamCompositionException( $"MultiConvolutionFilter expects filterL and filterR lengths match. Filter lengths: {filterL.Length} {filterR.Length}."); } filterLength = filterL.Length; Channels = 2; int fftSize = Math.Max(FFT_EXP_MIN, filterLength.ToNextExponentOf2() + FFT_SIZE_BUMP); fftLength = 1 << fftSize; samplesPerOverlap = fftLength - filterLength; //Protect against infinite streams if (stream.ChannelSamples == int.MaxValue) { ChannelSamples = int.MaxValue; TotalSamples = int.MaxValue; } else { ChannelSamples = filterLength + stream.ChannelSamples - 1; TotalSamples = Channels * ChannelSamples; } inputBuffer = new float[samplesPerOverlap]; outputAccumulation = new float[Channels * fftLength]; fftBuffer = new Complex64[fftLength]; ifftBuffer = new Complex64[fftLength]; filterFD = new Complex64[Channels][]; filterFD[0] = new Complex64[fftLength]; filterFD[1] = new Complex64[fftLength]; for (int i = 0; i < filterLength; i++) { filterFD[0][i] = filterL[i]; filterFD[1][i] = filterR[i]; } initialized = false; this.rmsBehavior = rmsBehavior; }
public SingleFrequencyDomainToneComposer( IEnumerable <ComplexCarrierTone> carrierTones, int sampleCount, TransformRMSBehavior rmsBehavior = TransformRMSBehavior.Passthrough) { this.carrierTones = carrierTones.ToArray(); Samples = new float[sampleCount]; this.rmsBehavior = rmsBehavior; }
public static IBGCStream CarlileShuffle( this IBGCStream stream, IEnumerable <double> frequencyDistribution, TransformRMSBehavior rmsBehavior = TransformRMSBehavior.Passthrough, Random randomizer = null) { return(new CarlileShuffler( stream: stream, frequencyDistribution: frequencyDistribution, rmsBehavior: rmsBehavior, randomizer: randomizer)); }
public SingleFrequencyDomainToneComposer( IEnumerable <ComplexCarrierTone> carrierTones, double duration, TransformRMSBehavior rmsBehavior = TransformRMSBehavior.Passthrough) { this.carrierTones = carrierTones.ToArray(); int sampleCount = (int)Math.Ceiling(duration * SamplingRate); Samples = new float[sampleCount]; this.rmsBehavior = rmsBehavior; }
public static IBGCStream EchoEffector( this IBGCStream stream, double delay = 0.100, double decay = 0.200, TransformRMSBehavior rmsBehavior = TransformRMSBehavior.Passthrough) { throw new NotImplementedException(); //return new EchoEffector( // stream: stream, // delay: delay, // decay: decay, // rmsBehavior: rmsBehavior); }
public StreamPadder( IBGCStream stream, double totalDuration, StimulusPlacement stimPlacement, TransformRMSBehavior rmsBehavior = TransformRMSBehavior.Passthrough) : base(stream) { if (stream.ChannelSamples == int.MaxValue) { throw new StreamCompositionException("Cannot pad infinite stream using stimPlacement"); } int requestedSamples = (int)Math.Round(totalDuration * SamplingRate); int paddingSamples = requestedSamples - stream.ChannelSamples; this.rmsBehavior = rmsBehavior; if (paddingSamples < 0) { throw new StreamCompositionException("Stimulus exceeds targeted padding length"); } switch (stimPlacement) { case StimulusPlacement.Front: appendedSamples = 0; prependedSamples = paddingSamples; break; case StimulusPlacement.Center: //Putting our extra sample in front appendedSamples = paddingSamples / 2; prependedSamples = paddingSamples - appendedSamples; break; case StimulusPlacement.Back: appendedSamples = paddingSamples; prependedSamples = 0; break; default: throw new NotSupportedException($"Stimulus Placement not supported: {stimPlacement}"); } appendStartSample = stream.ChannelSamples + prependedSamples; ChannelSamples = requestedSamples; TotalSamples = Channels * ChannelSamples; Reset(); }
public StreamWindower( IBGCStream stream, Windowing.Function function = Windowing.Function.Hamming, double totalDuration = double.NaN, int smoothingSamples = 1000, int sampleShift = 0, TransformRMSBehavior rmsBehavior = TransformRMSBehavior.Passthrough) : base(stream) { if (sampleShift > stream.ChannelSamples) { Debug.LogError("Requested a sampleOffset larger than clip length"); sampleShift = 0; } this.sampleShift = sampleShift; if (!double.IsNaN(totalDuration)) { ChannelSamples = Math.Min( (int)Math.Round(totalDuration * SamplingRate), stream.ChannelSamples - sampleShift); TotalSamples = Channels * ChannelSamples; } else { if (stream.ChannelSamples == int.MaxValue) { ChannelSamples = int.MaxValue; TotalSamples = int.MaxValue; } else { ChannelSamples = stream.ChannelSamples - sampleShift; TotalSamples = Channels * ChannelSamples; } } this.rmsBehavior = rmsBehavior; smoothingSamples = Math.Min(smoothingSamples, ChannelSamples / 2); openingWindow = Windowing.GetHalfWindow(function, smoothingSamples); closingWindow = openingWindow; endOpeningWindow = smoothingSamples; startClosingWindow = ChannelSamples - smoothingSamples; Reset(); }
public static IBGCStream ChorusEffector( this IBGCStream stream, double minDelay = 0.040, double maxDelay = 0.060, double rate = 0.25, TransformRMSBehavior rmsBehavior = TransformRMSBehavior.Passthrough) { return(new ChorusEffector( stream: stream, minDelay: minDelay, maxDelay: maxDelay, rate: rate, rmsBehavior: rmsBehavior)); }
public static IBGCStream CarlileShuffle( this IBGCStream stream, double freqLowerBound = 20.0, double freqUpperBound = 16000.0, int bandCount = 22, TransformRMSBehavior rmsBehavior = TransformRMSBehavior.Passthrough, Random randomizer = null) { return(new CarlileShuffler( stream: stream, freqLowerBound: freqLowerBound, freqUpperBound: freqUpperBound, bandCount: bandCount, rmsBehavior: rmsBehavior, randomizer: randomizer)); }
public MultiChannelNoiseGateFilter( IBGCStream stream, double threshold = -50.0, double windowDuration = 0.1, double minNonSilentDuration = 0.07, double attackDuration = 0.05, TransformRMSBehavior rmsBehavior = TransformRMSBehavior.Passthrough) : base(stream) { this.minNonSilentDuration = minNonSilentDuration; threshold = Math.Pow(10.0, threshold / 20.0); int halfWindowSamples = (int)Math.Floor(windowDuration * SamplingRate * 0.5f); int windowSamples = 2 * halfWindowSamples + 1; int smoothingWindowSize = (int)Math.Floor(attackDuration * SamplingRate); latencySamples = halfWindowSamples + smoothingWindowSize; nonSilenceWindow = new NonSilenceWindow( nonSilentSize: windowSamples, maxWindowSize: (int)Math.Round(SamplingRate * 0.005), samplingRate: SamplingRate, channels: Channels, levelThreshold: (float)threshold); smoothingWindow = new SmoothingWindow( windowSize: smoothingWindowSize, channels: Channels); sampleRingBuffer = new RingBuffer <float>(Channels * latencySamples); bufferSize = BUFFER_SIZE_PER_CHANNEL * Channels; sampleBuffer = new float[bufferSize]; this.rmsBehavior = rmsBehavior; if (stream.ChannelSamples == int.MaxValue) { ChannelSamples = int.MaxValue; TotalSamples = int.MaxValue; } else { ChannelSamples = stream.ChannelSamples + latencySamples; TotalSamples = Channels * ChannelSamples; } }
public static IBGCStream NoiseVocode( this IBGCStream stream, double freqLowerBound = 50.0, double freqUpperBound = 16000.0, int bandCount = 22, int fftSize = 1 << 13, int overlapRatio = 4, TransformRMSBehavior rmsBehavior = TransformRMSBehavior.Passthrough, Random randomizer = null) { if (stream.Channels == 1) { return(new NoiseVocoder( stream: stream, freqLowerBound: freqLowerBound, freqUpperBound: freqUpperBound, bandCount: bandCount, fftSize: fftSize, overlapRatio: overlapRatio, rmsBehavior: rmsBehavior, randomizer: randomizer)); } IBGCStream leftStream = stream.Split(out IBGCStream rightStream); leftStream = leftStream.NoiseVocode( freqLowerBound: freqLowerBound, freqUpperBound: freqUpperBound, bandCount: bandCount, fftSize: fftSize, overlapRatio: overlapRatio, rmsBehavior: rmsBehavior, randomizer: randomizer); rightStream = rightStream.NoiseVocode( freqLowerBound: freqLowerBound, freqUpperBound: freqUpperBound, bandCount: bandCount, fftSize: fftSize, overlapRatio: overlapRatio, rmsBehavior: rmsBehavior, randomizer: randomizer); return(new StreamMergeFilter(leftStream, rightStream)); }
public static IBGCStream ContinuousFilter( this IBGCStream stream, IBGCEnvelopeStream envelopeStream, ContinuousFilter.FilterType filterType, double freqLB, double freqUB, double qFactor = double.NaN, TransformRMSBehavior rmsBehavior = TransformRMSBehavior.Recalculate) { return(new ContinuousFilter( stream: stream, filterEnvelope: envelopeStream, filterType: filterType, freqLB: freqLB, freqUB: freqUB, qFactor: qFactor, rmsBehavior: rmsBehavior)); }
public StreamPadder( IBGCStream stream, double prependDuration, double appendDuration, TransformRMSBehavior rmsBehavior = TransformRMSBehavior.Passthrough) : base(stream) { if (prependDuration < 0.0) { throw new StreamCompositionException("Cannot prepend negative durations"); } if (appendDuration < 0.0) { throw new StreamCompositionException("Cannot append negative durations"); } prependedSamples = (int)Math.Round(prependDuration * stream.SamplingRate); appendedSamples = (int)Math.Round(appendDuration * stream.SamplingRate); this.rmsBehavior = rmsBehavior; if (stream.ChannelSamples == int.MaxValue) { if (appendedSamples != 0) { throw new StreamCompositionException("Cannot append padding to an infinite stream"); } appendStartSample = int.MaxValue; ChannelSamples = int.MaxValue; TotalSamples = int.MaxValue; } else { appendStartSample = stream.ChannelSamples + prependedSamples; ChannelSamples = stream.ChannelSamples + prependedSamples + appendedSamples; TotalSamples = stream.Channels * ChannelSamples; } Reset(); }
public StreamEnveloper( IBGCStream stream, IBGCEnvelopeStream envelopeStream, TransformRMSBehavior rmsBehavior = TransformRMSBehavior.Passthrough) : base(stream) { this.rmsBehavior = rmsBehavior; this.envelopeStream = envelopeStream; ChannelSamples = Math.Min(envelopeStream.Samples, stream.ChannelSamples); if (ChannelSamples == int.MaxValue) { TotalSamples = int.MaxValue; } else { TotalSamples = Channels * ChannelSamples; } }
public static BiQuadFilter HighpassFilter( IBGCStream stream, double criticalFrequency, double qFactor = double.NaN, TransformRMSBehavior rmsBehavior = TransformRMSBehavior.Recalculate) { if (double.IsNaN(qFactor)) { qFactor = 1.0 / Math.Sqrt(2.0); } double k = Math.Tan(Math.PI * criticalFrequency / stream.SamplingRate); double norm = 1.0 / (1.0 + k / qFactor + k * k); double a0 = 1.0 * norm; double a1 = -2.0 * a0; double a2 = a0; double b1 = 2.0 * (k * k - 1.0) * norm; double b2 = (1.0 - k / qFactor + k * k) * norm; return(new BiQuadFilter(stream, a0, a1, a2, b1, b2, rmsBehavior)); }
public ConvolutionFilter( IBGCStream stream, IBGCStream filter, TransformRMSBehavior rmsBehavior = TransformRMSBehavior.Passthrough) : base(stream) { if (filter.Channels != 1) { throw new StreamCompositionException($"ConvolutionFilter expects a single-channel filter."); } filterLength = filter.ChannelSamples; int fftSize = Math.Max(FFT_EXP_MIN, filterLength.ToNextExponentOf2() + FFT_SIZE_BUMP); fftLength = 1 << fftSize; samplesPerOverlap = fftLength - filterLength; //Protect against infinite streams if (stream.ChannelSamples == int.MaxValue) { ChannelSamples = int.MaxValue; TotalSamples = int.MaxValue; } else { ChannelSamples = filterLength + stream.ChannelSamples - 1; TotalSamples = Channels * ChannelSamples; } inputBuffer = new float[Channels * samplesPerOverlap]; outputAccumulation = new float[Channels * fftLength]; fftBuffer = new Complex64[fftLength]; filterFD = filter.ComplexSamples(fftLength); initialized = false; this.rmsBehavior = rmsBehavior; }
public ConvolutionFilter( IBGCStream stream, double[] filter, TransformRMSBehavior rmsBehavior = TransformRMSBehavior.Passthrough) : base(stream) { filterLength = filter.Length; int fftSize = Math.Max(FFT_EXP_MIN, filterLength.ToNextExponentOf2() + FFT_SIZE_BUMP); fftLength = 1 << fftSize; samplesPerOverlap = fftLength - filterLength; //Protect against infinite streams if (stream.ChannelSamples == int.MaxValue) { ChannelSamples = int.MaxValue; TotalSamples = int.MaxValue; } else { ChannelSamples = filterLength + stream.ChannelSamples - 1; TotalSamples = Channels * ChannelSamples; } inputBuffer = new float[Channels * samplesPerOverlap]; outputAccumulation = new float[Channels * fftLength]; fftBuffer = new Complex64[fftLength]; filterFD = new Complex64[fftLength]; for (int i = 0; i < filterLength; i++) { filterFD[i] = filter[i]; } initialized = false; this.rmsBehavior = rmsBehavior; }