OO 디자인, Tonal Harmony 모델링 방법


12

코드, 음계 및 하모니를 분석하는 프로그램을 C ++ 11로 작성하기 시작했습니다. 내 디자인 단계에서 가장 큰 문제는 'C'음표는 음표, 코드 형식 (Cmaj, Cmin, C7 등) 및 키 유형 (Cmajor, Cminor의 키)이라는 것입니다. 같은 문제가 간격 (부 3, 3)에서 발생합니다.

프로그램의 모든 '기호'에 대한 기본 클래스 인 기본 클래스 인 토큰을 사용하고 있습니다. 예를 들어 :

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

클래스 C는이 모든 것을 동시에 할 수는 없습니다. 상황에 따라 다형성이 작동하지 않습니다 (수퍼 메소드를 수행하는 방법을 결정하는 방법은 무엇입니까? 모든 수퍼 클래스 생성자를 호출하면 여기서 발생하지 않아야 함)

사람들이 제공해야하는 디자인 아이디어 나 제안이 있습니까? OO 관점에서 색조 조화 모델링과 관련하여 Google에서 아무것도 찾을 수 없었습니다. 모든 개념들 사이에는 관계가 너무 많습니다.


8
왜 'C'가 수업일까요? 나는 'Note', 'Chord'등이 클래스가 될 것이라고 상상할 것입니다.
Rotem

사용자가 코드 CEG를 입력하면, 적절한 코드를 형성하기 위해 음표가 무엇인지 추론해야합니다. <Notes> 벡터를 execute () 메소드의 매개 변수로 전달하려고 생각했습니다.이 메소드는 모두 다형성으로 처리됩니다. 그러나 열거자를 사용하는 것이 의미가 있지만 사용하려는 열거로 모든 객체를 인스턴스화해야합니다.
Igneous01

나는 이것에 대해 @Rotem을 사용하고 있습니다 : 때로는 상속보다 객체 구성을 선호해야합니다.
Spoike

당신이 원하는 것을 생각하는 것이 도움이 될 수 있음을 날 것으로 보인다 이 노트 / 코드 / 스케일 클래스와. 악보를 제작할 예정입니까? 미디 파일? 악보 변환 (조옮김, 모든 음표 길이를 두 배로 늘리기, 특정 음표 위의 모든 음표에 트릴 추가 등)을 수행합니까? 수업 구조가 가능 해지면 이러한 작업을 수행하는 방법에 대해 생각하십시오. 어색해 보이면 다른 클래스 구조를 원할 수도 있습니다.
MatrixFrog

답변:


9

가장 좋은 방법은 이러한 개체들 간의 실제 관계를 재현하는 것입니다.

예를 들어, 다음을 가질 수 있습니다.

  • Note속성이 있는 객체

    • 이름 (C, D, E, F, G, A, B)

    • 우발적 (자연스럽고 평평하며 날카로움)

    • 주파수 또는 다른 고유 피치 식별자

  • Chord속성이 있는 객체

    • Note객체 의 배열

    • 이름

    • 우연한

    • 품질 (주, 부, 감소, 확대, 중단)

    • 추가 (7, 7+, 6, 9, 9+, 4)

  • Scale속성이 있는 객체

    • Note객체 의 배열

    • 이름

    • 유형 (주, 자연 부, 멜로디 부, 고조파 부)

    • 모드 (이오니아 어, 도리안 어, 프리지아 어, 리디안 어, 믹스 올리 디 언어, 바람개비, 로케 리안 어)

그런 다음 입력 내용이 텍스트 인 경우 실수로 음표 이름 (필요한 경우) 옥타브를 포함하는 문자열로 음표를 만들 수 있습니다.

예를 들어 (의사 코드, 나는 C ++을 모른다) :

note = new Note('F#2');

그런 다음 Note클래스에서 문자열을 구문 분석하고 속성을 설정할 수 있습니다.

A Chord는 메모로 구성 할 수 있습니다.

chord = new Chord(['C2', 'E2', 'G2']);

... 또는 이름, 품질 및 추가 메모가 포함 된 문자열로 :

chord = new Chord('Cmaj7');

