From b4be2cd0633b2d176288326b79262d500604696d Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 1 Jul 2018 18:28:25 -0400 Subject: [PATCH] Implements PCMTrack::add_segment. Thereby completes PCMTrack::resampled_clone. --- Storage/Disk/Track/PCMSegment.cpp | 4 ++++ Storage/Disk/Track/PCMSegment.hpp | 1 + Storage/Disk/Track/PCMTrack.cpp | 29 ++++++++++++++++++++++------- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/Storage/Disk/Track/PCMSegment.cpp b/Storage/Disk/Track/PCMSegment.cpp index 12e96fe77..d70265780 100644 --- a/Storage/Disk/Track/PCMSegment.cpp +++ b/Storage/Disk/Track/PCMSegment.cpp @@ -120,3 +120,7 @@ Storage::Time PCMSegmentEventSource::seek_to(const Time &time_from_start) { const PCMSegment &PCMSegmentEventSource::segment() const { return *segment_; } + +PCMSegment &PCMSegmentEventSource::segment() { + return *segment_; +} diff --git a/Storage/Disk/Track/PCMSegment.hpp b/Storage/Disk/Track/PCMSegment.hpp index de90c4f7d..3e206c0a2 100644 --- a/Storage/Disk/Track/PCMSegment.hpp +++ b/Storage/Disk/Track/PCMSegment.hpp @@ -179,6 +179,7 @@ class PCMSegmentEventSource { @returns a reference to the underlying segment. */ const PCMSegment &segment() const; + PCMSegment &segment(); private: std::shared_ptr segment_; diff --git a/Storage/Disk/Track/PCMTrack.cpp b/Storage/Disk/Track/PCMTrack.cpp index ec54c3b86..dc89fb32d 100644 --- a/Storage/Disk/Track/PCMTrack.cpp +++ b/Storage/Disk/Track/PCMTrack.cpp @@ -50,7 +50,7 @@ PCMTrack::PCMTrack(unsigned int bits_per_track) : PCMTrack() { PCMSegment segment; segment.length_of_a_bit.length = 1; segment.length_of_a_bit.clock_rate = bits_per_track; - segment.data.resize((bits_per_track + 7) >> 3); + segment.data.resize(bits_per_track); segment_event_sources_.emplace_back(segment); } @@ -59,10 +59,12 @@ Track *PCMTrack::clone() const { } Track *PCMTrack::resampled_clone(size_t bits_per_track) { - PCMTrack *new_track = new PCMTrack(static_cast(bits_per_track)); + // Create an empty track. + PCMTrack *const new_track = new PCMTrack(static_cast(bits_per_track)); + // Plot all segments from this track onto the destination. Time start_time; - for(const auto &event_source : segment_event_sources_) { + for(const auto &event_source: segment_event_sources_) { const PCMSegment &source = event_source.segment(); new_track->add_segment(start_time, source, true); start_time += source.length(); @@ -131,11 +133,24 @@ Storage::Time PCMTrack::seek_to(const Time &time_since_index_hole) { } void PCMTrack::add_segment(const Time &start_time, const PCMSegment &segment, bool clamp_to_index_hole) { - // Write half a bit of silence to lead up to the first possible flux point. + // Get a reference to the destination. + PCMSegment &destination = segment_event_sources_.front().segment(); - // Write out the bits contained in this segment. + // Determine the range to fill on the target segment. + const Time end_time = start_time + segment.length(); + const size_t start_bit = start_time.length * destination.data.size() / start_time.clock_rate; + const size_t end_bit = end_time.length * destination.data.size() / end_time.clock_rate; - // Write half a bit of silence to end the segment. + // Reset the destination. + std::fill(destination.data.begin() + static_cast(start_bit), destination.data.begin() + static_cast(end_bit), false); - unsigned int position = start_time.length; + // Step through the source data, and for each true map to a location in the destination and set it. + const size_t target_width = end_bit - start_bit; + const size_t half_offset = target_width / (2 * segment.data.size()); + for(size_t bit = 0; bit < segment.data.size(); ++bit) { + if(segment.data[bit]) { + const size_t output_bit = start_bit + half_offset + (bit * target_width) / segment.data.size(); + destination.data[output_bit] = true; + } + } }