{"id":16374351,"url":"https://github.com/raphimc/noteblocklib","last_synced_at":"2025-03-21T01:32:03.626Z","repository":{"id":144935091,"uuid":"553026393","full_name":"RaphiMC/NoteBlockLib","owner":"RaphiMC","description":"Library for reading, writing, manipulating and playing Minecraft note block songs","archived":false,"fork":false,"pushed_at":"2024-09-29T06:05:56.000Z","size":2022,"stargazers_count":17,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-10-12T03:17:00.790Z","etag":null,"topics":["midi","midi-converter","minecraft","nbs","noteblock","noteblockapi","noteblocksongs","noteblockstudio"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RaphiMC.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"ko_fi":"rk_01"}},"created_at":"2022-10-17T15:42:13.000Z","updated_at":"2024-09-29T06:05:58.000Z","dependencies_parsed_at":null,"dependency_job_id":"d42b9d95-1294-4ded-8818-d68ca4a665fe","html_url":"https://github.com/RaphiMC/NoteBlockLib","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RaphiMC%2FNoteBlockLib","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RaphiMC%2FNoteBlockLib/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RaphiMC%2FNoteBlockLib/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RaphiMC%2FNoteBlockLib/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RaphiMC","download_url":"https://codeload.github.com/RaphiMC/NoteBlockLib/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244097192,"owners_count":20397562,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["midi","midi-converter","minecraft","nbs","noteblock","noteblockapi","noteblocksongs","noteblockstudio"],"created_at":"2024-10-11T03:16:58.993Z","updated_at":"2025-03-21T01:32:03.621Z","avatar_url":"https://github.com/RaphiMC.png","language":"Java","readme":"# NoteBlockLib\nLibrary for reading, writing, manipulating and playing Minecraft note block songs.\n\nTo use NoteBlockLib in your application, check out the [Usage](#usage) section.  \nFor a reference implementation of NoteBlockLib, check out [NoteBlockTool](https://github.com/RaphiMC/NoteBlockTool).\n\n## Features\n- Supports reading .nbs, .mid, .txt, .mcsp, .mcsp2 and .notebot files\n- Supports writing .nbs, .txt and .mcsp2 files\n- Can convert all formats to .nbs\n- Offers an easy way to play note block songs in your application\n- Good MIDI importer\n  - Supports most MIDI files\n  - Supports velocity and panning\n  - Can handle Black MIDI files\n- Supports all NBS versions\n  - Version 0 - 5\n  - Supports Tempo Changers\n- Many tools for manipulating songs\n  - Optimize songs for use in Minecraft (Transposing, Resampling)\n  - Resampling songs with a different TPS\n  - Instrument replacement\n  - Note deduplication (Useful for Black MIDI files)\n  - Removal of quiet notes (Useful for Black MIDI files)\n- Very fast and efficient\n\n## Releases\n### Gradle/Maven\nTo use NoteBlockLib with Gradle/Maven you can get it from [Maven Central](https://mvnrepository.com/artifact/net.raphimc/NoteBlockLib), [Lenni0451's Maven](https://maven.lenni0451.net/#/releases/net/raphimc/NoteBlockLib) or [Jitpack](https://jitpack.io/#RaphiMC/NoteBlockLib).\nYou can also find instructions how to implement it into your build script there.\n\n### Jar File\nIf you just want the latest jar file you can download it from [GitHub Actions](https://github.com/RaphiMC/NoteBlockLib/actions/workflows/build.yml) or [Lenni0451's Jenkins](https://build.lenni0451.net/job/NoteBlockLib/).\n\n## Usage\n### Concepts and terminology\nThe main class of NoteBlockLib is the ``NoteBlockLib`` class. It contains all the methods for reading, writing and creating songs.  \nSome utils for manipulating and getting metrics about songs are located in the ``util`` package.\n\nThe ``Song`` class is the main data structure for parsed songs. It contains generalized and format specific data.  \nThe generalized data only includes the most important data of songs like the format, the title, the description, the author, the notes and the tempo.  \nTo access format specific data you have to cast the song instance to a specific format (``NbsSong`` for example).  \nMost of the time you will only need the generalized data and all the methods for manipulating, playing and converting songs will work with the generalized data.\n\nAll data structures in NoteBlockLib are mutable and can be modified at any time. All data structures also have a ``copy`` method to create a deep copy of the data structure.\n\n### Reading a song\nTo read a song you can use the ``NoteBlockLib.readSong(\u003cinput\u003e, [format])`` method.\nThe input can be a File, InputStream or a byte array.\nThe format is optional and can be used to specify the format of the input. If the format is not specified, NoteBlockLib will try to guess the format based on the file extension.\n\n### Writing a song\nTo write a song you can use the ``NoteBlockLib.writeSong(\u003csong\u003e, \u003coutput\u003e)`` method.\n\n### Creating a song\nThe easiest way to create a song is to create a ``new GenericSong()``, fill in the data and then use the ``NoteBlockLib.convertSong(\u003csong\u003e, \u003cformat\u003e)`` method to create a format specific song from it.  \nAlternatively you can create a format specific Song directly by using for example the ``new NbsSong()`` constructor. This requires you to fill in all the format specific data yourself.\n\n### Playing a song\nTo play a song you can use the ``SongPlayer`` class. The SongPlayer provides basic controls like play, pause, stop and seek.  \nTo create a SongPlayer implementation, you have to create a class which extends the ``SongPlayer`` class.\nThe SongPlayer class requires you to implement the ``playNotes`` method, but also offers several optional methods like ``onFinished``.\n\n### Manipulating a song\nThere are multiple utils for manipulating a song.\n\n#### SongResampler\nThe SongResampler can be used to resample a song to a different TPS without changing the musical speed or length of the song.  \nThis is very useful if you want to export the song as a schematic and play it in Minecraft as that is limited to 10 TPS.\n\n#### MinecraftDefinitions\nThe MinecraftDefinitions class contains definitions and formulas for Minecraft related manipulations.  \nThis for example includes multiple methods for getting notes within the Minecraft octave range, such as transposing them.\n\n#### SongUtil\nThis class has some general utils for getting various metrics about a song.\n\n## Examples\n**Reading a song, transposing its notes and writing it back**\n```java\nSong song = NoteBlockLib.readSong(new File(\"input.nbs\"));\n\n// Clamp the note key\n// song.getNotes().forEach(MinecraftDefinitions::clampNoteKey);\n\n// Transpose the note key\n// song.getNotes().forEach(MinecraftDefinitions::transposeNoteKey);\n\n// Shift the instrument of out of range notes to a higher/lower one. Sounds better than all above.\nsong.getNotes().forEach(MinecraftDefinitions::instrumentShiftNote);\n// Clamp the remaining out of range notes\nsong.getNotes().forEach(MinecraftDefinitions::clampNoteKey);\n\n// The operations above work with the generalized song model. If you want to write it back to a specific format, you need to convert it first.\nSong convertedSong = NoteBlockLib.convertSong(song, SongFormat.NBS);\n\nNoteBlockLib.writeSong(convertedSong, new File(\"output.nbs\"));\n```\n**Reading a MIDI, and writing it as NBS**\n```java\nSong midiSong = NoteBlockLib.readSong(new File(\"input.mid\"));\nSong nbsSong = NoteBlockLib.convertSong(midiSong, SongFormat.NBS);\nNoteBlockLib.writeSong(nbsSong, new File(\"output.nbs\"));\n```\n**Reading a song, changing its tempo to 10 TPS and writing it back**\n```java\nSong song = NoteBlockLib.readSong(new File(\"input.nbs\"));\nSongResampler.changeTickSpeed(song, 10F);\n// The operations above work with the generalized song model. If you want to write it back to a specific format, you need to convert it first.\nSong newSong = NoteBlockLib.convertSong(song, SongFormat.NBS);\nNoteBlockLib.writeSong(newSong, new File(\"output.nbs\"));\n```\n**Creating a new song and saving it as NBS**\n```java\nSong mySong = new GenericSong();\nmySong.setTitle(\"My song\");\nmySong.getTempoEvents().set(0, 10F); // set the tempo to 10 ticks per second\nmySong.getNotes().add(0, new Note().setInstrument(MinecraftInstrument.HARP).setNbsKey((byte) 46));\nmySong.getNotes().add(5, new Note().setInstrument(MinecraftInstrument.BASS).setNbsKey((byte) 60));\nmySong.getNotes().add(8, new Note().setInstrument(MinecraftInstrument.BIT).setNbsKey((byte) 84));\nSong nbsSong = NoteBlockLib.convertSong(mySong, SongFormat.NBS);\nNoteBlockLib.writeSong(nbsSong, new File(\"output.nbs\"));\n```\n**Playing a song**\n\nCreate the custom SongPlayer implementation:\n```java\npublic class MySongPlayer extends SongPlayer {\n\n    public MySongPlayer(Song song) {\n        super(song);\n    }\n\n    @Override\n    protected void playNotes(List\u003cNote\u003e notes) {\n        for (Note note : notes) {\n            // This method gets called in real time as the song is played.\n            // Make sure to check the javadoc of the various methods from the Note class to see how you should use the returned values.\n            System.out.println(note.getInstrument() + \" \" + note.getPitch() + \" \" + note.getVolume() + \" \" + note.getPanning());\n        }\n    }\n\n    // There are other methods like onFinished which can be overridden.\n}\n```\n\nStart playing the song;\n```java\nSong song = NoteBlockLib.readSong(new File(\"input.nbs\"));\n\n// Optionally apply a modification to all notes here (For example to transpose the note keys)\n\n// Create a song player\nSongPlayer player = new MySongPlayer(song);\n\n// Start playing\nplayer.start();\n\n// Pause\nplayer.setPaused(true);\n\n// Resume\nplayer.setPaused(false);\n\n// Seek to a specific tick\nplayer.setTick(50);\n\n// Seek to a specific time\nplayer.setMillisecondPosition(1000);\n\n// Get the current millisecond position\nplayer.getMillisecondPosition();\n\n// Stop\nplayer.stop();\n```\n\n## Contact\nIf you encounter any issues, please report them on the\n[issue tracker](https://github.com/RaphiMC/NoteBlockLib/issues).  \nIf you just want to talk or need help implementing NoteBlockLib feel free to join my\n[Discord](https://discord.gg/dCzT9XHEWu).\n","funding_links":["https://ko-fi.com/rk_01"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fraphimc%2Fnoteblocklib","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fraphimc%2Fnoteblocklib","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fraphimc%2Fnoteblocklib/lists"}