Skip to content

Commit a14095e

Browse files
committed
Moved logic to fill generalized song data into separate method
1 parent 35fe999 commit a14095e

File tree

10 files changed

+232
-153
lines changed

10 files changed

+232
-153
lines changed
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* This file is part of NoteBlockLib - https://github.com/RaphiMC/NoteBlockLib
3+
* Copyright (C) 2022-2026 RK_01/RaphiMC and contributors
4+
*
5+
* This program is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation; either
8+
* version 3 of the License, or (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
package net.raphimc.noteblocklib.format.futureclient;
19+
20+
import net.raphimc.noteblocklib.format.futureclient.model.FutureClientNote;
21+
import net.raphimc.noteblocklib.format.futureclient.model.FutureClientSong;
22+
import net.raphimc.noteblocklib.format.minecraft.MinecraftInstrument;
23+
import net.raphimc.noteblocklib.model.note.Note;
24+
25+
import java.util.List;
26+
import java.util.Map;
27+
28+
public class FutureClientConverter {
29+
30+
/**
31+
* Fills the general data of the given song from the Future Client specific data.
32+
*
33+
* @param song The song
34+
*/
35+
public static void fillGeneralData(final FutureClientSong song) {
36+
song.getTempoEvents().set(0, FutureClientDefinitions.TEMPO);
37+
for (Map.Entry<Integer, List<FutureClientNote>> entry : song.getFutureClientNotes().entrySet()) {
38+
for (FutureClientNote futureClientNote : entry.getValue()) {
39+
final Note note = new Note();
40+
note.setInstrument(MinecraftInstrument.fromMcId(futureClientNote.getInstrument()));
41+
note.setMcKey(futureClientNote.getKey());
42+
song.getNotes().add(entry.getKey(), note);
43+
}
44+
}
45+
}
46+
47+
}

src/main/java/net/raphimc/noteblocklib/format/futureclient/FutureClientIo.java

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@
2121
import com.google.common.io.LittleEndianDataInputStream;
2222
import net.raphimc.noteblocklib.format.futureclient.model.FutureClientNote;
2323
import net.raphimc.noteblocklib.format.futureclient.model.FutureClientSong;
24-
import net.raphimc.noteblocklib.format.minecraft.MinecraftInstrument;
25-
import net.raphimc.noteblocklib.model.note.Note;
2624

2725
import java.io.BufferedInputStream;
2826
import java.io.IOException;
@@ -64,18 +62,7 @@ public static FutureClientSong readSong(final InputStream is, final String fileN
6462
}
6563
}
6664

