diff --git a/etc/wavpcm/build.sh b/etc/wavpcm/build.sh new file mode 100755 index 0000000..6a61b18 --- /dev/null +++ b/etc/wavpcm/build.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +echo "Formatting.." +clang-format -i wavpcm.c + +echo "Cleaning.." +rm -f ../../bin/wavpcm + +echo "Building.." +mkdir -p ../../bin +cc -std=c89 -DDEBUG -Wall -Wno-unknown-pragmas -Wpedantic -Wshadow -Wextra -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -Wvla -g -Og -fsanitize=address -fsanitize=undefined -lm wavpcm.c -o ../../bin/wavpcm + +echo "Running.." +../../bin/wavpcm + +echo "Done." diff --git a/etc/wavpcm/wavpcm.c b/etc/wavpcm/wavpcm.c new file mode 100644 index 0000000..c9b83f2 --- /dev/null +++ b/etc/wavpcm/wavpcm.c @@ -0,0 +1,63 @@ +#include +#include + +/* +Copyright (c) 2020 Devine Lu Linvega + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE. +*/ + +#define PI 3.14159265358979323846 +#define SAMPLES 256 +#define RATE 1 + +typedef unsigned char Uint8; + +int +clamp(int val, int min, int max) +{ + return (val >= min) ? (val <= max) ? val : max : min; +} + +Uint8 +sinw(int i) +{ + return 0x7f * sin(i * RATE * 2 * PI / SAMPLES); +} + +Uint8 +triw(int i) +{ + if(i < 0x40) + return i * 2; + if(i >= 0xc0) + return (i - 0xc0) * 2 - 0x7f; + return 0x7f - (i - 0x40) * 2; +} + +Uint8 +sqrw(int i) +{ + return ((i * RATE) % 0xff) < 0x80 ? 0x7f : 0x80; +} + +int +main() +{ + int i; + printf("%d:\n\n", SAMPLES); + for(i = 0; i < SAMPLES; ++i) { + if(i % 0x10 == 0) + printf("\n"); + else if(i % 2 == 0) + printf(" "); + printf("%02x", (triw(i) + sinw(i)) / 2); + } + printf("\n\n"); + return 0; +} diff --git a/projects/demos/piano.usm b/projects/demos/piano.usm index 66b7867..4aece31 100644 --- a/projects/demos/piano.usm +++ b/projects/demos/piano.usm @@ -8,6 +8,8 @@ %TOS { #00 SWP } %MOD { DUP2 DIV MUL SUB } +%WAVEFORM { #1000 } + ( devices ) |00 @System [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ] @@ -20,6 +22,7 @@ |70 @Midi [ &vector $2 &channel $1 ¬e $1 &velocity $1 ] |80 @Controller [ &vector $2 &button $1 &key $1 ] |90 @Mouse [ &vector $2 &x $2 &y $2 &state $1 &chord $1 ] +|a0 @File [ &vector $2 &success $2 &offset $2 &pad $2 &name $2 &length $2 &load $2 &save $2 ] ( variables ) @@ -51,34 +54,49 @@ ;on-midi .Midi/vector DEO2 ;on-frame .Screen/vector DEO2 + ( load waveform ) + ;sin-path .File/name DEO2 #0100 .File/length DEO2 WAVEFORM .File/load DEO2 + ;tri-path .File/name DEO2 #0100 .File/length DEO2 WAVEFORM #0100 ADD2 .File/load DEO2 + ;sqr-path .File/name DEO2 #0100 .File/length DEO2 WAVEFORM #0200 ADD2 .File/load DEO2 + ( find center ) .Screen/width DEI2 2/ .center/x POK2 .Screen/height DEI2 2/ .center/y POK2 ( place octave ) - .center/x PEK2 #0050 SUB2 .octave-view/x1 POK2 + .center/x PEK2 #0080 SUB2 .octave-view/x1 POK2 .center/y PEK2 8+ .octave-view/y1 POK2 - .octave-view/x1 PEK2 #0048 ADD2 .octave-view/x2 POK2 + .octave-view/x1 PEK2 #0050 ADD2 .octave-view/x2 POK2 .octave-view/y1 PEK2 #0018 ADD2 .octave-view/y2 POK2 ( place adsr ) - .center/x PEK2 .adsr-view/x1 POK2 + .center/x PEK2 #0020 SUB2 .adsr-view/x1 POK2 .center/y PEK2 8+ .adsr-view/y1 POK2 - .adsr-view/x1 PEK2 #0058 ADD2 .adsr-view/x2 POK2 + .adsr-view/x1 PEK2 #00a0 ADD2 .adsr-view/x2 POK2 .adsr-view/y1 PEK2 #0018 ADD2 .adsr-view/y2 POK2 ( place waveform ) - .center/x PEK2 #0050 SUB2 .wave-view/x1 POK2 + .center/x PEK2 #0080 SUB2 .wave-view/x1 POK2 .center/y PEK2 #0020 SUB2 .wave-view/y1 POK2 - .wave-view/x1 PEK2 #00a8 ADD2 .wave-view/x2 POK2 + .wave-view/x1 PEK2 #0100 ADD2 .wave-view/x2 POK2 .wave-view/y1 PEK2 #0020 ADD2 .wave-view/y2 POK2 ( default settings ) #ff .last-note POK #048c .Audio0/adsr DEO2 #88 .Audio0/volume DEO - ;sine-wave .Audio0/addr DEO2 - ;sine-wave/end ;sine-wave SUB2 #0001 SFT2 .Audio0/length DEO2 + WAVEFORM .Audio0/addr DEO2 + #0100 .Audio0/length DEO2 + + #011a .Audio1/adsr DEO2 + #88 .Audio1/volume DEO + WAVEFORM #0100 ADD2 .Audio1/addr DEO2 + #0100 .Audio1/length DEO2 + + #1118 .Audio2/adsr DEO2 + #88 .Audio2/volume DEO + WAVEFORM #0200 ADD2 .Audio2/addr DEO2 + #0100 .Audio2/length DEO2 ( inital drawing ) ;draw-octave JSR2 @@ -132,7 +150,7 @@ BRK @on-touch-octave-view ( -> ) - .Mouse/x DEI2 .octave-view/x1 PEK2 SUB2 8/ SWP POP #08 NEQ ,&no-mod JNZ + .Mouse/x DEI2 .octave-view/x1 PEK2 SUB2 8/ SWP POP #09 NEQ ,&no-mod JNZ .Mouse/y DEI2 .octave-view/y1 PEK2 SUB2 8/ SWP POP DUP #00 NEQ ,&no-incr JNZ .octave PEK #01 ADD .octave POK &no-incr @@ -144,10 +162,11 @@ BRK BRK &no-mod - .Mouse/x DEI2 .octave-view/x1 PEK2 SUB2 8/ DUP2 SWP POP .last-note POK ;notes ADD2 GET ;play JSR2 - - ( release ) #00 .Mouse/state DEO - ;draw-octave JSR2 + .Mouse/x DEI2 .octave-view/x1 PEK2 SUB2 8/ SWP POP #06 GTH ,&no-key JNZ + .Mouse/x DEI2 .octave-view/x1 PEK2 SUB2 8/ DUP2 SWP POP .last-note POK ;notes ADD2 GET ;play JSR2 + ( release ) #00 .Mouse/state DEO + ;draw-octave JSR2 + &no-key BRK @@ -170,6 +189,14 @@ BRK .Audio0/adsr #01 ADD DEI DUP #f0 AND STH #01 .Mouse/state DEI #10 EQU #0e MUL ADD ADD #0f AND STHr ADD .Audio0/adsr #01 ADD DEO &no-r + DUP #05 NEQ ,&no-left JNZ + .Audio0/volume DEI + #10 .Mouse/state DEI #10 EQU #e0 MUL ADD ADD + .Audio0/volume DEO &no-left + DUP #06 NEQ ,&no-right JNZ + .Audio0/volume DEI + DUP #f0 AND STH #01 .Mouse/state DEI #10 EQU #0e MUL ADD ADD #0f AND STHr ADD + .Audio0/volume DEO &no-right POP ( release ) #00 .Mouse/state DEO @@ -223,7 +250,7 @@ BRK @play ( pitch -- ) - .octave PEK #0c MUL ADD .Audio0/pitch DEO + DUP .octave PEK #0c MUL ADD .Audio0/pitch DEO RTN @@ -258,8 +285,9 @@ RTN OVR2 #0028 ADD2 OVR2 ;keys-middle-icns #21 .last-note PEK #05 EQU ADD ;draw-key JSR2 SWP2 #0030 ADD2 SWP2 ;keys-right-icns #21 .last-note PEK #06 EQU ADD ;draw-key JSR2 + .octave-view/x1 PEK2 #0048 ADD2 .Screen/x DEO2 + ;arrow-icns .Screen/addr DEO2 - .octave-view/x1 PEK2 #0040 ADD2 .Screen/x DEO2 .octave-view/y1 PEK2 .Screen/y DEO2 #21 .Screen/color DEO @@ -268,7 +296,6 @@ RTN #21 .Screen/color DEO ;font-hex .octave PEK #03 ADD #00 SWP #0008 MUL2 ADD2 .Screen/addr DEO2 - .octave-view/x2 PEK2 #0008 SUB2 .Screen/x DEO2 .octave-view/y1 PEK2 8+ .Screen/y DEO2 #23 .Screen/color DEO @@ -306,6 +333,14 @@ RTN .Audio0/adsr #01 ADD DEI #0f AND ;draw-knob JSR2 + ( volume ) + .adsr-view/x2 PEK2 #0028 SUB2 .adsr-view/y1 PEK2 + .Audio0/volume DEI #04 SFT + ;draw-knob JSR2 + .adsr-view/x2 PEK2 #0010 SUB2 .adsr-view/y1 PEK2 + .Audio0/volume DEI #0f AND + ;draw-knob JSR2 + RTN @draw-wave ( -- ) @@ -321,7 +356,7 @@ RTN .wave-view/x1 PEK2 .Screen/x DEO2 ( waveform ) - #00 #a8 + #00 #ff &loop ( dotted line ) OVR #01 AND ,&no-dot JNZ @@ -490,38 +525,6 @@ RTN 007c 8280 8080 827c 00fc 8282 8282 82fc 007c 8280 f080 827c 007c 8280 f080 8080 ] -@sine-wave [ - 0004 090e 1217 1c20 2529 2e32 363b 3f43 - 474b 4e52 5659 5c60 6365 686b 6d70 7274 - 7677 797a 7b7c 7d7e 7e7e 7e7e 7e7e 7d7c - 7b7a 7978 7674 7270 6e6b 6966 6360 5d5a - 5753 4f4c 4844 403c 3833 2f2a 2621 1d18 - 140f 0a05 01fc f7f2 eee9 e4e0 dbd7 d2ce - cac5 c1bd b9b5 b1ae aaa7 a3a0 9d9a 9795 - 9290 8e8c 8a88 8785 8483 8282 8181 8181 - 8181 8282 8384 8687 898a 8c8e 9193 9598 - 9b9e a1a4 a8ab afb2 b6ba bec2 c6cb cfd3 - d8dc e1e6 eaef f4f8 ] &end - -@tri-wave [ - 0002 0406 080a 0c0e 1012 1416 181a 1c1e - 2022 2426 282a 2c2e 3032 3436 383a 3c3e - 4041 4345 4749 4b4d 4f51 5355 5759 5b5d - 5f61 6365 6769 6b6d 6f71 7375 7779 7b7d - 7f7d 7b79 7775 7371 6f6d 6b69 6765 6361 - 5f5d 5b59 5755 5351 4f4d 4b49 4745 4341 - 403e 3c3a 3836 3432 302e 2c2a 2826 2422 - 201e 1c1a 1816 1412 100e 0c0a 0806 0402 - 00fe fcfa f8f6 f4f2 f0ee ecea e8e6 e4e2 - e0de dcda d8d6 d4d2 d0ce ccca c8c6 c4c2 - c1bf bdbb b9b7 b5b3 ] - -@arc [ - 8000 8d00 9a02 a706 b40b c011 cb18 d520 - df2a e734 ee40 f44b f958 fd65 ff72 ff80 - ff8d fd9a f9a7 f4b4 eec0 e7cb dfd5 d5df - cbe7 c0ee b4f4 a7f9 9afd 8dff 80ff 72ff - 65fd 58f9 4bf4 40ee 34e7 2adf 20d5 18cb - 11c0 0bb4 06a7 029a 008d 0080 0072 0265 - 0658 0b4b 113f 1834 202a 2a20 3418 3f11 - 4b0b 5806 6502 7200 ] \ No newline at end of file +@sin-path "projects/sounds/sin.pcm $1 +@tri-path "projects/sounds/tri.pcm $1 +@sqr-path "projects/sounds/sqr.pcm $1 \ No newline at end of file diff --git a/projects/sounds/sin.pcm b/projects/sounds/sin.pcm new file mode 100644 index 0000000..7ec741c Binary files /dev/null and b/projects/sounds/sin.pcm differ diff --git a/projects/sounds/sqr.pcm b/projects/sounds/sqr.pcm new file mode 100644 index 0000000..3aa80c7 --- /dev/null +++ b/projects/sounds/sqr.pcm @@ -0,0 +1 @@ +€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€ \ No newline at end of file diff --git a/projects/sounds/tri.pcm b/projects/sounds/tri.pcm new file mode 100644 index 0000000..48c4940 Binary files /dev/null and b/projects/sounds/tri.pcm differ