From: Joel Holdsworth Date: Sat, 16 Mar 2013 10:11:50 +0000 (+0000) Subject: Added code to construct analog envelope levels X-Git-Tag: pulseview-0.1.0~75 X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=fda5b6e0e0ebbe55f3d173051b8800293f87cd09;p=pulseview.git Added code to construct analog envelope levels --- diff --git a/pv/data/analogsnapshot.cpp b/pv/data/analogsnapshot.cpp index 1658a04c..c052782e 100644 --- a/pv/data/analogsnapshot.cpp +++ b/pv/data/analogsnapshot.cpp @@ -25,6 +25,8 @@ #include #include +#include + #include #include "analogsnapshot.h" @@ -35,18 +37,35 @@ using namespace std; namespace pv { namespace data { +const int AnalogSnapshot::EnvelopeScalePower = 4; +const int AnalogSnapshot::EnvelopeScaleFactor = 1 << EnvelopeScalePower; +const float AnalogSnapshot::LogEnvelopeScaleFactor = + logf(EnvelopeScaleFactor); +const uint64_t AnalogSnapshot::EnvelopeDataUnit = 64*1024; // bytes + AnalogSnapshot::AnalogSnapshot(const sr_datafeed_analog &analog) : Snapshot(sizeof(float)) { lock_guard lock(_mutex); + memset(_envelope_levels, 0, sizeof(_envelope_levels)); append_payload(analog); } +AnalogSnapshot::~AnalogSnapshot() +{ + lock_guard lock(_mutex); + BOOST_FOREACH(Envelope &e, _envelope_levels) + free(e.samples); +} + void AnalogSnapshot::append_payload( const sr_datafeed_analog &analog) { lock_guard lock(_mutex); append_data(analog.data, analog.num_samples); + + // Generate the first mip-map from the data + append_payload_to_envelope_levels(); } const float* AnalogSnapshot::get_samples( @@ -66,5 +85,89 @@ const float* AnalogSnapshot::get_samples( return data; } +void AnalogSnapshot::reallocate_envelope(Envelope &e) +{ + const uint64_t new_data_length = ((e.length + EnvelopeDataUnit - 1) / + EnvelopeDataUnit) * EnvelopeDataUnit; + if (new_data_length > e.data_length) + { + e.data_length = new_data_length; + e.samples = (EnvelopeSample*)realloc(e.samples, + new_data_length * sizeof(EnvelopeSample)); + } +} + +void AnalogSnapshot::append_payload_to_envelope_levels() +{ + Envelope &e0 = _envelope_levels[0]; + uint64_t prev_length; + EnvelopeSample *dest_ptr; + + // Expand the data buffer to fit the new samples + prev_length = e0.length; + e0.length = _sample_count / EnvelopeScaleFactor; + + // Break off if there are no new samples to compute + if (e0.length == prev_length) + return; + + reallocate_envelope(e0); + + dest_ptr = e0.samples + prev_length; + + // Iterate through the samples to populate the first level mipmap + const float *const end_src_ptr = (float*)_data + + e0.length * EnvelopeScaleFactor; + for (const float *src_ptr = (float*)_data + + prev_length * EnvelopeScaleFactor; + src_ptr < end_src_ptr; src_ptr += EnvelopeScaleFactor) + { + const EnvelopeSample sub_sample = { + *min_element(src_ptr, src_ptr + EnvelopeScaleFactor), + *max_element(src_ptr, src_ptr + EnvelopeScaleFactor), + }; + + *dest_ptr++ = sub_sample; + } + + // Compute higher level mipmaps + for (unsigned int level = 1; level < ScaleStepCount; level++) + { + Envelope &e = _envelope_levels[level]; + const Envelope &el = _envelope_levels[level-1]; + + // Expand the data buffer to fit the new samples + prev_length = e.length; + e.length = el.length / EnvelopeScaleFactor; + + // Break off if there are no more samples to computed + if (e.length == prev_length) + break; + + reallocate_envelope(e); + + // Subsample the level lower level + const EnvelopeSample *src_ptr = + el.samples + prev_length * EnvelopeScaleFactor; + const EnvelopeSample *const end_dest_ptr = e.samples + e.length; + for (dest_ptr = e.samples + prev_length; + dest_ptr < end_dest_ptr; dest_ptr++) + { + const EnvelopeSample *const end_src_ptr = + src_ptr + EnvelopeScaleFactor; + + EnvelopeSample sub_sample = *src_ptr++; + while (src_ptr < end_src_ptr) + { + sub_sample.min = min(sub_sample.min, src_ptr->min); + sub_sample.max = max(sub_sample.max, src_ptr->max); + src_ptr++; + } + + *dest_ptr = sub_sample; + } + } +} + } // namespace data } // namespace pv diff --git a/pv/data/analogsnapshot.h b/pv/data/analogsnapshot.h index a4539184..8eec2797 100644 --- a/pv/data/analogsnapshot.h +++ b/pv/data/analogsnapshot.h @@ -31,15 +31,44 @@ namespace data { class AnalogSnapshot : public Snapshot { +private: + struct EnvelopeSample + { + float min; + float max; + }; + + struct Envelope + { + uint64_t length; + uint64_t data_length; + EnvelopeSample *samples; + }; + +private: + static const unsigned int ScaleStepCount = 10; + static const int EnvelopeScalePower; + static const int EnvelopeScaleFactor; + static const float LogEnvelopeScaleFactor; + static const uint64_t EnvelopeDataUnit; + public: AnalogSnapshot(const sr_datafeed_analog &analog); + virtual ~AnalogSnapshot(); + void append_payload(const sr_datafeed_analog &analog); const float* get_samples(int64_t start_sample, int64_t end_sample) const; -}; +private: + void reallocate_envelope(Envelope &l); + + void append_payload_to_envelope_levels(); + +private: + struct Envelope _envelope_levels[ScaleStepCount]; } // namespace data } // namespace pv