11P by neo 3달전 | favorite | 댓글 2개
  • 작은 모바일 화면에서 A4 PDF를 확대하며 연주하는 음악가들을 위해, 웹에서 유동적이고 반응형인 악보 렌더링이 필요함

Scribe 프로토타입

  • 과거에 JSON에서 SVG를 출력하는 Scribe라는 음악 렌더러를 프로토타입으로 제작했음
  • 원래 목표는 반응형 음악 렌더러를 제작하는 것이었으나 복잡한 다중 패스 레이아웃 엔진을 작성해야 해서 진전이 어려웠음
  • 이후 CSS Grid를 프로젝트에 도입하면서 Scribe에서 다루던 레이아웃 문제의 해답이 될 수 있을 것 같았음

.stave 클래스

  • 오선지는 그리드와 비슷함. 수직 축은 음높이, 수평 축은 시간임
  • .stave 클래스에서는 수직 축인 그리드 행을 정의
  • 표준 음높이 이름으로 고정 크기 그리드 행을 만들고 오선지를 그리는 배경 이미지를 사용
  • 트레블 음자리 오선에 대한 행 맵 예시:
    .stave {  
      display: grid;  
      row-gap: 0;  
      grid-template-rows:   
        [A5] 0.25em [G5] 0.25em [F5] 0.25em [E5] 0.25em  
        [D5] 0.25em [C5] 0.25em [B4] 0.25em [A4] 0.25em  
        [G4] 0.25em [F4] 0.25em [E4] 0.25em [D4] 0.25em  
        [C4] 0.25em ;  
      background-image: url('/path/to/stave.svg');  
      background-repeat: no-repeat;  
      background-size: 100% 2.25em;  
      background-position: 0 50%;  
    }  
    
  • 각 오선과 간격에 음높이 이름의 그리드 선이 생김

오선에 음높이 배치

  • 오선의 각 행에는 여러 음높이가 위치할 수 있음
  • DOM 요소가 올바른 행에 위치하도록 하기 위해 data-pitch 속성에 음높이 이름을 넣고 CSS로 data-pitch 값을 오선 행에 매핑
    .stave > [data-pitch^="G"][data-pitch$="4"] { grid-row-start: G4; }  
    
  • 이 규칙은 'G'로 시작하고 '4'로 끝나는 음높이를 캡처해서 'G♭4', 'G4', 'G♯4' 등을 G4 행에 할당
  • 모든 오선 행에 대해 이를 수행해야 함
  • 이제 몇 가지 기호를 오선에 배치할 수 있음

.bar 클래스와 박자

  • 리듬을 처리하는 것은 좀 더 까다로움
  • 모든 종류의 리듬을 지원하는 명확한 최소 리듬 분할이 없음
  • 24열 당 1박자 접근법은 8분 음표, 16분 음표, 32분 음표 및 3연음표를 균등하게 배치할 수 있어 좋은 출발점임
  • 4박자를 4 × 24 = 96 그리드 열로 정의하고 시작과 끝에 열을 추가:
    .bar {  
      column-gap: 0.03125em;  
      grid-template-columns:  
        [bar-begin]  
        max-content  
        repeat(96, minmax(max-content, auto))  
        max-content  
        [bar-end];  
    }  
    
  • ::before와 ::after로 마디선을 추가하고 data-pitch="B4"로 음자리 기호를 중앙에 배치

박자에 기호 배치

  • 이번에는 data-beat 속성을 사용하여 요소에 박자를 할당하고 CSS 규칙을 사용하여 박자를 그리드 열에 매핑
  • CSS 맵은 1/24박자마다 하나의 규칙으로 구성
  • 속성 ^= 시작 선택기를 사용하면 규칙이 오차 허용이 됨
  • .stave 클래스와 함께 사용하면 data-beat를 1~5 사이의 박자로, data-pitch를 음 이름으로 설정하여 박자와 음높이별로 기호를 배치할 수 있음

유동적이고 반응형인 악보

  • 이러한 여러 마디를 flexbox 컨테이너에 넣으면 반응형 악보를 볼 수 있음
  • 아직 누락된 것들이 많지만 시작하기에 좋은 기반임
  • 이미 온라인 음악 렌더러보다 훨씬 우아하게 줄 바꿈이 됨

