A => LICENSE +19 -0
@@ 1,19 @@
+Copyright (c) 2018-2020 Amavect
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
A => README +15 -0
@@ 1,15 @@
+musical experiments
+
+top level contains various programs
+piano originally by umbraticus
+bb/ contains bytebeat songs
+
+build:
+mk $O.$program # whatever your $O objtype prefix is
+
+play:
+# turn down your volume before playing!
+6.out >/dev/audio
+
+for piano programs:
+[az] is octave, [sx] is volume, [qwertyuiop2356790] is keyboard<
\ No newline at end of file
A => bb/0.c +43 -0
@@ 1,43 @@
+/* bytebeat!
+ * play by writing to /dev/audio
+ */
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+/* unnecessary but whatever */
+short
+vtos(uvlong v)
+{
+ return (short)(v&0xFFFF);
+}
+
+/* insert bytebeat formula here */
+uvlong
+next(uvlong t)
+{
+ return t;
+}
+
+void
+main(void)
+{
+ uvlong t;
+ uvlong x, y;
+ short s, s2;
+ Biobuf bfile;
+
+ if(Binit(&bfile, 1, OWRITE) == Beof)
+ sysfatal("%r");
+
+ for(t = 0;; t++){
+ x = next(t);
+ y = next(t);
+ s = vtos(x);
+ s2 = vtos(y);
+ if(Bwrite(&bfile, &s, sizeof(s)) < 0)
+ sysfatal("%r");
+ if(Bwrite(&bfile, &s2, sizeof(s)) < 0)
+ sysfatal("%r");
+ }
+}
A => bb/1.c +45 -0
@@ 1,45 @@
+/* bytebeat!
+ * play by writing to /dev/audio
+ */
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+/* unnecessary but whatever */
+short
+vtos(uvlong v)
+{
+ return (short)(v&0xFFFF);
+}
+
+/* insert bytebeat formula here */
+uvlong
+next(uvlong t)
+{
+ t = t * 8000 / 44100;
+ t = t*(42&t>>10);
+ return t<<8;
+}
+
+void
+main(void)
+{
+ uvlong t;
+ uvlong x, y;
+ short s, s2;
+ Biobuf bfile;
+
+ if(Binit(&bfile, 1, OWRITE) == Beof)
+ sysfatal("%r");
+
+ for(t = 0;; t++){
+ x = next(t);
+ y = next(t);
+ s = vtos(x);
+ s2 = vtos(y);
+ if(Bwrite(&bfile, &s, sizeof(s)) < 0)
+ sysfatal("%r");
+ if(Bwrite(&bfile, &s2, sizeof(s)) < 0)
+ sysfatal("%r");
+ }
+}
A => bb/10.c +42 -0
@@ 1,42 @@
+/* orig by pete */
+/* 44.1 kHz, stereo, signed 16-bit */
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+/* unnecessary but whatever */
+short
+vtos(uvlong v)
+{
+ return (short)(v&0xFFFF);
+}
+
+uvlong
+next(uvlong t)
+{
+ t = t<<2; return (t-(t^((t+0xFFFF)>>1)));
+ //return (128*t * ((1<<5)-((t>>9)%(1<<5)))/(1<<4));
+}
+
+void
+main(void)
+{
+ uvlong t;
+ uvlong x, y;
+ short s, s2;
+ Biobuf bfile;
+
+ if(Binit(&bfile, 1, OWRITE) == Beof)
+ sysfatal("Binit failed!");
+
+ for(t = 1;; t++){
+ x = next(t);
+ y = x;
+ s = vtos(x);
+ s2 = vtos(y);
+ if(Bwrite(&bfile, &s, sizeof(s)) < 0)
+ sysfatal("Bwrite failed!");
+ if(Bwrite(&bfile, &s2, sizeof(s)) < 0)
+ sysfatal("Bwrite failed!");
+ }
+}
A => bb/11.c +41 -0
@@ 1,41 @@
+/* orig by pete */
+/* 44.1 kHz, stereo, signed 16-bit */
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+/* unnecessary but whatever */
+short
+vtos(uvlong v)
+{
+ return (short)(v&0xFFFF);
+}
+
+uvlong
+next(uvlong t)
+{
+ return ((t|(((t^(t>>1))&(((t>>13)%256)^((t>>18)^451)))*((t>>10)&(((t>>12)&253)^(353^(t*17)))))) ^((t>>6)&((t-(t^(t>>1)))^((t-(t^(t>>1)))<<1)^((t-(t^(t>>1)))>>1))));
+}
+
+void
+main(void)
+{
+ uvlong t;
+ uvlong x, y;
+ short s, s2;
+ Biobuf bfile;
+
+ if(Binit(&bfile, 1, OWRITE) == Beof)
+ sysfatal("Binit failed!");
+
+ for(t = 1;; t++){
+ x = next(t);
+ y = x;
+ s = vtos(x);
+ s2 = vtos(y);
+ if(Bwrite(&bfile, &s, sizeof(s)) < 0)
+ sysfatal("Bwrite failed!");
+ if(Bwrite(&bfile, &s2, sizeof(s)) < 0)
+ sysfatal("Bwrite failed!");
+ }
+}
A => bb/12.c +40 -0
@@ 1,40 @@
+/* 44.1 kHz, stereo, signed 16-bit */
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+/* unnecessary but whatever */
+short
+vtos(uvlong v)
+{
+ return (short)(v&0xFFFF);
+}
+
+uvlong
+next(uvlong t)
+{
+ return ((((t<<3)-(t<<3^(((t<<3)+0xFFFF)>>1))) | ((((t<<3)|(t<<2)|(t<<1)) ))) + ( ((t*t*t)/(t%256 + 1))|( (((t<<1) + (1<<15))|(t<<2)|(t<<3)|(t<<4)) ) )) ^ ((t|(((t^(t>>1))&(((t>>13)%256)^((t>>18)^451)))*((t>>10)&(((t>>12)&253)^(353^(t*17)))))) ^((t>>6)&((t-(t^(t>>1)))^((t-(t^(t>>1)))<<1)^((t-(t^(t>>1)))>>1))));
+}
+
+void
+main(void)
+{
+ uvlong t;
+ uvlong x, y;
+ short s, s2;
+ Biobuf bfile;
+
+ if(Binit(&bfile, 1, OWRITE) == Beof)
+ sysfatal("Binit failed!");
+
+ for(t = 1;; t++){
+ x = next(t);
+ y = x;
+ s = vtos(x);
+ s2 = vtos(y);
+ if(Bwrite(&bfile, &s, sizeof(s)) < 0)
+ sysfatal("Bwrite failed!");
+ if(Bwrite(&bfile, &s2, sizeof(s)) < 0)
+ sysfatal("Bwrite failed!");
+ }
+}
A => bb/2.c +45 -0
@@ 1,45 @@
+/* bytebeat!
+ * play by writing to /dev/audio
+ */
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+/* unnecessary but whatever */
+short
+vtos(uvlong v)
+{
+ return (short)(v&0xFFFF);
+}
+
+/* insert bytebeat formula here */
+uvlong
+next(uvlong t)
+{
+ uvlong s;
+ t = (t<<6) | ( (((t>>1)&((t>>1)+(1<<15)))|t|(t<<1)|(t<<2)|(t<<3)) & (((s>>1)&((s>>1)+(1<<15)))|s|(s<<1)|(s<<2)|(s<<3)) );
+ return t;
+}
+
+void
+main(void)
+{
+ uvlong t;
+ uvlong x, y;
+ short s, s2;
+ Biobuf bfile;
+
+ if(Binit(&bfile, 1, OWRITE) == Beof)
+ sysfatal("%r");
+
+ for(t = 0;; t++){
+ x = next(t);
+ y = next(t);
+ s = vtos(x);
+ s2 = vtos(y);
+ if(Bwrite(&bfile, &s, sizeof(s)) < 0)
+ sysfatal("%r");
+ if(Bwrite(&bfile, &s2, sizeof(s)) < 0)
+ sysfatal("%r");
+ }
+}
A => bb/4.c +49 -0
@@ 1,49 @@
+/* Amavect!
+ * Spring Beat
+ * to play: 6.out >/dev/audio
+ * (turn down your volume)
+ */
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+/* unnecessary but whatever */
+short
+vtos(uvlong v)
+{
+ return (short)(v&0xFFFF);
+}
+
+/* insert bytebeat formula here */
+uvlong
+next(uvlong t)
+{
+
+ uvlong hat = ( ((t*t*t)/(t%256 + 1))|( (((t<<1) + (1<<15))|(t<<2)|(t<<3)|(t<<4)) ) );
+ uvlong kick = ( (128*t * ((1<<5)-((t>>9)%(1<<5)))/(1<<4))|((t<<3)|(t<<2)|(t<<1)) );
+ uvlong melody = ((3*64*t&t>>7)|(4*64*t&t>>2)|(5*64*t&t>>6)|(9*64*t&t>>4));
+ return (kick + hat) ^ melody;
+}
+
+void
+main(void)
+{
+ uvlong t;
+ uvlong x, y;
+ short s, s2;
+ Biobuf bfile;
+
+ if(Binit(&bfile, 1, OWRITE) == Beof)
+ sysfatal("Binit failed!");
+
+ for(t = 0;; t++){
+ x = next(t);
+ y = next(t);
+ s = vtos(x);
+ s2 = vtos(y);
+ if(Bwrite(&bfile, &s, sizeof(s)) < 0)
+ sysfatal("Bwrite failed!");
+ if(Bwrite(&bfile, &s2, sizeof(s)) < 0)
+ sysfatal("Bwrite failed!");
+ }
+}
A => bb/5.c +110 -0
@@ 1,110 @@
+/* Amavect!
+ * Panning Test
+ * to play: 6.out >/dev/audio
+ * (turn down your volume)
+ */
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+typedef struct Bytebeat Bytebeat;
+typedef struct Sound Sound;
+typedef struct Audio Audio;
+
+/* unsignedlonglongbeat? */
+struct Bytebeat{
+ uvlong l;
+ uvlong r;
+};
+
+/* continuous sounds are to be modelled with precision */
+struct Sound{
+ double l;
+ double r;
+};
+
+/* audio(3) */
+struct Audio{
+ short l;
+ short r;
+};
+
+/* unnecessary but whatever */
+Audio
+bbtoaudio(Bytebeat bb)
+{
+ Audio a;
+ a.l = (short)(bb.l&0xFFFF);
+ a.r = (short)(bb.r&0xFFFF);
+ return a;
+}
+
+Sound
+audiotosound(Audio a)
+{
+ Sound s;
+ s.l = (double)a.l / (1<<15); /* avoid clipping for a.l=-1<<15 */
+ s.r = (double)a.r / (1<<15);
+ return s;
+}
+
+Audio
+soundtoaudio(Sound s)
+{
+ Audio a;
+ a.l = (short)(s.l * (1<<15 - 1)); /* avoid clipping for s.l=1.0 */
+ a.r = (short)(s.r * (1<<15 - 1));
+ return a;
+}
+
+Sound
+nextpan(uvlong t)
+{
+ Sound m;
+ m.l = cos(t / 44100.0);
+ m.r = sin(t / 44100.0);
+ return m;
+}
+
+Sound
+soundmod(Sound s, Sound m)
+{
+ s.l *= m.l;
+ s.r *= m.r;
+ return s;
+}
+
+/* insert bytebeat formula here */
+Bytebeat
+next(uvlong t)
+{
+ Bytebeat bb;
+ bb.l = t<<6;
+ bb.r = bb.l;
+ return bb;
+}
+
+void
+main(void)
+{
+ uvlong t;
+ Bytebeat bb;
+ Audio a;
+ Sound s, m;
+ Biobuf bfile;
+
+ if(Binit(&bfile, 1, OWRITE) == Beof)
+ sysfatal("Binit failed!");
+
+ for(t = 0;; t++){
+ bb = next(t);
+ s = audiotosound(bbtoaudio(bb));
+ m = nextpan(t);
+ s = soundmod(s, m);
+ a = soundtoaudio(s);
+ if(Bwrite(&bfile, &a.l, sizeof(a.l)) < 0)
+ sysfatal("Bwrite failed!");
+ if(Bwrite(&bfile, &a.r, sizeof(a.r)) < 0)
+ sysfatal("Bwrite failed!");
+ }
+}
A => bb/6.c +206 -0
@@ 1,206 @@
+/* Amavect!
+ * Xenihak
+ * to play: 6.out >/dev/audio
+ * (turn down your volume)
+ */
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+typedef struct Bytebeat Bytebeat;
+typedef struct Sound Sound;
+typedef struct Audio Audio;
+
+/* unsignedlonglongbeat? */
+struct Bytebeat{
+ uvlong l;
+ uvlong r;
+};
+
+/* continuous sounds are to be modelled with precision */
+struct Sound{
+ double l;
+ double r;
+};
+
+/* audio(3) */
+struct Audio{
+ short l;
+ short r;
+};
+
+/* unnecessary but whatever */
+Audio
+bbtoaudio(Bytebeat bb)
+{
+ Audio a;
+ a.l = (short)(bb.l&0xFFFF);
+ a.r = (short)(bb.r&0xFFFF);
+ return a;
+}
+
+Sound
+audiotosound(Audio a)
+{
+ Sound s;
+ s.l = (double)a.l / (1<<15); /* avoid clipping for a.l=-1<<15 */
+ s.r = (double)a.r / (1<<15);
+ return s;
+}
+
+Audio
+soundtoaudio(Sound s)
+{
+ Audio a;
+ a.l = (short)(s.l * ((1<<15) - 1)); /* avoid clipping for s.l=1.0 */
+ a.r = (short)(s.r * ((1<<15) - 1));
+ return a;
+}
+
+Sound
+nextpan(uvlong t)
+{
+ Sound m;
+ m.l = cos(t / (2 * 44100.0));
+ m.r = sin(t / (2 * 44100.0));
+ return m;
+}
+
+Sound
+swapchan(Sound s)
+{
+ double d;
+ d = s.l;
+ s.l = s.r;
+ s.r = d;
+ return s;
+}
+
+Sound
+nextvol(uvlong t)
+{
+ Sound v;
+ v.l = sin(t / 200000.0);
+ v.r = v.l;
+ return v;
+}
+
+Sound
+nextvol2(uvlong t)
+{
+ Sound v;
+ v.l = cos(t / 200000.0);
+ v.r = v.l;
+ return v;
+}
+Sound
+soundmod(Sound s, Sound m)
+{
+ s.l *= m.l;
+ s.r *= m.r;
+ return s;
+}
+
+Sound
+soundmix(Sound s, Sound t)
+{
+ s.l = (s.l + t.l) / 2.0;
+ s.r = (s.r + t.r) / 2.0;
+ return s;
+}
+
+/* insert bytebeat formula here */
+Bytebeat
+next(uvlong t)
+{
+ Bytebeat bb;
+ bb.l = (7*t<<7)&(666666|t>>4) ^ ((19*t<<6)%(1<<16))|(t>>1) ^ (3*t<<9&t>>2)^ (13*t<<10&t>>3);
+ bb.r = bb.l;
+ return bb;
+}
+
+Bytebeat
+next2(uvlong t)
+{
+ Bytebeat bb;
+ bb.l = (17*t<<7)&(666666|t>>7) ^ (11*t<<8&t>>6) ^ (23*t<<9&t>>3);
+ bb.r = bb.l;
+ return bb;
+}
+
+Bytebeat
+nextdrop(uvlong t)
+{
+ Bytebeat bb;
+ uvlong u, s, p, hat, snare, kick, bass, mel;
+
+ hat = ( ((t*t*t)/(t%256 + 1))|( (((t<<1)|(t<<2) + (1<<15))|(t<<2)|(t<<((t<<2)&(t<<3)))|(t<<4)*(t>>13&t>>12)) ) );
+ u = t+(1<<14);
+ s = t+(3<<13);
+ p = (t*1/1)*(((t>>17)+3)%4/3) + (t*3/4)*(((t>>17)+2)%4/3) + (t*7/8)*(((t>>17)+1)%4/3) + (t*15/16)*(((t>>17)+0)%4/3);
+ kick = ( (128*t * ((1<<5)-((t>>8)%(1<<5)))/(1<<4))|( (((t>>1)&((t>>1)+(1<<15)))|t|(t<<1)|(t<<2)|(t<<3)) & (((s>>1)&((s>>1)+(1<<15)))|s|(s<<1)|(s<<2)|(s<<3)) ) );
+ bass = (((1000*t/1001<<6) & (1001*t/1000<<6)) - 1) & (t<<((999*t/998>>1|t>>8)*(t>>13&t>>12)));
+ snare = ( ((t<<8)%666666) ^ ((t<<5)%(1<<16) + 1) ) | ( (u&(u+(1<<15))|(u<<1)|(u<<2)|(u<<3)) );
+ mel = (7*t<<7&t>>2)|(9*t<<7&t>>3)|(19*t<<6&t>>4)|(11*t<<7&t>>5);
+
+ if(t >= 1<<20 && t < (1<<21) - (1<<17)){
+ bb.l = hat;
+ }else if(t >= 1<<21 && t < 1<<22){
+ bb.l = (kick + snare + hat) ^ bass;
+ }else if(t >= 1<<22 && t < (1<<22) + (1<<20)){
+ bb.l = (snare + hat) | mel;
+ }else if(t >= (1<<22) + (1<<20) && t < (3<<21) - (1<<17)){
+ bb.l = hat | mel;
+ }else if(t >= 3<<21 && t < (1<<23) - (1<<17)){
+ bass = (((1000*p/1001<<6) & (1001*p/1000<<6)) - 1) & (t<<((999*t/998>>1|t>>8)*(t>>13&t>>12)));
+ bb.l = (kick + snare + hat) ^ bass;
+ }else if(t >= (1<<23) - (1<<17) && t < 1<<23){
+ bass = (((1000*p/1001<<6) & (1001*p/1000<<6)) - 1) & (t<<((999*t/998>>1|t>>8)*(t>>13&t>>12)));
+ bb.l = (snare + hat) ^ bass;
+ }else{
+ bb.l = 0;
+ }
+ bb.r = bb.l;
+ return bb;
+}
+
+void
+main(void)
+{
+ uvlong t;
+ Bytebeat b1, b2, b3;
+ Audio a;
+ Sound s1, s2, s3, m1, m2, v1, v2;
+ Biobuf bfile;
+
+ if(Binit(&bfile, 1, OWRITE) == Beof)
+ sysfatal("Binit failed!");
+
+ for(t = 0; t < (1<<23) + (1<<20); t++){
+ b1 = next(t);
+ b2 = next2(t);
+ s1 = audiotosound(bbtoaudio(b1));
+ s2 = audiotosound(bbtoaudio(b2));
+ m1 = nextpan(t);
+ m2 = swapchan(m1);
+ v1 = nextvol(t);
+ v2 = nextvol2(t);
+ s1 = soundmod(s1, m1);
+ s2 = soundmod(s2, m2);
+ s1 = soundmod(s1, v1);
+ s2 = soundmod(s2, v2);
+ s1 = soundmix(s1, s2);
+ b3 = nextdrop(t);
+ s3 = audiotosound(bbtoaudio(b3));
+ s3 = soundmix(s3, s1);
+ s3.l *= 4.0/3.0; /* normalize, as max(s3)≈0.749999 due to panning phase */
+ s3.r *= 4.0/3.0;
+ a = soundtoaudio(s3);
+ if(Bwrite(&bfile, &a.l, sizeof(a.l)) < 0)
+ sysfatal("Bwrite failed!");
+ if(Bwrite(&bfile, &a.r, sizeof(a.r)) < 0)
+ sysfatal("Bwrite failed!");
+ }
+
+ exits(nil);
+}
A => bb/7.c +51 -0
@@ 1,51 @@
+/* Amavect!
+ * Collatz Conjecture
+ * to play: 6.out >/dev/audio
+ * (turn down your volume)
+ */
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+/* unnecessary but whatever */
+short
+vtos(uvlong v)
+{
+ return (short)(v&0xFFFF);
+}
+
+/* insert bytebeat formula here */
+uvlong
+next(uvlong t)
+{
+ if(t % 2 == 0)
+ return t / 2;
+ else
+ return 3 * t + 1;
+}
+
+void
+main(void)
+{
+ uvlong t, u;
+ uvlong x, y;
+ short s, s2;
+ Biobuf bfile;
+
+ if(Binit(&bfile, 1, OWRITE) == Beof)
+ sysfatal("Binit failed!");
+
+ u = 1;
+ for(t = 1;; t = next(t)){
+ if(t == 1)
+ t = u++;
+ x = t;
+ y = t;
+ s = vtos(x);
+ s2 = vtos(y);
+ if(Bwrite(&bfile, &s, sizeof(s)) < 0)
+ sysfatal("Bwrite failed!");
+ if(Bwrite(&bfile, &s2, sizeof(s)) < 0)
+ sysfatal("Bwrite failed!");
+ }
+}
A => bb/8.c +46 -0
@@ 1,46 @@
+/* orig by pete */
+/* 44.1 kHz, stereo, signed 16-bit */
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+/* unnecessary but whatever */
+short
+vtos(uvlong v)
+{
+ return (short)(v&0xFFFF);
+}
+
+uvlong
+next(uvlong t)
+{
+ return ((((t>>2)&0xff)^0x99) * ((t|(t>>10))&0xff)) |
+ (((t<<4)&(1|(~t)))) +
+ ((t + (t>>8) + (t>>16) + (t>>24)) /
+ (1|((t>>17) &
+ (((t>>((((t>>17)&0xf)^0x4)^(~(t>>12)&0xf)))%42)*0x7ff))))
+ /**/;
+}
+
+void
+main(void)
+{
+ uvlong t;
+ uvlong x, y;
+ short s, s2;
+ Biobuf bfile;
+
+ if(Binit(&bfile, 1, OWRITE) == Beof)
+ sysfatal("Binit failed!");
+
+ for(t = 1;; t++){
+ x = next(t);
+ y = x;
+ s = vtos(x);
+ s2 = vtos(y);
+ if(Bwrite(&bfile, &s, sizeof(s)) < 0)
+ sysfatal("Bwrite failed!");
+ if(Bwrite(&bfile, &s2, sizeof(s)) < 0)
+ sysfatal("Bwrite failed!");
+ }
+}
A => bb/9.c +42 -0
@@ 1,42 @@
+/* orig by pete */
+/* 44.1 kHz, stereo, signed 16-bit */
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+/* unnecessary but whatever */
+short
+vtos(uvlong v)
+{
+ return (short)(v&0xFFFF);
+}
+
+uvlong
+next(uvlong t)
+{
+ return ((t>>20)+((t<<5)|(t>>2))) |((((0x81ca)&(0x83e9e97be99393e9LL>>(4*(((t>>14)-(t>>18))%16))))*(t<<15))/44100);
+
+}
+
+void
+main(void)
+{
+ uvlong t;
+ uvlong x, y;
+ short s, s2;
+ Biobuf bfile;
+
+ if(Binit(&bfile, 1, OWRITE) == Beof)
+ sysfatal("Binit failed!");
+
+ for(t = 1;; t++){
+ x = next(t);
+ y = x;
+ s = vtos(x);
+ s2 = vtos(y);
+ if(Bwrite(&bfile, &s, sizeof(s)) < 0)
+ sysfatal("Bwrite failed!");
+ if(Bwrite(&bfile, &s2, sizeof(s)) < 0)
+ sysfatal("Bwrite failed!");
+ }
+}
A => bb/mkfile +6 -0
@@ 1,6 @@
+</$objtype/mkfile
+
+default:V:
+ echo 'usage: mk $O.0, mk $O.1, ...'
+
+</sys/src/cmd/mkmany
A => bb/p1.c +112 -0
@@ 1,112 @@
+/* Amavect!
+ * Quick PM synthesis demo.
+ * echo 'master 70' >/dev/volume
+ * 6.out >/dev/audio
+ */
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+#define SAMPLERATE 44100
+double prate = 1 / (double)SAMPLERATE;
+uvlong srate = SAMPLERATE;
+
+short dtos(double d);
+
+short
+dtos(double d)
+{
+ short s;
+ if(d > 1.0 || d < -1.0)
+ sysfatal("no do dat pls");
+ s = (short)(d*32767);
+ return s;
+}
+
+double osc1t = 0.0;
+
+double
+osc1(double p, double phi, double amt)
+{
+ double out = cos(2*PI*(p*osc1t) + amt*phi);
+ osc1t += prate;
+ return out;
+}
+
+double osc2t = 0.0;
+
+double
+osc2(double p, double phi, double amt)
+{
+ double out = cos(2*PI*(p*osc2t) + amt*phi);
+ osc2t += prate;
+ return out;
+}
+
+double osc3t = 0.0;
+
+double
+osc3(double p, double phi, double amt)
+{
+ double out = cos(2*PI*(p*osc3t) + amt*phi);
+ osc3t += prate;
+ return out;
+}
+
+double env1t = 0.0;
+double
+env1(uchar trig)
+{
+ double r = 0.0;
+ if(trig != 0)
+ env1t = 0.0;
+ if(env1t >= 3.0)
+ r = 0.0;
+ else if(env1t >= 0.0)
+ r = 1.0-env1t/3;
+ env1t += prate;
+ return r;
+}
+
+double env2t = 0.0;
+double
+env2(uchar trig)
+{
+ double r = 0.0;
+ if(trig != 0)
+ env2t = 0.0;
+ if(env2t >= 2.0)
+ r = 0.0;
+ else if(env2t >= 0.0)
+ r = 1.0-env2t/2;
+ env2t += prate;
+ return r;
+}
+
+void
+main(void)
+{
+ uvlong t;
+ uchar trig;
+ double x, y, amt1, amt2;
+ short s, s2;
+ Biobuf bfile;
+
+ if(Binit(&bfile, 1, OWRITE) == Beof)
+ sysfatal("Binit failed!");
+
+ for(t = 0;; t++){
+ trig = (t%(4*srate)) == 0;
+ amt1 = env1(trig);
+ amt2 = env2(trig);
+ x = osc1(200, osc2(200,0,0)*amt2, 10000)*amt1;
+ y = x;
+ s = dtos(x);
+ s2 = dtos(y);
+ if(Bwrite(&bfile, &s, sizeof(s)) < 0)
+ sysfatal("Bwrite failed!");
+ if(Bwrite(&bfile, &s2, sizeof(s)) < 0)
+ sysfatal("Bwrite failed!");
+ }
+ exits(nil);
+}
A => bb/p2.c +152 -0
@@ 1,152 @@
+/* Amavect!
+ * More complex PM synthesis + vibrato demo.
+ * Uses structs to represent Oscs and ADSR envelopes.
+ * Structs and funcs could be moved to a lib.
+ * don't blow your ears: echo 'master 80' >/dev/volume
+ * 6.out >/dev/audio
+ */
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+short dtos(double d);
+
+/* Linear ADSR envelope */
+typedef struct Adsr Adsr;
+struct Adsr {
+ int on; /* on/off flag */
+ double t; /* time */
+ double a; /* attack length */
+ double d; /* decay length */
+ double s; /* sustain volume, [0.0, 1.0] */
+ double r; /* release length */
+ double amp; /* current amplitude */
+};
+
+/* Generic oscillator struct */
+typedef struct Osc Osc;
+struct Osc {
+ double ω; /* pitch, in Hz */
+ double θ; /* angle, in turns */
+ double φ; /* phase shift, in turns */
+ double (*wave)(Osc*); /* -1.0 <= wave(Osc) <= 1.0 */
+ double amp; /* current amplitude */
+};
+
+enum{
+ srate = 44100, /* sample rate */
+ prate = 1 / (double)srate, /* period rate */
+};
+
+short
+dtos(double d)
+{
+ short s;
+ if(d > 1.0 || d < -1.0)
+ sysfatal("no do dat pls");
+ s = (short)(d*32767);
+ return s;
+}
+
+/* not gonna prevent you from being stupid! */
+Adsr
+adsrnew(double a, double d, double s, double r)
+{
+ Adsr adsr;
+ adsr.on = 0;
+ adsr.a = a;
+ adsr.d = d;
+ adsr.s = s;
+ adsr.r = r;
+ adsr.t = r;
+ return adsr;
+}
+
+void
+adsrnext(Adsr *adsr, double Δt, int trig)
+{
+ double a, d, s, r;
+ a = adsr->a;
+ d = adsr->d;
+ s = adsr->s;
+ r = adsr->r;
+ if(trig == 1){
+ adsr->t = 0.0;
+ adsr->on = adsr->on ? 0 : 1;
+ }
+ if(adsr->on == 1){
+ if(adsr->t < a)
+ adsr->amp = adsr->t / a;
+ else if(adsr->t < a+d)
+ adsr->amp = (1 - (1 - s)*(adsr->t - a)/d);
+ else
+ adsr->amp = s;
+ } else{
+ if(adsr->t < r)
+ adsr->amp = s * (1 - adsr->t/r);
+ else
+ adsr->amp = 0;
+ }
+ adsr->t += Δt;
+}
+
+void
+oscnext(Osc *osc, double Δt)
+{
+ osc->amp = osc->wave(osc);
+ osc->θ += Δt * osc->ω;
+}
+
+double
+oscsine(Osc *osc)
+{
+ return sin(2*PI*(osc->θ + osc->φ));
+}
+
+double
+oscsaw(Osc *osc)
+{
+ double a = osc->θ + osc->φ;
+ return a - floor(a);
+}
+
+void
+main(void)
+{
+ uvlong t;
+ uchar trig;
+ Adsr env1, env2;
+ Osc osc1, osc2;
+ short s, s2;
+ Biobuf bfile;
+
+ if(Binit(&bfile, 1, OWRITE) == Beof)
+ sysfatal("Binit failed!");
+
+ env1 = adsrnew(1,1,0.5,1);
+ env2 = adsrnew(1,1,0.5,1);
+ osc1.wave = oscsine;
+ osc2.wave = oscsine;
+ osc1.ω = 200;
+ osc2.ω = 200;
+
+ for(t = 0;; t++){
+ trig = (t%(4*srate)) == 0;
+ adsrnext(&env1, prate, trig);
+ adsrnext(&env2, prate, trig);
+ oscnext(&osc2, prate);
+ osc2.ω = 200 + 3*sin(3*2*PI*t*prate);
+ osc1.ω = 200 + 3*sin(3*2*PI*t*prate);
+ osc1.φ = osc2.amp * env2.amp * 3;
+ oscnext(&osc1, prate);
+
+ //print("%f, %f %f %f\n", osc1.amp, osc2.amp, env1.amp, env2.amp);
+
+ s = dtos(osc1.amp*env1.amp);
+ s2 = dtos(osc1.amp*env1.amp);
+ if(Bwrite(&bfile, &s, sizeof(s)) < 0)
+ sysfatal("Bwrite failed!");
+ if(Bwrite(&bfile, &s2, sizeof(s)) < 0)
+ sysfatal("Bwrite failed!");
+ }
+}
A => bb/p3.c +170 -0
@@ 1,170 @@
+/* Amavect!
+ * More complex PM synthesis + vibrato demo.
+ * Uses structs to represent Oscs and ADSR envelopes.
+ * Structs and funcs could be moved to a lib.
+ * don't blow your ears: echo 'master 80' >/dev/volume
+ * 6.out >/dev/audio
+ */
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+short dtos(double d);
+
+/* Linear ADSR envelope */
+typedef struct Adsr Adsr;
+struct Adsr {
+ int on; /* on/off flag */
+ double t; /* time */
+ double a; /* attack length */
+ double d; /* decay length */
+ double s; /* sustain volume, [0.0, 1.0] */
+ double r; /* release length */
+ double amp; /* current amplitude */
+};
+
+/* Generic oscillator struct */
+typedef struct Osc Osc;
+struct Osc {
+ double ω; /* pitch, in Hz */
+ double θ; /* angle, in turns */
+ double φ; /* phase shift, in turns */
+ double (*wave)(Osc*); /* -1.0 <= wave(Osc) <= 1.0 */
+ double amp; /* current amplitude */
+};
+
+enum{
+ srate = 44100, /* sample rate */
+ prate = 1 / (double)srate, /* period rate */
+};
+
+short
+dtos(double d)
+{
+ short s;
+ if(d > 1.0 || d < -1.0)
+ sysfatal("no do dat pls");
+ s = (short)(d*32767);
+ return s;
+}
+
+/* not gonna prevent you from being stupid! */
+Adsr
+adsrnew(double a, double d, double s, double r)
+{
+ Adsr adsr;
+ adsr.on = 0;
+ adsr.a = a;
+ adsr.d = d;
+ adsr.s = s;
+ adsr.r = r;
+ adsr.t = r;
+ return adsr;
+}
+
+void
+adsrnext(Adsr *adsr, double Δt, int trig)
+{
+ double a, d, s, r;
+ a = adsr->a;
+ d = adsr->d;
+ s = adsr->s;
+ r = adsr->r;
+ if(trig == 1){
+ adsr->t = 0.0;
+ adsr->on = adsr->on ? 0 : 1;
+ }
+ if(adsr->on == 1){
+ if(adsr->t < a)
+ adsr->amp = adsr->t / a;
+ else if(adsr->t < a+d)
+ adsr->amp = (1 - (1 - s)*(adsr->t - a)/d);
+ else
+ adsr->amp = s;
+ } else{
+ if(adsr->t < r)
+ adsr->amp = s * (1 - adsr->t/r);
+ else
+ adsr->amp = 0;
+ }
+ adsr->t += Δt;
+}
+
+void
+oscnext(Osc *osc, double Δt)
+{
+ osc->amp = osc->wave(osc);
+ osc->θ += Δt * osc->ω;
+}
+
+double
+oscsine(Osc *osc)
+{
+ return sin(2*PI*(osc->θ + osc->φ));
+}
+
+double
+oscsaw(Osc *osc)
+{
+ double a = osc->θ + osc->φ;
+ return a - floor(a);
+}
+
+void
+main(void)
+{
+ uvlong t;
+ uint trig, trig2;
+ Adsr env1, env2;
+ Osc osc1, osc2, osc3, osc4, osc5, osc6;
+ double mix;
+ short s, s2;
+ Biobuf bfile;
+
+ if(Binit(&bfile, 1, OWRITE) == Beof)
+ sysfatal("Binit failed!");
+
+ env1 = adsrnew(0.05, 1.0, 0.0, 0.0);
+ env2 = adsrnew(0.05, 1.0, 0.0, 0.0);
+ osc1.wave = oscsaw;
+ osc2.wave = oscsaw;
+ osc3.wave = oscsaw;
+ osc4.wave = oscsaw;
+ osc5.wave = oscsaw;
+ osc6.wave = oscsaw;
+ osc1.ω = 302;
+ osc2.ω = 298;
+ osc3.ω = 300;
+ osc4.ω = 452;
+ osc5.ω = 448;
+ osc6.ω = 450;
+
+ for(t = 0;; t++){
+ trig = (t%(1*srate)) == 0;
+ trig2 = ((t + srate/2)%(1*srate)) == 0;
+ adsrnext(&env1, prate, trig);
+ adsrnext(&env2, prate, trig2);
+ osc1.ω = 298 + 3*sin(3*2*PI*t*prate);
+ osc2.ω = 302 + 3*sin(3*2*PI*t*prate);
+ osc3.ω = 300 + 3*sin(3*2*PI*t*prate);
+ osc4.ω = 452 + 3*sin(3*2*PI*t*prate);
+ osc5.ω = 448 + 3*sin(3*2*PI*t*prate);
+ osc6.ω = 450 + 3*sin(3*2*PI*t*prate);
+ oscnext(&osc1, prate);
+ oscnext(&osc2, prate);
+ oscnext(&osc3, prate);
+ oscnext(&osc4, prate);
+ oscnext(&osc5, prate);
+ oscnext(&osc6, prate);
+
+ mix = (env1.amp * (osc1.amp + osc2.amp + osc3.amp)
+ + env2.amp * (osc4.amp + osc5.amp + osc6.amp)) / 6.0;
+
+ s = dtos(mix);
+ s2 = s;
+ if(Bwrite(&bfile, &s, sizeof(s)) < 0)
+ sysfatal("Bwrite failed!");
+ if(Bwrite(&bfile, &s2, sizeof(s)) < 0)
+ sysfatal("Bwrite failed!");
+ }
+}
A => bb/p4.c +260 -0
@@ 1,260 @@
+/* Amavect!
+ * Synth loop!!!!
+ * Filters + preliminary resonance.
+ * Resonance needs better control over resonant frequency.
+ * For some reason, changing resonance amount changes the resonant frequency.
+ * Thus, resfilter() needs a new algorithm.
+ * don't blow your ears: echo 'master 90' >/dev/volume
+ * 6.out >/dev/audio
+ */
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+short dtos(double d);
+
+/* Linear ADSR envelope */
+typedef struct Adsr Adsr;
+struct Adsr {
+ int on; /* on/off flag */
+ double t; /* time */
+ double a; /* attack length */
+ double d; /* decay length */
+ double s; /* sustain volume, [0.0, 1.0] */
+ double r; /* release length */
+ double amp; /* current amplitude */
+};
+
+/* Generic oscillator struct */
+typedef struct Osc Osc;
+struct Osc {
+ double ω; /* pitch, in Hz */
+ double θ; /* angle, in turns */
+ double φ; /* phase shift, in turns */
+ double (*wave)(Osc*); /* -1.0 <= wave(Osc) <= 1.0 */
+ double amp; /* current amplitude */
+};
+
+/* infinite impulse response low pass filter */
+typedef struct Lpf Lpf;
+struct Lpf {
+ double cut; /* cutoff frequency */
+ double amp; /* current amplitude */
+};
+
+/* resonator */
+typedef struct Res Res;
+struct Res {
+ Lpf;
+ double res; /* resonance */
+ double Δamp; /* amplitude change */
+};
+
+enum{
+ srate = 44100, /* sample rate */
+ prate = 1 / (double)srate, /* period rate */
+};
+
+short
+dtos(double d)
+{
+ short s;
+ if(d > 1.0 || d < -1.0)
+ sysfatal("no do dat pls");
+ s = (short)(d*32767);
+ return s;
+}
+
+/* not gonna prevent you from being stupid! */
+Adsr
+adsrnew(double a, double d, double s, double r)
+{
+ Adsr adsr;
+ adsr.on = 0;
+ adsr.a = a;
+ adsr.d = d;
+ adsr.s = s;
+ adsr.r = r;
+ adsr.t = r;
+ return adsr;
+}
+
+void
+adsrnext(Adsr *adsr, double Δt, int trig)
+{
+ double a, d, s, r;
+ a = adsr->a;
+ d = adsr->d;
+ s = adsr->s;
+ r = adsr->r;
+ if(trig == 1){
+ adsr->t = 0.0;
+ adsr->on = adsr->on ? 0 : 1;
+ }
+ if(adsr->on == 1){
+ if(adsr->t < a)
+ adsr->amp = adsr->t / a;
+ else if(adsr->t < a+d)
+ adsr->amp = (1 - (1 - s)*(adsr->t - a)/d);
+ else
+ adsr->amp = s;
+ } else{
+ if(adsr->t < r)
+ adsr->amp = s * (1 - adsr->t/r);
+ else
+ adsr->amp = 0;
+ }
+ adsr->t += Δt;
+}
+
+void
+oscnext(Osc *osc, double Δt)
+{
+ osc->amp = osc->wave(osc);
+ osc->θ += Δt * osc->ω;
+}
+
+double
+oscsine(Osc *osc)
+{
+ return sin(2*PI*(osc->θ + osc->φ));
+}
+
+double
+oscsaw(Osc *osc)
+{
+ double a = osc->θ + osc->φ;
+ return a - floor(a);
+}
+
+double
+oscnoise(Osc*)
+{
+ return frand();
+}
+
+void
+lpffilter(Lpf *lpf, double in, double Δt)
+{
+ double rc, α;
+ rc = 1 / (2 * PI * lpf->cut); /* infinity is useful! */
+ α = Δt / (Δt + rc);
+ lpf->amp = α * in + (1-α) * lpf->amp;
+}
+
+void
+resfilter(Res *res, double in, double Δt)
+{
+ double rc, α;
+ rc = 1 / (2 * PI * res->cut); /* infinity is useful! */
+ α = Δt / (Δt + rc);
+ res->Δamp += α * (in - res->amp);
+ res->amp += res->res * res->Δamp + (1 - res->res) * α * (in - res->amp);
+}
+
+void
+main(void)
+{
+ uvlong t;
+ uint trig, trig2, trigkick, trighat, trigsn;
+ Adsr env1, env2, env3, env4, envkick, envhat, envsn1ω, envsn1, envsn2;
+ Osc osc1, osc2, osc3, osc4, osc5, osc6, lfo1, osckick, oschat, oscsn1, oscsn2;
+ Lpf lpfhat, lpfsnare;
+ Res rlpf1, rlpf2;
+ double mix, mix1, mix2, mix3, mix4, mix5, mix6, mix7;
+ short s, s2;
+ Biobuf bfile;
+
+ /* disable FPZDIV, allow div by 0 */
+ setfcr(FPPDBL|FPRNR|FPINVAL|FPOVFL);
+
+ if(Binit(&bfile, 1, OWRITE) == Beof)
+ sysfatal("Binit failed!");
+
+ env1 = adsrnew(0.05, 0.2, 0.0, 0.0);
+ env2 = adsrnew(0.05, 0.2, 0.0, 0.0);
+ env3 = adsrnew(0.05, 0.05, 0.05, 0.1);
+ env4 = adsrnew(0.05, 0.05, 0.05, 0.1);
+ envkick = adsrnew(0.0, 0.05, 0.0, 0.0);
+ envhat = adsrnew(0.0, 0.1, 0.0, 0.0);
+ envsn1ω = adsrnew(0.0, 0.05, 0.0, 0.0);
+ envsn1 = adsrnew(0.0, 0.1, 0.0, 0.0);
+ envsn2 = adsrnew(0.0, 0.15, 0.0, 0.0);
+ osc1.wave = oscsaw;
+ osc2.wave = oscsaw;
+ osc3.wave = oscsaw;
+ osc4.wave = oscsaw;
+ osc5.wave = oscsaw;
+ osc6.wave = oscsaw;
+ lfo1.wave = oscsine;
+ osckick.wave = oscsine;
+ oschat.wave = oscnoise;
+ oscsn1.wave = oscsine;
+ oscsn2.wave = oscnoise;
+ osc1.ω = 79.43;
+ osc2.ω = 80;
+ osc3.ω = 80.55;
+ osc4.ω = 119.47;
+ osc5.ω = 120;
+ osc6.ω = 120.57;
+ lfo1.ω = 0.20;
+ lpfhat.cut = 5000;
+ lpfsnare.cut = 800;
+ rlpf1.res = 0.5;
+ rlpf2.res = 0.5;
+
+ for(t = 0;; t++){
+ trigkick = ((t)%(srate/2)) == 0 || ((t+1)%(srate/2)) == 0;
+ trighat = ((t-srate/4)%(srate/2)) == 0 || ((t-3*srate/8)%(srate/2)) == 0;
+ trigsn = ((t+srate/2)%(srate)) == 0 || ((t+srate/4)%(srate)) == 0;
+ trig = ((t)%(srate/2)) == 0 || ((t-srate/8+1)%(srate/2)) == 0
+ || ((t-srate/8)%(srate/2)) == 0 || ((t-srate/4+1)%(srate/2)) == 0
+ || ((t-srate/4)%(srate/2)) == 0 || ((t-3*srate/8+1)%(srate/2)) == 0;
+ trig2 = ((t-3*srate/8)%(srate/2)) == 0 || ((t+1)%(srate/2)) == 0;
+ adsrnext(&env1, prate, trig);
+ adsrnext(&env2, prate, trig2);
+ adsrnext(&env3, prate, trig);
+ adsrnext(&env4, prate, trig2);
+ adsrnext(&envkick, prate, trigkick);
+ adsrnext(&envhat, prate, trighat);
+ adsrnext(&envsn1ω, prate, trigsn);
+ adsrnext(&envsn1, prate, trigsn);
+ adsrnext(&envsn2, prate, trigsn);
+ osckick.ω = 200 * envkick.amp + 40;
+ oscsn1.ω = 100 * envsn1ω.amp + 200;
+ oscnext(&osc1, prate);
+ oscnext(&osc2, prate);
+ oscnext(&osc3, prate);
+ oscnext(&osc4, prate);
+ oscnext(&osc5, prate);
+ oscnext(&osc6, prate);
+ oscnext(&lfo1, prate);
+ oscnext(&osckick, prate);
+ oscnext(&oschat, prate);
+ oscnext(&oscsn1, prate);
+ oscnext(&oscsn2, prate);
+ rlpf1.cut = (2500 + 2000*lfo1.amp) * env3.amp + 100;
+ rlpf2.cut = (2500 + 2000*lfo1.amp) * env4.amp + 100;
+
+ mix1 = env1.amp * (osc1.amp + osc2.amp + osc3.amp) / 3.0;
+ mix2 = env2.amp * (osc4.amp + osc5.amp + osc6.amp) / 3.0;
+ mix3 = envkick.amp * osckick.amp;
+ mix4 = envhat.amp * oschat.amp;
+ mix5 = envsn2.amp * oscsn2.amp;
+ resfilter(&rlpf1, mix1, prate);
+ resfilter(&rlpf2, mix2, prate);
+ lpffilter(&lpfhat, mix4, prate);
+ lpffilter(&lpfsnare, mix5, prate);
+ mix6 = mix4 - lpfhat.amp; /* high pass filter */
+ mix7 = 0.3*envsn1.amp * oscsn1.amp + 0.7*(mix5-lpfsnare.amp);
+
+ mix = (rlpf1.amp + rlpf2.amp + 0.8*mix3 + 0.6*mix6 + 0.6*mix7)/3.6;
+ //mix = mix7;
+ s = dtos(mix);
+ s2 = s;
+ if(Bwrite(&bfile, &s, sizeof(s)) < 0)
+ sysfatal("Bwrite failed!");
+ if(Bwrite(&bfile, &s2, sizeof(s)) < 0)
+ sysfatal("Bwrite failed!");
+ }
+}
A => mkfile +5 -0
@@ 1,5 @@
+</$objtype/mkfile
+
+TARG=xenihak pianoJI piano32
+
+</sys/src/cmd/mkmany
A => piano32.c +239 -0
@@ 1,239 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <mouse.h>
+#include <keyboard.h>
+#include <thread.h>
+
+enum{
+ SAW = 0, TRI, SIN, SQ, WAVES,
+ WAV = 128,
+ RATE = 44100,
+ BUF = RATE * 4 / 50,
+ OCTS = 9,
+ NOTES = OCTS * 12,
+ SHARPS = 1354, /* 0b010101001010 */
+ WWD = 48,
+ WHT = 180,
+ BWD = 28,
+ BHT = 120,
+};
+
+char *waveforms[] = {"sawtooth", "triangle", "sine", "square", nil};
+Menu b2 = {waveforms, nil, 0};
+char *name = "CCDDEFFGGAAB";
+char *key = "\t1q2we4r5t6yu8i9op-[=]\b\\";
+int oct = 4, vol = 63, wav[WAVES][WAV], wavn;
+char on[NOTES];
+u32int θ[NOTES], Δ[NOTES];
+Rectangle w[14], b[10];
+int woff[14] = {0,2,4,5,7,9,11,12,14,16,17,19,21,23};
+int boff[10] = {1,3,6,8,10,13,15,18,20,22};
+Image *down;
+Rune info[128];
+Point infop;
+
+void
+redraw(void)
+{
+ int i;
+ Rune *r;
+
+ draw(screen, screen->r, down, nil, ZP);
+ for(i = 0; i < nelem(w); i++){
+ draw(screen, w[i], on[12*oct+woff[i]]?down:display->white, nil, ZP);
+ border(screen, w[i], 1, display->black, ZP);
+ }
+ for(i = 0; i < nelem(b); i++){
+ draw(screen, b[i], on[12*oct+boff[i]]?down:display->black, nil, ZP);
+ border(screen, b[i], 1, display->black, ZP);
+ }
+ for(i = 0, r = info; i < oct; i++)
+ *r++ = '-';
+ *r++ = '0' + i++;
+ *r++ = '0' + i;
+ while(++i < OCTS)
+ *r++ = '-';
+ *r++ = ' ';
+ for(i = 0; i < NOTES; i++)
+ if(on[i]){
+ *r++ = name[i % 12];
+ if(SHARPS & 1 << i % 12)
+ *r++ = 0x266e; /* ♮ */
+ *r++ = i / 12 + '0';
+ *r++ = ' ';
+ if(r - info > nelem(info) - 5)
+ break;
+ }
+ *r = '\0';
+ runestring(screen, infop, display->black, ZP, font, info);
+ flushimage(display, 1);
+}
+
+void
+rthread(void *arg)
+{
+ Mousectl *m;
+ Point p;
+ int fd, i;
+
+ for(m = arg;;){
+ recvul(m->resizec);
+ if(getwindow(display, Refnone) < 0)
+ sysfatal("getwindow: %r");
+ if((Dx(screen->r) != nelem(w) * WWD
+ || Dy(screen->r) != WHT + font->height)
+ &&(fd = open("/dev/wctl", OWRITE)) >= 0){
+ fprint(fd, "resize -dx %d -dy %d",
+ nelem(w) * WWD + 2 * Borderwidth,
+ WHT + font->height + 2 * Borderwidth);
+ close(fd);
+ }
+ for(i = 0, p = screen->r.min; i < nelem(w); i++, p.x += WWD)
+ w[i] = rectaddpt(Rect(0, 0, WWD, WHT), p);
+ for(i = nelem(b), p.x -= WWD + BWD / 2; i--; p.x -= WWD){
+ b[i] = rectaddpt(Rect(0, 0, BWD, BHT), p);
+ if(i % 5 == 0 || i % 5 == 2)
+ p.x -= WWD;
+ }
+ infop = Pt(screen->r.min.x, screen->r.max.y - font->height);
+ redraw();
+ }
+}
+
+void
+mthread(void *arg)
+{
+ Mousectl *m;
+ int i;
+
+ for(m = arg;;){
+ recv(m->c, m);
+ switch(m->buttons){
+ default:
+ continue;
+ case 1:
+ for(i = 0; i < nelem(b); i++)
+ if(ptinrect(m->xy, b[i])){
+ on[oct*12+boff[i]] |= 2;
+ goto draw;
+ }
+ for(i = 0; i < nelem(w); i++)
+ if(ptinrect(m->xy, w[i])){
+ on[oct*12+woff[i]] |= 2;
+ break;
+ }
+ break;
+ case 2:
+ i = menuhit(2, m, &b2, nil);
+ if(i >= 0 && i < WAVES)
+ wavn = i;
+ break;
+ case 4:
+ for(i = 0; i < nelem(b); i++)
+ if(ptinrect(m->xy, b[i])){
+ on[oct*12+boff[i]] &= 1;
+ goto draw;
+ }
+ for(i = 0; i < nelem(w); i++)
+ if(ptinrect(m->xy, w[i])){
+ on[oct*12+woff[i]] &= 1;
+ break;
+ }
+ break;
+ }
+draw: redraw();
+ }
+}
+
+void
+kproc(void *)
+{
+ int fd, n, i;
+ char buf[128], *p;
+
+ if((fd = open("/dev/kbd", OREAD)) < 0)
+ sysfatal("open: %r");
+ for(;;){
+ if((n = read(fd, buf, sizeof(buf) - 1)) < 0)
+ sysfatal("read: %r");
+ buf[n] = '\0';
+ for(p = buf; p - buf < n;){
+ if(*p++ != 'c'){
+ if(strchr(p, Kdel)){
+ close(fd);
+ threadexitsall(nil);
+ }
+ if(strchr(p, 'a') && oct < OCTS - 2)
+ oct++;
+ if(strchr(p, 'z') && oct)
+ oct--;
+ if(strchr(p, 's') && vol < 126)
+ vol += 7;
+ if(strchr(p, 'x') && vol > 6)
+ vol -= 7;
+ for(i = 0; i < strlen(key); i++){
+ if(strchr(p, key[i]))
+ on[12 * oct + i] |= 1;
+ else
+ on[12 * oct + i] &= 2;
+ }
+ redraw();
+ }
+ while(*p++)
+ ;
+ }
+ }
+}
+
+void
+threadmain(int,char *argv[])
+{
+ Mousectl *m;
+ int fd, i, s;
+ uchar buf[BUF], *p;
+
+ for(i = 0; i < WAV / 2; i++){
+ wav[SAW][i] = 64 - 2 * 64 * i / WAV;
+ wav[TRI][i] = 64 - 64 * i * 4 / WAV;
+ wav[SIN][i] = 64 * sin(2 * PI * i / WAV);
+ wav[SQ][i] = -64;
+ }
+ for(; i < WAV; i++){
+ wav[SAW][i] = 64 - 2 * 64 * i / WAV;
+ wav[TRI][i] = 64 * (i - WAV / 2) * 4 / WAV - 64;
+ wav[SIN][i] = 64 * sin(2 * PI * i / WAV);
+ wav[SQ][i] = 64;
+ }
+ for(i = 0; i < NOTES; i++)
+ Δ[i] = (u32int)((440 * pow(2, 32.0)) * pow(2, (i - 57) / 12.0) / RATE);
+ if((fd = open("/dev/audio", OWRITE)) < 0)
+ sysfatal("open: %r");
+ if(initdraw(nil, nil, argv0 = argv[0]) < 0)
+ sysfatal("initdraw: %r");
+ if((down = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DPalegreygreen)) == nil)
+ sysfatal("allocimage: %r");
+ if((m = initmouse(nil, screen)) == nil)
+ sysfatal("initmouse: %r");
+ if(threadcreate(rthread, m, mainstacksize) < 0)
+ sysfatal("threadcreate: %r");
+ if(threadcreate(mthread, m, mainstacksize) < 0)
+ sysfatal("threadcreate: %r");
+ if(proccreate(kproc, nil, mainstacksize) < 0)
+ sysfatal("proccreate: %r");
+ sendul(m->resizec, 1);
+ for(;;){
+ for(p = buf; p - buf < BUF; p += 4){
+ for(i = 0, s = 0; i < NOTES; i++)
+ if(on[i])
+ s += wav[wavn][(θ[i] += Δ[i]) >> 25];
+ s *= vol;
+ p[0] = p[2] = s;
+ p[1] = p[3] = s >> 8;
+ }
+ if(write(fd, buf, BUF) != BUF)
+ break;
+ yield();
+ }
+ close(fd);
+}
A => pianoJI.c +260 -0
@@ 1,260 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <mouse.h>
+#include <keyboard.h>
+#include <thread.h>
+
+enum{
+ SAW = 0, TRI, SIN, SQ, WAVES,
+ WAV = 128,
+ RATE = 44100,
+ BUF = RATE * 4 / 50,
+ OCTS = 9,
+ NOTES = OCTS * 12,
+ SHARPS = 1354, /* 0b010101001010 */
+ WWD = 48,
+ WHT = 180,
+ BWD = 28,
+ BHT = 120,
+};
+
+char *waveforms[] = {"sawtooth", "triangle", "sine", "square", nil};
+Menu b2 = {waveforms, nil, 0};
+char *name = "CCDDEFFGGAAB";
+char *key = "\t1q2we4r5t6yu8i9op-[=]\b\\";
+int oct = 4, vol = 63, wav[WAVES][WAV], wavn;
+char on[NOTES];
+u32int θ[NOTES], Δ[NOTES];
+Rectangle w[14], b[10];
+int woff[14] = {0,2,4,5,7,9,11,12,14,16,17,19,21,23};
+int boff[10] = {1,3,6,8,10,13,15,18,20,22};
+Image *down;
+Rune info[128];
+Point infop;
+
+u32int
+powu32int(u32int x, u32int y)
+{
+ u32int a = 1;
+ for(; y > 0; y--)
+ a *= x;
+ return a;
+}
+
+void
+redraw(void)
+{
+ int i;
+ Rune *r;
+
+ draw(screen, screen->r, down, nil, ZP);
+ for(i = 0; i < nelem(w); i++){
+ draw(screen, w[i], on[12*oct+woff[i]]?down:display->white, nil, ZP);
+ border(screen, w[i], 1, display->black, ZP);
+ }
+ for(i = 0; i < nelem(b); i++){
+ draw(screen, b[i], on[12*oct+boff[i]]?down:display->black, nil, ZP);
+ border(screen, b[i], 1, display->black, ZP);
+ }
+ for(i = 0, r = info; i < oct; i++)
+ *r++ = '-';
+ *r++ = '0' + i++;
+ *r++ = '0' + i;
+ while(++i < OCTS)
+ *r++ = '-';
+ *r++ = ' ';
+ for(i = 0; i < NOTES; i++)
+ if(on[i]){
+ *r++ = name[i % 12];
+ if(SHARPS & 1 << i % 12)
+ *r++ = 0x266e; /* ♮ */
+ *r++ = i / 12 + '0';
+ *r++ = ' ';
+ if(r - info > nelem(info) - 5)
+ break;
+ }
+ *r = '\0';
+ runestring(screen, infop, display->black, ZP, font, info);
+ flushimage(display, 1);
+}
+
+void
+rthread(void *arg)
+{
+ Mousectl *m;
+ Point p;
+ int fd, i;
+
+ for(m = arg;;){
+ recvul(m->resizec);
+ if(getwindow(display, Refnone) < 0)
+ sysfatal("getwindow: %r");
+ if((Dx(screen->r) != nelem(w) * WWD
+ || Dy(screen->r) != WHT + font->height)
+ &&(fd = open("/dev/wctl", OWRITE)) >= 0){
+ fprint(fd, "resize -dx %d -dy %d",
+ nelem(w) * WWD + 2 * Borderwidth,
+ WHT + font->height + 2 * Borderwidth);
+ close(fd);
+ }
+ for(i = 0, p = screen->r.min; i < nelem(w); i++, p.x += WWD)
+ w[i] = rectaddpt(Rect(0, 0, WWD, WHT), p);
+ for(i = nelem(b), p.x -= WWD + BWD / 2; i--; p.x -= WWD){
+ b[i] = rectaddpt(Rect(0, 0, BWD, BHT), p);
+ if(i % 5 == 0 || i % 5 == 2)
+ p.x -= WWD;
+ }
+ infop = Pt(screen->r.min.x, screen->r.max.y - font->height);
+ redraw();
+ }
+}
+
+void
+mthread(void *arg)
+{
+ Mousectl *m;
+ int i;
+
+ for(m = arg;;){
+ recv(m->c, m);
+ switch(m->buttons){
+ default:
+ continue;
+ case 1:
+ for(i = 0; i < nelem(b); i++)
+ if(ptinrect(m->xy, b[i])){
+ on[oct*12+boff[i]] |= 2;
+ goto draw;
+ }
+ for(i = 0; i < nelem(w); i++)
+ if(ptinrect(m->xy, w[i])){
+ on[oct*12+woff[i]] |= 2;
+ break;
+ }
+ break;
+ case 2:
+ i = menuhit(2, m, &b2, nil);
+ if(i >= 0 && i < WAVES)
+ wavn = i;
+ break;
+ case 4:
+ for(i = 0; i < nelem(b); i++)
+ if(ptinrect(m->xy, b[i])){
+ on[oct*12+boff[i]] &= 1;
+ goto draw;
+ }
+ for(i = 0; i < nelem(w); i++)
+ if(ptinrect(m->xy, w[i])){
+ on[oct*12+woff[i]] &= 1;
+ break;
+ }
+ break;
+ }
+draw: redraw();
+ }
+}
+
+void
+kproc(void *)
+{
+ int fd, n, i;
+ char buf[128], *p;
+
+ if((fd = open("/dev/kbd", OREAD)) < 0)
+ sysfatal("open: %r");
+ for(;;){
+ if((n = read(fd, buf, sizeof(buf) - 1)) < 0)
+ sysfatal("read: %r");
+ buf[n] = '\0';
+ for(p = buf; p - buf < n;){
+ if(*p++ != 'c'){
+ if(strchr(p, Kdel)){
+ close(fd);
+ threadexitsall(nil);
+ }
+ if(strchr(p, 'a') && oct < OCTS - 2)
+ oct++;
+ if(strchr(p, 'z') && oct)
+ oct--;
+ if(strchr(p, 's') && vol < 126)
+ vol += 7;
+ if(strchr(p, 'x') && vol > 6)
+ vol -= 7;
+ for(i = 0; i < strlen(key); i++){
+ if(strchr(p, key[i]))
+ on[12 * oct + i] |= 1;
+ else
+ on[12 * oct + i] &= 2;
+ }
+ redraw();
+ }
+ while(*p++)
+ ;
+ }
+ }
+}
+
+void
+threadmain(int,char *argv[])
+{
+ Mousectl *m;
+ int fd, i, s;
+ uchar buf[BUF], *p;
+
+ for(i = 0; i < WAV / 2; i++){
+ wav[SAW][i] = 64 - 2 * 64 * i / WAV;
+ wav[TRI][i] = 64 - 64 * i * 4 / WAV;
+ wav[SIN][i] = 64 * sin(2 * PI * i / WAV);
+ wav[SQ][i] = -64;
+ }
+ for(; i < WAV; i++){
+ wav[SAW][i] = 64 - 2 * 64 * i / WAV;
+ wav[TRI][i] = 64 * (i - WAV / 2) * 4 / WAV - 64;
+ wav[SIN][i] = 64 * sin(2 * PI * i / WAV);
+ wav[SQ][i] = 64;
+ }
+ Δ[0] = ((1<<30) / RATE * 1/1) << 5;
+ Δ[1] = ((1<<30) / RATE * 17/16) << 5;
+ Δ[2] = ((1<<30) / RATE * 9/8) << 5;
+ Δ[3] = ((1<<30) / RATE * 19/16) << 5;
+ Δ[4] = ((1<<30) / RATE * 5/4) << 5;
+ Δ[5] = ((1<<30) / RATE * 21/16) << 5;
+ Δ[6] = ((1<<30) / RATE * 11/8) << 5;
+ Δ[7] = ((1<<30) / RATE * 3/2) << 5;
+ Δ[8] = ((1<<30) / RATE * 13/8) << 5;
+ Δ[9] = ((1<<30) / RATE * 27/16) << 5;
+ Δ[10] = ((1<<30) / RATE * 7/4) << 5;
+ Δ[11] = ((1<<30) / RATE * 15/8) << 5;
+ for(i = 0; i < NOTES; i++)
+ Δ[i] = Δ[i%12] * powu32int(2,i/12);
+ if((fd = open("/dev/audio", OWRITE)) < 0)
+ sysfatal("open: %r");
+ if(initdraw(nil, nil, argv0 = argv[0]) < 0)
+ sysfatal("initdraw: %r");
+ if((down = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DPalegreygreen)) == nil)
+ sysfatal("allocimage: %r");
+ if((m = initmouse(nil, screen)) == nil)
+ sysfatal("initmouse: %r");
+ if(threadcreate(rthread, m, mainstacksize) < 0)
+ sysfatal("threadcreate: %r");
+ if(threadcreate(mthread, m, mainstacksize) < 0)
+ sysfatal("threadcreate: %r");
+ if(proccreate(kproc, nil, mainstacksize) < 0)
+ sysfatal("proccreate: %r");
+ sendul(m->resizec, 1);
+ for(;;){
+ for(p = buf; p - buf < BUF; p += 4){
+ for(i = 0, s = 0; i < NOTES; i++)
+ if(on[i])
+ s += wav[wavn][(θ[i] += Δ[i]) >> 25];
+ s *= vol;
+ p[0] = p[2] = s;
+ p[1] = p[3] = s >> 8;
+ }
+ if(write(fd, buf, BUF) != BUF)
+ break;
+ yield();
+ }
+ close(fd);
+}
A => xenihak.c +206 -0
@@ 1,206 @@
+/* Amavect!
+ * Xenihak
+ * to play: 6.out >/dev/audio
+ * (turn down your volume)
+ */
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+typedef struct Bytebeat Bytebeat;
+typedef struct Sound Sound;
+typedef struct Audio Audio;
+
+/* unsignedlonglongbeat? */
+struct Bytebeat{
+ uvlong l;
+ uvlong r;
+};
+
+/* continuous sounds are to be modelled with precision */
+struct Sound{
+ double l;
+ double r;
+};
+
+/* audio(3) */
+struct Audio{
+ short l;
+ short r;
+};
+
+/* unnecessary but whatever */
+Audio
+bbtoaudio(Bytebeat bb)
+{
+ Audio a;
+ a.l = (short)(bb.l&0xFFFF);
+ a.r = (short)(bb.r&0xFFFF);
+ return a;
+}
+
+Sound
+audiotosound(Audio a)
+{
+ Sound s;
+ s.l = (double)a.l / (1<<15); /* avoid clipping for a.l=-1<<15 */
+ s.r = (double)a.r / (1<<15);
+ return s;
+}
+
+Audio
+soundtoaudio(Sound s)
+{
+ Audio a;
+ a.l = (short)(s.l * ((1<<15) - 1)); /* avoid clipping for s.l=1.0 */
+ a.r = (short)(s.r * ((1<<15) - 1));
+ return a;
+}
+
+Sound
+nextpan(uvlong t)
+{
+ Sound m;
+ m.l = cos(t / (2 * 44100.0));
+ m.r = sin(t / (2 * 44100.0));
+ return m;
+}
+
+Sound
+swapchan(Sound s)
+{
+ double d;
+ d = s.l;
+ s.l = s.r;
+ s.r = d;
+ return s;
+}
+
+Sound
+nextvol(uvlong t)
+{
+ Sound v;
+ v.l = sin(t / 200000.0);
+ v.r = v.l;
+ return v;
+}
+
+Sound
+nextvol2(uvlong t)
+{
+ Sound v;
+ v.l = cos(t / 200000.0);
+ v.r = v.l;
+ return v;
+}
+Sound
+soundmod(Sound s, Sound m)
+{
+ s.l *= m.l;
+ s.r *= m.r;
+ return s;
+}
+
+Sound
+soundmix(Sound s, Sound t)
+{
+ s.l = (s.l + t.l) / 2.0;
+ s.r = (s.r + t.r) / 2.0;
+ return s;
+}
+
+/* insert bytebeat formula here */
+Bytebeat
+next(uvlong t)
+{
+ Bytebeat bb;
+ bb.l = (7*t<<7)&(666666|t>>4) ^ ((19*t<<6)%(1<<16))|(t>>1) ^ (3*t<<9&t>>2)^ (13*t<<10&t>>3);
+ bb.r = bb.l;
+ return bb;
+}
+
+Bytebeat
+next2(uvlong t)
+{
+ Bytebeat bb;
+ bb.l = (17*t<<7)&(666666|t>>7) ^ (11*t<<8&t>>6) ^ (23*t<<9&t>>3);
+ bb.r = bb.l;
+ return bb;
+}
+
+Bytebeat
+nextdrop(uvlong t)
+{
+ Bytebeat bb;
+ uvlong u, s, p, hat, snare, kick, bass, mel;
+
+ hat = ( ((t*t*t)/(t%256 + 1))|( (((t<<1)|(t<<2) + (1<<15))|(t<<2)|(t<<((t<<2)&(t<<3)))|(t<<4)*(t>>13&t>>12)) ) );
+ u = t+(1<<14);
+ s = t+(3<<13);
+ p = (t*1/1)*(((t>>17)+3)%4/3) + (t*3/4)*(((t>>17)+2)%4/3) + (t*7/8)*(((t>>17)+1)%4/3) + (t*15/16)*(((t>>17)+0)%4/3);
+ kick = ( (128*t * ((1<<5)-((t>>8)%(1<<5)))/(1<<4))|( (((t>>1)&((t>>1)+(1<<15)))|t|(t<<1)|(t<<2)|(t<<3)) & (((s>>1)&((s>>1)+(1<<15)))|s|(s<<1)|(s<<2)|(s<<3)) ) );
+ bass = (((1000*t/1001<<6) & (1001*t/1000<<6)) - 1) & (t<<((999*t/998>>1|t>>8)*(t>>13&t>>12)));
+ snare = ( ((t<<8)%666666) ^ ((t<<5)%(1<<16) + 1) ) | ( (u&(u+(1<<15))|(u<<1)|(u<<2)|(u<<3)) );
+ mel = (7*t<<7&t>>2)|(9*t<<7&t>>3)|(19*t<<6&t>>4)|(11*t<<7&t>>5);
+
+ if(t >= 1<<20 && t < (1<<21) - (1<<17)){
+ bb.l = hat;
+ }else if(t >= 1<<21 && t < 1<<22){
+ bb.l = (kick + snare + hat) ^ bass;
+ }else if(t >= 1<<22 && t < (1<<22) + (1<<20)){
+ bb.l = (snare + hat) | mel;
+ }else if(t >= (1<<22) + (1<<20) && t < (3<<21) - (1<<17)){
+ bb.l = hat | mel;
+ }else if(t >= 3<<21 && t < (1<<23) - (1<<17)){
+ bass = (((1000*p/1001<<6) & (1001*p/1000<<6)) - 1) & (t<<((999*t/998>>1|t>>8)*(t>>13&t>>12)));
+ bb.l = (kick + snare + hat) ^ bass;
+ }else if(t >= (1<<23) - (1<<17) && t < 1<<23){
+ bass = (((1000*p/1001<<6) & (1001*p/1000<<6)) - 1) & (t<<((999*t/998>>1|t>>8)*(t>>13&t>>12)));
+ bb.l = (snare + hat) ^ bass;
+ }else{
+ bb.l = 0;
+ }
+ bb.r = bb.l;
+ return bb;
+}
+
+void
+main(void)
+{
+ uvlong t;
+ Bytebeat b1, b2, b3;
+ Audio a;
+ Sound s1, s2, s3, m1, m2, v1, v2;
+ Biobuf bfile;
+
+ if(Binit(&bfile, 1, OWRITE) == Beof)
+ sysfatal("Binit failed!");
+
+ for(t = 0; t < (1<<23) + (1<<20); t++){
+ b1 = next(t);
+ b2 = next2(t);
+ s1 = audiotosound(bbtoaudio(b1));
+ s2 = audiotosound(bbtoaudio(b2));
+ m1 = nextpan(t);
+ m2 = swapchan(m1);
+ v1 = nextvol(t);
+ v2 = nextvol2(t);
+ s1 = soundmod(s1, m1);
+ s2 = soundmod(s2, m2);
+ s1 = soundmod(s1, v1);
+ s2 = soundmod(s2, v2);
+ s1 = soundmix(s1, s2);
+ b3 = nextdrop(t);
+ s3 = audiotosound(bbtoaudio(b3));
+ s3 = soundmix(s3, s1);
+ s3.l *= 4.0/3.0; /* normalize, as max(s3)≈0.749999 due to panning phase */
+ s3.r *= 4.0/3.0;
+ a = soundtoaudio(s3);
+ if(Bwrite(&bfile, &a.l, sizeof(a.l)) < 0)
+ sysfatal("Bwrite failed!");
+ if(Bwrite(&bfile, &a.r, sizeof(a.r)) < 0)
+ sysfatal("Bwrite failed!");
+ }
+
+ exits(nil);
+}