diff --git a/build.gradle b/build.gradle index 37fbb99..70141d5 100644 --- a/build.gradle +++ b/build.gradle @@ -21,13 +21,10 @@ configurations { repositories { mavenCentral() - maven { - url = "https://maven.lenni0451.net/everything" - } } dependencies { - include "net.raphimc:NoteBlockLib:2.0.7-SNAPSHOT" + include "net.raphimc:NoteBlockLib:2.1.0" include "com.formdev:flatlaf:3.4.1" include "net.lenni0451.commons:swing:1.5.1" include "org.lwjgl:lwjgl:3.3.3" diff --git a/src/main/java/net/raphimc/noteblocktool/audio/SoundMap.java b/src/main/java/net/raphimc/noteblocktool/audio/SoundMap.java index 52c68ce..4cac0fb 100644 --- a/src/main/java/net/raphimc/noteblocktool/audio/SoundMap.java +++ b/src/main/java/net/raphimc/noteblocktool/audio/SoundMap.java @@ -18,45 +18,77 @@ package net.raphimc.noteblocktool.audio; import net.raphimc.noteblocklib.util.Instrument; -import net.raphimc.noteblocktool.audio.soundsystem.impl.JavaxSoundSystem; import net.raphimc.noteblocktool.util.SoundSampleUtil; import javax.sound.sampled.AudioFormat; +import java.io.File; +import java.net.URL; +import java.nio.file.Files; import java.util.EnumMap; +import java.util.HashMap; import java.util.Map; public class SoundMap { - public static final Map SOUNDS = new EnumMap<>(Instrument.class); + public static final Map INSTRUMENT_SOUNDS = new EnumMap<>(Instrument.class); + public static final Map SOUND_LOCATIONS = new HashMap<>(); static { - SOUNDS.put(Instrument.HARP, "/noteblock_sounds/harp.ogg"); - SOUNDS.put(Instrument.BASS, "/noteblock_sounds/bass.ogg"); - SOUNDS.put(Instrument.BASS_DRUM, "/noteblock_sounds/bd.ogg"); - SOUNDS.put(Instrument.SNARE, "/noteblock_sounds/snare.ogg"); - SOUNDS.put(Instrument.HAT, "/noteblock_sounds/hat.ogg"); - SOUNDS.put(Instrument.GUITAR, "/noteblock_sounds/guitar.ogg"); - SOUNDS.put(Instrument.FLUTE, "/noteblock_sounds/flute.ogg"); - SOUNDS.put(Instrument.BELL, "/noteblock_sounds/bell.ogg"); - SOUNDS.put(Instrument.CHIME, "/noteblock_sounds/icechime.ogg"); - SOUNDS.put(Instrument.XYLOPHONE, "/noteblock_sounds/xylobone.ogg"); - SOUNDS.put(Instrument.IRON_XYLOPHONE, "/noteblock_sounds/iron_xylophone.ogg"); - SOUNDS.put(Instrument.COW_BELL, "/noteblock_sounds/cow_bell.ogg"); - SOUNDS.put(Instrument.DIDGERIDOO, "/noteblock_sounds/didgeridoo.ogg"); - SOUNDS.put(Instrument.BIT, "/noteblock_sounds/bit.ogg"); - SOUNDS.put(Instrument.BANJO, "/noteblock_sounds/banjo.ogg"); - SOUNDS.put(Instrument.PLING, "/noteblock_sounds/pling.ogg"); + INSTRUMENT_SOUNDS.put(Instrument.HARP, "harp.ogg"); + INSTRUMENT_SOUNDS.put(Instrument.BASS, "bass.ogg"); + INSTRUMENT_SOUNDS.put(Instrument.BASS_DRUM, "bd.ogg"); + INSTRUMENT_SOUNDS.put(Instrument.SNARE, "snare.ogg"); + INSTRUMENT_SOUNDS.put(Instrument.HAT, "hat.ogg"); + INSTRUMENT_SOUNDS.put(Instrument.GUITAR, "guitar.ogg"); + INSTRUMENT_SOUNDS.put(Instrument.FLUTE, "flute.ogg"); + INSTRUMENT_SOUNDS.put(Instrument.BELL, "bell.ogg"); + INSTRUMENT_SOUNDS.put(Instrument.CHIME, "icechime.ogg"); + INSTRUMENT_SOUNDS.put(Instrument.XYLOPHONE, "xylobone.ogg"); + INSTRUMENT_SOUNDS.put(Instrument.IRON_XYLOPHONE, "iron_xylophone.ogg"); + INSTRUMENT_SOUNDS.put(Instrument.COW_BELL, "cow_bell.ogg"); + INSTRUMENT_SOUNDS.put(Instrument.DIDGERIDOO, "didgeridoo.ogg"); + INSTRUMENT_SOUNDS.put(Instrument.BIT, "bit.ogg"); + INSTRUMENT_SOUNDS.put(Instrument.BANJO, "banjo.ogg"); + INSTRUMENT_SOUNDS.put(Instrument.PLING, "pling.ogg"); + + reload(null); + } + + public static void reload(final File customSoundsFolder) { + SOUND_LOCATIONS.clear(); + for (Map.Entry entry : INSTRUMENT_SOUNDS.entrySet()) { + SOUND_LOCATIONS.put(entry.getValue(), SoundMap.class.getResource("/noteblock_sounds/" + entry.getValue())); + } + + if (customSoundsFolder != null && customSoundsFolder.exists() && customSoundsFolder.isDirectory()) { + try { + Files.walk(customSoundsFolder.toPath()).forEach(path -> { + try { + if (Files.isDirectory(path)) return; + + final String fileName = customSoundsFolder.toPath().relativize(path).toString(); + if (fileName.endsWith(".ogg") || fileName.endsWith(".wav")) { + SOUND_LOCATIONS.put(fileName.replace(File.separatorChar, '/'), path.toUri().toURL()); + } + } catch (Throwable e) { + throw new RuntimeException("Error while loading custom sound sample", e); + } + }); + } catch (Throwable e) { + throw new RuntimeException("Could not load custom sound samples", e); + } + } } - public static Map loadInstrumentSamples(final AudioFormat targetFormat) { + public static Map loadInstrumentSamples(final AudioFormat targetFormat) { try { - final Map instrumentSamples = new EnumMap<>(Instrument.class); - for (Map.Entry entry : SOUNDS.entrySet()) { - instrumentSamples.put(entry.getKey(), SoundSampleUtil.readSamples(JavaxSoundSystem.class.getResourceAsStream(entry.getValue()), targetFormat)); + final Map soundSamples = new HashMap<>(); + for (Map.Entry entry : SOUND_LOCATIONS.entrySet()) { + soundSamples.put(entry.getKey(), SoundSampleUtil.readSamples(entry.getValue().openStream(), targetFormat)); } - return instrumentSamples; + return soundSamples; } catch (Throwable e) { - throw new RuntimeException("Could not load instrument samples", e); + throw new RuntimeException("Could not load sound samples", e); } } diff --git a/src/main/java/net/raphimc/noteblocktool/audio/export/AudioExporter.java b/src/main/java/net/raphimc/noteblocktool/audio/export/AudioExporter.java index 7f203fe..e4262f4 100644 --- a/src/main/java/net/raphimc/noteblocktool/audio/export/AudioExporter.java +++ b/src/main/java/net/raphimc/noteblocktool/audio/export/AudioExporter.java @@ -17,11 +17,13 @@ */ package net.raphimc.noteblocktool.audio.export; +import net.raphimc.noteblocklib.format.nbs.model.NbsCustomInstrument; import net.raphimc.noteblocklib.model.Note; import net.raphimc.noteblocklib.model.SongView; +import net.raphimc.noteblocklib.player.FullNoteConsumer; import net.raphimc.noteblocklib.util.Instrument; import net.raphimc.noteblocklib.util.SongUtil; -import net.raphimc.noteblocktool.util.DefaultSongPlayerCallback; +import net.raphimc.noteblocktool.audio.SoundMap; import net.raphimc.noteblocktool.util.SampleOutputStream; import javax.sound.sampled.AudioFileFormat; @@ -34,9 +36,8 @@ import java.util.List; import java.util.function.Consumer; -public abstract class AudioExporter { +public abstract class AudioExporter implements FullNoteConsumer { - private final DefaultSongPlayerCallback noteConsumer = this::processNote; private final SongView songView; protected final AudioFormat format; private final Consumer progressConsumer; @@ -60,7 +61,7 @@ public void render() throws InterruptedException { final List notes = this.songView.getNotesAtTick(tick); for (Note note : notes) { if (Thread.currentThread().isInterrupted()) throw new InterruptedException(); - this.noteConsumer.playNote(note); + this.playNote(note); } this.processedNotes += notes.size(); this.writeSamples(); @@ -78,7 +79,17 @@ public void write(final AudioFileFormat.Type format, final File file) throws IOE audioInputStream.close(); } - protected abstract void processNote(final Instrument instrument, final float volume, final float pitch, final float panning); + @Override + public void playNote(final Instrument instrument, final float pitch, final float volume, final float panning) { + this.processSound(SoundMap.INSTRUMENT_SOUNDS.get(instrument), pitch, volume, panning); + } + + @Override + public void playCustomNote(final NbsCustomInstrument customInstrument, final float pitch, final float volume, final float panning) { + this.processSound(customInstrument.getSoundFileName().replace(File.separatorChar, '/'), pitch, volume, panning); + } + + protected abstract void processSound(final String sound, final float pitch, final float volume, final float panning); protected abstract void writeSamples(); diff --git a/src/main/java/net/raphimc/noteblocktool/audio/export/impl/JavaxAudioExporter.java b/src/main/java/net/raphimc/noteblocktool/audio/export/impl/JavaxAudioExporter.java index c6df421..fc55bf8 100644 --- a/src/main/java/net/raphimc/noteblocktool/audio/export/impl/JavaxAudioExporter.java +++ b/src/main/java/net/raphimc/noteblocktool/audio/export/impl/JavaxAudioExporter.java @@ -18,7 +18,6 @@ package net.raphimc.noteblocktool.audio.export.impl; import net.raphimc.noteblocklib.model.SongView; -import net.raphimc.noteblocklib.util.Instrument; import net.raphimc.noteblocktool.audio.SoundMap; import net.raphimc.noteblocktool.audio.export.AudioExporter; import net.raphimc.noteblocktool.audio.export.AudioMerger; @@ -31,7 +30,7 @@ public class JavaxAudioExporter extends AudioExporter { - private final Map sounds; + private final Map sounds; private final Map mutationCache; private final AudioMerger merger; @@ -43,9 +42,11 @@ public JavaxAudioExporter(final SongView songView, final AudioFormat format, } @Override - protected void processNote(final Instrument instrument, final float volume, final float pitch, final float panning) { - String key = instrument + "\0" + volume + "\0" + pitch + "\0" + panning; - this.merger.addSamples(this.mutationCache.computeIfAbsent(key, k -> SoundSampleUtil.mutate(this.format, this.sounds.get(instrument), volume, pitch, panning))); + protected void processSound(final String sound, final float pitch, final float volume, final float panning) { + if (!this.sounds.containsKey(sound)) return; + + final String key = sound + "\0" + pitch + "\0" + volume + "\0" + panning; + this.merger.addSamples(this.mutationCache.computeIfAbsent(key, k -> SoundSampleUtil.mutate(this.format, this.sounds.get(sound), pitch, volume, panning))); } @Override diff --git a/src/main/java/net/raphimc/noteblocktool/audio/export/impl/OpenALAudioExporter.java b/src/main/java/net/raphimc/noteblocktool/audio/export/impl/OpenALAudioExporter.java index 4a9d99e..cfda9a7 100644 --- a/src/main/java/net/raphimc/noteblocktool/audio/export/impl/OpenALAudioExporter.java +++ b/src/main/java/net/raphimc/noteblocktool/audio/export/impl/OpenALAudioExporter.java @@ -18,7 +18,6 @@ package net.raphimc.noteblocktool.audio.export.impl; import net.raphimc.noteblocklib.model.SongView; -import net.raphimc.noteblocklib.util.Instrument; import net.raphimc.noteblocktool.audio.export.AudioExporter; import net.raphimc.noteblocktool.audio.soundsystem.impl.OpenALSoundSystem; @@ -35,8 +34,8 @@ public OpenALAudioExporter(final OpenALSoundSystem soundSystem, final SongView sounds; + private final Map sounds; private final int samplesPerTick; private final SourceDataLine dataLine; private final Map mutationCache; @@ -56,9 +55,11 @@ public JavaxSoundSystem(final float playbackSpeed) { } @Override - public void playNote(final Instrument instrument, final float volume, final float pitch, final float panning) { - final String key = instrument.ordinal() + "\0" + volume + "\0" + pitch + "\0" + panning; - final int[] samples = this.mutationCache.computeIfAbsent(key, k -> SoundSampleUtil.mutate(FORMAT, this.sounds.get(instrument), volume * this.masterVolume, pitch, panning)); + public void playSound(final String sound, final float pitch, final float volume, final float panning) { + if (!this.sounds.containsKey(sound)) return; + + final String key = sound + "\0" + pitch + "\0" + volume + "\0" + panning; + final int[] samples = this.mutationCache.computeIfAbsent(key, k -> SoundSampleUtil.mutate(FORMAT, this.sounds.get(sound), pitch, volume * this.masterVolume, panning)); if (this.buffer.length < samples.length) this.buffer = Arrays.copyOf(this.buffer, samples.length); for (int i = 0; i < samples.length; i++) this.buffer[i] += samples[i]; } diff --git a/src/main/java/net/raphimc/noteblocktool/audio/soundsystem/impl/OpenALSoundSystem.java b/src/main/java/net/raphimc/noteblocktool/audio/soundsystem/impl/OpenALSoundSystem.java index 618fec5..284a1b8 100644 --- a/src/main/java/net/raphimc/noteblocktool/audio/soundsystem/impl/OpenALSoundSystem.java +++ b/src/main/java/net/raphimc/noteblocktool/audio/soundsystem/impl/OpenALSoundSystem.java @@ -18,7 +18,6 @@ package net.raphimc.noteblocktool.audio.soundsystem.impl; import com.google.common.util.concurrent.ThreadFactoryBuilder; -import net.raphimc.noteblocklib.util.Instrument; import net.raphimc.noteblocktool.audio.SoundMap; import net.raphimc.noteblocktool.audio.soundsystem.SoundSystem; import net.raphimc.noteblocktool.util.IOUtil; @@ -30,8 +29,9 @@ import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; import java.io.InputStream; +import java.net.URL; import java.nio.ByteBuffer; -import java.util.EnumMap; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; @@ -61,7 +61,7 @@ public static OpenALSoundSystem createCapture(final int maxSounds, final AudioFo private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(new ThreadFactoryBuilder().setNameFormat("OpenAL Sound System").setDaemon(true).build()); - private final Map instrumentBuffers = new EnumMap<>(Instrument.class); + private final Map soundBuffers = new HashMap<>(); private final List playingSources = new CopyOnWriteArrayList<>(); private final AudioFormat audioFormat; private long device; @@ -127,8 +127,12 @@ private OpenALSoundSystem(final int maxSounds, final AudioFormat captureAudioFor AL10.alListenerfv(AL10.AL_ORIENTATION, new float[]{0F, 0F, -1F, 0F, 1F, 0F}); this.checkError("Could not set listener orientation"); - for (Map.Entry entry : SoundMap.SOUNDS.entrySet()) { - this.instrumentBuffers.put(entry.getKey(), this.loadAudioFile(OpenALSoundSystem.class.getResourceAsStream(entry.getValue()))); + try { + for (Map.Entry entry : SoundMap.SOUND_LOCATIONS.entrySet()) { + this.soundBuffers.put(entry.getKey(), this.loadAudioFile(entry.getValue().openStream())); + } + } catch (Throwable e) { + throw new RuntimeException("Could not load sound samples", e); } this.scheduler.scheduleAtFixedRate(this::tick, 0, 100, TimeUnit.MILLISECONDS); @@ -145,7 +149,9 @@ private OpenALSoundSystem(final int maxSounds, final AudioFormat captureAudioFor } @Override - public void playNote(final Instrument instrument, final float volume, final float pitch, final float panning) { + public void playSound(final String sound, final float pitch, final float volume, final float panning) { + if (!this.soundBuffers.containsKey(sound)) return; + if (this.playingSources.size() >= this.maxSounds) { AL10.alDeleteSources(this.playingSources.remove(0)); this.checkError("Could not delete audio source"); @@ -154,12 +160,12 @@ public void playNote(final Instrument instrument, final float volume, final floa final int source = AL10.alGenSources(); this.checkError("Could not generate audio source"); if (source > 0) { - AL10.alSourcei(source, AL10.AL_BUFFER, this.instrumentBuffers.get(instrument)); + AL10.alSourcei(source, AL10.AL_BUFFER, this.soundBuffers.get(sound)); this.checkError("Could not set audio source buffer"); - AL10.alSourcef(source, AL10.AL_GAIN, volume); - this.checkError("Could not set audio source volume"); AL10.alSourcef(source, AL10.AL_PITCH, pitch); this.checkError("Could not set audio source pitch"); + AL10.alSourcef(source, AL10.AL_GAIN, volume); + this.checkError("Could not set audio source volume"); AL10.alSource3f(source, AL10.AL_POSITION, panning * 2F, 0F, 0F); this.checkError("Could not set audio source position"); @@ -207,8 +213,8 @@ public void close() { this.shutdownHook = null; } this.scheduler.shutdownNow(); - this.instrumentBuffers.values().forEach(AL10::alDeleteBuffers); - this.instrumentBuffers.clear(); + this.soundBuffers.values().forEach(AL10::alDeleteBuffers); + this.soundBuffers.clear(); this.playingSources.forEach(AL10::alDeleteSources); this.playingSources.clear(); if (this.context != 0L) { diff --git a/src/main/java/net/raphimc/noteblocktool/elements/drag/DragTable.java b/src/main/java/net/raphimc/noteblocktool/elements/drag/DragTable.java index cb4beae..c95f4ef 100644 --- a/src/main/java/net/raphimc/noteblocktool/elements/drag/DragTable.java +++ b/src/main/java/net/raphimc/noteblocktool/elements/drag/DragTable.java @@ -17,7 +17,6 @@ */ package net.raphimc.noteblocktool.elements.drag; -import net.raphimc.noteblocklib.util.Instrument; import net.raphimc.noteblocklib.util.MinecraftDefinitions; import net.raphimc.noteblocklib.util.SongUtil; import net.raphimc.noteblocktool.frames.ListFrame; @@ -92,13 +91,9 @@ private CompatibilityResult isSchematicCompatible(final ListFrame.LoadedSong son return false; }); - SongUtil.iterateAllNotes(song.getSong().getView(), note -> { - if (note.getInstrument() >= Instrument.values().length) { - result.add("The song contains notes with custom instruments"); - return true; - } - return false; - }); + if (!SongUtil.getUsedCustomInstruments(song.getSong().getView()).isEmpty()) { + result.add("The song contains notes with custom instruments"); + } return result; } diff --git a/src/main/java/net/raphimc/noteblocktool/frames/ExportFrame.java b/src/main/java/net/raphimc/noteblocktool/frames/ExportFrame.java index a704ddc..fcc8fa5 100644 --- a/src/main/java/net/raphimc/noteblocktool/frames/ExportFrame.java +++ b/src/main/java/net/raphimc/noteblocktool/frames/ExportFrame.java @@ -405,7 +405,6 @@ private void writeNbsSong(final ListFrame.LoadedSong song, final File file) { final NbsSong exportNbsSong = (NbsSong) exportSong; final NbsHeader exportNbsHeader = exportNbsSong.getHeader(); if (song.getSong() instanceof NbsSong) { - final NbsSong nbsSong = (NbsSong) song.getSong(); final NbsHeader nbsHeader = ((NbsSong) song.getSong()).getHeader(); exportNbsHeader.setVersion((byte) Math.max(nbsHeader.getVersion(), exportNbsHeader.getVersion())); exportNbsHeader.setAuthor(nbsHeader.getAuthor()); @@ -423,7 +422,6 @@ private void writeNbsSong(final ListFrame.LoadedSong song, final File file) { exportNbsHeader.setLoop(nbsHeader.isLoop()); exportNbsHeader.setMaxLoopCount(nbsHeader.getMaxLoopCount()); exportNbsHeader.setLoopStartTick(nbsHeader.getLoopStartTick()); - exportNbsSong.getData().setCustomInstruments(nbsSong.getData().getCustomInstruments()); } else if (song.getSong() instanceof McSpSong) { final McSpHeader mcSpHeader = ((McSpSong) song.getSong()).getHeader(); exportNbsHeader.setAuthor(mcSpHeader.getAuthor()); diff --git a/src/main/java/net/raphimc/noteblocktool/frames/SongPlayerFrame.java b/src/main/java/net/raphimc/noteblocktool/frames/SongPlayerFrame.java index 214096c..0b3b6c5 100644 --- a/src/main/java/net/raphimc/noteblocktool/frames/SongPlayerFrame.java +++ b/src/main/java/net/raphimc/noteblocktool/frames/SongPlayerFrame.java @@ -20,27 +20,31 @@ import net.lenni0451.commons.swing.GBC; import net.lenni0451.commons.swing.components.ScrollPaneSizedPanel; import net.raphimc.noteblocklib.format.nbs.NbsSong; +import net.raphimc.noteblocklib.format.nbs.model.NbsCustomInstrument; import net.raphimc.noteblocklib.format.nbs.model.NbsNote; import net.raphimc.noteblocklib.model.Note; import net.raphimc.noteblocklib.model.SongView; +import net.raphimc.noteblocklib.player.FullNoteConsumer; +import net.raphimc.noteblocklib.player.ISongPlayerCallback; import net.raphimc.noteblocklib.player.SongPlayer; import net.raphimc.noteblocklib.util.Instrument; import net.raphimc.noteblocklib.util.SongResampler; +import net.raphimc.noteblocktool.audio.SoundMap; import net.raphimc.noteblocktool.audio.soundsystem.SoundSystem; import net.raphimc.noteblocktool.audio.soundsystem.impl.JavaxSoundSystem; import net.raphimc.noteblocktool.audio.soundsystem.impl.OpenALSoundSystem; import net.raphimc.noteblocktool.elements.FastScrollPane; import net.raphimc.noteblocktool.elements.NewLineLabel; -import net.raphimc.noteblocktool.util.DefaultSongPlayerCallback; import javax.swing.*; import java.awt.*; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; +import java.io.File; import java.text.DecimalFormat; import java.util.Optional; -public class SongPlayerFrame extends JFrame implements DefaultSongPlayerCallback { +public class SongPlayerFrame extends JFrame implements ISongPlayerCallback, FullNoteConsumer { private static final String UNAVAILABLE_MESSAGE = "An error occurred while initializing the sound system.\nPlease make sure that your system supports the selected sound system."; private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#.##"); @@ -301,8 +305,13 @@ private void tick() { } @Override - public void playNote(Instrument instrument, float volume, float pitch, float panning) { - this.soundSystem.playNote(instrument, volume, pitch, panning); + public void playNote(Instrument instrument, float pitch, float volume, float panning) { + this.soundSystem.playSound(SoundMap.INSTRUMENT_SOUNDS.get(instrument), pitch, volume, panning); + } + + @Override + public void playCustomNote(NbsCustomInstrument customInstrument, float pitch, float volume, float panning) { + this.soundSystem.playSound(customInstrument.getSoundFileName().replace(File.separatorChar, '/'), pitch, volume, panning); } @Override diff --git a/src/main/java/net/raphimc/noteblocktool/frames/edittabs/CustomInstrumentsTab.java b/src/main/java/net/raphimc/noteblocktool/frames/edittabs/CustomInstrumentsTab.java index 3c0e56c..1d794ce 100644 --- a/src/main/java/net/raphimc/noteblocktool/frames/edittabs/CustomInstrumentsTab.java +++ b/src/main/java/net/raphimc/noteblocktool/frames/edittabs/CustomInstrumentsTab.java @@ -19,6 +19,7 @@ import net.raphimc.noteblocklib.format.nbs.model.NbsCustomInstrument; import net.raphimc.noteblocklib.format.nbs.model.NbsData; +import net.raphimc.noteblocklib.format.nbs.model.NbsNote; import net.raphimc.noteblocklib.model.Song; import net.raphimc.noteblocklib.model.SongView; import net.raphimc.noteblocklib.util.Instrument; @@ -28,12 +29,15 @@ import net.raphimc.noteblocktool.frames.ListFrame; import javax.swing.*; -import java.util.*; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; public class CustomInstrumentsTab extends EditTab { private InstrumentsTable table; - private Set usedInstruments; + private Set usedInstruments; public CustomInstrumentsTab(final List songs) { super("Custom Instruments", songs); @@ -46,28 +50,34 @@ protected void initComponents(JPanel center) { this.table = new InstrumentsTable(true); this.add(new FastScrollPane(this.table)); this.usedInstruments = SongUtil.getUsedCustomInstruments(this.songs.get(0).getSong().getView()); - NbsData data = (NbsData) this.songs.get(0).getSong().getData(); - for (Integer instrument : this.usedInstruments) { - NbsCustomInstrument customInstrument = data.getCustomInstruments().get(instrument - Instrument.values().length); + for (NbsCustomInstrument customInstrument : this.usedInstruments) { this.table.addRow(customInstrument.getName() + " (" + customInstrument.getSoundFileName() + ")", null); } } @Override public void apply(Song song, SongView view) { - Map replacements = new HashMap<>(); + Map replacements = new HashMap<>(); int i = 0; - for (Integer instrument : this.usedInstruments) { + for (NbsCustomInstrument customInstrument : this.usedInstruments) { Instrument replacement = (Instrument) this.table.getValueAt(i, 1); - replacements.put(instrument, replacement); + replacements.put(customInstrument, replacement); i++; } SongUtil.applyToAllNotes(view, note -> { - Instrument replacement = replacements.get((int) note.getInstrument()); - if (replacement != null) note.setInstrument(replacement.nbsId()); + if (note instanceof NbsNote) { + final NbsCustomInstrument customInstrument = ((NbsNote) note).getCustomInstrument(); + Instrument replacement = replacements.get(customInstrument); + if (replacement != null) { + note.setInstrument(replacement); + } + } }); - if (song != null && SongUtil.getUsedCustomInstruments(view).isEmpty()) { - ((NbsData) song.getData()).setCustomInstruments(new ArrayList<>()); + + if (song != null) { + for (NbsCustomInstrument customInstrument : replacements.keySet()) { + ((NbsData) song.getData()).getCustomInstruments().remove(customInstrument); + } } } diff --git a/src/main/java/net/raphimc/noteblocktool/frames/edittabs/InstrumentsTab.java b/src/main/java/net/raphimc/noteblocktool/frames/edittabs/InstrumentsTab.java index 63b4e30..fc3b261 100644 --- a/src/main/java/net/raphimc/noteblocktool/frames/edittabs/InstrumentsTab.java +++ b/src/main/java/net/raphimc/noteblocktool/frames/edittabs/InstrumentsTab.java @@ -54,16 +54,16 @@ protected void initComponents(JPanel center) { @Override public void apply(Song song, SongView view) { - Map replacements = new HashMap<>(); + Map replacements = new HashMap<>(); int i = 0; for (Instrument instrument : this.usedInstruments) { Instrument replacement = (Instrument) this.table.getValueAt(i, 1); - replacements.put(instrument.nbsId(), replacement); + replacements.put(instrument, replacement); i++; } SongUtil.applyToAllNotes(view, note -> { Instrument replacement = replacements.get(note.getInstrument()); - if (replacement != null) note.setInstrument(replacement.nbsId()); + if (replacement != null) note.setInstrument(replacement); }); } diff --git a/src/main/java/net/raphimc/noteblocktool/util/DefaultSongPlayerCallback.java b/src/main/java/net/raphimc/noteblocktool/util/DefaultSongPlayerCallback.java deleted file mode 100644 index e999c90..0000000 --- a/src/main/java/net/raphimc/noteblocktool/util/DefaultSongPlayerCallback.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * This file is part of NoteBlockTool - https://github.com/RaphiMC/NoteBlockTool - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package net.raphimc.noteblocktool.util; - -import net.raphimc.noteblocklib.format.nbs.NbsDefinitions; -import net.raphimc.noteblocklib.format.nbs.model.NbsNote; -import net.raphimc.noteblocklib.model.Note; -import net.raphimc.noteblocklib.model.NoteWithPanning; -import net.raphimc.noteblocklib.model.NoteWithVolume; -import net.raphimc.noteblocklib.player.ISongPlayerCallback; -import net.raphimc.noteblocklib.util.Instrument; -import net.raphimc.noteblocklib.util.MinecraftDefinitions; - -@FunctionalInterface -public interface DefaultSongPlayerCallback extends ISongPlayerCallback { - - @Override - default void playNote(final Note note) { - if (note.getInstrument() >= Instrument.values().length) return; - final float volume; - if (note instanceof NoteWithVolume) { - final NoteWithVolume noteWithVolume = (NoteWithVolume) note; - volume = noteWithVolume.getVolume(); - } else { - volume = 100F; - } - if (volume <= 0) return; - final float panning; - if (note instanceof NoteWithPanning) { - final NoteWithPanning noteWithPanning = (NoteWithPanning) note; - panning = noteWithPanning.getPanning(); - } else { - panning = 0F; - } - final float pitch; - if (note instanceof NbsNote) { - final NbsNote nbsNote = (NbsNote) note; - pitch = MinecraftDefinitions.nbsPitchToMcPitch(NbsDefinitions.getPitch(nbsNote)); - } else { - pitch = MinecraftDefinitions.mcKeyToMcPitch(MinecraftDefinitions.nbsKeyToMcKey(note.getKey())); - } - final Instrument instrument = Instrument.fromNbsId(note.getInstrument()); - final float playerVolume = volume / 100F; - final float playerPanning = panning / 100F; - - this.playNote(instrument, playerVolume, pitch, playerPanning); - } - - void playNote(final Instrument instrument, final float volume, final float pitch, final float panning); - -} diff --git a/src/main/java/net/raphimc/noteblocktool/util/SoundSampleUtil.java b/src/main/java/net/raphimc/noteblocktool/util/SoundSampleUtil.java index 22dc65d..eae5ba3 100644 --- a/src/main/java/net/raphimc/noteblocktool/util/SoundSampleUtil.java +++ b/src/main/java/net/raphimc/noteblocktool/util/SoundSampleUtil.java @@ -89,7 +89,7 @@ public static int[] readSamples(final InputStream inputStream, final AudioFormat return samples; } - public static int[] mutate(final AudioFormat format, final int[] samples, final float volume, final float pitch, final float panning) { + public static int[] mutate(final AudioFormat format, final int[] samples, final float pitch, final float volume, final float panning) { final int newLength = (int) ((float) samples.length / format.getChannels() / pitch * format.getChannels()); final int[] newSamples = new int[newLength];