67-
{ // Fill generalized song structure with data
68-
song.getTempoEvents().set(0, FutureClientDefinitions.TEMPO);
69-
for (Map.Entry<Integer, List<FutureClientNote>> entry : notes.entrySet()) {
70-
for (FutureClientNote futureClientNote : entry.getValue()) {
71-
final Note note = new Note();
72-
note.setInstrument(MinecraftInstrument.fromMcId(futureClientNote.getInstrument()));
73-
note.setMcKey(futureClientNote.getKey());
74-
song.getNotes().add(entry.getKey(), note);
75-
}
76-
}
77-
}
78-
65+
FutureClientConverter.fillGeneralData(song);
7966
return song;
8067
}
8168

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* This file is part of NoteBlockLib - https://github.com/RaphiMC/NoteBlockLib
3+
* Copyright (C) 2022-2026 RK_01/RaphiMC and contributors
4+
*
5+
* This program is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation; either
8+
* version 3 of the License, or (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
package net.raphimc.noteblocklib.format.mcsp;
19+
20+
import net.raphimc.noteblocklib.format.mcsp.model.McSpNote;
21+
import net.raphimc.noteblocklib.format.mcsp.model.McSpSong;
22+
import net.raphimc.noteblocklib.format.minecraft.MinecraftInstrument;
23+
import net.raphimc.noteblocklib.model.note.Note;
24+
25+
import java.util.Map;
26+
27+
public class McSpConverter {
28+
29+
/**
30+
* Fills the general data of the given song from the MCSP specific data.
31+
*
32+
* @param song The song
33+
*/
34+
public static void fillGeneralData(final McSpSong song) {
35+
song.getTempoEvents().set(0, McSpDefinitions.TEMPO);
36+
for (Map.Entry<Integer, McSpNote[]> entry : song.getMcSpNotes().entrySet()) {
37+
for (McSpNote mcSpNote : entry.getValue()) {
38+
if (mcSpNote == null) {
39+
continue;
40+
}
41+
42+
final Note note = new Note();
43+
note.setInstrument(MinecraftInstrument.fromNbsId(mcSpNote.getInstrument()));
44+
note.setMcKey(mcSpNote.getKey());
45+
song.getNotes().add(entry.getKey(), note);
46+
}
47+
}
48+
}
49+
50+
}

src/main/java/net/raphimc/noteblocklib/format/mcsp/McSpIo.java

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@
1919

2020
import net.raphimc.noteblocklib.format.mcsp.model.McSpNote;
2121
import net.raphimc.noteblocklib.format.mcsp.model.McSpSong;
22-
import net.raphimc.noteblocklib.format.minecraft.MinecraftInstrument;
23-
import net.raphimc.noteblocklib.model.note.Note;
2422

2523
import java.io.BufferedInputStream;
2624
import java.io.InputStream;
@@ -60,22 +58,7 @@ public static McSpSong readSong(final InputStream is, final String fileName) {
6058
notes.put(tick, noteArray);
6159
}
6260

63-
{ // Fill generalized song structure with data
64-
song.getTempoEvents().set(0, McSpDefinitions.TEMPO);
65-
for (Map.Entry<Integer, McSpNote[]> entry : notes.entrySet()) {
66-
for (McSpNote mcSpNote : entry.getValue()) {
67-
if (mcSpNote == null) {
68-
continue;
69-
}
70-
71-
final Note note = new Note();
72-
note.setInstrument(MinecraftInstrument.fromNbsId(mcSpNote.getInstrument()));
73-
note.setMcKey(mcSpNote.getKey());
74-
song.getNotes().add(entry.getKey(), note);
75-
}
76-
}
77-
}
78-
61+
McSpConverter.fillGeneralData(song);
7962
return song;
8063
}
8164

src/main/java/net/raphimc/noteblocklib/format/mcsp2/McSp2Converter.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,29 @@
2828
import net.raphimc.noteblocklib.util.SongResampler;
2929

3030
import java.util.List;
31+
import java.util.Map;
3132

