11 điểm bởi GN⁺ 2024-05-01 | 2 bình luận | Chia sẻ qua WhatsApp
  • Đối với các nhạc công phải phóng to PDF A4 trên màn hình di động nhỏ để chơi, cần có cách dựng bản nhạc linh hoạt và đáp ứng trên web

Nguyên mẫu Scribe

  • Trước đây đã tạo thử nghiệm một trình dựng nhạc tên là Scribe, xuất SVG từ JSON
  • Mục tiêu ban đầu là xây dựng một trình dựng nhạc đáp ứng, nhưng việc phải viết một bộ máy bố cục nhiều lượt phức tạp khiến tiến triển gặp khó khăn
  • Sau đó, khi đưa CSS Grid vào dự án, có cảm giác đây có thể là lời giải cho bài toán bố cục mà Scribe từng gặp

Lớp .stave

  • Khuông nhạc khá giống với lưới. Trục dọc là cao độ, trục ngang là thời gian
  • Trong lớp .stave, các hàng lưới theo trục dọc được định nghĩa
  • Tạo các hàng lưới có kích thước cố định bằng tên cao độ chuẩn và dùng ảnh nền để vẽ khuông nhạc
  • Ví dụ về ánh xạ hàng cho khuông khóa Sol:
    .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%;  
    }  
    
  • Mỗi dòng kẻ và khoảng cách trên khuông đều có một đường lưới mang tên cao độ

Đặt cao độ lên khuông

  • Mỗi hàng trên khuông có thể chứa nhiều cao độ
  • Để phần tử DOM nằm đúng hàng, đặt tên cao độ vào thuộc tính data-pitch và dùng CSS để ánh xạ giá trị data-pitch vào hàng của khuông
    .stave > [data-pitch^="G"][data-pitch$="4"] { grid-row-start: G4; }  
    
  • Quy tắc này bắt các cao độ bắt đầu bằng G và kết thúc bằng 4, rồi gán G♭4, G4, G♯4... vào hàng G4
  • Cần làm điều này cho mọi hàng của khuông
  • Giờ đây có thể đặt một số ký hiệu lên khuông

Lớp .bar và nhịp

  • Xử lý tiết tấu thì phức tạp hơn một chút
  • Không có một mức chia nhịp tối thiểu rõ ràng nào hỗ trợ mọi loại tiết tấu
  • Cách tiếp cận 24 cột cho mỗi phách là điểm khởi đầu tốt, vì có thể đặt đều nốt móc đơn, móc kép, móc ba mươi hai và tam liên
  • Định nghĩa 4 phách thành 4 × 24 = 96 cột lưới, rồi thêm cột ở đầu và cuối:
    .bar {  
      column-gap: 0.03125em;  
      grid-template-columns:  
        [bar-begin]  
        max-content  
        repeat(96, minmax(max-content, auto))  
        max-content  
        [bar-end];  
    }  
    
  • Thêm vạch nhịp bằng ::before::after, rồi đặt khóa nhạc vào giữa bằng data-pitch="B4"

Đặt ký hiệu theo nhịp

  • Lần này dùng thuộc tính data-beat để gán phách cho phần tử, và dùng các quy tắc CSS để ánh xạ phách vào cột lưới
  • Bản đồ CSS gồm một quy tắc cho mỗi 1/24 phách
  • Dùng bộ chọn thuộc tính bắt đầu ^= để quy tắc có khả năng chịu sai số
  • Khi dùng cùng lớp .stave, có thể đặt ký hiệu theo cả nhịp và cao độ bằng cách đặt data-beat thành giá trị phách từ 1 đến 5, và data-pitch thành tên nốt

Bản nhạc linh hoạt và đáp ứng

  • Đặt nhiều ô nhịp như vậy vào trong một vùng chứa flexbox sẽ cho ra bản nhạc đáp ứng
  • Vẫn còn thiếu nhiều thứ, nhưng đây là nền tảng tốt để bắt đầu
  • Việc xuống dòng đã thanh lịch hơn nhiều so với các trình dựng nhạc trực tuyến hiện có

Khoảng cách giữa các nốt

  • Các đầu nốt xảy ra gần nhau hơn về mặt thời gian sẽ được dựng gần nhau hơn một chút
  • Đây là hiệu ứng tinh tế nhưng có chủ đích do column-gap nhỏ tạo ra, đóng vai trò như một dạng “ether” thời gian để các phần tử ký hiệu rơi vào các khe
  • Bản thân các cột có độ rộng bằng 0 nếu không có đầu nốt, nhưng giữa các sự kiện cách xa nhau hơn sẽ có nhiều khoảng cách cột hơn (24 cột mỗi phách), nên tạo ra nhiều khoảng trống hơn
  • Có thể điều chỉnh khoảng đệm của ký hiệu để kiểm soát độ giãn cách tổng thể

