Minimalistic text-based 1-bit music tracker

Related tags

Miscellaneous 1bitr
Overview

1bitr

1bitr ("One Bitter" or "The Bitter One") is a minimalistic text-based music tracker. It only supports 1-bit audio playback and encourages users to write their own sound routines (engines), as well as the music itself.

Text file format

A code snippet is worth a thousand words:

; 0
; Fifth Symphony (ta-da-da  dah...)
G-4 60
G-4
G-4
D#4 e0

You can play it as ./1bitr < examples/fifth.

1bitr reads music line by line from stdin, parses it and passes each parsed row to the sound engine, which plays it. There are no patterns, no looping, no samples. Only notes and effects.

Line comments start with a ;. Comments are ignored. Blank line are skipped as well. First line comment is a special one, see below about the engines.

Other lines must contain musical data that the sound engine can interpret and play.

Each line is a row of numerical values (up to 256 columns are supported, but most likely you will never use more than 16). Numerical values are writted in hexadecimal format (without 0x prefix). Also, notes can be written as C-3 or A#4 and they are converted into numbers by parser. Values starting with a dash are interpreted as zeros (i.e. -- is zero and --- is zero and 00 is also zero).

Playback

There are no loops or patterns beacause one can easily simulate them:

# Put each part into a separate file and concatenate them
$ cat INTRO P1 P2 P1 P3 | ./1bitr

# Play part of the file from line 10 to line 20
$ tail -n +20 MELODY | head -n 10 | ./1bitr

# Play random notes (shuffle music file)
$ cat MUSIC | sort -R | ./1bitr

If the stdout is not a terminal, 1bitr write WAV data into the stdout (instead of playing it). This allows you to save music or to pass it further to other apps:

$ ./1bitr < MUSIC > music.bin
$ ./1bitr < MUSIC | aplay

Raw PCM data generated by 1bitr can be converted to WAV using SoX:

$ sox -t raw -e unsigned-integer -c 1 -r 44100 -b 8 music.bin music.wav

Engines

You are the master of your music. If you are into programming, please try writing your own 1-bit sound routine, it's likely to be fun! Please, make a PR to share it with the others.

Sound routine is a function that takes a row of up to 256 integers and a special out function, that set audio output to 0 or non-zero level.

Here's a sound routine that always plays noise and ignores all music data:

void noise(int *row, void (*out)(unsigned char)) {
  out(rand() % 2);
}

And here's the Sound Engine Zero, it can only play 1 square wave of the given frequency with 50% duty cycle:

static void zero(int *row, void (*out)(unsigned char)) {
  int counter = row[0];
  unsigned char value = 0;
  for (int timer = 0; timer < 5000; timer++) {
    if (--counter == 0) {
      value = !value;
      counter = row[0];
    }
    out(value);
  }
}

If you have added a new engine - choose a single-byte identifier for it (it can be a letter or a digit), and adjust set_engine function to switch to your engine. For example, for our engine "zero" would like to use identifier "Z":

static void set_engine(char c) {
  switch (c) {
    ...
    case 'Z': engine = zero; break;
    ...
  }
}

Now you can write music for your engine. Either make the first line of your music file to be ; Z or pass it via CLI switch:

$ cat << EOF | ./1bitr
; Z
C-4
G-4
EOF

or

$ (echo "C-4"; echo "G-4") | ./1bitr -Z

Default sound engines

Out of the box there are two sound engines: Zero and One. Engine Zero is mostly boring and useless, first column is note value, second is tempo.

Engine One is a bit more advanced. It can support 2 PWM channels, and click drums. The columns are:

; Note1 Note2 Drums FX
  C-4   C-5   03    15
  ---   D-5   00    00

Notes are obvious. Drums are short click samples, values from 1 to 5 are allowed. Effects are also rather simple. High nibble is effect ID, low nibble is effect value.

  • 1x - set channel 1 duty cycle to X. 1f - 50%, 10 - 0%.
  • 2x - same for channel 2.
  • 3x - swipe frequency up at speex X.
  • 4x - swipe frequency down at speed X.
  • fx - set tempo to X.

Both sound engines are provided mosly as references to let you build your own.

License

Code is distributed under MIT license. PRs are welcome! If you have written any interesting (or buzzing and noisy) music - feel free to share it using the issue tracker or twitter with #1bitr hashtag!

You might also like...
Ceres is designed to be a modern and minimalistic C like language.

Ceres v0.0.1 Ceres is designed to be a modern and minimalistic C like language. For now, it will be interpreted but later on I do want to write a comp

Very minimalistic UEFI boot menu / Stivale2 bootloader

Tosaithe Tosaithe is a minimalistic UEFI-firmware menu/bootloader. It can chain-load other EFI programs and loaders, including Linux kernels, and has

PicoQVGA - Minimalistic QVGA Display on Raspberry Pico

Minimalistic QVGA Display on Raspberry Pico with resolution 320x240/8bit, suitable as tutorial to PIO and DMA.

very basic and minimalistic hooking "library" for windows (x64 support soon)

