Crate pointillism

source ·
Expand description

A compositional library for musical composition.

§Examples

If you want to see pointillism in action and what it’s capable of, run the examples in the examples folder. There’s also many simple examples scattered throughout the source code, showing off different features.

For a starting example, see the [create] docs.

Note: Some examples may be loud, dissonant, and/or jarring. Hearing discretion is advised.

§Design

The default way in which pointillism outputs audio is by writing sample by sample into a 32-bit floating point .wav file. Internal calculations use 64-bit floating points.

For convenience, the Signal trait is provided. Types implementing this trait generate sample data frame by frame. If the type also implements SignalMut, it can be advanced or retriggered.

Signals may be composed to create more complex signals, using for instance the eff::MapSgn and eff::MutSgn structs. Moreover, you can implement the Signal and SignalMut traits for your own structs, giving you vast control over the samples you’re producing.

§Naming scheme

The pointillism code has a lot of moving parts, and a bunch of similarly named types. Because of this, we rely on the prelude to categorize things neatly.

Every type has a three-letter namespace which helps categorizes it. The main namespaces are as follows:

NamespaceFull NameContents
bufbuffersAudio buffers and associated traits.
crvcurvesBasic oscillator shapes, and builder methods for more complex ones (in the future).
ctrcontrolControl structures, which allow for events to happen at specified time intervals.
effeffectsFor effects, meaning types that alter other signals.
mapmapBasic maps and associated traits.
gengeneratorsTypes that generate a signal “on their own”. This includes the basic oscillators like gen::Loop and gen::Once.
sgnsignalTraits on signals, including the basic Signal and SignalMut.
smpsmpBasic traits and types for sample types, including smp::Mono and smp::Stereo.
rtnroutingStructures for mixing or combining different signals together.
untunitsDifferent units for musical measurement, and associated arithmetical boilerplate.

Note that traits are always imported when the prelude is imported. This simplifies some complex impl declarations, and also makes the trait methods available whenever.

Some of these namespaces also contain further nested namespaces, almost always three letters. See the documentation for the full breakdown.

§Compile-time

You can think of pointillism as a compile-time modular synthesizer, where every new struct is its own module.

Advantages of this design are extensibility and generality. It’s relatively easy to create a highly customizable and complex signal with many layers by composing some functions together.

The downside is that these synths end up having unwieldy type signatures. Moreso, it’s really hard to build synths in real time.

§Features

The project uses the following features:

FeatureEnables
hound*Saving songs as WAV files.
cpalPlaying songs in a dedicated thread.
midlyReading and playing back MIDI files.
human-duration*Pretty-printing for the unt::RawTime type.

* Features marked with an asterisk are enabled by default.

§Goals

Future goals of pointillism are:

  • (Better) algorithmic reverbs
  • Limiters, compressors, sidechaining
  • Me making a whole album with it :D

§Disclaimer

This is a passion project made by one college student learning about DSP. I make no guarantees on it being well-designed, well-maintained, or usable for your own goals.

If you just want to make music with code, and especially if you enjoy live feedback, SuperCollider and Pure Data will most likely be better alternatives for you.

That said, if you happen to stumble across this and make something cool, please let me know!

Modules§

  • Defines different types for audio buffers.
  • Declares control structures, which can be used to execute events at specified time intervals.
  • Declares basic curves that may be to generate audio via gen::Once or gen::Loop.
  • Implements many effects one can use to modify signals.
  • Implements generators of all kinds.
  • Defines the traits Map and Mut.
  • The crate prelude.
  • Structures for mixing or combining different signals together.
  • Defines the Sample trait, and implements it for types Mono, Stereo, and Env.
  • Declares the most basic traits concerning Signals.
  • Implements different units for time, frequency, MIDI notes, among others.

Structs§

  • Wraps a FnMut(unt::Time) -> A so that it implements the SongFunc trait.
  • Wraps a SignalMut so that it implements the SongFunc trait.
  • Wraps a &mut SignalMut so that it implements the SongFunc trait.
  • Represents a song, a piece of code that can be evaluated frame by frame to generate succesive samples. The duration of the file is exactly rounded down to the sample. The song will be mono or stereo, depending on whether the passed function returns smp::Mono or smp::Stereo.

Constants§

  • A generic “out of bounds” error message.

Traits§

  • A trait for some function that returns samples frame by frame.

Functions§