#include <SDL2/SDL.h>
#include <stdio.h>
#include <stdlib.h>

#define SAMPLE_RATE 44100
#define AMPLITUDE 30000
#define TONE_HZ 440
#define SECONDS_TO_PLAY 2

// Structure to pass user data to the audio callback
typedef struct {
    int sample_index;
    int tone_volume;
    int wave_period;
    int half_wave_period;
} AudioData;

// The audio callback function that generates the square wave
void audio_callback(void *user_data, Uint8 *raw_buffer, int bytes_to_write) {
    AudioData *audio_data = (AudioData *)user_data;
    // Cast the raw buffer to the appropriate sample format (Sint16 for 16-bit audio)
    Sint16 *sample_buffer = (Sint16 *)raw_buffer;
    int samples_to_write = bytes_to_write / sizeof(Sint16);

    for (int i = 0; i < samples_to_write; i++, audio_data->sample_index++) {
        Sint16 sample_value = audio_data->tone_volume;

        // Generate a square wave: positive for the first half of the period, negative for the second half
        if ((audio_data->sample_index / audio_data->half_wave_period) % 2) {
            sample_value = -audio_data->tone_volume;
        }

        // Write the sample to the buffer (assuming mono output, or same for left/right)
        *sample_buffer++ = sample_value;
    }
}

int main(int argc, char *argv[]) {
    // Initialize SDL2 Audio subsystem
    if (SDL_Init(SDL_INIT_AUDIO) != 0) {
        SDL_Log("Failed to initialize SDL: %s", SDL_GetError());
        return 1;
    }

    AudioData audio_data;
    audio_data.sample_index = 0;
    audio_data.tone_volume = AMPLITUDE;
    audio_data.wave_period = SAMPLE_RATE / TONE_HZ;
    audio_data.half_wave_period = audio_data.wave_period / 2;

    SDL_AudioSpec want, have;
    SDL_zero(want);

    want.freq = SAMPLE_RATE;        // Number of samples per second
    want.format = AUDIO_S16SYS;     // 16-bit signed little-endian samples
    want.channels = 1;              // Mono output
    want.samples = 2048;            // Audio buffer size (power of 2 is typical)
    want.callback = audio_callback; // Function SDL calls to get more audio
    want.userdata = &audio_data;    // Pass our custom struct to the callback

    // Open the audio device
    SDL_AudioDeviceID device_id = SDL_OpenAudioDevice(NULL, 0, &want, &have, 0);
    if (device_id == 0) {
        SDL_LogError(SDL_LOG_CATEGORY_AUDIO, "Failed to open audio: %s", SDL_GetError());
        SDL_Quit();
        return 1;
    }

    // Start playing sound (unpause the device)
    SDL_PauseAudioDevice(device_id, 0);

    // Keep the program running for a specified duration to allow the sound to play
    printf("Playing %d Hz square wave for %d seconds...\n", TONE_HZ, SECONDS_TO_PLAY);
    SDL_Delay(SECONDS_TO_PLAY * 1000);

    // Clean up
    SDL_PauseAudioDevice(device_id, 1); // Stop playing sound
    SDL_CloseAudioDevice(device_id);    // Close the audio device
    SDL_Quit();

    return 0;
}
