public void Clear() { _readPosition = 0; _writePosition = 0; _sampleCount = 0; _buffer = new SampleArray(_buffer.Length); }
public CircularSampleBuffer(int size) { _buffer = new SampleArray(size); _writePosition = 0; _readPosition = 0; _sampleCount = 0; }
private static void Init() { var EnvelopeSize = 64; var ExponentialCoeff = .09f; _envelopeTables = new SampleArray[4]; _envelopeTables[0] = (RemoveDenormals(CreateSustainTable(EnvelopeSize))); _envelopeTables[1] = (RemoveDenormals(CreateLinearTable(EnvelopeSize))); _envelopeTables[2] = (RemoveDenormals(CreateExponentialTable(EnvelopeSize, ExponentialCoeff))); _envelopeTables[3] = (RemoveDenormals(CreateSineTable(EnvelopeSize))); _centTable = CreateCentTable(); _semitoneTable = CreateSemitoneTable(); _sincTable = CreateSincTable(SynthConstants.SincWidth, SynthConstants.SincResolution, .43f, HammingWindow); _isInitialized = true; }
public VoiceParameters() { BlockBuffer = new SampleArray(SynthConstants.DefaultBlockSize); //create default number of each component PData = new UnionData[SynthConstants.MaxVoiceComponents]; GeneratorParams = new GeneratorParameters[SynthConstants.MaxVoiceComponents]; Envelopes = new Envelope[SynthConstants.MaxVoiceComponents]; Filters = new Filter[SynthConstants.MaxVoiceComponents]; Lfos = new Lfo[SynthConstants.MaxVoiceComponents]; //initialize each component for (int x = 0; x < SynthConstants.MaxVoiceComponents; x++) { GeneratorParams[x] = new GeneratorParameters(); Envelopes[x] = new Envelope(); Filters[x] = new Filter(); Lfos[x] = new Lfo(); } }
public Synthesizer(int sampleRate, int audioChannels, int bufferSize, int bufferCount, int polyphony) { var MinSampleRate = 8000; var MaxSampleRate = 96000; if (sampleRate < MinSampleRate || sampleRate > MaxSampleRate) throw new Exception("Invalid paramater: (sampleRate) Valid ranges are " + MinSampleRate + " to " + MaxSampleRate); if (audioChannels < 1 || audioChannels > 2) throw new Exception("Invalid paramater: (audioChannels) Valid ranges are " + 1 + " to " + 2); _midiMessageProcessed = new FastList<Action<MidiEvent>>(); // // Setup synth parameters _synthGain = 0.35f; _masterVolume = 1; SampleRate = sampleRate; AudioChannels = audioChannels; MicroBufferSize = SynthHelper.ClampI(bufferSize, (int)(SynthConstants.MinBufferSize * sampleRate), (int)(SynthConstants.MaxBufferSize * sampleRate)); MicroBufferSize = (int) (Math.Ceiling(MicroBufferSize / (double)SynthConstants.DefaultBlockSize) * SynthConstants.DefaultBlockSize); //ensure multiple of block size MicroBufferCount = (Math.Max(1, bufferCount)); SampleBuffer = new SampleArray((MicroBufferSize * MicroBufferCount * audioChannels)); LittleEndian = true; //Setup Controllers _synthChannels = new SynthParameters[SynthConstants.DefaultChannelCount]; for (int x = 0; x < _synthChannels.Length; x++) _synthChannels[x] = new SynthParameters(this); //Create synth voices _voiceManager = new VoiceManager(SynthHelper.ClampI(polyphony, SynthConstants.MinPolyphony, SynthConstants.MaxPolyphony)); //Create midi containers MidiEventQueue = new LinkedList<SynthEvent>(); MidiEventCounts = new int[MicroBufferCount]; _layerList = new Patch[15]; _midiMessageProcessed = new FastList<Action<MidiEvent>>(); ResetSynthControls(); }
private static SampleArray CreateSquareTable(int size, int k) {//Uses Fourier Expansion up to k terms var FourOverPi = 4 / Math.PI; var squaretable = new SampleArray(size); var inc = 1.0 / size; var phase = 0.0; for (int x = 0; x < size; x++) { var value = 0.0; for (int i = 1; i < k + 1; i++) { var twokminus1 = (2 * i) - 1; value += Math.Sin(SynthConstants.TwoPi * (twokminus1) * phase) / (twokminus1); } squaretable[x] = SynthHelper.ClampF((float)(FourOverPi * value), -1, 1); phase += inc; } return squaretable; }
public virtual void GetValues(GeneratorParameters generatorParams, SampleArray blockBuffer, double increment) { var proccessed = 0; do { var samplesAvailable = (int)(Math.Ceiling((generatorParams.CurrentEnd - generatorParams.Phase) / increment)); if (samplesAvailable > blockBuffer.Length - proccessed) { while (proccessed < blockBuffer.Length) { blockBuffer[proccessed++] = GetValue(generatorParams.Phase); generatorParams.Phase += increment; } } else { var endProccessed = proccessed + samplesAvailable; while (proccessed < endProccessed) { blockBuffer[proccessed++] = GetValue(generatorParams.Phase); generatorParams.Phase += increment; } switch (generatorParams.CurrentState) { case GeneratorState.PreLoop: generatorParams.CurrentStart = LoopStartPhase; generatorParams.CurrentEnd = LoopEndPhase; generatorParams.CurrentState = GeneratorState.Loop; break; case GeneratorState.Loop: generatorParams.Phase += generatorParams.CurrentStart - generatorParams.CurrentEnd; break; case GeneratorState.PostLoop: generatorParams.CurrentState = GeneratorState.Finished; while (proccessed < blockBuffer.Length) blockBuffer[proccessed++] = 0; break; } } } while (proccessed < blockBuffer.Length); }
public int Write(SampleArray data, int offset, int count) { var samplesWritten = 0; if (count > _buffer.Length - _sampleCount) { count = _buffer.Length - _sampleCount; } var writeToEnd = Math.Min(_buffer.Length - _writePosition, count); SampleArray.Blit(data, offset, _buffer, _writePosition, writeToEnd); _writePosition += writeToEnd; _writePosition %= _buffer.Length; samplesWritten += writeToEnd; if (samplesWritten < count) { SampleArray.Blit(data, offset + samplesWritten, _buffer, _writePosition, count - samplesWritten); _writePosition += (count - samplesWritten); samplesWritten = count; } _sampleCount += samplesWritten; return samplesWritten; }
public int Read(SampleArray data, int offset, int count) { if (count > _sampleCount) { count = _sampleCount; } var samplesRead = 0; var readToEnd = Math.Min(_buffer.Length - _readPosition, count); SampleArray.Blit(_buffer, _readPosition, data, offset, readToEnd); samplesRead += readToEnd; _readPosition += readToEnd; _readPosition %= _buffer.Length; if (samplesRead < count) { SampleArray.Blit(_buffer, _readPosition, data, offset + samplesRead, count - samplesRead); _readPosition += (count - samplesRead); samplesRead = count; } _sampleCount -= samplesRead; return samplesRead; }
public int Write(SampleArray data, int offset, int count) { var samplesWritten = 0; if (count > _buffer.Length - _sampleCount) { count = _buffer.Length - _sampleCount; } var writeToEnd = Math.Min(_buffer.Length - _writePosition, count); SampleArray.Blit(data, offset, _buffer, _writePosition, writeToEnd); _writePosition += writeToEnd; _writePosition %= _buffer.Length; samplesWritten += writeToEnd; if (samplesWritten < count) { SampleArray.Blit(data, offset + samplesWritten, _buffer, _writePosition, count - samplesWritten); _writePosition += (count - samplesWritten); samplesWritten = count; } _sampleCount += samplesWritten; return(samplesWritten); }
public override void GetValues(GeneratorParameters generatorParams, SampleArray blockBuffer, double increment) { int proccessed = 0; do { int samplesAvailable = (int)Math.Ceiling((generatorParams.CurrentEnd - generatorParams.Phase) / increment); if (samplesAvailable > blockBuffer.Length - proccessed) { Interpolate(generatorParams, blockBuffer, increment, proccessed, blockBuffer.Length); return; //proccessed = blockBuffer.Length; } else { int endProccessed = proccessed + samplesAvailable; Interpolate(generatorParams, blockBuffer, increment, proccessed, endProccessed); proccessed = endProccessed; switch (generatorParams.CurrentState) { case GeneratorState.PreLoop: generatorParams.CurrentStart = LoopStartPhase; generatorParams.CurrentEnd = LoopEndPhase; generatorParams.CurrentState = GeneratorState.Loop; break; case GeneratorState.Loop: generatorParams.Phase += generatorParams.CurrentStart - generatorParams.CurrentEnd; break; case GeneratorState.PostLoop: generatorParams.CurrentState = GeneratorState.Finished; while (proccessed < blockBuffer.Length) blockBuffer[proccessed++] = 0f; break; } } } while (proccessed < blockBuffer.Length); }
public int Read(SampleArray data, int offset, int count) { if (count > _sampleCount) { count = _sampleCount; } var samplesRead = 0; var readToEnd = Math.Min(_buffer.Length - _readPosition, count); SampleArray.Blit(_buffer, _readPosition, data, offset, readToEnd); samplesRead += readToEnd; _readPosition += readToEnd; _readPosition %= _buffer.Length; if (samplesRead < count) { SampleArray.Blit(_buffer, _readPosition, data, offset + samplesRead, count - samplesRead); _readPosition += (count - samplesRead); samplesRead = count; } _sampleCount -= samplesRead; return(samplesRead); }
public void AddSamples(SampleArray samples) { var uint8 = new Uint8Array(samples.Buffer); var b64 = JsCode("window.btoa(String.fromCharCode.apply(null, uint8))").As<string>(); document.getElementById(_swfId).As<IFlashSynthOutput>().AlphaSynthAddSamples(b64); }
private void GenerateSound(DOMEvent e) { var ae = (AudioProcessingEvent)e; var left = ae.outputBuffer.getChannelData(0); var right = ae.outputBuffer.getChannelData(1); var samples = left.length + right.length; if (_circularBuffer.Count < samples) { if (_finished) { if (Finished != null) Finished(); Stop(); } else { // when buffering we count it as pause time _pauseTime += (int)((BufferSize * 1000) / (2 * _context.sampleRate)); } } else { var buffer = new SampleArray(samples); _circularBuffer.Read(buffer, 0, buffer.Length); var s = 0; for (int i = 0; i < left.length; i++) { left[i] = buffer[s++]; right[i] = buffer[s++]; } } if (PositionChanged != null) { PositionChanged((int)(CalcPosition())); } if (!_finished) { RequestBuffers(); } }
private void Interpolate(GeneratorParameters generatorParams, SampleArray blockBuffer, double increment, int start, int end) { switch (SynthConstants.InterpolationMode) { case Interpolation.Linear: #region Linear { double _end = generatorParams.CurrentState == GeneratorState.Loop ? this.LoopEndPhase - 1 : this.EndPhase - 1; int index; float s1, s2, mu; while (start < end && generatorParams.Phase < _end)//do this until we reach an edge case or fill the buffer { index = (int)generatorParams.Phase; s1 = Samples[index]; s2 = Samples[index + 1]; mu = (float)(generatorParams.Phase - index); blockBuffer[start++] = s1 + mu * (s2 - s1); generatorParams.Phase += increment; } while (start < end)//edge case, if in loop wrap to loop start else use duplicate sample { index = (int)generatorParams.Phase; s1 = Samples[index]; if (generatorParams.CurrentState == GeneratorState.Loop) s2 = Samples[(int)generatorParams.CurrentStart]; else s2 = s1; mu = (float)(generatorParams.Phase - index); blockBuffer[start++] = s1 + mu * (s2 - s1); generatorParams.Phase += increment; } } #endregion break; case Interpolation.Cosine: #region Cosine { double _end = generatorParams.CurrentState == GeneratorState.Loop ? this.LoopEndPhase - 1 : this.EndPhase - 1; int index; float s1, s2, mu; while (start < end && generatorParams.Phase < _end)//do this until we reach an edge case or fill the buffer { index = (int)generatorParams.Phase; s1 = Samples[index]; s2 = Samples[index + 1]; mu = (1f - (float)Math.Cos((generatorParams.Phase - index) * Math.PI)) * 0.5f; blockBuffer[start++] = s1 * (1f - mu) + s2 * mu; generatorParams.Phase += increment; } while (start < end)//edge case, if in loop wrap to loop start else use duplicate sample { index = (int)generatorParams.Phase; s1 = Samples[index]; if (generatorParams.CurrentState == GeneratorState.Loop) s2 = Samples[(int)generatorParams.CurrentStart]; else s2 = s1; mu = (1f - (float)Math.Cos((generatorParams.Phase - index) * Math.PI)) * 0.5f; blockBuffer[start++] = s1 * (1f - mu) + s2 * mu; generatorParams.Phase += increment; } } #endregion break; case Interpolation.CubicSpline: #region CubicSpline { double _end = generatorParams.CurrentState == GeneratorState.Loop ? this.LoopStartPhase + 1 : this.StartPhase + 1; int index; float s0, s1, s2, s3, mu; while (start < end && generatorParams.Phase < _end)//edge case, wrap to endpoint or duplicate sample { index = (int)generatorParams.Phase; if (generatorParams.CurrentState == GeneratorState.Loop) s0 = Samples[(int)generatorParams.CurrentEnd - 1]; else s0 = Samples[index]; s1 = Samples[index]; s2 = Samples[index + 1]; s3 = Samples[index + 2]; mu = (float)(generatorParams.Phase - index); blockBuffer[start++] = ((-0.5f * s0 + 1.5f * s1 - 1.5f * s2 + 0.5f * s3) * mu * mu * mu + (s0 - 2.5f * s1 + 2f * s2 - 0.5f * s3) * mu * mu + (-0.5f * s0 + 0.5f * s2) * mu + (s1)); generatorParams.Phase += increment; } _end = generatorParams.CurrentState == GeneratorState.Loop ? this.LoopEndPhase - 2 : this.EndPhase - 2; while (start < end && generatorParams.Phase < _end) { index = (int)generatorParams.Phase; s0 = Samples[index - 1]; s1 = Samples[index]; s2 = Samples[index + 1]; s3 = Samples[index + 2]; mu = (float)(generatorParams.Phase - index); blockBuffer[start++] = ((-0.5f * s0 + 1.5f * s1 - 1.5f * s2 + 0.5f * s3) * mu * mu * mu + (s0 - 2.5f * s1 + 2f * s2 - 0.5f * s3) * mu * mu + (-0.5f * s0 + 0.5f * s2) * mu + (s1)); generatorParams.Phase += increment; } _end += 1; while (start < end)//edge case, wrap to startpoint or duplicate sample { index = (int)generatorParams.Phase; s0 = Samples[index - 1]; s1 = Samples[index]; if (generatorParams.Phase < _end) { s2 = Samples[index + 1]; if (generatorParams.CurrentState == GeneratorState.Loop) s3 = Samples[(int)generatorParams.CurrentStart]; else s3 = s2; } else { if (generatorParams.CurrentState == GeneratorState.Loop) { s2 = Samples[(int)generatorParams.CurrentStart]; s3 = Samples[(int)generatorParams.CurrentStart + 1]; } else { s2 = s1; s3 = s1; } } mu = (float)(generatorParams.Phase - index); blockBuffer[start++] = ((-0.5f * s0 + 1.5f * s1 - 1.5f * s2 + 0.5f * s3) * mu * mu * mu + (s0 - 2.5f * s1 + 2f * s2 - 0.5f * s3) * mu * mu + (-0.5f * s0 + 0.5f * s2) * mu + (s1)); generatorParams.Phase += increment; } } #endregion break; default: #region None { while (start < end) { blockBuffer[start++] = Samples[(int)generatorParams.Phase]; generatorParams.Phase += increment; } } #endregion break; } }
private static SampleArray CreateSincTable(int windowSize, int resolution, float cornerRatio, Func<float, int, float> windowFunction) { var subWindow = ((windowSize / 2) + 1); var table = new SampleArray((subWindow * resolution)); var gain = 2.0 * cornerRatio; for (int x = 0; x < subWindow; x++) { for (int y = 0; y < resolution; y++) { var a = x + (y / (float)(resolution)); var sinc = SynthConstants.TwoPi * cornerRatio * a; if (Math.Abs(sinc) > 0.00001) sinc = Math.Sin(sinc) / sinc; else sinc = 1.0; table[x * SynthConstants.SincResolution + y] = (float)(gain * sinc * windowFunction(a, windowSize)); } } return table; }
private static SampleArray CreateSineTable(int size) { var graph = new SampleArray(size); var inc = (float)(3.0 * Math.PI / 2.0) / (size - 1); var phase = 0.0; for (int x = 0; x < size; x++) { graph[x] = (float)Math.Abs(Math.Sin(phase)); phase += inc; } return graph; }
private static SampleArray CreateLinearTable(int size) { var table = new SampleArray(size); for (int x = 0; x < size; x++) { table[x] = x / (float)(size - 1); } return table; }
public override int Read(float[] buffer, int offset, int count) { if (_circularBuffer.Count < count) { if (_finished) { if (Finished != null) Finished(); Stop(); } else { // when buffering we count it as pause time _pauseTime += (BufferSize * 1000) / (2 * WaveFormat.SampleRate); } } else { var read = new SampleArray(count); _circularBuffer.Read(read, 0, read.Length); for (int i = 0; i < count; i++) { buffer[offset + i] = read[i]; } } if (PositionChanged != null) { PositionChanged((int)(CalcPosition())); } if (!_finished) { RequestBuffers(); } return count; }
public static void Blit(SampleArray src, int srcPos, SampleArray dest, int destPos, int len) { }
public void AddSamples(SampleArray samples) { PostMessage(new { cmd = "playerAddSamples", samples = samples }); }
public static void Blit(SampleArray src, int srcPos, SampleArray dest, int destPos, int len) { Array.Copy(src.Samples, srcPos, dest.Samples, destPos, len); }
private static SampleArray CreateSemitoneTable() {//-127 to 127 semitones var table = new SampleArray(255); for (int x = 0; x < table.Length; x++) { table[x] = (float)Math.Pow(2.0, (x - 127.0) / 12.0); } return table; }
private static SampleArray CreateSustainTable(int size) { var table = new SampleArray(size); for (int x = 0; x < size; x++) { table[x] = 1; } return table; }
public override int Read(float[] buffer, int offset, int count) { if (_circularBuffer.Count < count) { if (_finished) { if (Finished != null) Finished(); Stop(); } } else { var read = new SampleArray(count); _circularBuffer.Read(read, 0, read.Length); for (int i = 0; i < count; i++) { buffer[offset + i] = read[i]; } var samples = count/2.0; _currentTime += (samples / SampleRate) * 1000 * _playbackSpeed; } if (PositionChanged != null) { PositionChanged((int)_currentTime); } if (!_finished) { RequestBuffers(); } return count; }
private static SampleArray CreateExponentialTable(int size, float coeff) { coeff = SynthHelper.ClampF(coeff, .001f, .9f); var graph = new SampleArray(size); var val = 0.0; for (int x = 0; x < size; x++) { graph[x] = (float)val; val += coeff * ((1 / 0.63) - val); } for (int x = 0; x < size; x++) { graph[x] = graph[x] / graph[graph.Length - 1]; } return graph; }
public void SetAudioChannelCount(int channels) { channels = SynthHelper.ClampI(channels, 1, 2); if (AudioChannels != channels) { AudioChannels = channels; SampleBuffer = new SampleArray((MicroBufferSize * MicroBufferCount * AudioChannels)); } }
private static SampleArray RemoveDenormals(SampleArray data) { for (int x = 0; x < data.Length; x++) { if (Math.Abs(data[x]) < SynthConstants.DenormLimit) data[x] = 0; } return data; }
public void ApplyFilter(SampleArray data) { switch (FilterMethod) { case FilterType.BiquadHighpass: case FilterType.BiquadLowpass: for (int x = 0; x < data.Length; x++) { _m3 = data[x] - _a1 * _m1 - _a2 * _m2; data[x] = _b2 * (_m3 + _m2) + _b1 * _m1; _m2 = _m1; _m1 = _m3; } break; case FilterType.OnePoleLowpass: for (int x = 0; x < data.Length; x++) { _m1 += _a1 * (data[x] - _m1); data[x] = _m1; } break; } }
public void ApplyFilterInterp(SampleArray data, int sampleRate) { float[] ic = GenerateFilterCoeff(CutOff / sampleRate, Resonance); float a1_inc = (ic[0] - _a1) / data.Length; float a2_inc = (ic[1] - _a2) / data.Length; float b1_inc = (ic[2] - _b1) / data.Length; float b2_inc = (ic[3] - _b2) / data.Length; switch (FilterMethod) { case FilterType.BiquadHighpass: case FilterType.BiquadLowpass: for (int x = 0; x < data.Length; x++) { _a1 += a1_inc; _a2 += a2_inc; _b1 += b1_inc; _b2 += b2_inc; _m3 = data[x] - _a1 * _m1 - _a2 * _m2; data[x] = _b2 * (_m3 + _m2) + _b1 * _m1; _m2 = _m1; _m1 = _m3; } _a1 = ic[0]; _a2 = ic[1]; _b1 = ic[2]; _b2 = ic[3]; break; case FilterType.OnePoleLowpass: for (int x = 0; x < data.Length; x++) { _a1 += a1_inc; _m1 += _a1 * (data[x] - _m1); data[x] = _m1; } _a1 = ic[0]; break; } CoeffNeedsUpdating = false; }
public void AddSamples(SampleArray f) { _circularBuffer.Write(f, 0, f.Length); }
private static SampleArray CreateCentTable() {//-100 to 100 cents var cents = new SampleArray(201); for (int x = 0; x < cents.Length; x++) { cents[x] = (float)Math.Pow(2.0, (x - 100.0) / 1200.0); } return cents; }