Git Product home page Git Product logo

rudiments's Introduction

rudiments

Crates.io Crates.io License License

rudiments is a step-sequencing drum machine that plays rhythm patterns using audio samples.

muppets animal, personal use license

Features

  • 16-step programmable measures.
  • Configurable per-track amplitude.
  • Adjustable tempo.
  • Playback once or on repeat.
  • Supports several audio file formats:
    • MP3
    • WAV
    • Vorbis
    • Flac

Playback and audio file decoding are handled by rodio.

Usage

rudiments 0.1.1
A step-sequencing drum machine

USAGE:
    rudiments [FLAGS] [OPTIONS] --pattern <FILE> --instrumentation <FILE> --samples <DIRECTORY>

FLAGS:
    -h, --help       Prints help information
    -r, --repeat     Repeat the pattern until stopped
    -V, --version    Prints version information

OPTIONS:
    -i, --instrumentation <FILE>    Path to instrumentation file
    -p, --pattern <FILE>            Path to pattern file
    -s, --samples <DIRECTORY>       Search path for sample files
    -t, --tempo <NUMBER>            Playback tempo [default: 120]

Inputs

rudiments loads a pattern file and binds the pattern's tracks to audio files in a samples directory per an instrumentation file.

Pattern file (--pattern)

Each line of a pattern file represents a track. There is no limit to the number of tracks in a pattern. A track contains an instrument name, a 16-step sequence, and an optional amplitude. The instrument name is an identifier and can only appear once per pattern. Each sequence represents a single measure in 4/4 time divided into 16th note steps (x for play and - for silent). A track may optionally include an amplitude in the range of [0,1] inclusive. By default, a track plays at full volume.

This is an example of a pattern file's contents for a standard 8th note groove with the hi-hat track played at half volume.

hi-hat |x-x-|x-x-|x-x-|x-x-| 0.5
snare  |----|x---|----|x---|
kick   |x---|----|x---|----|

Instrumentation file (--instrumentation)

An instrumentation file binds the instruments from a pattern file to audio sample files. Each line of an instrumentation file contains an instrument name and an audio file name. Each instrument may only appear once, but a single audio file may be bound to multiple instruments.

This is an example of an instrumentation file's contents that binds five instruments to four audio sample files.

Note that tom.wav is used for both tom-1 and tom-2.

hi-hat hh.wav
tom-1  tom.wav
tom-2  tom.wav
snare  snare.wav
kick   kick.wav

Samples directory (--samples)

rudiments will look in the samples directory for the audio files listed in the instrumentation file.

Tempo (--tempo)

This adjusts the playback tempo (aka beats per minute). The default playback tempo is 120.

Installation

rudiments can be installed with cargo.

$ cargo install rudiments

Upcoming features

  • Swing
  • Reverb
  • Record to output audio file
  • Pattern composition
  • Prevent clipping
  • Trigger inputs
  • Different time signatures
  • Terminal-based UI
    • Playback tracking
    • Live pattern editing

Missing a fun or useful feature? Feel free to submit feature requests and PRs!

Demos ๐Ÿฅ

The assets directory contains several example patterns as well as audio samples from the LinnDrum drum machine.

Standard 8th note groove

$ rudiments \
    --pattern ./assets/patterns/standard \
    --instrumentation ./assets/instrumentations/linndrum \
    --samples ./assets/samples/linndrum \
    --repeat
$ rudiments \
    --pattern ./assets/patterns/burning-up \
    --instrumentation ./assets/instrumentations/linndrum \
    --samples ./assets/samples/linndrum \
    --tempo 140 \
    --repeat
$ rudiments \
    --pattern ./assets/patterns/thriller \
    --instrumentation ./assets/instrumentations/linndrum \
    --samples ./assets/samples/linndrum \
    --tempo 118 \
    --repeat
$ rudiments \
    --pattern ./assets/patterns/get-a-little \
    --instrumentation ./assets/instrumentations/linndrum \
    --samples ./assets/samples/linndrum \
    --repeat
$ rudiments \
    --pattern ./assets/patterns/i-wanna-dance-with-somebody \
    --instrumentation ./assets/instrumentations/linndrum \
    --samples ./assets/samples/linndrum \
    --tempo 118 \
    --repeat
