diff --git a/src/waveform.cpp b/src/waveform.cpp new file mode 100644 index 0000000..9cef236 --- /dev/null +++ b/src/waveform.cpp @@ -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& 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& 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 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"); + } +} +*/ \ No newline at end of file diff --git a/src/waveform.hpp b/src/waveform.hpp new file mode 100644 index 0000000..104448a --- /dev/null +++ b/src/waveform.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include +#include +#include + +#include "bitmap/bitmap.hpp" +#include "buffer/buffer.hpp" + + +void waveform_generate( + const Buffer &input_buffer, + std::vector& output, + size_t width, + size_t height +); + + +void waveform_draw_bitmap( + const std::vector& waveform, + Bitmap& bitmap +); \ No newline at end of file