private void ResetStream(bool hardReset) { if (position > byteMappings.Omega.To) { throw new Exception("position beyond length"); } length = byteMappings.Omega.To; byteMappings.SetWarpedPosition(position); ByteTimeWarp mL = byteMappings.Lower; ByteTimeWarp mH = byteMappings.Upper; if (cropStream == null || cropStream.Begin != mL.From || cropStream.End != mH.From || resamplingStream.Length != byteMappings.Omega.To) { // mapping has changed, stream subsection must be renewed if (hardReset) { // Each internal stream for each warped/resampled section works on the same underlying source stream, so // we add the SourceClosePreventionStream to avoid the source being closed when an internally used stream // of a section is disposed or closed (as in the call below). The source stream continues to get closed // when this stream is closed. cropStream = new CropStream(new SourceClosePreventionStream(sourceStream), mL.From, mH.From); // Get rid of stream for previous section if (resamplingStream != null) { resamplingStream.Close(); } // Create stream for current section resamplingStream = new ResamplingStream(cropStream, ResamplingQuality.VariableRate, ByteTimeWarp.CalculateSampleRateRatio(mL, mH)); resamplingStream.Position = position - mL.To; } else { // Reset the streams to the new conditions without creating new instances as the hard reset does // NOTE always hard resetting works too, but this mode has been added to keep the sample resampler throughout playback // Reset crop stream to source bounds, else the successive setting of begin and end can fail if // the new begin position is after the old end position and the validation in the crop stream fails cropStream.Begin = 0; cropStream.End = sourceStream.Length; // Reset the crop stream to the new bounds cropStream.Begin = mL.From; cropStream.End = mH.From; cropStream.Position = 0; // Reset the resampling stream resamplingStream.SampleRateRatio = ByteTimeWarp.CalculateSampleRateRatio(mL, mH); resamplingStream.Position = position - mL.To; } } }
private void ResetStream(bool hardReset) { if (position > byteMappings.Omega.To) { throw new Exception("position beyond length"); } length = byteMappings.Omega.To; byteMappings.SetWarpedPosition(position); ByteTimeWarp mL = byteMappings.Lower; ByteTimeWarp mH = byteMappings.Upper; if (cropStream == null || cropStream.Begin != mL.From || cropStream.End != mH.From || resamplingStream.Length != byteMappings.Omega.To) { // mapping has changed, stream subsection must be renewed if (hardReset) { cropStream = new CropStream(sourceStream, mL.From, mH.From); if (resamplingStream != null) { resamplingStream.Close(); } resamplingStream = new ResamplingStream(cropStream, ResamplingQuality.VariableRate, ByteTimeWarp.CalculateSampleRateRatio(mL, mH)); resamplingStream.Position = position - mL.To; } else { // Reset the streams to the new conditions without creating new instances as the hard reset does // NOTE always hard resetting works too, but this mode has been added to keep the sample resampler throughout playback // Reset crop stream to source bounds, else the successive setting of begin and end can fail if // the new begin position is after the old end position and the validation in the crop stream fails cropStream.Begin = 0; cropStream.End = sourceStream.Length; // Reset the crop stream to the new bounds cropStream.Begin = mL.From; cropStream.End = mH.From; cropStream.Position = 0; // Reset the resampling stream resamplingStream.SampleRateRatio = ByteTimeWarp.CalculateSampleRateRatio(mL, mH); resamplingStream.Position = position - mL.To; } } }
private void mappings_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { var alpha = new ByteTimeWarp { From = 0, To = 0 }; var omega = new ByteTimeWarp { From = sourceStream.Length, To = sourceStream.Length }; if (mappings.Count > 0) { // Convert time mappings to byte mappings // This is the place where the TimeWarps and ByteTimeWarps are kept in sync!! byteMappings = new ByteTimeWarpCollection(mappings.Count); foreach (TimeWarp mapping in mappings) { byteMappings.Add(ByteTimeWarp.Convert(mapping, Properties)); } var first = byteMappings.Alpha; if (first.From > alpha.From) { // The first mapping is not at the start of the stream, insert start of stream alpha byteMappings.Insert(0, alpha); } var last = byteMappings.Omega; if (last.From < omega.From) { // The last mapping is not at the end of the stream, insert EOS omega omega.To += last.Offset; byteMappings.Insert(byteMappings.Count, omega); } } else { byteMappings.Add(alpha); byteMappings.Add(omega); } if (position > byteMappings.Omega.To) { Position = byteMappings.Omega.To; } ResetStream(); }
public static double CalculateSampleRateRatio(ByteTimeWarp mL, ByteTimeWarp mH) { return((mH.To - mL.To) / (double)(mH.From - mL.From)); }