음표 사이의 공간

  • 서로 더 가까운 시간에 발생하는 음표 머리는 약간 더 가깝게 렌더링됨
  • 작은 column-gap에 의해 만들어진 미묘하고 의도적인 효과로, 기호 요소가 슬롯에 들어가는 일종의 시간 '에테르' 역할을 함
  • 열 자체는 음표 머리가 없으면 너비가 0이지만 박자가 더 멀리 떨어진 이벤트 사이에는 더 많은 열 간격(박자당 24개)이 있어 더 많은 거리가 생김
  • 기호의 여백을 조정하여 일정한 간격을 제어할 수 있음

음자리와 박자 기호

  • 수직 및 수평 간격에 대해 별도 클래스를 사용한 이유는 다른 것을 건드리지 않고 하나를 교체할 수 있기 때문
  • 같은 멜로디를 베이스 음자리에 표시하려면 .stave 클래스를 같은 data-pitch 속성을 베이스 오선 행에 매핑하는 bass-stave 클래스로 교체하면 됨
  • CSS로 data-duration="5"를 .bar의 120 그리드 템플릿 열에 매핑하면 같은 오선에 5/4 박자 기호를 줄 수 있음

코드와 가사

  • CSS Grid를 사용하면 악보 그리드 내에서 다른 기호도 정렬할 수 있음
  • 코드와 가사, 다이내믹 등을 시간이 지정된 이벤트와 정렬하고 확장할 수 있음

음표 꼬리

  • 음표 꼬리, 코드, 일부 긴 쉼표는 data-duration 속성을 grid-column-end 범위 값에 매핑하여 열에 걸치게 만듦

크기 조정

  • 전체 시스템은 em 단위로 크기가 지정되므로 font-size를 변경하는 것만으로 크기를 조정할 수 있음

Flex와 Grid의 한계

  • 완벽한 시스템은 아님. 한계점:
    1. CSS는 줄 바꿈시 새 음자리/조표를 자동으로 배치할 수 없음
    2. 새 줄의 새 음표에 묶음줄을 연결할 수 없음
    3. 기울어진 음표 꼬리는 Grid가 배치한 후에야 정확한 위치를 알 수 있어 정렬이 어려움
  • 완전히 마무리하려면 약간의 정리 JavaScript가 필요하지만 CSS가 레이아웃 작업의 대부분을 처리하므로 JavaScript에서 할 레이아웃 작업이 훨씬 줄어듦

사용자 정의 요소

  • 이 새로운 CSS 시스템을 중심으로 인터프리터를 작성하고 요소에 래핑함
  • 아직 프로덕션 준비는 안되었지만 반응형 리드 시트를 렌더링하고 드럼을 표기할 수 있어 흥미롭고 유용함
  • 콘텐츠의 데이터, src 속성으로 가져온 파일, 요소의 .data 속성에 설정된 JS 객체에서 악보를 렌더링함
  • 현재 개발 빌드는 웹 페이지에 파일을 가져와서 사용해 볼 수 있음

앞으로 계획

  • Scribe 0.3의 개선사항 외에 장기적으로 조사하고 싶은 기능:
    • SMuFL 글꼴 지원 - 악보 기호에 사용되는 글꼴 변경
    • 중첩 시퀀스 지원 - 다중 파트 곡 활성화
    • 분할 오선 렌더링 - 한 오선에 여러 파트 배치
    • 다중 오선 렌더링 - 여러 개의 정렬된 오선에 여러 파트 배치

GN⁺의 의견

  • 웹에서 악보를 유동적이고 반응형으로 렌더링하는 것은 음악가와 음악 애호가 모두에게 매우 유용할 것 같음. PDF 악보를 작은 화면에서 확대/축소하며 보는 불편함을 해소해 줄 수 있을 것
  • CSS의 Grid와 Flex 레이아웃을 활용한 접근 방식이 흥미로움. 복잡한 레이아웃 엔진 없이도 CSS만으로 꽤 많은 부분을 해결할 수 있다는 것을 보여주는 좋은 예시
  • 하지만 악보의 특성상 CSS만으로는 한계가 있는 부분들도 있음. 줄 바꿈 시 자동으로 음자리나 조표를 배치한다든지, 묶음줄을 자동 연결하는 것 같이 음악적 문맥을 이해해야 하는 부분은 자바스크립트의 도움이 필요할 것
  • 리드 악보 렌더링과 드럼 악보 지원 등 이미 꽤 많은 부분을 구현했다고 하니, 조만간 충분히 쓸만한 수준으로 개선될 수 있을 것 같음. 오픈소스화 해서 개발이 지속된다면 MuseScore 같은 기존 악보 편집기의 좋은 대안이 될 수 있을 것
  • 앞으로 계획하고 있는 SMuFL 글꼴 지원, 다중 파트 및 다중 오선 렌더링 지원 등의 기능이 구현된다면 악보 표현의 완성도가 크게 높아질 것 같음. 기대가 되는 프로젝트

