एक मिडी ट्रैक प्रदर्शित करें


17

पृष्ठभूमि

मिडी फाइलें WAV या MP3 ऑडियो फाइलों से काफी अलग होती हैं। MP3 और WAV फ़ाइलों में ऑडियो की "रिकॉर्डिंग" का प्रतिनिधित्व करने वाले बाइट्स होते हैं, जबकि MIDI फ़ाइलों में MIDI इवेंट्स में संग्रहीत MIDI संदेशों की एक श्रृंखला होती है, जो MIDI सिंथेसाइज़र को बताती है कि कौन सा वाद्य यंत्र बजाना है या MIDI सीक्वेंसर प्लेबैक टेम्पल 2 का उपयोग किया जाना चाहिए। ये संदेश पटरियों में संग्रहीत किए जाते हैं, और पटरियों का एक संग्रह एक MIDI अनुक्रम बनाता है, जिसकी घटनाओं का विश्लेषण एक अनुक्रमक द्वारा किया जा सकता है और इसके संदेश क्रमांक से एक सिंथेसाइज़र रिसीवर को प्रेषित होते हैं।

अधिकांश समय मिडी घटनाओं में संग्रहीत मिडी संदेश नोट ऑन संदेश होते हैं जो सिंथेसाइज़र को एक विशेष नोट चलाने के लिए कहते हैं, या नोट बंद करने वाले संदेश बताते हैं जो सिंथेसाइज़र को नोट चलाने से रोकते हैं। इन संदेशों में दो डेटा बाइट्स होते हैं, जिनमें से पहला नोट के वेग के सिंथेसाइज़र को सूचित करता है (उच्च वेग एक ज़ोर नोट में), और दूसरा जो सिंथेसाइज़र को नोट को खेलने के लिए कहता है (अर्थात मध्य C)। घटनाओं में स्वयं भी टिक होते हैं जो संदेश भेजने के लिए सीक्वेंसर को बताने के उद्देश्य से काम करते हैं।

चुनौती

चुनौती एक पूर्ण कार्यक्रम या एक फ़ंक्शन लिखने की है जो एक एकल-ट्रैक मिडी अनुक्रम में नोट ऑन और नोट ऑफ मिडी संदेशों की एक श्रृंखला का विश्लेषण करती है और किसी विशेष चार्ट के बंद होने पर, और जब वे बंद होते हैं, तब चार्ट दिखाने के लिए आउटपुट करते हैं। इन नोटों का वेग। चार्ट का ऊर्ध्वाधर अक्ष नोट मान का प्रतिनिधित्व करता है और इसे नीचे वर्णित के रूप में लेबल किया जाना चाहिए, और क्षैतिज अक्ष MIDI टिक्स में समय का प्रतिनिधित्व करता है (हालांकि यह जटिलता और रिक्ति के मुद्दों को कम करने के लिए बिना लेबल के रहना चाहिए)।

आपका इनपुट चार अलग-अलग सरणियाँ या सूचियां हो सकती हैं, जिनमें से प्रत्येक पूर्णांक मानों की एक श्रृंखला होती है; द्वि-आयामी सरणी या सूची जिसमें पूर्णांक मानों की एक श्रृंखला के साथ चार उप-सरणियाँ / उप-सूचियाँ होती हैं; या किसी अन्य सुविधाजनक साधन; यह ट्रैक में नोट ऑन और नोट ऑफ संदेशों के साथ संग्रह MIDI घटनाओं का प्रतिनिधित्व करता है। इन सरणियों में से पहला मान नोट निर्दिष्ट करता है, दूसरा वेग, तीसरा नोट इवेंट टिक पर, और चौथा नोट ऑफ इवेंट टिक। उदाहरण के लिए, इन के रूप में चार सरणियाँ दी गई हैं:

{60, 62, 64, 65,  67}
{20, 40, 60, 80, 100}
{ 0,  4,  8, 12,  16}
{ 2,  6, 10, 14,  18}

