diff --git a/src/main/java/net/raphimc/noteblocktool/audio/SoundMap.java b/src/main/java/net/raphimc/noteblocktool/audio/SoundMap.java index 7eeb1cd..ae5944a 100644 --- a/src/main/java/net/raphimc/noteblocktool/audio/SoundMap.java +++ b/src/main/java/net/raphimc/noteblocktool/audio/SoundMap.java @@ -19,12 +19,12 @@ import net.raphimc.noteblocklib.util.Instrument; -import java.util.HashMap; +import java.util.EnumMap; import java.util.Map; public class SoundMap { - public static final Map SOUNDS = new HashMap<>(); + public static final Map SOUNDS = new EnumMap<>(Instrument.class); static { SOUNDS.put(Instrument.HARP, "/noteblock_sounds/harp.wav"); 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 82468ff..2558ffa 100644 --- a/src/main/java/net/raphimc/noteblocktool/audio/export/AudioExporter.java +++ b/src/main/java/net/raphimc/noteblocktool/audio/export/AudioExporter.java @@ -20,6 +20,7 @@ import net.raphimc.noteblocklib.model.Note; import net.raphimc.noteblocklib.model.SongView; import net.raphimc.noteblocklib.util.Instrument; +import net.raphimc.noteblocklib.util.SongUtil; import net.raphimc.noteblocktool.util.DefaultSongPlayerCallback; import javax.sound.sampled.AudioFileFormat; @@ -34,7 +35,7 @@ public abstract class AudioExporter { - private final DefaultSongPlayerCallback callback = this::processNote; + private final DefaultSongPlayerCallback noteConsumer = this::processNote; private final SongView songView; protected final AudioFormat format; private final Consumer progressConsumer; @@ -49,16 +50,16 @@ public AudioExporter(final SongView songView, final AudioFormat format, final this.progressConsumer = progressConsumer; this.sampleOutputStream = new SampleOutputStream(format); - this.noteCount = songView.getNotes().values().stream().mapToLong(List::size).sum(); + this.noteCount = SongUtil.getNoteCount(songView); this.samplesPerTick = (int) (format.getSampleRate() / songView.getSpeed()); } public void render() throws InterruptedException { for (int tick = 0; tick <= this.songView.getLength(); tick++) { - List notes = this.songView.getNotesAtTick(tick); + final List notes = this.songView.getNotesAtTick(tick); for (Note note : notes) { if (Thread.currentThread().isInterrupted()) throw new InterruptedException(); - this.callback.playNote(note); + this.noteConsumer.playNote(note); } this.processedNotes += notes.size(); this.writeSamples(); @@ -69,10 +70,10 @@ public void render() throws InterruptedException { this.finish(); } - public void write(final File file) throws IOException { - ByteArrayInputStream bais = new ByteArrayInputStream(this.sampleOutputStream.getBytes()); - AudioInputStream audioInputStream = new AudioInputStream(bais, this.format, bais.available()); - AudioSystem.write(audioInputStream, AudioFileFormat.Type.WAVE, file); + public void write(final AudioFileFormat.Type format, final File file) throws IOException { + final ByteArrayInputStream bais = new ByteArrayInputStream(this.sampleOutputStream.getBytes()); + final AudioInputStream audioInputStream = new AudioInputStream(bais, this.format, bais.available()); + AudioSystem.write(audioInputStream, format, file); audioInputStream.close(); } diff --git a/src/main/java/net/raphimc/noteblocktool/audio/export/AudioMerger.java b/src/main/java/net/raphimc/noteblocktool/audio/export/AudioMerger.java index 875ad35..ac363b6 100644 --- a/src/main/java/net/raphimc/noteblocktool/audio/export/AudioMerger.java +++ b/src/main/java/net/raphimc/noteblocktool/audio/export/AudioMerger.java @@ -28,9 +28,9 @@ public AudioMerger(final int sampleCount) { public void addSamples(final int[] samples) { for (int i = 0; i < samples.length; i++) { - int index = this.sampleIndex + i; + final int index = this.sampleIndex + i; if (index >= this.samples.length) break; - int sample = samples[i]; + final int sample = samples[i]; this.samples[index] += sample; } } @@ -40,8 +40,8 @@ public void pushSamples(final int samples) { } public byte[] normalizeBytes() { - byte[] bytes = new byte[this.samples.length]; - long max = this.getMax(); + final byte[] bytes = new byte[this.samples.length]; + final long max = this.getMax(); for (int i = 0; i < this.samples.length; i++) { bytes[i] = (byte) (this.samples[i] * Byte.MAX_VALUE / max); } @@ -49,8 +49,8 @@ public byte[] normalizeBytes() { } public short[] normalizeShorts() { - short[] shorts = new short[this.samples.length]; - long max = this.getMax(); + final short[] shorts = new short[this.samples.length]; + final long max = this.getMax(); for (int i = 0; i < this.samples.length; i++) { shorts[i] = (short) (this.samples[i] * Short.MAX_VALUE / max); } @@ -58,8 +58,8 @@ public short[] normalizeShorts() { } public int[] normalizeInts() { - int[] ints = new int[this.samples.length]; - long max = this.getMax(); + final int[] ints = new int[this.samples.length]; + final long max = this.getMax(); for (int i = 0; i < this.samples.length; i++) { ints[i] = (int) (this.samples[i] * Integer.MAX_VALUE / max); } 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 6744d1d..2af19f7 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 @@ -51,7 +51,7 @@ public JavaxAudioExporter(final SongView songView, final AudioFormat format, } @Override - protected void processNote(Instrument instrument, float volume, float pitch, float panning) { + protected void processNote(final Instrument instrument, final float volume, final float pitch, final float panning) { String key = instrument + "\0" + volume + "\0" + pitch; this.merger.addSamples(this.mutationCache.computeIfAbsent(key, k -> SoundSampleUtil.mutate(this.sounds.get(instrument), volume, pitch))); } 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 c77cbd0..4a9d99e 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 @@ -35,7 +35,7 @@ public OpenALAudioExporter(final OpenALSoundSystem soundSystem, final SongView mutationCache; private long[] buffer = new long[0]; - public JavaxSoundSystem(final int maxSounds, final float playbackSpeed) { - super(maxSounds); + public JavaxSoundSystem(final float playbackSpeed) { + super(0); try { this.sounds = this.loadSounds(); @@ -62,16 +62,16 @@ public JavaxSoundSystem(final int maxSounds, final float playbackSpeed) { } @Override - public void playNote(Instrument instrument, float volume, float pitch, float panning) { - String key = instrument.ordinal() + "\0" + volume + "\0" + pitch; - int[] samples = this.mutationCache.computeIfAbsent(key, k -> SoundSampleUtil.mutate(this.sounds.get(instrument), volume * this.masterVolume, pitch)); + public void playNote(final Instrument instrument, final float volume, final float pitch, final float panning) { + final String key = instrument.ordinal() + "\0" + volume + "\0" + pitch; + final int[] samples = this.mutationCache.computeIfAbsent(key, k -> SoundSampleUtil.mutate(this.sounds.get(instrument), volume * this.masterVolume, pitch)); 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]; } @Override public void writeSamples() { - long[] samples = Arrays.copyOfRange(this.buffer, 0, this.samplesPerTick); + final long[] samples = Arrays.copyOfRange(this.buffer, 0, this.samplesPerTick); this.dataLine.write(this.write(samples), 0, samples.length * 2); if (this.buffer.length > this.samplesPerTick) this.buffer = Arrays.copyOfRange(this.buffer, this.samplesPerTick, this.buffer.length); else if (this.buffer.length != 0) this.buffer = new long[0]; @@ -88,24 +88,19 @@ public void close() { } @Override - public void setMasterVolume(float volume) { - super.setMasterVolume(volume); - this.mutationCache.clear(); - } - - @Override - public int getMaxSounds() { + public int getSoundCount() { return 0; } @Override - public int getSoundCount() { - return 0; + public void setMasterVolume(final float volume) { + super.setMasterVolume(volume); + this.mutationCache.clear(); } private Map loadSounds() { try { - Map sounds = new EnumMap<>(Instrument.class); + final Map sounds = new EnumMap<>(Instrument.class); for (Map.Entry entry : SoundMap.SOUNDS.entrySet()) { sounds.put(entry.getKey(), this.readSound(JavaxSoundSystem.class.getResourceAsStream(entry.getValue()))); } @@ -134,13 +129,13 @@ private int[] readSound(final InputStream is) { } private byte[] write(final long[] samples) { - byte[] out = new byte[samples.length * 2]; + final byte[] out = new byte[samples.length * 2]; for (int i = 0; i < samples.length; i++) { long sample = samples[i]; if (sample > Short.MAX_VALUE) sample = Short.MAX_VALUE; else if (sample < Short.MIN_VALUE) sample = Short.MIN_VALUE; - short conv = (short) sample; + final short conv = (short) sample; out[i * 2] = (byte) (conv & 0xFF); out[i * 2 + 1] = (byte) ((conv >> 8) & 0xFF); } 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 92364d8..79413d2 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 @@ -70,11 +70,11 @@ public static OpenALSoundSystem createCapture(final int maxSounds, final AudioFo private Thread shutdownHook; private ByteBuffer captureBuffer; - private OpenALSoundSystem(final int maxSounds) { //Playback + private OpenALSoundSystem(final int maxSounds) { // Playback this(maxSounds, null); } - private OpenALSoundSystem(final int maxSounds, final AudioFormat captureAudioFormat) { //Capture + private OpenALSoundSystem(final int maxSounds, final AudioFormat captureAudioFormat) { // Capture super(maxSounds); this.audioFormat = captureAudioFormat; @@ -146,7 +146,7 @@ private OpenALSoundSystem(final int maxSounds, final AudioFormat captureAudioFor } @Override - public void playNote(Instrument instrument, float volume, float pitch, float panning) { + public void playNote(final Instrument instrument, final float volume, final float pitch, final float panning) { if (this.playingSources.size() >= this.maxSounds) { AL10.alDeleteSources(this.playingSources.remove(0)); this.checkError("Could not delete audio source"); @@ -229,14 +229,14 @@ public void close() { } @Override - public void setMasterVolume(float volume) { - AL10.alListenerf(AL10.AL_GAIN, volume); - this.checkError("Could not set listener gain"); + public int getSoundCount() { + return this.playingSources.size(); } @Override - public int getSoundCount() { - return this.playingSources.size(); + public void setMasterVolume(final float volume) { + AL10.alListenerf(AL10.AL_GAIN, volume); + this.checkError("Could not set listener gain"); } private void tick() { diff --git a/src/main/java/net/raphimc/noteblocktool/frames/ExportFrame.java b/src/main/java/net/raphimc/noteblocktool/frames/ExportFrame.java index 4751de6..d1065ba 100644 --- a/src/main/java/net/raphimc/noteblocktool/frames/ExportFrame.java +++ b/src/main/java/net/raphimc/noteblocktool/frames/ExportFrame.java @@ -36,6 +36,7 @@ import net.raphimc.noteblocktool.audio.soundsystem.impl.OpenALSoundSystem; import net.raphimc.noteblocktool.util.filefilter.SingleFileFilter; +import javax.sound.sampled.AudioFileFormat; import javax.sound.sampled.AudioFormat; import javax.swing.*; import java.awt.*; @@ -58,7 +59,7 @@ public class ExportFrame extends JFrame { private final List loadedSongs; private final JComboBox format = new JComboBox<>(new String[]{"NBS", "WAV", "AIF"}); private final JLabel soundSystemLabel = new JLabel("Sound System:"); - private final JComboBox soundSystem = new JComboBox<>(new String[]{"OpenAL (better sound quality)", "Javax (faster, normalized, multithreaded, mono only)"}); + private final JComboBox soundSystem = new JComboBox<>(new String[]{"OpenAL (better sound quality)", "Javax (faster, normalized, mono only)"}); private final JLabel sampleRateLabel = new JLabel("Sample Rate:"); private final JSpinner sampleRate = new JSpinner(new SpinnerNumberModel(44_100, 8_000, 192_000, 1_000)); private final JLabel bitDepthLabel = new JLabel("PCM Bit Depth:"); @@ -390,7 +391,7 @@ private void exportSong(final ListFrame.LoadedSong song, final OpenALSoundSystem else exporter = new JavaxAudioExporter(songView, format, progressConsumer); exporter.render(); - exporter.write(file); + exporter.write(this.format.getSelectedIndex() == 1 ? AudioFileFormat.Type.WAVE : AudioFileFormat.Type.AIFF, file); } } diff --git a/src/main/java/net/raphimc/noteblocktool/frames/ListFrame.java b/src/main/java/net/raphimc/noteblocktool/frames/ListFrame.java index c3ffbb6..2d6828a 100644 --- a/src/main/java/net/raphimc/noteblocktool/frames/ListFrame.java +++ b/src/main/java/net/raphimc/noteblocktool/frames/ListFrame.java @@ -24,6 +24,7 @@ import net.raphimc.noteblocklib.format.nbs.NbsSong; import net.raphimc.noteblocklib.model.Song; import net.raphimc.noteblocklib.model.SongView; +import net.raphimc.noteblocklib.util.SongUtil; import net.raphimc.noteblocktool.elements.FastScrollPane; import net.raphimc.noteblocktool.elements.TextOverlayPanel; import net.raphimc.noteblocktool.elements.drag.DragTable; @@ -329,7 +330,7 @@ public int getNoteCount() { } public int getNoteCount(final SongView view) { - return (int) view.getNotes().values().stream().mapToLong(List::size).sum(); + return (int) SongUtil.getNoteCount(view); } @Override diff --git a/src/main/java/net/raphimc/noteblocktool/frames/SongPlayerFrame.java b/src/main/java/net/raphimc/noteblocktool/frames/SongPlayerFrame.java index 41ff412..a9c2562 100644 --- a/src/main/java/net/raphimc/noteblocktool/frames/SongPlayerFrame.java +++ b/src/main/java/net/raphimc/noteblocktool/frames/SongPlayerFrame.java @@ -245,7 +245,7 @@ private boolean initSoundSystem() { if (this.soundSystemComboBox.getSelectedIndex() == 0) { this.soundSystem = OpenALSoundSystem.createPlayback(((Number) this.maxSoundsSpinner.getValue()).intValue()); } else if (this.soundSystemComboBox.getSelectedIndex() == 1) { - this.soundSystem = new JavaxSoundSystem(((Number) this.maxSoundsSpinner.getValue()).intValue(), this.songPlayer.getSongView().getSpeed()); + this.soundSystem = new JavaxSoundSystem(this.songPlayer.getSongView().getSpeed()); } else { throw new UnsupportedOperationException(UNAVAILABLE_MESSAGE); } diff --git a/src/main/java/net/raphimc/noteblocktool/util/DefaultSongPlayerCallback.java b/src/main/java/net/raphimc/noteblocktool/util/DefaultSongPlayerCallback.java index b53d9bf..e999c90 100644 --- a/src/main/java/net/raphimc/noteblocktool/util/DefaultSongPlayerCallback.java +++ b/src/main/java/net/raphimc/noteblocktool/util/DefaultSongPlayerCallback.java @@ -30,7 +30,7 @@ public interface DefaultSongPlayerCallback extends ISongPlayerCallback { @Override - default void playNote(Note note) { + default void playNote(final Note note) { if (note.getInstrument() >= Instrument.values().length) return; final float volume; if (note instanceof NoteWithVolume) { @@ -61,6 +61,6 @@ default void playNote(Note note) { this.playNote(instrument, playerVolume, pitch, playerPanning); } - void playNote(Instrument instrument, float volume, float pitch, float panning); + void playNote(final Instrument instrument, final float volume, final float pitch, final float panning); }