Khóa nhạc và ký hiệu nhịp

  • Lý do dùng các lớp riêng cho khoảng cách dọc và ngang là để có thể thay một thứ mà không ảnh hưởng đến thứ còn lại
  • Muốn hiển thị cùng một giai điệu ở khóa Fa, chỉ cần thay lớp .stave bằng lớp bass-stave, lớp này ánh xạ cùng thuộc tính data-pitch vào các hàng của khuông khóa Fa
  • Nếu dùng CSS để ánh xạ data-duration="5" vào 120 cột mẫu lưới của .bar, có thể gán nhịp 5/4 cho cùng khuông đó

Hợp âm và lời ca

  • Dùng CSS Grid cũng cho phép căn chỉnh các ký hiệu khác bên trong lưới bản nhạc
  • Có thể căn và kéo giãn hợp âm, lời ca, ký hiệu cường độ... theo các sự kiện có gán thời gian

Đuôi nốt

  • Đuôi nốt, hợp âm và một số dấu nghỉ dài có thể được cho trải qua nhiều cột bằng cách ánh xạ thuộc tính data-duration vào giá trị phạm vi grid-column-end

Thay đổi kích thước

  • Toàn bộ hệ thống dùng đơn vị em, nên chỉ cần thay đổi font-size là có thể đổi kích thước

Giới hạn của Flex và Grid

  • Đây không phải là một hệ thống hoàn hảo. Các giới hạn gồm:
    1. CSS không thể tự động đặt khóa nhạc/ký hiệu hóa biểu mới khi xuống dòng
    2. Không thể nối dấu móc nhóm sang nốt đầu tiên của dòng mới
    3. Đuôi nốt nghiêng chỉ biết được vị trí chính xác sau khi Grid đã bố trí xong, nên khó căn chỉnh
  • Để hoàn thiện hoàn toàn thì vẫn cần một ít JavaScript dọn dẹp, nhưng vì CSS đã xử lý phần lớn công việc bố cục nên lượng việc bố cục còn lại trong JavaScript giảm đi rất nhiều

Phần tử tùy chỉnh

  • Đã viết một bộ thông dịch xoay quanh hệ thống CSS mới này và bọc nó trong một phần tử
  • Dù chưa sẵn sàng cho production, nó đã có thể dựng lead sheet đáp ứng và ký âm cho trống, nên khá thú vị và hữu ích
  • Dựng bản nhạc từ dữ liệu nội dung, từ tệp được nạp bằng thuộc tính src, hoặc từ đối tượng JS được gán vào thuộc tính .data của phần tử
  • Bản dựng phát triển hiện tại có thể được nạp vào trang web để dùng thử

Kế hoạch sắp tới

  • Ngoài các cải tiến của Scribe 0.3, về dài hạn còn muốn khảo sát các tính năng sau:
    • Hỗ trợ phông chữ SMuFL - thay đổi phông chữ dùng cho ký hiệu bản nhạc
    • Hỗ trợ chuỗi lồng nhau - kích hoạt tác phẩm nhiều bè
    • Dựng khuông chia tách - đặt nhiều bè trên một khuông
    • Dựng nhiều khuông - đặt nhiều bè trên nhiều khuông được căn chỉnh

Ý kiến của GN⁺

  • Việc dựng bản nhạc theo kiểu linh hoạt và đáp ứng trên web có vẻ sẽ rất hữu ích cho cả nhạc công lẫn người yêu nhạc. Nó có thể giải quyết sự bất tiện khi phải phóng to/thu nhỏ bản nhạc PDF trên màn hình nhỏ
  • Cách tiếp cận tận dụng bố cục Grid và Flex của CSS rất thú vị. Đây là ví dụ tốt cho thấy chỉ với CSS cũng có thể giải quyết được khá nhiều vấn đề mà không cần một bộ máy bố cục phức tạp
  • Tuy vậy, do đặc thù của bản nhạc, vẫn có những phần CSS đơn thuần không xử lý nổi. Những việc cần hiểu ngữ cảnh âm nhạc như tự động đặt khóa nhạc hoặc hóa biểu khi xuống dòng, hay tự động nối dấu móc nhóm, sẽ cần đến sự hỗ trợ của JavaScript
  • Vì đã hiện thực được khá nhiều phần như dựng lead sheet và hỗ trợ bản nhạc trống, nên có vẻ dự án này sớm có thể được cải thiện đến mức đủ hữu dụng. Nếu được mã nguồn mở và tiếp tục phát triển, nó có thể trở thành một lựa chọn thay thế tốt cho các trình biên tập bản nhạc hiện có như MuseScore
  • Nếu các tính năng đang được lên kế hoạch như hỗ trợ phông chữ SMuFL, hỗ trợ nhiều bè và nhiều khuông được hiện thực, mức độ hoàn thiện trong biểu diễn bản nhạc có lẽ sẽ tăng lên đáng kể. Đây là một dự án đáng mong đợi

