Novolis Docs
novolis-audio / design.md

Design

dotnetaudiottsminiaudionovolis

Goals

  • Graphics-independent audio for games, tools, and Avalonia hosts.
  • Cross-platform via native novolis_audio (miniaudio) per RID, swapped like Raylib natives.
  • Manifest-driven codegen so interop and façades stay auditable and drift-checked.

Layers

IAudioEngine (Abstractions)
    ↑
MiniaudioAudioEngine (Runtime, hand-written)
    ↑
AudioDevice / Sound façades (*.g.cs)
    ↑
NovolisAudioNative [LibraryImport("novolis_audio")]
    ↑
novolis_audio.dll (C shim → miniaudio)

Native API

Stable C exports in codegen/vendor/novolis_audio/include/novolis_audio.h. The manifest lists only these symbols; step_03_verify_manifest ensures header parity.

Extending

  1. Add NA_API functions to novolis_audio.h and implement in novolis_audio.c.
  2. Add rows to NovolisAudioInteropManifest.cs and façade methods in NovolisAudioFacadesManifest.cs.
  3. Run dotnet run --project codegen/Novolis.Audio.Pipeline -- run generate.
  4. Commit manifests + *.g.cs.

Voice model catalog (manifest + codegen)

Bundled Piper models are not listed file-by-file in codegen. `NovolisAudioVoiceModelsManifest.cs` declares profile ids, repo folders, required top-level files, and sample rate; the pipeline verifies models/ and emits `VoiceModelCatalog.g.cs` (VoiceModelProfile, VoiceModelEngine, BundledVoiceModel, VoiceModelCatalog).

dotnet run --project codegen/Novolis.Audio.Pipeline -- run generate

Voice / PCM pipeline (separate from game SFX)

Game playback (Novolis.Audio / miniaudio) and voice/TTS use different package families:

IVoiceService (Novolis.Audio.Voice)
    ↑
IVoiceSynthesizer → IAudioEffectPipeline → IAudioPlayback / IWavEncoder
    ↑
PcmBuffer (Novolis.Audio.Core)
PackageRole
Novolis.Audio.CorePCM buffers, WAV read/write
Novolis.Audio.FiltersBand-limit and other PCM filters
Novolis.Audio.EffectsDynamics, gain, coloration, effect pipelines
Novolis.Audio.PlaybackPCM playback (null in CI)
Novolis.Audio.Voice.AbstractionsTTS contracts
Novolis.Audio.Voice.SherpaOnnxSherpa adapter (stub → null synth)
Novolis.Audio.Voice.PhraseologyICAO digit words
Novolis.Audio.VoiceSpeakAsync / WriteToFileAsync facade
Novolis.Audio.Voice.ProfilesNeutral base-voice archetypes (model + rate)
Novolis.Audio.Voice.DesignPreset drafts, validation, preview, GPR code export

Consumer entry for voice: Novolis.Audio.Voice (not bundled into the Novolis.Audio meta-package).

Compose archetype (Voice.Profiles) then optional delivery (phraseology + effect chain in your app, or copy Novolis.Dogfooding.Voice from dogfooding).

Parallel MP3 path: Voice.AzureSpeech returns user-owned Azure Speech MP3 bytes — not IVoiceSynthesizer. See the package README.

Live music: separate family — see live.md.

Speech input (STT)

ISpeechService (Novolis.Audio.Voice)
    ↑
IAudioCapture → IAudioEffectPipeline → IVoiceActivityDetector → ISpeechRecognizer
    ↑
PcmBuffer (Novolis.Audio.Core)
PackageRole
Novolis.Audio.PlaybackNaudioMicrophoneCapture, NullAudioCapture
Novolis.Audio.FiltersBandLimitEffect in mic/ATC chains
Novolis.Audio.EffectsInputSpeechEffects preprocessor chain
Novolis.Audio.Voice.AbstractionsListenAsync, STT/VAD contracts, SpeechModelCatalog
Novolis.Audio.Voice.SherpaOnnxSherpa Silero VAD + offline Whisper
Novolis.Audio.VoiceSpeechService, AddNovolisSpeech()

See speech-models.md for fetch/pack instructions.