Я начал писать программу на C ++ 11, которая будет анализировать аккорды, гаммы и гармонию. Самая большая проблема, с которой я сталкиваюсь на этапе разработки, заключается в том, что нота «C» - это нота, тип аккорда (Cmaj, Cmin, C7 и т. Д.) И тип ключа (ключ Cmajor, Cminor). Та же проблема возникает с интервалами (второстепенный третий, крупный третий).
Я использую базовый класс Token, который является базовым классом для всех «символов» в программе. так например:
class Token {
public:
typedef shared_ptr<Token> pointer_type;
Token() {}
virtual ~Token() {}
};
class Command : public Token {
public:
Command() {}
pointer_type execute();
}
class Note : public Token;
class Triad : public Token; class MajorTriad : public Triad; // CMajorTriad, etc
class Key : public Token; class MinorKey : public Key; // Natural Minor, Harmonic minor,etc
class Scale : public Token;
Как вы можете видеть, создание всех производных классов (CMajorTriad, C, CMajorScale, CMajorKey и т. Д.) Быстро стало бы до смешного сложным, включая все другие заметки, а также расширенную гармонику. множественное наследование не будет работать, т.е.
class C : public Note, Triad, Key, Scale
класс С, не может быть все эти вещи одновременно. Это контекстно, также полиморфирование с этим не будет работать (как определить, какие супер-методы нужно выполнить? Вызов всех конструкторов суперкласса не должен происходить здесь)
Есть ли какие-нибудь дизайнерские идеи или предложения, которые люди могут предложить? Я не смог найти что-либо на Google в отношении моделирования тональной гармонии с точки зрения ОО. Здесь слишком много связей между всеми понятиями.
источник
Ответы:
Я думаю, что лучший подход - воспроизвести реальные отношения между этими объектами.
Например, вы могли бы иметь:
Note
объект, свойство которогоимя (C, D, E, F, G, A, B)
случайный (естественный, плоский, острый)
частота или другой уникальный идентификатор высоты тона
Chord
объект, свойство которогомассив
Note
объектовимя
случайный
качество (основное, второстепенное, пониженное, расширенное, приостановленное)
дополнения (7, 7+, 6, 9, 9+, 4)
Scale
объект, свойство которогомассив
Note
объектовимя
тип (мажор, натуральный минор, мелодический минор, гармонический минор)
мода (ионная, дорианская, фригийская, лидийская, миксолидианская, эоловая, локская)
Затем, если ваш ввод текста, вы можете создавать заметки со строкой, включающей название заметки, случайную и (если вам это нужно) октаву.
Например (псевдокод, я не знаю C ++):
Затем в
Note
классе вы можете разобрать строку и установить свойства.А
Chord
можно построить по его заметкам:... или строкой, включающей имя, качество и дополнительные примечания:
Я не знаю, что именно сделает ваше приложение, так что это всего лишь идеи.
Удачи в вашем увлекательном проекте!
источник
Несколько общих советов.
Если в дизайне класса ожидается много неопределенности (например, в вашей ситуации), я бы порекомендовал поэкспериментировать с различными проектами конкурирующих классов.
Использование C ++ на этом этапе может быть не таким продуктивным, как в других языках. (Эта проблема проявляется в ваших фрагменты коды, чтобы иметь дело с
typedef
иvirtual
деструкторами.) Даже если целью проекта является создание C ++ кода, он может быть продуктивным , чтобы сделать первоначальный дизайн класса на другом языке. (Например, Java, хотя есть много вариантов.)Не выбирайте C ++ только из-за множественного наследования. Множественное наследование имеет свое применение, но это не правильный способ моделирования этой проблемы (теория музыки).
Обратите особое внимание на неоднозначность. Несмотря на то, что в англоязычных (текстовых) описаниях встречается много неясностей, эти двусмысленности необходимо устранять при разработке классов ООП.
Мы говорим о G и G резко, как примечания. Мы говорим о мажоре и минор как шкалы. Таким образом,
Note
иScale
не являются взаимозаменяемыми понятиями. Не может быть никакого объекта, который может быть одновременно экземпляром aNote
и aScale
.Эта страница содержит несколько диаграмм, иллюстрирующих взаимосвязь: http://www.howmusicworks.org/600/ChordScale-Relations/Chord-and-Scale-Relations
Для другого примера, «Триада, начинающаяся с G по мажорной шкале C », не имеет того же значения, что и «Триада, начинающаяся с C по мажорной шкале G ».
На этой ранней стадии
Token
класс (суперкласс всего) неоправдан, потому что он предотвращает неоднозначность. Это может быть введено позже при необходимости (поддерживается фрагментом кода, который демонстрирует, как это может быть полезно).Для начала, начните с
Note
класса, который является центром диаграммы классов, затем постепенно добавляйте отношения (фрагменты данных, которые должны быть связаны с кортежамиNote
s) к диаграмме отношений классов.C нота является экземпляром
Note
класса. С нотой будет возвращать свойства , которые имеют отношение к настоящей записке, такие , как связанные с триадами, и его относительное положение (Interval
) по отношению к ,Scale
который начинается с C нотой.Отношения между экземплярами одного и того же класса (например, между заметкой C и заметкой E ) должны моделироваться как свойства, а не как наследование.
Более того, многие межклассовые отношения в ваших примерах также более подходящим образом смоделированы как свойства. Пример:
(примеры кода ожидают рассмотрения, потому что мне нужно заново изучить теорию музыки ...)
источник
В основном, музыкальные ноты - это частоты, а музыкальные интервалы - это частотные отношения.
Все остальное может быть построено на этом.
Аккорд - это список интервалов. Масштаб - фундаментальная нота и система настройки. Система настройки также представляет собой список интервалов.
Как вы их называете, просто культурный артефакт.
Статья по теории музыки в Википедии - хорошая отправная точка.
источник
Я нахожу эту дискуссию захватывающей.
Вводятся ли ноты через миди (или какое-либо устройство захвата тона) или вводятся путем ввода букв и символов?
В случае интервала от C до D-Sharp / E-flat:
Хотя D-Sharp и E-Flat являются одним и тем же тоном (около 311 Гц, если A = 440 Гц), интервал от C -> D-Sharp записывается как расширенный 2-й, а интервал от C -> E-Flat записывается как несовершеннолетний третий. Достаточно просто, если вы знаете, как записка была написана. Невозможно определить, есть ли у вас только два тона.
В этом случае, я полагаю, вам также понадобится способ увеличения / уменьшения тона вместе с упомянутыми методами .Sharpen () и .Flatten (), такими как .SemiToneUp (), .FullToneDown () и т. Д., Поэтому что вы можете найти последующие заметки в шкале, не «окрашивая» их как острые предметы / квартиры.
Я должен согласиться с @Rotem, что «C» не является классом сам по себе, а скорее является экземпляром класса Note.
Если вы определите свойства для примечания, включая все интервалы в виде полутонов, то независимо от начального значения примечания ("C", "F", "G #") вы сможете сказать, что последовательность из трех примечаний, которая имеет корень, главный 3-й (М3), затем младший 3-й (м3) будет основной триадой. Точно так же m3 + M3 - это второстепенная триада, уменьшенная m3 + m3, увеличенная M3 + M3. Кроме того, это даст вам возможность инкапсулировать нахождение 11-го, уменьшенного 13-го и т. Д. Без явного кодирования их для всех 12 базовых нот и их октав вверх и вниз.
Как только это будет сделано, у вас все еще есть проблемы, которые нужно решить.
Возьмите триаду C, E, G. Как музыкант, я ясно вижу это как аккорд Cmaj. Тем не менее, разработчик во мне может интерпретировать это дополнительно как ми минор Augment 5 (Root E + m3 + a5) или Gsus4 6th no 5th (RootG + 4 + 6).
Итак, чтобы ответить на ваш вопрос о проведении анализа, я думаю, что лучший способ определить модальность (майор, минор и т. Д.) - это взять все введенные ноты, расположить их в возрастающем полутоновом значении и проверить их по известным формам аккордов. , Затем используйте каждую введенную заметку в качестве корневой заметки и выполните тот же набор оценок.
Вы можете взвесить формы аккордов так, чтобы более распространенные (мажорные, минорные) имели приоритет над расширенными, приостановленными, электровыми и т. Д. Аккордами, но точный анализ потребовал бы представления всех соответствующих форм аккордов в качестве возможных решений.
Опять же, статья в Википедии, на которую ссылаются, хорошо перечисляет классы основного тона, поэтому должно быть просто (хотя и утомительно) кодировать модели аккордов, брать введенные ноты, назначать их классам / интервалам основного тона, а затем сравнивать против известных форм для матчей.
Это было очень весело. Благодарность!
источник
Походит на случай для шаблонов. Вы , кажется , есть
template <?> class Major : public Chord;
такMajor<C>
есть-Chord
, как этоMajor<B>
. Точно так же у вас естьNote<?>
шаблон с экземплярамиNote<C>
иNote<D>
.Единственное, что я оставил, это
?
часть. Кажется, у вас есть,enum {A,B,C,D,E,F,G}
но я не знаю, как бы вы назвали это перечисление.источник
Спасибо за все предложения, как-то мне удалось пропустить лишние ответы. До сих пор мои занятия были разработаны так:
Чтобы решить мои проблемы с вычислением интервалов и аккордов, я решил использовать кольцевой буфер, который позволяет мне проходить через буфер из любой точки, двигаясь вперед, пока не найду следующую ноту, которая соответствует.
Чтобы найти интерпретированный интервал, проходящий через буфер реальных нот, остановитесь, когда буквы совпадают (только буква, а не реальная нота или позиция), поэтому c - g # = 5
Чтобы найти реальное расстояние - пройдите еще один буфер из 12 целых чисел, остановитесь, когда верхняя позиция ноты совпадает со значением буфера в индексе, опять же, это только движение вперед. Но смещение может быть где угодно (т. Е. Buffer.at (-10))
теперь я знаю как интерпретируемый интервал, так и физическое расстояние между ними. поэтому имя интервала уже наполовину завершено.
Теперь я могу интерпретировать интервал, т.е. если интервал равен 5, а расстояние равно 8, то это увеличенный 5-й.
Пока нота и интервал работают, как и ожидалось, теперь мне нужно только определить идентификатор аккорда.
Еще раз спасибо, я перечитал некоторые из этих ответов и включил некоторые идеи здесь.
источник