diff --git a/Backends/Audio2/DirectSound/Sources/kinc/backend/DirectSound.cpp b/Backends/Audio2/DirectSound/Sources/kinc/backend/DirectSound.cpp index 068f56a70..ea57965d2 100644 --- a/Backends/Audio2/DirectSound/Sources/kinc/backend/DirectSound.cpp +++ b/Backends/Audio2/DirectSound/Sources/kinc/backend/DirectSound.cpp @@ -6,6 +6,8 @@ #include +#include + namespace { IDirectSound8 *dsound = nullptr; IDirectSoundBuffer *dbuffer = nullptr; @@ -19,7 +21,7 @@ namespace { const int gap = 10 * 1024; DWORD writePos = gap; - void (*a2_callback)(kinc_a2_buffer_t *buffer, int samples, void *userdata) = nullptr; + void (*a2_callback)(kinc_a2_buffer_t *buffer, uint32_t samples, void *userdata) = nullptr; void *a2_userdata = nullptr; kinc_a2_buffer_t a2_buffer; } @@ -36,7 +38,9 @@ void kinc_a2_init() { a2_buffer.read_location = 0; a2_buffer.write_location = 0; a2_buffer.data_size = 128 * 1024; - a2_buffer.data = new uint8_t[a2_buffer.data_size]; + a2_buffer.channel_count = 2; + a2_buffer.channels[0] = new float[a2_buffer.data_size]; + a2_buffer.channels[1] = new float[a2_buffer.data_size]; kinc_microsoft_affirm(DirectSoundCreate8(nullptr, &dsound, nullptr)); // TODO (DK) only for the main window? @@ -62,26 +66,34 @@ void kinc_a2_init() { kinc_microsoft_affirm(dsound->CreateSoundBuffer(&bufferDesc, &dbuffer, nullptr)); DWORD size1; - uint8_t *buffer1; + uint8_t *buffer1 = NULL; kinc_microsoft_affirm(dbuffer->Lock(writePos, gap, (void **)&buffer1, &size1, nullptr, nullptr, 0)); - for (int i = 0; i < gap; ++i) + assert(buffer1 != NULL); + for (DWORD i = 0; i < size1; ++i) { buffer1[i] = 0; + } kinc_microsoft_affirm(dbuffer->Unlock(buffer1, size1, nullptr, 0)); kinc_microsoft_affirm(dbuffer->Play(0, 0, DSBPLAY_LOOPING)); } -void kinc_a2_set_callback(void (*kinc_a2_audio_callback)(kinc_a2_buffer_t *buffer, int samples, void *userdata), void *userdata) { +uint32_t kinc_a2_samples_per_second(void) { + return samplesPerSecond; +} + +void kinc_a2_set_callback(void (*kinc_a2_audio_callback)(kinc_a2_buffer_t *buffer, uint32_t samples, void *userdata), void *userdata) { a2_callback = kinc_a2_audio_callback; a2_userdata = userdata; } namespace { - void copySample(uint8_t *buffer, DWORD &index) { - float value = *(float *)&a2_buffer.data[a2_buffer.read_location]; - a2_buffer.read_location += 4; - if (a2_buffer.read_location >= a2_buffer.data_size) { - a2_buffer.read_location = 0; + void copySample(uint8_t *buffer, DWORD &index, bool left) { + float value = *(float *)&a2_buffer.channels[left ? 0 : 1][a2_buffer.read_location]; + if (!left) { + a2_buffer.read_location += 1; + if (a2_buffer.read_location >= a2_buffer.data_size) { + a2_buffer.read_location = 0; + } } *(int16_t *)&buffer[index] = static_cast(value * 32767); index += 2; @@ -94,47 +106,49 @@ void kinc_a2_update() { kinc_microsoft_affirm(dbuffer->GetCurrentPosition(&playPosition, &writePosition)); int dif; - if (writePos >= writePosition) + if (writePos >= writePosition) { dif = writePos - writePosition; - else + } + else { dif = dsize - writePosition + writePos; + } - if (dif < gap) + if (dif < gap) { return; + } if (writePos + gap >= dsize) { - if (playPosition >= writePos || playPosition <= gap) + if (playPosition >= writePos || playPosition <= gap) { return; - if (writePosition >= writePos || writePosition <= gap) + } + if (writePosition >= writePos || writePosition <= gap) { return; + } } else { - if (playPosition >= writePos && playPosition <= writePos + gap) + if (playPosition >= writePos && playPosition <= writePos + gap) { return; - if (writePosition >= writePos && writePosition <= writePos + gap) + } + if (writePosition >= writePos && writePosition <= writePos + gap) { return; + } } - a2_callback(&a2_buffer, gap / 2, a2_userdata); + a2_callback(&a2_buffer, (uint32_t)(gap / 4), a2_userdata); - DWORD size1, size2; - uint8_t *buffer1, *buffer2; - kinc_microsoft_affirm(dbuffer->Lock(writePos, gap, (void **)&buffer1, &size1, (void **)&buffer2, &size2, 0)); + DWORD size1; + uint8_t *buffer1; + kinc_microsoft_affirm(dbuffer->Lock(writePos, gap, (void **)&buffer1, &size1, NULL, NULL, 0)); for (DWORD i = 0; i < size1 - (bitsPerSample / 8 - 1);) { - copySample(buffer1, i); + copySample(buffer1, i, ((writePos + i) / 2) % 2 == 0); } writePos += size1; - if (buffer2 != nullptr) { - for (DWORD i = 0; i < size2 - (bitsPerSample / 8 - 1);) { - copySample(buffer2, i); - } - writePos = size2; - } - kinc_microsoft_affirm(dbuffer->Unlock(buffer1, size1, buffer2, size2)); + kinc_microsoft_affirm(dbuffer->Unlock(buffer1, size1, NULL, 0)); - if (writePos >= dsize) + if (writePos >= dsize) { writePos -= dsize; + } } void kinc_a2_shutdown() { diff --git a/Backends/Audio2/WASAPI/Sources/kinc/backend/wasapi.c b/Backends/Audio2/WASAPI/Sources/kinc/backend/wasapi.c index e3a32d7fe..9746d49ea 100644 --- a/Backends/Audio2/WASAPI/Sources/kinc/backend/wasapi.c +++ b/Backends/Audio2/WASAPI/Sources/kinc/backend/wasapi.c @@ -16,7 +16,7 @@ #define NOCTLMGR #define NODEFERWINDOWPOS #define NODRAWTEXT -//#define NOGDI +// #define NOGDI #define NOGDICAPMASKS #define NOHELP #define NOICONS @@ -28,7 +28,7 @@ #define NOMENUS #define NOMETAFILE #define NOMINMAX -//#define NOMSG +// #define NOMSG #define NONLS #define NOOPENFILE #define NOPROFILER @@ -40,7 +40,7 @@ #define NOSYSCOMMANDS #define NOSYSMETRICS #define NOTEXTMETRIC -//#define NOUSER +// #define NOUSER #define NOVIRTUALKEYCODES #define NOWH #define NOWINMESSAGES @@ -63,7 +63,7 @@ DEFINE_GUID(IID_IMMDeviceEnumerator, 0xA95664D2, 0x9614, 0x4F35, 0xA7, 0x46, 0xD DEFINE_GUID(CLSID_MMDeviceEnumerator, 0xBCDE0395, 0xE52F, 0x467C, 0x8E, 0x3D, 0xC4, 0x57, 0x92, 0x91, 0x69, 0x2E); // based on the implementation in soloud and Microsoft sample code -static volatile void (*a2_callback)(kinc_a2_buffer_t *buffer, int samples, void *userdata) = NULL; +static volatile void (*a2_callback)(kinc_a2_buffer_t *buffer, uint32_t samples, void *userdata) = NULL; static void *a2_userdata = NULL; static kinc_a2_buffer_t a2_buffer; @@ -77,6 +77,18 @@ static UINT32 bufferFrames; static WAVEFORMATEX requestedFormat; static WAVEFORMATEX *closestFormat; static WAVEFORMATEX *format; +static uint32_t samples_per_second = 44100; +static void (*sample_rate_callback)(void *userdata) = NULL; +static void *sample_rate_callback_userdata = NULL; + +uint32_t kinc_a2_samples_per_second(void) { + return samples_per_second; +} + +void kinc_a2_set_sample_rate_callback(void (*kinc_a2_sample_rate_callback)(void *userdata), void *userdata) { + sample_rate_callback_userdata = userdata; + sample_rate_callback = kinc_a2_sample_rate_callback; +} static bool initDefaultDevice() { if (renderClient != NULL) { @@ -131,10 +143,12 @@ static bool initDefaultDevice() { return false; } - kinc_a2_samples_per_second = format->nSamplesPerSec; - a2_buffer.format.samples_per_second = kinc_a2_samples_per_second; - a2_buffer.format.bits_per_sample = 16; - a2_buffer.format.channels = 2; + uint32_t old_samples_per_second = samples_per_second; + samples_per_second = format->nSamplesPerSec; + if (samples_per_second != old_samples_per_second && sample_rate_callback != NULL) { + sample_rate_callback(sample_rate_callback_userdata); + } + a2_buffer.channel_count = 2; bufferFrames = 0; kinc_microsoft_affirm(audioClient->lpVtbl->GetBufferSize(audioClient, &bufferFrames)); @@ -153,20 +167,26 @@ static bool initDefaultDevice() { } } -static void copyS16Sample(int16_t *buffer) { - float value = *(float *)&a2_buffer.data[a2_buffer.read_location]; - a2_buffer.read_location += 4; - if (a2_buffer.read_location >= a2_buffer.data_size) +static void copyS16Sample(int16_t *left, int16_t *right) { + float left_value = *(float *)&a2_buffer.channels[0][a2_buffer.read_location]; + float right_value = *(float *)&a2_buffer.channels[1][a2_buffer.read_location]; + a2_buffer.read_location += 1; + if (a2_buffer.read_location >= a2_buffer.data_size) { a2_buffer.read_location = 0; - *buffer = (int16_t)(value * 32767); + } + *left = (int16_t)(left_value * 32767); + *right = (int16_t)(right_value * 32767); } -static void copyFloatSample(float *buffer) { - float value = *(float *)&a2_buffer.data[a2_buffer.read_location]; - a2_buffer.read_location += 4; - if (a2_buffer.read_location >= a2_buffer.data_size) +static void copyFloatSample(float *left, float *right) { + float left_value = *(float *)&a2_buffer.channels[0][a2_buffer.read_location]; + float right_value = *(float *)&a2_buffer.channels[1][a2_buffer.read_location]; + a2_buffer.read_location += 1; + if (a2_buffer.read_location >= a2_buffer.data_size) { a2_buffer.read_location = 0; - *buffer = value; + } + *left = left_value; + *right = right_value; } static void submitEmptyBuffer(unsigned frames) { @@ -194,18 +214,16 @@ static void submitBuffer(unsigned frames) { } if (a2_callback != NULL) { - a2_callback(&a2_buffer, frames * 2, a2_userdata); + a2_callback(&a2_buffer, frames, a2_userdata); memset(buffer, 0, frames * format->nBlockAlign); if (format->wFormatTag == WAVE_FORMAT_PCM) { for (UINT32 i = 0; i < frames; ++i) { - copyS16Sample((int16_t *)&buffer[i * format->nBlockAlign]); - copyS16Sample((int16_t *)&buffer[i * format->nBlockAlign + 2]); + copyS16Sample((int16_t *)&buffer[i * format->nBlockAlign], (int16_t *)&buffer[i * format->nBlockAlign + 2]); } } else { for (UINT32 i = 0; i < frames; ++i) { - copyFloatSample((float *)&buffer[i * format->nBlockAlign]); - copyFloatSample((float *)&buffer[i * format->nBlockAlign + 4]); + copyFloatSample((float *)&buffer[i * format->nBlockAlign], (float *)&buffer[i * format->nBlockAlign + 4]); } } } @@ -258,7 +276,9 @@ void kinc_a2_init() { a2_buffer.read_location = 0; a2_buffer.write_location = 0; a2_buffer.data_size = 128 * 1024; - a2_buffer.data = (uint8_t *)malloc(a2_buffer.data_size); + a2_buffer.channel_count = 2; + a2_buffer.channels[0] = (float *)malloc(a2_buffer.data_size * sizeof(float)); + a2_buffer.channels[1] = (float *)malloc(a2_buffer.data_size * sizeof(float)); audioProcessingDoneEvent = CreateEvent(0, FALSE, FALSE, 0); kinc_affirm(audioProcessingDoneEvent != 0); @@ -271,7 +291,7 @@ void kinc_a2_init() { } } -void kinc_a2_set_callback(void (*kinc_a2_audio_callback)(kinc_a2_buffer_t *buffer, int samples, void *userdata), void *userdata) { +void kinc_a2_set_callback(void (*kinc_a2_audio_callback)(kinc_a2_buffer_t *buffer, uint32_t samples, void *userdata), void *userdata) { a2_callback = kinc_a2_audio_callback; a2_userdata = userdata; } diff --git a/Backends/Audio2/WASAPI_WinRT/Sources/kinc/backend/WASAPI.winrt.cpp b/Backends/Audio2/WASAPI_WinRT/Sources/kinc/backend/WASAPI.winrt.cpp index 356f4fce6..cb218b120 100644 --- a/Backends/Audio2/WASAPI_WinRT/Sources/kinc/backend/WASAPI.winrt.cpp +++ b/Backends/Audio2/WASAPI_WinRT/Sources/kinc/backend/WASAPI.winrt.cpp @@ -40,7 +40,7 @@ template void SafeRelease(__deref_inout_opt T **ppT) { // based on the implementation in soloud and Microsoft sample code namespace { kinc_thread_t thread; - void (*a2_callback)(kinc_a2_buffer_t *buffer, int samples, void *userdata) = nullptr; + void (*a2_callback)(kinc_a2_buffer_t *buffer, uint32_t samples, void *userdata) = NULL; void *a2_userdata = nullptr; kinc_a2_buffer_t a2_buffer; @@ -54,6 +54,9 @@ namespace { WAVEFORMATEX requestedFormat; WAVEFORMATEX *closestFormat; WAVEFORMATEX *format; + static uint32_t samples_per_second = 44100; + static void (*sample_rate_callback)(void *userdata) = NULL; + static void *sample_rate_callback_userdata = NULL; bool initDefaultDevice(); void audioThread(LPVOID); @@ -133,8 +136,12 @@ namespace { return false; } - kinc_a2_samples_per_second = format->nSamplesPerSec; - a2_buffer.format.samples_per_second = kinc_a2_samples_per_second; + uint32_t old_samples_per_second = samples_per_second; + samples_per_second = format->nSamplesPerSec; + if (samples_per_second != old_samples_per_second && sample_rate_callback != NULL) { + sample_rate_callback(sample_rate_callback_userdata); + } + a2_buffer.channel_count = 2; bufferFrames = 0; kinc_microsoft_affirm(audioClient->GetBufferSize(&bufferFrames)); @@ -153,18 +160,26 @@ namespace { } } - void copyS16Sample(s16 *buffer) { - float value = *(float *)&a2_buffer.data[a2_buffer.read_location]; - a2_buffer.read_location += 4; - if (a2_buffer.read_location >= a2_buffer.data_size) a2_buffer.read_location = 0; - *buffer = (s16)(value * 32767); + void copyS16Sample(int16_t *left, int16_t *right) { + float left_value = *(float *)&a2_buffer.channels[0][a2_buffer.read_location]; + float right_value = *(float *)&a2_buffer.channels[1][a2_buffer.read_location]; + a2_buffer.read_location += 1; + if (a2_buffer.read_location >= a2_buffer.data_size) { + a2_buffer.read_location = 0; + } + *left = (int16_t)(left_value * 32767); + *right = (int16_t)(right_value * 32767); } - void copyFloatSample(float *buffer) { - float value = *(float *)&a2_buffer.data[a2_buffer.read_location]; - a2_buffer.read_location += 4; - if (a2_buffer.read_location >= a2_buffer.data_size) a2_buffer.read_location = 0; - *buffer = value; + void copyFloatSample(float *left, float *right) { + float left_value = *(float *)&a2_buffer.channels[0][a2_buffer.read_location]; + float right_value = *(float *)&a2_buffer.channels[1][a2_buffer.read_location]; + a2_buffer.read_location += 1; + if (a2_buffer.read_location >= a2_buffer.data_size) { + a2_buffer.read_location = 0; + } + *left = left_value; + *right = right_value; } void submitEmptyBuffer(unsigned frames) { @@ -192,18 +207,16 @@ namespace { } if (a2_callback != nullptr) { - a2_callback(&a2_buffer, frames * 2, a2_userdata); + a2_callback(&a2_buffer, frames, a2_userdata); memset(buffer, 0, frames * format->nBlockAlign); if (format->wFormatTag == WAVE_FORMAT_PCM) { for (UINT32 i = 0; i < frames; ++i) { - copyS16Sample((s16 *)&buffer[i * format->nBlockAlign]); - copyS16Sample((s16 *)&buffer[i * format->nBlockAlign + 2]); + copyS16Sample((int16_t *)&buffer[i * format->nBlockAlign], (int16_t *)&buffer[i * format->nBlockAlign + 2]); } } else { for (UINT32 i = 0; i < frames; ++i) { - copyFloatSample((float *)&buffer[i * format->nBlockAlign]); - copyFloatSample((float *)&buffer[i * format->nBlockAlign + 4]); + copyFloatSample((float *)&buffer[i * format->nBlockAlign], (float *)&buffer[i * format->nBlockAlign + 4]); } } } @@ -259,7 +272,9 @@ void kinc_a2_init() { a2_buffer.read_location = 0; a2_buffer.write_location = 0; a2_buffer.data_size = 128 * 1024; - a2_buffer.data = (uint8_t *)malloc(a2_buffer.data_size); + a2_buffer.channel_count = 2; + a2_buffer.channels[0] = (float *)malloc(a2_buffer.data_size * sizeof(float)); + a2_buffer.channels[1] = (float *)malloc(a2_buffer.data_size * sizeof(float)); audioProcessingDoneEvent = CreateEvent(0, FALSE, FALSE, 0); kinc_affirm(audioProcessingDoneEvent != 0); @@ -282,11 +297,19 @@ void kinc_a2_init() { #endif } -void kinc_a2_set_callback(void (*kinc_a2_audio_callback)(kinc_a2_buffer_t *buffer, int samples, void *userdata), void *userdata) { +void kinc_a2_set_callback(void (*kinc_a2_audio_callback)(kinc_a2_buffer_t *buffer, uint32_t samples, void *userdata), void *userdata) { a2_callback = kinc_a2_audio_callback; a2_userdata = userdata; } +uint32_t kinc_a2_samples_per_second(void) { + return samples_per_second; +} + +void kinc_a2_set_sample_rate_callback(void (*kinc_a2_sample_rate_callback)(void *userdata), void *userdata) { + sample_rate_callback = kinc_a2_sample_rate_callback; +} + void kinc_a2_update() {} void kinc_a2_shutdown() { diff --git a/Backends/System/Android/Sources/kinc/backend/audio.c.h b/Backends/System/Android/Sources/kinc/backend/audio.c.h index 9819a21e4..4b6b91a22 100644 --- a/Backends/System/Android/Sources/kinc/backend/audio.c.h +++ b/Backends/System/Android/Sources/kinc/backend/audio.c.h @@ -6,7 +6,7 @@ #include #include -static void (*a2_callback)(kinc_a2_buffer_t *buffer, int samples, void *userdata) = NULL; +static void (*a2_callback)(kinc_a2_buffer_t *buffer, uint32_t samples, void *userdata) = NULL; static void *a2_userdata = NULL; static kinc_a2_buffer_t a2_buffer; @@ -20,17 +20,20 @@ static SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue; static int16_t tempBuffer[AUDIO_BUFFER_SIZE]; static void copySample(void *buffer) { - float value = *(float *)&a2_buffer.data[a2_buffer.read_location]; - a2_buffer.read_location += 4; - if (a2_buffer.read_location >= a2_buffer.data_size) + float left_value = *(float *)&a2_buffer.channels[0][a2_buffer.read_location]; + float right_value = *(float *)&a2_buffer.channels[1][a2_buffer.read_location]; + a2_buffer.read_location += 1; + if (a2_buffer.read_location >= a2_buffer.data_size) { a2_buffer.read_location = 0; - *(int16_t *)buffer = (int16_t)(value * 32767); + } + ((int16_t *)buffer)[0] = (int16_t)(left_value * 32767); + ((int16_t *)buffer)[1] = (int16_t)(right_value * 32767); } static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf caller, void *context) { if (a2_callback != NULL) { - a2_callback(&a2_buffer, AUDIO_BUFFER_SIZE, a2_userdata); - for (int i = 0; i < AUDIO_BUFFER_SIZE; i++) { + a2_callback(&a2_buffer, AUDIO_BUFFER_SIZE / 2, a2_userdata); + for (int i = 0; i < AUDIO_BUFFER_SIZE; i += 2) { copySample(&tempBuffer[i]); } SLresult result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, tempBuffer, AUDIO_BUFFER_SIZE * 2); @@ -50,11 +53,12 @@ void kinc_a2_init() { initialized = true; - kinc_a2_samples_per_second = 44100; a2_buffer.read_location = 0; a2_buffer.write_location = 0; a2_buffer.data_size = 128 * 1024; - a2_buffer.data = malloc(a2_buffer.data_size); + a2_buffer.channel_count = 2; + a2_buffer.channels[0] = (float*)malloc(a2_buffer.data_size * sizeof(float)); + a2_buffer.channels[1] = (float*)malloc(a2_buffer.data_size * sizeof(float)); SLresult result; result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL); @@ -94,14 +98,16 @@ void kinc_a2_init() { } void pauseAudio() { - if (bqPlayerPlay == NULL) + if (bqPlayerPlay == NULL) { return; + } SLresult result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PAUSED); } void resumeAudio() { - if (bqPlayerPlay == NULL) + if (bqPlayerPlay == NULL) { return; + } SLresult result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING); } @@ -125,7 +131,19 @@ void kinc_a2_shutdown() { } } -void kinc_a2_set_callback(void (*kinc_a2_audio_callback)(kinc_a2_buffer_t *buffer, int samples, void *userdata), void *userdata) { +void kinc_a2_set_callback(void (*kinc_a2_audio_callback)(kinc_a2_buffer_t *buffer, uint32_t samples, void *userdata), void *userdata) { a2_callback = kinc_a2_audio_callback; a2_userdata = userdata; } + +static void (*sample_rate_callback)(void *userdata) = NULL; +static void *sample_rate_callback_userdata = NULL; + +uint32_t kinc_a2_samples_per_second(void) { + return 44100; +} + +void kinc_a2_set_sample_rate_callback(void (*kinc_a2_sample_rate_callback)(void *userdata), void *userdata) { + sample_rate_callback_userdata = userdata; + sample_rate_callback = kinc_a2_sample_rate_callback; +} diff --git a/Backends/System/Android/Sources/kinc/backend/video.c.h b/Backends/System/Android/Sources/kinc/backend/video.c.h index 04454c1be..cb780ebdc 100644 --- a/Backends/System/Android/Sources/kinc/backend/video.c.h +++ b/Backends/System/Android/Sources/kinc/backend/video.c.h @@ -36,8 +36,10 @@ void kinc_video_sound_stream_impl_destroy(kinc_internal_video_sound_stream_t *st void kinc_video_sound_stream_impl_insert_data(kinc_internal_video_sound_stream_t *stream, float *data, int sample_count) {} -float kinc_internal_video_sound_stream_next_sample(kinc_internal_video_sound_stream_t *stream) { - return 0; +static float samples[2] = {0}; + +float *kinc_internal_video_sound_stream_next_frame(kinc_internal_video_sound_stream_t *stream) { + return samples; } bool kinc_internal_video_sound_stream_ended(kinc_internal_video_sound_stream_t *stream) { diff --git a/Backends/System/Android/Sources/kinc/backend/video.h b/Backends/System/Android/Sources/kinc/backend/video.h index ca4e90c8e..471e32fc0 100644 --- a/Backends/System/Android/Sources/kinc/backend/video.h +++ b/Backends/System/Android/Sources/kinc/backend/video.h @@ -40,7 +40,7 @@ void kinc_internal_video_sound_stream_destroy(kinc_internal_video_sound_stream_t void kinc_internal_video_sound_stream_insert_data(kinc_internal_video_sound_stream_t *stream, float *data, int sample_count); -float kinc_internal_video_sound_stream_next_sample(kinc_internal_video_sound_stream_t *stream); +float *kinc_internal_video_sound_stream_next_frame(kinc_internal_video_sound_stream_t *stream); bool kinc_internal_video_sound_stream_ended(kinc_internal_video_sound_stream_t *stream); diff --git a/Backends/System/Emscripten/Sources/kinc/backend/audio.c.h b/Backends/System/Emscripten/Sources/kinc/backend/audio.c.h index 177cd5709..e55c9254a 100644 --- a/Backends/System/Emscripten/Sources/kinc/backend/audio.c.h +++ b/Backends/System/Emscripten/Sources/kinc/backend/audio.c.h @@ -6,7 +6,7 @@ #include #include -static void (*a2_callback)(kinc_a2_buffer_t *buffer, int samples, void *userdata) = NULL; +static void (*a2_callback)(kinc_a2_buffer_t *buffer, uint32_t samples, void *userdata) = NULL; static void *a2_userdata = NULL; static kinc_a2_buffer_t a2_buffer; @@ -22,35 +22,41 @@ static bool audioRunning = false; static short buf[BUFSIZE]; #define NUM_BUFFERS 3 +static uint32_t samples_per_second = 44100; + static void copySample(void *buffer) { - float value = *(float *)&a2_buffer.data[a2_buffer.read_location]; - a2_buffer.read_location += 4; + float left_value = *(float *)&a2_buffer.channels[0][a2_buffer.read_location]; + float right_value = *(float *)&a2_buffer.channels[1][a2_buffer.read_location]; + a2_buffer.read_location += 1; if (a2_buffer.read_location >= a2_buffer.data_size) { a2_buffer.read_location = 0; } - *(int16_t *)buffer = (int16_t)(value * 32767); + ((int16_t *)buffer)[0] = (int16_t)(left_value * 32767); + ((int16_t *)buffer)[1] = (int16_t)(right_value * 32767); } static void streamBuffer(ALuint buffer) { if (a2_callback != NULL) { - a2_callback(&a2_buffer, BUFSIZE, a2_userdata); - for (int i = 0; i < BUFSIZE; ++i) { + a2_callback(&a2_buffer, BUFSIZE / 2, a2_userdata); + for (int i = 0; i < BUFSIZE; i += 2) { copySample(&buf[i]); } } - alBufferData(buffer, format, buf, BUFSIZE * 2, 44100); + alBufferData(buffer, format, buf, BUFSIZE * 2, samples_per_second); } static void iter() { - if (!audioRunning) + if (!audioRunning) { return; + } ALint processed; alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed); - if (processed <= 0) + if (processed <= 0) { return; + } while (processed--) { ALuint buffer; alSourceUnqueueBuffers(source, 1, &buffer); @@ -77,7 +83,9 @@ void kinc_a2_init() { a2_buffer.read_location = 0; a2_buffer.write_location = 0; a2_buffer.data_size = 128 * 1024; - a2_buffer.data = malloc(a2_buffer.data_size); + a2_buffer.channel_count = 2; + a2_buffer.channels[0] = (float*)malloc(a2_buffer.data_size * sizeof(float)); + a2_buffer.channels[1] = (float*)malloc(a2_buffer.data_size * sizeof(float)); audioRunning = true; @@ -107,7 +115,19 @@ void kinc_a2_shutdown() { audioRunning = false; } -void kinc_a2_set_callback(void (*kinc_a2_audio_callback)(kinc_a2_buffer_t *buffer, int samples, void *userdata), void *userdata) { +void kinc_a2_set_callback(void (*kinc_a2_audio_callback)(kinc_a2_buffer_t *buffer, uint32_t samples, void *userdata), void *userdata) { a2_callback = kinc_a2_audio_callback; a2_userdata = userdata; } + +static void (*sample_rate_callback)(void *userdata) = NULL; +static void *sample_rate_callback_userdata = NULL; + +uint32_t kinc_a2_samples_per_second(void) { + return samples_per_second; +} + +void kinc_a2_set_sample_rate_callback(void (*kinc_a2_sample_rate_callback)(void *userdata), void *userdata) { + sample_rate_callback_userdata = userdata; + sample_rate_callback = kinc_a2_sample_rate_callback; +} diff --git a/Backends/System/Emscripten/Sources/kinc/backend/gamepad.c.h b/Backends/System/Emscripten/Sources/kinc/backend/gamepad.c.h new file mode 100644 index 000000000..7a2ed0b1d --- /dev/null +++ b/Backends/System/Emscripten/Sources/kinc/backend/gamepad.c.h @@ -0,0 +1,15 @@ +#include + +const char *kinc_gamepad_vendor(int gamepad) { + return "None"; +} + +const char *kinc_gamepad_product_name(int gamepad) { + return "Gamepad"; +} + +bool kinc_gamepad_connected(int gamepad) { + return false; +} + +void kinc_gamepad_rumble(int gamepad, float left, float right) {} diff --git a/Backends/System/Emscripten/Sources/kinc/backend/html5unit.c b/Backends/System/Emscripten/Sources/kinc/backend/html5unit.c index 48072f369..08c2b4b1f 100644 --- a/Backends/System/Emscripten/Sources/kinc/backend/html5unit.c +++ b/Backends/System/Emscripten/Sources/kinc/backend/html5unit.c @@ -1,6 +1,7 @@ #include "audio.c.h" #include "display.c.h" #include "event.c.h" +#include "gamepad.c.h" #include "mouse.c.h" #include "mutex.c.h" #include "semaphore.c.h" diff --git a/Backends/System/Emscripten/Sources/kinc/backend/video.c.h b/Backends/System/Emscripten/Sources/kinc/backend/video.c.h index e1a511118..c5d3481af 100644 --- a/Backends/System/Emscripten/Sources/kinc/backend/video.c.h +++ b/Backends/System/Emscripten/Sources/kinc/backend/video.c.h @@ -46,8 +46,10 @@ void kinc_internal_video_sound_stream_destroy(kinc_internal_video_sound_stream_t void kinc_internal_video_sound_stream_insert_data(kinc_internal_video_sound_stream_t *stream, float *data, int sample_count) {} -float kinc_internal_video_sound_stream_next_sample(kinc_internal_video_sound_stream_t *stream) { - return 0.0f; +float samples[2] = {0}; + +float *kinc_internal_video_sound_stream_next_frame(kinc_internal_video_sound_stream_t *stream) { + return samples; } bool kinc_internal_video_sound_stream_ended(kinc_internal_video_sound_stream_t *stream) { diff --git a/Backends/System/Emscripten/Sources/kinc/backend/video.h b/Backends/System/Emscripten/Sources/kinc/backend/video.h index 0acd202e6..146a7d4c1 100644 --- a/Backends/System/Emscripten/Sources/kinc/backend/video.h +++ b/Backends/System/Emscripten/Sources/kinc/backend/video.h @@ -18,7 +18,7 @@ void kinc_internal_video_sound_stream_destroy(kinc_internal_video_sound_stream_t void kinc_internal_video_sound_stream_insert_data(kinc_internal_video_sound_stream_t *stream, float *data, int sample_count); -float kinc_internal_video_sound_stream_next_sample(kinc_internal_video_sound_stream_t *stream); +float *kinc_internal_video_sound_stream_next_frame(kinc_internal_video_sound_stream_t *stream); bool kinc_internal_video_sound_stream_ended(kinc_internal_video_sound_stream_t *stream); diff --git a/Backends/System/Linux/Sources/kinc/backend/sound.c.h b/Backends/System/Linux/Sources/kinc/backend/sound.c.h index 2a2702c7f..256823a1d 100644 --- a/Backends/System/Linux/Sources/kinc/backend/sound.c.h +++ b/Backends/System/Linux/Sources/kinc/backend/sound.c.h @@ -9,7 +9,7 @@ // apt-get install libasound2-dev -void (*a2_callback)(kinc_a2_buffer_t *buffer, int samples, void *userdata) = NULL; +void (*a2_callback)(kinc_a2_buffer_t *buffer, uint32_t samples, void *userdata) = NULL; void *a2_userdata = NULL; kinc_a2_buffer_t a2_buffer; @@ -18,28 +18,40 @@ bool audioRunning = false; snd_pcm_t *playback_handle; short buf[4096 * 4]; +static unsigned int samples_per_second = 44100; + +static void (*sample_rate_callback)(void *userdata) = NULL; +static void *sample_rate_callback_userdata = NULL; + +uint32_t kinc_a2_samples_per_second(void) { + return samples_per_second; +} + +void kinc_a2_set_sample_rate_callback(void (*kinc_a2_sample_rate_callback)(void *userdata), void *userdata) { + sample_rate_callback_userdata = userdata; + sample_rate_callback = kinc_a2_sample_rate_callback; +} + void copySample(void *buffer) { - float value = *(float *)&a2_buffer.data[a2_buffer.read_location]; - a2_buffer.read_location += 4; - if (a2_buffer.read_location >= a2_buffer.data_size) + float left_value = *(float *)&a2_buffer.channels[0][a2_buffer.read_location]; + float right_value = *(float *)&a2_buffer.channels[1][a2_buffer.read_location]; + a2_buffer.read_location += 1; + if (a2_buffer.read_location >= a2_buffer.data_size) { a2_buffer.read_location = 0; - if (value != 0) { - int a = 3; - ++a; } - *(int16_t *)buffer = (int16_t)(value * 32767); + ((int16_t *)buffer)[0] = (int16_t)(left_value * 32767); + ((int16_t *)buffer)[1] = (int16_t)(right_value * 32767); } int playback_callback(snd_pcm_sframes_t nframes) { int err = 0; if (a2_callback != NULL) { - a2_callback(&a2_buffer, nframes * 2, a2_userdata); + a2_callback(&a2_buffer, nframes, a2_userdata); int ni = 0; while (ni < nframes) { int i = 0; for (; ni < nframes && i < 4096 * 2; ++i, ++ni) { copySample(&buf[i * 2]); - copySample(&buf[i * 2 + 1]); } int err2; if ((err2 = snd_pcm_writei(playback_handle, buf, i)) < 0) { @@ -108,9 +120,8 @@ void *doAudio(void *arg) { return NULL; } - unsigned int rate = 44100; int dir = 0; - if ((err = snd_pcm_hw_params_set_rate_near(playback_handle, hw_params, &rate, &dir)) < 0) { + if ((err = snd_pcm_hw_params_set_rate_near(playback_handle, hw_params, &samples_per_second, &dir)) < 0) { fprintf(stderr, "cannot set sample rate (%s)\n", snd_strerror(err)); return NULL; } @@ -120,7 +131,7 @@ void *doAudio(void *arg) { return NULL; } - snd_pcm_uframes_t bufferSize = rate / 8; + snd_pcm_uframes_t bufferSize = samples_per_second / 8; if (((err = snd_pcm_hw_params_set_buffer_size(playback_handle, hw_params, bufferSize)) < 0 && (snd_pcm_hw_params_set_buffer_size_near(playback_handle, hw_params, &bufferSize)) < 0)) { fprintf(stderr, "cannot set buffer size (%s)\n", snd_strerror(err)); @@ -217,7 +228,9 @@ void kinc_a2_init() { a2_buffer.read_location = 0; a2_buffer.write_location = 0; a2_buffer.data_size = 128 * 1024; - a2_buffer.data = (uint8_t *)malloc(a2_buffer.data_size); + a2_buffer.channel_count = 2; + a2_buffer.channels[0] = (float *)malloc(a2_buffer.data_size * sizeof(float)); + a2_buffer.channels[1] = (float *)malloc(a2_buffer.data_size * sizeof(float)); audioRunning = true; pthread_create(&threadid, NULL, &doAudio, NULL); @@ -229,7 +242,7 @@ void kinc_a2_shutdown() { audioRunning = false; } -void kinc_a2_set_callback(void (*kinc_a2_audio_callback)(kinc_a2_buffer_t *buffer, int samples, void *userdata), void *userdata) { +void kinc_a2_set_callback(void (*kinc_a2_audio_callback)(kinc_a2_buffer_t *buffer, uint32_t samples, void *userdata), void *userdata) { a2_callback = kinc_a2_audio_callback; a2_userdata = userdata; } diff --git a/Backends/System/Linux/Sources/kinc/backend/video.c.h b/Backends/System/Linux/Sources/kinc/backend/video.c.h index 5171667ea..adf52f71e 100644 --- a/Backends/System/Linux/Sources/kinc/backend/video.c.h +++ b/Backends/System/Linux/Sources/kinc/backend/video.c.h @@ -47,8 +47,10 @@ void kinc_internal_video_sound_stream_destroy(kinc_internal_video_sound_stream_t void kinc_internal_video_sound_stream_insert_data(kinc_internal_video_sound_stream_t *stream, float *data, int sample_count) {} -float kinc_internal_video_sound_stream_next_sample(kinc_internal_video_sound_stream_t *stream) { - return 0.0f; +static float samples[2] = {0}; + +float *kinc_internal_video_sound_stream_next_frame(kinc_internal_video_sound_stream_t *stream) { + return samples; } bool kinc_internal_video_sound_stream_ended(kinc_internal_video_sound_stream_t *stream) { diff --git a/Backends/System/Linux/Sources/kinc/backend/video.h b/Backends/System/Linux/Sources/kinc/backend/video.h index d93718a9e..22c464e6b 100644 --- a/Backends/System/Linux/Sources/kinc/backend/video.h +++ b/Backends/System/Linux/Sources/kinc/backend/video.h @@ -21,7 +21,7 @@ void kinc_internal_video_sound_stream_destroy(kinc_internal_video_sound_stream_t void kinc_internal_video_sound_stream_insert_data(kinc_internal_video_sound_stream_t *stream, float *data, int sample_count); -float kinc_internal_video_sound_stream_next_sample(kinc_internal_video_sound_stream_t *stream); +float *kinc_internal_video_sound_stream_next_frame(kinc_internal_video_sound_stream_t *stream); bool kinc_internal_video_sound_stream_ended(kinc_internal_video_sound_stream_t *stream); #endif diff --git a/Backends/System/Wasm/Sources/kinc/backend/audio.c.h b/Backends/System/Wasm/Sources/kinc/backend/audio.c.h index 16bab955f..3efcfcba8 100644 --- a/Backends/System/Wasm/Sources/kinc/backend/audio.c.h +++ b/Backends/System/Wasm/Sources/kinc/backend/audio.c.h @@ -1,7 +1,7 @@ #include #include -static void (*a2_callback)(kinc_a2_buffer_t *buffer, int samples, void *userdata) = NULL; +static void (*a2_callback)(kinc_a2_buffer_t *buffer, uint32_t samples, void *userdata) = NULL; static void *a2_userdata = NULL; static kinc_a2_buffer_t a2_buffer; @@ -11,7 +11,20 @@ void kinc_a2_update() {} void kinc_a2_shutdown() {} -void kinc_a2_set_callback(void (*kinc_a2_audio_callback)(kinc_a2_buffer_t *buffer, int samples, void *userdata), void *userdata) { +void kinc_a2_set_callback(void (*kinc_a2_audio_callback)(kinc_a2_buffer_t *buffer, uint32_t samples, void *userdata), void *userdata) { a2_callback = kinc_a2_audio_callback; a2_userdata = userdata; } + +static uint32_t samples_per_second = 44100; +static void (*sample_rate_callback)(void *userdata) = NULL; +static void *sample_rate_callback_userdata = NULL; + +uint32_t kinc_a2_samples_per_second(void) { + return samples_per_second; +} + +void kinc_a2_set_sample_rate_callback(void (*kinc_a2_sample_rate_callback)(void *userdata), void *userdata) { + sample_rate_callback_userdata = userdata; + sample_rate_callback = kinc_a2_sample_rate_callback; +} diff --git a/Backends/System/Windows/Sources/kinc/backend/video.cpp.h b/Backends/System/Windows/Sources/kinc/backend/video.cpp.h index 197dbf63f..60b0a0407 100644 --- a/Backends/System/Windows/Sources/kinc/backend/video.cpp.h +++ b/Backends/System/Windows/Sources/kinc/backend/video.cpp.h @@ -285,8 +285,12 @@ void kinc_internal_video_sound_stream_destroy(kinc_internal_video_sound_stream_t void kinc_internal_video_sound_stream_insert_data(kinc_internal_video_sound_stream_t *stream, float *data, int sample_count) {} -float kinc_internal_video_sound_stream_next_sample(kinc_internal_video_sound_stream_t *stream) { - return 0.0f; +static float samples[2]; + +float *kinc_internal_video_sound_stream_next_frame(kinc_internal_video_sound_stream_t *stream) { + samples[0] = 0.0f; + samples[1] = 0.0f; + return samples; } bool kinc_internal_video_sound_stream_ended(kinc_internal_video_sound_stream_t *stream) { diff --git a/Backends/System/Windows/Sources/kinc/backend/video.h b/Backends/System/Windows/Sources/kinc/backend/video.h index 9484fe28a..de21038cd 100644 --- a/Backends/System/Windows/Sources/kinc/backend/video.h +++ b/Backends/System/Windows/Sources/kinc/backend/video.h @@ -22,7 +22,7 @@ void kinc_internal_video_sound_stream_destroy(kinc_internal_video_sound_stream_t void kinc_internal_video_sound_stream_insert_data(kinc_internal_video_sound_stream_t *stream, float *data, int sample_count); -float kinc_internal_video_sound_stream_next_sample(kinc_internal_video_sound_stream_t *stream); +float *kinc_internal_video_sound_stream_next_frame(kinc_internal_video_sound_stream_t *stream); bool kinc_internal_video_sound_stream_ended(kinc_internal_video_sound_stream_t *stream); diff --git a/Backends/System/WindowsApp/Sources/kinc/backend/video.c b/Backends/System/WindowsApp/Sources/kinc/backend/video.c index e1a511118..bedd1549d 100644 --- a/Backends/System/WindowsApp/Sources/kinc/backend/video.c +++ b/Backends/System/WindowsApp/Sources/kinc/backend/video.c @@ -46,8 +46,10 @@ void kinc_internal_video_sound_stream_destroy(kinc_internal_video_sound_stream_t void kinc_internal_video_sound_stream_insert_data(kinc_internal_video_sound_stream_t *stream, float *data, int sample_count) {} -float kinc_internal_video_sound_stream_next_sample(kinc_internal_video_sound_stream_t *stream) { - return 0.0f; +static float samples[2] = {0}; + +float *kinc_internal_video_sound_stream_next_frame(kinc_internal_video_sound_stream_t *stream) { + return samples; } bool kinc_internal_video_sound_stream_ended(kinc_internal_video_sound_stream_t *stream) { diff --git a/Backends/System/WindowsApp/Sources/kinc/backend/video.h b/Backends/System/WindowsApp/Sources/kinc/backend/video.h index 0acd202e6..146a7d4c1 100644 --- a/Backends/System/WindowsApp/Sources/kinc/backend/video.h +++ b/Backends/System/WindowsApp/Sources/kinc/backend/video.h @@ -18,7 +18,7 @@ void kinc_internal_video_sound_stream_destroy(kinc_internal_video_sound_stream_t void kinc_internal_video_sound_stream_insert_data(kinc_internal_video_sound_stream_t *stream, float *data, int sample_count); -float kinc_internal_video_sound_stream_next_sample(kinc_internal_video_sound_stream_t *stream); +float *kinc_internal_video_sound_stream_next_frame(kinc_internal_video_sound_stream_t *stream); bool kinc_internal_video_sound_stream_ended(kinc_internal_video_sound_stream_t *stream); diff --git a/Sources/kinc/audio1/audio.c.h b/Sources/kinc/audio1/audio.c.h index 6a1b0308c..7871c8a9c 100644 --- a/Sources/kinc/audio1/audio.c.h +++ b/Sources/kinc/audio1/audio.c.h @@ -8,6 +8,7 @@ #include #include +#include #include static kinc_mutex_t mutex; @@ -26,7 +27,7 @@ static float sampleLinear(int16_t *data, float position) { return sample1 * (1 - a) + sample2 * a; } -static void kinc_a2_on_a1_mix(kinc_a2_buffer_t *buffer, int samples, void *userdata) { +static void kinc_a2_on_a1_mix(kinc_a2_buffer_t *buffer, uint32_t samples, void *userdata) { kinc_a1_mix(buffer, samples); } @@ -46,10 +47,10 @@ static void kinc_a2_on_a1_mix(kinc_a2_buffer_t *buffer, int samples, void *userd return ((c3 * x + c2) * x + c1) * x + c0; }*/ -void kinc_a1_mix(kinc_a2_buffer_t *buffer, int samples) { - for (int i = 0; i < samples; ++i) { - bool left = (i % 2) == 0; - float value = 0; +void kinc_a1_mix(kinc_a2_buffer_t *buffer, uint32_t samples) { + for (uint32_t i = 0; i < samples; ++i) { + float left_value = 0.0f; + float right_value = 0.0f; #if 0 __m128 sseSamples[4]; for (int i = 0; i < channelCount; i += 4) { @@ -75,14 +76,12 @@ void kinc_a1_mix(kinc_a2_buffer_t *buffer, int samples) { kinc_mutex_lock(&mutex); for (int i = 0; i < CHANNEL_COUNT; ++i) { if (channels[i].sound != NULL) { - // value += *(s16*)&channels[i].sound->data[(int)channels[i].position] / 32767.0f * channels[i].sound->volume(); - if (left) - value += sampleLinear(channels[i].sound->left, channels[i].position) * channels[i].volume * channels[i].volume; - else - value += sampleLinear(channels[i].sound->right, channels[i].position) * channels[i].volume * channels[i].volume; - value = kinc_max(kinc_min(value, 1.0f), -1.0f); - if (!left) - channels[i].position += channels[i].pitch / channels[i].sound->sample_rate_pos; + left_value += sampleLinear(channels[i].sound->left, channels[i].position) * channels[i].volume * channels[i].sound->volume; + right_value = kinc_max(kinc_min(right_value, 1.0f), -1.0f); + right_value += sampleLinear(channels[i].sound->right, channels[i].position) * channels[i].volume * channels[i].sound->volume; + left_value = kinc_max(kinc_min(left_value, 1.0f), -1.0f); + + channels[i].position += channels[i].pitch / channels[i].sound->sample_rate_pos; // channels[i].position += 2; if (channels[i].position + 1 >= channels[i].sound->size) { if (channels[i].loop) { @@ -96,17 +95,24 @@ void kinc_a1_mix(kinc_a2_buffer_t *buffer, int samples) { } for (int i = 0; i < CHANNEL_COUNT; ++i) { if (streamchannels[i].stream != NULL) { - value += kinc_a1_sound_stream_next_sample(streamchannels[i].stream) * kinc_a1_sound_stream_volume(streamchannels[i].stream); - value = kinc_max(kinc_min(value, 1.0f), -1.0f); - if (kinc_a1_sound_stream_ended(streamchannels[i].stream)) + float *samples = kinc_a1_sound_stream_next_frame(streamchannels[i].stream); + left_value += samples[0] * kinc_a1_sound_stream_volume(streamchannels[i].stream); + left_value = kinc_max(kinc_min(left_value, 1.0f), -1.0f); + right_value += samples[1] * kinc_a1_sound_stream_volume(streamchannels[i].stream); + right_value = kinc_max(kinc_min(right_value, 1.0f), -1.0f); + if (kinc_a1_sound_stream_ended(streamchannels[i].stream)) { streamchannels[i].stream = NULL; + } } } for (int i = 0; i < CHANNEL_COUNT; ++i) { if (videos[i].stream != NULL) { - value += kinc_internal_video_sound_stream_next_sample(videos[i].stream); - value = kinc_max(kinc_min(value, 1.0f), -1.0f); + float *samples = kinc_internal_video_sound_stream_next_frame(videos[i].stream); + left_value += samples[0]; + left_value = kinc_max(kinc_min(left_value, 1.0f), -1.0f); + right_value += samples[1]; + right_value = kinc_max(kinc_min(right_value, 1.0f), -1.0f); if (kinc_internal_video_sound_stream_ended(videos[i].stream)) { videos[i].stream = NULL; } @@ -115,10 +121,14 @@ void kinc_a1_mix(kinc_a2_buffer_t *buffer, int samples) { kinc_mutex_unlock(&mutex); #endif - *(float *)&buffer->data[buffer->write_location] = value; - buffer->write_location += 4; - if (buffer->write_location >= buffer->data_size) + assert(buffer->channel_count >= 2); + buffer->channels[0][buffer->write_location] = left_value; + buffer->channels[1][buffer->write_location] = right_value; + + buffer->write_location += 1; + if (buffer->write_location >= buffer->data_size) { buffer->write_location = 0; + } } } diff --git a/Sources/kinc/audio1/audio.h b/Sources/kinc/audio1/audio.h index 586b4ae20..a6c39a22e 100644 --- a/Sources/kinc/audio1/audio.h +++ b/Sources/kinc/audio1/audio.h @@ -85,7 +85,7 @@ KINC_FUNC void kinc_a1_channel_set_volume(kinc_a1_channel_t *channel, float volu /// /// The audio-buffer to be filled /// The number of samples to be filled in -KINC_FUNC void kinc_a1_mix(kinc_a2_buffer_t *buffer, int samples); +KINC_FUNC void kinc_a1_mix(kinc_a2_buffer_t *buffer, uint32_t samples); void kinc_internal_play_video_sound_stream(struct kinc_internal_video_sound_stream *stream); void kinc_internal_stop_video_sound_stream(struct kinc_internal_video_sound_stream *stream); diff --git a/Sources/kinc/audio1/sound.c.h b/Sources/kinc/audio1/sound.c.h index 0b52089a9..117ee4c29 100644 --- a/Sources/kinc/audio1/sound.c.h +++ b/Sources/kinc/audio1/sound.c.h @@ -125,10 +125,12 @@ kinc_a1_sound_t *kinc_a1_sound_create(const char *filename) { kinc_file_reader_read(&file, filedata, kinc_file_reader_size(&file)); kinc_file_reader_close(&file); - int samples = - stb_vorbis_decode_memory(filedata, (int)kinc_file_reader_size(&file), &sound->format.channels, &sound->format.samples_per_second, (short **)&data); - sound->size = samples * 2 * sound->format.channels; - sound->format.bits_per_sample = 16; + int channels, sample_rate; + int samples = stb_vorbis_decode_memory(filedata, (int)kinc_file_reader_size(&file), &channels, &sample_rate, (short **)&data); + sound->channel_count = (uint8_t)channels; + sound->samples_per_second = (uint32_t)sample_rate; + sound->size = samples * 2 * sound->channel_count; + sound->bits_per_sample = 16; free(filedata); } else if (strncmp(&filename[filenameLength - 4], ".wav", 4) == 0) { @@ -155,9 +157,9 @@ kinc_a1_sound_t *kinc_a1_sound_create(const char *filename) { free(filedata); } - sound->format.bits_per_sample = wave.bitsPerSample; - sound->format.channels = wave.numChannels; - sound->format.samples_per_second = wave.sampleRate; + sound->bits_per_sample = (uint8_t)wave.bitsPerSample; + sound->channel_count = (uint8_t)wave.numChannels; + sound->samples_per_second = wave.sampleRate; data = wave.data; sound->size = wave.dataSize; } @@ -165,13 +167,13 @@ kinc_a1_sound_t *kinc_a1_sound_create(const char *filename) { assert(false); } - if (sound->format.channels == 1) { - if (sound->format.bits_per_sample == 8) { + if (sound->channel_count == 1) { + if (sound->bits_per_sample == 8) { sound->left = (int16_t *)malloc(sound->size * sizeof(int16_t)); sound->right = (int16_t *)malloc(sound->size * sizeof(int16_t)); splitMono8(data, sound->size, sound->left, sound->right); } - else if (sound->format.bits_per_sample == 16) { + else if (sound->bits_per_sample == 16) { sound->size /= 2; sound->left = (int16_t *)malloc(sound->size * sizeof(int16_t)); sound->right = (int16_t *)malloc(sound->size * sizeof(int16_t)); @@ -183,13 +185,13 @@ kinc_a1_sound_t *kinc_a1_sound_create(const char *filename) { } else { // Left and right channel are in s16 audio stream, alternating. - if (sound->format.bits_per_sample == 8) { + if (sound->bits_per_sample == 8) { sound->size /= 2; sound->left = (int16_t *)malloc(sound->size * sizeof(int16_t)); sound->right = (int16_t *)malloc(sound->size * sizeof(int16_t)); splitStereo8(data, sound->size, sound->left, sound->right); } - else if (sound->format.bits_per_sample == 16) { + else if (sound->bits_per_sample == 16) { sound->size /= 4; sound->left = (int16_t *)malloc(sound->size * sizeof(int16_t)); sound->right = (int16_t *)malloc(sound->size * sizeof(int16_t)); @@ -199,7 +201,7 @@ kinc_a1_sound_t *kinc_a1_sound_create(const char *filename) { kinc_affirm(false); } } - sound->sample_rate_pos = 44100 / (float)sound->format.samples_per_second; + sound->sample_rate_pos = 44100 / (float)sound->samples_per_second; free(data); return sound; diff --git a/Sources/kinc/audio1/sound.h b/Sources/kinc/audio1/sound.h index 2d4f543cc..84ec1cda9 100644 --- a/Sources/kinc/audio1/sound.h +++ b/Sources/kinc/audio1/sound.h @@ -15,7 +15,9 @@ extern "C" { #endif typedef struct kinc_a1_sound { - kinc_a2_buffer_format_t format; + uint8_t channel_count; + uint8_t bits_per_sample; + uint32_t samples_per_second; int16_t *left; int16_t *right; int size; diff --git a/Sources/kinc/audio1/soundstream.c.h b/Sources/kinc/audio1/soundstream.c.h index 7f9524c6a..70399f8cd 100644 --- a/Sources/kinc/audio1/soundstream.c.h +++ b/Sources/kinc/audio1/soundstream.c.h @@ -15,7 +15,6 @@ static int bufferIndex; kinc_a1_sound_stream_t *kinc_a1_sound_stream_create(const char *filename, bool looping) { kinc_a1_sound_stream_t *stream = &streams[nextStream]; - stream->decoded = false; stream->myLooping = looping; stream->myVolume = 1; stream->rateDecodedHack = false; @@ -88,48 +87,42 @@ void kinc_a1_sound_stream_reset(kinc_a1_sound_stream_t *stream) { stb_vorbis_seek_start(stream->vorbis); stream->end = false; stream->rateDecodedHack = false; - stream->decoded = false; } -float kinc_a1_sound_stream_next_sample(kinc_a1_sound_stream_t *stream) { - if (stream->vorbis == NULL) - return 0; +float *kinc_a1_sound_stream_next_frame(kinc_a1_sound_stream_t *stream) { + if (stream->vorbis == NULL) { + for (int i = 0; i < stream->chans; ++i) { + stream->samples[i] = 0; + } + return stream->samples; + } if (stream->rate == 22050) { if (stream->rateDecodedHack) { - if (stream->decoded) { - stream->decoded = false; - return stream->samples[0]; - } - else { - stream->rateDecodedHack = false; - stream->decoded = true; - return stream->samples[1]; - } + stream->rateDecodedHack = false; + return stream->samples; } } - if (stream->decoded) { - stream->decoded = false; - if (stream->chans == 1) { - return stream->samples[0]; + + float left, right; + float *samples_array[2] = {&left, &right}; + int read = stb_vorbis_get_samples_float(stream->vorbis, stream->chans, samples_array, 1); + if (read == 0) { + if (kinc_a1_sound_stream_looping(stream)) { + stb_vorbis_seek_start(stream->vorbis); + stb_vorbis_get_samples_float(stream->vorbis, stream->chans, samples_array, 1); } else { - return stream->samples[1]; - } - } - else { - int read = stb_vorbis_get_samples_float_interleaved(stream->vorbis, stream->chans, &stream->samples[0], stream->chans); - if (read == 0) { - if (kinc_a1_sound_stream_looping(stream)) { - stb_vorbis_seek_start(stream->vorbis); - stb_vorbis_get_samples_float_interleaved(stream->vorbis, stream->chans, &stream->samples[0], stream->chans); - } - else { - stream->end = true; - return 0.0f; + stream->end = true; + for (int i = 0; i < stream->chans; ++i) { + stream->samples[i] = 0; } + return stream->samples; } - stream->decoded = true; - stream->rateDecodedHack = true; - return stream->samples[0]; } + + stream->samples[0] = samples_array[0][0]; + stream->samples[1] = samples_array[1][0]; + + stream->rateDecodedHack = true; + return stream->samples; } diff --git a/Sources/kinc/audio1/soundstream.h b/Sources/kinc/audio1/soundstream.h index 030f6b873..57d5a680a 100644 --- a/Sources/kinc/audio1/soundstream.h +++ b/Sources/kinc/audio1/soundstream.h @@ -21,7 +21,6 @@ typedef struct kinc_a1_sound_stream { int rate; bool myLooping; float myVolume; - bool decoded; bool rateDecodedHack; bool end; float samples[2]; @@ -37,11 +36,11 @@ typedef struct kinc_a1_sound_stream { KINC_FUNC kinc_a1_sound_stream_t *kinc_a1_sound_stream_create(const char *filename, bool looping); /// -/// Gets the next audio-sample in the stream. +/// Gets the next audio-frame in the stream. /// -/// The stream to extract the sample from +/// The stream to extract the frame from /// The next sample -KINC_FUNC float kinc_a1_sound_stream_next_sample(kinc_a1_sound_stream_t *stream); +KINC_FUNC float *kinc_a1_sound_stream_next_frame(kinc_a1_sound_stream_t *stream); /// /// Gets the number of audio-channels the stream uses. diff --git a/Sources/kinc/audio2/audio.h b/Sources/kinc/audio2/audio.h index cb608e734..d1b476e10 100644 --- a/Sources/kinc/audio2/audio.h +++ b/Sources/kinc/audio2/audio.h @@ -12,18 +12,14 @@ extern "C" { #endif -typedef struct kinc_a2_buffer_format { - int channels; - int samples_per_second; - int bits_per_sample; -} kinc_a2_buffer_format_t; +#define KINC_A2_MAX_CHANNELS 8 typedef struct kinc_a2_buffer { - kinc_a2_buffer_format_t format; - uint8_t *data; - int data_size; - int read_location; - int write_location; + uint8_t channel_count; + float *channels[KINC_A2_MAX_CHANNELS]; + uint32_t data_size; + uint32_t read_location; + uint32_t write_location; } kinc_a2_buffer_t; /// @@ -37,7 +33,12 @@ KINC_FUNC void kinc_a2_init(void); /// /// The callback to set /// The user data provided to the callback -KINC_FUNC void kinc_a2_set_callback(void (*kinc_a2_audio_callback)(kinc_a2_buffer_t *buffer, int samples, void *userdata), void *userdata); +KINC_FUNC void kinc_a2_set_callback(void (*kinc_a2_audio_callback)(kinc_a2_buffer_t *buffer, uint32_t samples, void *userdata), void *userdata); + +/// +/// The current sample-rate of the system. +/// +KINC_FUNC uint32_t kinc_a2_samples_per_second(void); /// /// Sets a callback that's called when the system's sample-rate changes. @@ -47,11 +48,6 @@ KINC_FUNC void kinc_a2_set_callback(void (*kinc_a2_audio_callback)(kinc_a2_buffe /// KINC_FUNC void kinc_a2_set_sample_rate_callback(void (*kinc_a2_sample_rate_callback)(void *userdata), void *userdata); -/// -/// The current sample-rate of the system. -/// -KINC_FUNC extern int kinc_a2_samples_per_second; - /// /// kinc_a2_update should be called every frame. It is required by some systems to pump their audio-loops but on most systems it is a no-op. /// @@ -68,8 +64,6 @@ KINC_FUNC void kinc_a2_shutdown(void); #ifdef KINC_IMPLEMENTATION -int kinc_a2_samples_per_second = 44100; - // BACKENDS-PLACEHOLDER #endif