Replies: 5 comments
-
First of all, I definitely support the idea of the format discussion and I think it may bring some really good things to the .nbs format.
This is definitely interresting issue and as far as I remember it is also inconsistently used. NoteBlockAPI use the 'Sound file' property for custom instrument's since there is lower probabilty that it will be in incorrect format (OpenNoteBlockStudio's default custom instrument name is not allowed in Minecraft).
Most of the songs I came across didn't even have their metadata field filled but I agree that on the specification level this may be a problem. The first obvious idea is to switch to UTF-8 which is completely universal when it comes to letters, symbols and whatever may user enter. However, it's decoding is definitely more complicated than ASCII since it's not only multibyte but also with different count of bytes per symbol. For Java parsers like NoteBlockAPI this shouldn't be a problem.
I think that the fact that NBS files are binary is a good thing and I would definitely stick to it because any textual format would make the files a lot bigger. The solution to the issue of future proof implementation also is not as complicated and have been used in many file formats over the years. The NBS file is already splited into blocks (metadata block, note blocks, layer blocks, custom instrument blocks) if you add a length information in bytes to the beginning of each block, you can later add any field you want to the end of the block and properly implemented parsers should simply seek to the end of the block and ignore these new fields.
Actually, this is not really true. There are hard limits in the NBS specification. Since e.g. song's length is signed short in the specification you simply can't have a song longer than 32 767 ticks even if your parser would be able to handle it. And the same holds for every numeric field. I think that especially numbers like song's length (short), instrument's identifier (byte), custom instrument's count and identifier (both byte) should be changed to at least int or short. From the point of view of the NoteBlockAPI developer, the rest of the issues is not very important for me. Layer lock was ignored so far because it doesn't make much sense to lock some layer in the exported song (and there is also no reason why would you export song with multiple layers but only want to play only one layer). Since the tempo is stored as ticks per second in file the issue with BPM is also not relevant for me. NoteBlockAPI already supports future instruments so that is also not an issue for me. |
Beta Was this translation helpful? Give feedback.
-
I believe this would be a great feature to keep and document, as I and many others mute incomplete sections of the song or single out certain layers. The lack of documentation creates inconsistencies between ONBS, NoteBlockAPI, NBS.js, and whatever other
I believe this is up to the library developers and users to deal with. Every implementation of the format would be different either way. NBAPI would have to map to Minecraft's sound events, NBS.js has to load instruments from an ArrayBuffer somehow, etc. The only solution I'd have in mind is to include the instrument files directly in the file, but that'd add an extreme amount of bloat fast. Potentially a way to export the song and its instruments separately from saving the song?
Saving with a JSON-like format would be much easier to read, manipulate, and write. However, as @koca2000 said, the file size would explode. While I was working on the playlist feature of NBSPlayer, I attempted to save the loaded songs as their loaded JSON form. The resulting file was megabytes larger than all the loaded There's most likely a better way to keep the format future-proof while sticking with the binary format. For example, containing "version" blocks at the end of the file, such as a "v1" block, "v2", and so on. The parser can stop when it's finished reading all the version data it needs, and won't run into issues with any unimplemented versions.
This could be easily solved by making BPM the primary tempo format. Load as BPM, then calculate and save the TPS from said BPM. I greatly appreciate the new approach on spec changes. As the community expands and more parsers are developed, this will ensure the future stability of the format and its parsers! |
Beta Was this translation helpful? Give feedback.
-
Thank you @koca2000 and @encode42 for your input! It's great to have different perspectives on the problem.
This goes to show how important proper standardization is. We've had two different implementations having to come up with workarounds for issues with the format in their own way!
I can confirm we won't be moving to a different format. Not only the increased file size would be undesirable, but this would mean an added difficulty for plugin makers to maintain two different formats. That being said, JSON could be used in the future as an intermediate format for saving project files. (I'll get back to this!)
This is probably the solution we're gonna go with. Though, we must also clearly determine how existing songs have to be interpreted, as for example pynbs crashes when reading a field containing non-ASCII characters due to not specifying an encoding (see OpenNBS/pynbs#3).
This is planned as a separate file format! See #239.
These are both great ideas, but I'm wondering if they can be implemented in a successful way, given the kinds of changes we might have to make. For example, if you look at the kinds of fields that have been added over the past few NBS versions, not all of them are simply part of a block, but they are compound fields that appear once for every instance of an element (e.g. layer lock, note block pitch). So to make this work while allowing new fields to be added anywhere -- even in note blocks or layers --, we would probably have to repeat this procedure on multiple levels. Not only this, but some of the changes could even modify the way some fields are interpreted: see, for example, @encode42's suggestion:
Considering changes of this nature could be needed even after the future-proof update, no change in the file structure would account for this in a way that would avoid the need for parser updates, unless we marked the existing field as deprecated and re-added it later in the file. Accounting for all of this would increase the format's complexity in such a way that it makes me wonder whether it's worth to make the format future-proof at all. On the long term it would be a wise idea, but on the other hand, the number of fields we could potentially still add is so small that it possibly doesn't justify such a large structural change.
And this brings me to the third point: NBS files are already kinda saturated with features. Anything we could add further on from this point would probably be irrelevant for NBS players -- as mentioned by @koca2000, features such as layer lock already are. There are two solutions for this: one is to delay NBS version 6 so we have enough time to think of all features that could potentially cause breaking changes, and add them to the format in that version. The other, and more ideal, one, would be to split responsibilities: create a new type of file called So, here are the key takeaways of this:
NB: in the past, I've done a detailed write-up on both character encoding and layer lock, but on both occasions I've lost them due to typing directly on the GitHub form. :( |
Beta Was this translation helpful? Give feedback.
-
I also prefer binary files to text files. However, the current
The table shows that a compressed JSON file may be smaller than an uncompressed NBS file. Therefore, I think it'd be nice if we could save songs as both compressed and uncompressed files in the future.
A perfect case study for this is module file, especially the .xm file. A module file stores song data (notes, effects) and sample data (audio of instruments) in a single file with a small file size.
I also faced this problem when implementing file conversion from a new format to the classic format in NBSTool. In my opinion, a simple solution would be saving the Minecraft version which a song aimed at as a string, such as "1.14", or as an integer (Minecraft protocol version number for example) in the file. Data-pack exporting can also utilize this information to output the correct pack format (see #429).
I also would like to discuss how to store tempo change "events" (or whatever they are called) and future similar events in NBS version 6. I have two solutions to resolve this.
Overall, that's my two cents about these issues. This conversation has been a good read to me so far. |
Beta Was this translation helpful? Give feedback.
-
Hi @IoeCmcomc! Thanks for your input.
That's a very interesting comparison! Overall, NBS files are small enough that implementing a compression approach wouldn't provide significant gains (as most files are <100 KB, which for most purposes is a negligible file size nowadays). However, for large files like the Megacollab, compression can be quite significant as you've shown. It's quite curious how a compressed JSON can be smaller than an uncompressed NBS file! All the repetition and markup originating from the format are "canceled out" by the compression. Although we still won't replace the NBS format with JSON, I'm wondering how you've represented the data in the JSON format to achieve those results — this might be useful when we're developing the intermediate format we mentioned above, since it should be a superset of the current features in the NBS format.
I agree it would be useful to save songs in a compressed format. My only worry is, as that wasn't the default option from the very beginning (like the NBT specification which specifies gzip as one kind of compression you can find in NBT files in the wild), parsers would need a way to differentiate compressed vs. uncompressed files. Thinking of Python and an EAFP approach, one could verify if the first two bytes of the file are zero – if not, try reading it as a classic NBS file, and if that fails, try decompressing it. Or in a different order: try decompressing it first and, if it fails, read it like an uncompressed file. (The magic bytes in each format should help!) A third approach could be introducing a new file extension for compressed NBS files; however, I don't think it'd be used widely enough to warrant a good adoption by plugins. We've had good reasons to introduce new file extensions before and we've passed on most of them – mostly because it would duplicate the work on code, maintenance, documentation etc.
That's an awesome example! I'll keep it in mind once it comes the time to implement these changes. All the features/new formats we're discussing will eventually turn into more detailed format proposals that explicitly outline the suggested changes -- this will allow everyone to influence the new formats' evolving direction and discuss the additions in depth.
I agree a simple "Minecraft version" field would fix this problem! The protocol version is an interesting suggestion. Though, since changes to note block instruments only happened on two occasions (1.12 and 1.14), I believe it could be overkill (too much granularity) to have a field that changes so often when the file otherwise remains unchanged. The data pack export is certainly something to think about, though. My current idea for the data pack rewrite is to allow you to pick the Minecraft version when exporting the pack. This way the extra granularity could be offered there, since it's necessary, and be untied from the song itself -- this way you can export the same song for different Minecraft versions, keeping songs MC version-agnostic as much as possible.
Your first solution is more in line with the implementation I was thinking about. I'm not a fan of storing things that are not notes as notes, like we currently do with the "Tempo Changer" hidden feature -- although it makes some stuff easier to implement, it requires adding a lot of edge cases while parsing something unrelated, and feels more like a hack/bodge on top of the current format than a proper addition. My vision of events would be placeable markers (just like the section and playback markers) that you could position across the song, changing their properties when the marker flies past them. Storing them separately allows us more freedom than using the existing properties of notes to encode event information. For instance, we could have an "event ID" field (0 for tempo change, something else for possible other future events), together with a single value (or array of values) that could be different as required by the event type. We can still take inspiration from your second approach while parsing the song -- depending on the implementation, it should be trivial to convert events to be treated as notes internally, which could make it easier to track/handle them while playing back the song.
Thanks for your input again! It's interesting to think about the kinds of changes that would be the most useful, as well as how they could be implemented. More input from the community is very welcome and always spawns new ideas. Keep in touch for the Official™ proposal which should happen soon :) |
Beta Was this translation helpful? Give feedback.
-
Overview
Since the transition from MCNBS to ONBS, many updates to the .nbs format have been released. While those updates were necessary to support new features being added to the program, new NBS versions have been, so far, released on an "as necessary" basis, without any specific criteria or public notice prior to the official release.
Ideally, releasing a new version of a widely adopted format should be preceded by public discussions with its users. In the case of the NBS format, these would include plugin developers, as well as anyone creating software based on the format. The release schedule should also include an adaptation period, so developers have enough time to update plugins to comply with the new version.
In practice, this was never the case with the format versions released to this date. This impairs the widespread adoption of the format and causes plugins to be automatically outdated as a new version is released, to the detriment of their users and the NBS ecosystem as a whole.
Starting in NBS version 6, the project should strive to be as clear and transparent as possible about the upcoming changes, as well as take community input into consideration as much as possible. This way, future changes to the format can be bundled up in fewer version updates released as sparingly as possible.
This issue is an attempt to gather all the current issues with the NBS format as of version 5, as well as suggestions for new features that could potentially be included in version 6. Keep in mind this is only an overview of the current issues -- where necessary, more detailed write-ups on each of these issues may be written, including their possible workarounds.
If you're a developer creating something based on the .nbs format and would like to suggest a change, feel free to send it in the comments below!
Format issues
0x00
-0x7F
), the equivalent ASCII character is displayed; otherwise, the displayed character is whatever ANSI character Windows maps that codepoint to. This can be fixed by encoding strings in UTF-8. Once this issue is fixed, the documentation should indicate how invalid ASCII characters should be treated in versions 0-5.Documentation issues
Feature suggestions
Beta Was this translation helpful? Give feedback.
All reactions