diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 65f5925..431eeca 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -33,9 +33,9 @@ jobs:
shell: pwsh
run: |
New-Item -ItemType Directory -Force release | Out-Null
- Copy-Item staging/input/Kimusic.jar release/Kimusic-0.1.0.jar
- jpackage --type exe --name Kimusic --app-version 0.1.0 --input staging/input --main-jar Kimusic.jar --main-class club.muimi.kimusic.Launcher --icon logo.ico --dest release --win-shortcut --win-menu
- jpackage --type msi --name Kimusic --app-version 0.1.0 --input staging/input --main-jar Kimusic.jar --main-class club.muimi.kimusic.Launcher --icon logo.ico --dest release --win-shortcut --win-menu
+ Copy-Item staging/input/Kimusic.jar release/Kimusic-0.1.1.jar
+ jpackage --type exe --name Kimusic --app-version 0.1.1 --input staging/input --main-jar Kimusic.jar --main-class club.muimi.kimusic.Launcher --icon logo.ico --dest release --win-shortcut --win-menu
+ jpackage --type msi --name Kimusic --app-version 0.1.1 --input staging/input --main-jar Kimusic.jar --main-class club.muimi.kimusic.Launcher --icon logo.ico --dest release --win-shortcut --win-menu
- uses: actions/upload-artifact@v4
with:
name: windows-release
@@ -62,9 +62,9 @@ jobs:
- name: Build Debian package and app image
run: |
mkdir -p release
- cp staging/input/Kimusic.jar release/Kimusic-0.1.0.jar
- jpackage --type deb --name Kimusic --app-version 0.1.0 --input staging/input --main-jar Kimusic.jar --main-class club.muimi.kimusic.Launcher --dest release
- jpackage --type app-image --name Kimusic --app-version 0.1.0 --input staging/input --main-jar Kimusic.jar --main-class club.muimi.kimusic.Launcher --dest staging
+ cp staging/input/Kimusic.jar release/Kimusic-0.1.1.jar
+ jpackage --type deb --name Kimusic --app-version 0.1.1 --input staging/input --main-jar Kimusic.jar --main-class club.muimi.kimusic.Launcher --dest release
+ jpackage --type app-image --name Kimusic --app-version 0.1.1 --input staging/input --main-jar Kimusic.jar --main-class club.muimi.kimusic.Launcher --dest staging
cp src/main/resources/club/muimi/kimusic/logo.png staging/Kimusic/kimusic.png
cat > staging/Kimusic/Kimusic.desktop <<'EOF'
[Desktop Entry]
diff --git a/pom.xml b/pom.xml
index e70a7cb..9719d6e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
club.muimi
Kimusic
- 0.1.0
+ 0.1.1
Kimusic
diff --git a/src/main/java/club/muimi/kimusic/service/playback/JavaSoundPlaybackEngine.java b/src/main/java/club/muimi/kimusic/service/playback/JavaSoundPlaybackEngine.java
index 49650f0..5d1a3d5 100644
--- a/src/main/java/club/muimi/kimusic/service/playback/JavaSoundPlaybackEngine.java
+++ b/src/main/java/club/muimi/kimusic/service/playback/JavaSoundPlaybackEngine.java
@@ -320,21 +320,16 @@ private float[] spectrumOf(byte[] buffer, int length) {
}
fft(real, imaginary);
- float[] spectrum = new float[64];
+ // Return the positive-frequency FFT bins. WaveformView owns the only
+ // frequency-band projection so logarithmic scaling is not applied twice.
int usableBins = fftSize / 2;
- for (int band = 0; band < spectrum.length; band++) {
- double fromRatio = band / (double) spectrum.length;
- double toRatio = (band + 1) / (double) spectrum.length;
- int from = Math.max(1, (int) Math.round(Math.pow(fromRatio, 2) * usableBins));
- int to = Math.max(from + 1, (int) Math.round(Math.pow(toRatio, 2) * usableBins));
- double peak = 0;
- for (int bin = from; bin < Math.min(to, usableBins); bin++) {
- peak = Math.max(peak, Math.hypot(real[bin], imaginary[bin]));
- }
+ float[] spectrum = new float[usableBins];
+ for (int bin = 1; bin < usableBins; bin++) {
+ double magnitude = Math.hypot(real[bin], imaginary[bin]);
// Keep a little over-range so the view can normalize all bands against
// the current maximum instead of flattening clipped peaks.
- spectrum[band] = (float) Math.max(0, Math.min(4,
- Math.log10(1 + peak * 18) / Math.log10(19)));
+ spectrum[bin] = (float) Math.max(0, Math.min(4,
+ Math.log10(1 + magnitude * 18) / Math.log10(19)));
}
return spectrum;
}
diff --git a/src/main/java/club/muimi/kimusic/view/component/WaveformView.java b/src/main/java/club/muimi/kimusic/view/component/WaveformView.java
index 90fe4de..e96a5b8 100644
--- a/src/main/java/club/muimi/kimusic/view/component/WaveformView.java
+++ b/src/main/java/club/muimi/kimusic/view/component/WaveformView.java
@@ -63,10 +63,12 @@ private void pushSpectrum(float[] values) {
return;
}
for (int index = 0; index < spectrum.length; index++) {
- int source = Math.min(values.length - 1,
- (int) ((long) index * values.length / spectrum.length));
+ double normalized = (double) index / spectrum.length;
+ double freq = 20.0 * Math.pow(20000.0 / 20.0, normalized);
+ int source = (int) (freq / (20000.0 / values.length));
+ source = Math.min(values.length - 1, Math.max(0, source));
// Preserve headroom so dense peaks can be normalized during drawing.
- float value = Math.max(0, Math.min(4, values[source]));
+ float value = Math.max(0, Math.min(20, values[source]));
spectrum[index] += (value - spectrum[index]) * (value > spectrum[index] ? 0.62f : 0.2f);
spectrumPeaks[index] = Math.max(spectrum[index], spectrumPeaks[index] - 0.018f);
}
@@ -151,11 +153,17 @@ private void drawSpectrum(GraphicsContext graphics, double width, double height)
displayScale = Math.max(0.35, Math.min(6.0, displayScale));
for (int index = 0; index < spectrum.length; index++) {
double x = index * width / spectrum.length;
- double magnitude = Math.max(0.025, Math.min(1.0, spectrum[index] * displayScale));
+ float raw = (float) (spectrum[index] * displayScale);
+ double db = 20 * Math.log10(raw + 1e-12);
+ double normalized = (db + 120) / 120;
+ double magnitude = Math.max(0.025, Math.min(1.0, normalized));
double barHeight = Math.max(3, magnitude * (height - 13));
graphics.setFill(Color.web("#1aa79b", 0.9));
graphics.fillRoundRect(x, height - barHeight, bandWidth, barHeight, 3, 3);
- double peakMagnitude = Math.min(1.0, spectrumPeaks[index] * displayScale);
+ float peakRaw = (float) (spectrumPeaks[index] * displayScale);
+ double peakDb = 20 * Math.log10(peakRaw + 1e-12);
+ double peakNormalized = (peakDb + 120) / 120;
+ double peakMagnitude = Math.max(0.025, Math.min(1.0, peakNormalized));
double peakY = height - Math.max(3, peakMagnitude * (height - 13));
graphics.setFill(Color.web("#8be0d5", 0.86));
graphics.fillRoundRect(x, peakY, bandWidth, 2, 2, 2);