summaryrefslogtreecommitdiff
path: root/midirip.c
diff options
context:
space:
mode:
Diffstat (limited to 'midirip.c')
-rw-r--r--midirip.c340
1 files changed, 340 insertions, 0 deletions
diff --git a/midirip.c b/midirip.c
new file mode 100644
index 0000000..f0c86a5
--- /dev/null
+++ b/midirip.c
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 2010 Florian Jung <flo@windfisch.org>
+ * for the MIDI constants and some jack-midi code, which has been
+ * taken from jack-keyboard:
+ * Copyright (c) 2007, 2008 Edward Tomasz Napierała <trasz@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <assert.h>
+#include <string.h>
+#include <jack/jack.h>
+#include <jack/midiport.h>
+#include <jack/ringbuffer.h>
+
+
+#define MIDI_PORT_NAME "midi"
+#define REC_PORT_NAME "rec"
+
+jack_port_t *recport, *midiport;
+double rate_limit = 0.0;
+jack_client_t *jack_client = NULL;
+
+#define MIDI_NOTE_ON 0x90
+#define MIDI_NOTE_OFF 0x80
+#define MIDI_PROGRAM_CHANGE 0xC0
+#define MIDI_CONTROLLER 0xB0
+#define MIDI_RESET 0xFF
+#define MIDI_HOLD_PEDAL 64
+#define MIDI_ALL_SOUND_OFF 120
+#define MIDI_ALL_MIDI_CONTROLLERS_OFF 121
+#define MIDI_ALL_NOTES_OFF 123
+#define MIDI_BANK_SELECT_MSB 0
+#define MIDI_BANK_SELECT_LSB 32
+
+#define BANK_MIN 0
+#define BANK_MAX 127
+#define PROGRAM_MIN 0
+#define PROGRAM_MAX 16383
+#define CHANNEL_MIN 1
+#define CHANNEL_MAX 16
+
+#define time_offsets_are_zero 0
+
+struct MidiMessage {
+ jack_nframes_t time;
+ int len; /* Length of MIDI message, in bytes. */
+ unsigned char data[3];
+};
+
+#define RINGBUFFER_SIZE 1024*sizeof(struct MidiMessage)
+
+jack_ringbuffer_t *ringbuffer;
+
+/* Number of currently selected channel (0..15). */
+int channel = 9;
+
+
+
+//FINDMICH
+#define RECBUF_LEN 44100*60
+#define SILENCE_LEN 44100*2
+#define SILENCE_ADD 0.01
+#define QUIET_LEN 44100*1
+#define WAIT_AFTER 22050
+
+jack_default_audio_sample_t recbuf[RECBUF_LEN];
+int rbpos;
+jack_default_audio_sample_t silence;
+int note=60, laut=100, notelen=22050;
+
+int flo_start=0;
+
+jack_default_audio_sample_t arr_dist (jack_default_audio_sample_t a[], int l)
+{
+ int i;
+ jack_default_audio_sample_t max,min;
+ min=max=a[0];
+
+ for (i=0;i<l;i++)
+ if (a[i]>max)
+ max=a[i];
+ else if (a[i]<min)
+ min=a[i];
+
+ return max-min;
+}
+
+
+int process_callback(jack_nframes_t nframes, void *notused) //WICHTIG FINDMICH
+{
+ static int state = 0;
+ static int frame_cnt;
+
+ int i;
+ void *midipb;
+ jack_nframes_t last_frame_time;
+ unsigned char data[3];
+
+ last_frame_time = jack_last_frame_time(jack_client);
+
+
+ jack_default_audio_sample_t *recpb=
+ (jack_default_audio_sample_t *) jack_port_get_buffer (recport, nframes);
+ if (recpb==NULL) printf("rec fail\n");
+
+ midipb = jack_port_get_buffer(midiport, nframes);
+ if (midipb==NULL) printf("midi fail\n");
+ jack_midi_clear_buffer(midipb);
+
+
+ switch(state)
+ {
+ case 0: // warte auf freigabe
+ if (flo_start)
+ {
+ state=1;
+ rbpos=0;
+ printf("messe stille\n");
+ }
+ break;
+
+ case 1: // sammle daten über stille
+ for (i=0;i<nframes;i++)
+ {
+ recbuf[rbpos]=recpb[i];
+ rbpos++;
+ }
+ if (rbpos>=SILENCE_LEN) //genug?
+ {
+ silence=arr_dist(recbuf,SILENCE_LEN) + SILENCE_ADD;
+ printf(" stille=%f\n",silence);
+ state=2;
+ }
+ break;
+
+ case 2: // spiele note
+ //TODO: hole nächsten eintrag
+ printf("NOTE ON\n");
+ data[0]=MIDI_NOTE_ON;
+ data[1]=note; //TODO
+ data[2]=laut; //TODO
+ if (jack_midi_event_write(midipb, 0, data, 3))
+ fprintf(stderr,"Note loss when writing\n");
+ frame_cnt=notelen; //TODO
+
+ rbpos=0;
+
+ state=3;
+ break;
+
+ case 3: // nehme auf und sende ggf note off
+ if (frame_cnt != -1) //ggf note off
+ {
+ if (frame_cnt < nframes) //noteoff in diesem frame?
+ {
+ printf("NOTE OFF in %i\n",frame_cnt);
+ data[0]=MIDI_NOTE_OFF;
+ data[1]=note; //TODO
+ data[2]=laut; //TODO
+
+ if (jack_midi_event_write(midipb, frame_cnt, data, 3))
+ fprintf(stderr,"Note loss when writing\n");
+
+ frame_cnt=-1;
+ }
+ else
+ frame_cnt-=nframes;
+ }
+
+ for (i=0;i<nframes;i++) //aufnehmen
+ {
+ if (rbpos>=RECBUF_LEN)
+ printf("WARNING: segfault\n"); //TODO
+ recbuf[rbpos]=recpb[i];
+ rbpos++;
+ }
+ if (rbpos>QUIET_LEN)
+ {
+// printf ("%f\n",arr_dist(&recbuf[rbpos-QUIET_LEN],QUIET_LEN));
+ if (arr_dist(&recbuf[rbpos-QUIET_LEN],QUIET_LEN)<=silence) //es wird still...
+ {
+ if (recend!=-1) recend=rbpos-QUIET_LEN;
+
+ if (frame_cnt==-1) //ggf aufs noteoff warten
+ {
+ printf ("aufnahme fertig\n");
+ frame_cnt=WAIT_AFTER;
+
+ for (i=1;i<=QUIET_LEN;i++)
+ if (arr_dist(recbuf,i) > silence)
+ recstart=i-1;
+
+ if (recstart==-1)
+ for (i=QUIET_LEN;i<recend;i++)
+ if (arr_dist(&recbuf[i-QUIET_LEN],QUIET_LEN) > silence)
+ recstart=i-1;
+
+ if (recstart!=-1)
+ {
+ printf("gotcha.\n"); //TODO: speichern
+ }
+ else
+ {
+ printf ("komisch. nur stille aufgenommen...\n"); //TODO handlen!
+ }
+
+ state=4; //fertig mit aufnehmen
+ }
+ }
+ else //nicht (mehr?) still?
+ {
+ if (recend!=-1)
+ printf("komisch... erst still, dann laut?\n");
+ recend=-1;
+ }
+ }
+ break;
+
+ case 4: //fertig mit aufnehmen, es ist bereits wieder still; noch einige zeit warten
+ frame_cnt-=nframes;
+ if (frame_cnt<=0)
+ {
+ frame_cnt=-1;
+ printf ("fertig mit warten\n");
+ state=2;
+ }
+
+ break;
+ }
+
+ if (nframes <= 0) {
+ fprintf(stderr,"Process callback called with nframes = 0; bug in JACK?\n");
+ return 0;
+ }
+
+
+ return 0;
+}
+
+void init_jack(void) //WICHTIG !!!
+{
+ jack_client = jack_client_open("ripmidi", JackNullOption, NULL);
+ if (jack_client == NULL)
+ {
+ fprintf(stderr,"Registering client failed.\n");
+ exit(1);
+ }
+
+ ringbuffer = jack_ringbuffer_create(RINGBUFFER_SIZE);
+ if (ringbuffer == NULL)
+ {
+ fprintf(stderr,"Creating ringbuffer failed.\n");
+ exit(1);
+ }
+ jack_ringbuffer_mlock(ringbuffer);
+
+ if (jack_set_process_callback(jack_client, process_callback, 0))
+ {
+ fprintf(stderr,"Registering callback failed.\n");
+ exit(1);
+ }
+
+ recport=jack_port_register(jack_client, REC_PORT_NAME, JACK_DEFAULT_AUDIO_TYPE,
+ JackPortIsInput, 0);
+ midiport = jack_port_register(jack_client, MIDI_PORT_NAME, JACK_DEFAULT_MIDI_TYPE,
+ JackPortIsOutput, 0);
+
+ if ((midiport == NULL) || (recport == NULL)) {
+ fprintf(stderr,"Registering ports failed.\n");
+ exit(1);
+ }
+
+ if (jack_activate(jack_client))
+ {
+ fprintf(stderr,"Activating client failed.\n");
+ exit(1);
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ //init header
+ strcpy(wavheader+ 0, "RIFF");
+ //u32cpy(wavheader+ 4, filelen-8);
+ strcpy(wavheader+ 8, "WAVE");
+
+ strcpy(wavheader+12, "fmt ");
+ u32cpy(wavheader+16, 16);
+ u16cpy(wavheader+20, 1);
+ u16cpy(wavheader+22, 1);
+ u32cpy(wavheader+24, samp_rate);
+ u32cpy(wavheader+28, samp_rate*bytes);
+ u16cpy(wavheader+32, bytes);
+ u16cpy(wavheader+34, bytes*8);
+
+ strcpy(wavheader+36, "data");
+ //u32cpy(wavheader+40, datalen);
+
+
+
+
+ rbpos=0;
+ init_jack();
+
+ char foo[10]; gets(foo);
+
+ flo_start=1;
+
+ gets(foo);
+
+ return 0;
+}
+