이러시는 이유가 있을거 아니예요

Hacker News 의견
  • Sheet music 소프트웨어 개발자로부터 CSS 그리드를 이용한 악보 렌더링 방식에 대해 찬사가 있음
    • Soundslice라는 웹 기반 악보 렌더링 서비스를 10년 넘게 개발해 왔으며, 2014년에 최초로 "반응형" 웹 악보 렌더링을 구현했음
    • 관련 기술 상세 내용은 발표 영상 링크 참고: https://www.youtube.com/watch?v=XH5EtQge_Bg
    • Soundslice의 반응형 악보 예시 링크: https://www.soundslice.com/slices/zzNlc/
    • 웹 기반 편집기, 연습 기능, 사진/PDF에서 악보 데이터 추출하는 스캔 기능 등 다양한 툴을 제공함
    • CSS 그리드 방식은 가벼운 프로젝트에는 유용할 수 있지만, 풀 스코어의 복잡하고 미묘한 표현을 다 구현하기는 어려울 것임
  • JavaScript 없이 CSS만으로 구현할 수 있도록 CSS 커뮤니티에 제안해보는 것도 좋을 듯함
    • 예를 들어 줄바꿈 시 음자리표 반복 표시는 sticky table header와 유사한데, 악보 외에도 활용될 수 있음
  • CSS의 attribute selector([...]) 문법이 인상 깊었음. 예: .stave > [data-pitch^="A"][data-pitch$="5"] { grid-row-start: A5; }
  • 음악 조판사 입장에서는 시각적으로 개선이 많이 필요해 보임. CSS만으로는 정밀도에 한계가 있어 어려울 듯함
    • 음표 기둥, 활, 붙임줄 등의 표현에 문제가 있음
    • 대부분의 브라우저 악보는 SVG나 Canvas로 벡터 렌더링하여 핀포인트 정밀도를 구현함
    • CSS 외에 이미 Soundslice, Sibelius Cloud Publishing 등 브라우저에서 스케일러블한 악보를 구현하는 다른 도구들이 있음
  • 처음에는 CSS로 악보를 표현하는 게 잘 안 될 것 같았는데, 간단한 방식으로 타이포그래피 품질이 인상적임. 작성자에게 찬사를 보냄
    • 다만 화음, 8/16분음표 간격, 파트 간 정렬 등 특수한 경우 잘 작동할지 우려됨. Lilypond는 이런 복잡한 표현에서 유연성이 입증됨
  • CSS 그리드가 흥미로움. 예전에 가구 디자이너를 pure frontend JS로 CSS 그리드 활용해 구현한 적 있음: https://alnvdl.github.io/2023/01/…
  • <scribe-music> 커스텀 엘리먼트도 기대됨
    • 몇 년 전 인턴이 VexFlow를 웹 컴포넌트로 래핑한 프로젝트 진행했었는데 유지보수 안 됨: https://github.com/PolymerLabs/vexflow-elements/…
    • 잘 관리되고 사용하기 쉬운 라이브러리가 웹 음악 표기법에 큰 도움이 될 것임
  • Lilypond(lilypond.org)의 대안이 나온 것은 좋지만, 표기법이 매우 복잡해서 간결성의 이점은 오래가지 않을 듯함
    • Asciidoc 매니아라면 Lilypond를 Asciidoc 툴체인에 통합하기 쉬움. DocBook PDF 파이프라인에서 사용 중이며, 출력물이 꽤 괜찮음. TeX과 유사함
  • https://www.musicxml.comhttps://opensheetmusicdisplay.org 를 상기시켜 줌. 훨씬 큰 비용이 들지만 완전한 솔루션임
  • Impro-Visor(https://github.com/Impro-Visor/Impro-Visor)의 어설픈 악보 기능을 이것으로 대체할 수 있을지 궁금함
  • CSS 벤치마크 같은 느낌