diff --git a/src/main/java/me/chayapak1/chomens_bot/song/Instrument.java b/src/main/java/me/chayapak1/chomens_bot/song/Instrument.java index 1e9b3562..ced256e0 100644 --- a/src/main/java/me/chayapak1/chomens_bot/song/Instrument.java +++ b/src/main/java/me/chayapak1/chomens_bot/song/Instrument.java @@ -2,48 +2,48 @@ package me.chayapak1.chomens_bot.song; // Author: hhhzzzsss public class Instrument { - public static final Instrument HARP = new Instrument(0, "harp", 54); - public static final Instrument BASEDRUM = new Instrument(1, "basedrum", 0); - public static final Instrument SNARE = new Instrument(2, "snare", 0); - public static final Instrument HAT = new Instrument(3, "hat", 0); - public static final Instrument BASS = new Instrument(4, "bass", 30); - public static final Instrument FLUTE = new Instrument(5, "flute", 66); - public static final Instrument BELL = new Instrument(6, "bell", 78); - public static final Instrument GUITAR = new Instrument(7, "guitar", 42); - public static final Instrument CHIME = new Instrument(8, "chime", 78); - public static final Instrument XYLOPHONE = new Instrument(9, "xylophone", 78); - public static final Instrument IRON_XYLOPHONE = new Instrument(10, "iron_xylophone", 54); - public static final Instrument COW_BELL = new Instrument(11, "cow_bell", 66); - public static final Instrument DIDGERIDOO = new Instrument(12, "didgeridoo", 30); - public static final Instrument BIT = new Instrument(13, "bit", 54); - public static final Instrument BANJO = new Instrument(14, "banjo", 54); - public static final Instrument PLING = new Instrument(15, "pling", 54); + public static final Instrument HARP = new Instrument(0, "harp", 54); + public static final Instrument BASEDRUM = new Instrument(1, "basedrum", 0); + public static final Instrument SNARE = new Instrument(2, "snare", 0); + public static final Instrument HAT = new Instrument(3, "hat", 0); + public static final Instrument BASS = new Instrument(4, "bass", 30); + public static final Instrument FLUTE = new Instrument(5, "flute", 66); + public static final Instrument BELL = new Instrument(6, "bell", 78); + public static final Instrument GUITAR = new Instrument(7, "guitar", 42); + public static final Instrument CHIME = new Instrument(8, "chime", 78); + public static final Instrument XYLOPHONE = new Instrument(9, "xylophone", 78); + public static final Instrument IRON_XYLOPHONE = new Instrument(10, "iron_xylophone", 54); + public static final Instrument COW_BELL = new Instrument(11, "cow_bell", 66); + public static final Instrument DIDGERIDOO = new Instrument(12, "didgeridoo", 30); + public static final Instrument BIT = new Instrument(13, "bit", 54); + public static final Instrument BANJO = new Instrument(14, "banjo", 54); + public static final Instrument PLING = new Instrument(15, "pling", 54); - public final int id; - public final String name; - public final int offset; - public final String sound; + public final int id; + public final String name; + public final int offset; + public final String sound; - private Instrument (int id, String name, int offset) { - this.id = id; - this.name = name; - this.offset = offset; - this.sound = "minecraft:block.note_block." + name; - } + private Instrument (int id, String name, int offset) { + this.id = id; + this.name = name; + this.offset = offset; + this.sound = "minecraft:block.note_block." + name; + } - public Instrument (int id, String name, int offset, String sound) { - this.id = id; - this.name = name; - this.offset = offset; - this.sound = sound; - } + public Instrument (int id, String name, int offset, String sound) { + this.id = id; + this.name = name; + this.offset = offset; + this.sound = sound; + } - public static Instrument of (String sound) { - return new Instrument(-1, null, 0, sound); - } + public static Instrument of (String sound) { + return new Instrument(-1, null, 0, sound); + } - private static final Instrument[] values = {HARP, BASEDRUM, SNARE, HAT, BASS, FLUTE, BELL, GUITAR, CHIME, XYLOPHONE, IRON_XYLOPHONE, COW_BELL, DIDGERIDOO, BIT, BANJO, PLING}; - public static Instrument fromId (int id) { - return values[id]; - } + private static final Instrument[] values = {HARP, BASEDRUM, SNARE, HAT, BASS, FLUTE, BELL, GUITAR, CHIME, XYLOPHONE, IRON_XYLOPHONE, COW_BELL, DIDGERIDOO, BIT, BANJO, PLING}; + public static Instrument fromId (int id) { + return values[id]; + } } diff --git a/src/main/java/me/chayapak1/chomens_bot/song/MidiConverter.java b/src/main/java/me/chayapak1/chomens_bot/song/MidiConverter.java index 0bf47a23..ce0a8e01 100644 --- a/src/main/java/me/chayapak1/chomens_bot/song/MidiConverter.java +++ b/src/main/java/me/chayapak1/chomens_bot/song/MidiConverter.java @@ -13,446 +13,446 @@ import static javax.sound.midi.ShortMessage.SYSTEM_RESET; // Author: hhhzzzsss // i modified this and some codes are stolen from https://github.com/RaphiMC/NoteBlockLib so thanks to them public class MidiConverter implements Converter { - public static final int TEXT = 0x01; - public static final int TRACK_NAME = 0x03; - public static final int LYRICS = 0x05; - public static final int VOLUME_CONTROL_MSB = 0x07; - public static final int PAN_CONTROL_MSB = 0x0A; - public static final int SET_INSTRUMENT = 0xC0; - public static final int SET_TEMPO = 0x51; - public static final int RESET_CONTROLS = 0x79; + public static final int TEXT = 0x01; + public static final int TRACK_NAME = 0x03; + public static final int LYRICS = 0x05; + public static final int VOLUME_CONTROL_MSB = 0x07; + public static final int PAN_CONTROL_MSB = 0x0A; + public static final int SET_INSTRUMENT = 0xC0; + public static final int SET_TEMPO = 0x51; + public static final int RESET_CONTROLS = 0x79; - @Override - public Song getSongFromBytes(byte[] bytes, String name, Bot bot) throws InvalidMidiDataException, IOException { - Sequence sequence = MidiSystem.getSequence(new ByteArrayInputStream(bytes)); - return getSong(sequence, name, bot); - } - - public static Song getSong(Sequence sequence, String name, Bot bot) { - final Map lyrics = new HashMap<>(); - - long tpq = sequence.getResolution(); - - String songName = null; - - final StringBuilder tracks = new StringBuilder(); - final StringBuilder text = new StringBuilder(); - - boolean isFirst = true; - - ArrayList tempoEvents = new ArrayList<>(); - for (Track track : sequence.getTracks()) { - final int trackSize = track.size(); - - for (int i = 0; i < trackSize; i++) { - MidiEvent event = track.get(i); - MidiMessage message = event.getMessage(); - if (message instanceof MetaMessage mm) { - if (mm.getType() == SET_TEMPO) { - tempoEvents.add(event); - } else if (mm.getType() == TRACK_NAME) { - final String stringTitle = new String(mm.getData(), StandardCharsets.UTF_8); - - if (stringTitle.isBlank()) continue; - - tracks.append(stringTitle); - tracks.append("\n"); - - if (isFirst) { - songName = stringTitle + " (" + name + ")"; // i have put the ` (filename)` just in case the sequence is getting sus (like Track 2 for example) - - isFirst = false; - } - } else if (mm.getType() == TEXT) { - text.append(new String(mm.getData(), StandardCharsets.UTF_8)); - text.append('\n'); - } else if (mm.getType() == LYRICS) { - final String lyric = new String(mm.getMessage(), StandardCharsets.UTF_8); - - lyrics.put(event.getTick(), lyric); - } - } - } + @Override + public Song getSongFromBytes(byte[] bytes, String name, Bot bot) throws InvalidMidiDataException, IOException { + Sequence sequence = MidiSystem.getSequence(new ByteArrayInputStream(bytes)); + return getSong(sequence, name, bot); } - String stringTracks = tracks.toString(); - String stringText = text.toString(); + public static Song getSong(Sequence sequence, String name, Bot bot) { + final Map lyrics = new HashMap<>(); - if (stringText.endsWith("\n")) stringText = stringText.substring(0, stringText.length() - 1); - if (stringTracks.endsWith("\n")) stringTracks = stringTracks.substring(0, stringTracks.length() - 1); + long tpq = sequence.getResolution(); - final Song song = new Song(name, bot, songName, null, null, stringText, stringTracks, false); - - tempoEvents.sort(Comparator.comparingLong(MidiEvent::getTick)); + String songName = null; - final int[] channelVolumes = new int[16]; - final int[] channelPans = new int[16]; - Arrays.fill(channelVolumes, 127); - Arrays.fill(channelPans, 64); - - for (Track track : sequence.getTracks()) { - long microTime = 0; - int[] ids = new int[16]; - int mpq = 500000; - int tempoEventIdx = 0; - long prevTick = 0; + final StringBuilder tracks = new StringBuilder(); + final StringBuilder text = new StringBuilder(); - final int trackSize = track.size(); + boolean isFirst = true; - for (int i = 0; i < trackSize; i++) { - MidiEvent event = track.get(i); - MidiMessage message = event.getMessage(); - - while (tempoEventIdx < tempoEvents.size() && event.getTick() > tempoEvents.get(tempoEventIdx).getTick()) { - long deltaTick = tempoEvents.get(tempoEventIdx).getTick() - prevTick; - prevTick = tempoEvents.get(tempoEventIdx).getTick(); - microTime += (mpq/tpq) * deltaTick; - - MetaMessage mm = (MetaMessage) tempoEvents.get(tempoEventIdx).getMessage(); - byte[] data = mm.getData(); - int new_mpq = (data[2]&0xFF) | ((data[1]&0xFF)<<8) | ((data[0]&0xFF)<<16); - if (new_mpq != 0) mpq = new_mpq; - tempoEventIdx++; - } - - if (message instanceof ShortMessage sm) { - if (sm.getCommand() == SET_INSTRUMENT) { - ids[sm.getChannel()] = sm.getData1(); - } - else if (sm.getCommand() == ShortMessage.NOTE_ON) { - if (sm.getData2() == 0) continue; - int pitch = sm.getData1(); - int velocity = sm.getData2(); - float effectiveVelocity = (float) velocity * channelVolumes[sm.getChannel()] / 127; - int pan = channelPans[sm.getChannel()]; - long deltaTick = event.getTick() - prevTick; - prevTick = event.getTick(); - microTime += (mpq/tpq) * deltaTick; + ArrayList tempoEvents = new ArrayList<>(); + for (Track track : sequence.getTracks()) { + final int trackSize = track.size(); - Note note; - if (sm.getChannel() == 9) { - note = getMidiPercussionNote(pitch, effectiveVelocity, microTime, pan); + for (int i = 0; i < trackSize; i++) { + MidiEvent event = track.get(i); + MidiMessage message = event.getMessage(); + if (message instanceof MetaMessage mm) { + if (mm.getType() == SET_TEMPO) { + tempoEvents.add(event); + } else if (mm.getType() == TRACK_NAME) { + final String stringTitle = new String(mm.getData(), StandardCharsets.UTF_8); + + if (stringTitle.isBlank()) continue; + + tracks.append(stringTitle); + tracks.append("\n"); + + if (isFirst) { + songName = stringTitle + " (" + name + ")"; // i have put the ` (filename)` just in case the sequence is getting sus (like Track 2 for example) + + isFirst = false; + } + } else if (mm.getType() == TEXT) { + text.append(new String(mm.getData(), StandardCharsets.UTF_8)); + text.append('\n'); + } else if (mm.getType() == LYRICS) { + final String lyric = new String(mm.getMessage(), StandardCharsets.UTF_8); + + lyrics.put(event.getTick(), lyric); + } + } } - else { - note = getMidiInstrumentNote(ids[sm.getChannel()], pitch, effectiveVelocity, microTime, pan); - } - if (note != null) { - song.add(note); - } - - long time = microTime / 1000L; - if (time > song.length) { - song.length = time; - } - } - else if (sm.getCommand() == ShortMessage.NOTE_OFF) { - long deltaTick = event.getTick() - prevTick; - prevTick = event.getTick(); - microTime += (mpq/tpq) * deltaTick; - long time = microTime / 1000L; - if (time > song.length) { - song.length = time; - } - } - else if (sm.getCommand() == ShortMessage.CONTROL_CHANGE) { - if (sm.getData1() == VOLUME_CONTROL_MSB) { - channelVolumes[sm.getChannel()] = sm.getData2(); - } else if (sm.getData1() == PAN_CONTROL_MSB) { - channelPans[sm.getChannel()] = sm.getData2(); - } else if (sm.getData1() == RESET_CONTROLS) { - channelVolumes[sm.getChannel()] = 127; - channelPans[sm.getChannel()] = 64; - } - } - else if (sm.getCommand() == SYSTEM_RESET) { - Arrays.fill(channelVolumes, 127); - Arrays.fill(channelPans, 64); - } } - if (lyrics.get(event.getTick()) != null) { - song.lyrics.put(microTime / 1000L, lyrics.get(event.getTick())); + String stringTracks = tracks.toString(); + String stringText = text.toString(); + + if (stringText.endsWith("\n")) stringText = stringText.substring(0, stringText.length() - 1); + if (stringTracks.endsWith("\n")) stringTracks = stringTracks.substring(0, stringTracks.length() - 1); + + final Song song = new Song(name, bot, songName, null, null, stringText, stringTracks, false); + + tempoEvents.sort(Comparator.comparingLong(MidiEvent::getTick)); + + final int[] channelVolumes = new int[16]; + final int[] channelPans = new int[16]; + Arrays.fill(channelVolumes, 127); + Arrays.fill(channelPans, 64); + + for (Track track : sequence.getTracks()) { + long microTime = 0; + int[] ids = new int[16]; + int mpq = 500000; + int tempoEventIdx = 0; + long prevTick = 0; + + final int trackSize = track.size(); + + for (int i = 0; i < trackSize; i++) { + MidiEvent event = track.get(i); + MidiMessage message = event.getMessage(); + + while (tempoEventIdx < tempoEvents.size() && event.getTick() > tempoEvents.get(tempoEventIdx).getTick()) { + long deltaTick = tempoEvents.get(tempoEventIdx).getTick() - prevTick; + prevTick = tempoEvents.get(tempoEventIdx).getTick(); + microTime += (mpq/tpq) * deltaTick; + + MetaMessage mm = (MetaMessage) tempoEvents.get(tempoEventIdx).getMessage(); + byte[] data = mm.getData(); + int new_mpq = (data[2]&0xFF) | ((data[1]&0xFF)<<8) | ((data[0]&0xFF)<<16); + if (new_mpq != 0) mpq = new_mpq; + tempoEventIdx++; + } + + if (message instanceof ShortMessage sm) { + if (sm.getCommand() == SET_INSTRUMENT) { + ids[sm.getChannel()] = sm.getData1(); + } + else if (sm.getCommand() == ShortMessage.NOTE_ON) { + if (sm.getData2() == 0) continue; + int pitch = sm.getData1(); + int velocity = sm.getData2(); + float effectiveVelocity = (float) velocity * channelVolumes[sm.getChannel()] / 127; + int pan = channelPans[sm.getChannel()]; + long deltaTick = event.getTick() - prevTick; + prevTick = event.getTick(); + microTime += (mpq/tpq) * deltaTick; + + Note note; + if (sm.getChannel() == 9) { + note = getMidiPercussionNote(pitch, effectiveVelocity, microTime, pan); + } + else { + note = getMidiInstrumentNote(ids[sm.getChannel()], pitch, effectiveVelocity, microTime, pan); + } + if (note != null) { + song.add(note); + } + + long time = microTime / 1000L; + if (time > song.length) { + song.length = time; + } + } + else if (sm.getCommand() == ShortMessage.NOTE_OFF) { + long deltaTick = event.getTick() - prevTick; + prevTick = event.getTick(); + microTime += (mpq/tpq) * deltaTick; + long time = microTime / 1000L; + if (time > song.length) { + song.length = time; + } + } + else if (sm.getCommand() == ShortMessage.CONTROL_CHANGE) { + if (sm.getData1() == VOLUME_CONTROL_MSB) { + channelVolumes[sm.getChannel()] = sm.getData2(); + } else if (sm.getData1() == PAN_CONTROL_MSB) { + channelPans[sm.getChannel()] = sm.getData2(); + } else if (sm.getData1() == RESET_CONTROLS) { + channelVolumes[sm.getChannel()] = 127; + channelPans[sm.getChannel()] = 64; + } + } + else if (sm.getCommand() == SYSTEM_RESET) { + Arrays.fill(channelVolumes, 127); + Arrays.fill(channelPans, 64); + } + } + + if (lyrics.get(event.getTick()) != null) { + song.lyrics.put(microTime / 1000L, lyrics.get(event.getTick())); + } + } } - } + + song.sort(); + + return song; } - song.sort(); - - return song; - } + public static Note getMidiInstrumentNote(int midiInstrument, int midiPitch, float velocity, long microTime, int panning) { + Instrument shiftedInstrument = null; + Instrument[] instrumentList = instrumentMap.get(midiInstrument); + if (instrumentList != null) { + for (Instrument candidateInstrument : instrumentList) { + if (midiPitch >= candidateInstrument.offset && midiPitch <= candidateInstrument.offset+24) { + shiftedInstrument = candidateInstrument; + break; + } + } - public static Note getMidiInstrumentNote(int midiInstrument, int midiPitch, float velocity, long microTime, int panning) { - Instrument shiftedInstrument = null; - Instrument[] instrumentList = instrumentMap.get(midiInstrument); - if (instrumentList != null) { - for (Instrument candidateInstrument : instrumentList) { - if (midiPitch >= candidateInstrument.offset && midiPitch <= candidateInstrument.offset+24) { - shiftedInstrument = candidateInstrument; - break; - } - } - - if (shiftedInstrument == null) { + if (shiftedInstrument == null) { // shiftedInstrument = instrumentList[0]; - // we are finding the closest instrument offset here and use that - // closest instrument as the instrument + // we are finding the closest instrument offset here and use that + // closest instrument as the instrument - final Integer[] offsets = Arrays.stream(instrumentList).map(ins -> ins.offset).toArray(Integer[]::new); + final Integer[] offsets = Arrays.stream(instrumentList).map(ins -> ins.offset).toArray(Integer[]::new); - // https://stackoverflow.com/questions/13318733/get-closest-value-to-a-number-in-array - int distance = Math.abs(offsets[0] - midiPitch); - int idx = 0; - for (int c = 1; c < offsets.length; c++) { - int cdistance = Math.abs(offsets[c] - midiPitch); - if (cdistance < distance) { - idx = c; - distance = cdistance; - } + // https://stackoverflow.com/questions/13318733/get-closest-value-to-a-number-in-array + int distance = Math.abs(offsets[0] - midiPitch); + int idx = 0; + for (int c = 1; c < offsets.length; c++) { + int cdistance = Math.abs(offsets[c] - midiPitch); + if (cdistance < distance) { + idx = c; + distance = cdistance; + } + } + + final int closest = offsets[idx]; + + shiftedInstrument = Arrays.stream(instrumentList) + .filter(ins -> ins.offset == closest) + .findFirst() + .orElse(null); + } } - final int closest = offsets[idx]; + if (shiftedInstrument == null) { + return null; + } - shiftedInstrument = Arrays.stream(instrumentList) - .filter(ins -> ins.offset == closest) - .findFirst() - .orElse(null); - } + int shiftedInstrumentPitch = midiPitch - shiftedInstrument.offset; + int pitch = midiPitch - instrumentList[0].offset; + + float volume = velocity / 127.0f; + long time = microTime / 1000L; + + return new Note(instrumentList[0], shiftedInstrument, pitch, shiftedInstrumentPitch, midiPitch, volume, time, (int) ((panning - 64) / (float) 64) * 100, 100); } - if (shiftedInstrument == null) { - return null; + private static Note getMidiPercussionNote (int midiPitch, float velocity, long microTime, int panning) { + if (percussionMap.containsKey(midiPitch)) { + int noteId = percussionMap.get(midiPitch); + int pitch = noteId % 25; + float volume = velocity / 127.0f; + Instrument instrument = Instrument.fromId(noteId / 25); + long time = microTime / 1000L; + + return new Note(instrument, pitch, midiPitch, volume, time, (int) ((panning - 64) / (float) 64) * 100, 100); + } + return null; } - int shiftedInstrumentPitch = midiPitch - shiftedInstrument.offset; - int pitch = midiPitch - instrumentList[0].offset; + public static final HashMap instrumentMap = new HashMap<>(); + static { + // Piano (HARP BASS BELL) + instrumentMap.put(0, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Acoustic Grand Piano + instrumentMap.put(1, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Bright Acoustic Piano + instrumentMap.put(2, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); // Electric Grand Piano + instrumentMap.put(3, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Honky-tonk Piano + instrumentMap.put(4, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); // Electric Piano 1 + instrumentMap.put(5, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); // Electric Piano 2 + instrumentMap.put(6, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Harpsichord + instrumentMap.put(7, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Clavinet - float volume = velocity / 127.0f; - long time = microTime / 1000L; + // Chromatic Percussion (IRON_XYLOPHONE XYLOPHONE BASS) + instrumentMap.put(8, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Celesta + instrumentMap.put(9, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Glockenspiel + instrumentMap.put(10, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Music Box + instrumentMap.put(11, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Vibraphone + instrumentMap.put(12, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Marimba + instrumentMap.put(13, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Xylophone + instrumentMap.put(14, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Tubular Bells + instrumentMap.put(15, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Dulcimer - return new Note(instrumentList[0], shiftedInstrument, pitch, shiftedInstrumentPitch, midiPitch, volume, time, (int) ((panning - 64) / (float) 64) * 100, 100); - } + // Organ (BIT DIDGERIDOO BELL) + instrumentMap.put(16, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Drawbar Organ + instrumentMap.put(17, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Percussive Organ + instrumentMap.put(18, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Rock Organ + instrumentMap.put(19, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Church Organ + instrumentMap.put(20, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Reed Organ + instrumentMap.put(21, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Accordian + instrumentMap.put(22, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Harmonica + instrumentMap.put(23, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Tango Accordian - private static Note getMidiPercussionNote (int midiPitch, float velocity, long microTime, int panning) { - if (percussionMap.containsKey(midiPitch)) { - int noteId = percussionMap.get(midiPitch); - int pitch = noteId % 25; - float volume = velocity / 127.0f; - Instrument instrument = Instrument.fromId(noteId / 25); - long time = microTime / 1000L; + // Guitar (BIT DIDGERIDOO BELL) + instrumentMap.put(24, new Instrument[]{Instrument.GUITAR, Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Acoustic Guitar (nylon) + instrumentMap.put(25, new Instrument[]{Instrument.GUITAR, Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Acoustic Guitar (steel) + instrumentMap.put(26, new Instrument[]{Instrument.GUITAR, Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Electric Guitar (jazz) + instrumentMap.put(27, new Instrument[]{Instrument.GUITAR, Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Electric Guitar (clean) + instrumentMap.put(28, new Instrument[]{Instrument.GUITAR, Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Electric Guitar (muted) + instrumentMap.put(29, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Overdriven Guitar + instrumentMap.put(30, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Distortion Guitar + instrumentMap.put(31, new Instrument[]{Instrument.GUITAR, Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Guitar Harmonics - return new Note(instrument, pitch, midiPitch, volume, time, (int) ((panning - 64) / (float) 64) * 100, 100); - } - return null; - } + // Bass + instrumentMap.put(32, new Instrument[]{Instrument.BASS, Instrument.HARP, Instrument.BELL}); // Acoustic Bass + instrumentMap.put(33, new Instrument[]{Instrument.BASS, Instrument.HARP, Instrument.BELL}); // Electric Bass (finger) + instrumentMap.put(34, new Instrument[]{Instrument.BASS, Instrument.HARP, Instrument.BELL}); // Electric Bass (pick) + instrumentMap.put(35, new Instrument[]{Instrument.BASS, Instrument.HARP, Instrument.BELL}); // Fretless Bass + instrumentMap.put(36, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Slap Bass 1 + instrumentMap.put(37, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Slap Bass 2 + instrumentMap.put(38, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Synth Bass 1 + instrumentMap.put(39, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Synth Bass 2 - public static final HashMap instrumentMap = new HashMap<>(); - static { - // Piano (HARP BASS BELL) - instrumentMap.put(0, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Acoustic Grand Piano - instrumentMap.put(1, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Bright Acoustic Piano - instrumentMap.put(2, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); // Electric Grand Piano - instrumentMap.put(3, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Honky-tonk Piano - instrumentMap.put(4, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); // Electric Piano 1 - instrumentMap.put(5, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); // Electric Piano 2 - instrumentMap.put(6, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Harpsichord - instrumentMap.put(7, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Clavinet + // Strings + instrumentMap.put(40, new Instrument[]{Instrument.FLUTE, Instrument.GUITAR, Instrument.BASS, Instrument.BELL}); // Violin + instrumentMap.put(41, new Instrument[]{Instrument.FLUTE, Instrument.GUITAR, Instrument.BASS, Instrument.BELL}); // Viola + instrumentMap.put(42, new Instrument[]{Instrument.FLUTE, Instrument.GUITAR, Instrument.BASS, Instrument.BELL}); // Cello + instrumentMap.put(43, new Instrument[]{Instrument.FLUTE, Instrument.GUITAR, Instrument.BASS, Instrument.BELL}); // Contrabass + instrumentMap.put(44, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); // Tremolo Strings + instrumentMap.put(45, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Pizzicato Strings + instrumentMap.put(46, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.CHIME}); // Orchestral Harp + instrumentMap.put(47, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Timpani - // Chromatic Percussion (IRON_XYLOPHONE XYLOPHONE BASS) - instrumentMap.put(8, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Celesta - instrumentMap.put(9, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Glockenspiel - instrumentMap.put(10, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Music Box - instrumentMap.put(11, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Vibraphone - instrumentMap.put(12, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Marimba - instrumentMap.put(13, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Xylophone - instrumentMap.put(14, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Tubular Bells - instrumentMap.put(15, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Dulcimer + // Ensenble + instrumentMap.put(48, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // String Ensemble 1 + instrumentMap.put(49, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // String Ensemble 2 + instrumentMap.put(50, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Synth Strings 1 + instrumentMap.put(51, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Synth Strings 2 + instrumentMap.put(52, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Choir Aahs + instrumentMap.put(53, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Voice Oohs + instrumentMap.put(54, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Synth Choir + instrumentMap.put(55, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Orchestra Hit - // Organ (BIT DIDGERIDOO BELL) - instrumentMap.put(16, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Drawbar Organ - instrumentMap.put(17, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Percussive Organ - instrumentMap.put(18, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Rock Organ - instrumentMap.put(19, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Church Organ - instrumentMap.put(20, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Reed Organ - instrumentMap.put(21, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Accordian - instrumentMap.put(22, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Harmonica - instrumentMap.put(23, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Tango Accordian + // Brass + instrumentMap.put(56, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); + instrumentMap.put(57, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); + instrumentMap.put(58, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); + instrumentMap.put(59, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); + instrumentMap.put(60, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); + instrumentMap.put(61, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); + instrumentMap.put(62, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); + instrumentMap.put(63, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); - // Guitar (BIT DIDGERIDOO BELL) - instrumentMap.put(24, new Instrument[]{Instrument.GUITAR, Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Acoustic Guitar (nylon) - instrumentMap.put(25, new Instrument[]{Instrument.GUITAR, Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Acoustic Guitar (steel) - instrumentMap.put(26, new Instrument[]{Instrument.GUITAR, Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Electric Guitar (jazz) - instrumentMap.put(27, new Instrument[]{Instrument.GUITAR, Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Electric Guitar (clean) - instrumentMap.put(28, new Instrument[]{Instrument.GUITAR, Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Electric Guitar (muted) - instrumentMap.put(29, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Overdriven Guitar - instrumentMap.put(30, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Distortion Guitar - instrumentMap.put(31, new Instrument[]{Instrument.GUITAR, Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Guitar Harmonics + // Reed + instrumentMap.put(64, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); + instrumentMap.put(65, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); + instrumentMap.put(66, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); + instrumentMap.put(67, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); + instrumentMap.put(68, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); + instrumentMap.put(69, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); + instrumentMap.put(70, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); + instrumentMap.put(71, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); - // Bass - instrumentMap.put(32, new Instrument[]{Instrument.BASS, Instrument.HARP, Instrument.BELL}); // Acoustic Bass - instrumentMap.put(33, new Instrument[]{Instrument.BASS, Instrument.HARP, Instrument.BELL}); // Electric Bass (finger) - instrumentMap.put(34, new Instrument[]{Instrument.BASS, Instrument.HARP, Instrument.BELL}); // Electric Bass (pick) - instrumentMap.put(35, new Instrument[]{Instrument.BASS, Instrument.HARP, Instrument.BELL}); // Fretless Bass - instrumentMap.put(36, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Slap Bass 1 - instrumentMap.put(37, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Slap Bass 2 - instrumentMap.put(38, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Synth Bass 1 - instrumentMap.put(39, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Synth Bass 2 + // Pipe + instrumentMap.put(72, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); + instrumentMap.put(73, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); + instrumentMap.put(74, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); + instrumentMap.put(75, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); + instrumentMap.put(76, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); + instrumentMap.put(77, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); + instrumentMap.put(78, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); + instrumentMap.put(79, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); - // Strings - instrumentMap.put(40, new Instrument[]{Instrument.FLUTE, Instrument.GUITAR, Instrument.BASS, Instrument.BELL}); // Violin - instrumentMap.put(41, new Instrument[]{Instrument.FLUTE, Instrument.GUITAR, Instrument.BASS, Instrument.BELL}); // Viola - instrumentMap.put(42, new Instrument[]{Instrument.FLUTE, Instrument.GUITAR, Instrument.BASS, Instrument.BELL}); // Cello - instrumentMap.put(43, new Instrument[]{Instrument.FLUTE, Instrument.GUITAR, Instrument.BASS, Instrument.BELL}); // Contrabass - instrumentMap.put(44, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); // Tremolo Strings - instrumentMap.put(45, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Pizzicato Strings - instrumentMap.put(46, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.CHIME}); // Orchestral Harp - instrumentMap.put(47, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Timpani + // Synth Lead + instrumentMap.put(80, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(81, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(82, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(83, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(84, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(85, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(86, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(87, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - // Ensenble - instrumentMap.put(48, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // String Ensemble 1 - instrumentMap.put(49, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // String Ensemble 2 - instrumentMap.put(50, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Synth Strings 1 - instrumentMap.put(51, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Synth Strings 2 - instrumentMap.put(52, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Choir Aahs - instrumentMap.put(53, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Voice Oohs - instrumentMap.put(54, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Synth Choir - instrumentMap.put(55, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Orchestra Hit + // Synth Pad + instrumentMap.put(88, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(89, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(90, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(91, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(92, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(93, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(94, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(95, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - // Brass - instrumentMap.put(56, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); - instrumentMap.put(57, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); - instrumentMap.put(58, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); - instrumentMap.put(59, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); - instrumentMap.put(60, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); - instrumentMap.put(61, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); - instrumentMap.put(62, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); - instrumentMap.put(63, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); - - // Reed - instrumentMap.put(64, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); - instrumentMap.put(65, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); - instrumentMap.put(66, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); - instrumentMap.put(67, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); - instrumentMap.put(68, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); - instrumentMap.put(69, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); - instrumentMap.put(70, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); - instrumentMap.put(71, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); - - // Pipe - instrumentMap.put(72, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); - instrumentMap.put(73, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); - instrumentMap.put(74, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); - instrumentMap.put(75, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); - instrumentMap.put(76, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); - instrumentMap.put(77, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); - instrumentMap.put(78, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); - instrumentMap.put(79, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); - - // Synth Lead - instrumentMap.put(80, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(81, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(82, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(83, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(84, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(85, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(86, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(87, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - - // Synth Pad - instrumentMap.put(88, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(89, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(90, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(91, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(92, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(93, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(94, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(95, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - - // Synth Effects + // Synth Effects // instrumentMap.put(96, new Instrument[]{}); // instrumentMap.put(97, new Instrument[]{}); - instrumentMap.put(98, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); - instrumentMap.put(99, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(100, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(101, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(102, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(103, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(98, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); + instrumentMap.put(99, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(100, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(101, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(102, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(103, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - // Ethnic - instrumentMap.put(104, new Instrument[]{Instrument.BANJO, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(105, new Instrument[]{Instrument.BANJO, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(106, new Instrument[]{Instrument.BANJO, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(107, new Instrument[]{Instrument.BANJO, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(108, new Instrument[]{Instrument.BANJO, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(109, new Instrument[]{Instrument.HARP, Instrument.DIDGERIDOO, Instrument.BELL}); - instrumentMap.put(110, new Instrument[]{Instrument.HARP, Instrument.DIDGERIDOO, Instrument.BELL}); - instrumentMap.put(111, new Instrument[]{Instrument.HARP, Instrument.DIDGERIDOO, Instrument.BELL}); + // Ethnic + instrumentMap.put(104, new Instrument[]{Instrument.BANJO, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(105, new Instrument[]{Instrument.BANJO, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(106, new Instrument[]{Instrument.BANJO, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(107, new Instrument[]{Instrument.BANJO, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(108, new Instrument[]{Instrument.BANJO, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(109, new Instrument[]{Instrument.HARP, Instrument.DIDGERIDOO, Instrument.BELL}); + instrumentMap.put(110, new Instrument[]{Instrument.HARP, Instrument.DIDGERIDOO, Instrument.BELL}); + instrumentMap.put(111, new Instrument[]{Instrument.HARP, Instrument.DIDGERIDOO, Instrument.BELL}); - // Percussive - instrumentMap.put(112, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); - instrumentMap.put(113, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); - instrumentMap.put(114, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); - instrumentMap.put(115, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); - instrumentMap.put(116, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); - instrumentMap.put(117, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); - instrumentMap.put(118, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); - instrumentMap.put(119, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); - } + // Percussive + instrumentMap.put(112, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); + instrumentMap.put(113, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); + instrumentMap.put(114, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); + instrumentMap.put(115, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); + instrumentMap.put(116, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); + instrumentMap.put(117, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); + instrumentMap.put(118, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); + instrumentMap.put(119, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); + } - public static final HashMap percussionMap = new HashMap<>(); - static { - percussionMap.put(35, 10 + 25*Instrument.BASEDRUM.id); - percussionMap.put(36, 6 + 25*Instrument.BASEDRUM.id); - percussionMap.put(37, 6 + 25*Instrument.HAT.id); - percussionMap.put(38, 8 + 25*Instrument.SNARE.id); - percussionMap.put(39, 6 + 25*Instrument.HAT.id); - percussionMap.put(40, 4 + 25*Instrument.SNARE.id); - percussionMap.put(41, 6 + 25*Instrument.BASEDRUM.id); - percussionMap.put(42, 22 + 25*Instrument.SNARE.id); - percussionMap.put(43, 13 + 25*Instrument.BASEDRUM.id); - percussionMap.put(44, 22 + 25*Instrument.SNARE.id); - percussionMap.put(45, 15 + 25*Instrument.BASEDRUM.id); - percussionMap.put(46, 18 + 25*Instrument.SNARE.id); - percussionMap.put(47, 20 + 25*Instrument.BASEDRUM.id); - percussionMap.put(48, 23 + 25*Instrument.BASEDRUM.id); - percussionMap.put(49, 17 + 25*Instrument.SNARE.id); - percussionMap.put(50, 23 + 25*Instrument.BASEDRUM.id); - percussionMap.put(51, 24 + 25*Instrument.SNARE.id); - percussionMap.put(52, 8 + 25*Instrument.SNARE.id); - percussionMap.put(53, 13 + 25*Instrument.SNARE.id); - percussionMap.put(54, 18 + 25*Instrument.HAT.id); - percussionMap.put(55, 18 + 25*Instrument.SNARE.id); - percussionMap.put(56, 1 + 25*Instrument.HAT.id); - percussionMap.put(57, 13 + 25*Instrument.SNARE.id); - percussionMap.put(58, 2 + 25*Instrument.HAT.id); - percussionMap.put(59, 13 + 25*Instrument.SNARE.id); - percussionMap.put(60, 9 + 25*Instrument.HAT.id); - percussionMap.put(61, 2 + 25*Instrument.HAT.id); - percussionMap.put(62, 8 + 25*Instrument.HAT.id); - percussionMap.put(63, 22 + 25*Instrument.BASEDRUM.id); - percussionMap.put(64, 15 + 25*Instrument.BASEDRUM.id); - percussionMap.put(65, 13 + 25*Instrument.SNARE.id); - percussionMap.put(66, 8 + 25*Instrument.SNARE.id); - percussionMap.put(67, 8 + 25*Instrument.HAT.id); - percussionMap.put(68, 3 + 25*Instrument.HAT.id); - percussionMap.put(69, 20 + 25*Instrument.HAT.id); - percussionMap.put(70, 23 + 25*Instrument.HAT.id); - percussionMap.put(71, 24 + 25*Instrument.HAT.id); - percussionMap.put(72, 24 + 25*Instrument.HAT.id); - percussionMap.put(73, 17 + 25*Instrument.HAT.id); - percussionMap.put(74, 11 + 25*Instrument.HAT.id); - percussionMap.put(75, 18 + 25*Instrument.HAT.id); - percussionMap.put(76, 9 + 25*Instrument.HAT.id); - percussionMap.put(77, 5 + 25*Instrument.HAT.id); - percussionMap.put(78, 22 + 25*Instrument.HAT.id); - percussionMap.put(79, 19 + 25*Instrument.SNARE.id); - percussionMap.put(80, 17 + 25*Instrument.HAT.id); - percussionMap.put(81, 22 + 25*Instrument.HAT.id); - percussionMap.put(82, 22 + 25*Instrument.SNARE.id); - percussionMap.put(83, 24 + 25*Instrument.CHIME.id); - percussionMap.put(84, 24 + 25*Instrument.CHIME.id); - percussionMap.put(85, 21 + 25*Instrument.HAT.id); - percussionMap.put(86, 14 + 25*Instrument.BASEDRUM.id); - percussionMap.put(87, 7 + 25*Instrument.BASEDRUM.id); - } + public static final HashMap percussionMap = new HashMap<>(); + static { + percussionMap.put(35, 10 + 25*Instrument.BASEDRUM.id); + percussionMap.put(36, 6 + 25*Instrument.BASEDRUM.id); + percussionMap.put(37, 6 + 25*Instrument.HAT.id); + percussionMap.put(38, 8 + 25*Instrument.SNARE.id); + percussionMap.put(39, 6 + 25*Instrument.HAT.id); + percussionMap.put(40, 4 + 25*Instrument.SNARE.id); + percussionMap.put(41, 6 + 25*Instrument.BASEDRUM.id); + percussionMap.put(42, 22 + 25*Instrument.SNARE.id); + percussionMap.put(43, 13 + 25*Instrument.BASEDRUM.id); + percussionMap.put(44, 22 + 25*Instrument.SNARE.id); + percussionMap.put(45, 15 + 25*Instrument.BASEDRUM.id); + percussionMap.put(46, 18 + 25*Instrument.SNARE.id); + percussionMap.put(47, 20 + 25*Instrument.BASEDRUM.id); + percussionMap.put(48, 23 + 25*Instrument.BASEDRUM.id); + percussionMap.put(49, 17 + 25*Instrument.SNARE.id); + percussionMap.put(50, 23 + 25*Instrument.BASEDRUM.id); + percussionMap.put(51, 24 + 25*Instrument.SNARE.id); + percussionMap.put(52, 8 + 25*Instrument.SNARE.id); + percussionMap.put(53, 13 + 25*Instrument.SNARE.id); + percussionMap.put(54, 18 + 25*Instrument.HAT.id); + percussionMap.put(55, 18 + 25*Instrument.SNARE.id); + percussionMap.put(56, 1 + 25*Instrument.HAT.id); + percussionMap.put(57, 13 + 25*Instrument.SNARE.id); + percussionMap.put(58, 2 + 25*Instrument.HAT.id); + percussionMap.put(59, 13 + 25*Instrument.SNARE.id); + percussionMap.put(60, 9 + 25*Instrument.HAT.id); + percussionMap.put(61, 2 + 25*Instrument.HAT.id); + percussionMap.put(62, 8 + 25*Instrument.HAT.id); + percussionMap.put(63, 22 + 25*Instrument.BASEDRUM.id); + percussionMap.put(64, 15 + 25*Instrument.BASEDRUM.id); + percussionMap.put(65, 13 + 25*Instrument.SNARE.id); + percussionMap.put(66, 8 + 25*Instrument.SNARE.id); + percussionMap.put(67, 8 + 25*Instrument.HAT.id); + percussionMap.put(68, 3 + 25*Instrument.HAT.id); + percussionMap.put(69, 20 + 25*Instrument.HAT.id); + percussionMap.put(70, 23 + 25*Instrument.HAT.id); + percussionMap.put(71, 24 + 25*Instrument.HAT.id); + percussionMap.put(72, 24 + 25*Instrument.HAT.id); + percussionMap.put(73, 17 + 25*Instrument.HAT.id); + percussionMap.put(74, 11 + 25*Instrument.HAT.id); + percussionMap.put(75, 18 + 25*Instrument.HAT.id); + percussionMap.put(76, 9 + 25*Instrument.HAT.id); + percussionMap.put(77, 5 + 25*Instrument.HAT.id); + percussionMap.put(78, 22 + 25*Instrument.HAT.id); + percussionMap.put(79, 19 + 25*Instrument.SNARE.id); + percussionMap.put(80, 17 + 25*Instrument.HAT.id); + percussionMap.put(81, 22 + 25*Instrument.HAT.id); + percussionMap.put(82, 22 + 25*Instrument.SNARE.id); + percussionMap.put(83, 24 + 25*Instrument.CHIME.id); + percussionMap.put(84, 24 + 25*Instrument.CHIME.id); + percussionMap.put(85, 21 + 25*Instrument.HAT.id); + percussionMap.put(86, 14 + 25*Instrument.BASEDRUM.id); + percussionMap.put(87, 7 + 25*Instrument.BASEDRUM.id); + } } diff --git a/src/main/java/me/chayapak1/chomens_bot/song/NBSConverter.java b/src/main/java/me/chayapak1/chomens_bot/song/NBSConverter.java index 624cf5a3..3ad57040 100644 --- a/src/main/java/me/chayapak1/chomens_bot/song/NBSConverter.java +++ b/src/main/java/me/chayapak1/chomens_bot/song/NBSConverter.java @@ -23,286 +23,286 @@ import java.util.Map; // Author: hhhzzzsss public class NBSConverter implements Converter { - public static final Instrument[] INSTRUMENT_INDEX = new Instrument[] { - Instrument.HARP, - Instrument.BASS, - Instrument.BASEDRUM, - Instrument.SNARE, - Instrument.HAT, - Instrument.GUITAR, - Instrument.FLUTE, - Instrument.BELL, - Instrument.CHIME, - Instrument.XYLOPHONE, - Instrument.IRON_XYLOPHONE, - Instrument.COW_BELL, - Instrument.DIDGERIDOO, - Instrument.BIT, - Instrument.BANJO, - Instrument.PLING, - }; + public static final Instrument[] INSTRUMENT_INDEX = new Instrument[] { + Instrument.HARP, + Instrument.BASS, + Instrument.BASEDRUM, + Instrument.SNARE, + Instrument.HAT, + Instrument.GUITAR, + Instrument.FLUTE, + Instrument.BELL, + Instrument.CHIME, + Instrument.XYLOPHONE, + Instrument.IRON_XYLOPHONE, + Instrument.COW_BELL, + Instrument.DIDGERIDOO, + Instrument.BIT, + Instrument.BANJO, + Instrument.PLING, + }; - public static final Map CUSTOM_INSTRUMENT_REPLACEMENTS = new HashMap<>(); + public static final Map CUSTOM_INSTRUMENT_REPLACEMENTS = new HashMap<>(); - static { - CUSTOM_INSTRUMENT_REPLACEMENTS.put("entity\\.firework\\.", "entity.firework_rocket."); - CUSTOM_INSTRUMENT_REPLACEMENTS.put(".*glass.*", "block.glass.break"); - CUSTOM_INSTRUMENT_REPLACEMENTS.put(".*door.*", "block.wooden_door.open"); - CUSTOM_INSTRUMENT_REPLACEMENTS.put(".*anvil.*", "block.anvil.fall"); - CUSTOM_INSTRUMENT_REPLACEMENTS.put(".*piston.*", "block.piston.extend"); - CUSTOM_INSTRUMENT_REPLACEMENTS.put(".*explode|explosion.*", "entity.generic.explode"); - CUSTOM_INSTRUMENT_REPLACEMENTS.put(".*eye.*", "block.end_portal_frame.fill"); - CUSTOM_INSTRUMENT_REPLACEMENTS.put("fizz", "block.sand.break"); // not really sure what this exactly is, but it exists in some NBSes - } - - public static class NBSNote { - public int tick; - public short layer; - public byte instrument; - public byte key; - public byte velocity = 100; - public byte panning = 100; - public short pitch = 0; - } - - public static class NBSLayer { - public String name; - public byte lock = 0; - public byte volume; - public byte stereo = 100; - } - - private static class NBSCustomInstrument { - public String name; - public String file; - public byte pitch = 0; - public boolean key = false; - } - - @Override - public Song getSongFromBytes(byte[] bytes, String fileName, Bot bot) throws IOException { - ByteBuffer buffer = ByteBuffer.wrap(bytes); - buffer.order(ByteOrder.LITTLE_ENDIAN); - - short songLength; - byte format = 0; - byte vanillaInstrumentCount = 0; - songLength = buffer.getShort(); // If it's not 0, then it uses the old format - if (songLength == 0) { - format = buffer.get(); + static { + CUSTOM_INSTRUMENT_REPLACEMENTS.put("entity\\.firework\\.", "entity.firework_rocket."); + CUSTOM_INSTRUMENT_REPLACEMENTS.put(".*glass.*", "block.glass.break"); + CUSTOM_INSTRUMENT_REPLACEMENTS.put(".*door.*", "block.wooden_door.open"); + CUSTOM_INSTRUMENT_REPLACEMENTS.put(".*anvil.*", "block.anvil.fall"); + CUSTOM_INSTRUMENT_REPLACEMENTS.put(".*piston.*", "block.piston.extend"); + CUSTOM_INSTRUMENT_REPLACEMENTS.put(".*explode|explosion.*", "entity.generic.explode"); + CUSTOM_INSTRUMENT_REPLACEMENTS.put(".*eye.*", "block.end_portal_frame.fill"); + CUSTOM_INSTRUMENT_REPLACEMENTS.put("fizz", "block.sand.break"); // not really sure what this exactly is, but it exists in some NBSes } - if (format >= 1) { - vanillaInstrumentCount = buffer.get(); - } - if (format >= 3) { - songLength = buffer.getShort(); + public static class NBSNote { + public int tick; + public short layer; + public byte instrument; + public byte key; + public byte velocity = 100; + public byte panning = 100; + public short pitch = 0; } - short layerCount = buffer.getShort(); - String songName = getString(buffer, bytes.length); - String songAuthor = getString(buffer, bytes.length); - String songOriginalAuthor = getString(buffer, bytes.length); - String songDescription = getString(buffer, bytes.length); - short tempo = buffer.getShort(); - byte autoSaving = buffer.get(); - byte autoSavingDuration = buffer.get(); - byte timeSignature = buffer.get(); - int minutesSpent = buffer.getInt(); - int leftClicks = buffer.getInt(); - int rightClicks = buffer.getInt(); - int blocksAdded = buffer.getInt(); - int blocksRemoved = buffer.getInt(); - String origFileName = getString(buffer, bytes.length); - - byte loop = 0; - byte maxLoopCount = 0; - short loopStartTick = 0; - if (format >= 4) { - loop = buffer.get(); - maxLoopCount = buffer.get(); - loopStartTick = buffer.getShort(); + public static class NBSLayer { + public String name; + public byte lock = 0; + public byte volume; + public byte stereo = 100; } - ArrayList nbsNotes = new ArrayList<>(); - short tick = -1; - while (true) { - int tickJumps = buffer.getShort(); - if (tickJumps == 0) break; - tick += (short) tickJumps; + private static class NBSCustomInstrument { + public String name; + public String file; + public byte pitch = 0; + public boolean key = false; + } - short layer = -1; - while (true) { - int layerJumps = buffer.getShort(); - if (layerJumps == 0) break; - layer += (short) layerJumps; - NBSNote note = new NBSNote(); - note.tick = tick; - note.layer = layer; - note.instrument = buffer.get(); - note.key = buffer.get(); + @Override + public Song getSongFromBytes(byte[] bytes, String fileName, Bot bot) throws IOException { + ByteBuffer buffer = ByteBuffer.wrap(bytes); + buffer.order(ByteOrder.LITTLE_ENDIAN); + + short songLength; + byte format = 0; + byte vanillaInstrumentCount = 0; + songLength = buffer.getShort(); // If it's not 0, then it uses the old format + if (songLength == 0) { + format = buffer.get(); + } + + if (format >= 1) { + vanillaInstrumentCount = buffer.get(); + } + if (format >= 3) { + songLength = buffer.getShort(); + } + + short layerCount = buffer.getShort(); + String songName = getString(buffer, bytes.length); + String songAuthor = getString(buffer, bytes.length); + String songOriginalAuthor = getString(buffer, bytes.length); + String songDescription = getString(buffer, bytes.length); + short tempo = buffer.getShort(); + byte autoSaving = buffer.get(); + byte autoSavingDuration = buffer.get(); + byte timeSignature = buffer.get(); + int minutesSpent = buffer.getInt(); + int leftClicks = buffer.getInt(); + int rightClicks = buffer.getInt(); + int blocksAdded = buffer.getInt(); + int blocksRemoved = buffer.getInt(); + String origFileName = getString(buffer, bytes.length); + + byte loop = 0; + byte maxLoopCount = 0; + short loopStartTick = 0; if (format >= 4) { - note.velocity = buffer.get(); - note.panning = buffer.get(); - note.pitch = buffer.getShort(); + loop = buffer.get(); + maxLoopCount = buffer.get(); + loopStartTick = buffer.getShort(); } - nbsNotes.add(note); - } - } - ArrayList nbsLayers = new ArrayList<>(); - if (buffer.hasRemaining()) { - for (int i=0; i= 4) { - layer.lock = buffer.get(); + ArrayList nbsNotes = new ArrayList<>(); + short tick = -1; + while (true) { + int tickJumps = buffer.getShort(); + if (tickJumps == 0) break; + tick += (short) tickJumps; + + short layer = -1; + while (true) { + int layerJumps = buffer.getShort(); + if (layerJumps == 0) break; + layer += (short) layerJumps; + NBSNote note = new NBSNote(); + note.tick = tick; + note.layer = layer; + note.instrument = buffer.get(); + note.key = buffer.get(); + if (format >= 4) { + note.velocity = buffer.get(); + note.panning = buffer.get(); + note.pitch = buffer.getShort(); + } + nbsNotes.add(note); + } } - layer.volume = buffer.get(); - if (format >= 2) { - layer.stereo = buffer.get(); + + ArrayList nbsLayers = new ArrayList<>(); + if (buffer.hasRemaining()) { + for (int i=0; i= 4) { + layer.lock = buffer.get(); + } + layer.volume = buffer.get(); + if (format >= 2) { + layer.stereo = buffer.get(); + } + nbsLayers.add(layer); + } } - nbsLayers.add(layer); - } - } - ArrayList customInstruments = new ArrayList<>(); - if (buffer.hasRemaining()) { - byte customInstrumentCount = buffer.get(); - for (int i = 0; i < customInstrumentCount; i++) { - NBSCustomInstrument customInstrument = new NBSCustomInstrument(); - customInstrument.name = getString(buffer, bytes.length); - customInstrument.file = getString(buffer, bytes.length); - customInstrument.pitch = buffer.get(); - customInstrument.key = buffer.get() != 0; - customInstruments.add(customInstrument); - } - } + ArrayList customInstruments = new ArrayList<>(); + if (buffer.hasRemaining()) { + byte customInstrumentCount = buffer.get(); + for (int i = 0; i < customInstrumentCount; i++) { + NBSCustomInstrument customInstrument = new NBSCustomInstrument(); + customInstrument.name = getString(buffer, bytes.length); + customInstrument.file = getString(buffer, bytes.length); + customInstrument.pitch = buffer.get(); + customInstrument.key = buffer.get() != 0; + customInstruments.add(customInstrument); + } + } - final StringBuilder layerNames = new StringBuilder(); + final StringBuilder layerNames = new StringBuilder(); - for (NBSLayer layer : nbsLayers) { - layerNames.append(layer.name); - layerNames.append("\n"); - } + for (NBSLayer layer : nbsLayers) { + layerNames.append(layer.name); + layerNames.append("\n"); + } - final String stringLayerNames = layerNames.toString(); + final String stringLayerNames = layerNames.toString(); - Song song = new Song(!songName.isBlank() ? songName : fileName, bot, songName, songAuthor, songOriginalAuthor, songDescription, stringLayerNames.substring(0, stringLayerNames.length() - 1), true); - if (loop > 0) { - song.loopPosition = getMilliTime(loopStartTick, tempo); + Song song = new Song(!songName.isBlank() ? songName : fileName, bot, songName, songAuthor, songOriginalAuthor, songDescription, stringLayerNames.substring(0, stringLayerNames.length() - 1), true); + if (loop > 0) { + song.loopPosition = getMilliTime(loopStartTick, tempo); // song.loopCount = maxLoopCount; - } - for (NBSNote note : nbsNotes) { - Instrument instrument; - double key = note.key; - if (note.instrument < INSTRUMENT_INDEX.length) { - instrument = INSTRUMENT_INDEX[note.instrument]; + } + for (NBSNote note : nbsNotes) { + Instrument instrument; + double key = note.key; + if (note.instrument < INSTRUMENT_INDEX.length) { + instrument = INSTRUMENT_INDEX[note.instrument]; - key = (double) ((note.key * 100) + note.pitch) / 100; - } else { - final int index = note.instrument - INSTRUMENT_INDEX.length; + key = (double) ((note.key * 100) + note.pitch) / 100; + } else { + final int index = note.instrument - INSTRUMENT_INDEX.length; - if (index >= customInstruments.size()) continue; + if (index >= customInstruments.size()) continue; - final NBSCustomInstrument customInstrument = customInstruments.get(index); + final NBSCustomInstrument customInstrument = customInstruments.get(index); - String name = customInstrument.name; - String file = Path.of(customInstrument.file).getFileName().toString(); + String name = customInstrument.name; + String file = Path.of(customInstrument.file).getFileName().toString(); - // should i hardcode the extension like this? - if (file.endsWith(".ogg")) file = file.substring(0, file.length() - ".ogg".length()); + // should i hardcode the extension like this? + if (file.endsWith(".ogg")) file = file.substring(0, file.length() - ".ogg".length()); - boolean replaced = false; + boolean replaced = false; - final String replacedName = StringUtilities.replaceAllWithMap(name.toLowerCase(), CUSTOM_INSTRUMENT_REPLACEMENTS); - final String replacedFile = StringUtilities.replaceAllWithMap(file.toLowerCase(), CUSTOM_INSTRUMENT_REPLACEMENTS); + final String replacedName = StringUtilities.replaceAllWithMap(name.toLowerCase(), CUSTOM_INSTRUMENT_REPLACEMENTS); + final String replacedFile = StringUtilities.replaceAllWithMap(file.toLowerCase(), CUSTOM_INSTRUMENT_REPLACEMENTS); - if (!file.equals(replacedFile)) { - file = replacedFile; - replaced = true; - } else if (!name.equals(replacedName)) { - name = replacedName; - replaced = true; + if (!file.equals(replacedFile)) { + file = replacedFile; + replaced = true; + } else if (!name.equals(replacedName)) { + name = replacedName; + replaced = true; + } + + if (!sounds.contains(name) && !sounds.contains(file) && !replaced) { + final List outputTitles = LevenshteinUtilities.searchTitles(name, subtitles.values()); + + final String bestMatch = outputTitles.isEmpty() ? "" : outputTitles.getFirst(); + + for (Map.Entry entry : subtitles.entrySet()) { + if (!entry.getValue().equals(bestMatch)) continue; + + name = entry.getKey().substring("subtitles.".length()); + + break; + } + } + + if (!sounds.contains(name) && sounds.contains(file)) name = file; + + instrument = Instrument.of(name); + + key += (double) (customInstrument.pitch + note.pitch) / 100; + } + + byte layerVolume = 100; + if (nbsLayers.size() > note.layer) { + layerVolume = nbsLayers.get(note.layer).volume; + } + + double pitch = key - 33; + + try { + song.add(new Note(instrument, pitch, key, (float) note.velocity * (float) layerVolume / 10000f, getMilliTime(note.tick, tempo), Byte.toUnsignedInt(note.panning), Byte.toUnsignedInt(nbsLayers.get(note.layer).stereo))); + } catch (Exception e) { + song.add(new Note(instrument, pitch, key, (float) note.velocity * (float) layerVolume / 10000f, getMilliTime(note.tick, tempo), -1, 100)); + } } - if (!sounds.contains(name) && !sounds.contains(file) && !replaced) { - final List outputTitles = LevenshteinUtilities.searchTitles(name, subtitles.values()); + song.length = song.get(song.size()-1).time + 50; - final String bestMatch = outputTitles.isEmpty() ? "" : outputTitles.getFirst(); + return song; + } - for (Map.Entry entry : subtitles.entrySet()) { - if (!entry.getValue().equals(bestMatch)) continue; + private static String getString (ByteBuffer buffer, int maxSize) throws IOException { + int length = buffer.getInt(); + if (length > maxSize) { + throw new IOException("String is too large"); + } + byte[] arr = new byte[length]; + buffer.get(arr, 0, length); + return new String(arr, StandardCharsets.UTF_8); + } - name = entry.getKey().substring("subtitles.".length()); + private static int getMilliTime(int tick, int tempo) { + return 1000 * tick * 100 / tempo; + } - break; - } + private static final Map subtitles = new HashMap<>(); + + static { + for (Map.Entry entry : ComponentUtilities.LANGUAGE.entrySet()) { + if (!entry.getKey().startsWith("subtitles.")) continue; + + subtitles.put(entry.getKey(), entry.getValue()); + } + } + + private static final List sounds = loadJsonStringArray("sounds.json"); + + private static List loadJsonStringArray (String name) { + List list = new ArrayList<>(); + + InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream(name); + BufferedReader reader = new BufferedReader(new InputStreamReader(is)); + JsonArray json = JsonParser.parseReader(reader).getAsJsonArray(); + + for (JsonElement entry : json) { + list.add(entry.getAsString()); } - if (!sounds.contains(name) && sounds.contains(file)) name = file; - - instrument = Instrument.of(name); - - key += (double) (customInstrument.pitch + note.pitch) / 100; - } - - byte layerVolume = 100; - if (nbsLayers.size() > note.layer) { - layerVolume = nbsLayers.get(note.layer).volume; - } - - double pitch = key - 33; - - try { - song.add(new Note(instrument, pitch, key, (float) note.velocity * (float) layerVolume / 10000f, getMilliTime(note.tick, tempo), Byte.toUnsignedInt(note.panning), Byte.toUnsignedInt(nbsLayers.get(note.layer).stereo))); - } catch (Exception e) { - song.add(new Note(instrument, pitch, key, (float) note.velocity * (float) layerVolume / 10000f, getMilliTime(note.tick, tempo), -1, 100)); - } + return list; } - - song.length = song.get(song.size()-1).time + 50; - - return song; - } - - private static String getString (ByteBuffer buffer, int maxSize) throws IOException { - int length = buffer.getInt(); - if (length > maxSize) { - throw new IOException("String is too large"); - } - byte[] arr = new byte[length]; - buffer.get(arr, 0, length); - return new String(arr, StandardCharsets.UTF_8); - } - - private static int getMilliTime(int tick, int tempo) { - return 1000 * tick * 100 / tempo; - } - - private static final Map subtitles = new HashMap<>(); - - static { - for (Map.Entry entry : ComponentUtilities.LANGUAGE.entrySet()) { - if (!entry.getKey().startsWith("subtitles.")) continue; - - subtitles.put(entry.getKey(), entry.getValue()); - } - } - - private static final List sounds = loadJsonStringArray("sounds.json"); - - private static List loadJsonStringArray (String name) { - List list = new ArrayList<>(); - - InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream(name); - BufferedReader reader = new BufferedReader(new InputStreamReader(is)); - JsonArray json = JsonParser.parseReader(reader).getAsJsonArray(); - - for (JsonElement entry : json) { - list.add(entry.getAsString()); - } - - return list; - } } diff --git a/src/main/java/me/chayapak1/chomens_bot/song/Note.java b/src/main/java/me/chayapak1/chomens_bot/song/Note.java index 07c5c5d2..b9f7cb00 100644 --- a/src/main/java/me/chayapak1/chomens_bot/song/Note.java +++ b/src/main/java/me/chayapak1/chomens_bot/song/Note.java @@ -2,60 +2,60 @@ package me.chayapak1.chomens_bot.song; // Author: hhhzzzsss public class Note implements Comparable { - public final Instrument instrument; - public final Instrument shiftedInstrument; - public final double pitch; - public final double shiftedPitch; - public final double originalPitch; - public final float volume; - public final long time; - public final int panning; - public final int stereo; + public final Instrument instrument; + public final Instrument shiftedInstrument; + public final double pitch; + public final double shiftedPitch; + public final double originalPitch; + public final float volume; + public final long time; + public final int panning; + public final int stereo; - public Note ( - Instrument instrument, - double pitch, - double originalPitch, - float volume, - long time, - int panning, - int stereo - ) { - this.instrument = instrument; - this.shiftedInstrument = this.instrument; - this.pitch = pitch; - this.shiftedPitch = this.pitch; - this.originalPitch = originalPitch; - this.volume = volume; - this.time = time; - this.panning = panning; - this.stereo = stereo; - } + public Note ( + Instrument instrument, + double pitch, + double originalPitch, + float volume, + long time, + int panning, + int stereo + ) { + this.instrument = instrument; + this.shiftedInstrument = this.instrument; + this.pitch = pitch; + this.shiftedPitch = this.pitch; + this.originalPitch = originalPitch; + this.volume = volume; + this.time = time; + this.panning = panning; + this.stereo = stereo; + } - public Note ( - Instrument instrument, - Instrument shiftedInstrument, - double pitch, - double shiftedPitch, - double originalPitch, - float volume, - long time, - int panning, - int stereo - ) { - this.instrument = instrument; - this.shiftedInstrument = shiftedInstrument; - this.pitch = pitch; - this.shiftedPitch = shiftedPitch; - this.originalPitch = originalPitch; - this.volume = volume; - this.time = time; - this.panning = panning; - this.stereo = stereo; - } + public Note ( + Instrument instrument, + Instrument shiftedInstrument, + double pitch, + double shiftedPitch, + double originalPitch, + float volume, + long time, + int panning, + int stereo + ) { + this.instrument = instrument; + this.shiftedInstrument = shiftedInstrument; + this.pitch = pitch; + this.shiftedPitch = shiftedPitch; + this.originalPitch = originalPitch; + this.volume = volume; + this.time = time; + this.panning = panning; + this.stereo = stereo; + } - @Override - public int compareTo(Note other) { - return Long.compare(time, other.time); - } + @Override + public int compareTo(Note other) { + return Long.compare(time, other.time); + } } diff --git a/src/main/java/me/chayapak1/chomens_bot/song/Song.java b/src/main/java/me/chayapak1/chomens_bot/song/Song.java index 5b5d66db..25174146 100644 --- a/src/main/java/me/chayapak1/chomens_bot/song/Song.java +++ b/src/main/java/me/chayapak1/chomens_bot/song/Song.java @@ -8,145 +8,145 @@ import static me.chayapak1.chomens_bot.util.StringUtilities.isNotNullAndNotBlank // Author: hhhzzzsss & _ChipMC_ but i changed most of the stuff public class Song { - public final ArrayList notes = new ArrayList<>(); - public final String originalName; - public String name; - public String requester = "Unknown"; - public int position = 0; // Current note index - public boolean paused = true; - public long startTime = 0; // Start time in millis since unix epoch - public long length = 0; // Milliseconds in the song - public long time = 0; // Time since start of song - public long loopPosition = 0; // Milliseconds into the song to start looping + public final ArrayList notes = new ArrayList<>(); + public final String originalName; + public String name; + public String requester = "Unknown"; + public int position = 0; // Current note index + public boolean paused = true; + public long startTime = 0; // Start time in millis since unix epoch + public long length = 0; // Milliseconds in the song + public long time = 0; // Time since start of song + public long loopPosition = 0; // Milliseconds into the song to start looping - public final Map lyrics = new HashMap<>(); + public final Map lyrics = new HashMap<>(); - public String songName; - public String songAuthor; - public String songOriginalAuthor; - public String songDescription; + public String songName; + public String songAuthor; + public String songOriginalAuthor; + public String songDescription; - public String tracks; + public String tracks; - public final boolean nbs; + public final boolean nbs; // public int loopCount = 0; // Number of times to loop // public int currentLoop = 0; // Number of loops so far - private final Bot bot; + private final Bot bot; - public Song (String originalName, Bot bot, String songName, String songAuthor, String songOriginalAuthor, String songDescription, String tracks, boolean nbs) { - this.originalName = originalName; - this.bot = bot; - this.songName = songName; - this.songAuthor = songAuthor; - this.songOriginalAuthor = songOriginalAuthor; - this.songDescription = songDescription; - this.tracks = tracks; - this.nbs = nbs; + public Song (String originalName, Bot bot, String songName, String songAuthor, String songOriginalAuthor, String songDescription, String tracks, boolean nbs) { + this.originalName = originalName; + this.bot = bot; + this.songName = songName; + this.songAuthor = songAuthor; + this.songOriginalAuthor = songOriginalAuthor; + this.songDescription = songDescription; + this.tracks = tracks; + this.nbs = nbs; - updateName(); - } - - public void updateName() { - String authorPart = null; - - if (isNotNullAndNotBlank(songOriginalAuthor) && isNotNullAndNotBlank(songAuthor)) { - authorPart = String.format("%s/%s", songOriginalAuthor, songAuthor); - } else if (isNotNullAndNotBlank(songOriginalAuthor)) { - authorPart = songOriginalAuthor; - } else if (isNotNullAndNotBlank(songAuthor)) { - authorPart = songAuthor; + updateName(); } - String namePart = isNotNullAndNotBlank(songName) ? songName : originalName; - name = (authorPart != null) ? String.format("%s - %s", authorPart, namePart) : namePart; - } + public void updateName() { + String authorPart = null; - public Note get (int i) { - return notes.get(i); - } - - public void add (Note e) { - notes.add(e); - } - - public void sort () { - Collections.sort(notes); - } - - /** - * Starts playing song (does nothing if already playing) - */ - public void play () { - if (paused) { - if (loopPosition != 0) bot.music.loop = Loop.CURRENT; - paused = false; - startTime = System.currentTimeMillis() - time; - } - } - - /** - * Pauses song (does nothing if already paused) - */ - public void pause () { - if (!paused) { - paused = true; - // Recalculates time so that the song will continue playing after the exact point it was paused - advanceTime(); - } - } - - public void setTime (long t) { - time = t; - startTime = System.currentTimeMillis() - time; - position = 0; - while (position < notes.size() && notes.get(position).time < t) { - position++; - } - } - - public void advanceTime () { - time = (long) ((System.currentTimeMillis() - startTime) * bot.music.speed); - } - - public boolean reachedNextNote () { - if (position < notes.size()) { - return notes.get(position).time <= time * bot.music.speed; - } else { - if (finished() && bot.music.loop != Loop.OFF) { - if (position < notes.size()) { - return notes.get(position).time <= time * bot.music.speed; - } else { - return false; + if (isNotNullAndNotBlank(songOriginalAuthor) && isNotNullAndNotBlank(songAuthor)) { + authorPart = String.format("%s/%s", songOriginalAuthor, songAuthor); + } else if (isNotNullAndNotBlank(songOriginalAuthor)) { + authorPart = songOriginalAuthor; + } else if (isNotNullAndNotBlank(songAuthor)) { + authorPart = songAuthor; } - } else { - return false; - } + + String namePart = isNotNullAndNotBlank(songName) ? songName : originalName; + name = (authorPart != null) ? String.format("%s - %s", authorPart, namePart) : namePart; } - } - public void loop () { - position = 0; - startTime += length - loopPosition; - time -= length - loopPosition; - while (position < notes.size() && notes.get(position).time < loopPosition) { - position++; + public Note get (int i) { + return notes.get(i); } - } - public Note getNextNote () { - if (position >= notes.size()) { - if (bot.music.loop == Loop.OFF) return null; + public void add (Note e) { + notes.add(e); } - return notes.get(position++); - } - public boolean finished () { - return (time * bot.music.speed) > length || position >= size(); - } + public void sort () { + Collections.sort(notes); + } - public int size () { - return notes.size(); - } + /** + * Starts playing song (does nothing if already playing) + */ + public void play () { + if (paused) { + if (loopPosition != 0) bot.music.loop = Loop.CURRENT; + paused = false; + startTime = System.currentTimeMillis() - time; + } + } + + /** + * Pauses song (does nothing if already paused) + */ + public void pause () { + if (!paused) { + paused = true; + // Recalculates time so that the song will continue playing after the exact point it was paused + advanceTime(); + } + } + + public void setTime (long t) { + time = t; + startTime = System.currentTimeMillis() - time; + position = 0; + while (position < notes.size() && notes.get(position).time < t) { + position++; + } + } + + public void advanceTime () { + time = (long) ((System.currentTimeMillis() - startTime) * bot.music.speed); + } + + public boolean reachedNextNote () { + if (position < notes.size()) { + return notes.get(position).time <= time * bot.music.speed; + } else { + if (finished() && bot.music.loop != Loop.OFF) { + if (position < notes.size()) { + return notes.get(position).time <= time * bot.music.speed; + } else { + return false; + } + } else { + return false; + } + } + } + + public void loop () { + position = 0; + startTime += length - loopPosition; + time -= length - loopPosition; + while (position < notes.size() && notes.get(position).time < loopPosition) { + position++; + } + } + + public Note getNextNote () { + if (position >= notes.size()) { + if (bot.music.loop == Loop.OFF) return null; + } + return notes.get(position++); + } + + public boolean finished () { + return (time * bot.music.speed) > length || position >= size(); + } + + public int size () { + return notes.size(); + } } diff --git a/src/main/java/me/chayapak1/chomens_bot/song/SongLoaderException.java b/src/main/java/me/chayapak1/chomens_bot/song/SongLoaderException.java index 6f9890e0..fdfc6062 100644 --- a/src/main/java/me/chayapak1/chomens_bot/song/SongLoaderException.java +++ b/src/main/java/me/chayapak1/chomens_bot/song/SongLoaderException.java @@ -2,12 +2,12 @@ package me.chayapak1.chomens_bot.song; import net.kyori.adventure.text.Component; -// Author: _ChipMC_ or hhhzzzsss? +// Author: hhhzzzsss public class SongLoaderException extends Exception { - public final Component message; + public final Component message; - public SongLoaderException (Component message) { - super(); - this.message = message; - } + public SongLoaderException (Component message) { + super(); + this.message = message; + } } diff --git a/src/main/java/me/chayapak1/chomens_bot/song/SongLoaderThread.java b/src/main/java/me/chayapak1/chomens_bot/song/SongLoaderThread.java index 1bfcdfb1..d5438ae3 100644 --- a/src/main/java/me/chayapak1/chomens_bot/song/SongLoaderThread.java +++ b/src/main/java/me/chayapak1/chomens_bot/song/SongLoaderThread.java @@ -15,152 +15,152 @@ import java.util.ArrayList; import java.util.List; import java.util.stream.Stream; -// Author: _ChipMC_ & hhhzzzsss +// Author: _ChipMC_ & hhhzzzsss but modified public class SongLoaderThread extends Thread { - // should the converters be here? - public static final List converters = new ArrayList<>(); + // should the converters be here? + public static final List converters = new ArrayList<>(); - static { - converters.add(new MidiConverter()); - converters.add(new NBSConverter()); - converters.add(new TextFileConverter()); - converters.add(new SongPlayerConverter()); - } - - public final String fileName; - - private Path songPath; - private URL songUrl; - public SongLoaderException exception; - public Song song; - - private final Bot bot; - - private final String requester; - - private final boolean isUrl; - - private byte[] data; - - private boolean isItem = false; - - private boolean isFolder = false; - - public SongLoaderThread(URL location, Bot bot, String requester) { - this.bot = bot; - this.requester = requester; - isUrl = true; - songUrl = location; - - fileName = location.getFile(); - } - - public SongLoaderThread(Path location, Bot bot, String requester) { - this.bot = bot; - this.requester = requester; - isUrl = false; - songPath = location; - - isFolder = Files.isDirectory(songPath); - - fileName = location.getFileName().toString(); - } - - public SongLoaderThread (byte[] data, Bot bot, String requester) { - this.bot = bot; - this.requester = requester; - this.data = data; - this.isItem = true; - this.isUrl = false; - - fileName = requester + "'s song item"; - } - - @Override - public void run () { - if (isFolder && !isUrl && !isItem) { - try (Stream files = Files.list(songPath)) { - files.forEach((file) -> { - songPath = file; - processFile(); - }); - - showAddedToQueue(); - } catch (IOException e) { - bot.logger.error(e); - } - } else processFile(); - } - - private void processFile () { - if (bot.music.songQueue.size() > 100) return; - - byte[] bytes; - String name; - try { - if (isUrl) { - bytes = DownloadUtilities.DownloadToByteArray(songUrl, 5 * 1024 * 1024); - final Path fileName = Paths.get(songUrl.toURI().getPath()).getFileName(); - - name = fileName == null ? "(root)" : fileName.toString(); - } else if (isItem) { - bytes = data; - name = requester + "'s song item"; - } else { - bytes = Files.readAllBytes(songPath); - name = !isFolder ? fileName : songPath.getFileName().toString(); - } - } catch (Exception e) { - exception = new SongLoaderException(Component.text(e.getMessage())); - - failed(); - - return; + static { + converters.add(new MidiConverter()); + converters.add(new NBSConverter()); + converters.add(new TextFileConverter()); + converters.add(new SongPlayerConverter()); } - for (Converter converter : converters) { - if (song != null && !isFolder) break; + public final String fileName; - try { - song = converter.getSongFromBytes(bytes, name, bot); - } catch (Exception ignored) {} + private Path songPath; + private URL songUrl; + public SongLoaderException exception; + public Song song; + + private final Bot bot; + + private final String requester; + + private final boolean isUrl; + + private byte[] data; + + private boolean isItem = false; + + private boolean isFolder = false; + + public SongLoaderThread(URL location, Bot bot, String requester) { + this.bot = bot; + this.requester = requester; + isUrl = true; + songUrl = location; + + fileName = location.getFile(); } - if (song == null) { - exception = new SongLoaderException(Component.translatable("Invalid format")); + public SongLoaderThread(Path location, Bot bot, String requester) { + this.bot = bot; + this.requester = requester; + isUrl = false; + songPath = location; - failed(); - } else { - song.requester = requester; + isFolder = Files.isDirectory(songPath); - bot.music.songQueue.add(song); - - if (!isFolder) showAddedToQueue(); + fileName = location.getFileName().toString(); } - bot.music.loaderThread = null; - } + public SongLoaderThread (byte[] data, Bot bot, String requester) { + this.bot = bot; + this.requester = requester; + this.data = data; + this.isItem = true; + this.isUrl = false; - private void showAddedToQueue () { - if (isFolder) { - bot.chat.tellraw( - Component.text( - "Added folder to the song queue" - ).color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor)) - ); - } else { - bot.chat.tellraw( - Component.translatable( - "Added %s to the song queue", - Component.empty().append(Component.text(song.name)).color(ColorUtilities.getColorByString(bot.config.colorPalette.secondary)) - ).color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor)) - ); + fileName = requester + "'s song item"; } - } - private void failed() { - bot.logger.error(exception); - bot.chat.tellraw(Component.translatable("Failed to load song: %s", exception.message).color(NamedTextColor.RED)); - bot.music.loaderThread = null; - } + @Override + public void run () { + if (isFolder && !isUrl && !isItem) { + try (Stream files = Files.list(songPath)) { + files.forEach((file) -> { + songPath = file; + processFile(); + }); + + showAddedToQueue(); + } catch (IOException e) { + bot.logger.error(e); + } + } else processFile(); + } + + private void processFile () { + if (bot.music.songQueue.size() > 100) return; + + byte[] bytes; + String name; + try { + if (isUrl) { + bytes = DownloadUtilities.DownloadToByteArray(songUrl, 5 * 1024 * 1024); + final Path fileName = Paths.get(songUrl.toURI().getPath()).getFileName(); + + name = fileName == null ? "(root)" : fileName.toString(); + } else if (isItem) { + bytes = data; + name = requester + "'s song item"; + } else { + bytes = Files.readAllBytes(songPath); + name = !isFolder ? fileName : songPath.getFileName().toString(); + } + } catch (Exception e) { + exception = new SongLoaderException(Component.text(e.getMessage())); + + failed(); + + return; + } + + for (Converter converter : converters) { + if (song != null && !isFolder) break; + + try { + song = converter.getSongFromBytes(bytes, name, bot); + } catch (Exception ignored) {} + } + + if (song == null) { + exception = new SongLoaderException(Component.translatable("Invalid format")); + + failed(); + } else { + song.requester = requester; + + bot.music.songQueue.add(song); + + if (!isFolder) showAddedToQueue(); + } + + bot.music.loaderThread = null; + } + + private void showAddedToQueue () { + if (isFolder) { + bot.chat.tellraw( + Component.text( + "Added folder to the song queue" + ).color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor)) + ); + } else { + bot.chat.tellraw( + Component.translatable( + "Added %s to the song queue", + Component.empty().append(Component.text(song.name)).color(ColorUtilities.getColorByString(bot.config.colorPalette.secondary)) + ).color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor)) + ); + } + } + + private void failed() { + bot.logger.error(exception); + bot.chat.tellraw(Component.translatable("Failed to load song: %s", exception.message).color(NamedTextColor.RED)); + bot.music.loaderThread = null; + } } \ No newline at end of file