1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
//! 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:
//!
//! | Namespace | Full Name | Contents |
//! |-|-|-|
//! | [`buf`] | `buffers` | Audio buffers and associated traits.
//! | [`crv`] | `curves` | Basic oscillator shapes, and builder methods for more complex ones (in the future).
//! | [`ctr`] | `control` | Control structures, which allow for events to happen at specified time intervals.
//! | [`eff`] | `effects` | For effects, meaning types that alter other signals.
//! | [`map`] | `map` | Basic maps and associated traits.
//! | [`gen`] | `generators` | Types that generate a signal "on their own". This includes the basic oscillators like [`gen::Loop`] and [`gen::Once`].
//! | [`sgn`] | `signal` | Traits on signals, including the basic [`Signal`] and [`SignalMut`].
//! | [`smp`] | `smp` | Basic traits and types for sample types, including [`smp::Mono`] and [`smp::Stereo`].
//! | [`rtn`] | `routing` | Structures for mixing or combining different signals together.
//! | [`unt`] | `units` | Different 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:
//!
//! | Feature | Enables |
//! |-|-|
//! | [`hound`](https://docs.rs/hound/latest/hound)* | Saving songs as WAV files. |
//! | [`cpal`](https://docs.rs/cpal/latest/cpal) | Playing songs in a dedicated thread. |
//! | [`midly`](https://docs.rs/midly/latest/midly) | Reading and playing back MIDI files. |
//! | [`human-duration`](https://docs.rs/human-duration/latest/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](https://viiii.bandcamp.com) 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](https://supercollider.github.io) and [Pure Data](https://puredata.info) 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!
pub use *;
// Needed so that the docs render properly.
use crate*;
/// A generic "out of bounds" error message.
pub const OOB: &str = "index out of bounds";
/// Increments a value in `0..len` by one, and wraps it around.
///
/// This should be marginally more efficient than `value = (value + 1) % len`, as it avoids the more
/// costly modulo operation.
pub
/// A trait for some function that returns samples frame by frame.
/// 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`](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`].
///
/// See the `examples` folder for example creations.
///
/// ## Example
///
/// We make the most basic song possible: a single sine wave.
///
/// ```
/// # use pointillism::prelude::*;
/// // Project sample rate.
/// const SAMPLE_RATE: unt::SampleRate = unt::SampleRate::CD;
///
/// // File duration.
/// let length = unt::Time::from_sec(1.0, SAMPLE_RATE);
/// // Sine wave frequency.
/// let freq = unt::Freq::from_hz(440.0, SAMPLE_RATE);
///
/// // We create a mono signal that loops through a sine curve at the specified frequency.
/// let mut sgn = gen::Loop::<smp::Mono, _>::new(crv::Sin, freq);
///
/// // Export to file.
/// Song::new_sgn(length, SAMPLE_RATE, &mut sgn).export("examples/sine.wav");
/// ```
/// Methods that require [`hound`].
/// The crate prelude.
///
/// See the readme for a full list of abbreviations.