1

音階の音符を取得するためのプログラムを作成しようとしています。これは私が今までに得たものですが、とてつもなく複雑に思えます!! 私は何が欠けていますか?そんなはずじゃないの?

notes = [ "c", "c#", "d", "d#", "e", "f", "f#", "g", "g#", "a", "a#", "b" ]
major = [2,2,1,2,2,2] # semitone steps
root  = "f"
root_i= notes.index(root)

index = [root_i+i for i in [sum(major[:y]) for y in range(len(major)+1)]]
scale = [notes[i] if i < len(notes) else notes[i-len(notes)] for i in index]

root_i各「ステップ」ごとにインクリメントしmajor、最後に到達したら再起動する必要がありnotesます...

ありがとう。

4

4 に答える 4

2

それを行う 1 つの方法は を使用することですが、ベースのアプローチdequeには特に問題はありません。list独自の関数に入れることで、何が起こっているのかをもう少し明確にする傾向があります...

from collections import deque

notes = [ "c", "c#", "d", "d#", "e", "f", "f#", "g", "g#", "a", "a#", "b" ]

def get_scale(seq, start):
    d = deque(seq)
    d.rotate(-seq.index(start)) 
    yield d[0]
    for idx in [2, 2, 1, 2, 2, 2]:
        d.rotate(-idx) # always bring element to index 0
        yield d[0] 

print list(get_scale(notes, 'c'))

そして、ロットを事前に計算することもできます。

>>> scales = {k:list(get_scale(notes, k)) for k in notes}
>>> scales
{'a': ['a', 'b', 'c#', 'd', 'e', 'f#', 'g#'], 'c': ['c', 'd', 'e', 'f', 'g', 'a', 'b'], 'b': ['b', 'c#', 'd#', 'e', 'f#', 'g#', 'a#'], 'e': ['e', 'f#', 'g#', 'a', 'b', 'c#', 'd#'], 'd': ['d', 'e', 'f#', 'g', 'a', 'b', 'c#'], 'g': ['g', 'a', 'b', 'c', 'd', 'e', 'f#'], 'f': ['f', 'g', 'a', 'a#', 'c', 'd', 'e'], 'c#': ['c#', 'd#', 'f', 'f#', 'g#', 'a#', 'c'], 'd#': ['d#', 'f', 'g', 'g#', 'a#', 'c', 'd'], 'f#': ['f#', 'g#', 'a#', 'b', 'c#', 'd#', 'f'], 'g#': ['g#', 'a#', 'c', 'c#', 'd#', 'f', 'g'], 'a#': ['a#', 'c', 'd', 'd#', 'f', 'g', 'a']}
>>> scales['d']
['d', 'e', 'f#', 'g', 'a', 'b', 'c#']
>>> scales['c']
['c', 'd', 'e', 'f', 'g', 'a', 'b']
于 2012-12-05T12:56:51.443 に答える
2

音符の正しいスペルを取得することに関心がある場合は、より洗練されたアプローチが必要になります。たとえば、F# メジャー スケールは [F#、G#、A#、B、C#、D#、F] と表示されますが、本当に必要なのはリーディング トーンの E# です。同様に、スペルが気になる場合は、フラットも実装する必要があります。メジャー スケール以外のダイアトニック スケール (ナチュラルおよびハーモニック マイナー、リディアンなど) に関心がある場合は、目的のスケール間隔から音符間隔を切り離す必要もあります。代わりに、次のようなより複雑なものが必要になります。

def getScale(root='C', mode='major')
    noteNames = ['C','D','E','F','G','A','B']
    noteSpacing = [2,2,1,2,2,2,1]
    if mode == 'natural minor':
        scaleSpacing = [2,1,2,2,1,2,2]
    elif mode == 'harmonic minor':
        scaleSpacing = [2,1,2,2,1,3,1]
    else:
        scaleSpacing = [2,2,1,2,2,2,1]

    startingIndex = noteNames.index(root[0])

    baseSemitoneOffset = root.count('#') - root.count('b')
    currentSemitones = 0
    correctSemitones = 0

    scale = [root]
    for noteDegree in range(1, 7):
        currentIndex = (startingIndex + noteDegree) % len(noteNames)
        currentSemitones += scaleSpacing[(noteDegree -1) % len(noteNames)]
        correctSemitones += noteSpacing[(currentIndex - 1) % len(noteNames)]
        currentSemitonesWithOffset = currentSemitones + baseSemitoneOffset
        thisNoteStep = noteNames[currentIndex]
        if currentSemitonesWithOffset < correctSemitones:
            thisNoteName = thisNoteStep + 'b' * (correctSemitones - currentSemitonesWithOffset)
        elif currentSemitonesWithOffset > correctSemitones:
            thisNoteName = thisNoteStep + '#' * (currentSemitonesWithOffset - correctSemitones)
        else:
            thisNoteName = thisNoteStep
        #print thisNoteName, currentSemitonesWithOffset, currentSemitones, correctSemitones
        scale.append(thisNoteName)

    return scale

これらの値に対して、期待どおりの結果が返されます

print getScale('C')
print getScale('Ab')
print getScale('F#')

['C', 'D', 'E', 'F', 'G', 'A', 'B']
['Ab', 'Bb', 'C', 'Db', 'Eb', 'F', 'G']
['F#', 'G#', 'A#', 'B', 'C#', 'D#', 'E#']

そして、よりあいまいなスケールで機能します:

print getScale('C', mode='harmonic minor')
print getScale('Ab', mode='natural minor')
print getScale('Fb', mode='major')

['C', 'D', 'Eb', 'F', 'G', 'Ab', 'B']
['Ab', 'Bb', 'Cb', 'Db', 'Eb', 'Fb', 'Gb']
['Fb', 'Gb', 'Ab', 'Bbb', 'Cb', 'Db', 'Eb']

音楽理論はグラフィックスやオーディオよりもコンピューターに実装するのがはるかに簡単であるという本当の仮定があります...そしてそれはそうですが、それほど簡単ではありません. Python プログラマーは、Pedro Kroger によるMusic for Geeks and Nerdsという本に興味があるかもしれません。または、より深い音楽理論の問題 (昇順と降順が異なるメロディック マイナー スケール、非オクターブ反復スケールなど) に取り組みたい場合は、music21 Python ツールキット、特にmusic21.scaleモジュール。

于 2012-12-09T20:51:05.233 に答える
1

最も簡単な?

scale = [notes[(y+root_i)%len(notes)] for y in [0,2,4,5,7,9,11]]

あるいは

scale = [notes[(y+notes.index(root))%len(notes)] for y in [0,2,4,5,7,9,11]]

root_i や index は必要ありません

于 2012-12-05T13:04:57.443 に答える
1
scale = [notes[i] if i < len(notes) else notes[i-len(notes)] for i in index]

次のように書くことができます

scale = [notes[i % len(notes)] for i in index]

全体は次のように書き直すことができますitertools:

import itertools as it
notes = [ "c", "c#", "d", "d#", "e", "f", "f#", "g", "g#", "a", "a#", "b" ]
major = [2,2,1,2,2,2] # semitone steps
root  = "f"

note_iter = it.dropwhile(root.__ne__, it.cycle(notes))
scale = [list(it.islice(note_iter, m))[0] for m in major]

または「ワン」ライナー:

scale = [n for i, n in it.izip(it.chain.from_iterable(xrange(m) for m in major),
                               it.dropwhile(root.__ne__, it.cycle(notes)))
           if i == 0]
于 2012-12-05T12:42:38.373 に答える