fix: honor the soundfont -> baseUrl config

This commit is contained in:
Xiaohan-Tian
2026-04-17 16:18:33 -07:00
parent cb4bf59de1
commit 206fa6fdf9
+25 -19
View File
@@ -1,5 +1,6 @@
import { SAMPLER_CONSTANTS } from '../../constants/coreConstants'; import { SAMPLER_CONSTANTS } from '../../constants/coreConstants';
import { FLUIDR3_INSTRUMENT_MAP } from '../../constants/generalMidiConstants'; import { FLUIDR3_INSTRUMENT_MAP } from '../../constants/generalMidiConstants';
import { ConfigManager } from '../config/ConfigManager';
import * as Tone from 'tone'; import * as Tone from 'tone';
/** /**
@@ -12,7 +13,7 @@ export class KGToneBuffersPool {
// Map to store ToneAudioBuffers by instrument name // Map to store ToneAudioBuffers by instrument name
private bufferMap: Map<string, Tone.ToneAudioBuffers> = new Map(); private bufferMap: Map<string, Tone.ToneAudioBuffers> = new Map();
// Map to store loading promises to prevent duplicate loading and handle race conditions // Map to store loading promises to prevent duplicate loading and handle race conditions
private loadingPromises: Map<string, Promise<Tone.ToneAudioBuffers>> = new Map(); private loadingPromises: Map<string, Promise<Tone.ToneAudioBuffers>> = new Map();
@@ -89,16 +90,16 @@ export class KGToneBuffersPool {
try { try {
const buffers = await loadingPromise; const buffers = await loadingPromise;
// Cache the fully loaded buffers // Cache the fully loaded buffers
this.bufferMap.set(name, buffers); this.bufferMap.set(name, buffers);
console.log(`KGToneBuffersPool: Cached loaded buffers for ${name}`); console.log(`KGToneBuffersPool: Cached loaded buffers for ${name}`);
// Remove from loading promises since it's complete // Remove from loading promises since it's complete
this.loadingPromises.delete(name); this.loadingPromises.delete(name);
this.emitLoadingEvent({ type: 'end', instrument: name }); this.emitLoadingEvent({ type: 'end', instrument: name });
console.log(`[KGToneBuffersPool] end: Active load count: ${this.getActiveLoadCount()}`); console.log(`[KGToneBuffersPool] end: Active load count: ${this.getActiveLoadCount()}`);
return buffers; return buffers;
} catch (error) { } catch (error) {
// Remove failed loading promise so it can be retried // Remove failed loading promise so it can be retried
@@ -115,21 +116,26 @@ export class KGToneBuffersPool {
* Create ToneAudioBuffers for an instrument * Create ToneAudioBuffers for an instrument
*/ */
private async createToneAudioBuffers(name: string): Promise<Tone.ToneAudioBuffers> { private async createToneAudioBuffers(name: string): Promise<Tone.ToneAudioBuffers> {
const configManager = ConfigManager.instance();
if (!configManager.getIsInitialized()) {
await configManager.initialize();
}
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
try { try {
// Get instrument configuration from constants
const fluidConfig = SAMPLER_CONSTANTS.TONE_SAMPLERS.FLUID;
const instrumentName = name; const instrumentName = name;
if (!instrumentName) { if (!instrumentName) {
throw new Error(`Unknown instrument: ${name}`); throw new Error(`Unknown instrument: ${name}`);
} }
// Generate URL mapping for all keys from A0 to Bb7 const baseUrl = (ConfigManager.instance().get('general.soundfont.base_url') as string)
const urls = this.generateKeyUrls(fluidConfig.url, instrumentName); || SAMPLER_CONSTANTS.TONE_SAMPLERS.FLUID.url;
const urls = this.generateKeyUrls(baseUrl, instrumentName);
console.log(`Loading ToneAudioBuffers for ${name} (${instrumentName})...`); console.log(`Loading ToneAudioBuffers for ${name} (${instrumentName})...`);
// Create ToneAudioBuffers with onload callback // Create ToneAudioBuffers with onload callback
const buffers = new Tone.ToneAudioBuffers( const buffers = new Tone.ToneAudioBuffers(
urls, urls,
@@ -140,7 +146,7 @@ export class KGToneBuffersPool {
); );
// Don't cache until loading is complete - this will be handled in getToneAudioBuffers // Don't cache until loading is complete - this will be handled in getToneAudioBuffers
} catch (error) { } catch (error) {
console.error(`Error creating ToneAudioBuffers for ${name}:`, error); console.error(`Error creating ToneAudioBuffers for ${name}:`, error);
reject(error); reject(error);
@@ -158,23 +164,23 @@ export class KGToneBuffersPool {
// get the range of the instrument. // get the range of the instrument.
// TODO: make the sound library name configurable. // TODO: make the sound library name configurable.
const range = FLUIDR3_INSTRUMENT_MAP[instrumentName]?.pitchRange || [21, 108]; const range = FLUIDR3_INSTRUMENT_MAP[instrumentName]?.pitchRange || [21, 108];
// Note names in order (using flats instead of sharps where applicable) // Note names in order (using flats instead of sharps where applicable)
const noteNames = ['C', 'Db', 'D', 'Eb', 'E', 'F', 'Gb', 'G', 'Ab', 'A', 'Bb', 'B']; const noteNames = ['C', 'Db', 'D', 'Eb', 'E', 'F', 'Gb', 'G', 'Ab', 'A', 'Bb', 'B'];
// Generate keys from A0 to C8 (MIDI notes 21 to 108) // Generate keys from A0 to C8 (MIDI notes 21 to 108)
for (let midiNote = range[0]; midiNote <= range[1]; midiNote++) { for (let midiNote = range[0]; midiNote <= range[1]; midiNote++) {
const octave = Math.floor((midiNote - 12) / 12); const octave = Math.floor((midiNote - 12) / 12);
const noteIndex = (midiNote - 12) % 12; const noteIndex = (midiNote - 12) % 12;
const noteName = noteNames[noteIndex]; const noteName = noteNames[noteIndex];
const keyName = `${noteName}${octave}`; const keyName = `${noteName}${octave}`;
// Generate URL for this key // Generate URL for this key
urls[keyName] = `${baseUrl}${instrumentName}-mp3/${keyName}.mp3`; urls[keyName] = `${baseUrl}${instrumentName}-mp3/${keyName}.mp3`;
} }
console.log(`Generated ${Object.keys(urls).length} key URLs for ${instrumentName} from A0 to Bb7`); console.log(`Generated ${Object.keys(urls).length} key URLs for ${instrumentName} from A0 to Bb7`);
return urls; return urls;
} }
@@ -196,7 +202,7 @@ export class KGToneBuffersPool {
// Clear both maps // Clear both maps
this.bufferMap.clear(); this.bufferMap.clear();
this.loadingPromises.clear(); this.loadingPromises.clear();
console.log("KGToneBuffersPool disposed successfully"); console.log("KGToneBuffersPool disposed successfully");
} catch (error) { } catch (error) {
console.error("Error disposing KGToneBuffersPool:", error); console.error("Error disposing KGToneBuffersPool:", error);
@@ -207,7 +213,7 @@ export class KGToneBuffersPool {
* Preload buffers for specific instruments (optional performance optimization) * Preload buffers for specific instruments (optional performance optimization)
*/ */
public async preloadInstruments(instrumentNames: string[]): Promise<void> { public async preloadInstruments(instrumentNames: string[]): Promise<void> {
const loadPromises = instrumentNames.map(name => const loadPromises = instrumentNames.map(name =>
this.getToneAudioBuffers(name).catch(error => { this.getToneAudioBuffers(name).catch(error => {
console.warn(`Failed to preload ${name}:`, error); console.warn(`Failed to preload ${name}:`, error);
}) })