Skip to content

Commit

Permalink
Obscene amount of things in this commit.
Browse files Browse the repository at this point in the history
Added better peak meters.
Moved fft global variables into dingle_dots struct.
Added sounds for snapshots using libcanberra.
Added bitrate gui control.
  • Loading branch information
dsheeler committed May 5, 2018
1 parent 496b946 commit 8686151
Show file tree
Hide file tree
Showing 15 changed files with 434 additions and 296 deletions.
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,17 @@ LFLAGS = $(shell pkg-config --libs cairo) \
$(shell pkg-config --libs pangocairo) \
$(shell pkg-config --libs gtk+-3.0) \
$(shell pkg-config --libs fftw3) \
$(shell pkg-config --libs glib-2.0 libcanberra) \
-lccv -lm -lpng -ljpeg -lswscale -lavutil -lswresample \
-lavformat -lavcodec -lpthread -ljack
LIBS =
#CFLAGS = -O3 -ffast-math -Wall
CFLAGS =-g -Wall
CFLAGS += $(shell pkg-config --cflags pangocairo) \
$(shell pkg-config --cflags gtk+-3.0) \
$(shell pkg-config --cflags fftw3)
$(shell pkg-config --cflags fftw3) \
$(shell pkg-config --cflags glib-2.0 libcanberra)

