Модернизируем исходную схему CHORD_BUILDER так, чтобы с её помощью на грифе струнного инструмента можно было задавать табулатуры аккордов:
Сначала зададим новые типы для описания индекса струны, для гитары нумерация будет идти от единицы (верхняя Ми) до шести (нижняя Ми) - CBStringIndex, тип CBFretIndex будет описывать индекс лада, на котором зажимается струна (начиная с 1), а тип CBFingerIndex будет использоваться для определения пальца, которым струна зажимается на указанном ладу (от 1 до 5).
В класс, описывающий накладку на гриф добавим инверсный атрибут в котором будут собранны все доступные в модели табулатуры аккордов для данного инструмента:
CBFretboard; Id: OPTIONAL STRING(64); Name: STRING(64); NFrets: CBPositiveInteger; Strings: LIST [1:?] OF CBString; INVERSE OfInstrument: CBInstrument FOR Fretboard; HasChords: SET [0:?] OF CBChord FOR Fretboard;
Следующим шагом добавим в схему возможность описания места, на котором будет зажата струна. Класс CPBressure будет иметь три атрибута для указания индеска струны, индекса лада и индекса пальца руки, которым струна зажимается на данном ладу:
ENTITY CBPressure; StringIndex: CBStringIndex; Fret: OPTIONAL CBFretIndex; Finger: OPTIONAL CBFingerIndex; END_ENTITY;
EXPRESS-описание для табулатуры аккорда зададим определением CBChord, который кроме названия символа аккорда содержит ссылку на накладу на гриф (CBFretboard), не обязательный атрибут Barre которым задаётся индекс лада для зажатия баррэ и контейнер SET ссылок на объекты CBPressure, которые формируют табулатуру аккорда.
ENTITY CBChord; Symbol: STRING(64); Fretboard: CBFretboard; Barre: OPTIONAL CBFretIndex; Pressures: SET [0:?] OF CBPressure; END_ENTITY;
Наличие опциональных аттрибутов для указания индекса лада (Fret) и индекса пальца (Finger) позволит определять струну, как не используемую в данном аккорде (т.е. для струны достаточно не указывать Fret и Finger для того чтобы она считалась не звучащей).
Полная схема в результате изменений будет такой:
SCHEMA CHORD_BUILDER; TYPE CBPositiveInteger = INTEGER; WHERE IsPositive: SELF > 0; END_TYPE; TYPE CBStringIndex = INTEGER; WHERE IsPositive: SELF >= 1; END_TYPE; TYPE CBFretIndex = INTEGER; WHERE IsPositive: SELF >= 1; END_TYPE; TYPE CBFingerIndex = INTEGER; WHERE IsAppropriate: ((SELF >= 1) AND (SELF <= 5)); END_TYPE; ENTITY CBInstrument; Name: STRING(64); Fretboard: CBFretboard; END_ENTITY; ENTITY CBFretboard; Id: OPTIONAL STRING(64); Name: STRING(64); NFrets: CBPositiveInteger; Strings: LIST [1:?] OF CBString; INVERSE OfInstrument: CBInstrument FOR Fretboard; HasChords: SET [0:?] OF CBChord FOR Fretboard; END_ENTITY; ENTITY CBString; Name: OPTIONAL STRING(64); Symbol: STRING(2); INVERSE OfFretboard: CBFretboard FOR Strings; END_ENTITY; ENTITY CBPressure; StringIndex: CBStringIndex; Fret: OPTIONAL CBFretIndex; Finger: OPTIONAL CBFingerIndex; END_ENTITY; ENTITY CBChord; Symbol: STRING(64); Fretboard: CBFretboard; Barre: OPTIONAL CBFretIndex; Pressures: SET [0:?] OF CBPressure; END_ENTITY; END_SCHEMA;
СИДД (SDAI) код для Smorodina STEP который добавляет аккорд в модель в соответствии с текущей схемой будет выглядеть следующим образом
// Функция добавляет в модель объект CBPressure для описания зажатия струны пальцем на определённом ладу:
SdaiAppInstance appendPressure(SdaiModel model, SdaiSet pressures, SdaiInteger stringIndex, SdaiInteger fretIndex = SDAI::Const::Integer_unset, SdaiInteger fingerIndex = SDAI::Const::Integer_unset)
{
SdaiAppInstance string = sdaiCreateInstanceBN(model, "cbpressure");
sdaiPutAttrBN(string, "stringindex", sdaiINTEGER, stringIndex);
sdaiPutAttrBN(string, "fret", sdaiINTEGER, fretIndex);
sdaiPutAttrBN(string, "finger", sdaiINTEGER, fingerIndex);
sdaiAdd(pressures, sdaiINSTANCE, string);
return string;
}
...
SdaiAppInstance chord_F = sdaiCreateInstanceBN(model, "cbchord");
sdaiPutAttrBN(chord_F, "symbol", sdaiSTRING, "F");
sdaiPutAttrBN(chord_F, "fretboard", sdaiINSTANCE, fretboard);
sdaiPutAttrBN(chord_F, "barre", sdaiINTEGER, 1);
SdaiSet pressures_F = sdaiCreateAggrBN(chord_F, "pressures");
appendPressure(model, pressures_F, 3, 2, 2);
appendPressure(model, pressures_F, 4, 3, 4);
appendPressure(model, pressures_F, 5, 3, 3);
...
Фрагмент Step Physical File, содержащий данный объект выглядит следующим образом:
...
#49=CBCHORD('F',#1,1,(#50,#51,#52));
#50=CBPRESSURE(3,2,2);
#51=CBPRESSURE(4,3,4);
#52=CBPRESSURE(5,3,3);
...
В приложении, отображающем табулатуры аккордов, аккорд F (Фа-Мажор) может выглядеть так:
Аккорд Am (Ля-Минор) может выглядеть следующим образом:
Исходный код на Smorodina STEP СИДД (SDAI) для аккорда Am:
SdaiSet createCBChord(SdaiModel model, SdaiString symbol, SdaiAppInstance fretboard, SdaiInteger barreIndex = SDAI::Const::Integer_unset)
{
SdaiAppInstance chord = sdaiCreateInstanceBN(model, "cbchord");
sdaiPutAttrBN(chord, "symbol", sdaiSTRING, symbol);
sdaiPutAttrBN(chord, "fretboard", sdaiINSTANCE, fretboard);
if (!SDAI::Unset::is(barreIndex))
sdaiPutAttrBN(chord, "barre", sdaiINTEGER, barreIndex);
return sdaiCreateAggrBN(chord, "pressures");
}
...
SdaiSet pressures_Am = createCBChord(model, "Am", fretboard);
SdaiAppInstance Am_String_2 = sdaiCreateInstanceBN(model, "cbpressure");
sdaiPutAttrBN(Am_String_2, "stringindex", sdaiINTEGER, 2);
sdaiPutAttrBN(Am_String_2, "fret", sdaiINTEGER, 1);
sdaiPutAttrBN(Am_String_2, "finger", sdaiINTEGER, 1);
sdaiAdd(pressures_Am, sdaiINSTANCE, Am_String_2);
SdaiAppInstance Am_String_3 = sdaiCreateInstanceBN(model, "cbpressure");
sdaiPutAttrBN(Am_String_3, "stringindex", sdaiINTEGER, 3);
sdaiPutAttrBN(Am_String_3, "fret", sdaiINTEGER, 2);
sdaiPutAttrBN(Am_String_3, "finger", sdaiINTEGER, 3);
sdaiAdd(pressures_Am, sdaiINSTANCE, Am_String_3);
SdaiAppInstance Am_String_4 = sdaiCreateInstanceBN(model, "cbpressure");
sdaiPutAttrBN(Am_String_4, "stringindex", sdaiINTEGER, 4);
sdaiPutAttrBN(Am_String_4, "fret", sdaiINTEGER, 2);
sdaiPutAttrBN(Am_String_4, "finger", sdaiINTEGER, 4);
sdaiAdd(pressures_Am, sdaiINSTANCE, Am_String_4);
SdaiAppInstance Am_String_6 = sdaiCreateInstanceBN(model, "cbpressure");
sdaiPutAttrBN(Am_String_6, "stringindex", sdaiINTEGER, 6);
// Не задаём значения Fret и Finger для того чтобы обозначить, что 6 струна не используется в данном аккорде
sdaiAdd(pressures_Am, sdaiINSTANCE, Am_String_6);
Аккорд Bm - комбинация баррэ и не звучащей струны (его описание с использованием Smorodina STEP СИДД может быть выполнено в качестве упражнения):
- Войдите или зарегистрируйтесь, чтобы оставлять комментарии