$ rudiments \
    --pattern ./assets/patterns/tom-sawyer \
    --instrumentation ./assets/instrumentations/linndrum \
    --samples ./assets/samples/linndrum \
    --tempo 180
$ rudiments \
    --pattern ./assets/patterns/never-gonna-give-you-up \
    --instrumentation ./assets/instrumentations/linndrum \
    --samples ./assets/samples/linndrum

rudiments's People

Contributors

jonasrmichel avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

rudiments's Issues

Playing on repeat may stop unexpectedly

The thread::park function is used to block the main thread indefinitely for play on repeat. However, per the thread::park documentation, this function may not actually block indefinitely...

A call to park does not guarantee that the thread will remain parked forever, and callers should be prepared for this possibility.

Question: Curious why you chose to premix the sound files?

Looking through the code, I can see that you wrote some code to premix the files into a single "track". This is cool and it never occurred to me that this approach can work well (which it does clearly!).

I just have a general curiosity/architecture question for you?

Why did you choose to premix in the first place versus playing the individual samples in real time? If they're managed individually you could potentially build a UI/Command-line component where you can view the sequencer and turn on or off each instrument per note?

Really cool lib btw!

-deckarep

install fails on Apple Silicon

I tried installing via cargo install on my M1 Max chipset and it failed with the following error:

error: cannot find derive macro Parser in this scope
--> /Users/ken/.cargo/registry/src/github.com-1ecc6299db9ec823/rudiments-0.1.1/src/main.rs:169:10
|
169 | #[derive(Parser, Debug)]
| ^^^^^^
|
note: Parser is imported here, but it is only a trait, without a derive macro
--> /Users/ken/.cargo/registry/src/github.com-1ecc6299db9ec823/rudiments-0.1.1/src/main.rs:158:5
|
158 | use clap::Parser;
| ^^^^^^^^^^^^

error: cannot find attribute clap in this scope
--> /Users/ken/.cargo/registry/src/github.com-1ecc6299db9ec823/rudiments-0.1.1/src/main.rs:170:3
|
170 | #[clap(version = "0.1.1")]
| ^^^^
|
= note: clap is in scope, but it is a crate, not an attribute
error: cannot find attribute clap in this scope
--> /Users/ken/.cargo/registry/src/github.com-1ecc6299db9ec823/rudiments-0.1.1/src/main.rs:173:7
|
173 | #[clap(short, long, value_name = "NUMBER", default_value = "120")]
| ^^^^
|
= note: clap is in scope, but it is a crate, not an attribute
error: cannot find attribute clap in this scope
--> /Users/ken/.cargo/registry/src/github.com-1ecc6299db9ec823/rudiments-0.1.1/src/main.rs:177:7
|
177 | #[clap(short, long, value_name = "FILE")]
| ^^^^
|
= note: clap is in scope, but it is a crate, not an attribute