SRCS = drawable.cc v4l2_wayland.cc muxing.cc sound_shape.cc midi.cc kmeter.cc \
video_file_source.cc dingle_dots.cc v4l2.cc sprite.cc snapshot_shape.cc \
easer.cc easable.cc video_file_out.cc
Expand Down
157 changes: 156 additions & 1 deletion dingle_dots.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,18 @@ int DingleDots::init(int width, int height) {
for (int i = 0; i < MAX_NUM_SOUND_SHAPES; ++i) {
this->sound_shapes[i].clear_state();
}
this->setup_jack();
int sr = jack_get_sample_rate(this->client);
int bufsize = jack_get_buffer_size(this->client);
float w = width / 5;
ca_context_create(&this->event_sound_ctx);
color c1;
color c2;
color_init(&c1, 0.0, 0.2, 0.4, 1.0);
color_init(&c2, 0.0, 0.2, 0.1, 1.0);
this->meters[0].init(this, sr, bufsize, 0.1f, 20.0f, width/2 - 2*w, height/2, w, c1);
this->meters[1].init(this, sr, bufsize, 0.1f, 20.0f, width/2 + 2*w, height/2, w, c2);

snapshot_shape.init("SNAPSHOT", this->drawing_rect.width / 2., this->drawing_rect.width / 16.,
this->drawing_rect.width / 32., random_color(), this);

Expand All @@ -68,6 +80,145 @@ int DingleDots::deactivate_sound_shapes() {
return 0;
}

void jack_shutdown (void *) {
printf("JACK shutdown\n");
abort();
}

double hanning_window(int i, int N) {
return 0.5 * (1 - cos(2 * M_PI * i / (N - 1)));
}

int process(jack_nframes_t nframes, void *arg) {
DingleDots *dd = (DingleDots *)arg;
if (!dd->can_process) return 0;
midi_process_output(nframes, dd);
for (int chn = 0; chn < dd->nports; chn++) {
dd->in[chn] = (jack_default_audio_sample_t *)jack_port_get_buffer(dd->in_ports[chn], nframes);
dd->out[chn] = (jack_default_audio_sample_t *)jack_port_get_buffer(dd->out_ports[chn], nframes);
}
if (nframes >= FFT_SIZE) {
for (int i = 0; i < FFT_SIZE; i++) {
dd->fftw_in[i][0] = dd->in[0][i] * hanning_window(i, FFT_SIZE);
dd->fftw_in[i][1] = 0.0;
}
fftw_execute(dd->p);
}

for (uint i = 0; i < nframes; i++) {
for (int chn = 0; chn < dd->nports; chn++) {
dd->out[chn][i] = dd->in[chn][i];
}
}
for (int i = 0; i < MAX_NUM_VIDEO_FILES; ++i) {
VideoFile *vf = &dd->vf[i];
if (vf->active && vf->audio_playing && !vf->paused) {
jack_default_audio_sample_t sample;
if (vf->audio_decoding_started) {
if (vf->audio_decoding_finished &&
jack_ringbuffer_read_space(vf->abuf) == 0) {
vf->audio_playing = 0;
if (pthread_mutex_trylock(&vf->video_lock) == 0) {
pthread_cond_signal(&vf->video_data_ready);
pthread_mutex_unlock(&vf->video_lock);
}
} else{
for (uint frm = 0; frm < nframes; ++frm) {
for (int chn = 0; chn < 2; ++chn) {
if (jack_ringbuffer_read_space(vf->abuf) >= sizeof(sample)) {
jack_ringbuffer_read(vf->abuf, (char *)&sample, sizeof(sample));
dd->out[chn][frm] += sample;
}
}
}
vf->nb_frames_played += nframes;
if (pthread_mutex_trylock(&vf->audio_lock) == 0) {
pthread_cond_signal(&vf->audio_data_ready);
pthread_mutex_unlock(&vf->audio_lock);
}
}
}
}
}
for (int chn = 0; chn < 2; chn++) {
if (dd->meters[chn].active) dd->meters[chn].process(dd->out[chn], nframes);
}

uint32_t sample_size = sizeof(jack_default_audio_sample_t);
if (dd->vfo[0].get_recording_started() && !dd->vfo[0].get_audio_done() &&
dd->vfo[0].get_recording_audio()) {
if (dd->vfo[0].get_audio_first_call()) {
struct timespec *ats = dd->vfo[0].get_audio_first_time();
clock_gettime(CLOCK_MONOTONIC, ats);
dd->vfo[0].set_audio_samples_count(0);
dd->vfo[0].set_audio_first_call(0);
}
jack_ringbuffer_t *rb = dd->vfo[0].get_audio_ringbuffer();
for (uint i = 0; i < nframes; i++) {
for (int chn = 0; chn < dd->nports; chn++) {
if (jack_ringbuffer_write(rb, (const char *) (dd->out[chn]+i),
sample_size) < sample_size) {
printf("jack overrun: %ld\n", ++dd->jack_overruns);
}
}
}
dd->vfo[0].wake_up_audio_write_thread();
}
dd->vfo[0].wake_up_audio_write_thread();
return 0;
}

int DingleDots::setup_jack()
{
size_t in_size;
this->can_process = 0;
this->jack_overruns = 0;
if ((this->client = jack_client_open("v4l2_wayland",
JackNoStartServer, NULL)) == 0) {
printf("jack server not running?\n");
exit(1);
}
jack_set_process_callback(this->client, process, this);
jack_on_shutdown(this->client, jack_shutdown, NULL);
if (jack_activate(this->client)) {
printf("cannot activate jack client\n");
}
this->nports = 2;
this->in_ports = (jack_port_t **) malloc(sizeof(jack_port_t *) * this->nports);
this->out_ports = (jack_port_t **) malloc(sizeof(jack_port_t *) * this->nports);
in_size = this->nports * sizeof (jack_default_audio_sample_t *);
this->in = (jack_default_audio_sample_t **) malloc (in_size);
this->out = (jack_default_audio_sample_t **) malloc (in_size);

memset(this->in, 0, in_size);
memset(this->out, 0, in_size);
this->midi_ring_buf = jack_ringbuffer_create(MIDI_RB_SIZE);
fftw_in = (fftw_complex *)fftw_malloc(sizeof(fftw_complex) * FFT_SIZE);
fftw_out = (fftw_complex *)fftw_malloc(sizeof(fftw_complex) * FFT_SIZE);
p = fftw_plan_dft_1d(FFT_SIZE, fftw_in, fftw_out, FFTW_FORWARD, FFTW_ESTIMATE);
for (int i = 0; i < this->nports; i++) {
char name[64];
sprintf(name, "input%d", i + 1);
if ((this->in_ports[i] = jack_port_register (this->client, name, JACK_DEFAULT_AUDIO_TYPE,
JackPortIsInput, 0)) == 0) {
printf("cannot register input port \"%s\"!\n", name);
jack_client_close(this->client);
exit(1);
}
sprintf(name, "output%d", i + 1);
if ((this->out_ports[i] = jack_port_register (this->client, name, JACK_DEFAULT_AUDIO_TYPE,
JackPortIsOutput, 0)) == 0) {
printf("cannot register output port \"%s\"!\n", name);
jack_client_close(this->client);
exit(1);
}
}
this->midi_port = jack_port_register(this->client, "output_midi",
JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0);
this->can_process = 1;
return 0;
}


int DingleDots::free() {
if (this->analysis_resize) {
Expand Down Expand Up @@ -192,7 +343,11 @@ void DingleDots::get_sound_shapes(std::vector<Drawable *> &sound_shapes)
SoundShape *ss = &this->sound_shapes[i];
if (ss->active) sound_shapes.push_back(ss);
}
sound_shapes.push_back(&this->snapshot_shape);
for (int i = 0; i < 2; ++i) {
Meter *m = &this->meters[i];
if (m->active) sound_shapes.push_back(m);
}
//sound_shapes.push_back(&this->snapshot_shape);
}

void DingleDots::get_sources(std::vector<Drawable *> &list)
Expand Down
9 changes: 8 additions & 1 deletion dingle_dots.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ extern "C" {
}
#endif
#include <gtk/gtk.h>
#include <canberra.h>
#include "v4l2_wayland.h"
#include <fftw3.h>
typedef struct midi_key_t midi_key_t;
#include "sound_shape.h"
#include "snapshot_shape.h"
Expand All @@ -37,6 +39,7 @@ class DingleDots : public Easable {
int init(int width, int height);
int free();
int deactivate_sound_shapes();
int setup_jack();
int add_note(char *scale_name,
int scale_num, int midi_note, int midi_channel,
double x, double y, double r, color *c);
Expand Down Expand Up @@ -69,7 +72,7 @@ class DingleDots : public Easable {
Sprite sprites[MAX_NUM_SPRITES];
SnapshotShape snapshot_shape;
SoundShape sound_shapes[MAX_NUM_SOUND_SHAPES];
kmeter meters[2];
Meter meters[2];
GdkRectangle drawing_rect;
int doing_motion;
int doing_tld;
Expand Down Expand Up @@ -97,10 +100,14 @@ class DingleDots : public Easable {
GtkWidget *rand_color_button;
GtkWidget *scale_color_button;
GtkWidget *record_button;
GtkWidget *bitrate_entry;
GtkWidget *delete_button;
GtkWidget *channel_combo;
ca_context *event_sound_ctx;
long jack_overruns;
int nports;
fftw_complex *fftw_in, *fftw_out;
fftw_plan p;
jack_default_audio_sample_t **in;
jack_default_audio_sample_t **out;
jack_port_t **in_ports;
Expand Down
8 changes: 8 additions & 0 deletions drawable.cc
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ void Drawable::set_scale(double value)
gtk_widget_queue_draw(this->dingle_dots->drawing_area);
}

int Drawable::fade_in(double duration) {
this->opacity = 0.0;
Easer *e = new Easer();
e->initialize(this, EASER_LINEAR, boost::bind(&Drawable::set_opacity, this, _1), 0, 1.0, duration);
e->start();
return 0;
}

int Drawable::scale_to_fit(double duration) {
this->scale = min(this->dingle_dots->drawing_rect.width / this->pos.width,
this->dingle_dots->drawing_rect.height / this->pos.height);
Expand Down
3 changes: 2 additions & 1 deletion drawable.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ class Drawable : public Easable {

int activate_spin_and_scale_to_fit();
int scale_to_fit(double duration);
protected:
int fade_in(double duration);
protected:
virtual void deactivate_action();
};

Expand Down
1 change: 1 addition & 0 deletions easer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -194,3 +194,4 @@ void Easer::add_finish_action(boost::function<void()> action)
this->finish_actions.push_back(action);
}


Loading

0 comments on commit 8686151

Please sign in to comment.