#include "audio.h" #include "log.h" #include static SDL_AudioSpec recording_spec; static SDL_AudioSpec playback_spec; static SDL_AudioSpec received_recording_spec; static SDL_AudioSpec received_playback_spec; int audio_init(audio_state* state) { state->recording_device_id = 0; state->playback_device_id = 0; SDL_zero(recording_spec); recording_spec.freq = 44100; recording_spec.format = AUDIO_S16; recording_spec.channels = 2; recording_spec.samples = 4096; recording_spec.callback = audio_recording_callback; recording_spec.userdata = state; SDL_zero(playback_spec); playback_spec.freq = 44100; playback_spec.format = AUDIO_S16; playback_spec.channels = 2; playback_spec.samples = 4096; playback_spec.callback = audio_playback_callback; playback_spec.userdata = state; state->recording_buffer = NULL; state->recording_buffer_size = 0; state->recording_buffer_position = 0; return 1; } int audio_recording_init(audio_state* state, int index) { SDL_AudioDeviceID device_id = SDL_OpenAudioDevice(SDL_GetAudioDeviceName(index, 1), 1, &recording_spec, &received_recording_spec, SDL_AUDIO_ALLOW_FORMAT_CHANGE); log_message(LOG_INFO, "Recording Device: %s", SDL_GetAudioDeviceName(index, 1)); if (!device_id) { log_message(LOG_INFO, "Failed to open recording device! SDL Error: %s", SDL_GetError()); return 0; } state->recording_device_id = device_id; unsigned int bytes_per_sample = received_recording_spec.channels * (SDL_AUDIO_BITSIZE(received_recording_spec.format)/8); unsigned int bytes_per_second = received_recording_spec.freq * bytes_per_sample; state->recording_buffer_size = MAX_RECORDING_SECONDS * bytes_per_second; if (state->recording_buffer) free(state->recording_buffer); state->recording_buffer = malloc(state->recording_buffer_size); memset(state->recording_buffer, 0, state->recording_buffer_size); return 1; } void audio_destroy(audio_state* state) { free(state->recording_buffer); SDL_CloseAudioDevice(state->recording_device_id); SDL_CloseAudioDevice(state->playback_device_id); } int audio_playback_init(audio_state* state) { if (!state->recording_buffer) { log_message(LOG_INFO, "Audio buffer not initialized"); return 0; } SDL_AudioDeviceID device_id = SDL_OpenAudioDevice(NULL, 0, &playback_spec, &received_playback_spec, SDL_AUDIO_ALLOW_FORMAT_CHANGE); if (!device_id) { log_message(LOG_INFO, "Failed to open playback device! SDL Error: %s", SDL_GetError()); return 0; } state->playback_device_id = device_id; return 1; } void audio_recording_callback(void* userdata, uint8_t* stream, int len) { audio_state* state = userdata; int space_left = state->recording_buffer_size - state->recording_buffer_position; if (space_left <= 0) { log_message(LOG_INFO, "Stopping recording ID: %i", state->recording_device_id); SDL_PauseAudioDevice(state->recording_device_id, 1); return; } if (len > space_left) { len = space_left; } memcpy(&state->recording_buffer[state->recording_buffer_position], stream, len); state->recording_buffer_position += len; log_message(LOG_INFO, "Record pos: %u/%u (%u)", state->recording_buffer_position, state->recording_buffer_size, len); } void audio_playback_callback(void* userdata, uint8_t* stream, int len) { audio_state* state = userdata; int space_left = state->recording_buffer_size - state->recording_buffer_position; if (space_left <= 0) { log_message(LOG_INFO, "Stopping playback ID: %i", state->recording_device_id); SDL_PauseAudioDevice(state->playback_device_id, 1); return; } if (len > space_left) { len = space_left; } memcpy(stream, &state->recording_buffer[state->recording_buffer_position], len); state->recording_buffer_position += len; log_message(LOG_INFO, "Playback pos: %u/%u (%u)", state->recording_buffer_position, state->recording_buffer_size, len); }