feat(bank_panel): docked bank grid with LICE waveform thumbnails (M5 Wave A)
Docked SWELL window toggled by a new action, drawing the current bank as per-sample min/max thumbnails (PCM_source + peaks) with an in-memory cache. Pure grid-layout/cache-key math in bank_grid (tested). Renames peaks::Sample -> AudioSample to avoid colliding with bank_model::Sample.
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
// bank_grid — pure implementation. See bank_grid.h. NO REAPER / SWELL / vendor.
|
||||
|
||||
#include "bank_grid.h"
|
||||
|
||||
namespace reasampler {
|
||||
|
||||
int columnsForWidth(int panelWidth, const GridSpec& spec) {
|
||||
// Layout: [gap][cell][gap][cell]...[cell][gap]. n cells occupy
|
||||
// gap + n*(cellWidth + gap). Solve for the largest n that fits panelWidth,
|
||||
// clamped to at least 1 so a too-narrow panel still shows a (clipped) column.
|
||||
const int cell = spec.cellWidth + spec.gap;
|
||||
if (cell <= 0) return 1; // degenerate spec — one column, avoid divide-by-zero
|
||||
const int usable = panelWidth - spec.gap;
|
||||
if (usable < spec.cellWidth) return 1;
|
||||
const int cols = usable / cell;
|
||||
return cols < 1 ? 1 : cols;
|
||||
}
|
||||
|
||||
std::vector<CellRect> computeCellRects(int itemCount,
|
||||
int panelWidth,
|
||||
const GridSpec& spec) {
|
||||
std::vector<CellRect> rects;
|
||||
if (itemCount <= 0) return rects;
|
||||
|
||||
const int cols = columnsForWidth(panelWidth, spec);
|
||||
rects.reserve(static_cast<std::size_t>(itemCount));
|
||||
|
||||
for (int i = 0; i < itemCount; ++i) {
|
||||
const int col = i % cols;
|
||||
const int row = i / cols;
|
||||
CellRect r;
|
||||
r.x = spec.gap + col * (spec.cellWidth + spec.gap);
|
||||
r.y = spec.gap + row * (spec.cellHeight + spec.gap);
|
||||
r.width = spec.cellWidth;
|
||||
r.height = spec.cellHeight;
|
||||
rects.push_back(r);
|
||||
}
|
||||
return rects;
|
||||
}
|
||||
|
||||
int contentHeight(int itemCount, int panelWidth, const GridSpec& spec) {
|
||||
if (itemCount <= 0) return 0;
|
||||
const int cols = columnsForWidth(panelWidth, spec);
|
||||
// Ceil-divide item count by columns to get the row count (partial last row
|
||||
// still occupies a full row of height).
|
||||
const int rows = (itemCount + cols - 1) / cols;
|
||||
return spec.gap + rows * (spec.cellHeight + spec.gap);
|
||||
}
|
||||
|
||||
std::string thumbnailKeyString(const ThumbnailKey& key) {
|
||||
// Length-prefix the sampleId so a delimiter byte inside an id cannot forge a
|
||||
// collision with a different (id, width, generation) triple.
|
||||
std::string s;
|
||||
s.reserve(key.sampleId.size() + 32);
|
||||
s += std::to_string(key.sampleId.size());
|
||||
s += ':';
|
||||
s += key.sampleId;
|
||||
s += '|';
|
||||
s += std::to_string(key.width);
|
||||
s += '|';
|
||||
s += std::to_string(key.generation);
|
||||
return s;
|
||||
}
|
||||
|
||||
} // namespace reasampler
|
||||
Reference in New Issue
Block a user