mindboost-rnbo-test-project/src/composables/BufferStore.ts

107 lines
2.8 KiB
TypeScript

// composables/useBufferStore.ts
import { db } from '../lib/db'
interface AudioNodeItem {
type: string;
node: AudioNode | null;
started?: boolean;
previousNodeName?:string;
nextNodeName?:string;
}
// Interner Buffer-Cache (nicht reaktiv)
const buffers = new Map<string, AudioBuffer>()
export const useBufferStore = () => ({
get: (id: string) => buffers.get(id),
set: (id: string, val: AudioBuffer) => buffers.set(id, val),
all: () => buffers
})
// Holt einen AudioBuffer aus dem Cache
export function getAudioBuffer(key: string): AudioBuffer | undefined {
return buffers.get(key)
}
// Holt oder erstellt einen BufferSourceNode mit geladenem AudioBuffer
export async function createBufferSource(
name: string,
audioContext: AudioContext
): Promise<AudioNodeItem> {
const store = useBufferStore()
const buffer = store.get(name)
if (!buffer) throw new Error(`Kein Buffer für "${name}" im Cache gefunden.`)
const source = audioContext.createBufferSource()
source.buffer = buffer
source.loop = true
return {
type: 'bufferSource',
node: source,
started: false,
}
}
// Speichert einen ArrayBuffer in IndexedDB unter gegebenem Namen
export async function saveBufferInIndexedDb(
fileName: string,
buffer: ArrayBuffer
): Promise<void> {
if (!db?.audiosources) {
console.warn('[BufferStore] Dexie DB nicht verfügbar')
return
}
try {
const existing = await db.audiosources.get({ name: fileName })
if (existing) {
await db.audiosources.update(existing.id!, { buffer })
console.info(`[BufferStore] Buffer für "${fileName}" aktualisiert`)
} else {
console.log("BUFFER", {buffer})
await db.audiosources.add({ name: fileName, buffer })
console.info(`[BufferStore] Buffer für "${fileName}" gespeichert`)
}
} catch (err) {
console.error('[BufferStore] Fehler beim Speichern in IndexedDB:', err)
}
}
// Lädt AudioBuffer aus IndexedDB oder via fetch
export async function fetchOrLoadBuffer(
name: string,
url: string,
audioContext: AudioContext
): Promise<AudioBuffer> {
const store = useBufferStore()
// Zuerst aus Cache
const cached = store.get(name)
if (cached) return cached
let arrayBuffer: ArrayBuffer
// Versuch aus IndexedDB
const existing = await db?.audiosources?.get({ name })
if (existing?.buffer) {
arrayBuffer = existing.buffer
console.info(`[BufferStore] Buffer für "${name}" aus IndexedDB geladen`)
} else {
// Fallback: fetch
const response = await fetch(url)
if (!response.ok) throw new Error(`Fetch fehlgeschlagen für ${url}`)
arrayBuffer = await response.arrayBuffer()
await saveBufferInIndexedDb(name, arrayBuffer)
}
// Dekodieren & speichern
const audioBuffer = await audioContext.decodeAudioData(arrayBuffer.slice(0))
store.set(name, audioBuffer)
return audioBuffer
}