2016-06-06 10 views
5

मैं सोच रहा था कि PHP में एक फ़ंक्शन कैसे बनाया जाएगा, जिसका उपयोग कुछ संगीत तारों को स्थानांतरित करने के लिए किया जाता है।PHP के साथ संगीत तारों को कैसे स्थानांतरित करें?

मैं यह समझाने की कोशिश करूंगा कि यह संगीत सिद्धांत में कैसे काम करता है। मुझे आशा है कि मैं कुछ नहीं भूलूंगा। अगर कुछ गलतियां हैं, तो कृपया इसे ठीक करने में मेरी सहायता करें।


1. सरल तार।

सरल chords लगभग के रूप में एक वर्णमाला के रूप में सरल हैं और यह इस प्रकार है:

सी, सी #, डी, डी #, ई, एफ, एफ #, जी, जी #, ए, ए # बी

बी से यह फिर से सी पर लूप करता है। इसलिए, यदि मूल तार E है और हम +1 को ट्रांसफर करना चाहते हैं, परिणामी तार F है। यदि हम +4 को स्थानांतरित करते हैं, तो परिणामस्वरूप तार G# है।

2. विस्तारित तार।

वे लगभग साधारण तारों की तरह काम करते हैं, लेकिन कुछ और वर्ण होते हैं, जिन्हें ट्रांसपोज़ करते समय सुरक्षित रूप से अनदेखा किया जा सकता है।

CMI, सी # 7, Dsus7, ईएमआई, Fsus4, एफ # मील, जी ...

तो फिर, सरल chords के साथ के रूप में, हम स्थानांतरित करता है, तो Dsus7 + 3: उदाहरण के लिए = Fsus7

3. गैर रूट बास टोन।

समस्या तब उत्पन्न होती है जब बास कोर रूट टोन की तुलना में एक अलग स्वर बजाता है। यह तार के बाद एक स्लैश द्वारा चिह्नित किया जाता है और इसे भी स्थानांतरित करने की आवश्यकता होती है। उदाहरण:

सी/जी, Dmi/ए, एफ # sus7/A #

1 2 उदाहरण और साथ के रूप में, सब कुछ एक ही है, लेकिन स्लेश जरूरतों के बाद वाले हिस्से भी स्थानांतरित, इसलिए :

C/G + 5 = F/C

F#sus7/A# + 1 = Gsus7/B


तो मूल रूप से, कल्पना करें कि आपके पास एक PHP चर है जिसे chord और ट्रांसपोज़र मान transpose कहा जाता है। कौन सा कोड तार को स्थानांतरित करेगा?

उदाहरण:

var chord = 'F#sus7/C#'; 
var transpose = 3; // remember this value also may be negative, like "-4" 
... code here ... 
var result; // expected result = 'Asus7/E'; 

मैं StackOverflow, at here पर एक ही अस्तित्व में सवाल मिल गया है। वे तार-प्रगति के लिए एल्गोरिदम के बारे में बात करते हैं।


मैं PHP के साथ संगीत chords कैसे स्थानांतरित करते हैं, बढ़ाने या semitones द्वारा कम करके?

+1

