मेरे लिए एक गाना चलाएं


23

चुनौती

गिटार की झांकी को देखते हुए आपको टैब द्वारा प्रस्तुत गीत का उत्पादन करना चाहिए। यह आपके कंप्यूटर के स्पीकर या ऑडियो फ़ाइल (.wav, .mp3, .midi, .aiff, आदि) के लिए हो सकता है। टाइमिंग के लिए दूसरा इनपुट भी होगा।

टैब एक फ़ाइल के माध्यम से या सीधे STDIN के लिए इनपुट हो सकता है। टैब ASCII फॉर्म में होगा ।

कल्पना

सभी टैब मानक ई ट्यूनिंग के साथ 6 छह स्ट्रिंग गिटार के लिए हैं: ई 2 (82.41 हर्ट्ज), ए 2 (110.00 हर्ट्ज), डी 3 (146.83 हर्ट्ज), जी 3 (196.00 हर्ट्ज), बी 3 (246.94 हर्ट्ज), ई 4 (329.63 हर्ट्ज)।

केवल तकनीकों (सामान्य उठा के अलावा) के लिए आपको पूरा करना होगा:

  • झुकना (यह हमेशा एक आधा टोन मोड़ होगा)
  • पर हथौड़ा मार रहा है
  • खींचना
  • ऊपर / नीचे खिसकना

आप एक मौन स्ट्रिंग, इलाज की आवाज संश्लेषण नहीं कर सकते xएक के रूप में -

जब झुकते हैं, तो असमान से स्ट्रिंग के पूर्ण संक्रमण को फिर से असंतुलित करने के लिए झुकें।

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

इनपुट के लिए:

e|---
B|---
G|---
D|---
A|---
E|---

समय के साथ 0.5, क्योंकि 3प्रतीकों के स्तंभ हैं (लेकिन कोई नोट नहीं), आउटपुट ऑडियो फ़ाइल मौन का ( 3*0.5=1.5) 1.5सेकंड है।

उदाहरण टैब

1 - द वेट (जैक व्हाइट, जिमी पेज + द एज संस्करण)

e|----3-----3---3----2---------3--------------------|
B|----3-----3---3----3--1-1----3--------------------|
G|----0-----0---0----2--0-0----0--------------------|
D|----0-----0---2-------2-2----0--------------------|          
A|----2-----0---2-------3-3----2--------------------|     
E|----3-----2---x----2--x-x----3--------------------|   

2 - किशोर आत्मा की तरह खुशबू आ रही है

e|--------------|---------------|-------------|-------------|
B|--------------|---------------|-------------|-------------|
G|-----8h10-----|-8-8b----6--5--|-6--5--------|-------------|
D|-10--------6--|---------------|-------8-6-8-|-8b----6--5--|
A|--------------|---------------|-------------|-------------|
E|--------------|---------------|-------------|-------------|

3 - स्टार स्पैंगल्ड बैनर

e|---0-------2-5---9-7-5-----------9-7-5-4-2-4-5------|
B|-----2---2-------------2-4-5---5---------------5-2--|
G|-------2-------------------------------------------2|
D|----------------------------------------------------|
A|----------------------------------------------------|
E|----------------------------------------------------|

3
मैंने आपकी आवृत्तियों में कुछ और दशमलव स्थान जोड़े हैं। यह देखते हुए कि एक सेमीटोन = 1 झल्लाहट 1.059463: 1 का अनुपात है (अर्थात लगभग 6% का अंतर) निकटतम 1 हर्ट्ज के लिए ट्यूनिंग एक अच्छी इन-ट्यून ध्वनि प्राप्त करने के लिए पर्याप्त सटीक नहीं है। बेशक एक लोकप्रियता प्रतियोगिता होने के नाते, खराब ट्यूनिंग स्वीकार्य हो सकती है लेकिन यह जीत नहीं पाएगी।
लेवल रिवर सेंट

बहुत रचनात्मक प्रतियोगिता! एएससीआईआई फॉर्म के लिंक को देखने के बाद, मैं उदाहरण 2 (जब से मैंने गाना सुना है) को समझ सकता था, लेकिन क्योंकि मैं गिटार नहीं जानता, मुझे लगता है कि चुनौती में एक उच्च सीखने की अवस्था है। मुझे ऑडेसिटी के मूल उपयोग के अलावा ऑडियो हेरफेर के साथ भी बहुत कम अनुभव है।
mbomb007

क्या MIDI को 'ऑडियो फ़ाइल' के रूप में गिना जाता है?
orlp