귀하의 응용 프로그램이 정확히 무엇을할지 모르겠으므로 아이디어 일뿐입니다.

당신의 매혹적인 프로젝트와 행운을 빕니다!


4

일반적인 조언.


클래스 디자인에서 (예를 들어 상황과 같이) 불확실성이 많이 예상되는 경우 다른 경쟁 클래스 디자인을 실험 해 보는 것이 좋습니다.

이 단계에서 C ++를 사용하는 것이 다른 언어만큼 생산적이지 않을 수 있습니다. (이 문제는 코드 조각 typedefvirtual소멸자 를 처리해야하는 코드에서 분명합니다 .) 프로젝트 목표가 C ++ 코드를 생성하는 것이더라도 다른 언어로 초기 클래스 디자인을 수행하는 것이 생산적 일 수 있습니다. (예를 들어 Java는 선택의 여지가 많지만)

다중 상속 때문에 C ++을 선택하지 마십시오. 다중 상속에는 그 용도가 있지만이 문제를 모델링하는 올바른 방법은 아닙니다 (음악 이론).


명확하게주의하십시오. 모호성은 영어 (텍스트) 설명으로 풍부하지만 OOP 클래스를 설계 할 때 이러한 모호성을 해결해야합니다.

우리는 메모로 GG를 예리 하게 말합니다. 우리는 G 메이저G 마이너 를 비늘로 말합니다 . 따라서, NoteScale교체 개념이 아니다. 동시에 a 와 a 의 인스턴스가 될 수 있는 객체 가있을 수 없습니다 .NoteScale

이 페이지에는 관계를 설명하는 몇 가지 다이어그램이 있습니다. http://www.howmusicworks.org/600/ChordScale-Relations/Chord-and-Scale-Relations

또 다른 예를 들어, "트라이어드 그 와 함께 시작 G A의 C 장조 스케일" "트라이어드 것과 같은 의미가 없습니다 로 시작하는 C A의 G 큰 규모".

이 초기 단계에서 Token클래스 (모든 것의 수퍼 클래스)는 명확성을 보장하지 않기 때문에 보증되지 않습니다. 필요한 경우 나중에 소개 할 수 있습니다 (유용한 방법을 보여주는 코드 조각으로 지원됨).


우선, Note클래스 다이어그램의 중심 인 클래스로 시작한 다음 Note클래스 관계 다이어그램에 관계 (s의 튜플과 연관되어야하는 데이터 조각)를 점차적으로 추가하십시오 .

C의 노트는의 인스턴스 Note클래스입니다. C의 참고 예로서 관련 화음이 주 관련된 속성 및 그것의 상대 위치를 (반환 Interval(A)에 대해) Scale시작 A의 C의 주.

동일한 클래스의 인스턴스 (예 : C 노트와 E 노트) 간의 관계는 상속이 아니라 속성으로 모델링되어야합니다.

또한 예제의 많은 클래스 간 관계도 속성으로보다 적절하게 모델링됩니다. 예:

(음악 이론을 다시 배울 필요가 있기 때문에 코드 예제가 보류 중입니다 ...)


재미있는 생각이지만, 고조파 분석의 맥락에서 화음 자질을 결정하는 방법은 무엇입니까? C 코드 인스턴스는 품질 속성이 마이너 (괜찮음)로 설정되어 있어야하지만 지배 / 감소 / 증강 / 사소한 7, 9, 11 코드는 어떻습니까? 단일 음표에 속할 수있는 많은 코드가 있습니다. 코드의 분석 섹션에 다양한 종류의 코드와 각각의 자질이 무엇인지 어떻게 알 수 있습니까?
Igneous01

나는 음악 이론이 거의 없기 때문에 귀하의 질문에 대답 할 수 없습니다. 이해하는 데 도움이되는 한 가지 방법은 해당 개념과 관련된 모든 참고 사항이 나열된 표를 찾는 것입니다. 코드 쿼리는 추가 매개 변수를 사용할 수 있습니다.
rwong

