// // Created by bruno on 13. 7. 2026. // #ifndef AUDIOCODER_DECODER_H #define AUDIOCODER_DECODER_H #define DECODER_SAMPLE_HISTORY 262144 #define MAX_FSK_TONES 32 #include #include #include #include "goertzel.h" typedef enum { RX_SEARCH, RX_SYNC, RX_MAGIC, RX_DATA } RxState; typedef enum { PKT_WAIT_PREAMBLE, PKT_WAIT_MAGIC, PKT_WAIT_LENGTH, PKT_WAIT_DATA, PKT_WAIT_CRC1, PKT_WAIT_CRC2 } PacketState; typedef struct { uint8_t bitsPerSymbol; uint8_t toneCount; uint16_t startFreq; uint16_t endFreq; uint16_t dataSpacing; uint16_t clock0; uint16_t clock1; uint8_t magicBuffer[16]; uint32_t magicIndex; uint32_t preambleCount; uint8_t lostClockCount; uint8_t goodClockCount; uint32_t symbolSamples; uint32_t sampleRate; uint32_t sampleCount; float sampleHistory[DECODER_SAMPLE_HISTORY]; uint32_t sampleHistoryWrite; uint32_t sampleHistoryCount; uint64_t totalSamples; Goertzel tones[MAX_FSK_TONES + 2]; float energies[MAX_FSK_TONES + 2]; uint8_t currentByte; uint8_t bitIndex; uint8_t buffer[1024*1024*8]; uint32_t bufferSize; bool lastClock; float maxEnergy; float clockEnergy0; float clockEnergy1; float clockRatio; uint8_t lastDecodedByte; int bestSyncScore; int bestSyncPhase; RxState rxState; PacketState packetState; bool expectedClock; float lastClockEnergy; uint32_t goodClocks; uint32_t syncIndex; uint32_t badClocks; uint64_t phaseSearchStart; uint32_t phaseWait; int phaseOffset; bool phaseSearchReady; uint32_t searchOffset; uint32_t syncOffset; uint8_t clockHistory; uint8_t clockCount; bool locked; SDL_Renderer *renderer; } Decoder; void decoder_init( Decoder *dec ); void decoder_process( Decoder *dec, float *samples, uint32_t count ); void decoder_rebuild_tones( Decoder *dec ); extern Decoder decoder; extern SDL_AudioDeviceID inputDev; extern const uint8_t syncBytes[4]; // Internal audio bus for loopback #define INTERNAL_BUFFER_SIZE 262144 extern float internalBusSamples[INTERNAL_BUFFER_SIZE]; extern volatile uint32_t internalBusWrite; extern volatile uint32_t internalBusRead; void initAudioDecoder(SDL_Renderer *renderer); void decoder_reset_rx(Decoder *dec); #endif //AUDIOCODER_DECODER_H