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
//! Parser and player of **F**amicon (a.k.a. NES) **F**lavored **M**usic **M**acro **L**anguage (FFMML).
//!
//! The language specification of FFMML is based on [MCK].
//! But there are (known) differences between FFMML and MCK as follows:
//!
//! - FFMML doesn't support the following features:
//! - `#INCLUDE` directive
//! - `#OCTAVE-REV` directive
//! - `@n` command (direct frequency select)
//! - `n` command (direct note select)
//! - `y` command (direct memory entry)
//! - DPCM channel
//! - FFMML features `#CHANNEL <CHANNEL_NAME> <OSCILLATOR>` directive that defines custom channels:
//! - `<CHANNEL_NAME>`: `A..=Z`
//! - `<OSCILLATOR>`: `1` (pulse wave), `2` (triangle wave), or `3` (noise)
//!
//! [MCK]: https://www.nesdev.org/mckc-e.txt
//!
//! # Examples
//!
//! The following example parses an MML script and generates audio data:
//! ```
//! let mml = r#"; From https://www.nesdev.org/mck_guide_v1.0.txt
//! #TITLE My First NES Chip
//! #COMPOSER Nullsleep
//! #PROGRAMER 2003 Jeremiah Johnson
//!
//! @v0 = { 10 9 8 7 6 5 4 3 2 }
//! @v1 = { 15 15 14 14 13 13 12 12 11 11 10 10 9 9 8 8 7 7 6 6 }
//! @v2 = { 15 12 10 8 6 3 2 1 0 }
//! @v3 = { 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 }
//!
//! ABCD t150
//!
//! A l8 o4 @01 @v0
//! A [c d e f @v1 g4 @v0 a16 b16 >c c d e f @v1 g4 @v0 a16 b16 >c<<]2
//!
//! C l4 o3 q6
//! C [c e g8 g8 a16 b16 >c8 c e g8 g8 a16 b16 >c8<<]4
//!
//! D l4 @v2 @0
//! D [@v2 b @v3 e @v2 b @v3 e @v2 b @v3 e @v2 b @v3 e8 @v2 b8]4"#;
//!
//! let music = mml.parse::<ffmml::Music>().unwrap_or_else(|e| panic!("{e}"));
//! let mut player = music.play(48000);
//! let audio_data = (&mut player).collect::<Vec<_>>();
//! player.take_last_error().map(|e| panic!("{e}"));
//! ```
//!
//! To play the music defined by the above MML script, run the following commands:
//! ```console
//! $ cargo install ffmmlc
//! $ cat examples/music01.mml | ffmmlc > music01.wav
//! $ play music01.wav
//! ```
//!
//! # References
//!
//! ### About MML
//!
//! - [MCK reference](https://www.nesdev.org/mckc-e.txt)
//! - [MCK guide](https://www.nesdev.org/mck_guide_v1.0.txt)
//! - [MCK reference (Japanese)](https://wikiwiki.jp/mck/MML%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9)
//! - [What's MML? (Japanese)](https://geolog.mydns.jp/www.geocities.co.jp/Playtown-Denei/9628/whatsmml.html)
//! ### Abount Famicon sound
//!
//! - [NES APU (audio processing unit)](https://www.nesdev.org/wiki/APU)
//! - [FC sound source (Japanese)](https://dic.nicovideo.jp/t/a/fc%E9%9F%B3%E6%BA%90)
//! - [MCK Wiki (Japanese)](https://wikiwiki.jp/mck/%E3%83%95%E3%82%A1%E3%83%9F%E3%82%B3%E3%83%B3%E9%9F%B3%E6%BA%90%E8%A9%B3%E7%B4%B0)
pub use ChannelName;
pub use ;
pub use ;
pub use Sample;