sdl-audio/audio.c

145 lines
4.4 KiB
C
Raw Normal View History

#include "audio.h"
#include "log.h"
#include <SDL2/SDL.h>
static SDL_AudioSpec recording_spec;
static SDL_AudioSpec playback_spec;
static SDL_AudioSpec received_recording_spec;
static SDL_AudioSpec received_playback_spec;
void audio_recording_callback(void* userdata, uint8_t* stream, int len);
void audio_playback_callback(void* userdata, uint8_t* stream, int len);
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_S32;
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_S32;
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_device_pause(audio_state* state, int is_recording, int is_pause)
{
int device_id = is_recording ? state->recording_device_id : state->playback_device_id;
SDL_PauseAudioDevice(device_id, is_pause);
}
void audio_device_close(audio_state* state, int is_recording)
{
int device_id = is_recording ? state->recording_device_id : state->playback_device_id;
SDL_CloseAudioDevice(device_id);
}
void audio_buffer_reset(audio_state* state)
{
memset(state->recording_buffer, 0, state->recording_buffer_size);
}
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) {
2024-10-17 03:16:41 +08:00
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;
2024-10-17 03:16:41 +08:00
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) {
2024-10-17 03:16:41 +08:00
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;
2024-10-17 03:16:41 +08:00
log_message(LOG_INFO, "Playback pos: %u/%u (%u)", state->recording_buffer_position, state->recording_buffer_size, len);
}