@orlp हाँ, यह करता है
बीटा डिके

1
भविष्य के संदर्भ के लिए अच्छी तरह से: v * (2 ^ (f / 12)) = x; v = स्ट्रिंग की आवृत्ति; f = झल्लाहट (टैब पर संख्या); एक्स = आवृत्ति खेला; टैब भी आपको नोट की लंबाई नहीं बताते हैं; आपके कार्यक्रम को स्मार्ट बनाने की आवश्यकता है।
ग्रांट डेविस

जवाबों:


7

MATLAB

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

यह सब कहने के बाद, यह स्क्रिप्ट "इनपुट.टेक्स्ट" नामक एक पाठ फ़ाइल में पढ़ेगी जिसमें आवश्यक रूप से एससी-टैब शामिल होगा और गाना बजाएगा।

% समय
टी = 0.25; निश्चित रूप से, यह रेखा 't = इनपुट (' टाइमिंग: ') हो सकती है;
        % अगर आप टा विनकी मूल्य बनाते हैं जैसे कि t * 8192 पूर्णांक नहीं है, तो कुछ
        % सामान फेल हो जाएगा
बाद में कुछ आलस्य की अनुमति देने के लिए% आवृत्तियों और अतिरिक्त चर
ई = 329.63; ईएन = 1;
बी = 246.94; बीएन = 2;
जी = 196.00; जीएन = 3;
डी = 146.83; डीएन = 4;
ए = 110.00; एएन = 5;
ई = 82.41; एन = 6;
यह गाना गाने को अधिक कंप्यूटर फ्रेंडली तरीके से स्टोर करेगा
गीत = शून्य (1,6);
v = आवृत्ति और f = fret से आवृत्ति प्राप्त करने के लिए% फ़ंक्शन
w = @ (V, च) वी * (2 ^ (f / 12));
% को इनपुट मिलता है और बड़ा लूप शुरू होता है
file = fopen ('input.txt');
line = fgetl (फ़ाइल);
जबकि इश्कार (लाइन)
    % लाइन का पहला वर्ण हमें लाइन फ्रीक्वेंसी देगा
    lfreqv = eval (पंक्ति (1)); % आवृत्ति
    lfreqN = eval ([लाइन (1), 'एन']); आवृत्ति का% क्षैतिज सूचकांक
    % प्रत्येक लाइन पर छोटे लूप शुरू करते हैं
    k = 3 के लिए: (संख्या (रेखा)) - 1
        if (strcmp (पंक्ति (k), '-')) || (strcmp (पंक्ति (k), '' '))) (strcmp (पंक्ति (k),' h))) || (strcmp (पंक्ति) (के), 'बी'))
            गीत (के -2, lfreqN) = 0;
        अन्य
            गीत (के -2, lfreqN) = w (lfreqv, डबल (लाइन (k)));
        समाप्त
    समाप्त
    line = fgetl (फ़ाइल);
समाप्त
fclose (फ़ाइल);
% यह गाना पकड़ लेगा
धुन = [];
खंड = शून्य (1,6);
प्लेफ = शून्य (1,6);
गीत के लिए = 1: आकार (गीत, 1)
    ctune = [];
    k = 1: 6 के लिए
        अगर गीत (गीतइंडेक्स, के) == ०
            vols (k) = 2 * vols (k) / 4;
        अन्य
            vols (k) = 1;
            playf (k) = गीत (songIndex, k);
        समाप्त
        ctune (k, 1: टी * 8192) = खंड (के) * पाप (0.5 * pi * playf (के) * (1: (टी * 8192)) / 8192);
    समाप्त
    धुन = [धुन ctune];
समाप्त
soundsc (राशि (धुन));

यहाँ पहले परीक्षण इनपुट की ध्वनि के लिए एक कड़ी है।

यहां तीसरे टेस्ट इनपुट की ध्वनि का लिंक दिया गया है। (स्टार स्पैंगल्ड बैनर या आइसक्रीम ट्रक?)

दूसरा टेस्ट इनपुट मुझे बहुत बुरा लगा, लेकिन ऐसा इसलिए हो सकता है क्योंकि इसमें बहुत सारे bs और hs का इस्तेमाल होता है जिसे स्क्रिप्ट नजरअंदाज कर देती है।

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


वाह, यह एक संगीत बॉक्स की तरह लगता है ... बहुत अच्छा!
बीटा डेके

5

अजगर ३

मुझे यह कोशिश करनी थी।

