Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Minijam #10

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
177 changes: 177 additions & 0 deletions Projects/minijam.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
# Minijam : a third-generation generative synth

Relevant links:

* [On Github](https://github.com/jamesmunns/minijam)
* [Soundcloud] minijam-001 through minijam-007 (3 years ago)
* Is it also here on [YouTube](https://www.youtube.com/watch?v=7ajO4_6BZ6I)? from 1 year ago (Spring 2022)
* On Cohost (Chronological, all from around November 2022)
* [maybe just little a happy chemicals, as a treat](https://cohost.org/jamesmunns/post/247735-maybe-just-little-a) with Soundcloud sample
* [Spec / Music Encoding Notes](https://cohost.org/jamesmunns/post/251210-update-1-the-spec) see below, this post has also more thoughts
* [Huh, I guess it works!](https://cohost.org/jamesmunns/post/252694-huh-i-guess-it-work) with link to Minijam on GitHub
* [music code progress continues](https://cohost.org/jamesmunns/post/266569-music-code-progress) with code blocks (length, pitch, octave)
* [music coding continues](https://cohost.org/jamesmunns/post/273609-music-coding-continu) with progress updates > exporting code for storing musical notes using the [`midly`](https://docs.rs/midly/latest/midly/) crate and the [MuseScore](https://musescore.org/en) music notation program.
* [A simpler way to calculate Euclidean Rhythms](https://cohost.org/jamesmunns/post/276695-a-simpler-way-to-cal) with link to GitHub from [padenot](https://github.com/padenot/euclidian-rythms/blob/3c72f37ff8a6c1b7897fdc783e52fabe8eb45dc8/src/lib.rs?utm_source=cohost&utm_medium=iframely#L5-L72)
* [Focus thinking](https://cohost.org/jamesmunns/post/286011-focus-thinking) with more open thoughts and theories
* [More synth thinking](https://cohost.org/jamesmunns/post/292698-more-synth-thinking) with diagram
* [A little more synth progress](https://cohost.org/jamesmunns/post/296675-a-little-more-synth) with code block "probably about half done now"
* Latest update> [not totally there, but progress](https://cohost.org/jamesmunns/post/309767-not-totally-there-b) with sheets of music, what was acheived so far, plans for TODOs and improvements

[Soundcloud]: https://soundcloud.com/james-munns

## Summary

This is a tiny, first attempt at a sequencer for Mnemos.

## Goals

Eventually it should be something bigger (or a part of something bigger), but the goals here are roughly:

* Come up with a way to sequence a single track, with start/end timings, notes, picking different wave types
* Come up with some way to command (RPC? script?) that track
* Spread it out to 4-8 tracks simultaneously
* Come up with a user interface for all that

## Current State

To Do> James

## Open tasks

To Do> James

## Areas of research

To Do> James

## Cross links to related topics/projects

To Do> James

## Note logs

To Do> James

# [The Spec](https://cohost.org/jamesmunns/post/251210-update-1-the-spechttps://cohost.org/jamesmunns/post/251210-update-1-the-spec)

## Music Encoding Notes

The idea is to use variable-length encoding for each of three fields:

* Pitch
* Starting Beat
* Note Length

Rests are NOT encoded, only played notes.

This format is intended to be used both as an in-memory format for generating data into a buffer, though it may serve as (part of) a wire format as well.

To do this, let's start with a single variable length primitive. This is roughly based on [varints](https://postcard.jamesmunns.com/wire-format.html#varint-encoded-integers), which I use in [postcard](/Projects/postcard.md).

Note: This is a sketch, not a formal spec proposal.

## `KCint`s
Let's make a number format that encodes 8 OR 16-bit numbers.

> authors note: 816 is the area code of Kansas City. Since these are 8/16-bit numbers, it made sense to me. Not to be confused with [Kansas City Standard](https://en.wikipedia.org/wiki/Kansas_City_standard).

The shorter, 8-bit variants will look like this:

`[0b0xxx_xxxx]` - One flag bit (zero), and 7 data bits. 0..=127

`[0b1xxx_xxxx, 0byyyy_yyyy]` - One flag bit (one) and 15 data bits, little endian. 0..=32767.

UNLIKE varints, the "continuation" bit only exists in the first, least significant byte, which means we have seven bits of data in one byte, or fifteen bits of data in a two-byte pair.

## Pitch

### 7-bit mode

Here, I'm going to steal a page from [MIDI encoding](https://www.audiolabs-erlangen.de/resources/MIR/FMP/C1/C1S2_MIDI.html) of pitch. Basically, `0` maps to `C0`, which has a freqency of 16.35Hz, and each number basically "walks up the keyboard", or increments the frequency by one semitone. [This table](https://pages.mtu.edu/~suits/notefreqs.html) also shows how the frequencies nonlinearly increase by semitone.

This gives us a frequency range of 16.25Hz (`C0`), up to 25kHz or so (`G10`), which is pretty much beyond the full range of human hearing in both directions.

### 15-bit mode

BUT! You might not want *exactly* a note from the scale! You might be doing something atonal, or may want to use a non-western scale.

For that, the lower 7 bits retain the same meaning as a "base note", and the upper 8 bits encode a linear offset towards the next note.

Let's say we start with `C4`, or `60`, or `0x3C` as our base note:

* `[0x3C]` - C4, 261.63Hz
* `[0x3D]` - C#4, 277.18Hz
* `[0xBC, 0x00]`- C4, 00% (000 / 256) to C#4, still 261.63Hz
* `[0xBC, 0x80]` - C4, 50% (128 / 256) to C#4, 269.41Hz
* `[0xBC, 0xC0]` - C4, 75% (192 / 256) to C#4, 273.29Hz

I'm not sure linear interpolation is the best choice here, so consider that subject to change.

## Starting Beat

Here, I plan to break blocks (somehow) into 64-quarter-note blocks. This matches 16 bars at a 4:4 time signature.

### 7-bit mode

In 7 bit mode, the starting number represents the index of eighth notes from the start.

This means that `0x00` maps to bar one, eighth note one. `0x7F` maps to bar 16, eighth note eight.

### 15-bit mode

In 15 bit mode, I again steal a page from MIDI and other audio equipment, and use the concep of [Pulses Per Quarter Note](https://en.wikipedia.org/wiki/Pulses_per_quarter_note). This is basically an integer divider for the "resolution" available within a single quarter note.

I plan to use 192 PPQN, which means I can accurately reproduce 64th note offsets as well as 32nd note triplet offsets. That's good enough for me.

This mode also indexes from the start of the 16-bar segment, which means:

* `0x80, 0x00` - (0) is the down beat of the first note of the first bar
* `0xC0, 0x01` - (192) is the down beat of the second quarter note of the first bar
* `0xFF, 0x5F` - (12287) is the last 64th note of the 16th bar
* All values above 12287 are invalid for now (treated as a decode error)

## Length

This is the length the note is to be held.

### 7-bit mode

In 7-bit mode, we use "regular" common note values.

* 0x00 - 32nd note triplet
* 0x01 - 16th note triplet
* 0x02 - 8th note triplet
* 0x03 - quarter note triplet
* 0x04 - half note triplet
* 0x05 - 64th note
* 0x06 - 32nd note
* 0x07 - 16th note
* 0x08 - 8th note
* 0x09..=0x3F - RESERVED (decode error)
* 0x40..=0x7F - Sustain, quarter note increments (see below)

For values 0x40..=0x7F, the note will be the (number of quarter note beats - 0x3F).

So:

* 0x40 - quarter note
* 0x41 - half note
* 0x43 - whole note
* 0x45 - whole + half
* 0x47 - two whole
* 0x7F - 16x whole notes

### 15-bit mode

In 15-bit mode, we go back to 192 PPQN counts. Currently a length of zero is reserved (decode error).

This means:

* `0x80, 0x01` - (1) would be 1/3 of a 64th note
* `0xC0, 0x01` - (192) would be the same as a quarter note
* `0xA0, 0x02` - (288) would be a quarter + an eighth
Anything > 12288 (`192 * 16 * 4`) will be treated as a decode error.

## Framing

Currently, this doesn't tackle the concepts of framing, or how we stitch together 16-bar chunks, or how to do fancy things like repeated blocks, or anything like that. I imagine the format described above will be "wrapped" in some slightly more comprehensive format.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ The information provided here is for general informational purposes only and is

## Project Page Organization

Different folders:
Different folders:

* Projects
* Inspiration from others
* Current Research
* Current Research
* Notes, other material

with these topics
with these topics

+ Name
+ Summary
Expand Down