Skip to content

Commit

Permalink
now compiles on windows with MSVC, need to add testing
Browse files Browse the repository at this point in the history
  • Loading branch information
peterino2 committed Jul 10, 2023
1 parent 530d7b5 commit 2a3505b
Show file tree
Hide file tree
Showing 15 changed files with 203 additions and 116 deletions.
4 changes: 3 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ set(LIBSOUNDIO_VERSION_PATCH 0)
set(LIBSOUNDIO_VERSION "${LIBSOUNDIO_VERSION_MAJOR}.${LIBSOUNDIO_VERSION_MINOR}.${LIBSOUNDIO_VERSION_PATCH}")
message("Configuring libsoundio version ${LIBSOUNDIO_VERSION}")


if(NOT SOUNDIO_STATIC_LIBNAME)
set(SOUNDIO_STATIC_LIBNAME soundio)
endif()
Expand Down Expand Up @@ -208,7 +209,6 @@ if(MSVC)
set(EXAMPLE_CFLAGS "/W4")
set(TEST_CFLAGS "${LIB_CFLAGS}")
set(TEST_LDFLAGS " ")
set(LIBM " ")
else()
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Werror -pedantic")
set(LIB_CFLAGS "-std=c11 -fvisibility=hidden -Wall -Werror=strict-prototypes -Werror=old-style-definition -Werror=missing-prototypes -D_REENTRANT -D_POSIX_C_SOURCE=200809L -Wno-missing-braces")
Expand Down Expand Up @@ -391,3 +391,5 @@ message(
"* CoreAudio (optional) : ${STATUS_COREAUDIO}\n"
"* WASAPI (optional) : ${STATUS_WASAPI}\n"
)


4 changes: 4 additions & 0 deletions example/sio_microphone.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,14 @@ static int prioritized_sample_rates[] = {
};


