switched to miniaudio since libsoundio is unmantained
This commit is contained in:
parent
dc0b7e94b4
commit
4a798951c3
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -1,3 +0,0 @@
|
|||||||
[submodule "extern/libsoundio"]
|
|
||||||
path = extern/libsoundio
|
|
||||||
url = https://github.com/andrewrk/libsoundio.git
|
|
||||||
@ -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
extern/libsoundio
vendored
@ -1 +0,0 @@
|
|||||||
Subproject commit 49a1f78b50eb0f5a49d096786a95a93874a2592a
|
|
||||||
95649
extern/miniaudio/miniaudio.h
vendored
Normal file
95649
extern/miniaudio/miniaudio.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
161
src/main.c
161
src/main.c
@ -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))) {
|
|
||||||
fprintf(stderr, "%s\n", soundio_strerror(err));
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
frames_left -= frame_count;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
// If we ran out early, zero the rest (silence).
|
||||||
int err;
|
for (ma_uint32 i = framesToWrite; i < frameCount; i++) {
|
||||||
struct SoundIo *soundio = soundio_create();
|
for (ma_uint32 ch = 0; ch < s->channels; ch++) {
|
||||||
if (!soundio) {
|
output[i * s->channels + ch] = 0.0f;
|
||||||
fprintf(stderr, "out of memory\n");
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s->frames_left -= framesToWrite;
|
||||||
|
|
||||||
|
// Stop after the beep finishes.
|
||||||
|
if (s->frames_left == 0) {
|
||||||
|
ma_device_stop(dev); // safe to request stop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
const double freq = 440.0;
|
||||||
|
const ma_uint32 sampleRate = 48000;
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user