summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README13
-rw-r--r--config.txt2
-rw-r--r--example-drums/config.txt4
-rw-r--r--example-drums/patches.txt53
-rw-r--r--example-instruments/config.txt48
-rw-r--r--example-instruments/groups.txt17
-rw-r--r--example-instruments/patches.txt128
-rw-r--r--groups.txt17
-rw-r--r--midirip.c963
-rw-r--r--parse0.c276
-rw-r--r--patches.txt128
-rw-r--r--trim.c61
-rw-r--r--wav.c102
13 files changed, 1812 insertions, 0 deletions
diff --git a/README b/README
new file mode 100644
index 0000000..c1487b1
--- /dev/null
+++ b/README
@@ -0,0 +1,13 @@
+this program can be used to rip your synthesizer's sound:
+it plays configured notes and records the result.
+
+have a look at the files under example-drums and example-instruments
+for the syntax
+
+for switching between instrument and drum mode, you must edit
+midirip.c and set/unset the #define DRUM_MODE!
+
+Disclaimer: this program has been written in a great hurry,
+ within less than ~5 hours of pure coding!
+ Expect appropriate buggyness.
+
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/example-drums/config.txt b/example-drums/config.txt
new file mode 100644
index 0000000..efbae76
--- /dev/null
+++ b/example-drums/config.txt
@@ -0,0 +1,4 @@
+24-84) 0
+31,33,35,36,38,42,44,46,53,56) 8, 16, 24, 32
+71,72,29) 0 120 3000
+ \ No newline at end of file
diff --git a/example-drums/patches.txt b/example-drums/patches.txt
new file mode 100644
index 0000000..85684cb
--- /dev/null
+++ b/example-drums/patches.txt
@@ -0,0 +1,53 @@
+29 Wirbel
+30 Click
+31 Snare
+32 Sticks
+33 BassDrum0
+34 Side
+35 AcBassDrum
+36 BassDrum1
+37 SideStick
+38 AcSnare
+39 HandClap
+40 ElSnare
+41 LowFloorTom
+42 ClosedHiHat
+43 HighFloorTom
+44 PedalHiHat
+45 LowTom
+46 OpenHiHat
+47 LowMidTom
+48 HighMidTom
+49 CrashCymbal1
+50 HighTom
+51 RideCymbal1
+52 ChineseCymbal
+53 RideBell
+54 Tambourine
+55 SplashCymbal
+56 Cowbell
+57 CrashCymbal2
+58 Vibraslap
+59 RideCymbal2
+60 HighBongo
+61 LowBongo
+62 MuteHiConga
+63 OpenHiConga
+64 LowConga
+65 HighTimbale
+66 LowTimbale
+67 HighAgogo
+68 LowAgogo
+69 Cabasa
+70 Maracas
+71 ShortWhistle
+72 LongWhistle
+73 ShortGuiro
+74 LongGuiro
+75 Claves
+76 HiWoodBlock
+77 LoWoodBlock
+78 MuteCuica
+79 OpenCuica
+80 MuteTriangle
+81 OpenTriangle
diff --git a/example-instruments/config.txt b/example-instruments/config.txt
new file mode 100644
index 0000000..5638489
--- /dev/null
+++ b/example-instruments/config.txt
@@ -0,0 +1,48 @@
+0,1,3) a1 40 2500, a1 120 2500, a3 40 2500, a3 120 2500, a3 80 2500
+0,1,3) a1 40 75, a1 120 75, a3 40 75, a3 120 75, a3 80 75
+2,4,5,6,7) a1 80 1500, a3 80 1500
+8-13) a4 80
+14) a3 80
+15) a3 80, a4 80
+16-23) a3 80 1500
+19) a1 80 2500, a1 a2 80 2500
+21) a2 80 2500, a2 80 75
+24-31) a2 80 1500
+32-39) a1 80 1500
+40) a3 80
+40-42) a2 80
+43) a1 80
+44-46) a3 80
+45) a1 80, a1 a2 80
+48-51) a1 120 75, a1 e2 120 75, a1 a2 120 75, a2 120 75, a2 e3 120 75, a2 a3 120 75, a3 120 75, a3 a4 120 75, a4 120 75
+48-51) a1 120 2000, a1 e2 120 2000, a1 a2 120 2000, a2 120 2000, a2 e3 120 2000, a2 a3 120 2000, a3 120 2000, a3 a4 120 2000, a4 120 2000
+52-54) a1 120 2000, a2 120 2000, a3 120 2000
+55) a2 120, a3 120
+56,57,60-62) a2 120 2000, a3 120 2000
+57,58,60,61) a1 120 2000
+64,65) a2 80
+68,69) a3 80
+69) a2 80
+70) a1 80
+71) a2 80, a3 80
+72) a4 80 2000
+73,75) a3 80
+76) a3 80, a4 80 2000
+80-87) a3 80 1500
+88-91) a2 80 1500
+90) a1 80 1500
+91) a3 80 1500
+92-94) a3 80
+98) a3 80
+104) a3 80
+105) a2 80, a3 80
+109) e2 80 2000, a3 80 2000
+110,111) a2 80 2000, a3 80 2000
+110) a2 80 150, a3 80 150
+112,114) a3 80
+116) e2 80
+119) a1 80 2000, a2 80 2000
+122-127) e3 80 2000
+
+
+
diff --git a/example-instruments/groups.txt b/example-instruments/groups.txt
new file mode 100644
index 0000000..5b25603
--- /dev/null
+++ b/example-instruments/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/example-instruments/patches.txt b/example-instruments/patches.txt
new file mode 100644
index 0000000..2e0eebd
--- /dev/null
+++ b/example-instruments/patches.txt
@@ -0,0 +1,128 @@
+0 AcPiano
+1 BrPiano
+2 ElPiano
+3 Honkytonk
+4 ElPiano1
+5 ElPiano2
+6 Harps
+7 Clavi
+8 Celesta
+9 Glockenspiel
+10 MusicBox
+11 Vibraphone
+12 Marimba
+13 Xylophone
+14 TubBells
+15 Dulcimer
+16 DrawOrg
+17 PercOrg
+18 RockOrg
+19 ChurchOrg
+20 ReedOrg
+21 Accordion
+22 Harmonica
+23 TangoAcc
+24 NylonGuit
+25 SteelGuit
+26 JazzGuit
+27 CleanGuit
+28 MutedGuit
+29 OvDrGuit
+30 DistGuit
+31 GuitHarm
+32 AcBass
+33 FingerBass
+34 PickBass
+35 Fretless Bass
+36 SlapBass1
+37 SlapBass2
+38 SynBass1
+39 SynBass2
+40 Violin
+41 Viola
+42 Cello
+43 Contrabass
+44 TremStr
+45 PizzStr
+46 Harp
+47 Timpani
+48 Strings1
+49 Strings2
+50 SynStrings1
+51 SynStrings2
+52 Aahs
+53 Oohs
+54 SynVoice
+55 OrchHit
+56 Trumpet
+57 Trombone
+58 Tuba
+59 MutedTrumpet
+60 FrenchHorn
+61 BrassSect
+62 SynBrass1
+63 SynBrass2
+64 SopSax
+65 AltSax
+66 TenSax
+67 BariSax
+68 Oboe
+69 EngHorn
+70 Bassoon
+71 Clarinet
+72 Piccolo
+73 Flute
+74 Recorder
+75 PanFlute
+76 Bottle
+77 Shakuhachi
+78 Whistle
+79 Ocarina
+80 SqLead
+81 SawLead
+82 CallLead
+83 ChiffLead
+84 CharLead
+85 VoiceLead
+86 FifthsLead
+87 BassLead
+88 NewAgePad
+89 WarmPad
+90 Polysynth
+91 ChoirPad
+92 BowedPad
+93 MetalPad
+94 HaloPad
+95 SweepPad
+96 FXRain
+97 FXSndTrck
+98 FXCrystal
+99 FXAtmo
+100 FXBright
+101 FXGoblins
+102 FXEchoes
+103 FXSciFi
+104 Sitar
+105 Banjo
+106 Shamisen
+107 Koto
+108 Kalimba
+109 Bagpipe
+110 Fiddle
+111 Shanai
+112 TinkBell
+113 Agogo
+114 SteelDrums
+115 Woodblock
+116 TaikoDrum
+117 MelTom
+118 SynDrum
+119 RevCymbal
+120 GuitFret
+121 Breath
+122 Seashore
+123 Bird
+124 Telephone
+125 Helicopter
+126 Applause
+127 Gunshot
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..8fff403
--- /dev/null
+++ b/midirip.c
@@ -0,0 +1,963 @@
+/*
+ * 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.
+ */
+
+
+/* TODO
+ * bytes aus datei lesen
+ * --overwrite-option?
+ * zwischen normalem und drum-modus wechseln!
+ */
+
+//LAST STABLE: 08
+
+// #define DRUM_MODE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.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.005 //schon ziemlich knapp. lieber weniger
+#define QUIET_LEN 441
+#define WAIT_AFTER 22050
+#define MAX_NOTES 10
+#define DEFAULT_LEN 1000 //TODO richtigen wert finden!
+#define LATENCY 1000
+
+jack_default_audio_sample_t buf1[RECBUF_LEN], buf2[RECBUF_LEN];
+jack_default_audio_sample_t *recbuf, *workbuf;
+jack_default_audio_sample_t silence;
+int note=60, laut=100, notelen=22050;
+int main_working, all_done;
+int workstart, workend, main_rbpos;
+
+int samp_rate;
+int bytes=2;
+char wavheader[44];
+int flo_start;
+
+struct entry_t
+{
+ char chan;
+ char patch;
+
+ char loud;
+ char note[MAX_NOTES];
+ int notelen;
+
+ char *file, *dir;
+
+ struct entry_t *next;
+};
+typedef struct entry_t entry_t;
+
+entry_t *recentry, *workentry, *firstentry;
+
+const int notemap[7]={33,35,24,26,28,29,31};
+
+char *dirs[128];
+char *patchname[128];
+
+
+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;
+
+}
+
+
+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;
+}
+
+
+
+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, frame_cnt2;
+ static int rbpos=0, recend;
+ 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 und initialisiere
+ if (flo_start)
+ {
+ state=1;
+ rbpos=0;
+ recentry=firstentry;
+ 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, wie in recentry beschrieben
+// printf("NOTE ON\n");
+ //TODO ggf noch bank select?
+
+ data[0]=MIDI_PROGRAM_CHANGE;
+ data[1]=recentry->patch;
+ if (jack_midi_event_write(midipb, 0, data, 2))
+ fprintf(stderr,"Note loss when writing\n");
+
+ data[0]=MIDI_NOTE_ON + (recentry->chan & 0x0F);
+ data[2]=recentry->loud;
+
+ for (i=0;recentry->note[i]!=-1;i++)
+ {
+ data[1]=recentry->note[i];
+ if (jack_midi_event_write(midipb, 0, data, 3))
+ fprintf(stderr,"Note loss when writing\n");
+ }
+ frame_cnt=recentry->notelen;
+ frame_cnt2=LATENCY*samp_rate/1000;
+
+ rbpos=0;
+ recend=-1;
+
+ state=3;
+ break;
+
+ case 3: // nehme auf und sende ggf note off
+ if (frame_cnt2 != -1)
+ {
+ frame_cnt2-=nframes;
+ if (frame_cnt2<=0) frame_cnt2=-1;
+ }
+ 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 + (recentry->chan & 0x0F);
+ data[2]=recentry->loud;
+ for (i=0;recentry->note[i]!=-1;i++)
+ {
+ data[1]=recentry->note[i];
+ 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: statt segfault tainted setzen und im letzten bufferteil loopen
+ recbuf[rbpos]=recpb[i];
+ rbpos++;
+ }
+ if (rbpos>QUIET_LEN) //TODO FINDMICH: QUIET_LEN mit nframes ersetzen???
+ {
+ if (arr_dist(&recbuf[rbpos-QUIET_LEN],QUIET_LEN)<=silence) //es wird still...
+ {
+ if (recend==-1) recend=rbpos-QUIET_LEN;
+
+ if ((frame_cnt==-1) && (frame_cnt2==-1)) //ggf aufs noteoff warten
+ {
+// printf ("aufnahme fertig\n");
+
+ state=4;
+ }
+ }
+ else //nicht (mehr?) still
+ {
+ recend=-1;
+ }
+ }
+ break;
+
+ case 4: //auf verarbeitungs-thread warten
+ if (main_working==0) //main ist fertig?
+ {
+ if (recbuf==buf1) //buffer wechseln
+ {
+ recbuf=buf2;
+ workbuf=buf1;
+ }
+ else
+ {
+ recbuf=buf1;
+ workbuf=buf2;
+ }
+ workend=recend;
+ main_rbpos=rbpos;
+ workentry=recentry;
+
+ main_working=1; //befehl zum starten geben
+
+
+ recentry=recentry->next;
+ if (recentry==NULL) //fertig?
+ {
+ printf("all done, waiting for main to finish and clean up\n");
+ all_done=1;
+ state=99;
+ }
+ else
+ {
+ frame_cnt=WAIT_AFTER;
+ state=5;
+ }
+ }
+ break;
+
+ case 5: //noch einige zeit warten
+ frame_cnt-=nframes;
+ if (frame_cnt<=0)
+ {
+ frame_cnt=-1;
+// printf ("fertig mit warten\n");
+ state=2;
+ }
+ break;
+
+ case 99: //nichts tun, main wird alles fertig machen, aufräumen und beenden.
+ 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);
+ }
+
+ samp_rate=jack_get_sample_rate(jack_client);
+
+ if (jack_activate(jack_client))
+ {
+ fprintf(stderr,"Activating client failed.\n");
+ exit(1);
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ int i,j,k,l,m;
+ FILE* f;
+ char line[1000];
+ char *range, *param;
+ int patchlist[128];
+
+ int oct,loud,len;
+ int notenum, note[10];
+ int state;
+ int dontignore;
+ int rangelen;
+
+ int drumprogram;
+
+ entry_t *curr_entry;
+
+
+ //TODO nettes CLI
+
+
+ bytes=2;
+
+ //init
+ recbuf=buf1; workbuf=buf2;
+ main_working=0; all_done=0;
+ flo_start=0;
+
+ init_jack();
+
+
+//TODO patchname und dirs initialisieren FINDMICH
+ char dummy[]="unknown";
+ for (i=0;i<128;i++)
+ dirs[i]=patchname[i]=dummy;
+
+ f=fopen("patches.txt","r");
+ while(!feof(f))
+ {
+ fgets(line,sizeof(line),f);
+ for (i=strlen(line)-1;i>=0;i--) //remove trailing spaces
+ {
+ if ((line[i]=='\n') || (line[i]==' ') || (line[i]=='\t'))
+ line[i]=0;
+ else
+ break;
+ }
+
+
+ if (!isdigit(line[0]))
+ {
+ fprintf(stderr,"invalid number in patchlist, ignoring it...\n");
+ }
+ else
+ {
+ i=0;
+ m=getnum(line,&i);
+ while ( ((line[i]==' ') || (line[i]=='\t')) && line[i] ) i++; //line[i] is letter or NUL
+ asprintf(&patchname[m], "%s", line+i);
+ }
+ }
+ fclose(f);
+
+#ifndef DRUM_MODE
+ f=fopen("groups.txt","r");
+ while(!feof(f))
+ {
+ fgets(line,sizeof(line),f);
+ for (i=strlen(line)-1;i>=0;i--) //remove trailing spaces
+ {
+ if ((line[i]=='\n') || (line[i]==' ') || (line[i]=='\t'))
+ line[i]=0;
+ else
+ break;
+ }
+
+ char *grptmp;
+ for (i=0;line[i];i++)
+ if ((line[i]=='\n') || (line[i]==' ') || (line[i]=='\t'))
+ {
+ line[i]=0;
+ grptmp=&line[i+1];
+ break;
+ }
+
+ int grprange[128];
+ m=parserange(line,grprange);
+ if (m<0)
+ {
+ printf("error parsing range, ignoring the line...\n");
+ }
+ else
+ {
+ char *grptmp2;
+ asprintf(&grptmp2, "%s", grptmp);
+ for (i=0;i<m;i++)
+ dirs[grprange[i]]=grptmp2;
+ }
+ }
+
+ fclose(f);
+#endif
+
+ f=fopen ("config.txt","r");
+ l=0;
+ curr_entry=firstentry=NULL;
+ while(!feof(f))
+ {
+ fgets(line,sizeof(line),f);
+ 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);
+ goto invalid;
+ }
+
+ 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);
+ goto invalid;
+ }
+
+ while(1)
+ {
+ for (i=0;(param[i]!=0) && (param[i]!=',') && (param[i]!='\n');i++); //find ','
+
+#ifdef DRUM_MODE
+ for (j=0;(param[j]!=0) && ((param[j]==' ') || (param[j]=='\t'));j++); //find nonspace
+ drumprogram=getnum(param,&j);
+ loud=120; //TODO anderer default?
+ len=75;
+
+ for (;(param[j]!=0) && ((param[j]==' ') || (param[j]=='\t'));j++); //find next nonspace
+ if (isdigit(param[j]))
+ {
+ printf("loud specified\n");
+ loud=getnum(param,&j);
+ }
+ for (;(param[j]!=0) && ((param[j]==' ') || (param[j]=='\t'));j++); //find next nonspace
+ if (isdigit(param[j]))
+ {
+ len=getnum(param,&j);
+ printf("len\n");
+ }
+
+
+#else //ifndef DRUM_MODE
+ state=0;
+ len=DEFAULT_LEN;
+ notenum=0;
+ note[notenum]=0; oct=99;
+
+ for (j=0;j<i;j++)
+ {
+ switch (state)
+ {
+ case 0: //expects a note (a4) or loudness (<num>) 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);
+ state=2;
+ }
+ else if ((param[j]!=' ') && (param[j]!='\t'))
+ {
+ printf("ERROR: expected note or number, found %c in line %i\n",param[j],l);
+ goto invalid;
+ }
+ break;
+
+ case 1: //expects octave (-2 or 4)
+ if ((param[j]=='-') || ((param[j]>='0') && (param[j]<='9')))
+ {
+// printf("found octave\n");
+ oct=getnum(param,&j);
+
+ note[notenum]+=oct*12;
+ if ((note[notenum]<0) || (note[notenum]>127)) //illegal note
+ {
+ printf("ERROR: invalid note in line %i\n",l);
+ goto invalid;
+ }
+ else
+ notenum++;
+ state=0;
+ }
+ else
+ {
+ printf ("ERROR: expected - or 0-9, found %c in line %i\n",param[j],l);
+ goto invalid;
+ }
+ break;
+
+
+ case 2: //expects notelen or 0
+ if ((param[j]>='0') && (param[j]<='9'))
+ {
+// printf("found notelen\n");
+ len=getnum(param,&j);
+ if (len<0)
+ {
+ printf("WARNING: len was negative in line %i; using absolute value\n",l);
+ len=-len;
+ }
+ state=4;
+ }
+ else if ((param[j]!=' ') && (param[j]!='\t'))
+ {
+ printf("ERROR: expected number, found %c in line %i\n",param[j],l);
+ goto invalid;
+ }
+ }
+ }
+
+#endif
+ //in die liste eintragen
+
+ for (k=0;k<rangelen;k++)
+ {
+ entry_t *tmpptr=malloc(sizeof(entry_t));
+ if (tmpptr==NULL)
+ {
+ printf("GAAAH... malloc error\n");
+ exit(1);
+ }
+ if (firstentry==NULL)
+ firstentry=tmpptr;
+ else
+ curr_entry->next=tmpptr;
+
+ tmpptr->loud=loud;
+ tmpptr->notelen=len*samp_rate /1000; //von msec in samples umrechnen
+#ifndef DRUM_MODE
+ tmpptr->chan=0;
+ tmpptr->patch=patchlist[k];
+ tmpptr->dir=dirs[patchlist[k]];
+
+ char ntmp[100]; //trim multiple, leading and trailing spaces from param
+ int supp_spc=1;
+ j=0;
+ for (m=0;(param[m]!=0) && (param[m]!=',') && (param[m]!='\n');m++)
+ { //if there will begin a new parameter, and there's not space or a note
+ if ( !(((param[m]>='a') && (param[m]<='g')) ||
+ (param[m]==' ') || (param[m]=='\t') ) && supp_spc) break;
+
+ if ((param[m]==' ') || (param[m]=='\t'))
+ {
+ if (!supp_spc)
+ ntmp[j++]=' ';
+ supp_spc=1;
+ }
+ else
+ {
+ supp_spc=0;
+ ntmp[j++]=param[m];
+ }
+ }
+ ntmp[j]=0;
+ if (ntmp[j-1]==' ') ntmp[j-1]=0;
+
+ asprintf(&tmpptr->file, "%s/%03i%s %s %03i %ims.wav",tmpptr->dir, tmpptr->patch,
+ patchname[tmpptr->patch], ntmp, tmpptr->loud, len);
+
+
+ for (j=0;j<notenum;j++)
+ tmpptr->note[j]=note[j];
+ tmpptr->note[notenum]=-1;
+#else // ifdef DRUM_MODE
+ tmpptr->chan=9;
+ tmpptr->note[0]=patchlist[k]; tmpptr->note[1]=-1;
+ tmpptr->patch=drumprogram;
+
+ tmpptr->dir="drums";
+ asprintf(&tmpptr->file, "%s/%03i%s %i %i %ims.wav",tmpptr->dir, tmpptr->note[0],
+ patchname[tmpptr->note[0]], tmpptr->patch, tmpptr->loud, len);
+
+
+ printf("chan=%i, note=%i, patch=%i, loud=%i, len=%i,\n\tdir='%s', file='%s'\n",
+ tmpptr->chan, tmpptr->note[0], tmpptr->patch, tmpptr->loud, tmpptr->notelen,
+ tmpptr->dir, tmpptr->file);
+#endif
+
+ tmpptr->next=NULL;
+
+ curr_entry=tmpptr;
+ }
+
+ if (param[i]==',') //is there a next param?
+ param=&param[i+1];
+ else
+ break;
+ }
+ }
+ }
+
+
+
+
+
+
+ //init header
+ strcpy(wavheader+ 0, "RIFF");
+ 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");
+
+
+
+
+ printf("connect ripmidi's midi port to some MIDI OUT and the audio\n"
+ "port to the corresponding audio input port; then press enter\n");
+ char foo[10]; gets(foo);
+
+ flo_start=1;
+
+ main_working=0;
+ printf("main: entering loop\n");
+ while(1)
+ {
+ while ((main_working==0) && (all_done==0)) usleep(100000); // 0.1 sec
+
+ printf("main: starting work cycle\n");
+
+ workstart=-1;
+ for (i=1;i<=QUIET_LEN;i++) //Find begin of non-silence
+ if (arr_dist(workbuf,i) > silence)
+ {
+ workstart=i-1;
+ break;
+ }
+
+ if (workstart==-1) // [ continued ]
+ for (i=QUIET_LEN;i<workend;i++)
+ if (arr_dist(&workbuf[i-QUIET_LEN],QUIET_LEN) > silence)
+ {
+ workstart=i-1;
+ break;
+ }
+
+ if (workstart!=-1)
+ {
+// printf("main: gotcha. %i - %i [%i - %i]\n",workstart,workend,0,main_rbpos);
+ jack_default_audio_sample_t max=0.0; //find max amplitude
+ for (i=workstart; i<=workend; i++)
+ {
+ if (workbuf[i]>0)
+ {
+ if (workbuf[i]>max) max=workbuf[i];
+ }
+ else
+ {
+ if (-workbuf[i]>max) max=-workbuf[i];
+ }
+ }
+
+ int datalen,filelen;
+ datalen=(workend-workstart+1)*bytes;
+ filelen=44+datalen;
+ u32cpy(wavheader+ 4, filelen-8);
+ u32cpy(wavheader+40, datalen);
+
+
+ int ret=mkdir(workentry->dir,S_IRWXU|S_IRWXG|S_IRWXO);
+ if ((ret==-1) && (errno!=EEXIST)) //a real error occurred
+ {
+ fprintf(stderr,"ERROR: could not create %s (%s)\n",workentry->dir,strerror(errno));
+ }
+
+ f=fopen(workentry->file,"w");
+ if (f==NULL)
+ {
+ fprintf(stderr,"ERROR: could not open %s (%s)\n",workentry->file,strerror(errno));
+ }
+ else
+ {
+ printf("writing to file %s\n",workentry->file);
+ unsigned char tmp[2];
+
+ fwrite(wavheader, 1, 44, f);
+ if (bytes==1)
+ for (i=workstart;i<=workend;i++)
+ {
+ *tmp=(workbuf[i]/max*127.0)+127;
+ fwrite(tmp,1,1,f);
+ }
+ else
+ for (i=workstart;i<=workend;i++)
+ {
+ s16cpy(tmp, (long)(workbuf[i]/max*32767.0));
+ fwrite(&tmp,1,2,f);
+ }
+
+ fclose(f);
+ }
+
+
+ }
+ else
+ {
+ printf ("ERROR: main: komisch. nur stille aufgenommen bei datei %s...\n",workentry->file); //TODO handlen!
+ }
+
+
+ printf("main: work done\n");
+ main_working=0;
+
+ if (all_done) break;
+ }
+
+ printf("\n=== ALL DONE ===\n[exiting...]\n\n");
+ return 0;
+
+
+
+ invalid:
+ printf("config file invalid, exiting...\n");
+ exit(1);
+}
+
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 <flo@windfisch.org>
+ *
+ * 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>
+
+// 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<i;j++)
+ {
+ printf ("%i: ",j);
+ switch (state)
+ {
+ case 0: //expects a note (a4) or loudness (<num>) 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<notenum;j++)
+ printf("%i ",note[j]);
+
+ printf("\n");
+
+ if (param[i]==',') //is there a next param?
+ {
+ param=&param[i+1];
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ printf("%i\n",i);
+ }
+
+ return 0;
+}
diff --git a/patches.txt b/patches.txt
new file mode 100644
index 0000000..2e0eebd
--- /dev/null
+++ b/patches.txt
@@ -0,0 +1,128 @@
+0 AcPiano
+1 BrPiano
+2 ElPiano
+3 Honkytonk
+4 ElPiano1
+5 ElPiano2
+6 Harps
+7 Clavi
+8 Celesta
+9 Glockenspiel
+10 MusicBox
+11 Vibraphone
+12 Marimba
+13 Xylophone
+14 TubBells
+15 Dulcimer
+16 DrawOrg
+17 PercOrg
+18 RockOrg
+19 ChurchOrg
+20 ReedOrg
+21 Accordion
+22 Harmonica
+23 TangoAcc
+24 NylonGuit
+25 SteelGuit
+26 JazzGuit
+27 CleanGuit
+28 MutedGuit
+29 OvDrGuit
+30 DistGuit
+31 GuitHarm
+32 AcBass
+33 FingerBass
+34 PickBass
+35 Fretless Bass
+36 SlapBass1
+37 SlapBass2
+38 SynBass1
+39 SynBass2
+40 Violin
+41 Viola
+42 Cello
+43 Contrabass
+44 TremStr
+45 PizzStr
+46 Harp
+47 Timpani
+48 Strings1
+49 Strings2
+50 SynStrings1
+51 SynStrings2
+52 Aahs
+53 Oohs
+54 SynVoice
+55 OrchHit
+56 Trumpet
+57 Trombone
+58 Tuba
+59 MutedTrumpet
+60 FrenchHorn
+61 BrassSect
+62 SynBrass1
+63 SynBrass2
+64 SopSax
+65 AltSax
+66 TenSax
+67 BariSax
+68 Oboe
+69 EngHorn
+70 Bassoon
+71 Clarinet
+72 Piccolo
+73 Flute
+74 Recorder
+75 PanFlute
+76 Bottle
+77 Shakuhachi
+78 Whistle
+79 Ocarina
+80 SqLead
+81 SawLead
+82 CallLead
+83 ChiffLead
+84 CharLead
+85 VoiceLead
+86 FifthsLead
+87 BassLead
+88 NewAgePad
+89 WarmPad
+90 Polysynth
+91 ChoirPad
+92 BowedPad
+93 MetalPad
+94 HaloPad
+95 SweepPad
+96 FXRain
+97 FXSndTrck
+98 FXCrystal
+99 FXAtmo
+100 FXBright
+101 FXGoblins
+102 FXEchoes
+103 FXSciFi
+104 Sitar
+105 Banjo
+106 Shamisen
+107 Koto
+108 Kalimba
+109 Bagpipe
+110 Fiddle
+111 Shanai
+112 TinkBell
+113 Agogo
+114 SteelDrums
+115 Woodblock
+116 TaikoDrum
+117 MelTom
+118 SynDrum
+119 RevCymbal
+120 GuitFret
+121 Breath
+122 Seashore
+123 Bird
+124 Telephone
+125 Helicopter
+126 Applause
+127 Gunshot
diff --git a/trim.c b/trim.c
new file mode 100644
index 0000000..baccd57
--- /dev/null
+++ b/trim.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2010 Florian Jung <flo@windfisch.org>
+ *
+ * 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>
+
+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 <flo@windfisch.org>
+ *
+ * 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>
+
+
+
+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; //RIFF<len>WAVE|fmt <len><fmt>|DATA<len><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;
+}