refactor: move all localSeparator*.ts into a subfolder
This commit is contained in:
@@ -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 });
|
||||
|
||||
@@ -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 ────────────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ vi.mock('../../../util/localLLMModelManager', () => ({
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock('../../../util/localSeparatorModelCache', () => ({
|
||||
vi.mock('../../../util/local-separator/modelCache', () => ({
|
||||
LocalSeparatorModelCache: localSeparatorModelCacheMock,
|
||||
}));
|
||||
|
||||
|
||||
@@ -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<string>(LOCAL_LLM_PROVIDER_KEY);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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';
|
||||
@@ -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;
|
||||
@@ -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<{
|
||||
@@ -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' });
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
Reference in New Issue
Block a user