2
다음은 가능한 모든 화음 목록입니다. en.wikipedia.org/wiki/List_of_chords 모든 화음을 어떤음에도 적용 할 수 있습니다. 내 상황에서 중요한 것은 화음이 정확하다는 것입니다. Cflat major! = BMajor, 피아노의 물리적 코드는 동일하지만 용지의 고조파 기능은 매우 다릅니다. 메모를 선명하게하거나 평평하게하는 열거자가 메모 인스턴스에 가장 적합하다고 생각합니다. C.Sharpen () = C # 및 C.Flatten () = Cb에서는 사용자 코드를보다 쉽게 ​​검증 할 수 있습니다.
Igneous01

2

기본적으로 음표는 주파수이고 음악 간격은 주파수 비율입니다.

그 밖의 모든 것을 만들 수 있습니다.

코드는 간격 목록입니다. 스케일은 기본 노트 및 튜닝 시스템입니다. 튜닝 시스템도 간격 목록입니다.

당신이 그것들을 어떻게 명명하는지는 단지 문화적 인공물입니다.

Wikipedia의 음악 이론 기사는 좋은 출발점입니다.


흥미롭지 만, 실제 물리적 현실의 관점에서 시스템을 모델링하는 것이 도움이 될지는 확실하지 않습니다. 모델은 하나의 특정 측면을 명확하게 설명하는 데 도움 이되어야하며 반드시 포괄적이거나 정확할 필요는 없습니다. 접근 방식은 정확하고 포괄적 일 수 있지만 OP 사용 사례에 비해 너무 낮은 수준 일 수 있습니다.
Konrad Rudolph

@KonradRudolph-극단적 인 위치로 일광 절약 시간과 비슷한 방식으로 기본 모델과 프레젠테이션 레이어를 혼합해서는 안된다는 점을 지적하고 싶었습니다. 모델 자체에서 계산이 훨씬 쉽습니다. 가장 유용한 추상화 수준이 내가 제안한 것이 아니라는 점에 동의하지만 OP가 제안한 추상화 수준도 적절하지 않다고 생각합니다.
mouviciel

이 프로그램의 목적은 반드시 음악의 실제 현실을 표시하는 것은 아닙니다. 그러나 (나 같은) 이론을 연구하는 사람들은 일부 화음으로 빠르게 음모를 꾸미고이 화음들이 조화로운 의미로 서로 어떻게 관련되어 있는지 최고의 능력으로 프로그램을 해석 할 수 있습니다. 나는 그것을 측정하여 점수 측정을 읽는 시도되고 진실한 방법을 분석 할 수 있지만, 이것은 일을 더 쉽게하고 분석 할 때 더 세밀한 세부 사항에 집중할 수있는 또 다른 도구입니다.
Igneous01

1

이 토론이 매력적이라고 ​​생각합니다.

노트가 midi (또는 일부 유형의 톤 캡처 장치)를 통해 입력되고 있거나 문자와 기호를 입력하여 입력하고 있습니까?

C에서 D-sharp / E-flat까지의 간격 :

D-sharp와 E-flat은 동일한 톤이지만 (A = 440Hz 인 경우 약 311Hz) C-> D-sharp의 간격은 2로 증가한 반면 C-> E-flat의 간격은 미성년자 메모 작성 방법을 알고 있으면 충분히 쉽습니다. 두 가지 톤만 계속 연주 할 수 있는지 판단 할 수 없습니다.

이 경우 .SemiToneUp (), .FullToneDown () 등과 같이 언급 된 .Sharpen () 및 .Flatten () 메서드와 함께 톤을 증가 / 감소시키는 방법이 필요하다고 생각합니다. 샤프 / 플랫으로 "채색"하지 않고 스케일에서 후속 음표를 찾을 수 있습니다.

"C"는 그 자체가 클래스가 아니라 Note 클래스의 인스턴스화라는 @Rotem에 동의해야합니다.

모든 간격을 포함하여 음표의 속성을 반음으로 정의하면 초기 음표 값 ( "C", "F", "G #")에 관계없이 음표가 루트, 메이저 3 (M3), 마이너 3 (m3)은 메이저 트라이어드가됩니다. 유사하게, m3 + M3은 작은 트라이어드이고, m3 + m3은 감소되고, M3 + M3은 증강된다. 또한 이것은 12 개의 기본 음표와 옥타브를 위아래로 명시 적으로 코딩하지 않고도 11 일, 13 일 등을 찾는 것을 캡슐화하는 방법을 제공합니다.

