removed old chord notation; intoroduced chord-octave notation

This commit is contained in:
Robert Bendun 2022-10-27 21:03:37 +02:00
parent baabdd2655
commit 02740d5865
3 changed files with 31 additions and 22 deletions

View File

@ -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

View File

@ -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 << ')';
} }

View File

@ -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;
} }