switched to miniaudio since libsoundio is unmantained

This commit is contained in:
plky 2026-01-15 00:04:42 -05:00
parent dc0b7e94b4
commit 4a798951c3
5 changed files with 95739 additions and 102 deletions

3
.gitmodules vendored
View File

@ -1,3 +0,0 @@
[submodule "extern/libsoundio"]
path = extern/libsoundio
url = https://github.com/andrewrk/libsoundio.git

View File

@ -9,25 +9,30 @@ set(C_STANDARD_REQUIRED True)
add_executable(${PROJECT_NAME} src/main.c) add_executable(${PROJECT_NAME} src/main.c)
# TODO: set with if checks # Pull all submodules if haven't already
set(ENABLE_ALSA ON CACHE BOOL "") # find_package(Git QUIET)
set(ENABLE_PULSEAUDIO OFF CACHE BOOL "") # if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git")
set(ENABLE_JACK OFF CACHE BOOL "") # option(GIT_SUBMODULE "Check submodules during build" ON)
set(ENABLE_COREAUDIO OFF CACHE BOOL "") # if(GIT_SUBMODULE)
set(ENABLE_WASAPI OFF CACHE BOOL "") # message(STATUS "Submodule update")
set(BUILD_EXAMPLE_PROGRAMS OFF CACHE BOOL "") # execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive
# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
# RESULT_VARIABLE GIT_SUBMOD_RESULT)
# if(NOT GIT_SUBMOD_RESULT EQUAL "0")
# message(FATAL_ERROR "git submodule update --init --recursive failed with ${GIT_SUBMOD_RESULT}, please checkout submodules")
# endif()
# endif()
# endif()
#
# if(NOT EXISTS "${PROJECT_SOURCE_DIR}/extern/libsoundio/CMakeLists.txt")
# message(FATAL_ERROR "The submodules were not downloaded! GIT_SUBMODULE was turned off or failed. Please update submodules and try again.")
# endif()
set(BUILD_DYNAMIC_LIBS ON CACHE BOOL "" FORCE) set(BUILD_DYNAMIC_LIBS ON CACHE BOOL "" FORCE)
set(BUILD_STATIC_LIBS ON CACHE BOOL "" FORCE) set(BUILD_STATIC_LIBS ON CACHE BOOL "" FORCE)
# libsoundio # libsoundio
add_subdirectory("${CMAKE_SOURCE_DIR}/extern/libsoundio") target_include_directories(${PROJECT_NAME} PRIVATE "${CMAKE_SOURCE_DIR}/extern/miniaudio")
target_include_directories(${PROJECT_NAME} PRIVATE "${CMAKE_SOURCE_DIR}/extern/libsoundio")
target_link_libraries(${PROJECT_NAME} PRIVATE
$<$<CONFIG:Debug>:libsoundio_shared>
$<$<CONFIG:Release>:libsoundio_static>
)
# math # math
target_link_libraries(${PROJECT_NAME} PRIVATE m) target_link_libraries(${PROJECT_NAME} PRIVATE m)

1
extern/libsoundio vendored

@ -1 +0,0 @@
Subproject commit 49a1f78b50eb0f5a49d096786a95a93874a2592a