यह एक टैब को मिडी फ़ाइल में कनवर्ट करता है जैसा कि एक पियानो द्वारा बजाया जाता है। मुझे नहीं पता कि पियानो पर एक स्ट्रिंग को कैसे झुकाया जाता है, इसलिए यह ऐसा नहीं कर सकता है, लेकिन हैमर-ऑन और पुल-ऑफ सीधे हैं।

मैंने परीक्षण फ़ाइलों को इस तरह उत्पन्न किया: सेकंड में एक नोट की लंबाई $ python3 tab.py The-weight.txt 0.14कहां 0.14है।

from midiutil.MidiFile3 import MIDIFile
import sys

# Read the relevant lines of the file
lines = []
if len(sys.argv) > 1:
    filename = sys.argv[1]
    try:
        beats_per_minute = 60 / float(sys.argv[2])
    except:
        beats_per_minute = 756
else:
    filename = 'mattys-tune.txt'
    beats_per_minute = 756
with open(filename) as f:
    for line in f:
        if len(line) > 3 and (line[1] == '|' or line[2] == '|'):
            line = line.replace('\n', '')
            lines.append(line)
assert len(lines) % 6 == 0

# Initialize the MIDIFile object (with 1 track)
time = 0
duration = 10
volume = 100
song = MIDIFile(1)
song.addTrackName(0, time, "pianized_guitar_tab.")
song.addTempo(0, time, beats_per_minute)

# The root-pitches of the guitar
guitar = list(reversed([52, 57, 62, 67, 71, 76])) # Assume EADGBe tuning
def add_note(string, fret):
    song.addNote(0, string, guitar[string] + fret, time, duration, volume)

# Process the entire tab
for current in range(0, len(lines), 6):  # The current base string
    for i in range(len(lines[current])): # The position in the current string
        time += 1
        for s in range(6):               # The number of the string
            c = lines[current + s][i]
            try: next_char = lines[current + s][i + 1]
            except: next_char = ''
            if c in '-x\\/bhp':
                # Ignore these characters for now
                continue
            elif c.isdigit():
                # Special case for fret 10 and higher
                if next_char.isdigit():
                    c += next_char
                    lines[current + s] = lines[current + s][:i+1] + '-' + lines[current + s][i+2:]
                # It's a note, play it!
                add_note(s, int(c))
            else:
                # Awww
                time -= 1
                break

# And write it to disk.
def save():
    binfile = open('song.mid', 'wb')
    song.writeFile(binfile)
    binfile.close()
    print('Done')
try:
    save()
except:
    print('Error writing to song.mid, try again.')
    input()
    try:
        save()
    except:
        print('Failed!')

कोड जीथब पर भी है, https://github.com/Mattias1/ascii-tab , जहां मैंने ओपी द्वारा प्रदान किए गए उदाहरणों का परिणाम भी अपलोड किया है। मैंने इसे अपने कुछ टैब्स पर भी आजमाया। पियानो बजाना सुनने के लिए यह काफी अजीब है, लेकिन यह बुरा नहीं है।

उदाहरण:

मैंने कुछ प्रत्यक्ष लिंक जोड़े हैं, लेकिन यह सुनिश्चित नहीं है कि वे कितने समय तक रहेंगे, इसलिए मैं पुराने डाउनलोड लिंक भी रखूंगा।

  1. वजन , या खेल
  2. स्मेल्स लाइक टीन स्पिरिट , या खेल की
  3. स्टार स्पैनरल्ड बैनर , या खेलते हैं
  4. माटी की धुन , या बजाने वाला
  5. डीएम ट्यून , या प्ले

और नीचे मैट की धुन (मेरा पसंदीदा) से टैब:

    Am/C        Am            F          G             Am/C        Am
e |------------------------|----------------0-------|------------------------|
B |-1--------1--1--------1-|-1--------1--3-----3----|-1--------1--1--------1-|
G |-2-----2-----2-----2----|-2-----2--------------0-|-2-----2-----2-----2----|
D |----2-----------2-------|----2-------------------|----2-----------2-------|
A |-3-----2-----0----------|-------0--------0--2----|-3-----------0----------|
E |-------------------3----|-1-----------3----------|------------------------|

    F        G               Am/C        Am           F           G
e |------------------------|------------------------|----------------0-------|
B |-1--------3-------------|-1--------1--1--------1-|-1--------1--3-----3----|
G |----------4-------------|-2-----2-----2-----2----|-2-----2--------------0-|
D |-------3--5-------------|----2-----------2-------|----2-------------------|
A |----3-----5--------0--2-|-3-----2-----0----------|-------0--------0--2----|
E |-1--------3-----3-------|-------------------3----|-1-----------3----------|

    Am/C        Am           F        G
