Skip to content

Commit

Permalink
hex meters good thing?
Browse files Browse the repository at this point in the history
  • Loading branch information
dsheeler committed Dec 24, 2016
1 parent f517b44 commit b62c805
Show file tree
Hide file tree
Showing 6 changed files with 232 additions and 10 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ LFLAGS = $(shell pkg-config --libs wayland-client) \
-lavformat -lavcodec -lpthread -ljack
LIBS =
CFLAGS = -Wall -g $(shell pkg-config --cflags pangocairo)
SRCS = v4l2_wayland.c muxing.c sound_shape.c midi.c
SRCS = v4l2_wayland.c muxing.c sound_shape.c midi.c kmeter.c
OBJS = $(SRCS:.c=.o)
HDRS = muxing.h sound_shape.h midi.h
HDRS = muxing.h sound_shape.h midi.h v4l2_wayland.h kmeter.h

.SUFFIXES:

Expand Down
181 changes: 181 additions & 0 deletions kmeter.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
// ------------------------------------------------------------------------
//
// Copyright (C) 2008-2011 Fons Adriaensen <fons@linuxaudio.org>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ------------------------------------------------------------------------

#include <math.h>
#include <string.h>

#include "kmeter.h"
#define GREY 0.197 / 0.255 * 1.0, 0.203 / 0.255 * 1.0, 0.203 / 0.255 * 1.0

void kmeter_process(kmeter *km, float *p, int n) {
float s, t, z1, z2;
if (km->flag == 1) {// Display thread has read the rms value.
km->rms = 0;
km->flag = 0;
}
z1 = km->z1;
z2 = km->z2;
t = 0;
n /= 4; // Loop is unrolled by 4.
while (n--) {
s = *p++;
s *= s;
if (t < s) t = s; // Update digital peak.
z1 += km->omega * (s - z1); // Update first filter.
s = *p++;
s *= s;
if (t < s) t = s; // Update digital peak.
z1 += km->omega * (s - z1); // Update first filter.
s = *p++;
s *= s;
if (t < s) t = s; // Update digital peak.
z1 += km->omega * (s - z1); // Update first filter.
s = *p++;
s *= s;
if (t < s) t = s; // Update digital peak.
z1 += km->omega * (s - z1); // Update first filter.
z2 += 4 * km->omega * (z1 - z2); // Update second filter.
}
t = sqrtf (t);
// Save filter state. The added constants avoid denormals.
km->z1 = z1 + 1e-20f;
km->z2 = z2 + 1e-20f;
// Adjust RMS value and update maximum since last read().
s = sqrtf (2 * z2);
if (s > km->rms) km->rms = s;
// Digital peak hold and fallback.
if (t > km->dpk) {
// If higher than current value, update and set hold counter.
km->dpk = t;
km->cnt = km->hold;
} else if (km->cnt) {
km->cnt--; // else decrement counter if not zero,
} else {
km->dpk *= km->fall; // else let the peak value fall back,
km->dpk += 1e-10f; // and avoid denormals.
}
}

void kmeter_read(kmeter *km, float *rms, float *dpk) {
// Called by display process approx. 30 times per second.
//
// Returns highest _rms value since last call,
// and current _dpk value.
*rms = km->rms;
*dpk = km->dpk;
km->flag = 1; // Resets _rms in next process().
}

void kmeter_init(kmeter *km, int fsamp, int fsize, float hold, float fall,
float x, float y, float w, color c) {
// Called by initialisation code.
// fsamp = sample frequency
// fsize = period size
// hold = peak hold time, seconds
// fall = peak fallback rate, dB/s
float t;
memset(km, 0, sizeof(*km));
km->omega = 9.72f / fsamp; // ballistic filter coefficient
t = (float) fsize / fsamp; // period time in seconds
km->hold = (int)(hold / t + 0.5f); // number of periods to hold peak
km->fall = powf (10.0f, -0.05f * fall * t); // per period fallback multiplier
km->x = x;
km->y = y;
km->w = w;
km->c = c;
}

