1 /**
2 * Copyright © Underground Rekordz 2019
3 * License: MIT (https://github.com/UndergroundRekordz/Musicpulator/blob/master/LICENSE)
4 * Author: Jacob Jensen (bausshf)
5 */
6 module musicpulator.songnote;
7 
8 import std.string : format;
9 
10 import musicpulator.musicalnote;
11 import musicpulator.constants;
12 import musicpulator.tools;
13 import musicpulator.songchordentry;
14 
15 /// Wrapper around a song note.
16 final class SongNote
17 {
18   private:
19   /// The musical note.
20   MusicalNote _note;
21   /// The length.
22   size_t _length;
23   /// The step.
24   size_t _step;
25   /// The octave.
26   size_t _octave;
27   /// The bar.
28   size_t _bar;
29   /// The parent chord entry.
30   SongChordEntry _parentChordEntry;
31 
32   public:
33   final:
34   /**
35   * Creates a new song note.
36   * Params:
37   *   note =   The note.
38   *   length = The length.
39   *   step =   The step.
40   *   octave = The octave.
41   *   bar =    The bar.
42   */
43   this(MusicalNote note, size_t length, size_t step, size_t octave, size_t bar)
44   {
45     _note = note;
46     _length = length;
47     _step = step;
48     _octave = octave;
49     _bar = bar;
50   }
51 
52   /**
53   * Creates a new song note.
54   * Params:
55   *   note =             The note.
56   *   step =             The step.
57   *   octave =           The octave.
58   *   parentChordEntry = The parent chord entry.
59   */
60   this(MusicalNote note, size_t step, size_t octave, SongChordEntry parentChordEntry)
61   {
62     _note = note;
63     _step = step;
64     _octave = octave;
65     _parentChordEntry = parentChordEntry;
66   }
67 
68   @property
69   {
70     /// Gets the musical note.
71     MusicalNote note() { return _note; }
72 
73     /// Gets the length.
74     size_t length()
75     {
76       if (_parentChordEntry)
77       {
78         return _parentChordEntry.length;
79       }
80 
81       return _length;
82     }
83 
84     /// Gets the step.
85     size_t step() { return _step; }
86 
87     /// Gets the relative step.
88     size_t relativeStep()
89     {
90       if (_parentChordEntry)
91       {
92         return _step + (_parentChordEntry.bar * songBarSize);
93       }
94 
95       return _step + (_bar * songBarSize);
96     }
97 
98     /// Gets the octave.
99     size_t octave() { return _octave; }
100 
101     /// Gets the bar.
102     size_t bar()
103     {
104       if (_parentChordEntry)
105       {
106         return _parentChordEntry.bar;
107       }
108 
109       return _bar;
110     }
111 
112     /// Gets the parent chord entry.
113     SongChordEntry parentChordEntry() { return _parentChordEntry; }
114 
115     package(musicpulator)
116     {
117       /// Sets the parent chord entry.
118       void parentChordEntry(SongChordEntry chordEntry)
119       {
120         _parentChordEntry = chordEntry;
121       }
122     }
123   }
124 
125   /// Converts the musical note to its relative flat note.
126   void convertToFlat()
127   {
128     _note = convertToFlatNote(_note);
129   }
130 
131   /// Converts the musical note from a flat note to its relative note.
132   void convertFromFlat()
133   {
134     _note = convertFromFlatNote(_note);
135   }
136 
137   /// Converts the note to a string. This will call toJson().
138   override string toString()
139   {
140     return toJson();
141   }
142 
143   /// Converts the note to json.
144   string toJson()
145   {
146     return `{"note":%s,"length":%d,"step":%d,"relativeStep":%d,"octave":%d,"bar":%d}`
147       .format(_note.toJson(), length, _step, relativeStep, _octave, bar);
148   }
149 
150   /// Converts the note to xml.
151   string toXml()
152   {
153     return `<SongNote note="%s" length="%d" step="%d" relativeStep="%d" octave="%d" bar="%d" />`
154       .format(_note.toXml(), length, _step, relativeStep, _octave, bar);
155   }
156 }