37 |
38 | #define MIN(x,y) ((x)<(y)?(x):(y))
39 | #define MAX(x,y) ((x)>(y)?(x):(y))
40 | #define MAXNOB 10000
41 |
42 | char *inbuf,*inend,*ip;
43 | int tr,infinity;
44 | int maj[14]={0,2,4,5,7,9,11, 12,14,16,17,19,21,23};
45 | typedef struct {int l,st,von,bt,pt,et,sta,bn,cr,tt,ln,ip,op;unsigned char *out;} trackinfo;
46 | trackinfo *tri;
47 | /*
48 | trackinfo:
49 | st = midi state (state of previous midi event laid down)
50 | bt = time of last event laid down
51 | pt = start time of last note or rest
52 | et = end time of last note or rest
53 | sta = track state
54 | state 0 ==> Need to read time of new line
55 | state 1 ==> Time of next line specified by tt
56 | state 2 ==> Time of next line specified by bn,cr; tt is valid if there is no time sig. change before it
57 | state 3 ==> Track at an end - no more lines on this track
58 | bn,cr,tt time of next event defined by (bn,cr) or tt according to state
59 | ip = integer input pointer (inbuf+.ip is actual pointer)
60 | ln = input line number
61 | out = pointer to start of output buffer (can change when gets resized)
62 | op = integer output pointer (.out+.op is actual pointer)
63 | l = allocated size of output buffer
64 | von = volume of last note-on event
65 | */
66 |
67 | void err(char *l){
68 | if(tr==-1)fprintf(stderr,"Error: %s\n",l); else fprintf(stderr,"Error: %s at line %d:\n%s\n",l,tri[tr].ln,ip);
69 | exit(1);
70 | }
71 | #define assrt(x,y) if(!(x))err(y);
72 |
73 | char *getns(char *l){while(*l==' ')l++; return l;}
74 |
75 | int strtoi(char *l,char **e){
76 | int b,n;
77 | char *l1,*l2;
78 | l1=l;while(*l1!=0&&*l1!='&'&&!isdigit(*l1)&&strncmp(l1,"infinity",8))l1++;
79 | if(strncmp(l1,"infinity",8)==0)return infinity;
80 | if(*l1=='&'){l1++;b=16;} else if(*l1=='0'&&l1[1]=='x'){l1+=2;b=16;} else b=10;
81 | n=strtol(l1,&l2,b);
82 | if(e){if(l2==l1)*e=l; else *e=l2;}
83 | return n;
84 | }
85 |
86 | /*
87 | int getfrn(char *l,int d){
88 | int a,b,c;
89 | char *l1;
90 | a=strtoi(l,&l1);
91 | if(l1[0]=='+')b=strtoi(l1+1,&l1); else {b=a;a=0;}
92 | if(a==infinity||b==infinity)return infinity;
93 | if(l1[0]=='/')c=strtoi(l1+1,0); else c=1;
94 | b+=a*c;
95 | assrt(d%c==0,"fraction not allowed");
96 | return b*(d/c);
97 | }
98 | */
99 | int getfrn(char *l,int d){
100 | int a,b,t;
101 | char *l1;
102 | t=0;
103 | do{
104 | a=strtoi(l,&l1);if(l1==l)break;
105 | if(a==infinity)return infinity;
106 | if(l1[0]=='/')b=strtoi(l1+1,&l1); else b=1;
107 | a*=d;assrt(a%b==0,"fraction not allowed");t+=a/b;
108 | l=l1;
109 | }while(l[0]=='+');
110 | return t;
111 | }
112 |
113 | int strton(char *l,char **e){
114 | int n;
115 | char *l1,*l2;
116 | while(*l==' ')l++;
117 | l1="CDEFGABR";l2=strchr(l1,toupper(*l));assrt(l2,"unrecognised note");
118 | if(l2-l1==7){*e=l+1;return -1;}
119 | n=60+maj[l2-l1];l++;
120 | while(*l=='#'){n++;l++;}
121 | while(*l=='b'){n--;l++;}
122 | while(*l=='\''){n+=12;l++;}
123 | while(*l=='-'){n-=12;l++;}
124 | assrt(n>=0&&n<128,"note out of range");
125 | *e=l;return n;
126 | }
127 |
128 | void acc(int p){
129 | int nl;
130 | unsigned char *new;
131 | if(p<=tri[tr].l)return;
132 | if(tri[tr].l==0)nl=10240; else nl=tri[tr].l*2;
133 | if(nl0)tri[tr].out[tri[tr].op++]=(t>>(--n)*8)&255;
141 | }
142 | void put1(int t){putn(1,t);}
143 | void put2(int t){putn(2,t);}
144 | void put3(int t){putn(3,t);}
145 | void put4(int t){putn(4,t);}
146 | void putv(int t){
147 | int n,u;
148 | assrt(t>=0&&t<0x10000000,"variable number out of range (event out of sequence?)");
149 | for(n=1,u=t;u>=128;n++)u>>=7;
150 | acc(tri[tr].op+n);
151 | while(n>0)tri[tr].out[tri[tr].op++]=((t>>(--n)*7)&127)|128;
152 | tri[tr].out[tri[tr].op-1]&=~128;
153 | }
154 | void putstn(char *l,int s){acc(tri[tr].op+s);memcpy(tri[tr].out+tri[tr].op,l,s);tri[tr].op+=s;}
155 | void putst(char *l){putstn(l,strlen(l));}
156 |
157 | char *getl(int tr){
158 | char *l;
159 | l=inbuf+tri[tr].ip;if(tri[tr].ln>0)l+=strlen(l)+1;
160 | tri[tr].ln++;
161 | while(l midifile\n\n");
175 | fprintf(stderr," Time of an event can be determined by one of\n");
176 | fprintf(stderr," (i) BA+CR: Bar number+Crotchet within bar\n");
177 | fprintf(stderr," (ii) CR: Crotchet number from the very start\n");
178 | fprintf(stderr," (iii) DT: Delta time from previous event - native midi format\n");
179 | fprintf(stderr," (iv) FOL[+/-crotchets]: Time from end of previous note/rest\n");
180 | fprintf(stderr," (v) SIM[+crotchets]: Time from start of previous note/rest\n");
181 | exit(1);
182 | }
183 | fpi=fopen(av[1],"r");if(!fpi){fprintf(stderr,"Couldn't open %s\n",av[1]);exit(1);}
184 | fseek(fpi,0,SEEK_END);siz=ftell(fpi);rewind(fpi);
185 | fprintf(stderr,"File size %d byte%s\n",siz,siz==1?"":"s");
186 | inbuf=(char*)malloc(siz+1);if(!inbuf){fprintf(stderr,"Couldn't malloc %d bytes (inbuf)\n",siz+1);exit(1);}
187 | n=fread(inbuf,1,siz,fpi);assert(n<=siz);siz=n;inbuf[siz]=0;inend=inbuf+siz;fclose(fpi);
188 | for(i=0;i is for the preamble */
200 | for(i=0;i<=tracks;i++){
201 | tri[i].out=0;tri[i].ip=0;tri[i].op=(i=0)tri[tr].tt=tri[tr].et; else
232 | fprintf(stderr,"Warning - FOL reverts to SIM following a DT-defined or infinite length note/rest\n");
233 | }
234 | if(ip[3]=='+')tri[tr].tt+=getfrn(ip+4,tpc);
235 | if(ip[3]=='-')tri[tr].tt-=getfrn(ip+4,tpc);
236 | tri[tr].sta=1;goto ok0;
237 | }
238 | if(strncmp(ip,"CR ",3)==0){
239 | tri[tr].tt=getfrn(ip+3,tpc);
240 | tri[tr].sta=1;goto ok0;
241 | }
242 | if(strncmp(ip,"BA ",3)==0){
243 | tri[tr].bn=strtoi(ip+3,&l1)-1;
244 | l1=getns(l1);if(strncmp(l1,"CR ",3))err("Expect CR after BA");
245 | tri[tr].cr=getfrn(l1+3,tpc);
246 | tri[tr].sta=2;goto ok0;
247 | }
248 | err("Expected time specification (DT, FOL, SIM, CR, or BA) at start of line");
249 | }
250 | ok0:
251 | if(tri[tr].sta==2)tri[tr].tt=tt+(tri[tr].bn-bn)*tis2+tri[tr].cr-cr;
252 | if(tri[tr].tt0){non-=i;memmove(nob,nob+i,non*sizeof(noteoffbuf));}
277 | tr=tr0;
278 | rest=0;if(!text){l1=strstr(ip,"NT ");if(l1)rest=(toupper(*(getns(l1+3)))=='R');}
279 | if(!rest){putv(tt-tri[tr].bt);tri[tr].bt=tt;}
280 | if(text){
281 | put1(tri[tr].st=0xFF);
282 | l1=strstr(ip,"type");assrt(l1,"missing 'type' in text line");t=strtoi(l1+4,0);put1(t);
283 | l1=strchr(l1+4,'"');assrt(l1,"missing opening quote in text line");l1++;
284 | l2=strrchr(l1,'"');assrt(l2,"missing closing quote in text line");
285 | for(i=s=0;i=0&&ch<16,"channel number out of range");
301 | l1=strstr(ip,"Time signature");if(l1){
302 | tis0=strtoi(l1+14,&l1);tis1=strtoi(l1+1,0);assrt((tis0*4*tpc)%tis1==0,"New time signature not commensurate with division");
303 | tis2=(tis0*4*tpc)/tis1;
304 | put1(tri[tr].st=0xFF);
305 | put1(0x58);putv(4);put1(tis0);
306 | for(i=0,n=tis1;n>1;i++)n>>=1;put1(i);
307 | l2=strstr(ip,"clocks/mtick");assrt(l2,"missing clocks/mtick");put1(strtoi(l2+12,0));
308 | l2=strstr(ip,"crotchets/32ndnote");assrt(l2,"missing crotchets/32ndnote");put1(strtoi(l2+18,0));
309 | continue;
310 | }
311 | l1=strstr(ip,"Channel volume");if(l1){
312 | st=0xB0+ch;if(st!=tri[tr].st)put1(tri[tr].st=st);
313 | t=strtoi(l1+14,0);assrt(t>=0&&t<128,"channel volume out of range");put1(7);put1(t);
314 | continue;
315 | }
316 | l1=strstr(ip,"Instrument");if(l1){
317 | st=0xC0+ch;if(st!=tri[tr].st)put1(tri[tr].st=st);
318 | t=strtoi(l1+10,0)-1;assrt(t>=0&&t<128,"instrument out of range");put1(t);
319 | continue;
320 | }
321 | l1=strstr(ip,"Sysex event");if(l1){
322 | put1(tri[tr].st=strtoi(l1+11,&l1));
323 | n=0;l2=l1;while(1){strtoi(l2,&l3);if(l3==l2)break;l2=l3;n++;}
324 | putv(n);for(l2=l1;n>0;n--)put1(strtoi(l2,&l2));
325 | continue;
326 | }
327 | l1=strstr(ip,"End of track");if(l1){
328 | put1(tri[tr].st=0xFF);
329 | put1(0x2F);put1(0);
330 | continue;
331 | }
332 | l1=strstr(ip,"Tempo");if(l1){
333 | put1(tri[tr].st=0xFF);
334 | n=(int)(60*1000000./atof(l1+5)+.5);assrt(n>=0&&n<=0xFFFFFF,"tempo out of range");
335 | put1(0x51);putv(3);put3(n);
336 | continue;
337 | }
338 | l1=strstr(ip,"Key ");if(l1){
339 | put1(tri[tr].st=0xFF);
340 | l1=getns(l1+4);l2="FCGDAEB";l3=strchr(l2,toupper(*l1));assrt(l3,"unrecognised key");sf=l3-l2-1;
341 | do{l1++;sf+=7*((*l1=='#')-(*l1=='b'));}while(*l1=='#'||*l1=='b');
342 | l2=strstr(l1," major");l3=strstr(l1," minor");assrt((l2!=0)^(l3!=0),"missing minor/major in key");
343 | mi=(l3!=0);sf-=3*mi;
344 | put1(0x59);putv(2);put1(sf&255);put1(mi);
345 | continue;
346 | }
347 | l1=strstr(ip,"Meta Event");if(l1){
348 | put1(tri[tr].st=0xFF);
349 | put1(strtoi(l1+10,&l1));
350 | n=0;l2=l1;while(1){strtoi(l2,&l3);if(l3==l2)break;l2=l3;n++;}
351 | putv(n);for(l2=l1;n>0;n--)put1(strtoi(l2,&l2));
352 | continue;
353 | }
354 | l1=strstr(ip,"ST ");if(l1){
355 | st=strtoi(l1+3,&l1);if(st!=tri[tr].st||((st&0xF0)==0xF0))put1(tri[tr].st=st);
356 | while(1){n=strtoi(l1,&l2);if(l2==l1)break;l1=l2;put1(n);}
357 | continue;
358 | }
359 | l1=strstr(ip,"NT ");if(l1){
360 | tri[tr].pt=tt;tri[tr].et=-1;
361 | n=strton(l1+3,&l1);l1=getns(l1);
362 | if(strncmp(l1,"on",2)==0){
363 | assrt(n>=0,"can't have rest and 'on'");
364 | st=0x90+ch;if(st!=tri[tr].st)put1(tri[tr].st=st);
365 | l2=strstr(l1,"von=");if(l2)tri[tr].von=strtoi(l2+4,0);
366 | assrt(tri[tr].von>=1&&tri[tr].von<128,"von out of range");
367 | put1(n);put1(tri[tr].von);
368 | continue;
369 | }
370 | if(strncmp(l1,"off",3)==0){
371 | l2=strstr(l1,"voff=");if(l2)t=strtoi(l2+5,0); else t=0x40;
372 | assrt(t>=0&&t<128,"voff out of range");
373 | if(t!=0x40){/* not most efficient coding, but most likely to mimic convention used by others(?) */
374 | st=0x80+ch;if(st!=tri[tr].st)put1(tri[tr].st=st);
375 | put1(n);put1(t);
376 | }else{
377 | st=0x90+ch;if(st!=tri[tr].st)put1(tri[tr].st=st);
378 | put1(n);put1(0);
379 | }
380 | continue;
381 | }
382 | d=getfrn(l1,tpc);if(d=0);
385 | l2=strstr(l1,"von=");if(l2)tri[tr].von=strtoi(l2+4,0);
386 | assrt(tri[tr].von>=1&&tri[tr].von<128,"von out of range");
387 | st=0x90+ch;if(st!=tri[tr].st)put1(tri[tr].st=st);
388 | put1(n);put1(tri[tr].von);
389 | if(d0){non-=i;memmove(nob,nob+i,non*sizeof(noteoffbuf));}
421 | fprintf(stderr,"Successfully parsed\n");
422 | fwrite(tri[tracks].out,1,tri[tracks].op,stdout);
423 | for(tr=0;tr
33 | #include
34 | #include
35 | #include
36 | #include
37 |
38 | #define MIN(x,y) ((x)<(y)?(x):(y))
39 | #define MAX(x,y) ((x)>(y)?(x):(y))
40 |
41 | #define MAXLL 10000
42 | #define MAXCH 16
43 | #define MAXNT 128
44 | unsigned char *dat;
45 | int p,siz,pr=0,raw,cro,fol,sep,frpad=9;
46 | int bgn[12][2]={{0,0},{0,1},{1,0},{2,-1},{2,0},{3,0},{3,1},{4,0},{4,1},{5,0},{6,-1},{6,0}};
47 | /* ^ best guess note from pitch relative to keynote: (In C maj/A min this would be: C C# D Eb E F F# G G# A Bb B) */
48 | int maj[14]={0,2,4,5,7,9,11, 12,14,16,17,19,21,23};
49 |
50 | void err(char *l){fprintf(stderr,"Error: %s\n",l);exit(1);}
51 | #define assrt(x,y) if(!(x))err(y);
52 |
53 | char *note2(int n,int s,int pad){
54 | static char buf[100][20];
55 | static int p=0;
56 | int i;
57 | p=(p+1)%100;
58 | buf[p][0]="CDEFGAB"[(n+700000)%7];
59 | i=1;
60 | while(s>0){assert(i<19);buf[p][i++]='#';s--;}
61 | while(s<0){assert(i<19);buf[p][i++]='b';s++;}
62 | while(n>=7){assert(i<19);buf[p][i++]='\'';n-=7;}
63 | while(n<0){assert(i<19);buf[p][i++]='-';n+=7;}
64 | if(pad)while(i=0&&n<128&&sf>=-128&&sf<=127);
71 | a0=(4*sf+7000)%7;b0=(sf+7001)/7-1000;/* (a0,b0) = keynote of (sf,mi) in pair form */
72 | n-=60+maj[a0]+b0;/* subtract keynote in single pitch form */
73 | m=(n+120000)%12;a=bgn[m][0];b=bgn[m][1];/* look up most likely pair form */
74 | return note2(a0+a+((n-m)/12)*7,maj[a0]+maj[a]-maj[a0+a]+b0+b,pad);/* evaluate cocycle! */
75 | }
76 | char *key(int sf,int mi,int pad){
77 | static char buf[100][21];
78 | static int p=0;
79 | int i,n;
80 | p=(p+1)%100;
81 | assert(sf>=-128&&sf<=127);
82 | if(mi)sf+=3;
83 | buf[p][0]="FCGDAEB"[(sf+7001)%7];
84 | n=(sf+7001)/7-1000;i=1;
85 | while(n>0){buf[p][i++]='#';n--;}
86 | while(n<0){buf[p][i++]='b';n++;}
87 | while(ix0*m){
119 | t=(int)(r/m);
120 | l1+=sprintf(l1,"%d",t);r-=t*m;
121 | if(dp){
122 | l1+=sprintf(l1,".");
123 | for(i=0;isiz){fprintf(stderr,"Unexpected EOF in %s, p=&%06x n=%d siz=&%06x\n",l,p,n,siz);exit(1);}
135 | }
136 | void skip(int n){need(n,"skip");p+=n;}
137 | void match(char *l){
138 | int i;
139 | need(strlen(l),"match");
140 | for(i=0;l[i];i++)if(l[i]!=dat[p++]){
141 | fprintf(stderr,"Bad match, p=%X i=%d l=%s &%02X!=&%02X\n",p,i,l,l[i],dat[p-1]);exit(1);
142 | }
143 | }
144 | int getn(int n,int a){
145 | int i,t;
146 | need(n,"getn");
147 | for(i=0,t=0;i=0x80)st=get1(); else assert(st>=0x80);
172 | sth=st>>4;
173 | if(sth==8||(sth==9&&dat[p+1]==0))skip(2); else {p=p0;return dt;}
174 | }
175 | return -1;
176 | }
177 |
178 | typedef struct {int tt,ch,nt,voff;} noteoffbuf;
179 | int cmp(const void*x,const void*y){return ((noteoffbuf*)x)->tt-((noteoffbuf*)y)->tt;}
180 |
181 | int main(int ac,char **av){
182 | int i,s,t,u,bf,bn,btt,fol1,rest,ch,dt,infinity,ln,mi,maxno,nat,non,ols,prb,help,
183 | sk,sf,st,sth,tis0,tis1,tis2,tpc,tr,trl,tt,ty,alltrfl,format,tracks,division,tempo,nobp[MAXCH][MAXNT];
184 | char l[MAXLL],*l1;
185 | double ert;
186 | typedef struct {int a,p0,l,e,p,pv,st,dt,tt,et,pt;} trackinfo;
187 | typedef struct fred {int all,bn,tr;char *l;struct fred *nx;} outline;
188 | trackinfo *tri;
189 | noteoffbuf *nob;
190 | outline *outbuf0,*outbuf;
191 | FILE *fpi;
192 |
193 | raw=cro=fol=sep=help=0;
194 | for(i=1;i textfile\n\n");
203 | fprintf(stderr," Default timing is to use absolute time determined by BA+CR\n");
204 | fprintf(stderr," and use durations for notes.\n");
205 | fprintf(stderr,"-c Use absolute crotchets rather than BA+CR to determine time.\n");
206 | fprintf(stderr," Useful if inserting or deleting.\n");
207 | fprintf(stderr,"-f 'Follow' (take time from start or end of previous note) to determine time.\n");
208 | fprintf(stderr,"-r \"raw\" format: time determined by DT, and note-off events\n");
209 | fprintf(stderr," are used instead of note durations.\n\n");
210 | fprintf(stderr," Default is to print all tracks merged in chronological order.\n");
211 | fprintf(stderr,"-s Print all tracks separately.\n");
212 | exit(1);
213 | }
214 | if(fol&&raw){fprintf(stderr,"fol and raw modes cannot be combined\n");exit(1);}
215 | fpi=fopen(av[ac-1],"rb");if(!fpi){fprintf(stderr,"Couldn't open %s\n",av[ac-1]);exit(1);}
216 | fseek(fpi,0,SEEK_END);siz=ftell(fpi);rewind(fpi);
217 | if(pr>=1)printf("# File size %d byte%s\n",siz,siz==1?"":"s");
218 | dat=(unsigned char*)malloc(siz);if(!dat){fprintf(stderr,"Couldn't malloc %d bytes\n",siz);exit(1);}
219 | fread(dat,1,siz,fpi);p=0;fclose(fpi);
220 | maxno=siz/2;
221 | match("MThd");
222 | assert(get4()==6);
223 | format=get2();tracks=get2();division=get2();
224 | printf("format=%d tracks=%d division=%d\n",format,tracks,division);
225 | if(division&(1<<15))tpc=48; else tpc=division;
226 | tri=(trackinfo *)malloc(tracks*sizeof(trackinfo));assert(tri);
227 | nob=(noteoffbuf *)malloc(maxno*sizeof(noteoffbuf));assert(nob);
228 | infinity=0x7fffffff;
229 |
230 | for(tr=0;p=0x80)st=get1(); else assert(st>=0x80);
243 | sth=st>>4;ch=st&15;
244 | if(sth==8||sth==9){
245 | t=get1();u=get1();
246 | if(sth==9){if(u)continue; else u=0x40;}
247 | assert(non=0);
267 | if(tri[tr].a){
268 | tri[tr].et=tri[tr].pt=0;tri[tr].dt=tri[tr].tt=t;tri[tr].p=p;tri[tr].pv=-1;nat++;
269 | }
270 | }
271 | sf=0;mi=0;/* Initial key C major */
272 | tis0=4;tis1=4;tis2=(tis0*4*tpc)/tis1;/* Initial time signature 4/4 */
273 | tempo=500000;/* Default usec/beat (= 120 bpm) */
274 | btt=0;bn=0;bf=0;ert=0;/* at time btt, bar number was bn (from 0), and part of bar complete was bf/tpc crotchets */
275 | prb=-1;
276 | ols=MAXLL*10;outbuf=outbuf0=(outline*)malloc(ols);outbuf->nx=0;
277 | if(!outbuf){fprintf(stderr,"Couldn't malloc %d bytes (outbuf1)\n",ols);exit(1);}
278 | while(nat>0){
279 | tt=infinity;tr=-1;alltrfl=0;
280 | for(i=0;i=0);
285 | p=tri[tr].p;t=look1();if(t>=0x80)st=get1(); else st=tri[tr].st;
286 | sth=st>>4;ch=st&15;
287 | assert(!(raw==0&&(sth==8||(sth==9&&dat[p+1]==0))));
288 | rest=(fol&&tri[tr].etbtt){
292 | ert+=(double)(tt-btt)*(double)tempo/(double)tpc;
293 | /* Elapsed crotchets=(btt-tt)/tpc, ticks/bar=tis2 */
294 | t=tt-btt+bf; bn+=t/tis2; bf=t%tis2; btt=tt;
295 | }
296 | if(!sep&&bn!=prb){l1+=sprintf(l1,"\n");prb=bn;}
297 | if(fol){
298 | u=0;
299 | if(fol1)l1+=sprintf(l1,"FOL"); else {
300 | l1+=sprintf(l1,"SIM");t=tri[tr].tt-tri[tr].pt;if(t){
301 | assert(t>0);l1+=sprintf(l1,"+");u=sprfrac(l1,t,tpc,1,0);l1+=u;u++;
302 | }
303 | }
304 | while(utt&&nob[i].ch==ch&&nob[i].nt==t)break;
331 | nobp[ch][t]=i;
332 | if(i=1&&ty<=7){
359 | l1+=sprintf(l1,"Text type %d: \"",ty);
360 | for(i=0;i=128)sf-=256;mi=get1();
395 | l1+=sprintf(l1,"Key %s %s\n",key(sf,mi,0),mi?"minor":"major");
396 | alltrfl=1;
397 | goto bp1;
398 | }
399 | l1+=sprintf(l1,"Meta Event type &%02X ",ty);
400 | for(i=0;i=0){tri[tr].tt+=tri[tr].dt;tri[tr].p=p;} else {tri[tr].a=0;nat--;}
411 | bp2:
412 | if(sep){
413 | s=l1-l+1;t=sizeof(outline);u=(s+t-1)/t;
414 | assert((u+1)*t<=MAXLL&&ols>=MAXLL);
415 | outbuf->tr=tr;outbuf->all=alltrfl;outbuf->bn=bn;outbuf->l=(char*)(outbuf+1);
416 | if(ols-(u+1)*tnx=(outline*)malloc(ols);
418 | if(!outbuf->nx){fprintf(stderr,"Couldn't malloc %d bytes (outbuf2)\n",ols);exit(1);}
419 | } else {
420 | outbuf->nx=outbuf+u+1;ols-=(u+1)*t;
421 | }
422 | memcpy(outbuf->l,l,s);outbuf=outbuf->nx;outbuf->nx=0;
423 | } else printf("%s",l);
424 | } /* main loop */
425 |
426 | if(sep)for(tr=0;trnx;outbuf=outbuf->nx){
430 | if((outbuf->all||outbuf->tr==tr)&&outbuf->bn!=prb){printf("\n");prb=outbuf->bn;}
431 | if(outbuf->all&&outbuf->tr!=tr)printf("# ");
432 | if(outbuf->all||outbuf->tr==tr)printf("%s",outbuf->l);
433 | }
434 | printf("\n");
435 | }
436 |
437 | printf("# Successfully parsed\n");
438 | printf("# Duration = %g seconds\n",ert/1000000);
439 | return 0;
440 | }
441 |
--------------------------------------------------------------------------------
/overtone/tools/midiconverter/midiasciiconversion.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | midi <-> ascii conversion
5 |
6 |
7 |
8 |
9 | midi <-> ascii conversion - instructions
10 |
11 |
12 | dictionary
13 | "crotchet" (UK English) = "quarter note" (US English). And "bar" = "measure".
14 |
15 | ascii file format
16 | Perhaps the easiest way to understand this is to look at examples
17 | generated by using mid2asc on midi files.
18 | Each non-blank line is either a comment (starts with '#'), or an event.
19 | The first item on an event line is the time the event occurs and can be determined in one
20 | of five ways:
21 |
22 | (i) | BA+CR | Bar number+Crotchet within bar |
23 | (ii) | CR | Crotchet number from the very start |
24 | (iii) | DT | Delta time from previous event - native midi format |
25 | (iv) | FOL[+/-crotchets] | Time from end of previous note/rest on same track |
26 | (v) | SIM[+crotchets] | Time from start of previous note/rest on same track |
27 |
28 | In case (iii), the time is in units of 'ticks', in the other four
29 | cases the time is in units of crotchets using fractional notation,
30 | e.g., 3+5/6. The denominator must divide the overall division set at
31 | the start of the file (e.g., 384). Further time descriptions can
32 | occur in brackets after the first one and are ignored by asc2mid.
33 | They are just output by mid2asc to help to see where you are, and it
34 | is OK to edit the first time description even if this becomes
35 | inconsistent with subsequent the bracketed ones.
36 |
37 | On the line there must be a track number between 0 and 15 specified by "TR <number>", and
38 | a channel number between 1 and 16 specified by "CH <number>".
39 | All numbers are either decimal or hexadecimal when preceeded by "&" or "0x".
40 |
41 |
42 | After that you can either write (i) a generic midi event, (ii) a
43 | generic meta event, (iii) a generic sysex event, or (iv) an event
44 | which has been given a name. Most common events have a name: NT (play
45 | a note), Time signature, Channel volume, Instrument, End of track,
46 | Tempo, Key, Text. For example,
47 | (i)
ST &A0 &3C &64
48 | (ii)
Meta Event type &7F 0 0 119 14 0
(don't put in length, asc2mid counts the data bytes.)
49 | (iii)
Sysex Event &F7 0 1 2 3
(don't put in length, asc2mid counts the data bytes.)
50 | (iv)
Channel volume 100
51 | Time signature 4/4, clocks/mtick 96, crotchets/32ndnote 8
52 | NT C'' 3+1/2 von=80
53 | Turn on C two octaves above middle C, lasting 3+1/2 crotchets, with velocity 80
54 | (asc2mid will insert the corresponding note-off event at the right time).
55 | NT Bb-- on
56 | Turn on Bb one-and-a-bit octaves below middle C with velocity
57 | given by most recent von on same track.
58 | NT R 3
59 | Insert a rest of 3 crotchets on this track (this doesn't actually write
60 | any midi events. Its only effect is on the next FOL or SIM).
61 |
62 | The instrument numbers go from 1 to 128. It is up to the user to put in an "End track" at
63 | the end of every track.
64 |
65 | mid2asc
66 |
67 | Usage:
mid2asc [-c] [-f,-r] [-s] midifile > textfile
68 | The -c, -f and -r flags affect how the timing of the event lines is specified.
69 | The default (none of -c, -f or -r) outputs BA+CR type timings (item
70 | (i) in above ascii file format description). There is a slight complication in
71 | this case, because the time signature affects the meaning of bar
72 | number, and the time signature can change at any time on any track,
73 | and should affect all tracks. This shouldn't cause any trouble, but
74 | to guide the eye when the time signature changes on some track,
75 | mid2asc outputs a comment line on every track. By the way, bar numbers
76 | start from 1 in keeping with usual conventions, but all other timing
77 | stuff starts from 0.
78 | -c mode outputs pure CR timings (crotchet number from very start - item (ii) in
79 | above ascii file format description).
80 | -r mode outputs DT (delta time) timings (ticks from previous event - item (iii) in
81 | above ascii file format description).
82 | -f mode outputs FOL, SIM or SIM+number timings (relative to end or start of previous note - items (iv), (v) in above ascii file format description).
83 | -s causes tracks to be output separately.
84 | asc2mid
85 | Usage:
asc2mid textfile > midifile
86 |
87 | Makes a midi file when given an ascii file in the format described
88 | above. It requires all lines corresponding to a given track to be in
89 | chronological order. (It's possible to drop this restriction, if all
90 | events are specified by the CR method, by presorting the lines.) Lines
91 | from different tracks can be separated or interleaved in any way.
92 |
93 | Other stuff
94 | The midi file format has slight redundancies so the representation
95 | is ambiguous. For example events occuring at the same time can
96 | sometimes be swapped; using running st mode is a matter of choice;
97 | using 0x8* or 0x9* for voff when velocity=0x40 is a matter of choice;
98 | there is allowed to be any junk after the end of the tracks. This
99 | means that applying mid2asc then asc2mid won't necessarily get you
100 | back to where you started. However, the choices asc2mid and mid2asc
101 | make are meant to be 'stable', so applying asc2mid, mid2asc then
102 | asc2mid should be the same as applying asc2mid. Also mid2asc asc2mid
103 | mid2asc should be the same as mid2asc.
104 |
Back up a level
105 |
106 |
107 |
--------------------------------------------------------------------------------
/tidal/awesome.tidal:
--------------------------------------------------------------------------------
1 | -- swing.tidal
2 | -- (c) 2017 by Milan Gruner
3 |
4 | bps (90/60)
5 |
6 | -- plain awesome
7 | d1 $ slow 2 $ stack [
8 | density 2 $ sound (samples "[bd:3(3,8), sn:3(2,8,6)]" "0 1 1 3 2")
9 | # delay "0.8"
10 | # pan (scale 0.25 0.75 rand)
11 | # shape (scale 0.2 0.3 sine1),
12 | every 4 (density 4) $ sound "arpy(5,8,2)"
13 | # sustain "2"
14 | # attack "0.3"
15 | # n "1 2 3 7 8 6 3 4 4 4 4"
16 | # shape "0.6",
17 | every 2 (density 2) $ sound (samples "hh(14,16,4) hh" (irand 13))
18 | # shape (scale 0.2 0.6 sine1)
19 | # sustain sine1
20 | ]
21 |
22 | d1 $ stack [
23 | every 4 (density 2) $ sound "[kd:2 (5,6,1), sn:6 (5,6,3), hh 12 (5,6,2)]"
24 | # shape (scale 0.2 0.6 saw),
25 | sound "bass:6(5,6)" # n "5 7 3 5 8 5 9 1" # shape (scale 0.2 0.8 saw1)
26 | ]
27 |
28 | d2 $ stack [
29 | every 4 (0.25 <~) $ sound "hh*12" # shape "0.8" # attack (scale 0.01 0.2 sine1),
30 | every 3 (density 1) $ sound "bass:6(3,3,0)"
31 | # n "3 1 3 1 5 1 "
32 | # shape "0.9"
33 | ]
34 |
35 | d2 silence
36 |
37 | hush
38 |
--------------------------------------------------------------------------------
/tidal/bjorklund.tidal:
--------------------------------------------------------------------------------
1 | -- bjorklund.tidal
2 | -- (c) 2017 by Milan Gruner
3 |
4 | bps (210/60)
5 |
6 | hush
7 |
8 | d1 $ e 5 9 $ sound "bd:3 sn:2 hh hh" # shape "0.4"
9 | d2 $ sound "bd:3(4,8)"
10 |
11 | d1 $ e 5 17 2 $ sound "bd [sn*2, hh]"
12 |
13 | d1 $ sound "sn:3([13 6 3]/2,8)"
14 |
15 | d1 $ sound "[bd(3,8) , sn(4,9) , hh(5,11)]"
16 |
17 | -- try them out here:
18 | d1 $ slow 1 $ sound "sn:1(3,4,1)?"
19 | d2 $ slow 1 $ sound "bd:2(3,4,2)"
20 |
21 | d1 $ sound (samples "bd*2 sn bd sn" "3 2 3 1")
22 |
23 | -- awesomely animated hihat drill
24 | d2 $ sound "hh*16 rd" # pan sine1 # shape (scale 0.2 0.6 sine1) # cutoff (scale 600 10000 sine1)
25 |
26 | d3 $ sound "[arpy*5, arpy*4] ~ arpy*2" # shape "0.2"
27 |
28 | d3 $ slow 1 $ sound (samples "sn(5,9)" "1 8 7 15 6 8") # shape (scale 0.2 0.3 sine1) # cutoff "500" # sustain "1.0 0.5 ~ 1" # resonance "0.2"
29 |
30 | d3 silence
31 |
32 | hush
33 |
34 | -- folk rhythms
35 | -- created by Bjorklund's algorithm
36 | -- originally intended for nuclear physics :D
37 | -- used with e function => e a b $
38 | -- or just drum(a,b) in rhythm
39 |
40 | -- special
41 | 4 11 Frank Zappa - Outside Now
42 | 5 11 Moussorgsky - Pictures at an Exhibition
43 | 7 8 bendir frame drum rhythm
44 | -- southern european
45 | 3 7 bulgarian ruchenitza
46 | 4 7 bulgarian ruchenitza
47 | 4 9 turkey aksak
48 | 3 5 2 persian or rumanian folk dance
49 | -- african
50 | 7 12 west african bell pattern
51 | 9 16 central african republic - rhythm necklace
52 | 11 24 14 central africa - aka pygmies rhythm necklace
53 | 13 24 5 another aka pygmies of the upper sangha rhythm necklace
54 | 5 12 south african venda clapping pattern
55 | -- arab
56 | 5 6 arab York-Samai
57 | 5 7 arab nawakhat
58 | 5 9 arab Agsag-Samai
59 | 2 5 persian khafif-e-ramal
60 | -- latin
61 | 5 8 cuban cinquillo
62 | 3 8 cuban tresillo
63 | 5 16 brazil bossa nova
64 | 3 4 cumbia (colombia)
65 | 7 16 14 brazil samba
66 |
--------------------------------------------------------------------------------
/tidal/drumulous.tidal:
--------------------------------------------------------------------------------
1 | -- drumulous.tidal
2 | -- (c) 2017 by Milan Gruner
3 |
4 | bps (120/60)
5 | hush
6 | d1 silence
7 | d2 silence
8 |
9 | d1 $ sound (samples "[bd*7 bd kd hh, sn sn hh*2 sn*8 sn] " "0 0 0 1 0 2 0") # shape "0.7" # pan (scale 0.25 0.75 sine1)
10 |
11 | d1 $ slow 1 $ sound "[kd:2(10,9,2) sn:7(4,9,3) hh(15, 18, 2)]"
12 | # shape (scale 0.3 0.7 sine1)
13 | # pan (scale 0.25 0.75 sine1)
14 | # sustain (scale 1 3 saw1)
15 |
16 | d1 $ stack [
17 | every 4 (density 0.25) $ sound "bd(7,8,2)",
18 | every 4 (e 15 20) $ sound "sn",
19 | sound "sn(20,24,5)"
20 | ]
21 |
22 | d2 $ slow 1 $ sound (samples "arpy(7,9,2)" (irand 16))
23 | # shape (scale 0.2 0.4 sine1)
24 | # sustain (scale 0.1 0.8 sine1)
25 | -- # hpf "600 1200 1800 100 200"
26 |
27 | d2 silence
28 |
--------------------------------------------------------------------------------
/tidal/dubbalicious.tidal:
--------------------------------------------------------------------------------
1 | -- dubbalicious.tidal
2 | -- (c) 2017 Milan Gruner
3 |
4 | bps (120/60)
5 |
6 | hush
7 |
8 | d1 $ stack [
9 | every 2 (0.5 <~) $ slowcat [
10 | sound "~ sn*14 ~ sn ~ bd sn*2" # speed (rand),
11 | sound "bd*16 ~" # speed sine1,
12 | sound "sn:3*8" # speed (rand)
13 | ],
14 | every 3 (density 0.5) $ sound "hh*8" # shape (scale 0.2 0.7 sine1),
15 | sound "bd:5(4,11)?" # shape "0.7" # pan sine1,
16 | every 4 (density 0.5) $ sound (samples "arpy(6,12,3)" (irand 6)) # sustain "0.4" # shape (scale 0.2 0.6 sine1)
17 | ]
18 |
19 | -- crazy hihat animation
20 | d1 $ stack [
21 | every 4 (density 0.5) $ slowcat [
22 | sound (samples "[bd:2(3,8), sn:3(3,8,2), hh:1*8]" "1") # shape tri1 # pan (scale 0.25 0.75 saw1),
23 | density 2 $ sound (samples "[hh*16, sn:3*2 bd:4*2] hh*16 hh*8" "4 5 2 6 4 7 2") # shape (scale 0.2 0.4 sine1) # speed (scale 0.2 0.6 sine1)
24 | ],
25 | every 2 (0.5 ~>) $ sound "hh:8(8,12)" # shape "0.7" # pan sine1 # speed (scale 0.2 3 saw1) # resonance "2",
26 | sound "bd sn bd sn"
27 | ]
28 |
29 | d1 $ slow 2 $ sound "bd ~ hh bd ~ sn:3 ~ ~ bd*4 ~ hh ~ sn*2 ~ hh" # delay "0"
30 |
31 | -- quirky half-step rhythm
32 | d1 $ stack [
33 | slow 2 $ slowcat [
34 | sound (samples "[lbass:6(7,8,6)?, lsn:7(1,8,3), lkd:7(3,8,1)]" "2 3 3 1 3 2 6")
35 | # shape "0.8 0.2 0.6 0.3"
36 | # shape (scale 0.4 0.4 tri1)
37 | # sustain "0.6",
38 | sound (samples "[lbass:6(2,8,6)?, lsn:7(3,8,1), lkd:7(5,8,3)]" "4 3 1 3 1 4 6 8 7 3")
39 | # shape "0.2 0.6 0.3 0.4"
40 | # shape (scale 0.4 0.7 sine1)
41 | # sustain "0.6"
42 | ],
43 | slow 4 $ sound (samples "[lhh:7(12,16,4)]" (irand 19))
44 | # shape "0.4"
45 | # speed (scale 0.1 2 sine1)
46 | # sustain "0.7",
47 | d1 $ slow 2 $ sound "lhh:7(11,16,2)" # sustain "0.7" # delay "0.3" # pan (scale 0.05 0.95 sine1)
48 | d2 $ slow 2 $ sound "latmo:4"
49 | ]
50 |
51 | d1 silence
52 | hush
53 |
54 | -- fuckaaa rhythm (best!)
55 | d1 $ slow 2 $ stack [
56 | density 2 $ sound (samples "[bd(3,8), sn(2,8,6)]" "0 1 1 3 2")
57 | # delay "0.8"
58 | # pan (scale 0.25 0.75 rand)
59 | # shape (scale 0.3 0.4 sine1),
60 | every 4 (density 4) $ sound (samples "bass1(4,8,2)" (irand 20))
61 | # sustain "0.8"
62 | # shape "0.4",
63 | every 8 (density 4) $ sound (samples "hh(14,16,4) hh" (irand 16))
64 | # shape (scale 0.2 0.4 sine1)
65 | ]
66 |
67 | hush
68 |
69 | -- quirky melody+drill combination
70 | d2 $ slow 4 $ sound (samples "sn*12 casio*7 sn cp bd*14" "1 3 4 7 8 3") # speed (scale 0.5 2 rand)
71 | d2 silence
72 |
--------------------------------------------------------------------------------
/tidal/experiments.tidal:
--------------------------------------------------------------------------------
1 | -- experiments.tidal
2 | -- (c) 2017 by Milan Gruner
3 |
4 | hush
5 |
6 | -- set cycles per second
7 | cps 1
8 | -- set tempo of 120 BPM
9 | bps (140/60)
10 |
11 | d1 $ sound "arpy:5(7,5,2)" # up (run 5) # shape "0.8 0.2 0.1 0.7"
12 |
13 | d1 $ sound "sn:3*64" # shape tri1 # pan sine1 -- # speed (run 8)
14 |
15 | d1 $ sound "bd*16 sn*8" # pan sine1 # speed (density 2.5 $ tri1)
16 |
17 | -- crazy sweeping rhythm
18 | d2 $ stack [
19 | sound "bd*2 cp sn:2*8 bd:3*6" # speed (scale 7 8 $ tri1) # pan sine1,
20 | sound "hh*32" # cutoff (scale 500 1220 $ slow 2 $ sine1) # resonance "0.7"
21 | ]
22 | -- sound "arpy(6,8) . [sn*5? cp:1*10]" # speed (scale 2 2 $ sine1) # delay "0.5 0.8 0.2 1.0"
23 |
24 | -- multi bar pattern
25 | d1 $ slowcat [
26 | sound "cp*2 sn*3" # vowel "[a e i o e]" # pan sine1,
27 | sound "cp*2 sn*3" # vowel "[u u a o e]" # pan sine1 # shape (scale 0.3 0.7 sine1),
28 | sound "cp*2 sn*3" # vowel "[o i i i e]" # pan sine1,
29 | sound (samples "drum*4" "0 1 2 3 4 4") # shape (scale 0.3 0.7 sine1)
30 | ]
31 |
32 | -- multi sound pattern
33 | d2 $ stack [
34 | --sound "arpy*8" # speed "0.5 1.0 0.5 1.0",
35 | d2 $ sound "arpy(5,6,12)" # speed rand # shape rand
36 | ]
37 |
38 | d1 silence
39 |
40 | -- time shifting/ shuffling
41 | d1 $ stack [
42 | every 3 (0.25 <~) $ sound "bd*2 sn:3*2 hh sn",
43 | every 3 (0.25 ~>) $ sound "bd sn:3 hh sn*2",
44 | every 6 (0.5 ~>) $ sound "sn:3*2 sn hh bd"
45 | ]
46 |
47 | d3 $ sound (samples "bd*8?" "0 1 1 2 4*3 3") # speed "43 3 50 1 50 1 4 50" # pan sine1
48 |
49 | -- random melody
50 | d2 $ s "arpy*8?" # n (irand 37) # delay "0.8" # shape sine1
51 |
52 | d2 $ s "arpy(7,8,2)" # n "37 30 27 18 19 22 27 37 35" # delay "0.8" # shape sine1
53 |
54 | hush
55 |
--------------------------------------------------------------------------------
/tidal/samba_for_the_salsa.tidal:
--------------------------------------------------------------------------------
1 | -- swing.tidal
2 | -- (c) 2017 by Milan Gruner
3 |
4 | bps (140/60)
5 |
6 | # samba
7 | 7 16 14
8 |
9 | d1 $ slowcat [
10 | stack [
11 | sound "lbd(7,16,14)" # shape "0.7",
12 | sound "lhh(12,16,14)" # shape "0.3",
13 | sound "arpy(3,16,14)" # shape "0.5"
14 | ],
15 | stack [
16 | sound "lbd(7,16,14)?" # shape "0.7",
17 | sound "lhh(12,16,14)?" # shape "0.3",
18 | sound "arpy(8,16,14)" # shape "0.5"
19 | ]
20 | ]
21 |
22 | -- just for reference
23 | d1 $ slow 2 $ stack [
24 | density 2 $ sound (samples "[bd:3(3,8), sn:3(2,8,6)]" "0 1 1 3 2")
25 | # delay "0.8"
26 | # pan (scale 0.25 0.75 rand)
27 | # shape (scale 0.2 0.3 sine1),
28 | every 4 (density 4) $ sound "arpy(5,8,2)"
29 | # sustain "2"
30 | # attack "0.3"
31 | # n "1 2 3 7 8 6 3 4 4 4 4"
32 | # shape "0.6",
33 | every 2 (density 2) $ sound (samples "hh(14,16,4) hh" (irand 13))
34 | # shape (scale 0.2 0.6 sine1)
35 | # sustain sine1
36 | ]
37 |
--------------------------------------------------------------------------------
/tidal/striation.tidal:
--------------------------------------------------------------------------------
1 | -- striation.tidal
2 | -- (c) 2017 by Milan Gruner
3 | -- inspired by kindohm (Mike Hodnik)
4 |
5 | bps (180/60)
6 |
7 | sound "lkd lcp [~ lkd] lcp",
8 | sound "lhh*8",
9 |
10 | d1 $ slow 2 $ slowcat [
11 | sound "amen:1",
12 | sound "amen:5",
13 | sound "[amen:4 amen:2]",
14 | sound "[amen:3, amen:6]"
15 | ]
16 |
17 | # shape "0.7"
18 | # sustain "0.0"
19 |
20 | sound "[amen:4, amen:2] amen:5 amen:1"
21 |
22 | d1 $ stack [
23 | every 3 (0.25 ~>)
24 | $ within (0.25, 0.75) (density 2)
25 | $ within (0.75, 1) (|+| speed "1.25")
26 | $ degradeBy 1
27 | $ slow 16
28 | $ striate 128
29 | $ sound "amen:2" -- :146 is max
30 | |+| delay "0.4"
31 | ]
32 | |+| delayfeedback "0.4"
33 | |+| delaytime "0.48"
34 |
35 | hush
36 |
--------------------------------------------------------------------------------
/tidal/test.tidal:
--------------------------------------------------------------------------------
1 | d1 $ sound "bd sn"
2 |
--------------------------------------------------------------------------------
/tidal/tutorial.tidal:
--------------------------------------------------------------------------------
1 | -- tutorial.tidal
2 | -- (c) 2017 by Milan Gruner
3 | -- Lots of random sounds! :D
4 |
5 | bps (120/60)
6 |
7 | hush
8 |
9 | d1 $ sound "bd:3 sn:2 bd:2 [bd sn:3 sn:3 bd:3]"
10 | d2 $ sound "hh hh hh hh"
11 | d3
12 | $ sound "arpy(6,8)"
13 | # speed "[1 0.5, 1.5 2 3 4 7 2 8 10 12]"
14 | # shape "0.8"
15 | # resonance "0.9"
16 | # attack "0 1 0.5 0.2 1"
17 | d3
18 | $ sound "arpy*3 cp"
19 | # speed "[1 0.5, 1.5 2 3 4]"
20 |
21 | d1 silence
22 |
23 | d1 $ sound "[bd sn sn, hh hh hh hh] bd sn bd"
24 | d2 $ sound "[bd bd] [bd [sn sn], sn], sn bd]"
25 |
26 | d2 $ slow 2 $ sound "arpy*12" # up "2 7 4 3 1 8 9 10 4 5 6 7"
27 |
28 | d1 $ sound "bd(3,8) sn(5,8,2)" # up "4 6 8 12"
29 |
30 | hush
31 |
32 | d1 $ sound "bd bd . sn sn sn . bd sn bd sn"
33 |
34 | d1 $ sound "[bd bd bd, [sn sn] cp, arpy [arpy arpy] arpy arpy, odx]"
35 |
36 | d1 $ sound "bd bd:4*2 cp sn"
37 | d2 $ sound "arpy*10 hh arpy*10 cp sn" # speed "[1 0.5, 1.5 2 3 4]"
38 |
39 | d1 $ density 1 $ sound "cp? bd:2*15 sn/2 bd:2? cp*5"
40 | d2 $ slow 2 $ rev (sound "[bd:2*15 sn:3*3? cp cp?]/2")
41 |
42 | d1 $ every 4 (density 4) $ sound "bd*2 [bd [sn sn*2 sn] sn]"
43 |
44 | d1 $ sound "bd*15 cp sn arpy*4 . cp cp" # gain "0.8" # delay "0.5" # shape "0.3"
45 |
--------------------------------------------------------------------------------
/visuals/.gitignore:
--------------------------------------------------------------------------------
1 | dist/
2 | .stack-work/
3 | TAGS
4 | *.cabal
5 |
--------------------------------------------------------------------------------
/visuals/HelloHylogen.hs:
--------------------------------------------------------------------------------
1 | -- HelloHylogen.hs
2 | -- (c) 2017 by Milan Gruner
3 | -- Adapted from Hylogen example code
4 |
5 | module HelloHylogen where
6 | import Hylogen.WithHylide
7 |
8 | output :: Program
9 | output = toProgram color
10 |
11 | color :: Vec4
12 | color = vec4(a*0.7, a*0.2, a*0.3, 1)
13 | where
14 | k = 40
15 | f = (*k) . sin . cos . tan . (/k)
16 | a = sum [
17 | cos(x_ uvN * f time + x_ mouse),
18 | sin(y_ uvN * f time + y_ mouse),
19 | atan(x_ uvN * f time + x_ mouse),
20 | tanh(y_ uvN * f time + y_ mouse)]
21 |
--------------------------------------------------------------------------------
/visuals/Poop.hs:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE FlexibleInstances #-}
2 | {-# LANGUAGE FlexibleContexts #-}
3 | {-# LANGUAGE GADTs #-}
4 | {-# LANGUAGE RankNTypes #-}
5 |
6 | module Poop where
7 | import Hylogen.WithHylide
8 |
9 | rot :: Vec1 -> Vec2 -> Vec2
10 | rot phi a = vec2 ( cos phi * (x_ a)
11 | + sin phi * (y_ a)
12 | , (-1) * sin phi * (x_ a)
13 | + cos phi * (y_ a)
14 | )
15 |
16 | rep :: forall n. Veccable n => Vec n -> Vec n -> Vec n
17 | rep c p = mod_ p c - 0.5 * c
18 |
19 | mirrorX v = vec2 (abs (x_ v), y_ v)
20 | mirrorY v = vec2 (x_ v, abs(y_ v))
21 |
22 | output = toProgram $ vec4 (r, g, b, 0.01) + bb
23 | where
24 | r = v
25 | & rep 2
26 | & (*0.1)
27 | & (/(x_ bb))
28 | & negate
29 | g = v
30 | & rep 2
31 | & (*0.01)
32 | & (/(x_ bb))
33 | & negate
34 | b = v
35 | & rep 2
36 | & (*0.1)
37 | & (/(x_ bb))
38 | & negate
39 | v = (sin (atan ((y_ uvN' / x_ uvN' - x_ audio * len uvN')) / x_ uvN' - w_ audio)) + z_ audio
40 | uvN' = uvN
41 | & mirrorX
42 | & mirrorY
43 | & (rot (pi/2))
44 | -- & (\x -> x - rep (copy $ w_ audio) x)
45 | & (^*(y_ audio * 5))
46 | & (+(negate (mouse)))
47 | bb = texture2D backBuffer bbN
48 | bbN = uvN
49 | -- & (\x -> x - rep (copy $ w_ audio) x)
50 | & (*1.01)
51 | & mirrorX
52 | & mirrorY
53 | & rot (pi/2)
54 | & (\x -> x * 0.5 + 0.5)
55 |
--------------------------------------------------------------------------------
/visuals/Regenbogenkotze.hs:
--------------------------------------------------------------------------------
1 | -- Regenbogenkotze.hs
2 | -- (c) 2017 by Milan Gruner
3 | -- adapted from: https://github.com/sleexyz/hylogen-fun/blob/master/CruelRainbow.hs
4 |
5 | {-# LANGUAGE GADTs #-}
6 | {-# LANGUAGE RankNTypes #-}
7 | {-# LANGUAGE FlexibleContexts #-}
8 |
9 | module Regenbogenkotze where
10 |
11 | import Util
12 | import Spirangle (spirangle)
13 |
14 | output = toProgram $ vec4 (0, 0, 0, 0)
15 | & const (vec4 (v, v, v, 1) )
16 | & mix 0.1 bb
17 |
18 | bb = bbqF (texture2D backBuffer) uvN
19 |
20 | bbqF x = x
21 | & lmap (view norm)
22 | & lmap (rot (w_ audio * 100))
23 | & lmap (*(x_ audio & copy))
24 | & rgbF 0.1
25 |
26 | v = vqF vq uvN
27 |
28 | vqF x = x
29 | -- & lmap (mirrorX)
30 |
31 | beaty = beat
32 |
33 | vq uv = (1 - (sin (beaty)) * x_ (uv * 10) + cos (y_ uv * copy time))
34 | & (* copy (x_ audio))
35 |
--------------------------------------------------------------------------------
/visuals/Spirangle.hs:
--------------------------------------------------------------------------------
1 | -- Spirangle.hs
2 | -- copied from https://github.com/sleexyz/hylogen-fun/blob/master/Spirangle.hs
3 |
4 | {-# LANGUAGE GADTs #-}
5 | {-# LANGUAGE RankNTypes #-}
6 | {-# LANGUAGE FlexibleContexts #-}
7 |
8 | module Spirangle where
9 |
10 | import Util
11 |
12 |
13 |
14 | output = toProgram (spirangle osc1)
15 |
16 | spirangle draw = rgba where
17 | rgba = (line)
18 | & (over (b2a bb))
19 | & (clamp 0 1)
20 |
21 | bb = q (texture2D backBuffer) uvN
22 |
23 | q x = x
24 | & lmap (view norm)
25 | & lmap (rot ((negate 2 * pi /3) + muchless sin time ))
26 | & lmap (*1.1)
27 | & rmap (clamp 0 1)
28 |
29 | mask :: (Veccable n) => Vec n -> Vec n
30 | mask x = (x `gt` 0) ? (0, 1)
31 |
32 | gate :: (Veccable n) => Vec n -> Vec n -> Vec n -> Vec n
33 | gate s e x = ((x `geq` s) * (x `lt` e)) ? (1, 0)
34 |
35 | line :: Vec4
36 | line = vec4 (v, v, v, 1)
37 | v = 1
38 | & (*(gate (-0.35) (-0.33) (y_ uvN)))
39 | & (*(gate (-0.55) (0.65) (x_ uvN)))
40 | & (*draw)
41 |
--------------------------------------------------------------------------------
/visuals/Util.hs:
--------------------------------------------------------------------------------
1 | -- Util.hs
2 | -- copied from https://github.com/sleexyz/hylogen-fun/blob/master/Util.hs
3 |
4 | {-# LANGUAGE RankNTypes #-}
5 | {-# LANGUAGE TypeFamilies #-}
6 | {-# LANGUAGE GADTs #-}
7 |
8 | module Util (
9 | module Hylogen.WithHylide,
10 | module Data.Profunctor,
11 | module Util,
12 | ) where
13 |
14 | import Hylogen.WithHylide hiding (uv)
15 | import Data.Profunctor
16 | import Hylogen.Expr
17 |
18 |
19 | type Optic p s t a b = p a b -> p s t
20 | type Optic' p a b = Optic p a b a b
21 | type Iso s t a b = forall p. (Profunctor p) => Optic p s t a b
22 | type Iso' a b = Iso a b a b
23 | type Fold r s t a b = Optic (Forget r) s t a b
24 | type Getter s t a b = Fold a s t a b
25 | view :: forall s t a b. Getter s t a b -> s -> a
26 | view l = runForget (l (Forget id))
27 |
28 | type Image = Vec2 -> Vec4
29 |
30 | (?) :: (ToGLSLType a) => Booly -> (Expr a, Expr a) -> Expr a
31 | (?) c (a, b) = sel c a b
32 |
33 |
34 | bw :: Vec1 -> Vec4
35 | bw v = vec4 (v, v, v, 1)
36 |
37 | rot :: Vec1 -> Vec2 -> Vec2
38 | rot phi a = vec2 ( cos phi * (x_ a)
39 | + sin phi * (y_ a)
40 | , (-1) * sin phi * (x_ a)
41 | + cos phi * (y_ a)
42 | )
43 |
44 | over :: Vec4 -> Vec4 -> Vec4
45 | over x y = mix a x' y'
46 | where
47 | x' = clamp 0 1 x
48 | y' = clamp 0 1 y
49 | a = 1 - w_ x'
50 |
51 | less :: (Floating a) => Optic' (->) a a
52 | less = dimap (id) (*0.1)
53 |
54 | muchless :: (Floating a) => Optic' (->) a a
55 | muchless = dimap (id) (*0.01)
56 |
57 | norm :: (Floating a) => Iso' a a
58 | norm = dimap (\x -> x * 0.5 + 0.5) (\x -> x * 2 - 1)
59 |
60 | hsv :: Optic' (->) (Vec4) (Vec4)
61 | hsv = dimap rgb2hsv hsv2rgb
62 |
63 | rep :: forall n. Veccable n => Vec n -> Vec n -> Vec n
64 | rep c p = mod_ p c - 0.5 * c
65 |
66 | -- rgbF :: Vec1 -> (Vec2 -> Vec4) -> (Vec2 -> Vec4)
67 | rgbF :: Vec1 -> Optic' (->) Vec2 Vec4
68 | rgbF offset q pos = vec4 (r, g, b, a)
69 | where
70 | r = q (pos + copy offset) & x_
71 | g = q pos & y_
72 | b = q (pos - copy offset) & z_
73 | a = q pos & w_
74 |
75 | phi uv = atan (y_ uv/x_ uv)
76 |
77 | scale :: Floating a => a -> Iso' a a
78 | scale s = dimap (*s) (/s)
79 |
80 | mirrorX :: Vec2 -> Vec2
81 | mirrorX v = vec2 (abs $ x_ v, y_ v)
82 |
83 |
84 | mirrorY :: Vec2 -> Vec2
85 | mirrorY v = vec2 (x_ v, abs $ y_ v)
86 |
87 | wiggle :: Vec2 -> Vec2
88 | wiggle = rot (cos (time * 0.8) * 0.1)
89 |
90 | desat = hsv $ modY (*0.9)
91 |
92 | polar :: Iso' Vec2 Vec2
93 | polar = dimap c2p p2c where
94 | c2p :: Vec2 -> Vec2
95 | c2p v = vec2 (len v, phi v)
96 | p2c :: Vec2 -> Vec2
97 | p2c v = x_ v *^ vec2 (cos (y_ v), sin (y_ v))
98 |
99 |
100 | -- fixme: make polymorphic
101 | modX :: (Vec1 -> Vec1) -> (Vec4 -> Vec4)
102 | modX f v = vec4 (f (x_ v), y_ v, z_ v, w_ v)
103 | modY :: (Vec1 -> Vec1) -> (Vec4 -> Vec4)
104 | modY f v = vec4 (x_ v, f (y_ v), z_ v, w_ v)
105 | modZ :: (Vec1 -> Vec1) -> (Vec4 -> Vec4)
106 | modZ f v = vec4 (x_ v, y_ v, f (z_ v), w_ v)
107 | modW :: (Vec1 -> Vec1) -> (Vec4 -> Vec4)
108 | modW f v = vec4 (x_ v, y_ v, z_ v, f (w_ v))
109 |
110 | beat' :: Vec1
111 | beat' = 2 * pi * beat
112 |
113 | rand :: Vec1 -> Vec1
114 | rand x = x
115 | & sin
116 | & (*43758.543123)
117 | & fract
118 |
119 | rand2 :: Vec2 -> Vec2
120 | rand2 x = fract(sin(x <.> vec2(12.9898, 4.1414))) *^ 43758.5453
121 |
122 | b2a :: Vec4 -> Vec4
123 | b2a x = vec4 (xyz_ x, x_ x)
124 |
125 | gate :: (Veccable n) => Vec n -> Vec n -> Vec n -> Vec n
126 | gate s e x = ((x `geq` s) * (x `lt` e)) ? (1, 0)
127 |
128 | diff :: Floating a => (a -> a) -> (a -> a)
129 | diff f x = (f (x - delta) - f (x + delta))/(delta * 2) where
130 | delta = 0.00001
131 |
132 |
133 | grad :: (Vec2 -> Vec1) -> (Vec2 -> Vec2)
134 | grad f x = vec2 (dx, dy) where
135 | dx = f (vec2 (x_ x - delta, y_ x)) - f (vec2 (x_ x + delta, y_ x))/delta
136 | dy = f (vec2 (x_ x, y_ x - delta)) - f (vec2 (x_ x, y_ x - delta))/delta
137 | delta = 1
138 |
139 | bpf pos delta = hsv (modX (clamp (pos - delta) (pos + delta)))
140 |
--------------------------------------------------------------------------------
/visuals/package.yaml:
--------------------------------------------------------------------------------
1 | name: algorithmuss-visuals
2 | source-dirs: ./
3 | dependencies:
4 | - base
5 | - hylide
6 | - hylogen
7 | - vector-space
8 | - profunctors
9 | - lens
10 | library: {}
11 |
--------------------------------------------------------------------------------
/visuals/stack.yaml:
--------------------------------------------------------------------------------
1 | flags: {}
2 | extra-package-dbs: []
3 | packages:
4 | - '.'
5 | extra-deps:
6 | - hylide-0.1.5.0
7 | - hylogen-0.1.5.0
8 | resolver: lts-7.5
9 |
--------------------------------------------------------------------------------