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.songchord; 7 8 import std.algorithm : map, joiner; 9 import std.array : array, join; 10 import std..string : format; 11 12 import musicpulator.tools; 13 import musicpulator.core; 14 import musicpulator.constants; 15 import musicpulator.songchordentry; 16 import musicpulator.musicalscale; 17 18 /// Alias for the chord entry collection. 19 private alias ChordEntryCollection = InternalMaxSizeCollection!(SongChordEntry, songBarSize); 20 21 /// Wrapper around a song chord. 22 final class SongChord 23 { 24 private: 25 /// The entries. 26 ChordEntryCollection _entries; 27 /// The bar of the chord. 28 size_t _bar; 29 /// The positive harmonics. 30 size_t _positiveHarmonics; 31 /// The negative harmonics. 32 size_t _negativeHarmonics; 33 34 public: 35 final: 36 /** 37 * Creates a new song chord. 38 * Params: 39 * entries = The entries of the song chord. 40 * bar = The bar of the chord. 41 * positiveHarmonics = The positive harmonics. 0 by default. 42 * negativeHarmonics = The negative harmonics. 0 by default. 43 */ 44 this(size_t bar, size_t positiveHarmonics = 0, size_t negativeHarmonics = 0) 45 { 46 _bar = bar; 47 _positiveHarmonics = positiveHarmonics; 48 _negativeHarmonics = negativeHarmonics; 49 } 50 51 /** 52 * Creates a new song chord. 53 * Params: 54 * entries = The entries of the song chord. 55 * bar = The bar of the chord. 56 * positiveHarmonics = The positive harmonics. 0 by default. 57 * negativeHarmonics = The negative harmonics. 0 by default. 58 */ 59 this(SongChordEntry[] entries, size_t bar, size_t positiveHarmonics = 0, size_t negativeHarmonics = 0) 60 { 61 if (entries && entries.length) 62 { 63 foreach (entry; entries.map!(e => new SongChordEntry(e.length, e.bar, e.notes.array))) 64 { 65 _entries.add(entry); 66 } 67 } 68 69 _bar = bar; 70 _positiveHarmonics = positiveHarmonics; 71 _negativeHarmonics = negativeHarmonics; 72 } 73 74 @property 75 { 76 /// Gets the entries of the chord. 77 ChordEntryCollection entries() { return _entries; } 78 79 /// Gets the scales of the chord. 80 const(MusicalScale[][]) scales() 81 { 82 MusicalScale[][] chordScales; 83 84 foreach (entry; _entries) 85 { 86 auto entryScales = entry.scalesInternal; 87 88 if (entryScales) 89 { 90 chordScales ~= entryScales; 91 } 92 } 93 94 return chordScales; 95 } 96 97 /// Gets the positive harmonics of the chord. 98 size_t positiveHarmonics() { return _positiveHarmonics; } 99 100 /// Sets the positive harmonics of the chord. 101 void positiveHarmonics(size_t harmonics) 102 { 103 _positiveHarmonics = harmonics; 104 } 105 106 /// Gets the negative harmonics of the chord. 107 size_t negativeHarmonics() { return _negativeHarmonics; } 108 109 /// Sets the negative harmonics of the chord. 110 void negativeHarmonics(size_t harmonics) 111 { 112 _negativeHarmonics = harmonics; 113 } 114 115 /// Gets the bar of the chord. 116 size_t bar() { return _bar; } 117 } 118 119 /** 120 * Adds a entries to the chord entry. 121 * Params: 122 * entries = The entries to add. 123 */ 124 void addChordEntry(SongChordEntry entry) 125 { 126 if (!entry) 127 { 128 return; 129 } 130 131 entry.parentChord = this; 132 133 _entries.add(entry); 134 } 135 136 /// Converts the chord to a string. This will call toJson(). 137 override string toString() 138 { 139 return toJson(); 140 } 141 142 /// Converts the chord to json. 143 string toJson() 144 { 145 return `{"bar":%d,"positiveHarmonics":%d,"negativeHarmonics":%d,"chordEntries":%s}` 146 .format(_bar, _positiveHarmonics, _negativeHarmonics, _entries.map!(e => e.toJson()).joiner(",").array); 147 } 148 149 /// Converts the chord to xml. 150 string toXml() 151 { 152 auto entryXml = ""; 153 154 if (_entries.length) 155 { 156 entryXml = _entries.map!(e => e.toXml()).array.join; 157 } 158 159 return `<SongChord bar="%d" positiveHarmonics="%d" negativeHarmonics="%d">%s</SongChord>` 160 .format(_bar, _positiveHarmonics, _negativeHarmonics, entryXml); 161 } 162 }