diff --git a/.claude/projects/-Users-am-Repositories-andre-michelle-openDAW/memory/feedback_no_as_any.md b/.claude/projects/-Users-am-Repositories-andre-michelle-openDAW/memory/feedback_no_as_any.md new file mode 100644 index 00000000..5a79216b --- /dev/null +++ b/.claude/projects/-Users-am-Repositories-andre-michelle-openDAW/memory/feedback_no_as_any.md @@ -0,0 +1,11 @@ +--- +name: Never use 'as any' +description: User strongly prohibits using 'as any' type casts - always use proper types instead +type: feedback +--- + +Never use `as any` in this codebase. Always define proper types. If a value needs a type that doesn't exist yet, add the field to the type definition (e.g., `id?: int` on UserOutput) rather than casting with `as any`. + +**Why:** The user considers `as any` a serious code quality violation. It bypasses the type system entirely and defeats the purpose of using TypeScript. + +**How to apply:** When you need to access a property that isn't on the current type, extend the type to include it. Never cast to `any` as a shortcut. diff --git a/packages/studio/core-processors/src/devices/midi-effects/SpielwerkDeviceProcessor.ts b/packages/studio/core-processors/src/devices/midi-effects/SpielwerkDeviceProcessor.ts index 805d0a43..879c5560 100644 --- a/packages/studio/core-processors/src/devices/midi-effects/SpielwerkDeviceProcessor.ts +++ b/packages/studio/core-processors/src/devices/midi-effects/SpielwerkDeviceProcessor.ts @@ -46,6 +46,7 @@ type UserEvent = | {readonly gate: false, readonly id: int, readonly position: ppqn, readonly pitch: byte} type UserOutput = { + readonly id?: int readonly position: ppqn readonly duration: ppqn readonly pitch: byte @@ -63,7 +64,7 @@ interface UserBlock { } interface UserProcessor { - process(block: UserBlock, events: IterableIterator): IterableIterator + process(block: UserBlock, events: Iterable): IterableIterator paramChanged?(label: string, value: number): void reset?(): void } @@ -182,6 +183,9 @@ export class SpielwerkDeviceProcessor extends EventProcessor implements MidiEffe cent: event.cent }) } else { + for (const released of this.#retainer.release(note => note.id === event.id)) { + yield NoteLifecycleEvent.stop(released, event.position) + } events.push({ gate: false, id: event.id, @@ -202,7 +206,7 @@ export class SpielwerkDeviceProcessor extends EventProcessor implements MidiEffe const userBlock: UserBlock = {from, to, bpm: 0, s0: 0, s1: 0, flags} try { let noteCount: int = 0 - for (const yielded of proc.process(userBlock, events[Symbol.iterator]())) { + for (const yielded of proc.process(userBlock, events)) { if (++noteCount > MAX_NOTES_PER_BLOCK) { this.#silence(`Note flood: exceeded ${MAX_NOTES_PER_BLOCK} notes per block`) return @@ -225,7 +229,7 @@ export class SpielwerkDeviceProcessor extends EventProcessor implements MidiEffe cent: yielded.cent ?? 0 }) } else { - yield* this.#emitNote(yielded) + yield* this.#emitNote(yielded, yielded.id) } } } catch (err) { @@ -303,9 +307,10 @@ export class SpielwerkDeviceProcessor extends EventProcessor implements MidiEffe this.#reportError(message) } - * #emitNote(note: ScheduledNote): IterableIterator { + * #emitNote(note: ScheduledNote, sourceId?: int): IterableIterator { const lifecycle = NoteLifecycleEvent.start(note.position, note.duration, note.pitch, note.velocity, note.cent) - this.#retainer.addAndRetain({...lifecycle}) - yield lifecycle + const entry = isDefined(sourceId) ? {...lifecycle, id: sourceId} : {...lifecycle} + this.#retainer.addAndRetain(entry) + yield entry } } diff --git a/packages/studio/core/src/EffectFactories.ts b/packages/studio/core/src/EffectFactories.ts index dc4dbb52..45b4b5b0 100644 --- a/packages/studio/core/src/EffectFactories.ts +++ b/packages/studio/core/src/EffectFactories.ts @@ -330,7 +330,7 @@ export namespace EffectFactories { export const NeuralAmp: EffectFactory = { defaultName: "Tone3000", defaultIcon: IconSymbol.Tone3000, - description: "Neural network-based amp modeling using NAM models", + description: "Access thousands of amps, pedals, and cabs captured with Neural Amp Modeler.", manualPage: DeviceManualUrls.NeuralAmp, separatorBefore: false, external: true,