반응형
Music21 라이브러리 가이드 3
from music21 import *
#Music21 User Guide 5,6 레퍼런스 정리
# 2차원 , 3차원 리스트
#User Guide 5는 2차원 , 3차원 리스트에 대해 설명한다.
#아마 스트림과 리스트를 비교하려는 듯 하다.
note1 = note.Note("C4")
note1.duration.type = 'half'
note2 = note.Note("F#4")
note3 = note.Note("B-2")
stream1 = stream.Stream()
stream1.id = 'some notes'
stream1.append(note1)
stream1.append(note2)
stream1.append(note3)
biggerStream = stream.Stream()
note2 = note.Note("D#5")
biggerStream.insert(0, note2)
biggerStream.append(stream1)
#다음과 같은 스트림들이 있을 때 , 내부 요소를 알고 싶다면 .show() 밖엔 없었다.
biggerStream.show('text')
#스트림은 music21의 객체를 계층적 , 시간적으로 분리하고 구조화하고 배치할 수 있다.
#스트림 또는 스트림 하위 클래스를 다른 스트림에 배치 할 수 있는 것이다.
#이러한 스트림 객체의 배열은 악보를 표현하는 가장 일반적인 방식이다.
#music21에는 music21.corpus 모듈이 있다.
#이 모듈을 통해서 다양한 함수를 사용 가능하고 다양한 정보들을 얻어낼 수 있다.
#corpus.parse는 악보를 스트림으로 만들어준다.
sBach = corpus.parse('bach/bwv57.8')
print(sBach)
#corpus.parse를 통해 스코어를 확인 가능하다.
#스코어는 a Metadata object, a StaffGroup object, and four Part objects 로 구성된다.
print(len(sBach[3]))
print(len(sBach[3][1]))
#스코어가 리스트의 형태로 나올텐데 그럼 어떤게 어떤건지 어떻게 아냐는 것이다.
#그래서 이런 기억과 순서에 의존하는 필터링은 좋지 않다.
#앞서 배운 getElementsByClass() 메소드를 통해 요소를 기준으로 필터링 하자.
print(len(sBach.getElementsByClass(stream.Part)))
print(len(sBach.getElementsByClass(stream.Part)[0].getElementsByClass(stream.Measure)))
print(len(sBach.getElementsByClass(stream.Part)[0].getElementsByClass(
stream.Measure)[1].getElementsByClass(note.Note)))
print(len(sBach.getElementsByClass('Part')))
alto = sBach.parts[1] # parts count from zero, so soprano is 0 and alto is 1
#part는 소프라노 , 알토 같은 부분을 이야기 한다.
#즉 파트가 나눠진 악보 예를 들어 여럿이서 부른다면 소프라노 파트 , 알토 파트 여럿이서 노래를 부를 것이다.
#이런 부분에 대해서 있는 속성이 part 다.
excerpt = alto.measures(1, 4) #마디를 의미한다.
#excerpt.show("midi")
excerpt.show("text")
#파디를 1 ~ 4 부분 띄어내어서 살퍄본다.
measure2 = alto.measure(2) # measure not measure_s_
measure2.show("text")
#띄어낸 부분에서 2번째 것이다.
#차이를 보면 단일 마디는 measure , 범위 마디는 measures 다.
measureStack = sBach.measures(2, 3)
measureStack.show("text")
# 스트림 에서의 재귀
#스트림은 스트림 안에 스트림이 들어 갈 수 있다.
#스트림의 각 하위의 레이어에 도달하기 위해 모든 요소들을 recurse() 라는 메소드가 방문한다.
s = stream.Score(id='mainScore')
p0 = stream.Part(id='part0')
p1 = stream.Part(id='part1')
m01 = stream.Measure(number=1)
m01.append(note.Note('C', type="whole"))
m02 = stream.Measure(number=2)
m02.append(note.Note('D', type="whole"))
p0.append([m01, m02])
m11 = stream.Measure(number=1)
m11.append(note.Note('E', type="whole"))
m12 = stream.Measure(number=2)
m12.append(note.Note('F', type="whole"))
p1.append([m11, m12])
s.insert(0, p0)
s.insert(0, p1)
s.show('text')
#결과
#{0.0} <music21.stream.Part part0>
# {0.0} <music21.stream.Measure 1 offset=0.0>
# {0.0} <music21.note.Note C>
# {4.0} <music21.stream.Measure 2 offset=4.0>
# {0.0} <music21.note.Note D>
# {0.0} <music21.stream.Part part1>
# {0.0} <music21.stream.Measure 1 offset=0.0>
# {0.0} <music21.note.Note E>
# {4.0} <music21.stream.Measure 2 offset=4.0>
# {0.0} <music21.note.Note F>
recurseScore = s.recurse()
print(recurseScore)
#print 해보니 iterator 쪽이다. for문을 활용해서 뜯어보자.
for el in s.recurse():
print(el.offset, el, el.activeSite)
#recurse의 결과는 리스트를 호출 하는 것처럼 사용해야 한다.
# 스트림 평탄화
#스트림을 평탄화 한다는 것은 중첩된 스트림을 평탄화 한다고 생각하면 된다.
#.flatten() 메소드의 결과를 확인해보자.
for el in s.flatten():
print(el.offset, el, el.activeSite)
#결과
# 0.0 <music21.note.Note C> <music21.stream.Score mainScore_flat>
# 0.0 <music21.note.Note E> <music21.stream.Score mainScore_flat>
# 4.0 <music21.note.Note D> <music21.stream.Score mainScore_flat>
# 4.0 <music21.note.Note F> <music21.stream.Score mainScore_flat>
#중첩된 스트림의 구조를 평탄화하면 플랫 속성이 액세스된 스트림의 컨텍스트에서
#적절한 위치를 반영하여 스트림의 각 요소에 대해 새로운 시프트 오프셋이 설정된다.
#이와는 별도로, 노트 오프셋은 편집되지 않았음을 인식하는 것이 중요하다.
Reference : mit.edu Music21 User Guide Documentation
Github : Gusehd/Music21_Guide: Python Music21 User_Guide KR (github.com)
반응형
'코딩 > 기타' 카테고리의 다른 글
[Music21] 4. Music21 가이드 ( Chords ) (0) | 2022.03.28 |
---|---|
[Music21] MuseScore 3 에러 해결 및 경로 처리 (0) | 2022.03.24 |
[Music21] 2. Music21 가이드 ( Stream ) (0) | 2022.03.21 |
[Music21] 1. Music21 가이드 ( Note , Pitch , Duration ) (0) | 2022.03.20 |
[기타] 블로그에 Jupyter notebook 올리기 (0) | 2022.03.19 |