removed old chord notation; intoroduced chord-octave notation
This commit is contained in:
parent
baabdd2655
commit
02740d5865
@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
### Added
|
### Added
|
||||||
|
|
||||||
- new builtins: map, while, set_len, duration
|
- new builtins: map, while, set_len, duration
|
||||||
|
- `<note><octave>` notation like `c4` that mimics [scientific notation](https://en.wikipedia.org/wiki/Scientific_pitch_notation)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
@ -21,6 +22,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
- Index operation using booleans behaves like a mask and not fancy way of spelling 0 and 1
|
- Index operation using booleans behaves like a mask and not fancy way of spelling 0 and 1
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
- Removed `<note><absolute notes indexes>` chord notation like `c47` meaning c-major
|
||||||
|
|
||||||
## [0.2.1] - 2022-10-21
|
## [0.2.1] - 2022-10-21
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
@ -20,15 +20,7 @@ Chord Chord::from(std::string_view source)
|
|||||||
ensure(note.has_value(), "don't know how this could happen");
|
ensure(note.has_value(), "don't know how this could happen");
|
||||||
|
|
||||||
Chord chord;
|
Chord chord;
|
||||||
source.remove_prefix(1 + (source[1] == '#'));
|
|
||||||
chord.notes.push_back(*std::move(note));
|
chord.notes.push_back(*std::move(note));
|
||||||
|
|
||||||
if (note->base) {
|
|
||||||
for (char digit : source) {
|
|
||||||
chord.notes.push_back(Note { .base = note->base.value() + i32(digit - '0') });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return chord;
|
return chord;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,11 +125,11 @@ std::ostream& operator<<(std::ostream& os, Chord const& chord)
|
|||||||
return os << chord.notes.front();
|
return os << chord.notes.front();
|
||||||
}
|
}
|
||||||
|
|
||||||
os << "chord[";
|
os << "chord (";
|
||||||
for (auto it = chord.notes.begin(); it != chord.notes.end(); ++it) {
|
for (auto it = chord.notes.begin(); it != chord.notes.end(); ++it) {
|
||||||
os << *it;
|
os << *it;
|
||||||
if (std::next(it) != chord.notes.end())
|
if (std::next(it) != chord.notes.end())
|
||||||
os << "; ";
|
os << "; ";
|
||||||
}
|
}
|
||||||
return os << ']';
|
return os << ')';
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include <musique/value/note.hh>
|
#include <musique/value/note.hh>
|
||||||
|
#include <charconv>
|
||||||
|
|
||||||
/// Finds numeric value of note. This form is later used as in
|
/// Finds numeric value of note. This form is later used as in
|
||||||
/// note to midi resolution in formula octave * 12 + note_index
|
/// note to midi resolution in formula octave * 12 + note_index
|
||||||
@ -44,23 +45,34 @@ constexpr std::string_view note_index_to_string(int note_index)
|
|||||||
|
|
||||||
std::optional<Note> Note::from(std::string_view literal)
|
std::optional<Note> Note::from(std::string_view literal)
|
||||||
{
|
{
|
||||||
if (literal.starts_with('p')) {
|
std::optional<Note> note;
|
||||||
return Note {};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto const base = note_index(literal[0]); base != u8(-1)) {
|
if (literal.starts_with("p")) {
|
||||||
Note note { .base = base };
|
note = Note{};
|
||||||
|
} else if (auto const base = note_index(literal[0]); base != u8(-1)) {
|
||||||
|
note = Note { .base = base };
|
||||||
|
|
||||||
while (literal.remove_prefix(1), not literal.empty()) {
|
while (literal.remove_prefix(1), not literal.empty()) {
|
||||||
switch (literal.front()) {
|
switch (literal.front()) {
|
||||||
case '#': case 's': ++*note.base; break;
|
case '#': case 's': ++*note->base; break;
|
||||||
case 'b': case 'f': --*note.base; break;
|
case 'b': case 'f': --*note->base; break;
|
||||||
default: return note;
|
default:
|
||||||
|
goto endloop;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return note;
|
endloop:
|
||||||
|
;
|
||||||
}
|
}
|
||||||
return std::nullopt;
|
|
||||||
|
if (note && literal.size()) {
|
||||||
|
auto &octave = note->octave.emplace();
|
||||||
|
auto [p, ec] = std::from_chars(&literal.front(), 1 + &literal.back(), octave);
|
||||||
|
ensure(p == &literal.back() + 1, "Parser must have failed in recognizing what is considered a valid note token #1");
|
||||||
|
ensure(ec != std::errc::invalid_argument, "Parser must have failed in recognizing what is considered a valid note token #2");
|
||||||
|
ensure(ec != std::errc::result_out_of_range, "Octave number is too high"); // TODO(assert)
|
||||||
|
}
|
||||||
|
|
||||||
|
return note;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<u8> Note::into_midi_note() const
|
std::optional<u8> Note::into_midi_note() const
|
||||||
@ -111,13 +123,13 @@ std::ostream& operator<<(std::ostream& os, Note note)
|
|||||||
if (note.base) {
|
if (note.base) {
|
||||||
os << note_index_to_string(*note.base);
|
os << note_index_to_string(*note.base);
|
||||||
if (note.octave) {
|
if (note.octave) {
|
||||||
os << ":oct=" << int(*note.octave);
|
os << int(*note.octave);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
os << "p";
|
os << "p";
|
||||||
}
|
}
|
||||||
if (note.length) {
|
if (note.length) {
|
||||||
os << ":len=" << *note.length;
|
os << " " << *note.length;
|
||||||
}
|
}
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user