{"id":20162660,"url":"https://github.com/slackadays/chata","last_synced_at":"2025-04-13T09:51:30.330Z","repository":{"id":213777993,"uuid":"664299859","full_name":"Slackadays/Chata","owner":"Slackadays","description":":guitar::long_drum::magic_wand: Make DSP Great Again. The Chata programming language!","archived":false,"fork":false,"pushed_at":"2025-03-09T03:49:49.000Z","size":1341,"stargazers_count":62,"open_issues_count":0,"forks_count":1,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-03-27T01:12:45.339Z","etag":null,"topics":["api","audio","chata","cli","community","console","cross-platform","digital-signal-processing","dsl","dsp","embedded","high-performance","library","linux","macos","open-source","programming-language","sound","terminal","windows"],"latest_commit_sha":null,"homepage":"https://slackadays.github.io/Chata/","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Slackadays.png","metadata":{"files":{"readme":".github/README-old.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["Slackadays"],"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"lfx_crowdfunding":null,"custom":null}},"created_at":"2023-07-09T14:48:48.000Z","updated_at":"2025-03-16T18:20:05.000Z","dependencies_parsed_at":"2023-12-23T02:54:47.111Z","dependency_job_id":"5c1dd02a-1195-4465-ae4a-b6a425434e6a","html_url":"https://github.com/Slackadays/Chata","commit_stats":{"total_commits":44,"total_committers":4,"mean_commits":11.0,"dds":0.2954545454545454,"last_synced_commit":"71bffe30c3b52a8c3b076a27b517202799d6a336"},"previous_names":["slackadays/chata"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Slackadays%2FChata","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Slackadays%2FChata/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Slackadays%2FChata/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Slackadays%2FChata/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Slackadays","download_url":"https://codeload.github.com/Slackadays/Chata/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248695300,"owners_count":21146952,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","audio","chata","cli","community","console","cross-platform","digital-signal-processing","dsl","dsp","embedded","high-performance","library","linux","macos","open-source","programming-language","sound","terminal","windows"],"created_at":"2024-11-14T00:26:10.102Z","updated_at":"2025-04-13T09:51:30.307Z","avatar_url":"https://github.com/Slackadays.png","language":"C++","readme":"\u003ch1\u003eWelcome to the Chata programming language\u003c/h1\u003e\n\nChata is an idea for programming language that's just for DSP, or Digital Signal Processing. \n\nChata gets rid of all the junk and cruft associated with DSP, letting you do awesome things easier than ever!\n\n# The Problem 😕\n\n**What is DSP anyway?**\n\nTons of things today use DSP, or Digital Signal Processing, to make them work. \n\nTake your wireless noise cancelling headphones for example. They're using DSP right now to beam that wireless signal and cancel that noise. \n\nMy guitar pedal with zillions of different effects uses a special DSP processor to create them all.\n\nBut how do you even get to this point?\n\n**Enter the clown world of DSP programming.**\n\nCurrent DSP processors often require bespoke tools to work with them. For example, take [SigmaStudio](https://www.analog.com/en/design-center/evaluation-hardware-and-software/software/ss_sigst_02.html).\n\nIf you just want to type code instead, then you're dealing with more bespoke SDKs, APIs, and other fun things.\n\nWhat about running DSP on a regular computer instead? At least you don't have to deal with closed-source, visual tools, but now you've got even more bespoke libraries to deal with.\n\nIs there a way out?\n\n**Enter Chata.**\n\nThe goal of Chata is to be the _dedicated_ way to do great things with DSP. To get really creative, 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.\n\n**Sound interesting? Read on.**\n\n# How It Works :eyes:\n\n\u003e [!Important]\n\u003e **Chata doesn't actually exist yet.**\n\nFirst, let's write a standard that's as polished as it can be. Then, once the standard is ready, we can start making it real. \n\nThe reason for doing this is because I think it's sometimes better to know what you want to achieve first and then work towards that actionable goal rather than working towards something and making up the goal along the way. \n\nHere's some of my goals for Chata:\n- a superb standard library with algorithms such as IIR, Hilbert Transform, and more\n- an action-oriented syntax with clear verbage\n- full math symbol support because DSP is all about math\n- a build system that lets you make different plugins for any valid Chata program\n- great support for DSP applications like RF and not just audio\n- support for compiling to DSP chip targets\n- first-class support for RISC-V\n\nThe language standard will live in this repository right here on GitHub. :octocat:\n\nWe'll figure out what it should look like and see if we can write some example programs that solve common problems. \n\n\u003e [!Tip]\n\u003e **We're all in this journey together!**\n\n\u003cp align=\"center\"\u003e\u003ca href=\"https://discord.gg/J6asnc3pEG\"\u003e\u003cimg src=\"DiscordBanner.png\" height=\"80px\"\u003e\u003c/a\u003e\u003c/p\u003e\n\n# Chata Compared ⚖️\n\nThere's already a similar thing called [SOUL](https://github.com/soul-lang/SOUL), or SOUnd Language.\n- SOUL isn't free and open source. The \"secret sauce\" is still opaque and closed source.\n- SOUL is just for audio. Chata, on the other hand, is for all kinds of DSP!\n- SOUL has tons of junk boilerplate. I couldn't read the example programs provided there.\n- SOUL is selling the implementation, not the end result. This limits SOUL's audience a lot.\n- SOUL is abandoned now, because the company behind it went bankrupt, down the drain, more imploded than the gamepad-controlled Titan submarine.\n\nAnd there's now a followup called [Cmajor](https://github.com/SoundStacks/cmajor)!\n- Cmajor STILL isn't free and open source. The tools provided as binaries are still opaque and closed source.\n- Cmajor still is focused on audio, while Chata is for all DSP.\n- Cmajor looks better regarding boilerplate, but still could do even better.\n- Cmajor's readme leaves a lot to be desired because there's almost no information on it.\n- Cmajor is STILL owned by some company which could go bust like the Challenger space shuttle.\n\nThere's also something else called [Faust](https://github.com/grame-cncm/faust).\n- Faust puts all of its eggs into functional programming. Chata, on the other hand, is imperative, which is better if that's what you're interested in.\n- Faust is \"block-diagram oriented.\" Chata, on the other hand, lacks any concept of block diagrams, which is better if you don't want them.\n- Faust is always \"fully compiled\" with zero interpretation. Chata is more flexible here because it doesn't specify either.\n- Faust relies on bespoke symbol characters like `:`, `,`, `~`, `\u003c:`, and `:\u003e`. With only a couple exceptions, Chata's non-text symbols, on the other hand, are standard mathematical symbols that aren't specific to one language, neither Human nor programming.\n- Faust can't combine multiple files into one program, and you have to specify boilerplate metadata within every code file. Chata, C, C++, Rust all have the ability to atomically combine separate files into one, with metadata specified in one place, baked right into the languages themselves. Examples: Rust and Cargo, C/C++ and CMake, and whatever Chata will have.\n\nHow about something called [Glicol](https://github.com/chaosprint/glicol)?\n- Glicol claims to be a \"graph-oriented live coding language\". However, Chata does not contain any graphs at all in the language.\n- Glicol also seems to be oriented around audio synthesis. However, Chata is for generic DSP, where audio generation is a mere bonus.\n- Glicol is also functional which Chata is not.\n\nIntroducing yet another competitor: [Extempore](https://github.com/digego/extempore)!\n- Extempore looks like one of those functional lisps. However, Chata is neither of those.\n- Extempore is yet another DSP language oriented toward music. However, again, Chata is for generic DSP with music as an application of that.\n- Extempore does not use a certified FOSS license. However, Chata uses the high-quality Mozilla Public License.\n\nLet's finish this comparison off with [Mimium](https://github.com/mimium-org/mimium):\n- Mimium claims that it's \"for sound and music\". Chata, yet again, is just generic DSP, with sound and music mere bonuses.\n- Mimium code actually looks similar to Chata code. However, it lacks some features such as more advanced math due to being only for sound and music.\n\nCommon to all of these options is that there is only one toolchain available for each. This is a monoculture, which means that all projects using it depend on one toolchain to work. Additionally, noncompliant behavior from a single toolchain influences the standard by becoming what projects experience. That's not good if you're interested in language standardization. Other languages like C, C++, Rust, Zig, and Go don't suffer from this. An example is with C and C++'s \"big three\" of GCC, Clang, and MSVC. For Rust, there's GCC and rustc. For Go, there's also GCC and the official go toolchain. Therefore, it's in our best interest that Chata never becomes a monoculture by making sure multiple toolchains remain available.\n\nOther than that, there is almost nothing available that even compares to Chata. Therefore, we'll be competing only with ourselves to make the best DSP language out there.\n\n# Contributing :heart:\n\nIf you want to help out, feel free to do so! I want Chata to be something that everyone can feel good about because it listens to them.\n\n**`How To Help`** Check out the Discord server above :point_up:. \n\nAfter that, if you see something that you want to change, fork this repo and make those changes. Then, we'll see if they integrate well into the main codebase.\n\n# Roadmap 🗺️\n\n- [ ] Chata Language Standard\n  - [ ] basic ideas for a general look\n    - [ ] what should it look like?\n    - [ ] what kinds of looks are feasible?\n    - [ ] how nice can it look?\n  - [ ] types\n    - [ ] int types\n    - [ ] float types\n    - [ ] buffer (array) types\n    - [ ] other types?\n  - [ ] versioning\n  - [ ] syntax\n    - [ ] procedural, functional, imperative?\n    - [ ] how should \"stuff\" work?\n    - [ ] generics/templates\n  - [ ] IO\n    - [ ] in != out IO\n  - [ ] names\n    - [ ] what kind of capitalization?\n    - [ ] what abbreviations should we use?\n  - [ ] math symbols\n    - [ ] what symbols can we support?\n    - [ ] can we seamlessly integrate math symbols into the code?\n  - [ ] standard library\n    - [ ] what features can we include?\n    - [ ] how should we implement the library?\n  - [ ] concurrency\n    - [ ] how can we determine concurrency support?\n  - [ ] platform support\n    - [ ] how can we support DSP processors?\n    - [ ] what ISAs should we support?\n    - [ ] should we use something like LLVM IR?\n  - [ ] multi-language support\n    - [ ] should we support multiple languages?\n- [ ] Official Implementation\n  - [x] license\n  - [ ] basic working interpreter\n    - [ ] what language?\n    - [ ] at what standard should it be built?\n  - [ ] a JIT/faster interpreter\n  - [ ] code generator\n    - [ ] what languages?\n  - [ ] native binary generator\n    - [ ] what ISAs?\n    - [ ] what platforms?\n- [ ] Alternative Implementation\n  - [ ] who will make it?\n  - [ ] license\n  - [ ] what language?\n- [ ] Documentation\n  - [x] readme with basic details\n  - [ ] Chata logo\n  - [ ] sample programs\n    - [ ] \"hello world\" (sine wave)\n    - [ ] delay\n    - [ ] EQ\n    - [ ] reverb\n  - [ ] website\n  - [ ] online playground\n- [ ] Your checkbox here!\n  - [ ] Feel free to contribute to this roadmap!\n\n# The Standard 📜\n\n## Definitions\n\n### Chata Programs\n\nA Chata implementation is any software that follows the Chata standard.\n\nA keyword is a symbol with an assigned meaning in a Chata implementation.\n\nAn action is a collection of symbols and keywords that contains the following in this order:\n- the keyword `action`\n- a valid name\n- optionally, variables in the format `type name` separated by a comma (`,`) character\n- an opening curly bracket symbol (`{`)\n- Chata code\n- a closing curly bracket symbol (`}`)\n\n\u003e [!Note]\n\u003e An action is like a function in regular programming languages, but because functions in Chata have a slightly different way of working, we call them actions instead.\n\nA Chata program is at least one action with name \"main.\"\n\nA Chata program file is a text file that contains only text encoded in UTF-8 format, and that end in a `.cha` extension, and that contains a valid Chata program.\n\nA symbol is the name of an action, function, variable, or other component of a Chata program that the code refers to by a Human-readable string of valid characters.\n\nA statement is a combination of symbols that fits on one line.\n\nA scope is the part of a Chata program in which code within the part can access variables.\n\nA variable is named container of data of a specific type.\n\nA namespace is a way to abstract variables within a single name.\n\n## General Requirements\n\nAll symbols must contain only the following classes of text characters:\n\n- any Latin script character\n- any of these symbols: _ (underscore), - (dash), + (plus)\n- any Greek alphabet letter conventionally used in mathematics except those which are constants\n- any number from 0 to 9\n\nVariable names must start with a Latin script character.\n\nVariable names must not be a symbol already used by a Chata implementation.\n\nAll statements must end with an ASCII line feed character or an ASCII carriage return character followed by an ASCII line feed character.\n\n\u003e [!Note]\n\u003e This means that either `\\n` or `\\r\\n` can delimit lines regardless of if the platform uses either option conventionally.\n\n## Preprocessing\n\nChata provides some ways to change your code before an implemention runs the `main` action.\n\n### inject\n\nInsert a file where the `inject` symbol appears. Specify the filename after `inject` with or without quotes, using POSIX conventions.\n\nThe `inject` symbol may appear within an action.\n\n**`Example`**\n```\ninject foo.cha\n\ninject foo bar.cha\n\ninject \"bar.cha\"\n\ninject \"bar foo.cha\"\n\naction main {\n  inject baz.cha\n  \n  # do stuff here\n}\n```\n\n## Variable Types\n\nThere are these variable types in Chata:\n\n### real\n\nThe `real` type is a floating-point or posit number.\n\n### signal\n\nThe `signal` type is a `real` with minimum value -1.0 and maximum value 1.0.\n\n### int\n\nThe `int` type is a signed integer.\n\n### imag\n\nThe `imag` type is the same as `real`, except that it has the semantics of imaginary numbers.\n\n\u003e [!Note]\n\u003e For example, if you multiplied a `imag` with itself, you would get a negative result.\n\n### complex\n\nThe `complex` type combines a `real` and a `imag`.\n\n## Number Precision\n\nThe Chata implementation defines the precision that all number types use.\n\n## Number Overflow\n\nIf adding a value to a type where the result exceeds the type's maximum capacity in either the positive or negative direction, the type must remain at its maximum possible value.\n\n\u003e [!Note]\n\u003e This means that if you add 1 to an `int` at value 2^31, it will stay at 2^31. This is also called \"saturating\" a value.\n\n## Actions\n\nAll actions start with the keyword `action` followed by the name of the action, optionally variables, followed by an opening curly bracket, Chata code, and closing curly bracket.\n\n**`Example`**\n```\naction main {\n  foobar\n}\n```\n\nActions may specify which variables that they can access directly in the format `action action-name, 1st-variable-type 1st-variable-name {code}`. To provide multiple variables, use the format `action action-name, 1st-variable-type 1st-variable-name, 2nd-variable-type 2nd-variable-name {code}`.\n\n**`Example`** An action that accepts a variable called `in1` of type `signal` and another of name `count` of type `int` can look like \n```\naction main, signal in1, int count {\n  foobar\n}\n```\n\n## Variable Creation\n\nVariable names must not start with a number.\n\nYou can create a variable by declaring it in the format `variable-type variable-name`.\n\n**`Example`** Declare a signal variable of name `foo` with `signal foo`:\n\n```\naction main {\n  signal foo\n}\n```\n\nAll variables which do not depend on other variables contain the value 0 by default.\n\nTo create a variable that matches the value of a different variable, declare it with `variable-type variable-name = target-variable-name`. Chata implementations must only copy the value held by `target-variable-name` into `variable-name`.\n\n## Math Symbol Support\n\nChata supports all standard algebraic math symbols like +, -, *, /, \u003c, \u003e, \u003c= (alias for ≤), =\u003e (alias for ≥), != (alias for ≠), =, ||, and ^.\n\nChata supports mathematical constants like π, τ, e, and i.\n\nChata supports mathematical functions like sqrt() (alias for √()), sin(), cos(), tan(), sec(), csc(), cot(), sinh(), cosh(), and tanh().\n\nChata supports standard mathematical syntax such as 5pi (alias for 5π) and 2 + 1.2sin(e)√(5), and (foovariable)sin(1)\n\nChata supports different mathematical order of operations, but PEMDAS is the default.\n\nAll trigonometric functions use radians for angle units.\n\n\u003e [!Note]\n\u003e This means that you can effortlessly do math on variables as if you were in a math class!\n\n**`Example`**\n```\naction main, signal in {\n  signal foo = 2πin\n}\n```\n\n## Using Actions\n\nTo use an action, use the format `action-name 1st-operand, 2nd-operand, ...`.\n\n**`Example`**\n```\naction doSomething, signal one, signal two {\n  signal three = one + two\n}\naction main, signal in, signal in2 {\n  doSomething in, in2\n}\n```\n\n## Built-In Actions\n\nChata provides several built-in actions that all implementations must include.\n\n\n### out\n\n`out target, ...`\n\nSet variables as the output signals of a Chata program.\n\n**`Example`**\n```\naction main, real in1 {\n  out in1\n}\n```\n\n\u003e [!Note]\n\u003e You can only use the `out` action in the `main` action.\n\n### set\n\n`set target, value, ...`\n\nSet a variable to one or more values.\n\n**`Example`**\n```\nint foo\nset foo, 100, 69, 420, 42\n// result: foo is 42\n```\n\n### add\n\n`add target, value, ...`\n\nAdd one or more values to a variable.\n\n**`Example`**\n```\nint foo\nadd foo, 1\n// result: foo is 1\nadd foo, 100, 50\n// result: foo is 151\n```\n\n### mul\n\n`mul target, value, ...`\n\nMultiply one or more values with a variable.\n\n**`Example`**\n```\nint foo\nmul foo, 10000000\n// result: foo is 0\nadd foo, 5\nmul foo, 100, 1, 5\n// result: foo is 2500\n```\n\n### sub\n\n`sub target, value, ...`\n\nSubtract one or more values from a variable.\n\n**`Example`**\n```\nint foo = 100\nsub foo, 10\n// result: foo is 90\nsub foo, foo - 50, 1\n// result: foo is 49\n```\n\n### setif\n\nSet a variable to one or more values if a condition is true.\n\n`setif condition, target, value, ...`\n\n**`Example`**\n```\nint foo = 100\nsub foo, 50\nsetif foo = 50, foo, 10\n// result: foo is 10\n```\n\n\u003e [!Note]\n\u003e `setif` exists to provide an easy way to do predicated actions on variables as is commonly done in DSPs.\n\n### addif \n\nAdd one or more values to a variable if a condition is true.\n\n`addif condition, target, value, ...`\n\n**`Example`**\n```\nint foo = 100\nsub foo, 50\naddif foo = 50, foo, 10\n// result: foo is 60\n```\n\n### subif \n\nSubtract one or more values from a variable if a condition is true.\n\n`subif condition, target, value, ...`\n\n**`Example`**\n```\nint foo = 100\nsub foo, 50\nsubif foo = 50, foo, 10\n// result: foo is 40\n```\n\n### mulif\n\nMultiply one or more values with a variable if a condition is true.\n\n`mulif condition, target, value, ...`\n\n**`Example`**\n```\nint foo = 100\nsub foo, 50\nmulif foo = 50, foo, 10\n// result: foo is 500\n```\n\n## Scopes\n\nAll Chata programs have a global scope where all actions within the program can access any variables declared in it.\n\nWithin an action, only code within the action and other actions created within it can access variables created in that action.\n\nOnly code following the creation of a variable may access that variable.\n\n## Comments\n\nChata implementations must not interpret code comments as code.\n\nCode comments can start anywhere.\n\nCode comments which span a single line start with the characters `//`.\n\nCode comments which can span multiple lines start with the character `#` and end with the character `#`.\n\n\u003e [!Note]\n\u003e The reason for using `#` for multi-line comments was so that you don't have to type more characters compared to a single-line comment.\n\n## Namespaces\n\nA namespace may contain one or more variables and/or namespaces under a single name. For example, the `foo` namespace may contain the variables `bar` and `baz`. \n\nYou can access variables or namespaces within a namespace in Chata in the format `namespace:content`. For example, to access the `bar` variable within `foo`, use `foo:bar`.\n\nTo create a namespace, use the format `namespace namespace-name {content}`. `content` is lines of variable or namespace declarations.\n\n**`Example`**\n```\nsignal someGlobalVar\nnamespace foo {\n  signal bar\n  int baz\n}\n#namespace junk {\n  blah var\n}#\naction main, signal in {\n  // make a copy of foo:bar\n  signal bat = foo:bar\n  set foo:baz, someGlobalVar\n}\n```\n\n\u003e [!Note]\n\u003e Here's the equivalent code but in C++:\n```cpp\nfloat someGlobalVar;\nnamespace foo {\n  float bar;\n  int baz;\n}\n/*namespace junk {\n  blah var\n}*/\nint main(float\u0026 in) { //note that you can't actually do this in C++!\n  // make a copy of foo:bar\n  float bat = foo::bar;\n  foo::baz = someGlobalVar + bat\n}\n```\n\n## Special Global Variables\n\nChata provides several global variables that are always present in all Chata programs.\n\n### Sample Rate\n\nThis variable of type `int` represents the current sample rate of the Chata implementation in Hertz. If the Chata implementation does not have a set sample rate, the value is 0.\n\nAccess the sample rate with `std:SampleRate`.\n\n**`Example`**\n```\naction main {\n  int foo = std:SampleRate\n}\n```\n\n# Examples :hammer:\n\n## Sine Wave\n\n```\naction main, signal in1 {\n  int hertz = 440\n  int samplesPerCycle = std:SampleRate / hertz\n  int cycles\n  set in1, sin(2πcycles/samplesPerCycle)\n  add cycles, 1\n}\n```\n\nissues:\n- won't exactly be 440 hertz because there is not enough precision when dividing ints\n- `cycles` will eventually saturate which leads to no more signals getting made\n\n## High Pass Filter\n\nNot implemented yet\n\n## Low Pass Filter\n\nNot implemented yet\n\n## Delay\n\nNot implemented yet\n\n## Reverb\n\nNot implemented yet\n\n# Inspiration ✨\n\nBa**chata** music, especially the guitar component of it, I think is the coolest thing ever. If you don't know what that is, check out the explanation on my [profile page](https://github.com/Slackadays/).\n\nTo make the \"classic\" bachata guitar sound, you need four audio effects: high-pass EQ, compression, 20ms-delay stereo chorus, and reverb, in that order. Unfortunately, unless you want to lug around a bunch of heavy guitar pedals, a laptop, or a vintage Ibanez PT-4 from the 1990s, a DSP \"multi-effects processor\" is the only practical option. Also unfortunately, researching how these DSP things work revealed how sorry of a state the professional audio industry is regarding free and open-source software. \n\nSo, I decided to just make the solution.\n\n**Sound interesting? Take a listen for yourself!**\n\n[Aventura: Todavía me amas](https://www.youtube.com/watch?v=RxIM2bMBhCo)\n\n[Aventura: Cuando volverás (English Version)](https://www.youtube.com/watch?v=jnD8Av4Dl4o)\n\n[Romeo Santos: Ileso](https://www.youtube.com/watch?v=yjdHGmRKz08)\n\n[Antony Santos: Corazón bonito](https://www.youtube.com/watch?v=gDYhGBy6304)\n\nNote that ⏫ this one ⏫ doesn't actually use a PT-4 due to barely predating its release in 1993. However, Antony Santos (NOT to be confused with Romeo Santos) was the first to use it to define the sound of bachata music.\n\n","funding_links":["https://github.com/sponsors/Slackadays"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fslackadays%2Fchata","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fslackadays%2Fchata","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fslackadays%2Fchata/lists"}