e |------------------------|------------------------|
B |-1--------1--1--------1-|-1----------3-----------|
G |-2-----2-----2-----2----|------------4-----------|
D |----2-----------2-------|-------3---5------------|
A |-3-----------0----------|----3------5------------|
E |------------------------|-1--------3-------------|

1
वाह, 756 बीपीएम ?! मुझे आशा है कि यह अंतिम हरा नहीं है ...
बीटा डेके

हाहा, ठीक है, मैं थोड़ा धोखा देता हूं। 2/3उन 'बीट्स' के कारण वास्तव में डैश हैं।
मैटी

वाह, मैटी की धुन बहुत अच्छी लगती है। यह एक गिटार पर क्या पसंद है?
बीटा डिके

1
धन्यवाद @BetaDecay, यह एक धुन है जिसे मैंने एक बार बनाया था, (बेसलाइन) टॉमी इमैनुएल के ब्लू मून से प्रेरित ( youtube.com/watch?v=v0IY3Ax2PkY )। लेकिन यह आधा ध्वनि नहीं करता है कि वह कैसे करता है।
मैटी

4

जावा स्क्रिप्ट

नोट: वेब डेवलपमेंट ऑडियो किट का उपयोग करता है; यह IE के लीग से बाहर का रास्ता है; Google Chrome में परीक्षण किया गया

आप टैक्स्ेरिया में टैब डाल सकते हैं। IE आप मैटी की पोस्ट से टैक्स्टारिया (नोट्स पर पत्र के साथ) में मैटी की धुन डाल सकते हैं और यह अभी भी सही ढंग से समतल होगा।

रन प्रोग्राम पर क्लिक करें

जावास्क्रिप्ट:

context = new AudioContext;
gainNode = context.createGain();
gainNode.connect(context.destination);

gain= 2;

function getValue(i) {
    return document.getElementById(i).value;
}

function addValue(i, d) {
    document.getElementById(i).value += d;
}

function setValue(i, d) {
    document.getElementById(i).value = d;
}

document.getElementById("tada").onclick = updateLines;

function updateLines(){
    var e=getValue("ta").replace(/[^-0-9\n]/g,'').replace("\n\n","\n").split("\n");
    for(var l=0;l<e.length;l+=6){
        try{
        addValue("littleE",e[l]);
        addValue("B",e[l+1]);
        addValue("G",e[l+2]);
        addValue("D",e[l+3]);
        addValue("A",e[l+4]);
        addValue("E",e[l+5]);
        }catch(err){}
    }
    updateDash();
}

document.getElementById("littleE").oninput = updateDash;
document.getElementById("B").oninput = updateDash;
document.getElementById("G").oninput = updateDash;
document.getElementById("D").oninput = updateDash;
document.getElementById("A").oninput = updateDash;
document.getElementById("E").oninput = updateDash;


function updateDash() {
    max = 10;
    findDashMax("littleE");
    findDashMax("B");
    findDashMax("G");
    findDashMax("D");
    findDashMax("A");
    findDashMax("E");
    applyMax();
    i = "littleE";
    dash = new Array();
    for (var l = 0; l < getValue(i).length; l++) {
        if (getValue(i).charCodeAt(l) == 45) {
            dash[l] = true;
        } else {
            dash[l] = false;
        }
    }
    /*applyDash("B");
    applyDash("G");
    applyDash("D");
    applyDash("A");
    applyDash("E");*/
}

function findDashMax(i) {
    if (getValue(i).length > max) {
        max = getValue(i).length;
    }
}

function applyMax() {
    if (max < 50) {
        document.getElementById("stepe").size = 50;
        document.getElementById("littleE").size = 50;
        document.getElementById("B").size = 50;
        document.getElementById("G").size = 50;
        document.getElementById("D").size = 50;
        document.getElementById("A").size = 50;
        document.getElementById("E").size = 50;
    } else {
        document.getElementById("stepe").size = max + 1;
        document.getElementById("littleE").size = max + 1;
        document.getElementById("B").size = max + 1;
        document.getElementById("G").size = max + 1;
        document.getElementById("D").size = max + 1;
        document.getElementById("A").size = max + 1;
        document.getElementById("E").size = max + 1;
    }
}

