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, overly focused design, and lack of real world applications.
The project currently consists of these four parts:
-> libchata
The core C++ library with the compiler, assembler, and execution environment.
-> chatadsp
The standard library of DSP effects.
-> chatacli
A convenient wrapper so you can use Chata code in your favorite terminal.
-> chatapanel
A web management panel so you can use Chata effects with your audio hardware.
Each part’s documentation lives under their respective folder in this repo.
[!TIP] Click here to go to libchata, chatadsp, chatacli, and chatapanel directly.
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?