error: cannot find attribute clap in this scope
--> /Users/ken/.cargo/registry/src/github.com-1ecc6299db9ec823/rudiments-0.1.1/src/main.rs:181:7
|
181 | #[clap(short, long, value_name = "FILE")]
| ^^^^
|
= note: clap is in scope, but it is a crate, not an attribute
error: cannot find attribute clap in this scope
--> /Users/ken/.cargo/registry/src/github.com-1ecc6299db9ec823/rudiments-0.1.1/src/main.rs:185:7
|
185 | #[clap(short, long, value_name = "DIRECTORY")]
| ^^^^
|
= note: clap is in scope, but it is a crate, not an attribute
error: cannot find attribute clap in this scope
--> /Users/ken/.cargo/registry/src/github.com-1ecc6299db9ec823/rudiments-0.1.1/src/main.rs:189:7
|
189 | #[clap(short, long)]
| ^^^^
|
= note: clap is in scope, but it is a crate, not an attribute
error[E0599]: no function or associated item named parse found for struct Opts in the current scope
--> /Users/ken/.cargo/registry/src/github.com-1ecc6299db9ec823/rudiments-0.1.1/src/main.rs:194:28
|
171 | struct Opts {
| ----------- function or associated item parse not found for this
...
194 | let opts: Opts = Opts::parse();
| ^^^^^ function or associated item not found in Opts
|
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following traits define an item parse, perhaps you need to implement one of them:
candidate #1: instrumentation::nom::Parser
candidate #2: Tuple
candidate #3: StructOpt

For more information about this error, try rustc --explain E0599.
error: could not compile rudiments due to 8 previous errors
error: failed to compile rudiments v0.1.1, intermediate artifacts can be found at /var/folders/l9/xdcp3xnn6s78_5l9w2_mnvtw0000gn/T/cargo-installmpUQJR

File not found errors for instrumentation and pattern

When trying out the examples, I noticed that when the instrumentation or pattern file is misspelled, the error message was not very useful. In the parse methods, the file is attempted to be opened with File::open(p)?;, but that error doesn't print out the path that wasn't found.

I'm new to rust, but my suggestion would be to add if !p.is_file() { return Err(FileDoesNotExistError(p.into())); } before the call to File::open(p)?, which let's us use the FileDoesNotExists error that's already defined in error.rs.

cargo run -- --pattern ./assets/patterns/standard --instrumentation ./assets/instrumentations/lindrum --samples ./assets/samples/linndrum --tempo 140 --repeat

Error: IOError(Os { code: 2, kind: NotFound, message: "The system cannot find the file specified." })
error: process didn't exit successfully: target\debug\rudiments.exe --pattern ./assets/patterns/standard --instrumentation ./assets/instrumentations/lindrum --samples ./assets/samples/linndrum --tempo 140 --repeat (exit code: 1)

Using custom Error enum as suggested, output becomes:

Error: FileDoesNotExistError("./assets/instrumentations/lindrum")
error: process didn't exit successfully: target\debug\rudiments.exe --pattern ./assets/patterns/standard --instrumentation ./assets/instrumentations/lindrum --samples ./assets/samples/linndrum --tempo 140 --repeat (exit code: 1)

Installation error: unresolved import `clap::Clap`

Hey!

When trying to install via cargo install rudiments, I am getting the following error:

   Compiling coreaudio-sys v0.2.8
   Compiling coreaudio-rs v0.9.1
   Compiling rodio v0.11.0
   Compiling rudiments v0.1.0
error[E0432]: unresolved import `clap::Clap`
   --> /Users/bolandross/.cargo/registry/src/github.com-1ecc6299db9ec823/rudiments-0.1.0/src/main.rs:158:5
    |
158 | use clap::Clap;
    |     ^^^^^^^^^^ no `Clap` in the root

rustup --version gives me

rustup 1.24.3 (ce5817a94 2021-05-31)
info: This is the version for the rustup toolchain manager, not the rustc compiler.
info: The currently active `rustc` version is `rustc 1.56.1 (59eed8a2a 2021-11-01)`

install fails on raspberrypi

Just tried to install on raspberrypi and got the following error:

$ cargo install rudiments
    Updating crates.io index
  Downloaded rudiments v0.1.1
  Downloaded 1 crate (855.8 KB) in 1.84s
  Installing rudiments v0.1.1
  Downloaded funty v1.1.0
  Downloaded byteorder v1.4.3
  Downloaded minimal-lexical v0.2.1
  Downloaded lewton v0.10.2
  Downloaded hound v3.5.0
  Downloaded wyz v0.2.0
  Downloaded nom v7.1.1
  Downloaded ogg v0.8.0
  Downloaded minimp3 v0.3.5
  Downloaded bitvec v0.18.5
  Downloaded claxon v0.4.3
  Downloaded slice-deque v0.3.0
  Downloaded radium v0.3.0
  Downloaded minimp3-sys v0.3.2
  Downloaded cpal v0.11.0
  Downloaded alsa-sys v0.1.2
  Downloaded rodio v0.11.0
  Downloaded 17 crates (8.0 MB) in 3.48s (largest was `rodio` at 7.1 MB)
   Compiling libc v0.2.135
   Compiling autocfg v1.1.0
   Compiling proc-macro2 v1.0.47
   Compiling unicode-ident v1.0.5
   Compiling quote v1.0.21
   Compiling syn v1.0.102
   Compiling pkg-config v0.3.25
   Compiling cc v1.0.73
   Compiling thiserror v1.0.37
   Compiling cpal v0.11.0
   Compiling tinyvec_macros v0.1.0
   Compiling memchr v2.5.0
   Compiling byteorder v1.4.3
   Compiling lazy_static v1.4.0
   Compiling hashbrown v0.12.3
   Compiling os_str_bytes v6.3.0
   Compiling hound v3.5.0
   Compiling bitflags v1.3.2
   Compiling claxon v0.4.3
   Compiling textwrap v0.15.1
   Compiling radium v0.3.0
   Compiling strsim v0.10.0
   Compiling wyz v0.2.0
   Compiling minimal-lexical v0.2.1
   Compiling termcolor v1.1.3
   Compiling funty v1.1.0
   Compiling num-traits v0.2.15
   Compiling indexmap v1.9.1
   Compiling tinyvec v1.6.0
   Compiling alsa-sys v0.1.2
   Compiling ogg v0.8.0
   Compiling clap_lex v0.2.4
   Compiling minimp3-sys v0.3.2
   Compiling bitvec v0.18.5
   Compiling lewton v0.10.2
   Compiling nom v7.1.1
   Compiling slice-deque v0.3.0
   Compiling atty v0.2.14
   Compiling clap v3.2.22
   Compiling minimp3 v0.3.5
   Compiling thiserror-impl v1.0.37
   Compiling rodio v0.11.0
   Compiling rudiments v0.1.1
error: cannot find derive macro `Parser` in this scope
   --> /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/rudiments-0.1.1/src/main.rs:169:10
    |
169 | #[derive(Parser, Debug)]
    |          ^^^^^^
    |
note: `Parser` is imported here, but it is only a trait, without a derive macro
   --> /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/rudiments-0.1.1/src/main.rs:158:5
    |
158 | use clap::Parser;
    |     ^^^^^^^^^^^^

error: cannot find attribute `clap` in this scope
   --> /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/rudiments-0.1.1/src/main.rs:170:3
    |
170 | #[clap(version = "0.1.1")]
    |   ^^^^
    |
    = note: `clap` is in scope, but it is a crate, not an attribute

error: cannot find attribute `clap` in this scope
   --> /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/rudiments-0.1.1/src/main.rs:173:7
    |
173 |     #[clap(short, long, value_name = "NUMBER", default_value = "120")]
    |       ^^^^
    |
    = note: `clap` is in scope, but it is a crate, not an attribute

error: cannot find attribute `clap` in this scope
   --> /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/rudiments-0.1.1/src/main.rs:177:7
    |
177 |     #[clap(short, long, value_name = "FILE")]
    |       ^^^^
    |
    = note: `clap` is in scope, but it is a crate, not an attribute

error: cannot find attribute `clap` in this scope
   --> /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/rudiments-0.1.1/src/main.rs:181:7
    |
181 |     #[clap(short, long, value_name = "FILE")]
    |       ^^^^
    |
    = note: `clap` is in scope, but it is a crate, not an attribute

error: cannot find attribute `clap` in this scope
   --> /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/rudiments-0.1.1/src/main.rs:185:7
    |
185 |     #[clap(short, long, value_name = "DIRECTORY")]
    |       ^^^^
    |
    = note: `clap` is in scope, but it is a crate, not an attribute

error: cannot find attribute `clap` in this scope
   --> /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/rudiments-0.1.1/src/main.rs:189:7
    |
189 |     #[clap(short, long)]
    |       ^^^^
    |
    = note: `clap` is in scope, but it is a crate, not an attribute

error[E0599]: no function or associated item named `parse` found for struct `Opts` in the current scope
   --> /home/pi/.cargo/registry/src/github.com-1285ae84e5963aae/rudiments-0.1.1/src/main.rs:194:28
    |
171 | struct Opts {
    | ----------- function or associated item `parse` not found for this struct
...
194 |     let opts: Opts = Opts::parse();
    |                            ^^^^^ function or associated item not found in `Opts`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following traits define an item `parse`, perhaps you need to implement one of them:
            candidate #1: `instrumentation::nom::Parser`
            candidate #2: `Tuple`
            candidate #3: `StructOpt`
            candidate #4: `TypedValueParser`

For more information about this error, try `rustc --explain E0599`.
error: could not compile `rudiments` due to 8 previous errors
error: failed to compile `rudiments v0.1.1`, intermediate artifacts can be found at `/tmp/cargo-installVcoA5C`

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.