SO में आपका स्वागत है। कृपया पढ़ें [मैं किस विषय के बारे में पूछ सकता हूं] (http://stackoverflow.com/help/on-topic) और [एक अच्छा सवाल कैसे पूछें] (http://stackoverflow.com/help/how-to -स्क) और [सही सवाल] (http://codeblog.jonskeet.uk/2010/08/29/writing-the-perfect-question/) SO ** एक मुफ्त कोडिंग या कोड रूपांतरण नहीं है या ट्यूटोरियल या पुस्तकालय खोज सेवा ** आपको यह भी दिखाना होगा कि आपने अपनी समस्या को हल करने के लिए कुछ प्रयास किए हैं। – RiggsFolly

+0

@lvk मेरी पहली टिप्पणी में लिंक पढ़ें! – RiggsFolly

+1

ऐसा लगता है कि आपको कोई समस्या है, लेकिन आपने समाधान का पता लगाने की भी कोशिश नहीं की है। क्या आपने अभी तक एक फ़ंक्शन लिखने का प्रयास किया है? आप लोगों को यहां आपके लिए कोड लिखने के लिए नहीं मिलेगा, ऐसा नहीं है कि यह कैसे काम करता है। हम उन चीजों को ठीक करने में मदद करते हैं जो काम नहीं कर रहे हैं लेकिन आपने शुरुआत नहीं की है। ऐसा लगता है कि आपको 'सरणी' ('सी', 'सी #') जैसे एक एसोसिएटिव सरणी बनाने की आवश्यकता है और फिर आप इच्छित मूल्य प्राप्त करने के लिए सरणी में इंडेक्स की तुलना करना शुरू कर सकते हैं। – Jimbo

उत्तर

0

ठीक है, तो कुछ ऐसी चीजें हैं जिन्हें आप संभालना चाहते हैं।

सबसे पहले, आप सरणी में चारों ओर लूप करने में सक्षम होना चाहते हैं। यह आसान है: modulus ऑपरेटर का उपयोग करें, जो php में % है।

function transpose($chord, $increment) { 
    $map = array('A', 'A#', 'B', 'C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#'); 

    // Get the index of the given chord 
    $index = array_search($chord, $map); 
    if($index === false) 
    return false; 

    // Get the transposed index and chord 
    $transpose_index = ($index + $increment) % count($map); 
    if($transpose_index < 0) 
    $transpose_index += count($map); 
    return $map[$transpose_index]; 
} 

दूसरा, आप वास्तविक चीजों को बाहर करने में सक्षम होना चाहते हैं जो आपके लिए महत्वपूर्ण हैं। आप का उपयोग कर ऐसा कर सकते हैं regular expression (RegEx):

function transposeFull($chords, $increment) { 

    // This RegEx looks for one character (optionally followed by a sharp). 
    //  .\#? 
    // This RegEx looks for an optional series of characters which are not/
    //  [^\/]* 
    // Put them together to get a RegEx that looks for an expanded chord 
    //  (.\#?)([^\/]*) 
    // Then, do it again, but add a/first, and make it optional. 
    //  (\/(.\#?)([^\/]*))? 
    $regex = '%(.\#?)([^\/]*)(\/(.\#?)([^\/]*))?%'; 

    // Note that the() allow us to pull out the matches. 
    // $matches[0] is always the full thing. 
    // $matches[i] is the ith match 
    // (so $matches[3] is the whole optional second chord; which is not useful) 
    $matches = array(); 
    preg_match($regex, $chords, $matches); 

    // Then, we get any parts that were matched and transpose them. 
    $chord1 = (count($matches) >= 2) ? transpose($matches[1], $increment) : false; 
    $expanded1 = (count($matches) >= 2) ? $matches[2] : ''; 
    $chord2 = (count($matches) >= 5) ? transpose($matches[4], $increment) : false; 
    $expanded2 = (count($matches) >= 6) ? $matches[5] : ''; 

    // Finally, put it back together. 
    $chords = ''; 
    if($chord1 !== false) 
    $chords .= $chord1.$expanded1; 
    if($chord2 !== false) 
    $chords .= '/'.$chord2.$expanded2; 

    return $chords; 
} 
1

एक त्वरित समाधान:

<?php 

// produces the expected result 
echo transpose("F#sus7/C#",3); 

function transpose($chord,$transpose) 
{ 
    // the chords 
    $chords = array("C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"); 

    $result = ""; 

    // get root tone 
    $root_arr = explode("/",$chord); 
    $root = strtoupper($root_arr[0]); 

    // the chord is the first character and a # if there is one 
    $root = $root[0].((strpos($root, "#") !== false)?"#":""); 

    // get any extra info 
    $root_extra_info = str_replace("#","",substr($root_arr[0],1)); // assuming that extra info does not have any # 

    // find the index on chords array 
    $root_index = array_search($root,$chords); 
    // transpose the values and modulo by 12 so we always point to existing indexes in our array 
    $root_transpose_index = floor(($root_index + $transpose) % 12); 

    if ($root_transpose_index < 0) 
    { 
     $root_transpose_index += 12; 
    } 

    $result.= $chords[$root_transpose_index].$root_extra_info; 

    if(count($root_arr)>1) 
    { 
     // get the non root tone 
     $non_root = $root_arr[1]; 
     // the chord is the first character and a # if there is one 
     $non_root = strtoupper($non_root[0]).((strpos($non_root, "#") !== false)?"#":""); 
     // get any extra info 
     $non_root_extra_info = str_replace("#","",substr($root_arr[1],1)); // assuming that extra info does not have any # 

     // find the index on chords array 
     $non_root_index = array_search($non_root,$chords); 
     // transpose the values and modulo by 12 so we always point to existing indexes in our array 
     $non_root_transpose_index = floor(($non_root_index + $transpose) % 12); 

     if ($non_root_transpose_index < 0) 
     { 
      $non_root_transpose_index += 12; 
     } 

     $result.= "/".$chords[$non_root_transpose_index].$non_root_extra_info; 
    } 

    return $result; 
} 

https://3v4l.org/Cd9Pg

कोड में सुधार की गुंजाइश के बहुत सारे, मैं सिर्फ समझने में आसान होने के लिए यह कोड करने के लिए करने की कोशिश की ।

+0

यदि आप किसी फ़ंक्शन में अपने 'स्प्लिट' के हिस्सों को संभाले हैं तो आप कुछ कोड पुनरावृत्ति से बच सकते हैं। मुझे लगता है कि आपके विचार को मेरे '(। \ #?) ([^ \ /] *) के साथ'/'पर विभाजित करने के लिए संयोजन है। 'RegEx को सबसे साफ कोड मिलेगा। – Kittsil

+0

@ किट्सिल हां सुधार के लिए बहुत सी जगह है। दुर्भाग्यवश, मैं एटीएम पर काम करता हूं इसलिए इस पर काम करने के लिए और अधिक समय उपलब्ध नहीं है - मैंने इसे अपने लंच ब्रेक में बनाया है:/कम से कम यह समझना आसान है: डी – Sharky

1

यहां मेरा रेगेक्स विचार preg_replace_callback (anonymous function का उपयोग PHP 5.3 की आवश्यकता है)।

function transpose($str, $t=0) 
{ 
    // the chords 
    $chords = ["C","C#","D","D#","E","F","F#","G","G#","A","A#","B"]; 

    // set transpose, return if none 
    $t = (int)$t % 12 + 12; if($t % 12 == 0) return $str; 

    // regex with callback 
    return preg_replace_callback('~[A-G]#?~', function($m) use (&$chords, &$t) { 
    return $chords[(array_search($m[0], $chords) + $t) % 12]; 
    }, $str); 
} 

Demo at eval.in  

echo transpose("Cmi, C#7, Dsus7, Emi, Fsus4, F#mi, G C/G, Dmi/A, F#sus7/A#", -3); 

अमी, एक # 7 (परीक्षण regex pattern [A-G]#? see regex101 के लिए), Bsus7, सी # मील, Dsus4, डी # मील, ईए/ई, बीएमआई/एफ #, डी # एसएस 7/जी

+1

अच्छा! आप '$ टी' के सामान्यीकरण को '$ t = (int) $ t% 12 + 12 के साथ सरल बना सकते हैं;'। – trincot

+0

@trincot धन्यवाद (: मैं आपके सुधार का परीक्षण करूंगा और उत्तर में जोड़ूंगा। –

+0

@trincot [इस बारे में कैसे?] (Https://eval.in/587175) –

संबंधित मुद्दे