2 bình luận

 
roxie 2024-05-06

Chắc hẳn phải có lý do gì đó chứ.

 
GN⁺ 2024-05-01
Ý kiến trên Hacker News
  • Có lời khen từ một nhà phát triển phần mềm bản nhạc về cách render bản nhạc bằng CSS Grid
    • Đã phát triển Soundslice, một dịch vụ render bản nhạc trên web, hơn 10 năm và từng triển khai bản nhạc web “responsive” đầu tiên vào năm 2014
    • Xem chi tiết kỹ thuật qua video thuyết trình liên quan: https://www.youtube.com/watch?v=XH5EtQge_Bg
    • Liên kết ví dụ về bản nhạc responsive của Soundslice: https://www.soundslice.com/slices/zzNlc/
    • Cung cấp nhiều công cụ như trình biên tập trên web, tính năng luyện tập, và chức năng quét để trích xuất dữ liệu bản nhạc từ ảnh/PDF
    • Cách làm bằng CSS Grid có thể hữu ích cho các dự án nhẹ, nhưng có lẽ sẽ khó thể hiện đầy đủ sự phức tạp và tinh tế của full score
  • Có lẽ cũng nên đề xuất với cộng đồng CSS để có thể triển khai chỉ bằng CSS mà không cần JavaScript
    • Ví dụ, việc lặp lại khóa nhạc khi xuống dòng tương tự như sticky table header, và có thể ứng dụng ngoài phạm vi bản nhạc
  • Cú pháp attribute selector([...]) của CSS gây ấn tượng. Ví dụ: .stave > [data-pitch^="A"][data-pitch$="5"] { grid-row-start: A5; }
  • Từ góc nhìn của người dàn bản nhạc, có vẻ vẫn cần cải thiện nhiều về mặt thị giác. Chỉ với CSS thì có lẽ khó đạt đủ độ chính xác
    • Có vấn đề trong việc thể hiện thân nốt, dấu luyến, và dấu nối
    • Phần lớn bản nhạc trên trình duyệt dùng SVG hoặc Canvas để render vector nhằm đạt độ chính xác tuyệt đối
    • Ngoài CSS, đã có các công cụ khác để hiện thực hóa bản nhạc có khả năng co giãn trên trình duyệt như Soundslice, Sibelius Cloud Publishing
  • Ban đầu tưởng rằng thể hiện bản nhạc bằng CSS sẽ không ổn, nhưng chất lượng typography theo cách đơn giản này khá ấn tượng. Gửi lời khen cho tác giả
    • Tuy vậy, vẫn lo ngại liệu nó có hoạt động tốt với các trường hợp đặc biệt như hợp âm, khoảng cách giữa các nốt móc đơn/móc kép, hay căn chỉnh giữa các part hay không. Lilypond đã chứng minh được tính linh hoạt trong những biểu đạt phức tạp như vậy
  • CSS Grid rất thú vị. Trước đây từng dùng pure frontend JS kết hợp CSS Grid để làm một công cụ thiết kế nội thất: https://alnvdl.github.io/2023/01/07/designing-furniture-using-the-css-grid.html
  • Cũng rất mong chờ custom element <scribe-music>
  • Thật tốt khi có một lựa chọn thay thế cho Lilypond(lilypond.org), nhưng ký âm quá phức tạp nên lợi thế về tính ngắn gọn có lẽ sẽ không kéo dài
    • Nếu là người mê Asciidoc thì khá dễ tích hợp Lilypond vào toolchain Asciidoc. Có người đang dùng nó trong pipeline DocBook PDF và cho ra kết quả khá ổn. Nó tương tự TeX
  • Gợi nhớ đến https://www.musicxml.comhttps://opensheetmusicdisplay.org. Tốn kém hơn nhiều nhưng là giải pháp hoàn chỉnh
  • Tò mò liệu có thể dùng cái này để thay thế tính năng bản nhạc còn khá vụng về của Impro-Visor(https://github.com/Impro-Visor/Impro-Visor) hay không
  • Cảm giác như một bài benchmark cho CSS