mirror of
https://github.com/Boof2015/prism.git
synced 2026-08-16 16:21:11 +02:00
change spectrum db to dbFS
This commit is contained in:
@@ -20,15 +20,17 @@ export class BridgeSpectrumAnalyzer implements SpectrumNativeAnalyzer {
|
||||
private sampleRate = 48000
|
||||
private magnitudes: Float32Array
|
||||
private sideMagnitudes: Float32Array
|
||||
private channelMaxMagnitudes: Float32Array
|
||||
|
||||
constructor(fftSize = 2048) {
|
||||
this.fftSize = fftSize
|
||||
this.magnitudes = new Float32Array(fftSize / 2).fill(FFT_SILENCE_DB)
|
||||
this.sideMagnitudes = new Float32Array(fftSize / 2).fill(FFT_SILENCE_DB)
|
||||
this.channelMaxMagnitudes = new Float32Array(fftSize / 2).fill(FFT_SILENCE_DB)
|
||||
}
|
||||
|
||||
/** Called by the bridge whenever the host emits a new frame. */
|
||||
setMagnitudes(magnitudes: Float32Array, side?: Float32Array): void {
|
||||
setMagnitudes(magnitudes: Float32Array, side?: Float32Array, channelMax?: Float32Array): void {
|
||||
if (magnitudes.length !== this.magnitudes.length) {
|
||||
this.magnitudes = new Float32Array(magnitudes.length)
|
||||
}
|
||||
@@ -40,6 +42,12 @@ export class BridgeSpectrumAnalyzer implements SpectrumNativeAnalyzer {
|
||||
}
|
||||
this.sideMagnitudes.set(side)
|
||||
}
|
||||
|
||||
const resolvedChannelMax = channelMax && channelMax.length > 0 ? channelMax : magnitudes
|
||||
if (resolvedChannelMax.length !== this.channelMaxMagnitudes.length) {
|
||||
this.channelMaxMagnitudes = new Float32Array(resolvedChannelMax.length)
|
||||
}
|
||||
this.channelMaxMagnitudes.set(resolvedChannelMax)
|
||||
}
|
||||
|
||||
isAvailable(): boolean {
|
||||
@@ -51,6 +59,7 @@ export class BridgeSpectrumAnalyzer implements SpectrumNativeAnalyzer {
|
||||
this.fftSize = size
|
||||
this.magnitudes = new Float32Array(size / 2).fill(FFT_SILENCE_DB)
|
||||
this.sideMagnitudes = new Float32Array(size / 2).fill(FFT_SILENCE_DB)
|
||||
this.channelMaxMagnitudes = new Float32Array(size / 2).fill(FFT_SILENCE_DB)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,6 +100,14 @@ export class BridgeSpectrumAnalyzer implements SpectrumNativeAnalyzer {
|
||||
return count
|
||||
}
|
||||
|
||||
fillChannelMaxMagnitudes(output: Float32Array): number {
|
||||
const count = Math.min(output.length, this.channelMaxMagnitudes.length)
|
||||
if (count > 0) {
|
||||
output.set(this.channelMaxMagnitudes.subarray(0, count), 0)
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
getMagnitudes(): Float32Array {
|
||||
return this.magnitudes
|
||||
}
|
||||
@@ -103,6 +120,10 @@ export class BridgeSpectrumAnalyzer implements SpectrumNativeAnalyzer {
|
||||
return this.sideMagnitudes
|
||||
}
|
||||
|
||||
getChannelMaxMagnitudes(): Float32Array {
|
||||
return this.channelMaxMagnitudes
|
||||
}
|
||||
|
||||
process(_audioData: Float32Array): Float32Array {
|
||||
return this.magnitudes
|
||||
}
|
||||
@@ -114,5 +135,6 @@ export class BridgeSpectrumAnalyzer implements SpectrumNativeAnalyzer {
|
||||
reset(): void {
|
||||
this.magnitudes.fill(FFT_SILENCE_DB)
|
||||
this.sideMagnitudes.fill(FFT_SILENCE_DB)
|
||||
this.channelMaxMagnitudes.fill(FFT_SILENCE_DB)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import { spectrumSettingsToOptions } from './spectrumOptions'
|
||||
import { getScopeCanvasTransformStyle } from '../renderer/scopeCanvasTransform'
|
||||
import { applyPluginScopeCanvasLayout } from './scopeCanvasLayout'
|
||||
import {
|
||||
formatSpectrumPeakDb,
|
||||
formatSpectrumPeakDbfs,
|
||||
formatSpectrumPeakFrequency,
|
||||
resolveFollowingPeakOverlayStyle,
|
||||
type CanvasResizeState,
|
||||
@@ -137,7 +137,7 @@ export default function SpectrumScope({
|
||||
className={['scope-module__peak-info', peakMode === 'following' ? 'is-following' : 'is-corner'].join(' ')}
|
||||
style={overlayStyle}
|
||||
>
|
||||
<span className="scope-module__peak-info-value">{formatSpectrumPeakDb(peak.db)}</span>
|
||||
<span className="scope-module__peak-info-value">{formatSpectrumPeakDbfs(peak.dbfs)}</span>
|
||||
<span className="scope-module__peak-info-separator">/</span>
|
||||
<span className="scope-module__peak-info-value">{formatSpectrumPeakFrequency(peak.frequencyHz)}</span>
|
||||
<span className="scope-module__peak-info-separator">/</span>
|
||||
|
||||
@@ -16,12 +16,15 @@ export interface SpectrumFrame {
|
||||
magnitudes: Float32Array
|
||||
/** Side magnitudes in dB (same length); empty if unavailable. */
|
||||
side: Float32Array
|
||||
/** Smoothed max(L, R) magnitudes in dBFS (same length). */
|
||||
channelMax: Float32Array
|
||||
}
|
||||
|
||||
interface SpectrumFramePayload {
|
||||
sampleRate?: number
|
||||
magnitudes?: string
|
||||
side?: string
|
||||
channelMax?: string
|
||||
}
|
||||
|
||||
type JuceBackend = {
|
||||
@@ -100,14 +103,19 @@ export function base64ToFloat32Array(b64: string): Float32Array {
|
||||
return new Float32Array(bytes.buffer, 0, byteLength >> 2)
|
||||
}
|
||||
|
||||
function decodeFrame(payload: unknown): SpectrumFrame | null {
|
||||
export function decodeSpectrumFrame(payload: unknown): SpectrumFrame | null {
|
||||
if (typeof payload !== 'object' || payload === null) return null
|
||||
const { sampleRate, magnitudes, side } = payload as SpectrumFramePayload
|
||||
const { sampleRate, magnitudes, side, channelMax } = payload as SpectrumFramePayload
|
||||
if (typeof magnitudes !== 'string' || magnitudes.length === 0) return null
|
||||
const decodedMagnitudes = base64ToFloat32Array(magnitudes)
|
||||
const decodedChannelMax = typeof channelMax === 'string'
|
||||
? base64ToFloat32Array(channelMax)
|
||||
: new Float32Array(0)
|
||||
return {
|
||||
sampleRate: typeof sampleRate === 'number' && sampleRate > 0 ? sampleRate : 48000,
|
||||
magnitudes: base64ToFloat32Array(magnitudes),
|
||||
magnitudes: decodedMagnitudes,
|
||||
side: typeof side === 'string' ? base64ToFloat32Array(side) : new Float32Array(0),
|
||||
channelMax: decodedChannelMax.length > 0 ? decodedChannelMax : decodedMagnitudes,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,6 +136,7 @@ export function connectSpectrumBridge(handlers: SpectrumBridgeHandlers): () => v
|
||||
const sampleRate = 48000
|
||||
const mid = new Float32Array(binCount)
|
||||
const side = new Float32Array(binCount).fill(-100)
|
||||
const channelMax = new Float32Array(binCount)
|
||||
let phase = 0
|
||||
const tick = (): void => {
|
||||
if (disposed) return
|
||||
@@ -138,8 +147,9 @@ export function connectSpectrumBridge(handlers: SpectrumBridgeHandlers): () => v
|
||||
const peak2 = Math.exp(-Math.pow((t - 0.5) * 18, 2)) * 50
|
||||
mid[i] = -100 + peak1 + peak2 + Math.random() * 6
|
||||
side[i] = -100 + peak2 * 0.4 + Math.random() * 4
|
||||
channelMax[i] = mid[i]
|
||||
}
|
||||
handlers.onFrame({ sampleRate, magnitudes: mid, side })
|
||||
handlers.onFrame({ sampleRate, magnitudes: mid, side, channelMax })
|
||||
mockRaf = requestAnimationFrame(tick)
|
||||
}
|
||||
mockRaf = requestAnimationFrame(tick)
|
||||
@@ -149,7 +159,7 @@ export function connectSpectrumBridge(handlers: SpectrumBridgeHandlers): () => v
|
||||
if (disposed) return
|
||||
if (backend) {
|
||||
listenerId = backend.addEventListener('spectrumFrame', (payload) => {
|
||||
const frame = decodeFrame(payload)
|
||||
const frame = decodeSpectrumFrame(payload)
|
||||
if (frame) handlers.onFrame(frame)
|
||||
})
|
||||
handlers.onConnected?.(false)
|
||||
|
||||
@@ -185,7 +185,7 @@ function buildApp(): JSX.Element {
|
||||
const analyzer = new BridgeSpectrumAnalyzer(2048)
|
||||
connectSpectrumBridge({
|
||||
onFrame: (frame) => {
|
||||
analyzer.setMagnitudes(frame.magnitudes, frame.side)
|
||||
analyzer.setMagnitudes(frame.magnitudes, frame.side, frame.channelMax)
|
||||
dataSource.setSampleRate(frame.sampleRate)
|
||||
dataSource.setPlaying(true)
|
||||
},
|
||||
|
||||
@@ -28,11 +28,11 @@ function clampNumber(value: number, min: number, max: number): number {
|
||||
return Math.min(max, Math.max(min, value))
|
||||
}
|
||||
|
||||
export function formatSpectrumPeakDb(value: number): string {
|
||||
export function formatSpectrumPeakDbfs(value: number): string {
|
||||
if (!Number.isFinite(value)) {
|
||||
return '--'
|
||||
}
|
||||
return `${value >= 0 ? '+' : ''}${value.toFixed(2)}dB`
|
||||
return `${value >= 0 ? '+' : ''}${value.toFixed(2)}dBFS`
|
||||
}
|
||||
|
||||
export function formatSpectrumPeakFrequency(value: number): string {
|
||||
|
||||
Reference in New Issue
Block a user