Chata is a free and open-source solution for DSP, or Digital Signal Processing.
Chata aims to fix problems other DSP libraries and languages have such as poor documentation, narrow application scope, and lack of real world usage.
This project currently consists of these five parts:
đ libchata
The core C++ library with the Chata compiler, Chatassembler, and execution environment. Click here to see libchata.
đ chatadsp
The standard library of DSP effects. Click here to see chatadsp.
đ chatacli
A convenient tool so you can use Chata in your favorite terminal. Click here to see chatacli.
đ chatapanel
A web management panel so you can use Chata effects with custom crafted audio hardware. Click here to see chatapanel.
đ hardware
The hardware that chatapanel
powers. Click here to see the Chata hardware.
Each partâs documentation lives under their respective folder in this repo.
Youâll need a compiler that supports C++20, or GCC 11 and up, CMake, and Just.
Start by cloning this repo from GitHub:
git clone https://github.com/Slackadays/Chata
Then use just
to build Chata:
just build # This builds and installs everything
just build-lib # This builds and installs just libchata
just build-cli # This builds and installs just chatacli
There are a lot of other things you can do here:
jackson@pop-desktop:~/Chata$ just
Available recipes:
build type='Release' # build everything
build-cli type='Release' # build just chatacli
build-lib type='Release' # build just libchata
check-format # check if all code is formatted
clean # clear all CMake files for everything
clean-cli # clear all CMake files for just chatacli
clean-lib # clear all CMake files for just libchata
copy # copy all files to a remote system
default # show this list
format # format all code
generate # run codegen scripts
test # run testsuites for everything
test-lib # run testsuite for just libchata
Use copy
if you want to edit the Chata projectâs code but build it remotely. This runs a script to copy everything to a remote system over SSH.
Use generate
if youâve modified data that the .py
codegen scripts use to generate code, or if youâve modified the scripts themselves.
libchata
into your projectStart by downloading and building libchata
. Then, add #include <libchata.hpp>
wherever you use its functions or objects.
If youâre not using C++, bindings for other languages are planned!
Everything that follows in this page has to do with Chata as a whole and the programming language specification.
Chata is an idea for a programming language thatâs just for DSP, or Digital Signal Processing.
Thereâs no junk or cruft with Chata, so it lets you do great things easier than ever!
Tons of things today use DSP, or Digital Signal Processing, to make them work.
Take your wireless noise cancelling headphones for example. Theyâre using DSP right now to beam that wireless signal and cancel that noise.
But how do you even get to this point?
Current DSP processors often require bespoke tools to work with them. For example, take SigmaStudio, a proprietary thing for everything to do with ADâs DSPs.
If you just want to simply type code instead like you really want to do, then youâre dealing with more bespoke SDKs, APIs, and other (not so) fun things.
Is there a way out?
The goal of Chata is to be the best way to do great things with DSP.
In marketing speak, imagine a one-two punch of an open road where your mind can run full speed with a language that lets you express your ideas, and a powerful ecosystem to put those ideas to work.
Sound interesting? Read on.
Chata builds off of a subset of RISC-V assembly. In case you donât know, RISC-V is a new kind of computer âinstruction set architectureâ (ISA) that defines the raw code that your computer runs. Weâll use this low-level language because DSP mainly performs low-level operations on raw data, and this saves us a lot of time and effort.
But if youâre scared of the idea of writing assembly, fear not. Chata will include a vast standard library with all the classic DSP goodies like filters, transforms, and the like. Plus, since we can take creative license, Chata will have a lot of helpers that make it feel more like other programming languages you might be used to already.
Finally, we put all this together with a complete toolchain so you can put DSP to use.
Like with my other projects, Iâm accepting any contributions you might want to make!
Status of each part:
-> libchata
In progress
-> chatadsp
Not started yet
-> chatacli
Works, but with few features
-> chatapanel
In progress
âRISC-V assemblyâ is the Unprivileged ISA standard defined by https://github.com/riscv/riscv-isa-manual/releases/tag/20240411.
An alias is a way to represent RISC-V assembly code with a different syntax.
All Chata programsâ code must be in files ending with the .chata
file extension.
Chata programs must not include Privileged assembly instructions or these Unprivileged ones:
scall
ecall
One common application of DSP is in audio. However, not all DSP applications are audio. To ensure Chata works with both audio and non-audio applications, we need to define a channel mapping to convert discrete audio channels and generic inputs to the programâs arguments.
Generic inputs | Audio format | Program arguments (audio channel: register) |
---|---|---|
1 | mono (1.0) | fa0 |
2 | stereo (2.0) | left: fa0, right: fa1 |
3 | stereo (2.1) | left: fa0, right: fa1, sub: fa2 |
3 | surround (3.0) | left: fa0, right: fa1, center/back: fa2 |
4 | surround (3.1) | left: fa0, right: fa1, center/back: fa2, sub: fa3 |
4 | quad (4.0) | left: fa0, right: fa1, back left: fa2, back right: fa3 |
more to come | Â | Â |
A register used for input will contain the value of the input signal, not the address of the value in memory.
A Chata program may use the ret
keyword at the uppermost level to stop execution early.
This is where Chata sets itself apart from RISC-V assembly. RISC-V assembly has âpseudo instructionsâ that are simply aliases for a different instruction. For example, âbnez rs1, offsetâ directly translates to âbne rs1, zero, offset,â and âzeroâ is in fact an alias itself for the register âx0.â
Chata, of course, supports all these pseudo instructions. What it includes in addition is âsuperpseudo instructionsâ that provide more logic and a larger selection than RISC-Vâs own pseudo instructions.
if
The code
if register condition register:
code
is equivalent to
if_jump:
code
beq|bne|blt|bge register, register, if_jump
where condition
can be =
, !=
, <
, >
, <=
, or >=
.
For example,
if fa1 = zero:
foobar
is the same as
if_jump:
foobar
beq fa1, x0, if_jump
which looks a lot nicer!
=
, *=
, +=
, -=
, and /=
The code
a0 = 69
fa0 = 69
is the same as
addi a0, zero, 69
addi t0, zero, 69
fcvt.s.w fa0, t0
The same idea is true for *=
, +=
, -=
, and /=
.
The code
a0 *= 2
a0 *= 3
a0 += 5
a0 -= 7
a0 /= 20
if a0 == 20:
a0 += a1
# Floating point
fa0 *= 2
fa0 += 5
fa0 -= 7
fa0 /= 20
is the same as
slli a0, a0, 2 # Automatically apply this easy optimization!
addi t0, zero, 3
mul a0, a0, t0
addi a0, a0, 5
addi t0, zero, 7
sub a0, a0, t0
addi t0, zero, 20
div a0, a0, t0
if_jump:
add a0, a0, a1
ret # AKA jalr x0, x1, 0
addi t0, zero, 20
beq a0, t0, if_jump
# Floating point
addi t0, zero, 2
fcvt.s.w ft0, t0
fmul.s fa0, fa0, ft0
addi t0, zero, 5
fcvt.s.w ft0, t0
fadd.s fa0, fa0, ft0
addi t0, zero, 7
fcvt.s.w ft0, t0
fsub.s fa0, fa0, ft0
addi t0, zero, 20
fcvt.s.w ft0, t0
fdiv.s fa0, fa0, ft0
Be honest: which one would you rather read?