प्रत्येक ऐरे के पहले तत्व का विश्लेषण करने से दो ईवेंट मिलते हैं: टिक 0 पर एक ईवेंट जिसमें एक संदेश है जिसमें नोट ऑन कमांड, नोट 60 (मध्य C), और 20 के नोट का वेग है; और टिक 2 पर एक घटना जिसमें एक संदेश है जिसमें एक ही नोट और वेग के साथ नोट ऑफ कमांड है।

नियम

चार्ट को बाईं ओर घटते क्रम में प्रदर्शित संख्या (नोट मान का प्रतिनिधित्व करते हुए) के माध्यम से 0 की संख्या को 127 तक पहुंचाना चाहिए, जब नोट शुरू होता है, प्रत्येक नोट की अवधि (नोट ऑफ टिक टिक नोट नोट पर टिक), और नोट का वेग। नोटों का प्रतिनिधित्व करने वाले प्रतीक उनके वेग पर निर्भर हैं:

  • 0-15: O
  • 16-31: =
  • 32-47: #
  • 48-63: -
  • 64-79: @
  • 80-95: +
  • 96-111: 0
  • 112-127: *

आप निम्नलिखित मान सकते हैं:

  • नोट और वेग के मान सीमा [0, 127] के भीतर होंगे।
  • चार सरणियों में से प्रत्येक की लंबाई हमेशा एक दूसरे के बराबर होगी।

कुछ उदाहरण निम्नलिखित हैं:

{60, 62, 64, 65,  67}
{20, 40, 60, 80, 100}
{ 0,  4,  8, 12,  16}
{ 2,  6, 10, 14,  18}

127|
126|
125|
...
67 |                00
66 |
65 |            ++
64 |        --
63 |
62 |    ##
61 |
60 |==
59 |
...
2  |
1  |
0  |


{60, 48, 62, 47, 64, 45,  65,  43, 67, 41, 65, 43, 64, 45,  62, 47, 60, 48}
{63, 31, 75, 90, 12, 23, 122, 104, 33, 19, 57, 42,  5, 82, 109, 86, 95, 71}
{0,   0,  2,  2,  4,  4,   6,   6,  8,  8, 10, 10, 12, 12,  14, 14, 16, 16}
{2,   2,  4,  4,  6,  6,   8,   8, 10, 10, 12, 12, 14, 14,  16, 16, 18, 18}

127|
126|
...
68 |
67 |        ##
66 |
65 |      **  --
64 |    OO      OO
63 |
62 |  @@          00
61 |
60 |--              ++
59 |
...
49 |
48 |==              @@
47 |  ++          ++
46 |
45 |    ==      ++
44 |
43 |      00  ##
42 |
41 |        ==
40 |
...
1  |
0  |

यहाँ एक उदाहरण है जो Ode to Joy के पहले कुछ नोट्स प्रदर्शित करता है:

{48, 55, 64, 64, 65, 67, 55, 67, 65, 64, 62, 52, 55,  60,  60,  62,  64,  55, 64, 62, 62}
{45, 45, 63, 63, 63, 63, 89, 66, 66, 66, 66, 30, 30, 103, 103, 103, 103, 127, 55, 55, 55}
{ 0,  0,  0,  4,  8, 12, 16, 16, 20, 24, 28, 32, 32,  32,  36,  40,  44,  48, 48, 54, 56}
{16, 16,  2,  6, 10, 14, 32, 18, 22, 26, 30, 48, 48,  34,  38,  42,  46,  64, 50, 55, 64}

127|
...
67 |            --  @@
66 |
65 |        --          @@
64 |--  --                  @@                  00  --
63 |
62 |                            @@          00            - --------
61 |
60 |                                00  00
59 |
58 |
57 |
56 |
55 |################++++++++++++++++================****************
54 |
53 |
52 |                                ================
51 |
50 |
49 |
48 |################
...
0  |

यदि आपका सबमिशन इनपुट के रूप में वास्तविक MIDI अनुक्रम लेता है, तो आप अपने स्कोर को 25% तक कम कर सकते हैं , अपने चयन के किसी भी ट्रैक के नोट ऑन और नोट ऑफ संदेशों का विश्लेषण करते हैं, बशर्ते इसमें नोट ऑन और नोट ऑफ संदेशों के साथ कम से कम चार इवेंट हों, और आउटपुट जैसा कि ऊपर वर्णित है एक चार्ट।

