Table of contents
This page features information helpful for understanding and expanding Playnote's codebase.
External resources
The most important resource for implementing the BMS format is hitkey's write-up. It can be a bit confusing due to machine translation, but the wealth of information is unparalleled.
Other BMS players commonly used by the western community:
- Lunatic Rave 2: The de-facto golden standard. Old and buggy, but highly respected for single-handedly popularizing BMS.
- beatoraja (and its western fork): A newer player written in Java. Introduces some modern features, and is highly customizable.
- Bemuse: A BMS player for the web. Requires no install and bundles some songs, making it the most accessible way to play BMS thus far.
wcko87's English beatoraja guide has lots of information about BMS in general, and links to places where one can find songs to play.
Audio latency
One of the goals of Playnote is to offer the smallest possible audio latency on every system by default. Here is what it means in detail, determined from personal experience and experimentation.
Windows
There are many audio APIs available on Windows. Most of them are now wrapped by newer APIs, and the one that makes the most sense to use is WASAPI. It provides reasonably direct access to either the direct audio device or the system mixer, while being available on every install.
Another alternative is ASIO, a proprietary API compatible with some high-end audio equipment. It guarantees the lowest latency when supported, but introduces packaging and licensing complications. Most computers would need a compatibility layer like ASIO4ALL to use it, defeating the point as it implements ASIO over WASAPI anyway.
WASAPI offers shared mode and exclusive mode. Shared mode allows other applications in the system to play audio at the same time, mixing them together, but at higher latencies to facilitate the mixing and any system-wide audio effects. In practice, this is around 10-22ms. Exclusive mode, on the other hand, allows an application to stream data directly to the audio device, bypassing the mixer. On the tested machines, it allowed for a 3ms latency. For this reason it's the default audio mode in Playnote, with an option to switch to shared if mixing is crucial for the player - for example to join voice chats during gameplay.
Linux
Linux is infamous for its many audio APIs. At the core is the now-deprecated OSS, which offered direct access to the audio device. ALSA, a layer over it, provided a mixer to allow for multiple apps to play audio. PulseAudio then ran as another layer above ALSA, taking over its mixing duties with extra capabilities like network streaming. JACK, an audio server for professional audio, was an alternative for low-latency audio routing. Finally, the most recent newcomer to the scene is PipeWire, which aims to be a drop-in replacement for both PulseAudio and JACK with stronger latency guarantees but configuration-free daily usage.
For Playnote, the option of choice is PipeWire. It has already been the default preinstalled audio server on every major Linux distribution for some time. PipeWire adjusts its mixer latency dynamically to match the lowest latency requested by any application, so its goals line up perfectly with Playnote's needs. The requested latency is in fact guaranteed, with any other components in the audio chain like system-wide effects using up some of the time budget, preferring to compromise stability of the stream over its latency. Interfacing with PipeWire directly, rather than using a higher-level library or another API it supports, allows us to make these latency requests instead of hoping for our calls to be translated as intended.