Added waveform functions

master
Mark 2022-06-24 20:02:47 -07:00
parent a97cbb249b
commit ab9f15e137
Signed by: Mark
GPG Key ID: AD62BB059C2AAEE4
2 changed files with 137 additions and 0 deletions

115
src/waveform.cpp Normal file
View File

@ -0,0 +1,115 @@
#include "waveform.hpp"
/*
Given an input_buffer, create a waveform of size width, height.
@param input_buffer Buffer to read from.
@param output Where to place output. Will be overwritten.
@param width Width of waveform. This is how many values will be written to output.
@param height Height of waveform. Every value in the output vector is less than or equal to height.
*/
void waveform_generate(
const Buffer& input_buffer,
std::vector<size_t>& output,
size_t width,
size_t height
) {
const int samples_per_column = input_buffer.get_output().size() / width;
if (samples_per_column == 0) {
printf("Too few samples %d\n", (int) input_buffer.get_output().size());
return;
}
double bar_height;
for (size_t x = 0; x < width; x++) {
bar_height = 0;
// Average bins
for (int j = 0; j < samples_per_column; j++) {
bar_height += input_buffer.get_output()[x*samples_per_column+j] + INT16_MAX;
}
bar_height /= samples_per_column;
// Scale bar height
bar_height *= height / (double) UINT16_MAX;
output[x] = (size_t) bar_height;
}
}
/*
Draw a waveform in a bitmap.
@param waveform Waveform data, as generated by gen_waveform
@param bitmap Bitmap to draw to. This will be modified, but will NOT be cleared.
*/
void waveform_draw_bitmap(
const std::vector<size_t>& waveform,
Bitmap& bitmap
) {
size_t pt = 0;
size_t prev_pt = 0;
size_t delta;
for (size_t x = 0; x < waveform.size(); x++) {
prev_pt = pt;
pt = waveform[x];
bitmap.setpixel(
pt, x,
0xFF, 0x00, 0x00
);
// If the gap between two consecutive points is too big,
// intermediate values are needed for the wave to be watchable.
delta = pt>prev_pt ? pt-prev_pt : prev_pt-pt;
if ( (x > 0) && (delta > 1) ){
const size_t half = (prev_pt + pt) / 2;
if (prev_pt < pt) {
for (auto y = prev_pt; y < pt; y++) {
bitmap.setpixel(
y, x - (y < half),
0xFF, 0x00, 0x00
);
}
} else {
for (auto y = prev_pt; y > pt; y--) {
bitmap.setpixel(
y, x - (y > half),
0xFF, 0x00, 0x00
);
}
}
}
}
}
/*
Example:
int main(int argc, char *argv[]) {
Buffer buf = Buffer(
"/tmp/mpd.fifo",
44100 / 2, // Keep 500ms of data in buffer
(44100 / 60 * 10)
// Double both if stereo
);
Bitmap b = Bitmap(width, 100);
std::vector<size_t> waveform;
waveform.resize(width);
while(1) {
b.clear();
buf.update();
waveform_generate(buf, waveform, width, 100);
waveform_draw_bitmap(waveform, b);
b.save("/tmp/o.bmp");
}
}
*/

22
src/waveform.hpp Normal file
View File

@ -0,0 +1,22 @@
#pragma once
#include <stdio.h>
#include <cstdint>
#include <vector>
#include "bitmap/bitmap.hpp"
#include "buffer/buffer.hpp"
void waveform_generate(
const Buffer &input_buffer,
std::vector<size_t>& output,
size_t width,
size_t height
);
void waveform_draw_bitmap(
const std::vector<size_t>& waveform,
Bitmap& bitmap
);