ऊ डिजाइन, टोनल हार्मनी कैसे मॉडल करें?


12

मैंने C ++ 11 में एक प्रोग्राम लिखना शुरू कर दिया है जो कॉर्ड, स्केल और सामंजस्य का विश्लेषण करेगा। मेरे डिजाइन चरण में सबसे बड़ी समस्या यह है कि नोट 'सी' एक नोट है, एक प्रकार का राग (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

क्लास सी, एक ही समय में ये सभी चीजें नहीं हो सकती हैं। यह प्रासंगिक है, इसके साथ बहुरूपता भी काम नहीं करेगा (यह निर्धारित करने के लिए कि कौन से सुपर तरीकों का प्रदर्शन करना है? हर सुपर क्लास कंस्ट्रक्टर्स को कॉल करना यहां नहीं होना चाहिए)

क्या कोई डिज़ाइन विचार या सुझाव है जो लोगों को पेश करना है? मैं OO के दृष्टिकोण से टोनल सामंजस्य के संबंध में Google पर कुछ भी नहीं खोज पाया। यहाँ सभी अवधारणाओं के बीच अभी बहुत अधिक संबंध हैं।


8
'सी' एक वर्ग क्यों होगा? मैं कल्पना करता हूं कि 'नोट', 'कॉर्ड', आदि कक्षाएं होंगी, जिनमें मूल्य गणना हो सकती है जिसमें एनम 'सी' एक भूमिका निभा सकता है।
रोटेम

यदि उपयोगकर्ता इनपुट-> कॉर्ड CEG, तो यह कटौती करने की आवश्यकता होगी कि नोटों को उपयुक्त कॉर्ड बनाने के लिए क्या है। मैं वेक्टर के <नोट्स> के रूप में पारित करने के बारे में सोच रहा था जो कि निष्पादन () विधि के लिए सर्वोपरि है, जिसे सभी बहुरूपिक रूप से नियंत्रित किया जाएगा। हालांकि एक एन्यूमरेटर का उपयोग करने से समझ में आता है, लेकिन तब मुझे उस एनम के साथ हर वस्तु को इंस्टेंट करना होगा जो मैं उपयोग करना चाहता हूं।
Igneous01

मैं इस पर @Rem के साथ हूं: कभी-कभी, आपको विरासत पर वस्तु रचना पसंद करना होगा।
15

यह मेरे लिए है कि यह है कि तुम क्या करना चाहते हैं के बारे में सोचने के लिए उपयोगी हो सकता है लगता है ऐसा इन नोट / तार / पैमाने वर्गों के साथ। क्या आप शीट संगीत का निर्माण करने जा रहे हैं? मिडी फाइलें? क्या स्कोर में बदलाव (ट्रांसपोज़िशन, सभी नोटों की लंबाई दोगुनी करना, एक निश्चित नोट के ऊपर सभी पूरे नोटों में ट्रिल्स जोड़ना) आदि? एक बार जब आपके पास एक संभावित वर्ग संरचना होती है, तो सोचें कि आप उन कार्यों को कैसे पूरा करेंगे। यदि यह अजीब लगता है, तो शायद आप एक अलग वर्ग संरचना चाहते हैं।
MatrixFrog

जवाबों:


9

मुझे लगता है कि सबसे अच्छा दृष्टिकोण इन संस्थाओं के बीच वास्तविक संबंधों को पुन: पेश करना है।

उदाहरण के लिए, आप कर सकते हैं:

  • एक Noteवस्तु, जिसके गुण हैं

    • नाम (सी, डी, ई, एफ, जी, ए, बी)

    • आकस्मिक (प्राकृतिक, सपाट, तेज)

    • आवृत्ति या एक और अद्वितीय पिच पहचानकर्ता

  • एक Chordवस्तु, जिसके गुण हैं

    • Noteवस्तुओं की एक सरणी

    • नाम

    • आकस्मिक

    • गुणवत्ता (प्रमुख, मामूली, कम, संवर्धित, निलंबित)

    • परिवर्धन (7, 7+, 6, 9, 9+, 4)

  • एक Scaleवस्तु, जिसके गुण हैं

    • Noteवस्तुओं की एक सरणी

    • नाम

    • प्रकार (प्रमुख, प्राकृतिक नाबालिग, मधुर नाबालिग, हार्मोनिक नाबालिग)

    • मोड (आयनियन, डोरियन, फ़्रीज़ियन, लिडियन, मिक्सडोलिडियन, आइओलियन, लोकेरियन)

फिर, यदि आपका इनपुट शाब्दिक है, तो आप नोट नाम, आकस्मिक सहित एक स्ट्रिंग के साथ नोट्स बना सकते हैं और (यदि आपको इसकी आवश्यकता है)।

उदाहरण के लिए (pseudocode, मैं C ++ नहीं जानता):

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

फिर, Noteकक्षा में आप स्ट्रिंग को पार्स कर सकते हैं और गुण सेट कर सकते हैं।

एक Chordअपने नोट्स द्वारा निर्मित किया जा सकता है:

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

... या नाम, गुणवत्ता और अतिरिक्त नोट सहित एक स्ट्रिंग द्वारा:

chord = new Chord('Cmaj7');

मुझे नहीं पता कि आपका आवेदन वास्तव में क्या करेगा, इसलिए ये सिर्फ विचार हैं।

अपने आकर्षक परियोजना के साथ शुभकामनाएँ!


4

कुछ सामान्य सलाह।


यदि वर्ग डिजाइन में बहुत अधिक अनिश्चितता की उम्मीद है (जैसे कि आपकी स्थिति में), तो मैं विभिन्न प्रतिस्पर्धी वर्ग डिजाइनों के साथ प्रयोग करने की सलाह दूंगा।

इस स्तर पर C ++ का उपयोग करना अन्य भाषाओं की तरह उत्पादक नहीं हो सकता है। (यह समस्या आपके कोड अंशों typedefऔर virtualविध्वंसकों से निपटने के लिए स्पष्ट है ।) भले ही परियोजना का लक्ष्य C ++ कोड का उत्पादन करना है, यह किसी अन्य भाषा में प्रारंभिक वर्ग डिजाइन करने के लिए उत्पादक हो सकता है। (उदाहरण के लिए जावा, हालांकि कई विकल्प हैं।)

केवल एकाधिक वंशानुक्रम के कारण C ++ का चयन न करें। मल्टीपल इनहेरिटेंस के इसके उपयोग हैं लेकिन यह इस समस्या (संगीत सिद्धांत) को मॉडल करने का सही तरीका नहीं है।


विस्मरण पर विशेष ध्यान रखें। भले ही अंग्रेजी (पाठ) विवरणों में अस्पष्टता प्रचुर मात्रा में है, इन अस्पष्टताओं को OOP कक्षाओं को डिजाइन करते समय हल किया जाना चाहिए।

हम नोट के रूप में जी और जी की तेज बात करते हैं। हम जी मेजर और जी माइनर को स्केल कहते हैं। इस प्रकार, Noteऔर Scaleविनिमेय अवधारणाएं नहीं हैं। ऐसी कोई वस्तु नहीं हो सकती है जो एक साथ एक Noteऔर एक की मिसाल बन सके Scale

इस पृष्ठ में कुछ चित्र शामिल हैं जो रिश्ते को स्पष्ट करते हैं: http://www.howmusicworks.org/600/ChordScale-Relations/Chord-and-Scale-Relations

एक अन्य उदाहरण के लिए, "एक त्रय जो कि एक प्रमुख पैमाने पर जी के साथ शुरू होता है " का एक ही अर्थ नहीं है "एक त्रय जो कि जी प्रमुख पैमाने पर सी के साथ शुरू होता है "।

इस प्रारंभिक चरण में, Tokenवर्ग (सब कुछ का सुपरक्लास) अनुचित है, क्योंकि यह असंतोष को रोकता है। इसे बाद में जरूरत पड़ने पर पेश किया जा सकता है (एक कोड टुकड़ा द्वारा समर्थित जो दर्शाता है कि यह कैसे उपयोगी हो सकता है।)


के साथ शुरू करने के लिए, एक Noteवर्ग के साथ शुरू करें जो वर्ग आरेख का केंद्र है, फिर धीरे-धीरे रिश्तों को जोड़ दें (डेटा के टुकड़े जिन्हें Noteएस के tuples के साथ जुड़े होने की आवश्यकता है ) वर्ग संबंध आरेख के लिए।

एक सी टिप्पणी का एक उदाहरण है Noteवर्ग। एक सी नोट उन गुणों को लौटाएगा जो इस नोट से संबंधित हैं, जैसे कि संबंधित ट्रायड्स, और इसकी सापेक्ष स्थिति ( Interval) जो Scaleकि सी नोट के साथ शुरू होती है

एक ही वर्ग के उदाहरणों के बीच संबंध (उदाहरण के लिए, एक सी नोट और एक नोट के बीच) को गुण के रूप में प्रतिरूपित किया जाना चाहिए, विरासत के रूप में नहीं।

इसके अलावा, आपके उदाहरणों में इंटर-क्लास संबंधों में से कई गुण के रूप में भी अधिक उचित रूप से मॉडल किए गए हैं। उदाहरण:

(कोड उदाहरण लंबित हैं क्योंकि मुझे संगीत सिद्धांत को फिर से सीखना होगा ...)


दिलचस्प विचार, लेकिन हार्मोनिक विश्लेषण के संदर्भ में कॉर्ड गुणों का निर्धारण करने वाला एक व्यक्ति कैसे संभाल करेगा? C कॉर्ड उदाहरण के लिए गुणवत्ता वाली संपत्ति होना आवश्यक है, जो नाबालिग के लिए निर्धारित है (जो ठीक है) लेकिन फिर एक प्रमुख / कम / संवर्धित / मामूली 7s, 9, 11 chords के बारे में क्या? बहुत सारे राग हैं जो एक ही नोट के हो सकते हैं। मैं यह कैसे निर्धारित करूंगा कि कोड के विश्लेषण अनुभाग में विभिन्न प्रकार के तार और उनके संबंधित गुण क्या हैं?
Igneous01

मैं बहुत कम संगीत सिद्धांत जानता हूं, इसलिए मैं आपके प्रश्न का उत्तर देने में सक्षम नहीं हूं। एक तरीका जो मुझे समझने में मदद कर सकता है, वह एक ऐसी तालिका ढूंढना होगा जो उन अवधारणाओं में शामिल सभी नोट्स को सूचीबद्ध करती है। जीवा के लिए प्रश्न अतिरिक्त पैरामीटर ले सकते हैं।
rwong

2
यहाँ सभी संभव chords की एक बहुत अच्छी सूची है: en.wikipedia.org/wiki/List_of_chords सभी chords किसी भी नोट पर लागू किए जा सकते हैं, मेरी स्थिति के साथ जो महत्वपूर्ण है वह यह है कि एनॉर्मोनिक्स सही हैं: अर्थात। Cflat प्रमुख! = बीएमजोर, वे शारीरिक रूप से पियानो पर एक ही राग हैं, लेकिन उनके हार्मोनिक कार्य कागज पर बहुत अलग हैं। मैं सोच रहा हूं कि किसी नोट को शार्प / फ्लैट करने के लिए एक एन्यूमरेटर नोट के उदाहरण के लिए सबसे अधिक समझ में आता है। जिस तरह से C.Sharpen () = C #, और C.Flatten () = Cb, इससे उपयोगकर्ता chords को मान्य करना आसान हो सकता है।
Igneous01

2

मूल रूप से, संगीत नोट आवृत्तियों हैं और संगीत अंतराल आवृत्ति अनुपात हैं।

बाकी सब कुछ उसी पर बनाया जा सकता है।

एक राग अंतराल की एक सूची है। एक पैमाना एक मौलिक नोट और एक ट्यूनिंग सिस्टम है। एक ट्यूनिंग सिस्टम भी अंतराल की एक सूची है।

आप उनका नाम कैसे लेते हैं, यह सिर्फ एक सांस्कृतिक कला है।

विकिपीडिया का संगीत सिद्धांत लेख एक अच्छा प्रारंभिक बिंदु है।


दिलचस्प है, हालांकि मुझे यकीन नहीं है कि अंतर्निहित भौतिक वास्तविकता के संदर्भ में सिस्टम को मॉडल करने के लिए आवश्यक रूप से उपयोगी है। याद रखें, मॉडल को एक विशेष पहलू की कलाकारी में सहायक होना आवश्यक है , जरूरी नहीं कि वह व्यापक या सटीक भी हो। हालांकि आपका दृष्टिकोण सटीक और व्यापक दोनों होगा, लेकिन ओपी के उपयोग के मामले में यह बहुत निम्न स्तर का हो सकता है।
कोनराड रुडोल्फ

@KonradRudolph - अपनी चरम स्थिति के साथ, मैं सिर्फ यह बताना चाहता था कि किसी को प्रेजेंटेशन लेयर के साथ अंतर्निहित मॉडल को नहीं मिलाना चाहिए, एक तरह से डेलाइट सेविंग टाइम के समान: कम्प्यूटेशंस मॉडल पर ही बहुत आसान हैं। मैं सहमत हूं कि सबसे उपयोगी अमूर्त स्तर वह नहीं है जो मैं सुझाता हूं, बल्कि मुझे लगता है कि ओपी द्वारा सुझाया गया अमूर्त स्तर पर्याप्त नहीं है।
मौविसील

इस कार्यक्रम का उद्देश्य संगीत की भौतिक वास्तविकता को प्रदर्शित करना नहीं है। लेकिन सिद्धांत (खुद की तरह) का अध्ययन करने वाले लोगों के लिए केवल कुछ जीवाओं में जल्दी से साजिश करने में सक्षम होना और कार्यक्रम की अपनी सर्वोत्तम क्षमता की व्याख्या करना है कि ये तार एक दूसरे से एक हार्मोनिक अर्थ में कैसे संबंधित हैं। मैं इसे माप द्वारा स्कोर माप को पढ़ने की कोशिश और सही तरीके से विश्लेषण कर सकता हूं, लेकिन चीजों को आसान बनाने के लिए और विश्लेषण करते समय अधिक बारीक विवरण पर ध्यान केंद्रित करने में सक्षम होने के लिए यह एक और उपकरण है।
Igneous01

1

मुझे यह डिसकशन आकर्षक लग रहा है।

क्या नोट मिडी (या किसी प्रकार के टोन कैप्चर डिवाइस) के माध्यम से इनपुट किए जा रहे हैं या उन्हें अक्षरों और प्रतीकों को टाइप करके दर्ज किया जा रहा है?

C से D- शार्प / ई-फ्लैट के अंतराल के मामले में:

यद्यपि डी-शार्प और ई-फ्लैट एक ही स्वर हैं (लगभग 311 हर्ट्ज अगर A = 440 हर्ट्ज), तो C -> D- शार्प के अंतराल को संवर्धित 2 लिखा जाता है, जबकि C -> ई-फ़्लैट के अंतराल को राइटिटम के रूप में लिखा जाता है। मामूली ३। काफी आसान है अगर आप जानते हैं कि नोट कैसे लिखा गया था। यह निर्धारित करने के लिए असंभव है कि क्या आपके पास केवल दो स्वर हैं।

इस मामले में, मेरा मानना ​​है कि आपको .Sharpen () और .Flatten () विधियों जैसे कि .SemiToneUp (), .FullToneDown (), इत्यादि के साथ स्वर को बढ़ाने / घटाने का एक तरीका भी चाहिए। कि आप शार्प / फ़्लैट के रूप में "कलरिंग" के बिना एक पैमाने पर उप-नकली नोट पा सकते हैं।

मुझे @Rotem से सहमत होना होगा कि "C" अपने आप में एक वर्ग नहीं है, बल्कि नोट वर्ग की तात्कालिकता है।

यदि आप एक नोट के लिए गुणों को परिभाषित करते हैं, जिसमें सभी अंतराल शामिल हैं, जैसे कि सेमीटाइन्स, तो प्रारंभिक नोट मान ("C", "F", "G #") की परवाह किए बिना, आप बता पाएंगे कि एक तीन नोट अनुक्रम जिसमें है रूट, प्रमुख 3rd (M3), फिर मामूली 3rd (m3) एक प्रमुख ट्रायड होगा। इसी तरह, एम 3 + एम 3 एक मामूली त्रय है, एम 3 + एम 3 कम, एम 3 + एम 3 संवर्धित है। इसके अतिरिक्त, यह आपको सभी 12 आधार नोटों के लिए स्पष्ट रूप से कोडिंग के बिना 11 वें, कम 13 वें, आदि को खोजने का एक तरीका देगा, और उनके ऊपर और नीचे।

एक बार जब आप कर रहे हैं, आप अभी भी हल करने के लिए कुछ समस्याओं के साथ छोड़ दिया है।

त्रिदोष C, E, G को लें। एक संगीतकार के रूप में, मैं इसे स्पष्ट रूप से काज कॉर्ड के रूप में देखता हूं। हालांकि, मुझ में डेवलपर इस अतिरिक्त को ई माइनर ऑगमेंट 5 (रूट ई + एम 3 + ए 5) या जीसस 4 6 नं 5 वें (रूटजी + 4 + 6) के रूप में व्याख्या कर सकता है।

इसलिए, विश्लेषण करने के बारे में आपके प्रश्न का उत्तर देने के लिए, मुझे लगता है कि विनियामक (मेजर, माइनर, इत्यादि) को निर्धारित करने का सबसे अच्छा तरीका यह होगा कि दर्ज किए गए सभी नोटों को ले जाएं, उन्हें आरोही सेमिटोन मूल्य में व्यवस्थित करें, और ज्ञात कॉर्ड रूपों के खिलाफ उनका परीक्षण करें । फिर, मूल नोट के रूप में दर्ज प्रत्येक नोट का उपयोग करें, और मूल्यांकन का एक ही सेट करें।

आप कॉर्ड फॉर्म को वेट कर सकते हैं ताकि अधिक सामान्य (प्रमुख, मामूली) पूर्ववर्ती, निलंबित, एलेक्ट्रा, आदि कॉर्ड रूपों पर पूर्वता हो, लेकिन एक सटीक विश्लेषण के लिए संभव समाधान के रूप में सभी मिलान कॉर्ड रूपों को प्रस्तुत करने की आवश्यकता होगी।

फिर से संदर्भित विकिपीडिया लेख पिच कक्षाओं को सूचीबद्ध करने का एक अच्छा काम करता है, इसलिए इसे कॉर्ड के मॉडल को कोड करने के लिए सरल (यद्यपि थकाऊ) होना चाहिए, दर्ज किए गए नोट्स लें, उन्हें पिच कक्षाओं / अंतरालों को असाइन करें, और फिर तुलना करें मैचों के लिए ज्ञात रूपों के खिलाफ।

यह बहुत मजेदार रहा है। धन्यवाद!


उन्हें अभी के लिए पाठ के माध्यम से इनपुट किया जा रहा है। हालाँकि बाद में मैं मिडी का उपयोग करने में सक्षम हो सकता है यदि प्रोग्राम ठीक से एनकैप्सुलेटेड है। बेबी अभी कदम: डी
Igneous01

0

टेम्पलेट्स के लिए एक मामले की तरह लगता है। आप एक है लगता है template <?> class Major : public Chord;तो Major<C>है-एक 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 पूर्णांकों के एक और बफर को पीछे छोड़ें, जब शीर्ष नोट की स्थिति सूचकांक में बफ़र के मान के समान हो, तो रोकें, फिर से यह केवल आगे बढ़ रहा है। लेकिन ऑफसेट कहीं भी हो सकता है (यानी। बफर .at (-10))

अब मैं दोनों व्याख्या अंतराल, और दोनों के बीच भौतिक दूरी को जानता हूं। इसलिए अंतराल का नाम पहले से ही आधा है।

अब मैं अंतराल की व्याख्या करने में सक्षम हूं, अर्थात। यदि अंतराल 5 है, और दूरी 8 है, तो यह संवर्धित 5 वीं है।

अभी तक नोट और अंतराल उम्मीद के मुताबिक काम कर रहे हैं, अब मुझे केवल कॉर्ड आइडेंटिफ़ायर से निपटना है।

फिर से धन्यवाद, मैं इनमें से कुछ प्रतिक्रियाओं को फिर से लिखूंगा और कुछ विचारों को यहां शामिल करूंगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.