diff --git a/src/components/KGOnePanel.test.tsx b/src/components/KGOnePanel.test.tsx index a4432b5..23f04c7 100644 --- a/src/components/KGOnePanel.test.tsx +++ b/src/components/KGOnePanel.test.tsx @@ -81,7 +81,7 @@ vi.mock('../util/audioUtil', () => ({ sliceAudioToWav: vi.fn(async (_buffer: ArrayBuffer) => _buffer), })); -vi.mock('../util/localSeparatorModelCache', () => ({ +vi.mock('../util/local-separator/modelCache', () => ({ LocalSeparatorModelCache: { exists: vi.fn(async () => localModelCached), download: vi.fn(async (url: string, filename: string, onProgress: (progress: unknown) => void) => { @@ -95,7 +95,7 @@ vi.mock('../util/localSeparatorModelCache', () => ({ }, })); -vi.mock('../util/localSeparatorRuntime', () => ({ +vi.mock('../util/local-separator/runtime', () => ({ detectLocalRuntimeSupport: () => ({ webgpuExposed: false }), LocalOrtRuntimeManager: class { constructor(private readonly options?: { onProviderChange?: (provider: string) => void }) {} @@ -109,7 +109,7 @@ vi.mock('../util/localSeparatorRuntime', () => ({ }, })); -vi.mock('../util/localSeparatorRunner', () => ({ +vi.mock('../util/local-separator/runner', () => ({ runLocalSeparator: vi.fn(async ({ onProgress, onProviderChange }) => { onProviderChange?.('cpu/wasm'); onProgress({ stage: 'main', passLabel: 'Main pass', percent: 100, processedChunks: 1, totalChunks: 1 }); diff --git a/src/components/KGOnePanel.tsx b/src/components/KGOnePanel.tsx index 7f86e6b..cf9386f 100644 --- a/src/components/KGOnePanel.tsx +++ b/src/components/KGOnePanel.tsx @@ -19,10 +19,10 @@ import { LOCAL_SEPARATOR_MODEL_CONFIG, LOCAL_SEPARATOR_MODEL_FILENAME, LOCAL_SEPARATOR_DEFAULT_MODEL_URL, -} from '../util/localSeparatorConfig'; -import { LocalSeparatorModelCache } from '../util/localSeparatorModelCache'; -import { runLocalSeparator } from '../util/localSeparatorRunner'; -import { LocalOrtRuntimeManager, detectLocalRuntimeSupport } from '../util/localSeparatorRuntime'; +} from '../util/local-separator/config'; +import { LocalSeparatorModelCache } from '../util/local-separator/modelCache'; +import { runLocalSeparator } from '../util/local-separator/runner'; +import { LocalOrtRuntimeManager, detectLocalRuntimeSupport } from '../util/local-separator/runtime'; // ─── Types ──────────────────────────────────────────────────────────────────── diff --git a/src/components/settings/sections/GeneralSettings.test.tsx b/src/components/settings/sections/GeneralSettings.test.tsx index 93cfd81..6f29bc0 100644 --- a/src/components/settings/sections/GeneralSettings.test.tsx +++ b/src/components/settings/sections/GeneralSettings.test.tsx @@ -80,7 +80,7 @@ vi.mock('../../../util/localLLMModelManager', () => ({ }, })); -vi.mock('../../../util/localSeparatorModelCache', () => ({ +vi.mock('../../../util/local-separator/modelCache', () => ({ LocalSeparatorModelCache: localSeparatorModelCacheMock, })); diff --git a/src/components/settings/sections/GeneralSettings.tsx b/src/components/settings/sections/GeneralSettings.tsx index a066b9e..4fee891 100644 --- a/src/components/settings/sections/GeneralSettings.tsx +++ b/src/components/settings/sections/GeneralSettings.tsx @@ -1,7 +1,7 @@ import React, { useState, useEffect, useCallback, useMemo } from 'react'; import { ConfigManager } from '../../../core/config/ConfigManager'; import { LocalLLMModelManager, type LocalLLMModelState } from '../../../util/localLLMModelManager'; -import { LocalSeparatorModelCache } from '../../../util/localSeparatorModelCache'; +import { LocalSeparatorModelCache } from '../../../util/local-separator/modelCache'; import { formatLocalLLMContextLength, LOCAL_LLM_CONTEXT_LENGTH_OPTIONS, @@ -12,7 +12,7 @@ import { normalizeLocalLLMContextLength, type LocalLLMContextLength, } from '../../../util/localLLMConfig'; -import { LOCAL_SEPARATOR_DEFAULT_MODEL_URL } from '../../../util/localSeparatorConfig'; +import { LOCAL_SEPARATOR_DEFAULT_MODEL_URL } from '../../../util/local-separator/config'; const GeneralSettings: React.FC = () => { const [llmProvider, setLlmProvider] = useState(LOCAL_LLM_PROVIDER_KEY); diff --git a/src/core/io/LocalSeparatorModelCache.test.ts b/src/core/io/LocalSeparatorModelCache.test.ts index 78d5f08..8429f50 100644 --- a/src/core/io/LocalSeparatorModelCache.test.ts +++ b/src/core/io/LocalSeparatorModelCache.test.ts @@ -1,9 +1,9 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'; -import { LocalSeparatorModelCache } from '../../util/localSeparatorModelCache'; +import { LocalSeparatorModelCache } from '../../util/local-separator/modelCache'; import { LOCAL_SEPARATOR_MODEL_EXPECTED_SIZE_BYTES, LOCAL_SEPARATOR_MODEL_FILENAME, -} from '../../util/localSeparatorConfig'; +} from '../../util/local-separator/config'; class MockWritableFileStream { private readonly handle: MockFileSystemFileHandle; diff --git a/src/util/localSeparatorConfig.ts b/src/util/local-separator/config.ts similarity index 92% rename from src/util/localSeparatorConfig.ts rename to src/util/local-separator/config.ts index 4a52ec5..79c8d31 100644 --- a/src/util/localSeparatorConfig.ts +++ b/src/util/local-separator/config.ts @@ -1,4 +1,4 @@ -import type { LocalSeparatorModelConfig } from './localSeparatorTypes'; +import type { LocalSeparatorModelConfig } from './types'; export const LOCAL_SEPARATOR_DEFAULT_MODEL_URL = 'https://huggingface.co/notabilia/uvr5-models/resolve/main/UVR-MDX-NET-Inst_HQ_3.onnx'; diff --git a/src/util/localSeparatorCpuDsp.ts b/src/util/local-separator/cpuDsp.ts similarity index 98% rename from src/util/localSeparatorCpuDsp.ts rename to src/util/local-separator/cpuDsp.ts index cda0ac3..b69d20e 100644 --- a/src/util/localSeparatorCpuDsp.ts +++ b/src/util/local-separator/cpuDsp.ts @@ -1,5 +1,5 @@ -import type { LocalSeparatorModelConfig, StereoChannels } from './localSeparatorTypes'; -import { FFT, createWindowCache, getHannPeriodic, index4d, reflectPad } from './localSeparatorShared'; +import type { LocalSeparatorModelConfig, StereoChannels } from './types'; +import { FFT, createWindowCache, getHannPeriodic, index4d, reflectPad } from './shared'; interface SpectrogramPayload { data: Float32Array; diff --git a/src/util/localSeparatorGpuDsp.ts b/src/util/local-separator/gpuDsp.ts similarity index 93% rename from src/util/localSeparatorGpuDsp.ts rename to src/util/local-separator/gpuDsp.ts index 41cb0e4..56d6909 100644 --- a/src/util/localSeparatorGpuDsp.ts +++ b/src/util/local-separator/gpuDsp.ts @@ -1,8 +1,8 @@ -import type { LocalSeparatorModelConfig } from './localSeparatorTypes'; -import { LocalSeparatorCpuDsp } from './localSeparatorCpuDsp'; -import { reflectPad } from './localSeparatorShared'; +import type { LocalSeparatorModelConfig } from './types'; +import { LocalSeparatorCpuDsp } from './cpuDsp'; +import { reflectPad } from './shared'; -function localSeparatorLog(message: string, payload?: unknown): void { +function log(message: string, payload?: unknown): void { if (payload === undefined) { console.log(`[localSeparator] ${message}`); return; @@ -145,22 +145,22 @@ export class LocalSeparatorGpuDsp { throw new Error('WebGPU is not available for GPU DSP.'); } - localSeparatorLog('Requesting WebGPU adapter for GPU DSP.'); + log('Requesting WebGPU adapter for GPU DSP.'); const adapter = await (navigator as NavigatorWithGpu).gpu?.requestAdapter({ powerPreference: 'high-performance', }); if (!adapter) { throw new Error('No WebGPU adapter was available for GPU DSP.'); } - localSeparatorLog('WebGPU adapter acquired for GPU DSP.', { + log('WebGPU adapter acquired for GPU DSP.', { features: typeof adapter.features?.values === 'function' ? Array.from(adapter.features.values()) : undefined, limits: adapter.limits, info: typeof adapter.info === 'object' ? adapter.info : undefined, }); - localSeparatorLog('Requesting WebGPU device for GPU DSP.'); + log('Requesting WebGPU device for GPU DSP.'); const device = await adapter.requestDevice(); - localSeparatorLog('WebGPU device acquired for GPU DSP.'); + log('WebGPU device acquired for GPU DSP.'); return new LocalSeparatorGpuDsp(config, device); } @@ -170,7 +170,7 @@ export class LocalSeparatorGpuDsp { this.nFft = config.metadata.mdx_n_fft_scale_set; this.hopLength = config.defaults.hopLength; this.trim = Math.floor(this.nFft / 2); - localSeparatorLog('Creating GPU DSP compute pipeline.'); + log('Creating GPU DSP compute pipeline.'); this.pipeline = device.createComputePipeline({ layout: 'auto', compute: { @@ -178,7 +178,7 @@ export class LocalSeparatorGpuDsp { entryPoint: 'main', }, }); - localSeparatorLog('GPU DSP compute pipeline created.'); + log('GPU DSP compute pipeline created.'); } public async forwardStereo(leftChunk: Float32Array, rightChunk: Float32Array): Promise<{ diff --git a/src/util/localSeparatorModelCache.ts b/src/util/local-separator/modelCache.ts similarity index 91% rename from src/util/localSeparatorModelCache.ts rename to src/util/local-separator/modelCache.ts index 619cbc5..96dc940 100644 --- a/src/util/localSeparatorModelCache.ts +++ b/src/util/local-separator/modelCache.ts @@ -1,8 +1,8 @@ import { LOCAL_SEPARATOR_MODEL_EXPECTED_SIZE_BYTES, LOCAL_SEPARATOR_MODEL_FILENAME, -} from './localSeparatorConfig'; -import { OpfsModelCache, type ModelDownloadProgress } from './opfsModelCache'; +} from './config'; +import { OpfsModelCache, type ModelDownloadProgress } from '../opfsModelCache'; const cache = new OpfsModelCache({ directoryName: 'models' }); diff --git a/src/util/localSeparatorRunner.ts b/src/util/local-separator/runner.ts similarity index 95% rename from src/util/localSeparatorRunner.ts rename to src/util/local-separator/runner.ts index f4634b5..916b5ec 100644 --- a/src/util/localSeparatorRunner.ts +++ b/src/util/local-separator/runner.ts @@ -1,13 +1,13 @@ import * as ort from 'onnxruntime-web/webgpu'; -import { LocalSeparatorCpuDsp } from './localSeparatorCpuDsp'; -import { LocalSeparatorGpuDsp } from './localSeparatorGpuDsp'; -import { LocalSeparatorTimingCollector } from './localSeparatorTiming'; +import { LocalSeparatorCpuDsp } from './cpuDsp'; +import { LocalSeparatorGpuDsp } from './gpuDsp'; +import { LocalSeparatorTimingCollector } from './timing'; import type { LocalRuntimeProvider, LocalSeparatorModelConfig, LocalSeparatorProgress, StereoChannels, -} from './localSeparatorTypes'; +} from './types'; import { concatFloat32, createWindowCache, @@ -16,11 +16,11 @@ import { normalizeChannels, scaleChannels, sliceChannels, -} from './localSeparatorShared'; +} from './shared'; const SAMPLE_RATE = 44100; -function localSeparatorLog(message: string, payload?: unknown): void { +function log(message: string, payload?: unknown): void { if (payload === undefined) { console.log(`[localSeparator] ${message}`); return; @@ -108,11 +108,11 @@ class BrowserMdxSeparator { try { dsp = await timing.measureAsync('dspInit', () => LocalSeparatorGpuDsp.create(config)); dspMode = 'gpu-hybrid'; - localSeparatorLog('GPU DSP initialized successfully.'); + log('GPU DSP initialized successfully.'); } catch (error) { console.warn('[localSeparator] GPU DSP initialization failed, using CPU DSP.', error); options.onProviderChange?.('webgpu + cpu dsp fallback'); - localSeparatorLog( + log( 'GPU DSP initialization failed. Inference session may still use WebGPU, but DSP will fall back to CPU.', error, ); @@ -122,9 +122,9 @@ class BrowserMdxSeparator { if (!dsp) { dsp = new LocalSeparatorCpuDsp(config); if (runtimeProvider === 'webgpu') { - localSeparatorLog('Using CPU DSP while keeping the WebGPU inference provider.'); + log('Using CPU DSP while keeping the WebGPU inference provider.'); } else { - localSeparatorLog('Using CPU DSP because the active inference provider is CPU/wasm.'); + log('Using CPU DSP because the active inference provider is CPU/wasm.'); } } @@ -376,7 +376,7 @@ class BrowserMdxSeparator { } catch (error) { if (payloads.length > 1 && this.runtimeBatchSize > 1) { console.warn('[localSeparator] Batched inference failed, falling back to batch size 1.', error); - localSeparatorLog('Batched inference failed. Falling back to batch size 1.', error); + log('Batched inference failed. Falling back to batch size 1.', error); this.runtimeBatchSize = 1; const singleResults: SpectrogramPayload[] = []; for (const payload of payloads) { @@ -486,7 +486,7 @@ export async function runLocalSeparator(options: { }> { const timing = new LocalSeparatorTimingCollector('local-separation'); const decoded = await timing.measureAsync('decode', () => decodeAudioToStereo(options.audioBuffer)); - localSeparatorLog(`Running browser MDX separation on ${options.runtimeProvider === 'webgpu' ? 'GPU/WebGPU' : 'CPU/wasm'}...`); + log(`Running browser MDX separation on ${options.runtimeProvider === 'webgpu' ? 'GPU/WebGPU' : 'CPU/wasm'}...`); const separator = await BrowserMdxSeparator.create( options.session, @@ -522,7 +522,7 @@ export async function runLocalSeparator(options: { debugSummary: separator.getDebugSummary({ model: options.modelConfig.filename }), }; } finally { - localSeparatorLog('Separation timing summary', separator.getDebugSummary({ model: options.modelConfig.filename })); + log('Separation timing summary', separator.getDebugSummary({ model: options.modelConfig.filename })); separator.dispose(); } } diff --git a/src/util/localSeparatorRuntime.ts b/src/util/local-separator/runtime.ts similarity index 75% rename from src/util/localSeparatorRuntime.ts rename to src/util/local-separator/runtime.ts index d01d266..497a282 100644 --- a/src/util/localSeparatorRuntime.ts +++ b/src/util/local-separator/runtime.ts @@ -1,8 +1,8 @@ import * as ort from 'onnxruntime-web/webgpu'; import ortWasmAsyncifyUrl from 'onnxruntime-web/ort-wasm-simd-threaded.asyncify.wasm?url'; -import type { LocalRuntimeState, LocalRuntimeSupport, LocalSeparatorModelConfig } from './localSeparatorTypes'; +import type { LocalRuntimeState, LocalRuntimeSupport, LocalSeparatorModelConfig } from './types'; -function localSeparatorLog(message: string, payload?: unknown): void { +function log(message: string, payload?: unknown): void { if (payload === undefined) { console.log(`[localSeparator] ${message}`); return; @@ -15,9 +15,9 @@ export function detectLocalRuntimeSupport(): LocalRuntimeSupport { webgpuExposed: typeof navigator !== 'undefined' && 'gpu' in navigator, }; if (support.webgpuExposed) { - localSeparatorLog('WebGPU API is exposed by this browser.'); + log('WebGPU API is exposed by this browser.'); } else { - localSeparatorLog('WebGPU API is not exposed by this browser. CPU/wasm will be used.'); + log('WebGPU API is not exposed by this browser. CPU/wasm will be used.'); } return support; } @@ -46,16 +46,16 @@ export class LocalOrtRuntimeManager { ort.env.wasm.wasmPaths = { wasm: ortWasmAsyncifyUrl, }; - localSeparatorLog('Configured ONNX Runtime wasm paths.', ort.env.wasm.wasmPaths); + log('Configured ONNX Runtime wasm paths.', ort.env.wasm.wasmPaths); LocalOrtRuntimeManager.wasmPathsConfigured = true; } const providersToTry: Array<'webgpu' | 'wasm'> = []; if (typeof navigator !== 'undefined' && 'gpu' in navigator) { providersToTry.push('webgpu'); - localSeparatorLog('navigator.gpu is available, trying WebGPU first.'); + log('navigator.gpu is available, trying WebGPU first.'); } else { - localSeparatorLog('navigator.gpu is not available. Falling back to CPU/wasm.'); + log('navigator.gpu is not available. Falling back to CPU/wasm.'); } providersToTry.push('wasm'); @@ -64,7 +64,7 @@ export class LocalOrtRuntimeManager { try { if (provider === 'webgpu' && ort.env?.webgpu) { ort.env.webgpu.powerPreference = 'high-performance'; - localSeparatorLog('Using WebGPU power preference high-performance.'); + log('Using WebGPU power preference high-performance.'); } const session = await ort.InferenceSession.create(modelData, { @@ -75,15 +75,15 @@ export class LocalOrtRuntimeManager { this.runtime = { provider, session }; this.currentModel = modelConfig.filename; this.onProviderChange(provider === 'wasm' ? 'cpu/wasm' : provider); - localSeparatorLog(`Using provider: ${provider}`); + log(`Using provider: ${provider}`); return this.runtime; } catch (error) { lastError = error; if (provider === 'webgpu') { - localSeparatorLog('WebGPU session creation failed. Falling back to CPU/wasm.', error); + log('WebGPU session creation failed. Falling back to CPU/wasm.', error); this.onProviderChange('cpu/wasm fallback'); } else { - localSeparatorLog(`Provider failed: ${provider}`, error); + log(`Provider failed: ${provider}`, error); } } } diff --git a/src/util/localSeparatorShared.ts b/src/util/local-separator/shared.ts similarity index 99% rename from src/util/localSeparatorShared.ts rename to src/util/local-separator/shared.ts index b6549f1..71119e3 100644 --- a/src/util/localSeparatorShared.ts +++ b/src/util/local-separator/shared.ts @@ -1,4 +1,4 @@ -import type { StereoChannels } from './localSeparatorTypes'; +import type { StereoChannels } from './types'; export function index4d(dims: number[], i0: number, i1: number, i2: number, i3: number): number { return (((i0 * dims[1] + i1) * dims[2] + i2) * dims[3]) + i3; diff --git a/src/util/localSeparatorTiming.ts b/src/util/local-separator/timing.ts similarity index 100% rename from src/util/localSeparatorTiming.ts rename to src/util/local-separator/timing.ts diff --git a/src/util/localSeparatorTypes.ts b/src/util/local-separator/types.ts similarity index 100% rename from src/util/localSeparatorTypes.ts rename to src/util/local-separator/types.ts