+ 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;
+ }
+ }