यह कोड गोल्फ है, इसलिए सबसे छोटा कोड जीतता है। सौभाग्य!

जवाबों:


6

PHP , 127 + 571 = 698 कुल स्कोर *

ठीक है, मैं बोनस का दावा कर रहा हूं। :) यह एक मानक मिडी फ़ाइल लेगा और आउटपुट प्रदर्शित करेगा।

मैंने स्कोर को मुख्य चुनौती में बदल दिया है (स्कोर / नोट पर विश्लेषण करें और चार्ट के रूप में प्रदर्शित करें) और स्कोर को अधिक तुलनीय बनाने के लिए बोनस चुनौती (मानक मिडी से इनपुट पढ़ें)।

मुख्य: 170 बाइट्स - 25% = 127

मुख्य के लिए, फ़ंक्शन $d()आवश्यक सरणी लेता है और ASCII आउटपुट प्रदर्शित करता है। नीचे परीक्षण मिडी फ़ाइल के सभी परीक्षण और आउटपुट शामिल हैं।

$d=function($a){for($l=max($n=$a[0]);$l>=min($n);){$r=' |';foreach($n as$c=>$e)while($e==$l&$a[2][$c]<$a[3][$c])$r[++$a[2][$c]+1]='O=#-@+0*'[$a[1][$c]/16];echo$l--,$r,"
";}}

इसे ऑनलाइन आज़माएं!

बोनस: 761 बाइट्स - 25% = 571

फ़ंक्शन $m()एक मानक मिडी फ़ाइल (या तो स्थानीय या URL से) लोड करेगा और पटरियों की एक सरणी लौटाएगा, जिनमें से प्रत्येक MIDI फ़ाइल ट्रैक्स के लिए निर्दिष्ट नोट प्रारूप में एक सरणी होगी।

$m=function($f){$a=function($f){do$s=($s<<7)+(($c=unpack(C,fread($f,1))[1])&127);while($c&128);return$s;};$r=function($n){foreach($n as$e){if($e[4]==9&&$e[1]>0)foreach($n as$y=>$f)if($f[0]==$e[0]&&($f[4]==8||($f[4]==9&&$f[1]==0))){$o[0][]=$e[0];$o[1][]=$e[1];$o[2][]=$e[2];$o[3][]=$f[2];$n[$y][4]=0;break;}}return$o;};$m=fopen($f,r);while($b=fread($m,8)){$z=unpack(N2,$b)[2];if($b[3]==d){$k=unpack(n3,fread($m,$z))[3]/4;}else{$t=0;$n=[];$d=ftell($m)+$z;while(ftell($m)<$d){$t+=$a($m);if(($e=unpack(C,fread($m,1))[1])==255){fread($m,1);if($w=$a($m))fread($m,$w);}else{if($e>127)list(,$e,$h)=unpack('C*',fread($m,($y=(240&$e)>>4)==12?1:2));else$h=unpack(C,fread($m,1))[1];if($y==9|$y==8)$n[]=[$e,$h,(int)round($t/$k),0,$y];}}if($n)$u[]=$r($n);}}fclose($m);return$u;};

इसे ऑनलाइन देखें! जाहिर है कि TIO को सैंडबॉक्स किया जाता है ताकि दूरस्थ अनुरोधों या स्थानीय फ़ाइलों की अनुमति न हो, इसलिए आपको इसे कार्रवाई में देखने के लिए स्थानीय रूप से इस कोड को चलाना होगा। प्रदर्शन समारोह में पहले [परीक्षण] [TIO-jrwa60tu] परीक्षण मिडी फ़ाइल से सरणी परिणाम शामिल हैं ।

मिडी फ़ाइल लोड दिनचर्या असंक्रमित:

$m=fopen($f,'r');                           // m = midi file handle
while($b=fread($m,8)){                      // read chunk header
    $z=unpack('N2',$b)[2];                  // z = current chunk size
    if($b[3]=='d'){                         // is a header chunk?
        $k=unpack('n3',fread($m,$z))[3]/4;  // k = ticks per quarter note (you can change the 4 to 8 or 16 to "zoom in" so each char represents eights or sixteenth notes)
    }else{                                  // is a track chunk?
        $t=0;                               // track/chunk time offset starts at 0
        $d=ftell($m)+$z;                    // d = end of chunk file pos
        while(ftell($m)<$d){                // q = current file pos
            $t+=$a($m);                     // decode var length for event offset and add to current time
            if(($e=unpack('C',fread($m,1))[1])==255){ // is a META event 
                fread($m,1);                // read and discard meta event type
                if($w=$a($m))
                    fread($m,$w);
            }else{                          // is a MIDI event
                if($e>127) {                // is a new event type
                    list(,$e,$h)=unpack('C*',  // if is a prog change (0x0c), event is 1 byte
                        fread($m,($y=(240&$e)>>4)==12?1:2)); // otherwise read 2 bytes
                } else {                    // is a MIDI "streaming" event, same type as last
                    $h=unpack('C',fread($m,1))[1];
                }
                if($y==9|$y==8)             // if is a Note On or Note Off
                    $n[]=[$e,$h,(int)round($t/$k),0,$y];  // add note to output
            }
        }
        if($n)                              // if this track has notes,
            $u[]=$r($n);                    // add to array of output tracks ($u)
    }
}
fclose($m); // yes, could golf this out and rely on PHP GC to close it

"ओड टू जॉय" की एक परीक्षण मिडी फ़ाइल जिसे यहां डाउनलोड किया जा सकता है । उदाहरण का उपयोग करें:

$d( $m( 'beethoven_ode_to_joy.mid' )[0] );      // display first track

$d( $m( 'https://www.8notes.com/school/midi/piano/beethoven_ode_to_joy.mid' )[0] );

foreach( $m( 'multi_track_song.mid' ) as $t ) {  // display all tracks
    $d( $t );
}

"ऑड टू जॉय" मिडी फ़ाइल आउटपुट

67 |            0000++++                                                        00000000                                                                                                                        00000000
66 |
65 |        0000        ++++                                                0000        0000                                                              @@              @@                                0000        ++++
64 |++++++++                ++++                0000000000          00000000                0000                0000                        @@@@        @@  ----        @@  ----                ++++++++++++                ++++                0000
63 |
62 |                            ++++        0000          00++++++++                            ++++        0000    000000          @@@@----        ----            @@@@        ----    ----                                    ++++        0000    000000
61 |
60 |++++                            ++++0000                        0000                            ++++0000              ++00000000            ----            ----                ----            00000000                        ++++0000    ****      ++00000000
59 |                                                        ++++++++
58 |                                                                                                                                                                                                        00000000
57 |                                                                                                                                                                                ----                            ++++++++
56 |                                                                                                                                                                        --------
55 |++++++++++++++++++++++++00000000000000000000000000000000++++++++00000000000000000000000000000000000000000000000000000000        ----------------------------------------                --------                                        0000    ++++++++00000000
54 |                                                                                                                                                                                    ----
53 |                                                                                                                                                                                                                        ++++++++
52 |                                0000000000000000                                                0000000000000000                                                                                                                ++++0000                00000000
51 |
50 |
49 |
48 |++++++++++++++++                0000000000000000                0000000000000000                0000000000000000        ++++++++                                                                                                                        00000000

टिप्पणियाँ

मिडी प्रारूप में, नोट पर / नोट ऑफ ईवेंट परमाणु हैं, जिसका अर्थ है कि आप किसी दिए गए नोट के लिए एक निश्चित समय पर एक नोट ईवेंट देखते हैं (ई 5 कहते हैं), और यह निहित है कि यह किसी अन्य ई 5 नोट के लिए ईवेंट बंद होने तक चलेगा। देखा गया। इस प्रकार, मिडी घटनाओं का विश्लेषण करना और दिए गए नोट ऑन टू इट नोट को मैच करना आवश्यक है, जो कि इसके लिए कोड है297184 बाइट्स। इसे और जटिल करते हुए, बाद के मिलान नोट को देखने के लिए मानक मिडी प्रारूप में यह काफी सामान्य है। वेग 0 के साथ नोट ऑफ के समान चीज़ का प्रतिनिधित्व करता है।

यह अब उन फ़ाइलों को सही ढंग से पढ़ेगा जिनमें नोट-ऑफ के बजाय शून्य-वेग नोट ऑन है, इसलिए अधिकांश मानक फाइलें खोलनी चाहिए।

चेतावनियां

यह किसी भी तरह से मिडी प्रारूप का पूर्ण कार्यान्वयन नहीं है, हालांकि मैंने मिडी फाइलों के काफी व्यापक संग्रह के साथ इसका परीक्षण किया है और यह उन सभी को अच्छी तरह से पढ़ता है।

यह सबमिशन अभी तक चरम पर नहीं पहुंचाया गया है, इसलिए पूरी तरह से संभावना है कि इसे छोटा किया जा सकता है। मुझे लगता है कि यह बहुत कम संभावना है कि 25% स्कोर कम करने वाला बोनस एक मानक मिडी फ़ाइल को पढ़ने के लिए आवश्यक कोड को ऑफसेट करेगा। जैसा कि (करंट) सबसे छोटा सबमिशन जो सिर्फ ASCII डिस्प्ले करता है106 65 बाइट्स में, इसे लागू करने के लिए MIDI फ़ाइल रूटीन की आवश्यकता होगी 2521 बाइट्स को हराया। मैं किसी को भी ऐसा करने के लिए चुनौती दूंगा (बिना किसी भाषा में निर्मित या मॉड्यूल का उपयोग किए)। :)


यह एक कमाल का जवाब है। इस चुनौती को देखते हुए, मैं इस बात से सहमत हूं कि बोनस राशि संभवत: MIDI फ़ाइल पढ़ने के ओवरहेड खाते के लिए स्कोर को कम नहीं करेगी। (मुझे लगता है कि बोनस आजकल वैसे भी हतोत्साहित किया जाता है।) फिर भी मैं बहुत प्रभावित हूं कि आपने बोनस चुनौती ली। मैं आपको इसके लिए एक अच्छा इनाम दे सकता हूं।
टीएनटी

@TNT, धन्यवाद! वास्तव में इसे करने में मज़ा आया और यह एसएमएफ के रूप में नासमझ के रूप में कुछ के लिए गोल्फ फ़ाइल प्रारूप दिनचर्या के लिए दिलचस्प था। बड़ी चुनौती!
640KB

5

रूबी, 106 बाइट्स

यह मजेदार था। मुझे यकीन नहीं है कि किसी ने इसका प्रयास क्यों नहीं किया।

यह फ़ंक्शन चार सरणी तर्कों के रूप में इनपुट लेता है और स्ट्रिंग की एक सरणी देता है, चार्ट की प्रत्येक पंक्ति के लिए।

->a,*r{q=(0..z=127).map{|i|"%3d|"%(z-i)+" "*1e4}
a.zip(*r){|n,v,o,f|q[z-n][o+4]="O=#-@+0*"[v/16]*(f-o)}
q}

नोट: यह मनमाने ढंग से मानता है कि 10,000 से अधिक टिक नहीं होंगे। यदि आप इसे अपने टर्मिनल में चलाते हैं तो मेरा सुझाव है कि lessआप इसे पाइपिंग करें ताकि आप क्षैतिज रूप से स्क्रॉल कर सकें। 1e4यदि आप अधिक टिक चाहते हैं, तो सभी तरह से बदल सकते हैं 9e9, लेकिन यह एक टेराबाइट या दो रैम लेगा।

इसे repl.it पर देखें: https://repl.it/Cx4I/1


प्रस्तुत करने के लिए धन्यवाद! लेकिन अजीब तरह से मैं आउटपुट को उत्तर पर देखने में असमर्थ हूं (सभी मैं देख सकता हूं कि उनके बीच बहुत अधिक रिटर्न के साथ संख्या 127-0 है)। मैंने पहले कभी उत्तर का उपयोग नहीं किया है इसलिए मुझे पता नहीं चलेगा, हालांकि। क्या आप मेरे लिए आउटपुट को ठीक से देखने का कोई तरीका सुझा सकते हैं?
टीएनटी

यह बहुत अजीब है। इससे मेरा काम बनता है। मैं अभी कंप्यूटर पर नहीं हूँ, लेकिन यहाँ मेरे फोन से एक स्क्रीनशॉट है: i.stack.imgur.com/3UCyn.jpg
जॉर्डन

स्क्रीनशॉट के लिए धन्यवाद। मुझे लगता है कि समस्या वेब ब्राउज़र का उपयोग कर सकती है जो मैं उपयोग कर रहा हूं, इसलिए मैं बाद में इसे अलग तरीके से आज़माऊंगा। हालांकि मुझ से +1। :)
टीएनटी