95649
extern/miniaudio/miniaudio.h vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,108 +1,95 @@
#include <soundio/soundio.h> // beep.c
// Build (Linux/macOS): cc beep.c -lm -o beep
// Build (Windows MSVC): cl /O2 beep.c
#define MINIAUDIO_IMPLEMENTATION
#include "miniaudio.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h> #include <math.h>
#include <stdint.h>
#include <stdio.h>
static const float PI = 3.1415926535f; typedef struct {
static float seconds_offset = 0.0f; double phase;
static void write_callback(struct SoundIoOutStream *outstream, double phase_inc;
int frame_count_min, int frame_count_max) uint32_t frames_left;
ma_uint32 channels;
} beep_state;
static void data_callback(ma_device* dev, void* out, const void* in, ma_uint32 frameCount)
{ {
const struct SoundIoChannelLayout *layout = &outstream->layout; (void)in;
float float_sample_rate = outstream->sample_rate; beep_state* s = (beep_state*)dev->pUserData;
float seconds_per_frame = 1.0f / float_sample_rate; float* output = (float*)out;
struct SoundIoChannelArea *areas;
int frames_left = frame_count_max;
int err;
while (frames_left > 0) { ma_uint32 framesToWrite = frameCount;
int frame_count = frames_left; if (s->frames_left < framesToWrite) framesToWrite = s->frames_left;
if ((err = soundio_outstream_begin_write(outstream, &areas, &frame_count))) { for (ma_uint32 i = 0; i < framesToWrite; i++) {
fprintf(stderr, "%s\n", soundio_strerror(err)); float sample = (float)sin(s->phase) * 0.2f; // volume
exit(1); s->phase += s->phase_inc;
}
if (!frame_count) // keep phase bounded (optional)
break; if (s->phase >= (2.0 * M_PI)) s->phase -= (2.0 * M_PI);
float pitch = 440.0f; for (ma_uint32 ch = 0; ch < s->channels; ch++) {
float radians_per_second = pitch * 2.0f * PI; output[i * s->channels + ch] = sample;
for (int frame = 0; frame < frame_count; frame += 1) {
float sample = sin((seconds_offset + frame * seconds_per_frame) * radians_per_second);
for (int channel = 0; channel < layout->channel_count; channel += 1) {
float *ptr = (float*)(areas[channel].ptr + areas[channel].step * frame);
*ptr = sample;
} }
} }
seconds_offset = fmod(seconds_offset + seconds_per_frame * frame_count, 1.0);
if ((err = soundio_outstream_end_write(outstream))) { // If we ran out early, zero the rest (silence).
fprintf(stderr, "%s\n", soundio_strerror(err)); for (ma_uint32 i = framesToWrite; i < frameCount; i++) {
exit(1); for (ma_uint32 ch = 0; ch < s->channels; ch++) {
output[i * s->channels + ch] = 0.0f;
}
} }
frames_left -= frame_count; s->frames_left -= framesToWrite;
// Stop after the beep finishes.
if (s->frames_left == 0) {
ma_device_stop(dev); // safe to request stop
} }
} }
int main(int argc, char **argv) { int main(void)
int err; {
struct SoundIo *soundio = soundio_create(); const double freq = 440.0;
if (!soundio) { const ma_uint32 sampleRate = 48000;
fprintf(stderr, "out of memory\n"); const double durationSec = 1.0;
beep_state s = {0};
s.phase = 0.0;
s.phase_inc = (2.0 * M_PI * freq) / (double)sampleRate;
s.frames_left = (uint32_t)(durationSec * (double)sampleRate);
ma_device_config cfg = ma_device_config_init(ma_device_type_playback);
cfg.playback.format = ma_format_f32;
cfg.playback.channels = 2;
cfg.sampleRate = sampleRate;
cfg.dataCallback = data_callback;
cfg.pUserData = &s;
ma_device dev;
if (ma_device_init(NULL, &cfg, &dev) != MA_SUCCESS) {
fprintf(stderr, "Failed to init audio device\n");
return 1; return 1;
} }
if ((err = soundio_connect(soundio))) { s.channels = dev.playback.channels; // in case backend adjusts
fprintf(stderr, "error connecting: %s\n", soundio_strerror(err));
if (ma_device_start(&dev) != MA_SUCCESS) {
fprintf(stderr, "Failed to start audio device\n");
ma_device_uninit(&dev);
return 1; return 1;
} }
soundio_flush_events(soundio); // Wait until callback stops the device.
while (ma_device_is_started(&dev)) {
int default_out_device_index = soundio_default_output_device_index(soundio); ma_sleep(10);
if (default_out_device_index < 0) {
fprintf(stderr, "no output device found\n");
return 1;
} }
struct SoundIoDevice *device = soundio_get_output_device(soundio, default_out_device_index); ma_device_uninit(&dev);
if (!device) {
fprintf(stderr, "out of memory\n");
return 1;
}
fprintf(stderr, "Output device: %s\n", device->name);
struct SoundIoOutStream *outstream = soundio_outstream_create(device);
if (!outstream) {
fprintf(stderr, "out of memory\n");
return 1;
}
outstream->format = SoundIoFormatFloat32NE;
outstream->write_callback = write_callback;
if ((err = soundio_outstream_open(outstream))) {
fprintf(stderr, "unable to open device: %s", soundio_strerror(err));
return 1;
}
if (outstream->layout_error)
fprintf(stderr, "unable to set channel layout: %s\n", soundio_strerror(outstream->layout_error));
if ((err = soundio_outstream_start(outstream))) {
fprintf(stderr, "unable to start device: %s\n", soundio_strerror(err));
return 1;
}
for (;;)
soundio_wait_events(soundio);
soundio_outstream_destroy(outstream);
soundio_device_unref(device);
soundio_destroy(soundio);
return 0; return 0;
} }