function applyDash(i) {
    var old = getValue(i);
    setValue(i, "");
    for (var l = 0; l < old.length || dash[l] == true; l++) {
        if (dash[l] == true) {
            addValue(i, "-");
        } else {
            if (old.charCodeAt(l) != 45) {
                addValue(i, old.charAt(l));
            }
        }
    }
}
document.getElementById("next").onclick = begin;

function addDash(i) {
    while (getValue(i).length < max) {
        addValue(i, "-");
    }
}

function begin() {
    setValue("littleE",getValue("littleE").replace(/[^-0-9]/g,''));
    setValue("B",getValue("B").replace(/[^-0-9]/g,''));
    setValue("G",getValue("G").replace(/[^-0-9]/g,''));
    setValue("D",getValue("D").replace(/[^-0-9]/g,''));
    setValue("A",getValue("A").replace(/[^-0-9]/g,''));
    setValue("E",getValue("E").replace(/[^-0-9]/g,''));
    addDash("littleE");
    addDash("B");
    addDash("G");
    addDash("D");
    addDash("A");
    addDash("E");
    setValue("next", "Stop");
    //playing = true;
    findLength();
    document.getElementById("next").onclick = function () {
        clearInterval(playingID);
        oscillator["littleE"].stop(0);
        oscillator["B"].stop(0);
        oscillator["G"].stop(0);
        oscillator["D"].stop(0);
        oscillator["A"].stop(0);
        oscillator["E"].stop(0);
        setValue("next", "Play");
        document.getElementById("next").onclick = begin;
    }
    step = -1;
    playingID = setInterval(function () {
        step++;
        setValue("stepe", "");
        for (var l = 0; l < step; l++) {
            addValue("stepe", " ");
        }
        addValue("stepe", "V");
        if (lg[step]) {
            oscillator["littleE"].stop(0);
            oscillator["B"].stop(0);
            oscillator["G"].stop(0);
            oscillator["D"].stop(0);
            oscillator["A"].stop(0);
            oscillator["E"].stop(0);
        }
        qw=0
        doSound("littleE");
        doSound("B");
        doSound("G");
        doSound("D");
        doSound("A");
        doSound("E");

    }, getValue("s") * 1000);
}

function doSound(i) {
    switch (getValue(i).charAt(step)) {
        case ("-"):
        case ("x"):
        case (""):
        case (" "):
            break;
        default:
            qw++;
            makeSound(fretToHz(getHz(i), getValue(i).charAt(step)), i);

    }
    checkTop();
}

function checkTop(){
    switch(qw){
        case 0:
            break;
        case 1:
            gain=2;
            break;
        case 2:
            gain=1;
            break;
        case 3:
            gain=.5;
            break;
        default:
            gain=.3;
            break;
    }
}

function getHz(i) {
    switch (i) {
        case "littleE":
            return 329.63;
        case "B":
            return 246.94;
        case "G":
            return 196;
        case "D":
            return 146.83;
        case "A":
            return 110;
        case "E":
            return 82.41;
    }
}

function fretToHz(v, f) {
    return v * (Math.pow(2, (f / 12)));
}

/*function getTime() {
    var u = 1;
    while (lg[step + u] == false) {
        u++;
    }
    return u;
}*/

function findLength() {
    lg = new Array();
    for (var h = 0; h < getValue("littleE").length; h++) {
        lg[h] = false;
        fl(h, "littleE");
        fl(h, "B");
        fl(h, "G");
        fl(h, "D");
        fl(h, "A");
        fl(h, "E");
    }
    console.table(lg);
}

function fl(h, i) {
    var l = getValue(i).charAt(h);
    switch (l) {
        case "-":
        case "|":
            break;
        default:
            lg[h] = true;
    }
}

oscillator = new Array();

function makeSound(hz, i) {
    console.log("playing " + hz + " Hz" + i);
    oscillator[i] = context.createOscillator();
    oscillator[i].connect(gainNode);
    oscillator[i].frequency.value = hz;
    oscillator[i].start(0);
}

soundInit("littleE");
soundInit("B");
soundInit("G");
soundInit("D");
soundInit("A");
soundInit("E");

function soundInit(i) {
    makeSound(440, i);
    oscillator[i].stop(0);
}
setInterval(function () {
    gainNode.gain.value = .5 * getValue("v") * gain;
    document.getElementById("q").innerHTML = "Volume:" + Math.round(getValue("v") * 100) + "%";
}, 100);

क्या आप इस गाने को पहचान सकते हैं?


