Added waveform functions
parent
a97cbb249b
commit
ab9f15e137
|
@ -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");
|
||||
}
|
||||
}
|
||||
*/
|
|
@ -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
|
||||
);
|
Loading…
Reference in New Issue