public int AddBend(double deltaMs, double deltaCents, bool endless = false) { double deltaSamples = _format.sampleRate * deltaMs / 1000; var bend = new Bend { centsPerSample = deltaCents / deltaSamples, refCount = endless ? 1 : 0 }; _bends.Add(bend); return(_bends.Count - 1); }
public bool Fill(byte[] buffer) { if (_parts.Count == 0) { return(false); // stop if no partials left on timeline } int bufferPos = 0; // in bytes int bufferSampleCount = buffer.Length / _format.bytesPerSample; var endedParts = new List <int>(); for (int i = 0; i < bufferSampleCount / _format.channels; ++i) { int[] sampleValues = new int[_format.channels]; // zeroes // step bends if (_bends.Count > 0) { for (int j = 0; j < _bends.Count; ++j) { _bends[j].MakeStep(); } } // step parts if (_parts.Count > 0) { for (int j = 0; j < _parts.Count; ++j) { Part p = _parts[j]; // copy if Part is struct if (p.endSample <= _currentSample) { if (p.endSample != _currentSample) { Debug.WriteLine("Warning! Part skipped: {0}", p); // partial added too late ? } endedParts.Add(j); continue; } if (p.startSample <= _currentSample) { // starting if (p.startSample == _currentSample) { if (p.bend != null) { p.bendStartFactor = p.bend.currentFactor; } } // playing if (p.bend != null) { // change current phase step for this copy //!!! valid for struct Part only double factor = p.bend.currentFactor / p.bendStartFactor; p.partial.phaseStep = (int)(p.partial.phaseStep * factor); } if (_format.channels == 2) // stereo { int v0, v1; p.partial.GetNextStereoValue(p.balance16, out v0, out v1); sampleValues[0] += v0; sampleValues[1] += v1; } else // ignore balance { int v = p.partial.GetNextValue(); for (int c = 0; c < sampleValues.Length; ++c) { sampleValues[c] += v; } } p.partial.phaseStep = _parts[j].partial.phaseStep; // !!! put the original step back _parts[j] = p; // for struct } else { break; } } if (endedParts.Count > 0) { for (int k = endedParts.Count - 1; k >= 0; --k) { int j = endedParts[k]; if (_parts[j].bend != null) { Bend bend = _parts[j].bend; bend.refCount -= 1; if (bend.refCount == 0) { _bends.Remove(bend); } } _parts.RemoveAt(j); } endedParts.Clear(); } } _currentSample += 1; // Write sample value to all channels for (int c = 0; c < _format.channels; ++c) { _format.WriteInt(buffer, bufferPos, sampleValues[c]); bufferPos += _format.bytesPerSample; } } //Debug.WriteLine(FormatBuffer(buffer)); return(true); }