1
यह पात्रों की तरह दुर्घटनाग्रस्त हो जाता है | / b h p। उन्हें बदलने के लिए सिर्फ थोड़ा स्ट्रिंग पार्सिंग ही क्यों -? यह काफी ठीक लग रहा है और यह काम करता है। (और शायद एक इनपुट बॉक्स का उपयोग करके नईलाइन्स पर विभाजित हो।) यही कारण है कि यह एक मजेदार स्क्रिप्ट के साथ खेलना होगा।
मैट

कि मैं क्या करने की योजना बना रहा था, मैं बस इसके आसपास कभी नहीं गया।
डेविस

मैं मानता हूं, प्रत्येक स्ट्रिंग के लिए अलग लाइन एक दर्द है, लेकिन अन्यथा यह अच्छा लगता है
बीटा डेके

पोस्ट को संपादित करने से पहले लॉगिन करना भूल गए।
ग्रांट डेविस

मैं धुन को पहचानता हूं, लेकिन मैं इसका नाम नहीं रख सकता ... हालांकि यह अच्छा लगता है
बीटा डिके

2

जावा

यह कार्यक्रम 16-बिट WAV प्रारूप के लिए एक सारणी में रूपांतरित करता है।

सबसे पहले, मैंने सारणीबद्ध पार्सिंग कोड का एक पूरा गुच्छा लिखा। मुझे यकीन नहीं है कि मेरा पार्सिंग पूरी तरह से सही है, लेकिन मुझे लगता है कि यह ठीक है। इसके अलावा, यह डेटा के लिए अधिक सत्यापन का उपयोग कर सकता है।

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

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

इसके अलावा, यह झुकने ( b), रिलीज ( r) और स्लाइडिंग ( /और \, विनिमेय) का समर्थन करता है। xस्ट्रिंग को म्यूट करने के रूप में कार्यान्वित किया जाता है।

आप कोड की शुरुआत में स्थिरांक को ट्विक करने की कोशिश कर सकते हैं। विशेष रूप से कम होने से silenceRateअक्सर बेहतर गुणवत्ता होती है।

उदाहरण के परिणाम

कोड

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

import java.io.*;
import java.util.*;

public class TablatureSong {

    public static final int sampleRate = 44100;

    public static final double silenceRate = .4;

    public static final int harmonies = 10;
    public static final double harmonyMultiplier = 0.3;

    public static final double bendDuration = 0.25;

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        System.out.println("Output file:");
        String outfile = in.nextLine();
        System.out.println("Enter tablature:");
        Tab tab = parseTablature(in);
        System.out.println("Enter tempo:");
        int tempo = in.nextInt();
        in.close();

        int samples = (int) (60.0 / tempo * tab.length * sampleRate);
        double[][] strings = new double[6][];
        for (int i = 0; i < 6; i++) {
            System.out.printf("Generating string %d/6...\n", i + 1);
            strings[i] = generateString(tab.actions.get(i), tempo, samples);
        }

        System.out.println("Combining...");
        double[] combined = new double[samples];
        for (int i = 0; i < samples; i++)
            for (int j = 0; j < 6; j++)
                combined[i] += strings[j][i];

        System.out.println("Normalizing...");
        double max = 0;
        for (int i = 0; i < combined.length; i++)
            max = Math.max(max, combined[i]);
        for (int i = 0; i < combined.length; i++)
            combined[i] = Math.min(1, combined[i] / max);

