miditorio라는 사이트에서 midi 파일을 변환해주기도 하지만 직접 하나 만들어보고 싶었다.
음악은 잘 모르지만 팩토리오에서 가능하다면 한번 직접 해봐야되지 않겠나.
miditorio에서 만들어주는건 악보 마디별로 따로따로 일정신호 조합기를 사용하지만 간단한 멜로디는 조합기 단위가 아니라 신호 단위에 악보 마디를 우겨넣을 수 있을 거 같아서.
그런건 이미 있긴한데 factorio portal radio 검색해보면 찾을 수 있다.
간단한 멜로디 악보를 팩토리오로 수작업으로 옮겨보려고 하나 가져왔음.
악보 사진은 아쉽게도 없음.
텍스트로 쓰기위해서 편의상 1/4음표를 1로 표기할거임.
그러면 1/8, 1/16, 1/2음표는 0.5, 0.25, 2로 표기되겠지.
음높이는 외국식을 따라서 CDEFGABC = 도레미파솔라시도 으로 표기.
가져온 이 악보는 2/4박자이기 때문에 한마디의 길이는 2가 됨.
- 시퀀스
마디번호, 음높이, 음길이
01 G 1 / E 1
02 E 0.5 / E 0.5 / E 1
03 E 0.5 / G 0.5 / E 0.5 / C 0.5
04 E 0.5 / G 0.25 / E 0.25 / C 0.5 / E 0.5
05 G 0.5 / E 0.5 / E 1
06 C 0.5 / C 0.25 / C 0.25 / C 1
07 E 0.5 / E 0.5 / E 1
08 E 0.5 / G 0.5 / E 0.5 / C 0.5
09 E 0.5 / G 0.25 / E 0.25 / C 0.5 / E 0.5
10 G 0.5 / E 0.5 / E 1
11 C 0.5 / C 0.25 / C 0.25 / C 1
12 C 2
13 G 0.5 / G 0.25 / E 0.25 / C 0.5 / E 0.5
14 C 0.25 / E 0.25 / C 0.25 / E 0.25 / G 1
15 G 2
16 C 0.5 / C 0.5 / E 0.5 / E 0.5
17 G 0.5 / G 0.25 / E 0.25 / C 0.5 / E 0.5
18 C 0.25 / E 0.25 / C 0.25 / E 0.25 / G 1
19 G 2
악보를 보면 가장 짧은 음길이는 0.25(1/16음표)임.
한마디 길이가 총 2이기 때문에 가장 짧은 음의 경우, 마디 하나에 8번 들어감.
그럼 32비트 단일 신호값 안에 얼마만큼 압축해 넣을 수 있나?
팩토리오에서 사용되는 음높이는 0~50가지정도로, 2^6=64 6비트 안에 해결봐야하므로,
6*8=48비트가 되서 32비트를 초과한다.
그럼 24비트로 반 쪼개서 반마디씩 저장하고 남은 8비트에 추가 정보를 저장해야겠네.
마디는 19개가 전부니까, 마디를 반 쪼갰으므로 38개가 됨, 마디번호가 2^6=64 6비트 안에 표현이 가능하네.
왜 7~8비트 안하냐면, 제일 앞 비트는 음수비트고, 두번째 비트는 제일 큰 양수 값을 만들어줄 비트인데, 신호 자동합산을 이용해서 필터링 하려면 비워둬야한다고 생각해서.
그러면 32비트안에 0.5마디 정보가 들어간다.
32비트 데이터를 생각하기 전에 템포를 생각해보자.
악보에 템포는 적혀있지 않았지만 1/4음표 = 120 BPM이라고 가정하자.
그러면 1/4음표 한개의 후딜레이는 60초/120 = 0.5초이다.
그러면 원래의 2/4박자의 한 마디는 1초가 걸린다.
위에 있는 간단한 오선지 그림의 한 마디가 1초.
근데 마디를 반으로 쪼개서 2배로 늘렸으니 쪼갠 마디 하나를 연주하는 데에는 0.5초가 걸림.
따라서 가장 짧은 1/16음표는 쪼갠 마디 하나에 4번까지 재생될 수 있다.
30틱(0.5초)안에 4번이라니 나누어 떨어지지 않으니까, 대충 근사치를 잡아서 7틱을 잡자.
그럼 마디하나에 28틱 걸리니까 실제로는 약간 더 빠르게 재생될 듯. 어쩔 수가 없네.
조합기로 이렇게 짜면 템포와 반복재생이 아마 구현되겠지.
초록색 신호는 틱생성을 하고, 0~6의 7개 값이 반복됨.
파란색 신호는 가장 짧은 음 기준으로 쪼갠 타이밍을 생성하고, 0~3의 4개 값이 반복되며, 7틱마다 값이 바뀐다.
노란색 신호는 마디번호이고, 0~38의 39개 값이 반복되며, 28틱마다 값이 바뀐다.
그럼 32비트 데이터로 돌아와서, 신호값 32비트 포맷은 다음과 같이 하면 되겠네.
ABCCCCCC DDDDDDEE EEEEFFFF FFGGGGGG
A : 음수 비트
B : 큰 수 비트
C : 마디번호
D : 0 타이밍의 음높이
E : 0.25 타이밍의 음높이
F : 0.5 타이밍의 음높이
G : 0.75 타이밍의 음높이
우선 현재 재생중인 마디번호와 같은 신호값만 필터링하는걸 구상해보자.
신호값들 [각각 >> 24] 비트 연산을 하면 오른쪽으로 비트 자리가 24번 밀리면서 오른쪽 24개를 지우고, ABCCCCCC자리가 FFGGGGGG자리로 이동하겠지.
그럼 값 자체가 마디번호가 된다. AB는 0이니까.
마디번호들 = [신호값들 각각 >> 24, 출력=각각]
필터링된 신호값과 현재마디번호를 비교하여 같은 경우 필터링된 신호종류가 무엇인지 출력한다.
필터된신호종류 = [마디번호들 각각 = 현재마디번호, 출력=각각(1)]
출력된 신호(1)에 적당히 큰 값인 다음 값을 곱해서 필터링된 신호를 가장 큰 수로 만들어줄 준비를 하고, 처음의 악보신호값들과 병합함.
01000000 00000000 00000000 00000000 = 1,073,741,824
병합된신호값들 = [필터링된신호종류 * 1,073,741,824] + 신호값들
그리고 병합한 신호를 다음 조건을 써서 필터링된 신호의 오른쪽의 24비트를 끄집어낼 수 있게 한다.
필터된신호값 = [병합된신호값들 >= 1,073,741,824, 출력=각각(입력값)]
단, 신호값중에 처음 마디번호의 노란색 신호가 섞여들어오는데, 없애야 하므로 일정신호조합기로 큰 음수를 더해서 출력되지 않게함.
그 다음, 필터해온 24비트를 4등분 할 차례다.
현재 진행중인 마디의 세부 타이밍 변수에 6씩 곱해서 시프트값을 출력함.
시프트값 = [세부타이밍*6]
그리고 필터링된 신호를 비트시프트해서 6비트 단위로 밀어서 제일 오른쪽 6비트가 음높이가 되도록 한 다음,
처리전음높이 = [필터된신호값 각각 >> 시프트값]
00111111 = 63 과 비트AND 연산을 해서 오른쪽 6비트만 남기고 다 날려버리면,
음높이 = [처리전음높이 AND 63]
현재 타이밍에 재생되야할 음높이만 딱 남겠네.
기반을 좀 만들었으니 악보를 데이터로 변환해보자.
트럼펫은 없고, 스퀘어가 그나마 어울린다고 처음에 생각했으니까,
스퀘어에서 C3이 8번째, E3는 12번째, G3가 15번째.
64는 커녕 32도 못넘네. 6비트말고 4비트나 5비트 할걸 그랬나.
그러면 마디번호 비트 길이를 늘려서 멜로디를 더 긴걸 넣을 수 있을텐데.
암튼 지금은 6비트 해도 상관없으니 계속 ㄱㄱ. 나중에 옥타브 올리고 싶어질 수도 있으니.
일정신호 조합기에 마디번호, 4가지 타이밍의 음높이를 입력하고
비트 연산으로 시프트 시킨걸 다 합친다.
그 출력값을 10진수 디스플레이 청사진을 써서 1의 자리까지 받아적는다.
이 작업을 마디마다 해서 숫자로 변환한다.
위에서 [필터된신호값 각각 >> 시프트값] 이라는 구문을 사용했고, 시프트값은 작은값부터 큰값으로 변화하므로,
제일 오른쪽의 6비트가 가장 먼저 연주되는 음표이다.
즉, 위에서 예상했던
D : 0 타이밍의 음높이
E : 0.25 타이밍의 음높이
F : 0.5 타이밍의 음높이
G : 0.75 타이밍의 음높이
이 순서가 반대로 뒤집혀서
D : 0.75 타이밍의 음높이
E : 0.5 타이밍의 음높이
F : 0.25 타이밍의 음높이
G : 0 타이밍의 음높이
이렇게 되어야 함.
그럼 각 마디의 첫 음은 비트시프트를 시키지 않고,
두번째 음은 6만큼, 세번째는 12만큼, 네번째는 18만큼 비트시프트를 시켜야 함.
아, 우선 마디를 반으로 쪼개야지.
반으로 쪼갰으니 1/4박자 악보처럼 바뀌겠지.
- 반으로 쪼개서 38마디가 된 시퀀스
마디번호, 음높이, 음길이
01 G 1
02 E 1
03 E 0.5 / E 0.5
04 E 1
05 E 0.5 / G 0.5
06 E 0.5 / C 0.5
07 E 0.5 / G 0.25 / E 0.25
08 C 0.5 / E 0.5
09 G 0.5 / E 0.5
10 E 1
11 C 0.5 / C 0.25 / C 0.25
12 C 1
13 E 0.5 / E 0.5
14 E 1
15 E 0.5 / G 0.5
16 E 0.5 / C 0.5
17 E 0.5 / G 0.25 / E 0.25
18 C 0.5 / E 0.5
19 G 0.5 / E 0.5
20 E 1
21 C 0.5 / C 0.25 / C 0.25
22 C 1
23 C 2
24
25 G 0.5 / G 0.25 / E 0.25
26 C 0.5 / E 0.5
27 C 0.25 / E 0.25 / C 0.25 / E 0.25
28 G 1
29 G 2
30
31 C 0.5 / C 0.5
32 E 0.5 / E 0.5
33 G 0.5 / G 0.25 / E 0.25
34 C 0.5 / E 0.5
35 C 0.25 / E 0.25 / C 0.25 / E 0.25
36 G 1
37 G 2
38
음높이는 C=8, E=12, G=15 이다.
숫자로 바꾸면,
01 16777231
02 33554444
03 50380812
04 67108876
05 83947532
06 100696076
07 120647692
08 134266888
09 151044111
10 167772172
11 186679304
12 201326600
13 218152972
14 234881036
15 251719692
16 268468236
17 288419852
18 302039048
19 318816271
20 335544332
21 354451464
22 369098760
23 385875976
24 402653184
25 422637583
26 436256776
27 456164104
28 469762063
29 486539279
30 503316480
31 520126472
32 536920076
33 556855311
34 570474504
35 590381832
36 603979791
37 620757007
38 637534208
5번까지 10진수 디스플레이 베껴쓰다가 스프레드시트로 옮겨서 작업함.
그리고 게임 내로 값을 복사해서 옮겨준다.
그냥 팩토리오에서 제공하는 신호 종류 앞에서부터 끌어쓴다. 나무상자부터.
이제 점검한번 해보자.
ㅎㅎㅎ 거의 다했따.
처리하는데 몇틱 딜레이가 있는지 세어볼까.
마지막 핑크색 신호를 펄스(1틱만 유지되는 신호)로 바꿔주기 위해서 처음의 초록색 신호를 끌어올 것이다.
그래서 그냥 끌어오면 문제가 있을까 싶어서 틱 딜레이를 따져보고 있는 것이다.
끝에 좀 안맞는거 같은데... 신호가 갈라진 이후, 도착타이밍이 서로 어느정도 맞아야하는데.
그냥 재생하니까 들리지 않는 음이 있었음. 틱 딜레이에 문제가 있으니 고쳐야 했다.
game.speed를 0.05까지 낮추면서 입출력 신호를 모니터링하며 틱 딜레이 타이밍을 맞춘 결과,
딜레이를 추가하기 위해 반복 조합기를 4개나 추가해서 사용공간이 늘어나서 맘에 안든다...
그러게 사전에 딜레이까지 생각하면서 설계했어야지 ㅡㅡ
아무튼 재생/정지 기능까지 추가하면 완료.
초록색 신호가 0이면 현재마디번호가 초기화되도록 했다.
38이하일 때, 메모리를 유지하도록 했으니, 38을 초과시켜버리면 초기화된다.
그럼 한번 들어보자. 조합기들을 한곳에 밀집시켰다.
근데 악기가 스퀘어는 별로 같아서 딴거함. 트럼펫도 없고 뭘하면 좋지.
간단한 멜로디라서 작게만들 수 있을 줄 알았는데, 의외로 커졌다.
간단한 멜로디에 어울리는 작은 설계가 가능할거 같았는데 어렵네.
설계를 바꾸면 조합기 대여섯개는 더 줄일 수 있을거 같은데... 에라 모르겠다.
factorio portal radio나 다른 재생기랑 비교해서 보면 멜로디 설계 궁금한 사람들에겐 도움이 될거 같다.
긴 음악은 신호값 하나로 퉁치기가 안될거임. 팩토리오 신호 가짓수가 제한되어있어서.
악보 사진 없다는건 구라고,
악보 여기있다.
http://www.culturecontent.com/content/contentView.do?search_div=CP_THE&search_div_id=CP_THE008&cp_code=cp0443&index_id=cp04430695&content_id=cp044306950001&search_left_menu=
밀집 버전과 작성에 사용한 버전, 1옥타브 올린 버전(C=20, E=24, G=27) 세가지가 있다.
뭘해도 트럼펫이 없어서 안어울리네 ㅜㅜ
악기 종류는 적절히 골라보자.
■■■■■■■■
청사진 문자열 https://pastebin.com/nbmW0dRh
■■■■■■■■
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
■■■■■■■■
댓글 영역
획득법
① NFT 발행
작성한 게시물을 NFT로 발행하면 일주일 동안 사용할 수 있습니다. (최초 1회)
② NFT 구매
다른 이용자의 NFT를 구매하면 한 달 동안 사용할 수 있습니다. (구매 시마다 갱신)
사용법
디시콘에서지갑연결시 바로 사용 가능합니다.