]> Some of my projects - openlase-old.git/commitdiff
Add MIDI viewer / visualization
authorHector Martin <hector@marcansoft.com>
Tue, 30 Nov 2010 05:01:21 +0000 (06:01 +0100)
committerHector Martin <hector@marcansoft.com>
Tue, 30 Nov 2010 05:01:21 +0000 (06:01 +0100)
examples/CMakeLists.txt
examples/midiview.c [new file with mode: 0644]

index 60dd6c12abbf68498e6fd1c262d7880e1b90681b..1056656ef19c64ebaf330a0f9248ac667634fca7 100644 (file)
@@ -27,3 +27,7 @@ target_link_libraries(simple openlase)
 
 add_executable(pong pong.c)
 target_link_libraries(pong openlase)
+
+find_package(ALSA REQUIRED)
+add_executable(midiview midiview.c)
+target_link_libraries(midiview openlase ${ALSA_LIBRARIES})
diff --git a/examples/midiview.c b/examples/midiview.c
new file mode 100644 (file)
index 0000000..c211bd0
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+        OpenLase - a realtime laser graphics toolkit
+
+Copyright (C) 2009-2010 Hector Martin "marcan" <hector@marcansoft.com>
+
+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 or version 3.
+
+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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "libol.h"
+
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <jack/jack.h>
+#include <alsa/asoundlib.h>
+#include <math.h>
+
+int portid;
+
+struct blip {
+       int active;
+       float ts;
+       float age;
+       float x, y;
+       float r;
+       float phase;
+       float bright;
+       int note;
+};
+
+float notespeed = 1.0;
+float avgnotes = 0.0;
+
+#define NUM_BLIPS 32
+
+int cur_blip = 0;
+struct blip blips[NUM_BLIPS];
+
+snd_seq_t *open_seq(void) {
+       snd_seq_t *seq_handle;
+
+       if (snd_seq_open(&seq_handle, "default", SND_SEQ_OPEN_INPUT, 0) < 0) {
+               fprintf(stderr, "Error opening ALSA sequencer.\n");
+               return NULL;
+       }
+       snd_seq_set_client_name(seq_handle, "midiview");
+       if ((portid = snd_seq_create_simple_port(seq_handle, "midiview",
+               SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE,
+               SND_SEQ_PORT_TYPE_APPLICATION)) < 0) {
+               fprintf(stderr, "Error creating sequencer port.\n");
+               return NULL;
+       }
+       return seq_handle;
+}
+
+void note_on(int note, int velocity)
+{
+       float ts = avgnotes;
+       if (ts > 20)
+               ts = 20;
+
+       blips[cur_blip].active = 1;
+       blips[cur_blip].ts = ts;
+       int xp = (note) % 12;
+       blips[cur_blip].x = (xp / 6.0 - 1.0)* 0.6;
+       blips[cur_blip].y = (2*note/127.0)-1.0;
+       blips[cur_blip].r = 0.05;
+       blips[cur_blip].bright = 0.3+(velocity / 70.0);
+       blips[cur_blip].phase = 1;
+       blips[cur_blip].note = 1;
+
+       cur_blip = (cur_blip + 1) % NUM_BLIPS;
+}
+
+int midi_action(snd_seq_t *seq_handle) {
+
+       snd_seq_event_t *ev;
+       int cnt = 0;
+
+       do {
+               snd_seq_event_input(seq_handle, &ev);
+               switch (ev->type) {
+                       case SND_SEQ_EVENT_NOTEON:
+                               if (ev->data.note.velocity != 0) {
+                                       note_on(ev->data.note.note, ev->data.note.velocity);
+                                       cnt++;
+                               }
+                       }
+               snd_seq_free_event(ev);
+       } while (snd_seq_event_input_pending(seq_handle, 0) > 0);
+       return cnt;
+}
+
+#define CP 0.55228475f
+
+void circle(float x, float y, float r, uint32_t color)
+{
+       olPushMatrix();
+       olPushColor();
+       olMultColor(color);
+       olTranslate(x, y);
+       olRotate((x+y)*123);
+       /*olBegin(OL_BEZIERSTRIP);
+       olVertex(0, r, color);
+       int i;
+       for (i=0; i<2; i++) {
+               olVertex(CP*r, r, C_WHITE);
+               olVertex(r, CP*r, C_WHITE);
+               olVertex(r, 0, C_WHITE);
+               olVertex(r, -CP*r, C_WHITE);
+               olVertex(CP*r, -r, C_WHITE);
+               olVertex(0, -r, C_WHITE);
+               olVertex(-CP*r, -r, C_WHITE);
+               olVertex(-r, -CP*r, C_WHITE);
+               olVertex(-r, 0, C_WHITE);
+               olVertex(-r, CP*r, C_WHITE);
+               olVertex(-CP*r, r, C_WHITE);
+               olVertex(0, r, C_WHITE);
+       }*/
+/*     olVertex(0, r, color);
+       olVertex(0, r, color);
+       olVertex(r*0.1, r, color);
+       olVertex(r*0.1, r, color);*/
+
+       float circum = 2 * M_PI * r;
+       int segments = circum / (1/30.0);
+       if (segments < 50)
+               segments = 50;
+       int i;
+       olBegin(OL_POINTS);
+       olVertex(r, 0, 0);
+       for (i=0; i<=(2*segments+10); i++) {
+               float w = i * M_PI * 2.0 / segments;
+               uint32_t c = C_WHITE;
+               if (i > 2*segments)
+                       c = C_GREY((10-(i-segments)) * 28);
+               else if (i < 3)
+                       c = C_GREY(i * 85);
+               olVertex(r*cosf(w), r*sinf(w), c);
+       }
+       olEnd();
+       olPopColor();
+       olPopMatrix();
+}
+
+int draw(void)
+{
+       int i;
+       int cnt = 0;
+       for (i=0; i<NUM_BLIPS; i++) {
+               struct blip *b = &blips[i];
+               if (b->active) {
+                       float br = b->bright * b->phase * 255.0;
+                       br = br > 255 ? 255 : br;
+                       uint32_t col = C_GREY((int)br);
+                       circle(b->x, b->y, b->r, col);
+                       cnt++;
+               }
+       }
+       return cnt;
+}
+
+void animate(float time)
+{
+       int i;
+       float ts = avgnotes;
+       if (ts > 20)
+               ts = 20;
+       for (i=0; i<NUM_BLIPS; i++) {
+               struct blip *b = &blips[i];
+
+               if (b->active) {
+                       //if (b->age < 0.3 && b->ts < ts)
+                       //      b->ts = ts;
+                       float bt = time * ts/14;
+                       b->r *= powf(300.0f, bt);
+                       //b->r += bt*1.4;
+                       b->phase -= bt * 2;
+                       if (b->r > 0.7 || b->phase < 0 || b->bright * b->phase < 0.3)
+                               b->active = 0;
+                       b->age += time;
+               }
+       }
+}
+
+int main (int argc, char *argv[])
+{
+
+       snd_seq_t *seq_handle;
+       int npfd;
+       struct pollfd *pfd;
+
+       seq_handle = open_seq();
+       npfd = snd_seq_poll_descriptors_count(seq_handle, POLLIN);
+       pfd = malloc(npfd * sizeof(*pfd));
+       snd_seq_poll_descriptors(seq_handle, pfd, npfd, POLLIN);
+
+       if (argc == 2) {
+               snd_seq_addr_t addr;
+               if (snd_seq_parse_address(seq_handle, &addr, argv[1]) == 0) {
+                       if (snd_seq_connect_from(seq_handle, portid, addr.client, addr.port) == 0) {
+                               printf("Connected to %s\n", argv[1]);
+                       }
+               }
+       }
+
+       OLRenderParams params;
+
+       memset(&params, 0, sizeof params);
+       params.rate = 48000;
+       params.on_speed = 2.0/50.0;
+       params.off_speed = 2.0/35.0;
+       params.start_wait = 6;
+       params.start_dwell = 1;
+       params.curve_dwell = 0;
+       params.corner_dwell = 0;
+       params.curve_angle = cosf(30.0*(M_PI/180.0)); // 30 deg
+       params.end_dwell = 0;
+       params.end_wait = 7;
+       params.flatness = 0.00001;
+       params.snap = 1/100000.0;
+       params.render_flags = RENDER_GRAYSCALE;
+
+       if(olInit(3, 30000) < 0)
+               return 1;
+
+       olSetRenderParams(&params);
+
+       float time = 0;
+       float ftime;
+       int i,j;
+
+       int frames = 0;
+
+       float nps = 0;
+       avgnotes = 5;
+       
+       while(1) {
+               olLoadIdentity();
+
+               int drawn = draw();
+               if (drawn < 2)
+                       draw();
+
+               ftime = olRenderFrame(100);
+
+               float t = powf(0.3, ftime);
+               avgnotes = avgnotes * t + (nps+2) * (1.0f-t);
+
+               animate(ftime);
+
+               int notes = 0;
+               if (poll(pfd, npfd, 0) > 0)
+                       notes = midi_action(seq_handle);
+
+               int pnotes = notes;
+               if (pnotes > 1)
+                       pnotes = 1;
+
+               nps = pnotes / ftime * 1.2;
+
+               frames++;
+               time += ftime;
+               printf("Frame time: %f, Avg FPS:%f, Cur FPS:%f, %d, nps:%3d, avgnotes:%f\n", ftime, frames/time, 1/ftime, notes, (int)nps, avgnotes);
+       }
+
+       olShutdown();
+       exit (0);
+}
+