From fcf34b20d40d511cbc36964d53fa00656ad8807a Mon Sep 17 00:00:00 2001 From: Florian Jung Date: Sun, 19 May 2013 19:20:08 +0200 Subject: initial commit --- config.txt | 2 + groups.txt | 17 +++ midirip.c | 340 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ parse0.c | 276 ++++++++++++++++++++++++++++++++++++++++++++++++ patches.txt | 128 +++++++++++++++++++++++ trim.c | 61 +++++++++++ wav.c | 102 ++++++++++++++++++ 7 files changed, 926 insertions(+) create mode 100644 config.txt create mode 100644 groups.txt create mode 100644 midirip.c create mode 100644 parse0.c create mode 100644 patches.txt create mode 100644 trim.c create mode 100644 wav.c diff --git a/config.txt b/config.txt new file mode 100644 index 0000000..0b49a0a --- /dev/null +++ b/config.txt @@ -0,0 +1,2 @@ +2,3) a4 100 500, a4 a5 100 500 + diff --git a/groups.txt b/groups.txt new file mode 100644 index 0000000..5b25603 --- /dev/null +++ b/groups.txt @@ -0,0 +1,17 @@ +0-7 00Piano +8-15 01Chromatic +16-23 02Organ +24-31 03Guitar +32-39 04Bass +40-47 05Strings +48-55 06Ensemble +56-63 07Brass +64-71 08Reed +72-79 09Pipe +80-87 10SynLead +88-95 11SynPad +96-103 12SynFX +104-111 13Ethnic +112-119 14Perc +120-127 15FX + 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 + * for the MIDI constants and some jack-midi code, which has been + * taken from jack-keyboard: + * Copyright (c) 2007, 2008 Edward Tomasz Napierała + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#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;imax) + max=a[i]; + else if (a[i]=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=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 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; +} + diff --git a/parse0.c b/parse0.c new file mode 100644 index 0000000..5a015d8 --- /dev/null +++ b/parse0.c @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2010 Florian Jung + * + * 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 + +// a0 b0 c0 d0 e0 f0 g0 +const int notemap[7]={33,35,24,26,28,29,31}; + +int getnum(char *s, int *i) +{ + int minus=0; + int num=0; + + if (s[*i]=='-') + { + minus=1; + (*i)++; + } + while((s[*i]>='0') && (s[*i]<='9')) + { + num=num*10+s[*i]-'0'; + (*i)++; + } + + if (minus) return -num; else return num; +} + +int parserange(char *s, int l[]) +{ + int i, state=0; + int j=0; + int num, end; + + for (i=0;;i++) + if ((s[i]!=' ') && (s[i]!='\t')) + { + switch(state) + { + case 0: //expects the (first) number + if ((s[i]>='0') && (s[i]<='9')) //a number? + { + num=getnum(s,&i); + i--; + state=1; + } + break; + case 1: //expects a , or a - + if (s[i]=='-') + { + state=2; + } + else if ((s[i]==',') || (s[i]==0)) + { + l[j]=num; + j++; + printf ("num=%i\n",num); + state=0; + } + else + { + printf("ERROR: expected ',' or '-', found '%c'\n",s[i]); + return -1; + } + break; + + case 2: //expects the second number that ends a range + if ((s[i]>='0') && (s[i]<='9')) //a number? + { + end=getnum(s,&i); + printf("numrange=%i-%i\n",num,end); + for (;num<=end;num++) + { + l[j]=num; + j++; + } + + i--; + state=3; + } + else + { + printf("ERROR: expected number, found '%c'\n",s[i]); + return -1; + } + break; + + case 3: //expects ',' + if ((s[i]==',') || (s[i]==0)) + state=0; + else + { + printf("ERROR: expected ',', found '%c'\n",s[i]); + return -1; + } + } + if (s[i]==0) break; + } + + return j; + +} + +int main(int argc, char** argv) +{ + int i,l; + FILE* f; + char line[1000]; + char *range, *param; + int patchlist[128]; + + int oct,loud,len; + int notenum, note[10]; + int j; + int state; + int dontignore; + int rangelen; + + f=fopen ("config.txt","r"); + l=0; + while(!feof(f)) + { + fgets(line,sizeof(line),f); + printf ("read %s",line); + l++; + + dontignore=0; + for (i=0;line[i];i++) + if ((line[i]!=' ') && (line[i]!='\t') && (line[i]!='\n')) + { + dontignore=1; + } + + if (dontignore) + { + for (i=0;(line[i]!=0) && (line[i]!=')');i++); //find ')' + if (line[i]==0) + { + printf("ERROR: expected ), found EOL in line %i\n",l); + } + else + { + line[i]=0; + range=line; + param=line+i+1; + + rangelen=parserange(range,patchlist); + if (rangelen==-1) + { + printf ("ERROR: invalid range specified in line %i\n",l); + } + + while(1) + { + for (i=0;(param[i]!=0) && (param[i]!=',') && (param[i]!='\n');i++); //find ',' + + printf("'%s', '%s'\n",range,param); + + state=0; + len=1337;//TODO sane default + notenum=0; + note[notenum]=0; oct=99; + + for (j=0;j) or \0 + if ((param[j]>='a') && (param[j]<='g')) //found a note + { + printf("found a note\n"); + note[notenum]=notemap[param[j]-'a']; + if ((param[j+1]=='b') || param[j+1]=='#') //vorzeichen? + { + if (param[j+1]=='b') + note[notenum]--; + else + note[notenum]++; + j++; + } + state=1; + } + else if ((param[j]>='0') && (param[j]<='9')) //found a number + { + printf("found loudness\n"); + loud=getnum(param,&j); + printf("j=%i\n",j); + state=2; + } + else if ((param[j]!=' ') && (param[j]!='\t')) + { + printf("ERROR: expected note or number, found %c in line %i\n",param[j],l); + } + break; + + case 1: //expects octave (-1 or 4) + if ((param[j]=='-') || ((param[j]>='0') && (param[j]<='9'))) + { + printf("found octave\n"); + oct=getnum(param,&j); + note[notenum]+=oct*12; + printf (" note=%i\n",note[notenum]); + + notenum++; + state=0; + } + else + { + printf ("ERROR: expected - or 0-9, found %c in line %i\n",param[j],l); + } + break; + + + case 2: //expects notelen or 0 + if ((param[j]>='0') && (param[j]<='9')) + { + printf("found notelen\n"); + len=getnum(param,&j); + state=4; + } + else if ((param[j]!=' ') && (param[j]!='\t')) + { + printf("ERROR: expected number, found %c in line %i\n",param[j],l); + } + } + } + + //TODO: neuen eintrag erstellen + printf ("==== RESULT: loud=%i, len=%i, notes=",loud,len); + for (j=0;j + * + * 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 + +int main(int argc, char** argv) +{ + char param[]=" a4 c#5 e5 200 "; + + char ntmp[100]; + int supp_spc=1; + int i,j; + j=0; + for (i=0;param[i];i++) + { //if there will begin a new parameter, and there's not space or a note + if ( !((param[i]>='a') && (param[i]<='g') || + (param[i]==' ') || (param[i]=='\t') ) && supp_spc) break; + + if ((param[i]==' ') || (param[i]=='\t')) + { + if (!supp_spc) + ntmp[j++]=' '; + supp_spc=1; + } + else + { + supp_spc=0; + ntmp[j++]=param[i]; + } + } + ntmp[j]=0; + if (ntmp[j-1]==' ') ntmp[j-1]=0; + +printf("'%s'\n",ntmp); + return 0; +} diff --git a/wav.c b/wav.c new file mode 100644 index 0000000..e2ca4fd --- /dev/null +++ b/wav.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2010 Florian Jung + * + * 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 + + + +void u16cpy(char *dest, int src) +{ + dest[0]=src%256; + dest[1]=src/256; +} + +void s16cpy(char *dest, int src) +{ + if (src<0) + src=(~(-src))+1; + + u16cpy(dest,src); +} + +void u32cpy(char *dest, long int src) +{ + dest[0]=src%256; + dest[1]=(src/256)%256; + dest[2]=(src/256/256)%256; + dest[3]=(src/256/256/256)%256; +} + +int main(int argc, char** argv) +{ + FILE *f; + f=fopen("test.wav","w"); + + //char buf[44]; + char buf[244]; + + int datalen,filelen,n_chans,samp_rate,bytes; + + datalen=100; + n_chans=1; + samp_rate=22050; + bytes=2; + + + filelen=12 + 24 + 8+datalen; //RIFFWAVE|fmt |DATA + + strcpy(buf+ 0, "RIFF"); + u32cpy(buf+ 4, filelen-8); + strcpy(buf+ 8, "WAVE"); + + strcpy(buf+12, "fmt "); + u32cpy(buf+16, 16); + u16cpy(buf+20, 1); // format=1 (PCM) + u16cpy(buf+22, n_chans); // mono + u32cpy(buf+24, samp_rate); + u32cpy(buf+28, samp_rate*n_chans*bytes); + u16cpy(buf+32, n_chans*bytes); + u16cpy(buf+34, bytes*8); + + strcpy(buf+36, "data"); + u32cpy(buf+40, datalen); + //data follows + + int i; + for (i=0;i<100;i++) + { + s16cpy(buf+i*2+44, sin((double)i/50.0*3.141592654*2)*30000); + //buf[i*2+44]= (sin((double)i/100.0*3.141592654*2)*30000); + } + + + fwrite(buf,1,244,f); + fclose(f); + + return 0; +} -- cgit v1.2.1