void kmeter_render(kmeter *km, cairo_t *cr, float opacity) {
float rms;
float dpk;
int r1;
float scale;
static float hexrot = 0;
cairo_pattern_t *pat;
float x;
float y;
float w;
color *c;
kmeter_read(km, &rms, &dpk);
x = km->x;
y = km->y;
w = dpk * km->w;
c = &km->c;
cairo_save(cr);
cairo_set_line_width(cr, 1);
cairo_set_source_rgba(cr, c->r, c->g, c->b, c->a);
scale = 2.5;
r1 = ((w)/2 * sqrt(3));
cairo_translate(cr, x, y);
cairo_rotate(cr, hexrot * (M_PI/180.0));
cairo_translate(cr, -(w/2), -r1);
cairo_move_to(cr, 0, 0);
cairo_rel_line_to(cr, w, 0);
cairo_rotate(cr, 60 * (M_PI/180.0));
cairo_rel_line_to(cr, w, 0);
cairo_rotate(cr, 60 * (M_PI/180.0));
cairo_rel_line_to(cr, w, 0);
cairo_rotate(cr, 60 * (M_PI/180.0));
cairo_rel_line_to(cr, w, 0);
cairo_rotate(cr, 60 * (M_PI/180.0));
cairo_rel_line_to(cr, w, 0);
cairo_rotate(cr, 60 * (M_PI/180.0));
cairo_rel_line_to(cr, w, 0);
hexrot += 1.5;
cairo_fill(cr);
cairo_restore(cr);
cairo_save(cr);
cairo_set_line_width(cr, 1.5);
cairo_set_operator(cr, CAIRO_OPERATOR_ADD);
cairo_set_source_rgba(cr, GREY, opacity);
cairo_translate(cr, x, y);
cairo_rotate(cr, hexrot * (M_PI/180.0));
cairo_translate(cr, -((w * scale)/2), -r1 * scale);
cairo_scale(cr, scale, scale);
cairo_move_to(cr, 0, 0);
cairo_rel_line_to(cr, w, 0);
cairo_rotate(cr, 60 * (M_PI/180.0));
cairo_rel_line_to(cr, w, 0);
cairo_rotate(cr, 60 * (M_PI/180.0));
cairo_rel_line_to(cr, w, 0);
cairo_rotate(cr, 60 * (M_PI/180.0));
cairo_rel_line_to(cr, w, 0);
cairo_rotate(cr, 60 * (M_PI/180.0));
cairo_rel_line_to(cr, w, 0);
cairo_rotate(cr, 60 * (M_PI/180.0));
cairo_rel_line_to(cr, w, 0);
cairo_rotate(cr, 60 * (M_PI/180.0));
cairo_set_operator(cr, CAIRO_OPERATOR_ADD);
pat = cairo_pattern_create_radial (w/2, r1, 3, w/2, r1, r1*scale);
cairo_pattern_add_color_stop_rgba (pat, 0, c->r, c->g, c->b, opacity);
cairo_pattern_add_color_stop_rgba (pat, 0.4, 0, 0, 0, 0);
cairo_set_source(cr, pat);
cairo_fill(cr);
cairo_pattern_destroy (pat);
/*cairo_save(cr);
cairo_set_source_rgba(cr, c->r, c->g, c->b, c->a);
cairo_translate(cr, x, y);
cairo_arc(cr, 0, 0, ss->r, 0, 2 * M_PI);
cairo_fill_preserve(cr);
cairo_set_source_rgba(cr, 0.5*c->r, 0.5*c->g, 0.5*c->b, 0.75);
cairo_stroke(cr);
cairo_restore(cr);*/
cairo_restore(cr);
}
29 changes: 29 additions & 0 deletions kmeter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#if !defined (_KMETER_H)
#define _KMETER_H (1)

#include <cairo.h>
#include "sound_shape.h"

typedef struct kmeter {
float z1; // filter state
float z2; // filter state
float rms; // max rms value since last read()
float dpk; // current digital peak value
int cnt; // digital peak hold counter
int flag; // flag set by read(), resets _rms
int hold;
float fall;
float omega;
color c;
float x;
float y;
float w;
} kmeter;

void kmeter_init(kmeter *km, int fsamp, int fsize, float hold, float fall,
float x, float y, float w, color c);
void kmeter_process(kmeter *km, float *p, int n);
void kmeter_read(kmeter *km, float *rms, float *dpk);
void kmeter_render(kmeter *km, cairo_t *cr, float opacity);