#ifndef _MSC_VER
__attribute__ ((cold))
__attribute__ ((noreturn))
__attribute__ ((format (printf, 1, 2)))
static void panic(const char *format, ...) {
#else
__declspec(noreturn) static void panic(const char *format, ...) {
#endif
va_list ap;
va_start(ap, format);
vfprintf(stderr, format, ap);
Expand Down
6 changes: 6 additions & 0 deletions example/sio_record.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,13 @@
#include <string.h>
#include <math.h>
#include <errno.h>

#ifndef _MSC_VER
#include <unistd.h>
#else
#include <Windows.h>
#define sleep Sleep
#endif

struct RecordContext {
struct SoundIoRingBuffer *ring_buffer;
Expand Down
47 changes: 26 additions & 21 deletions src/atomics.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ struct SoundIoAtomicBool {
};

struct SoundIoAtomicFlag {
char x;
long x;
};

struct SoundIoAtomicULong {
Expand All @@ -172,34 +172,39 @@ struct SoundIoAtomicULong {
// and gcc support.
//
// guess this is why c11 in msvc can't implement stdatomic.h right now
#define SOUNDIO_ATOMIC_LOAD_BOOL(a) *((volatile char*) &(a.x))
#define SOUNDIO_ATOMIC_LOAD_BOOL(a) (char) *((volatile char*) &(a.x))
#define SOUNDIO_ATOMIC_STORE_BOOL(a, value) (*((volatile char*) &(a.x))) = value
#define SOUNDIO_ATOMIC_FETCH_ADD_BOOL(a, delta) _InterlockedExchangeAdd8((char*) (&a.x), delta)
#define SOUNDIO_ATOMIC_EXCHANGE_BOOL(a, value) _InterlockedExchange8((char*) (&a.x), value)
#define SOUNDIO_ATOMIC_FETCH_ADD_BOOL(a, delta) _InterlockedExchangeAdd8((volatile char*) (&a.x), delta)
#define SOUNDIO_ATOMIC_EXCHANGE_BOOL(a, value) _InterlockedExchange8((volatile char*) (&a.x), value)

#define SOUNDIO_ATOMIC_LOAD_INT(a) *((volatile int*) &(a.x))
#define SOUNDIO_ATOMIC_LOAD_INT(a) (int) *((volatile int*) &(a.x))
#define SOUNDIO_ATOMIC_STORE_INT(a, value) *((volatile int*) &(a.x)) = value
#define SOUNDIO_ATOMIC_FETCH_ADD_INT(a, delta) _InterlockedExchangeAdd32((int*) (&a.x), delta)
#define SOUNDIO_ATOMIC_EXCHANGE_INT(a, value) _InterlockedExchange32((int*) (&a.x), value)
#define SOUNDIO_ATOMIC_FETCH_ADD_INT(a, delta) _InterlockedExchangeAdd((volatile LONG*) (&a.x), delta)
#define SOUNDIO_ATOMIC_EXCHANGE_INT(a, value) _InterlockedExchange((volatile LONG*) (&a.x), value)

#define SOUNDIO_ATOMIC_LOAD_LONG(a) SoundIoMSVCLoadLong(&a)
#define SOUNDIO_ATOMIC_STORE_LONG(a, value) SoundIoMSVCStoreLong(&a, value)
#define SOUNDIO_ATOMIC_FETCH_ADD_LONG(a, delta) _InterlockedExchange32Add((long*) (&a.x), delta)
#define SOUNDIO_ATOMIC_EXCHANGE_LONG(a, value) _InterlockedExchange32((long*) (&a.x), delta)
#define SOUNDIO_ATOMIC_STORE_LONG(a, value) SoundIoMSVCStoreLong((struct SoundIoAtomicLong*) &a, value)
#define SOUNDIO_ATOMIC_FETCH_ADD_LONG(a, delta) _InterlockedExchangeAdd64((long*) (&a.x), delta)
#define SOUNDIO_ATOMIC_EXCHANGE_LONG(a, value) _InterlockedExchange64((long*) (&a.x), delta)

#define SOUNDIO_ATOMIC_LOAD_ULONG(a) SoundIoMSVCLoadLong(&a)
#define SOUNDIO_ATOMIC_STORE_ULONG(a, value) SoundIoMSVCStoreLong((struct SoundIoAtomicULong*) &a, value)
#define SOUNDIO_ATOMIC_FETCH_ADD_ULONG(a, delta) _InterlockedExchangeAdd64((volatile long*) (&a.x), delta)
#define SOUNDIO_ATOMIC_EXCHANGE_ULONG(a, value) _InterlockedExchange64((volatile long*) (&a.x), delta)

#define SOUNDIO_ATOMIC_LOAD_ULONG(a) SoundIoMSVCLoadLong((unsigned long*)&a)
#define SOUNDIO_ATOMIC_STORE_ULONG(a, value) SoundIoMSVCStoreLong((unsigned long) &a, value)
#define SOUNDIO_ATOMIC_FETCH_ADD_ULONG(a, delta) _InterlockedExchange64Add((long*) (&a.x), delta)
#define SOUNDIO_ATOMIC_EXCHANGE_ULONG(a, value) _InterlockedExchange64((long*) (&a.x), delta)
#define SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(a) _interlockedbittestandset(&a.x, 1)
#define SOUNDIO_ATOMIC_FLAG_CLEAR(a) _interlockedbittestandset(&a.x, 0)
#define SOUNDIO_ATOMIC_FLAG_INIT {1}

#define SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(a) _interlockedbittestandset(a, 1)
#define SOUNDIO_ATOMIC_FLAG_CLEAR(a) _interlockedbittestandset(a, 0)
#define SOUNDIO_ATOMIC_FLAG_INIT 1
#define SOUNDIO_ATOMIC_LOAD(a) error
#define SOUNDIO_ATOMIC_FETCH_ADD(a, delta) error
#define SOUNDIO_ATOMIC_STORE(a, value) error
#define SOUNDIO_ATOMIC_EXCHANGE(a, value) error

long SoundIoMSVCLoadLong(SoundIoAtomicLong* a)
static long SoundIoMSVCLoadLong(struct SoundIoAtomicLong* a)
{
#if SOUNDIO_MSVC_POINTER_SIZE == 8
return ((volatile long*) a)->x;
return ((volatile struct SoundIoAtomicLong*) a)->x;
#else

uint64_t result;
Expand All @@ -216,10 +221,10 @@ long SoundIoMSVCLoadLong(SoundIoAtomicLong* a)
#endif
}

void SoundIoMSVCStoreLong(SoundIoAtomicLong* a, long value)
static void SoundIoMSVCStoreLong(struct SoundIoAtomicLong* a, long value)
{
#if SOUNDIO_MSVC_POINTER_SIZE == 8
((volatile long*) a)->x = value;
((volatile struct SoundIoAtomicLong*) a)->x = value;
#else
__asm {
mov esi, object;
Expand Down
2 changes: 1 addition & 1 deletion src/channel_layout.c
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ enum SoundIoChannelId soundio_parse_channel_id(const char *str, int str_len) {
const char *alias = channel_names[id][i];
if (!alias)
break;
int alias_len = strlen(alias);
int alias_len = (int) strlen(alias);
if (soundio_streql(alias, alias_len, str, str_len))
return (enum SoundIoChannelId)id;
}
Expand Down
58 changes: 31 additions & 27 deletions src/dummy.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
#include <stdio.h>
#include <string.h>

#if _MSC_VER
#define strdup _strdup
#endif

static void playback_thread_run(void *arg) {
struct SoundIoOutStreamPrivate *os = (struct SoundIoOutStreamPrivate *)arg;
struct SoundIoOutStream *outstream = &os->pub;
Expand All @@ -34,45 +38,45 @@ static void playback_thread_run(void *arg) {
soundio_os_cond_timed_wait(osd->cond, NULL, relative_time);
if (!SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(osd->clear_buffer_flag)) {
soundio_ring_buffer_clear(&osd->ring_buffer);
int free_bytes = soundio_ring_buffer_capacity(&osd->ring_buffer);
int free_frames = free_bytes / outstream->bytes_per_frame;
osd->frames_left = free_frames;
if (free_frames > 0)
outstream->write_callback(outstream, 0, free_frames);
int free_bytes_inner = soundio_ring_buffer_capacity(&osd->ring_buffer);
int free_frames_inner = free_bytes_inner / outstream->bytes_per_frame;
osd->frames_left = free_frames_inner;
if (free_frames_inner > 0)
outstream->write_callback(outstream, 0, free_frames_inner);
frames_consumed = 0;
start_time = soundio_os_get_time();
continue;
}

if (SOUNDIO_ATOMIC_LOAD(osd->pause_requested)) {
if (SOUNDIO_ATOMIC_LOAD_BOOL(osd->pause_requested)) {
start_time = now;
frames_consumed = 0;
continue;
}

int fill_bytes = soundio_ring_buffer_fill_count(&osd->ring_buffer);
int fill_frames = fill_bytes / outstream->bytes_per_frame;
int free_bytes = soundio_ring_buffer_capacity(&osd->ring_buffer) - fill_bytes;
int free_frames = free_bytes / outstream->bytes_per_frame;
int fill_bytes_inner = soundio_ring_buffer_fill_count(&osd->ring_buffer);
int fill_frames_inner = fill_bytes_inner / outstream->bytes_per_frame;
int free_bytes_inner = soundio_ring_buffer_capacity(&osd->ring_buffer) - fill_bytes_inner;
int free_frames_inner = free_bytes_inner / outstream->bytes_per_frame;

double total_time = soundio_os_get_time() - start_time;
long total_frames = total_time * outstream->sample_rate;
long total_frames = (long) (total_time * outstream->sample_rate);
int frames_to_kill = total_frames - frames_consumed;
int read_count = soundio_int_min(frames_to_kill, fill_frames);
int read_count = soundio_int_min(frames_to_kill, fill_frames_inner);
int byte_count = read_count * outstream->bytes_per_frame;
soundio_ring_buffer_advance_read_ptr(&osd->ring_buffer, byte_count);
frames_consumed += read_count;

if (frames_to_kill > fill_frames) {
if (frames_to_kill > fill_frames_inner) {
outstream->underflow_callback(outstream);
osd->frames_left = free_frames;
if (free_frames > 0)
outstream->write_callback(outstream, 0, free_frames);
osd->frames_left = free_frames_inner;
if (free_frames_inner > 0)
outstream->write_callback(outstream, 0, free_frames_inner);
frames_consumed = 0;
start_time = soundio_os_get_time();
} else if (free_frames > 0) {
osd->frames_left = free_frames;
outstream->write_callback(outstream, 0, free_frames);
} else if (free_frames_inner > 0) {
osd->frames_left = free_frames_inner;
outstream->write_callback(outstream, 0, free_frames_inner);
}
}
}
Expand All @@ -92,7 +96,7 @@ static void capture_thread_run(void *arg) {
double relative_time = next_period - now;
soundio_os_cond_timed_wait(isd->cond, NULL, relative_time);

if (SOUNDIO_ATOMIC_LOAD(isd->pause_requested)) {
if (SOUNDIO_ATOMIC_LOAD_BOOL(isd->pause_requested)) {
start_time = now;
frames_consumed = 0;
continue;
Expand All @@ -104,7 +108,7 @@ static void capture_thread_run(void *arg) {
int free_frames = free_bytes / instream->bytes_per_frame;

double total_time = soundio_os_get_time() - start_time;
long total_frames = total_time * instream->sample_rate;
long total_frames = (long) (total_time * instream->sample_rate);
int frames_to_kill = total_frames - frames_consumed;
int write_count = soundio_int_min(frames_to_kill, free_frames);
int byte_count = write_count * instream->bytes_per_frame;
Expand Down Expand Up @@ -178,7 +182,7 @@ static int outstream_open_dummy(struct SoundIoPrivate *si, struct SoundIoOutStre
struct SoundIoDevice *device = outstream->device;

SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(osd->clear_buffer_flag);
SOUNDIO_ATOMIC_STORE(osd->pause_requested, false);
SOUNDIO_ATOMIC_STORE_BOOL(osd->pause_requested, false);

if (outstream->software_latency == 0.0) {
outstream->software_latency = soundio_double_clamp(
Expand All @@ -188,7 +192,7 @@ static int outstream_open_dummy(struct SoundIoPrivate *si, struct SoundIoOutStre
osd->period_duration = outstream->software_latency / 2.0;

int err;
int buffer_size = outstream->bytes_per_frame * outstream->sample_rate * outstream->software_latency;
int buffer_size = (int) (outstream->bytes_per_frame * outstream->sample_rate * outstream->software_latency);
if ((err = soundio_ring_buffer_init(&osd->ring_buffer, buffer_size))) {
outstream_destroy_dummy(si, os);
return err;
Expand All @@ -208,7 +212,7 @@ static int outstream_open_dummy(struct SoundIoPrivate *si, struct SoundIoOutStre

static int outstream_pause_dummy(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os, bool pause) {
struct SoundIoOutStreamDummy *osd = &os->backend_data.dummy;
SOUNDIO_ATOMIC_STORE(osd->pause_requested, pause);
SOUNDIO_ATOMIC_STORE_BOOL(osd->pause_requested, pause);
return 0;
}

Expand Down Expand Up @@ -291,7 +295,7 @@ static int instream_open_dummy(struct SoundIoPrivate *si, struct SoundIoInStream
struct SoundIoInStream *instream = &is->pub;
struct SoundIoDevice *device = instream->device;

SOUNDIO_ATOMIC_STORE(isd->pause_requested, false);
SOUNDIO_ATOMIC_STORE_BOOL(isd->pause_requested, false);

if (instream->software_latency == 0.0) {
instream->software_latency = soundio_double_clamp(
Expand All @@ -303,7 +307,7 @@ static int instream_open_dummy(struct SoundIoPrivate *si, struct SoundIoInStream
double target_buffer_duration = isd->period_duration * 4.0;

int err;
int buffer_size = instream->bytes_per_frame * instream->sample_rate * target_buffer_duration;
int buffer_size = (int)(instream->bytes_per_frame * instream->sample_rate * target_buffer_duration);
if ((err = soundio_ring_buffer_init(&isd->ring_buffer, buffer_size))) {
instream_destroy_dummy(si, is);
return err;
Expand All @@ -323,7 +327,7 @@ static int instream_open_dummy(struct SoundIoPrivate *si, struct SoundIoInStream

static int instream_pause_dummy(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is, bool pause) {
struct SoundIoInStreamDummy *isd = &is->backend_data.dummy;
SOUNDIO_ATOMIC_STORE(isd->pause_requested, pause);
SOUNDIO_ATOMIC_STORE_BOOL(isd->pause_requested, pause);
return 0;
}

Expand Down
23 changes: 13 additions & 10 deletions src/ring_buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
#include <stdlib.h>

struct SoundIoRingBuffer *soundio_ring_buffer_create(struct SoundIo *soundio, int requested_capacity) {
(void)soundio;
(void)requested_capacity;

struct SoundIoRingBuffer *rb = ALLOCATE(struct SoundIoRingBuffer, 1);

assert(requested_capacity > 0);
Expand Down Expand Up @@ -43,30 +46,30 @@ int soundio_ring_buffer_capacity(struct SoundIoRingBuffer *rb) {
}

char *soundio_ring_buffer_write_ptr(struct SoundIoRingBuffer *rb) {
unsigned long write_offset = SOUNDIO_ATOMIC_LOAD(rb->write_offset);
unsigned long write_offset = SOUNDIO_ATOMIC_LOAD_ULONG(rb->write_offset);
return rb->mem.address + (write_offset % rb->capacity);
}

void soundio_ring_buffer_advance_write_ptr(struct SoundIoRingBuffer *rb, int count) {
SOUNDIO_ATOMIC_FETCH_ADD(rb->write_offset, count);
SOUNDIO_ATOMIC_FETCH_ADD_ULONG(rb->write_offset, count);
assert(soundio_ring_buffer_fill_count(rb) >= 0);
}

char *soundio_ring_buffer_read_ptr(struct SoundIoRingBuffer *rb) {
unsigned long read_offset = SOUNDIO_ATOMIC_LOAD(rb->read_offset);
unsigned long read_offset = SOUNDIO_ATOMIC_LOAD_ULONG(rb->read_offset);
return rb->mem.address + (read_offset % rb->capacity);
}

void soundio_ring_buffer_advance_read_ptr(struct SoundIoRingBuffer *rb, int count) {
SOUNDIO_ATOMIC_FETCH_ADD(rb->read_offset, count);
SOUNDIO_ATOMIC_FETCH_ADD_ULONG(rb->read_offset, count);
assert(soundio_ring_buffer_fill_count(rb) >= 0);
}

int soundio_ring_buffer_fill_count(struct SoundIoRingBuffer *rb) {
// Whichever offset we load first might have a smaller value. So we load
// the read_offset first.
unsigned long read_offset = SOUNDIO_ATOMIC_LOAD(rb->read_offset);
unsigned long write_offset = SOUNDIO_ATOMIC_LOAD(rb->write_offset);
unsigned long read_offset = SOUNDIO_ATOMIC_LOAD_ULONG(rb->read_offset);
unsigned long write_offset = SOUNDIO_ATOMIC_LOAD_ULONG(rb->write_offset);
int count = write_offset - read_offset;
assert(count >= 0);
assert(count <= rb->capacity);
Expand All @@ -78,16 +81,16 @@ int soundio_ring_buffer_free_count(struct SoundIoRingBuffer *rb) {
}

void soundio_ring_buffer_clear(struct SoundIoRingBuffer *rb) {
unsigned long read_offset = SOUNDIO_ATOMIC_LOAD(rb->read_offset);
SOUNDIO_ATOMIC_STORE(rb->write_offset, read_offset);
unsigned long read_offset = SOUNDIO_ATOMIC_LOAD_ULONG(rb->read_offset);
SOUNDIO_ATOMIC_STORE_ULONG(rb->write_offset, read_offset);
}

int soundio_ring_buffer_init(struct SoundIoRingBuffer *rb, int requested_capacity) {
int err;
if ((err = soundio_os_init_mirrored_memory(&rb->mem, requested_capacity)))
return err;
SOUNDIO_ATOMIC_STORE(rb->write_offset, 0);
SOUNDIO_ATOMIC_STORE(rb->read_offset, 0);
SOUNDIO_ATOMIC_STORE_ULONG(rb->write_offset, 0);
SOUNDIO_ATOMIC_STORE_ULONG(rb->read_offset, 0);
rb->capacity = rb->mem.capacity;

return 0;
Expand Down
Loading

0 comments on commit 2a3505b

Please sign in to comment.