2

अजगर 2, 163 160 156 145 बाइट्स

यह ऐसा करने का गोल्फ का तरीका नहीं है, लेकिन यह सबसे सरल में से एक था। अगर मैं यह पता लगा सकूं कि स्ट्रिंग्स के कुछ हिस्सों को लिस्ट में बदले बिना, रिप्लेस करके, और उन्हें वापस स्ट्रिंग्स में बदल दिया जाए, तो यहाँ बहुत मदद मिलेगी। गोल्फ सुझाव का स्वागत करते हैं।

संपादित करें: 18 बाइट्स लीक नन के लिए धन्यवाद। Ideone पर यह कोशिश करो !

a=input();z=[" "*max(a[3])]*128
for n,v,b,e in zip(*a):z[n]=z[n][:b]+"O=#-@+0*"[v/16]*(e-b)+z[n][e:]
for i in range(128)[::-1]:print"%3d|"%i+z[i]

@LeakyNun व्हाट्स, मेरा बुरा
लोवजो

क्या आप नियमित अभिव्यक्ति प्रतिस्थापन का उपयोग कर सकते हैं? रूबी में ऐसा कुछ है जो str.sub(/(?<=.{20}).{3}/,"foo")इसके बराबर है str[20,3] = "foo"। बेशक, इसका मतलब है कि सूचकांक / लंबाई चर के साथ स्ट्रिंग प्रक्षेप / संघनन द्वारा रेगेक्सपी का निर्माण करना - जो रूबी बाइट्स में सस्ता है, लेकिन शायद पायथन में नहीं।
जॉर्डन