IceHook very basic and minimalistic hooking "library" for windows (x64 support soon) Example how to use: typedef void(__stdcall* twglSwapBuffers)(HDC

Ureact - Minimalistic reactive library for c++

µReact µReact is an open-source minimalistic single-header reactive programming library for C++17. ❗️ This library is a work-in-progress. It should no

64-bit LKM Rootkit builder based on yaml prescription
64-bit LKM Rootkit builder based on yaml prescription

1337kit - LKM Rootkit Builder About project 1337kit is 64-bit LKM Rootkit builder based on yaml prescription Fully tested on: Linux 5.11.0-34-generic

Ios-malicious-bithunter - iOS Malicious Bit Hunter is a malicious plug-in detection engine for iOS applications. It can analyze the head of the macho file of the injected dylib dynamic library based on runtime. If you are interested in other programs of the author, please visit https://github.com/SecurityLife Small stack-based DSL for procedurally generated 1-bit graphics
Small stack-based DSL for procedurally generated 1-bit graphics

Bitlang Bitlang is a tiny stack-based DSL, designed for the sole purpose of producing procedurally generated 1-bit art. It is implemented in ANSI-C, a

The Gecko SDK (GSDK) combines all Silicon Labs 32-bit IoT product software development kits (SDKs) based on Gecko Platform into a single, integrated SDK.

Silicon Labs Gecko SDK (GSDK) The Gecko SDK (GSDK) combines Silicon Labs wireless software development kits (SDKs) and Gecko Platform into a single, i

Comments
  • music share: adventure!

    music share: adventure!

    I made a tiny little tune called "adventure". I have it inside of the adventure branch of my 1bitr fork:

    https://github.com/PaulBatchelor/1bitr/blob/adventure/examples/adventure

    opened by PaulBatchelor 1
  • added sox instructions to README

    added sox instructions to README

    It took me longer than I care to admit to figure out that the "wav" file generated by 1bitr is actually not a WAV file, but just using the same extension. What 1bitr is actually generating is known as raw audio.

    In the README, I added a one-liner that shows how to use the SoX utility to convert that raw PCM data to a WAV file. To remove confusion, I also changed the .wav prefix you used in the example to .bin (somewhat arbitrary, though perhaps .raw is better).

    opened by PaulBatchelor 0
Owner
Serge Zaitsev
Turning complex problems into a lightweight and simple software solutions.
Serge Zaitsev
Arduino based bicycle movement sensor and GPS tracker

Bike Tracker Background There are actually plenty of bicycle trackers around, so why make your own? Well, so that it works the way you want it… And it

null 22 Aug 21, 2022
A video input (V4L2) to NDI converter that works with Raspberry Pi (32-bit and 64-bit), and Intel/AMD CPUs

V4L2 to NDI V4L2 to NDI is an application that connects to attached V4L2 devices and encodes the video signal into NDI It uses the NDI library, allowi

Luke Plassman 43 Oct 5, 2022
Typewriter Effect with Rich Text + *Correct* Text Wrapping

Typewriter Effect with Rich Text + Correct Text Wrapping I've spent way too long getting this right. This is meant as a base class for a UMG dialogue

Sam Bloomberg 28 Sep 19, 2022
Text - A spicy text library for C++ that has the explicit goal of enabling the entire ecosystem to share in proper forward progress towards a bright Unicode future.

ztd.text Because if text works well in two of the most popular systems programming languages, the entire world over can start to benefit properly. Thi

Shepherd's Oasis 207 Sep 23, 2022
Bluetooth low energy (BLE) tracker for ESP32

BLEcker Bluetooth low energy (BLE) tracker for ESP32 This software is written for ESP32 boards to track BLE devices. It can be used for your smart hom

Vörös Ákos 40 Aug 17, 2022
Blazingly fast multi-object tracker. Works on 1 (x, y) point per object.

Norfair++ This is a C++ implementation of Techainer's Norfair, which originates from Norfair, a library for real-time 2D object tracking. Its function

Tô Đức (Watson) 6 Jan 26, 2022
A decompilation of the Nintendo Switch version of Captain Toad: Treasure Tracker [v1.3.0].

cttt-decomp A decompilation of the Nintendo Switch version of Captain Toad: Treasure Tracker [v1.3.0]. Build Instructions Obtain a clean copy of a mai

shibbs 14 Aug 17, 2022
Aims to be an accurate C port of Impulse Tracker 2.15's IT replayer (with selectable IT2 sound drivers)

it2play Aims to be an accurate C port of Impulse Tracker 2.15's IT replayer (with selectable IT2 sound drivers). This is a direct port of the original

Olav Sørensen 18 Sep 27, 2022
CC1312R1 Sub-G Solar power asset tracker

Sub-G Solar Power Asset Tracker TOP BOTTOM Sub-G Solar Power Asset Tracker 은 AxDen 의 Aggregator Platform 를 이용하여 온도, 가속도, GPS 위치와 같은 Asset tracking 에 필

AXDEN 4 Sep 23, 2022
A minimalistic implmentation of CRT0 for Cortex-M7

CM7_CRT0 A basic CRT0 like bootstrap implementation targeting Cortex-M7 The startup code basicall does: Initialize the system clock Initialize ZI regi

Malek Lamari 3 May 19, 2021