// AX audio mixer. // To add sound to your OS, you need to implement this small interface. #pragma once #include namespace Flipper { enum class AudioSampleRate { Rate_32000 = 0, Rate_48000, }; enum class AxChannel { AudioDma = 0, DvdAudio, Max, }; class AudioMixer; class AudioRing { AudioMixer* mixer; // Accumulate frameSize bytes in the circular buffer. // When we have accumulated, lock the DirectSound buffer and emit frameSize bytes there. // The frameSize size is not very large and not very small. // It should not be longer than 1 PAL / NTSC video frame, but not less than 1/3 video frame. static const size_t maxFrames = 16; static const size_t frameSize = 0x1000; // Audio frame size static const size_t ringSize = maxFrames * frameSize; uint8_t* ringBuffer = nullptr; size_t ringWritePtr = 0; size_t ringReadPtr = 0; size_t CurrentSize(); uint8_t FetchByte(); void EmitSound(); LPDIRECTSOUNDBUFFER DSBuffer = nullptr; bool enabled = false; size_t frameCounter = 0; void DumpDSBuffer(); void DumpRing(); void WaitBufferOverflow(void); size_t framesPerEmit = maxFrames / 2; int bufferMode = DSBPLAY_LOOPING; public: AudioRing(AudioMixer* parentInst); ~AudioRing(); void Enable(bool enable); bool IsEnabled() { return enabled; } void SetSampleRate(AudioSampleRate value); void PushBytes(uint8_t* sampleData, size_t sampleDataSize); }; class AudioMixer { friend AudioRing; AudioRing** Sources = nullptr; static const size_t numSources = 2; LPDIRECTSOUND8 lpds = nullptr; LPDIRECTSOUNDBUFFER PrimaryBuffer = nullptr; public: AudioMixer(HWConfig* config); ~AudioMixer(); void Enable(AxChannel channel, bool enable); bool IsEnabled(AxChannel channel); void SetSampleRate(AxChannel channel, AudioSampleRate value); void PushBytes(AxChannel channel, uint8_t* sampleData, size_t sampleDataSize); }; }