1

जाप , 65 बाइट्स

®Æ"O=#-@+0*"gXzG
#€Çs ú3 +'|ÃúUmg2 rÔ+5
£VhXÎVgXv)hXÎ+4Xo pXra
Vw

इसे ऑनलाइन आज़माएं!

प्रारूप में नोटों की सूची के रूप में इनपुट लेता है [pitch, start_tick, end_tick, velocity]। यदि अलग-अलग सूचियों के रूप में इनपुट लेना अनिवार्य है (यानी एक सूची जिसमें सभी पिचों में से एक है, जिसमें सभी वेग आदि शामिल हैं), जिसे लागत पर पूरा किया जा सकता है 1 बाइट

स्पष्टीकरण:

®Æ"O=#-@+0*"gXzG          #Gets the velocity character to use for each note
®                         # For each note in the input
 Æ                        # Replace the last item X with:
             XzG          #  Integer divide X by 16
  "O=#-@+0*"g             #  Get the character at that index in the string "O=#-@+0*"

#€Çs ú3 +'|ÃúUmg2 rÔ+5    #Generate the blank chart
#€Ç        à              # For each number X in the range [0...127]:
   s                      #  Turn X into a string
     ú3                   #  Right-pad with spaces until it is 3 characters long
        +'|               #  Add "|" to the end
            ú             # Right pad each of those with spaces to this length:
             Umg2         #  Get all the end_tick values
                  rÔ      #  Find the largest one
                    +5    #  Add 5

£VhXÎVgXv)hXÎ+4Xo pXra    #Put the notes into the chart
£                         # For each note:
     VgXv)                #  Get a line from the chart based on the note's pitch
          h               #  Overwrite part of that line:
           XÎ+4           #   Starting at index start_tick +4
               Xo         #   Overwrite characters with the velocity character
                  pXra    #   For the next end_tick - start_tick characters
 VhXÎ                     #  Put the modified line back into the chart

Vw                        #Print the chart
V                         # Get the chart
 w                        # Reverse it (so 127 is the first line)
                          # Implicitly print it
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.