        System.out.println("Writing file...");
        writeWaveFile(combined, outfile);
        System.out.println("Done");
    }

    private static double[] generateString(List<Action> actions, int tempo, int samples) {
        double[] harmonyPowers = new double[harmonies];
        for (int harmony = 0; harmony < harmonyPowers.length; harmony++) {
            if (Integer.toBinaryString(harmony).replaceAll("[^1]", "").length() == 1)
                harmonyPowers[harmony] = 2 * Math.pow(harmonyMultiplier, harmony);
            else
                harmonyPowers[harmony] = Math.pow(harmonyMultiplier, harmony);
        }
        double actualSilenceRate = Math.pow(silenceRate, 1.0 / sampleRate);

        double[] data = new double[samples];

        double phase = 0.0, amplitude = 0.0;
        double slidePos = 0.0, slideLength = 0.0;
        double startFreq = 0.0, endFreq = 0.0, thisFreq = 440.0;
        double bendModifier = 0.0;
        Iterator<Action> iterator = actions.iterator();
        Action next = iterator.hasNext() ? iterator.next() : new Action(Action.Type.NONE, Integer.MAX_VALUE);

        for (int sample = 0; sample < samples; sample++) {
            while (sample >= toSamples(next.startTime, tempo)) {
                switch (next.type) {
                case NONE:
                    break;
                case NOTE:
                    amplitude = 1.0;
                    startFreq = endFreq = thisFreq = next.value;
                    bendModifier = 0.0;
                    slidePos = 0.0;
                    slideLength = 0;
                    break;
                case BEND:
                    startFreq = addHalfSteps(thisFreq, bendModifier);
                    bendModifier = next.value;
                    slidePos = 0.0;
                    slideLength = toSamples(bendDuration);
                    endFreq = addHalfSteps(thisFreq, bendModifier);
                    break;
                case SLIDE:
                    slidePos = 0.0;
                    slideLength = toSamples(next.endTime - next.startTime, tempo);
                    startFreq = thisFreq;
                    endFreq = thisFreq = next.value;
                    break;
                case MUTE:
                    amplitude = 0.0;
                    break;
                }
                next = iterator.hasNext() ? iterator.next() : new Action(Action.Type.NONE, Integer.MAX_VALUE);
            }

            double currentFreq;
            if (slidePos >= slideLength || slideLength == 0)
                currentFreq = endFreq;
            else
                currentFreq = startFreq + (endFreq - startFreq) * (slidePos / slideLength);

            data[sample] = 0.0;
            for (int harmony = 1; harmony <= harmonyPowers.length; harmony++) {
                double phaseVolume = Math.sin(2 * Math.PI * phase * harmony);
                data[sample] += phaseVolume * harmonyPowers[harmony - 1];
            }

            data[sample] *= amplitude;
            amplitude *= actualSilenceRate;
            phase += currentFreq / sampleRate;
            slidePos++;
        }
        return data;
    }

    private static int toSamples(double seconds) {
        return (int) (sampleRate * seconds);
    }

    private static int toSamples(double beats, int tempo) {
        return (int) (sampleRate * beats * 60.0 / tempo);
    }

    private static void writeWaveFile(double[] data, String outfile) {
        try (OutputStream out = new FileOutputStream(new File(outfile))) {
            out.write(new byte[] { 0x52, 0x49, 0x46, 0x46 }); // Header: "RIFF"
            write32Bit(out, 44 + 2 * data.length, false); // Total size
            out.write(new byte[] { 0x57, 0x41, 0x56, 0x45 }); // Header: "WAVE"
            out.write(new byte[] { 0x66, 0x6d, 0x74, 0x20 }); // Header: "fmt "
            write32Bit(out, 16, false); // Subchunk1Size: 16
            write16Bit(out, 1, false); // Format: 1 (PCM)
            write16Bit(out, 1, false); // Channels: 1
            write32Bit(out, 44100, false); // Sample rate: 44100
            write32Bit(out, 44100 * 1 * 2, false); // Sample rate * channels *
                                                    // bytes per sample
            write16Bit(out, 1 * 2, false); // Channels * bytes per sample
            write16Bit(out, 16, false); // Bits per sample
            out.write(new byte[] { 0x64, 0x61, 0x74, 0x61 }); // Header: "data"
            write32Bit(out, 2 * data.length, false); // Data size
            for (int i = 0; i < data.length; i++) {
                write16Bit(out, (int) (data[i] * Short.MAX_VALUE), false); // Data
            }
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void write16Bit(OutputStream stream, int val, boolean bigEndian) throws IOException {
        int a = (val & 0xFF00) >> 8;
        int b = val & 0xFF;
        if (bigEndian) {
            stream.write(a);
            stream.write(b);
        } else {
            stream.write(b);
            stream.write(a);
        }
    }

    private static void write32Bit(OutputStream stream, int val, boolean bigEndian) throws IOException {
        int a = (val & 0xFF000000) >> 24;
        int b = (val & 0xFF0000) >> 16;
        int c = (val & 0xFF00) >> 8;
        int d = val & 0xFF;
        if (bigEndian) {
            stream.write(a);
            stream.write(b);
            stream.write(c);
            stream.write(d);
        } else {
            stream.write(d);
            stream.write(c);
            stream.write(b);
            stream.write(a);
        }
    }

    private static double[] strings = new double[] { 82.41, 110.00, 146.83, 196.00, 246.94, 329.63 };

    private static Tab parseTablature(Scanner in) {
        String[] lines = new String[6];
        List<List<Action>> result = new ArrayList<>();
        int longest = 0;
        for (int i = 0; i < 6; i++) {
            lines[i] = in.nextLine().trim().substring(2);
            longest = Math.max(longest, lines[i].length());
        }
        int skipped = 0;
        for (int i = 0; i < 6; i++) {
            StringIterator iterator = new StringIterator(lines[i]);
            List<Action> actions = new ArrayList<Action>();
            while (iterator.index() < longest) {
                if (iterator.get() < '0' || iterator.get() > '9') {
                    switch (iterator.get()) {
                    case 'b':
                        actions.add(new Action(Action.Type.BEND, 1, iterator.index(), iterator.index()));
                        iterator.next();
                        break;
                    case 'r':
                        actions.add(new Action(Action.Type.BEND, 0, iterator.index(), iterator.index()));
                        iterator.next();
                        break;
                    case '/':
                    case '\\':
                        int startTime = iterator.index();
                        iterator.findNumber();
                        int endTime = iterator.index();
                        int endFret = iterator.readNumber();
                        actions.add(new Action(Action.Type.SLIDE, addHalfSteps(strings[5 - i], endFret), startTime,
                                endTime));
                        break;
                    case 'x':
                        actions.add(new Action(Action.Type.MUTE, iterator.index()));
                        iterator.next();
                        break;
                    case '|':
                        iterator.skip(1);
                        iterator.next();
                        break;
                    case 'h':
                    case 'p':
                    case '-':
                        iterator.next();
                        break;
                    default:
                        throw new RuntimeException(String.format("Unrecognized character: '%c'", iterator.get()));
                    }
                } else {
                    StringBuilder number = new StringBuilder();
                    int startIndex = iterator.index();
                    while (iterator.get() >= '0' && iterator.get() <= '9') {
                        number.append(iterator.get());
                        iterator.next();
                    }
                    int fret = Integer.parseInt(number.toString());
                    double freq = addHalfSteps(strings[5 - i], fret);
                    actions.add(new Action(Action.Type.NOTE, freq, startIndex, startIndex));
                }
            }
            result.add(actions);
            skipped = iterator.skipped();
        }
        return new Tab(result, longest - skipped);
    }

    private static double addHalfSteps(double freq, double halfSteps) {
        return freq * Math.pow(2, halfSteps / 12.0);
    }

}

class StringIterator {
    private String string;
    private int index, skipped;

    public StringIterator(String string) {
        this.string = string;
        index = 0;
        skipped = 0;
    }

    public boolean hasNext() {
        return index < string.length() - 1;
    }

    public void next() {
        index++;
    }

    public void skip(int length) {
        skipped += length;
    }

    public char get() {
        if (index < string.length())
            return string.charAt(index);
        return '-';
    }

    public int index() {
        return index - skipped;
    }

    public int skipped() {
        return skipped;
    }

    public boolean findNumber() {
        while (hasNext() && (get() < '0' || get() > '9'))
            next();
        return get() >= '0' && get() <= '9';
    }

    public int readNumber() {
        StringBuilder number = new StringBuilder();
        while (get() >= '0' && get() <= '9') {
            number.append(get());
            next();
        }
        return Integer.parseInt(number.toString());
    }
}

class Action {
    public static enum Type {
        NONE, NOTE, BEND, SLIDE, MUTE;
    }

    public Type type;
    public double value;
    public int startTime, endTime;

    public Action(Type type, int time) {
        this(type, time, time);
    }

    public Action(Type type, int startTime, int endTime) {
        this(type, 0, startTime, endTime);
    }

    public Action(Type type, double value, int startTime, int endTime) {
        this.type = type;
        this.value = value;
        this.startTime = startTime;
        this.endTime = endTime;
    }
}

class Tab {
    public List<List<Action>> actions;
    public int length;

    public Tab(List<List<Action>> actions, int length) {
        this.actions = actions;
        this.length = length;
    }
}

मुझे पता है कि मैंने इसे निर्दिष्ट नहीं किया है, लेकिन क्या आप कुछ परीक्षण मामलों को पोस्ट कर सकते हैं जिन्हें लोग अन्य उत्तरों में पसंद कर सकते हैं?
बीटा डेके

@ BetaDecay ने मेरे उत्तर को अपडेट किया, अब परीक्षणों का एक गुच्छा है
PurkkaKoodari

वे लिंक काम नहीं करते: /
बीटा Decay

@BetaDecay मैंने उस ब्राउज़र के गुप्त मोड में एक और कनेक्शन पर डबल चेक किया जिसका मैं उपयोग नहीं करता। वे मेरे लिए काम करते हैं, कम से कम।
PurkkaKoodari

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