3233
public class McSp2Converter {
3334

35+
/**
36+
* Fills the general data of the given song from the MCSP2 specific data.
37+
*
38+
* @param song The song
39+
*/
40+
public static void fillGeneralData(final McSp2Song song) {
41+
song.getTempoEvents().set(0, song.getTempo());
42+
for (McSp2Layer layer : song.getLayers().values()) {
43+
for (Map.Entry<Integer, McSp2Note> noteEntry : layer.getNotes().entrySet()) {
44+
final McSp2Note mcSp2Note = noteEntry.getValue();
45+
46+
final Note note = new Note();
47+
note.setInstrument(MinecraftInstrument.fromNbsId(mcSp2Note.getInstrument()));
48+
note.setMcKey(mcSp2Note.getKey());
49+
song.getNotes().add(noteEntry.getKey(), note);
50+
}
51+
}
52+
}
53+
3454
/**
3555
* Creates a new MCSP2 song from the general data of the given song (Also copies some format specific fields if applicable).
3656
*

src/main/java/net/raphimc/noteblocklib/format/mcsp2/McSp2Io.java

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@
2020
import net.raphimc.noteblocklib.format.mcsp2.model.McSp2Layer;
2121
import net.raphimc.noteblocklib.format.mcsp2.model.McSp2Note;
2222
import net.raphimc.noteblocklib.format.mcsp2.model.McSp2Song;
23-
import net.raphimc.noteblocklib.format.minecraft.MinecraftInstrument;
24-
import net.raphimc.noteblocklib.model.note.Note;
2523

2624
import java.io.*;
2725
import java.nio.charset.StandardCharsets;
@@ -79,20 +77,7 @@ public static McSp2Song readSong(final InputStream is, final String fileName) {
7977
} catch (NoSuchElementException ignored) {
8078
}
8179

82-
{ // Fill generalized song structure with data
83-
song.getTempoEvents().set(0, song.getTempo());
84-
for (McSp2Layer layer : song.getLayers().values()) {
85-
for (Map.Entry<Integer, McSp2Note> noteEntry : layer.getNotes().entrySet()) {
86-
final McSp2Note mcSp2Note = noteEntry.getValue();
87-
88-
final Note note = new Note();
89-
note.setInstrument(MinecraftInstrument.fromNbsId(mcSp2Note.getInstrument()));
90-
note.setMcKey(mcSp2Note.getKey());
91-
song.getNotes().add(noteEntry.getKey(), note);
92-
}
93-
}
94-
}
95-
80+
McSp2Converter.fillGeneralData(song);
9681
return song;
9782
}
9883

src/main/java/net/raphimc/noteblocklib/format/nbs/NbsConverter.java

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
package net.raphimc.noteblocklib.format.nbs;
1919

2020
import net.raphimc.noteblocklib.format.mcsp2.model.McSp2Song;
21+
import net.raphimc.noteblocklib.format.midi.MidiDefinitions;
2122
import net.raphimc.noteblocklib.format.minecraft.MinecraftInstrument;
2223
import net.raphimc.noteblocklib.format.nbs.model.NbsCustomInstrument;
2324
import net.raphimc.noteblocklib.format.nbs.model.NbsLayer;
@@ -32,11 +33,101 @@
3233
import net.raphimc.noteblocklib.model.song.Song;
3334
import net.raphimc.noteblocklib.util.MathUtil;
3435

36+
import java.util.IdentityHashMap;
3537
import java.util.List;
38+
import java.util.Locale;
39+
import java.util.Map;
3640
import java.util.stream.Collectors;
3741

42+
import static net.raphimc.noteblocklib.format.nbs.NbsDefinitions.*;
43+
3844
public class NbsConverter {
3945

46+
/**
47+
* Fills the general data of the given song from the NBS specific data.
48+
*
49+
* @param song The song
50+
*/
51+
public static void fillGeneralData(final NbsSong song) {
52+
song.getTempoEvents().set(0, song.getTempo() / 100F);
53+
final Map<NbsCustomInstrument, NbsCustomInstrument> customInstrumentMap = new IdentityHashMap<>(song.getCustomInstruments().size()); // Cache map to avoid creating new instances for each note
54+
for (NbsCustomInstrument customInstrument : song.getCustomInstruments()) {
55+
customInstrumentMap.put(customInstrument, customInstrument.copy().setPitch(F_SHARP_4_KEY));
56+
}
57+
58+
final Map<Integer, NbsLayer> layers = song.getLayers();
59+
final boolean hasSoloLayers = layers.values().stream().anyMatch(layer -> layer.getStatus() == NbsLayer.Status.SOLO);
60+
for (Map.Entry<Integer, NbsLayer> entry : layers.entrySet()) {
61+
final NbsLayer layer = entry.getValue();
62+
for (Map.Entry<Integer, NbsNote> noteEntry : layer.getNotes().entrySet()) {
63+
final NbsNote nbsNote = noteEntry.getValue();
64+
65+
final Note note = new Note();
66+
note.setGroupId(entry.getKey());
67+
final float effectiveKey = (float) (MathUtil.clamp(nbsNote.getKey(), LOWEST_KEY, HIGHEST_KEY) * PITCHES_PER_KEY + nbsNote.getPitch()) / PITCHES_PER_KEY;
68+
note.setMidiKey(MathUtil.clamp(LOWEST_MIDI_KEY + effectiveKey, MidiDefinitions.LOWEST_KEY, MidiDefinitions.HIGHEST_KEY));
69+
70+
if (nbsNote.getInstrument() < song.getVanillaInstrumentCount()) {
71+
note.setInstrument(MinecraftInstrument.fromNbsId(nbsNote.getInstrument()));
72+
} else {
73+
final NbsCustomInstrument nbsCustomInstrument = song.getCustomInstruments().get(nbsNote.getInstrument() - song.getVanillaInstrumentCount());
74+
if (song.getVersion() >= 4) {
75+
if (TEMPO_CHANGER_CUSTOM_INSTRUMENT_NAME.equals(nbsCustomInstrument.getName())) {
76+
song.getTempoEvents().set(noteEntry.getKey(), Math.abs(nbsNote.getPitch() / 15F));
77+
continue;
78+
}
79+
if (TOGGLE_RAINBOW_CUSTOM_INSTRUMENT_NAME.equals(nbsCustomInstrument.getName())) {
80+
song.getEvents().add(noteEntry.getKey(), NbsToggleRainbowEvent.INSTANCE);
81+
continue;
82+
}
83+
}
84+
if (song.getVersion() >= 5) {
85+
if (SOUND_STOPPER_CUSTOM_INSTRUMENT_NAME.equals(nbsCustomInstrument.getName())) {
86+
final short startLayer = (short) Math.max(nbsNote.getPitch(), 0);
87+
final short endLayer = (short) Math.max((short) (((nbsNote.getPanning() + 156) % 256) + ((nbsNote.getVelocity() + 156) % 256) * 256), startLayer);
88+
song.getEvents().add(noteEntry.getKey(), new NbsSoundStopperEvent(startLayer, endLayer));
89+
continue;
90+
}
91+
if (SHOW_SAVE_POPUP_CUSTOM_INSTRUMENT_NAME.equals(nbsCustomInstrument.getName())) {
92+
song.getEvents().add(noteEntry.getKey(), NbsShowSavePopupEvent.INSTANCE);
93+
continue;
94+
}
95+
if (nbsCustomInstrument.getNameOr("").toLowerCase(Locale.ROOT).contains(CHANGE_COLOR_CUSTOM_INSTRUMENT_NAME.toLowerCase(Locale.ROOT))) {
96+
continue;
97+
}
98+
if (TOGGLE_BACKGROUND_ACCENT_CUSTOM_INSTRUMENT_NAME.equals(nbsCustomInstrument.getName())) {
99+
song.getEvents().add(noteEntry.getKey(), NbsToggleBackgroundAccentEvent.INSTANCE);
100+
continue;
101+
}
102+
}
103+
104+
final int pitchModifier = nbsCustomInstrument.getPitch() - F_SHARP_4_KEY;
105+
if (pitchModifier != 0) { // Pre-apply pitch modifier to note to make it easier for player implementations
106+
note.setNbsKey(note.getNbsKey() + pitchModifier);
107+
note.setInstrument(customInstrumentMap.get(nbsCustomInstrument)); // Use custom instrument with no pitch modifier, because the pitch modifier is already applied to the note
108+
} else {
109+
note.setInstrument(nbsCustomInstrument);
110+
}
111+
}
112+
113+
note.setVolume(MathUtil.clamp(Math.min(layer.getVolume() / 100F, 1F) * (nbsNote.getVelocity() / 100F), 0F, 1F));
114+
if (layer.getPanning() == CENTER_PANNING) { // Special case
115+
note.setPanning(MathUtil.clamp((nbsNote.getPanning() - CENTER_PANNING) / 100F, -1F, 1F));
116+
} else {
117+
note.setPanning(MathUtil.clamp(((layer.getPanning() - CENTER_PANNING) + (nbsNote.getPanning() - CENTER_PANNING)) / 200F, -1F, 1F));
118+
}
119+
120+
if (layer.getStatus() == NbsLayer.Status.LOCKED) { // Locked layers are muted
121+
note.setVolume(0F);
122+
} else if (hasSoloLayers && layer.getStatus() != NbsLayer.Status.SOLO) { // Non-solo layers are muted if there are solo layers
123+
note.setVolume(0F);
124+
}
125+
126+
song.getNotes().add(noteEntry.getKey(), note);
127+
}
128+
}
129+
}
130+
40131
/**
41132
* Creates a new NBS song from the general data of the given song (Also copies some format specific fields if applicable).
42133
*

0 commit comments

Comments
 (0)