스카이게임 악기.한선 — 합주 음계/코드 데이터 정본
개요
스카이식 악기 합주(펜타토닉)를 위한 데이터 정본을 한선씨로 작성. 실제 오디오 합성(주파수 2^(n/12))은 VM 정수나눗셈 불가라 절대 하지 않고, 정수 반음(semitone) 오프셋만 저장 — 합성은 브라우저 Web Audio(village.js)가 맡는다.
무엇을 했는지
/Users/ef/CrownyOS/os-site/게임슬라이스/악기.한선 생성
펜타토닉 스케일 반음 오프셋 [0,2,4,7,9], 근음 MIDI 60(C4), 4코드 진행(각 3음 triad 정수배열)을 data/악기.json에 기록 (장면3D.한선의 시작/항목/끝 append 패턴 그대로 답습)
함수 음유효(반음) — 근음 기준 ±24반음(2옥타브) 범위 검증, 참=1/거짓=-1
함수 노트이벤트(악기id, 반음, 시각) — village.js의 기존 PRESENCE 소켓 프로토콜({t:"chat",msg:..})을 확장한 {"t":"note","inst":..,"n":..,"time":..} 이벤트 문자열 조립. 무효 반음은 빈 문자열 반환.
CROWNY_STRICT=1로 컴파일: exit=0, toau 40824B, STRICT 경고 0
crownyc run으로 실행 확인: data/악기.json 생성됨(86B), 음유효/노트이벤트 데모 정상 동작
crownycode-learn.sh add "악기_펜타토닉_음계_노트브로드캐스트" 로 학습DB 등록산출 데이터
/Users/ef/CrownyOS/os-site/게임슬라이스/data/악기.json:
json{"scale":[0,2,4,7,9],"root":60,"chords":[[60,64,67],[67,71,74],[69,72,76],[65,69,72]]}
village.js(브라우저) 연동 방법 — 잔여 작업(라이브 무접촉이라 미배선)
악기.json을 fetch해 scale/root/chords 로드.
- 반음→주파수 합성은 반드시 JS에서:
freq = 440 * Math.pow(2, (root + semitone - 69) / 12).
- 사용자가 노트를 연주하면
PRESENCE.send({t:"note", inst:"harp1", n:semitone, time:performance.now()}) 형태로 기존 PRESENCE WS 소켓(line ~705 PRESENCE 객체)에 실어 보낸다 — 한선씨 노트이벤트()가 만드는 문자열과 동일 스키마.
PRESENCE 수신 핸들러(현재 o.t === "chat" 분기, village.js:715 부근)에 else if (o.t === "note") 분기를 추가해 다른 접속자의 화면에서 같은 반음으로 오디오를 트리거 → 합주 완성.
- 음계 제약은 서버가 아니라 클라이언트가
한선씨 음유효()와 동일한 범위(±24반음) 규칙으로 사전 필터링(치트 방지는 추후 서버 검증 과제로 남김).
관련 파일
/Users/ef/CrownyOS/os-site/게임슬라이스/악기.한선 (신규)
/Users/ef/CrownyOS/os-site/게임슬라이스/data/악기.json (신규, 실행 산출물)
- 참조 패턴:
/Users/ef/CrownyOS/스튜디오/장면3D.한선 (append 포맷 원본)
- 참조 대상(무접촉):
/Users/ef/CrownyOS/os-site/village.js (PRESENCE 소켓, chat 릴레이 — line 705~742, 1128)
잔여 이슈
- village.js에
note 이벤트 분기·Web Audio 합성·연주 UI는 아직 미구현(라이브 무접촉 지시로 이번 작업 범위 제외).
- 서버 측(presence.crowny.org) 반음 유효성 검증 없음 — 현재는 클라이언트 자율 필터만 가정.