#endif
2 changes: 0 additions & 2 deletions muxing.c
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,6 @@ static void open_video(AVFormatContext *oc, AVCodec *codec, OutputStream *ost, A
fprintf(stderr, "Could not copy the stream parameters\n");
exit(1);
}
clock_gettime(CLOCK_MONOTONIC, &ost->last_time);
}

int get_video_frame(OutputStream *ost, AVFrame **ret_frame) {
Expand Down Expand Up @@ -346,7 +345,6 @@ int get_video_frame(OutputStream *ost, AVFrame **ret_frame) {
ost->tmp_frame->linesize);
printf("after sws_scale get_video_frame\n");
ost->tmp_frame->pts = ost->frame->pts = ost->next_pts;
ost->last_time = *now;
*ret_frame = ost->tmp_frame;
return 0;
}
Expand Down
22 changes: 18 additions & 4 deletions v4l2_wayland.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include <wayland-client.h>
#include <linux/videodev2.h>

#include "kmeter.h"
#include "muxing.h"
#include "sound_shape.h"
#include "midi.h"
Expand Down Expand Up @@ -577,6 +578,9 @@ static void process_image(const void *p, const int size, int do_tld,
if (!dd->sound_shapes[i].active) continue;
sound_shape_render(&dd->sound_shapes[i], cr);
}
for (i = 0; i < 2; i++) {
kmeter_render(&dd->meters[i], cr, 1.);
}
if (mdown) {
render_detection_box(cr, 1, FIRST_X, FIRST_Y, FIRST_W, FIRST_H);
}
Expand Down Expand Up @@ -707,16 +711,20 @@ int process(jack_nframes_t nframes, void *arg) {
int chn;
size_t i;
static int first_call = 1;
if (can_process) process_midi_output(nframes);
if (can_process) {
process_midi_output(nframes);
for (chn = 0; chn < nports; chn++) {
in[chn] = jack_port_get_buffer(in_ports[chn], nframes);
kmeter_process(&dd->meters[chn], in[chn], nframes);
}
}
if ((!can_process) || (!can_capture) || (audio_done)) return 0;
if (first_call) {
struct timespec *ats = &dd->audio_thread_info->stream->first_time;
clock_gettime(CLOCK_MONOTONIC, ats);
dd->audio_thread_info->stream->samples_count = 0;
first_call = 0;
}
for (chn = 0; chn < nports; chn++)
in[chn] = jack_port_get_buffer(in_ports[chn], nframes);
for (i = 0; i < nframes; i++) {
for (chn = 0; chn < nports; chn++) {
if (jack_ringbuffer_write (audio_ring_buf, (void *) (in[chn]+i),
Expand Down Expand Up @@ -838,7 +846,13 @@ int dingle_dots_init(dingle_dots_t *dd, midi_key_t *keys, uint8_t nb_keys) {
}
}
}
printf("dd_init\n");
color meter_color;
color_init(&meter_color, 30./255., 0, 0, 0.5);
for (i = 0; i < 2; i++) {
float w = width/3.;
kmeter_init(&dd->meters[i], 48000, 256, 0.5, 15.0, w * (i + 1),
height - w, w, meter_color);
}
return 0;
}

Expand Down
4 changes: 2 additions & 2 deletions v4l2_wayland.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include <pthread.h>
#include "sound_shape.h"
#include "kmeter.h"

typedef struct output_frame {
uint32_t *data;
Expand All @@ -15,13 +16,11 @@ typedef struct OutputStream {
AVCodecContext *enc;
int64_t next_pts;
struct timespec first_time;
struct timespec last_time;
int samples_count;
int64_t overruns;
output_frame out_frame;
AVFrame *frame;
AVFrame *tmp_frame;
float t, tincr, tincr2;
struct SwsContext *sws_ctx;
struct SwrContext *swr_ctx;
} OutputStream;
Expand All @@ -37,6 +36,7 @@ typedef struct {
disk_thread_info_t *audio_thread_info;
disk_thread_info_t *video_thread_info;
sound_shape sound_shapes[MAX_NSOUND_SHAPES];
kmeter meters[2];
} dingle_dots_t;

int midi_scale_init(midi_scale_t *scale, uint8_t *notes, uint8_t nb_notes);
Expand Down

0 comments on commit b62c805

Please sign in to comment.