/* // Created by bruno on 16.2.2025. */ #include "audio.h" int pcm_buffer_empty(PcmVoice *pcm) { return pcm->head == pcm->tail; } int pcm_buffer_full(PcmVoice *pcm) { return ((pcm->tail + 1) % PCM_BUFFER_SIZE) == pcm->head; } void pcm_buffer_push(PcmVoice *pcm, uint16_t sample) { if (!pcm_buffer_full(pcm)) { pcm->buffer[pcm->tail] = sample; pcm->tail = (pcm->tail + 1) % PCM_BUFFER_SIZE; } } uint16_t pcm_buffer_pop(PcmVoice *pcm) { if (!pcm_buffer_empty(pcm)) { uint16_t sample = pcm->buffer[pcm->head]; pcm->head = (pcm->head + 1) % PCM_BUFFER_SIZE; return sample; } return 0; } void audio_callback(void *userdata, Uint8 *stream, int len) { AudioData *audio = (AudioData *) userdata; int samples = len / sizeof(float); for (int i = 0; i < samples; i++) { float mix = 0.0f; int activeVoices = 0; for (int v = 0; v < NUM_SYNTH_VOICES; v++) { SynthVoice *voice = &audio->synthVoices[v]; if (voice->volume == 0 || voice->frequency == 0) continue; float sample = 0.0f; float t = (float) voice->phase / 255.0f * 2.0f - 1.0f; switch (voice->waveform) { default: case WAVE_SINE: sample = sinf(voice->phase * 2.0f * M_PI / 256.0f); break; case WAVE_SQUARE: sample = (t >= 0.0f) ? 1.0f : -1.0f; break; case WAVE_SAWTOOTH: sample = t; break; case WAVE_TRIANGLE: sample = (t < 0) ? -t : t; break; case WAVE_NOISE: sample = ((float) rand() / RAND_MAX) * 2.0f - 1.0f; break; } voice->phase += (uint8_t) ((voice->frequency * 256) / SAMPLE_RATE); mix += sample * (voice->volume / 255.0f); activeVoices++; } PcmVoice *pcm = &audio->pcmVoice; if (pcm->volume > 0 && !pcm_buffer_empty(pcm)) { float pcmSample = pcm_buffer_pop(pcm) / 65535.0f; mix += pcmSample * (pcm->volume / 255.0f); activeVoices++; } ((float *) stream)[i] = (activeVoices > 0) ? mix / activeVoices : 0.0f; } }