Package: pynbs
pynbsA simple python library to read and write.nbs filesfromOpen Note Block Studio.pynbsmakes it possible to easily iterate over Note Block Studio songs.importpynbsfortick,chordinpynbs.read('demo_song.nbs'):print(tick,[note.keyfornoteinchord])You can also usepynbsto generate new songs programmatically.importpynbsnew_file=pynbs.new_file(song_name='Hello world')new_file.notes.extend([pynbs.Note(tick=i,layer=0,instrument=0,key=i+35)foriinrange(10)])new_file.save('new_file.nbs')InstallationThe package can be installed withpip.$pipinstallpynbsThe latest release follows the latest version of the NBS file formatspecification(version 5). However, it also allows you to load and save files in any of
the older versions.Basic usageReading filesYou can use theread()function to read and parse a specific NBS file.demo_song=pynbs.read('demo_song.nbs')Theread()function returns apynbsfile object. These objects have several
attributes that mirror the binary structure of NBS files.HeaderThe first attribute isheader, the file header. It contains information about
the file.header=demo_song.headerAttributeTypeDetailsheader.versionintThe NBS version this file was saved on.header.default_instrumentsintThe amount of instruments from vanilla Minecraft in the song.header.song_lengthintThe length of the song, measured in ticks.header.song_layersintThe ID of the last layer with at least one note block in it.header.song_namestrThe name of the song.header.song_authorstrThe author of the song.header.original_authorstrThe original song author of the song.header.descriptionstrThe description of the song.header.tempofloatThe tempo of the song.header.auto_saveboolWhether auto-saving has been enabled.header.auto_save_durationintThe amount of minutes between each auto-save.header.time_signatureintThe time signature of the song.header.minutes_spentintThe amount of minutes spent on the project.header.left_clicksintThe amount of times the user has left-clicked.header.right_clicksintThe amount of times the user has right-clicked.header.blocks_addedintThe amount of times the user has added a block.header.blocks_removedintThe amount of times the user has removed a block.header.song_originstrThe file name of the original MIDI or schematic.header.loopboolWhether the song should loop back to the start after ending.header.max_loop_countintThe amount of times to loop. 0 = infinite.header.loop_startintThe tick the song will loop back to at the end of playback.For more information about all these fields, check out theofficial specification.NotesThenotesattribute holds a list of all the notes of the song in order.first_note=demo_song.notes[0]AttributeTypeDetailsnote.tickintThe tick at which the note plays.note.layerintThe ID of the layer in which the note is placed.note.instrumentintThe ID of the instrument.note.keyintThe key of the note. (between 0 and 87)note.velocityintThe velocity of the note. (between 0 and 100)note.panningintThe stereo panning of the note. (between -100 and 100)note.pitchintThe detune of the note, in cents. (between -1200 and 1200)LayersThelayersattribute holds a list of all the layers of the song in order.first_layer=demo_song.layers[0]AttributeTypeDetailslayer.idintThe ID of the layer.layer.namestrThe name of the layer.layer.lockboolWhether the layer is locked.layer.volumeintThe volume of the layer.layer.panningintThe stereo panning of the layer.InstrumentsTheinstrumentsattribute holds a list of all the custom instruments of the
song in order.first_custom_instrument=demo_song.instruments[0]AttributeTypeDetailsinstrument.idintThe ID of the instrument.instrument.namestrThe name of the instrument.instrument.filestrThe name of the sound file of the instrument.instrument.pitchintThe pitch of the instrument. (between 0 and 87)instrument.press_keyboolWhether the piano should automatically press keys with the instrument when the marker passes them.Iterating over songsIterating over apynbsfile object yields consecutively all the chords of the song with
the associated tick.fortick,chordindemo_song:...chordis a list of all the notes that play during the ticktick.Creating new filesYou can create new files using thenew_file()function. The function lets
you specify header attributes with keyword arguments.new_file=pynbs.new_file(song_name='Hello world')The function returns a newpynbsfile object that you can now edit
programmatically.Saving filesYou can use thesave()method to encode and write the file to a specified
location.new_file.save('new_file.nbs')By default, the file will be saved in the latest NBS version available.
To save the file in an older version, you can use theversionparameter:# This will save the song in the classic format.new_file.save('new_file.nbs',version=0)(Keep in mind some of the song properties may be lost when saving in older versions.)Upgrading old filesWhilepynbsis up-to-date with the latest version of the Open Note Block Studio
specification, all previous versions — including the original file format — are still
supported by theread()function, making it possible to bulk upgrade songs to the
most recent version:importglobimportpynbsforold_fileinglob.glob('*.nbs'):pynbs.read(old_file).save(old_file)ContributingContributions are welcome. Make sure to first open an issue discussing the problem or the new feature before creating a pull request. The project usespoetry.$poetryinstallYou can run the tests withpoetry run pytest.$poetryrunpytestThe code follows theblackcode style. Import statements are sorted withisort.$poetryrunisortpynbstests
$poetryrunblackpynbstests
$poetryrunblack--checkpynbstestsLicense -MIT