완료되면 여전히 해결해야 할 몇 가지 문제가 남아 있습니다.

트라이어드 C, E, G를 가져 가라. 음악가로서 나는 이것을 Cmaj 코드로 분명히 본다. 그러나 개발자는이 추가 사항을 E minor Augment 5 (Root E + m3 + a5) 또는 Gsus4 6th no 5th (RootG + 4 + 6)로 해석 할 수 있습니다.

따라서 분석 수행에 대한 귀하의 질문에 대답하기 위해 양식 (메이저, 마이너 등)을 결정하는 가장 좋은 방법은 입력 된 모든 노트를 가져 와서 반음 값을 오름차순으로 정렬하고 알려진 코드 형식에 대해 테스트하는 것입니다. . 그런 다음, 근음으로 입력 된 각 음을 사용하고 동일한 평가 세트를 수행하십시오.

코드 형식에 가중치를 부여하여보다 일반적인 (주, 부) 코드가 확장, 일시 중단, 전자 코드 등의 코드 형식보다 우선 할 수 있지만 정확한 분석을 위해서는 모든 일치하는 코드 형식을 가능한 솔루션으로 제시해야합니다.

다시 언급 한 위키피디아 기사는 피치 클래스를 나열하는 데 도움이되므로 코드 모델을 코딩하고 입력 한 음표를 피치 클래스 / 간격에 할당 한 다음 비교하는 것이 간단합니다 (지루하지만) 알려진 형식과 일치합니다.

이것은 많은 재미이었다. 감사!


지금은 텍스트를 통해 입력되고 있습니다. 그러나 나중에 프로그램이 올바르게 캡슐화되면 midi를 사용할 수 있습니다. 베이비 발자국 : D
Igneous01

0

템플릿의 경우처럼 들립니다. 당신은 갖고있는 것 같다 template <?> class Major : public Chord;그래서이 Major<C>있다-A Chord등입니다 Major<B>. 마찬가지로, 당신은 또한이 Note<?>경우에 템플릿 Note<C>Note<D>.

내가 빠진 것은 ?부분입니다. 당신이 가지고있는 것 같지만 enum {A,B,C,D,E,F,G}그 열거 형의 이름을 어떻게 알지 모르겠습니다.


0

모든 제안에 감사드립니다. 어쨌든 나는 여분의 응답을 놓쳤습니다. 지금까지 내 수업은 다음과 같이 설계되었습니다.

Note
enum Qualities - { DFLAT = -2, FLAT, NATURAL, SHARP, DSHARP }
char letter[1] // 1 char letter
string name // real name of note
int value // absolute value, the position on the keyboard for a real note (ie. c is always 0)
int position // relative position on keyboard, when adding sharp/flat, position is modified
Qualities quality // the quality of the note ie sharp flat

내 간격과 화음 계산 문제를 해결하기 위해 순환 버퍼를 사용하기로 결정했습니다. 순환 버퍼를 사용하면 다음 지점과 일치하는 다음 음을 찾을 때까지 계속 진행할 수 있습니다.

해석 된 간격을 찾으려면 실제 음표 버퍼를 통과하려면 문자가 일치 할 때 (실제 음표 나 위치가 아닌 문자 만) 중지하십시오. c-g # = 5

실수로 12 정수의 다른 버퍼를 가로 지르려면 최상위 음표 위치가 인덱스의 버퍼 값과 같을 때 중지하고 다시 앞으로 이동합니다. 그러나 오프셋은 어디에나있을 수 있습니다 (예 : buffer.at (-10))

이제 해석 된 간격과 둘 사이의 물리적 거리를 모두 알고 있습니다. 따라서 간격 이름은 이미 절반이 완료되었습니다.

이제 간격을 해석 할 수 있습니다. 간격이 5이고 거리가 8이면 간격이 5가됩니다.

지금까지 음표와 간격이 예상대로 작동하므로 코드 식별자 만 다루면됩니다.

다시 한 번 감사드립니다.이 답변 중 일부를 다시 읽고 여기에 몇 가지 아이디어를 반영하겠습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.