Commit 6caa823e authored by David Reid's avatar David Reid

OSS: Work on the blocking read/write API.

parent 4e6f702f
...@@ -17956,7 +17956,7 @@ mal_result mal_device_init__oss(mal_context* pContext, mal_device_type type, con ...@@ -17956,7 +17956,7 @@ mal_result mal_device_init__oss(mal_context* pContext, mal_device_type type, con
case mal_format_s16: ossFormat = (mal_is_little_endian()) ? AFMT_S16_LE : AFMT_S16_BE; break; case mal_format_s16: ossFormat = (mal_is_little_endian()) ? AFMT_S16_LE : AFMT_S16_BE; break;
case mal_format_s24: ossFormat = (mal_is_little_endian()) ? AFMT_S32_LE : AFMT_S32_BE; break; case mal_format_s24: ossFormat = (mal_is_little_endian()) ? AFMT_S32_LE : AFMT_S32_BE; break;
case mal_format_s32: ossFormat = (mal_is_little_endian()) ? AFMT_S32_LE : AFMT_S32_BE; break; case mal_format_s32: ossFormat = (mal_is_little_endian()) ? AFMT_S32_LE : AFMT_S32_BE; break;
case mal_format_f32: ossFormat = (mal_is_little_endian()) ? AFMT_S32_LE : AFMT_S32_BE; break; case mal_format_f32: ossFormat = (mal_is_little_endian()) ? AFMT_S16_LE : AFMT_S16_BE; break;
case mal_format_u8: case mal_format_u8:
default: ossFormat = AFMT_U8; break; default: ossFormat = AFMT_U8; break;
} }
...@@ -18054,30 +18054,6 @@ mal_result mal_device_init__oss(mal_context* pContext, mal_device_type type, con ...@@ -18054,30 +18054,6 @@ mal_result mal_device_init__oss(mal_context* pContext, mal_device_type type, con
return MAL_SUCCESS; return MAL_SUCCESS;
} }
mal_result mal_device_start__oss(mal_device* pDevice)
{
mal_assert(pDevice != NULL);
// The device is started by the next calls to read() and write(). For playback it's simple - just read
// data from the client, then write it to the device with write() which will in turn start the device.
// For capture it's a bit less intuitive - we do nothing (it'll be started automatically by the first
// call to read().
if (pDevice->type == mal_device_type_playback) {
// Playback.
mal_device__read_frames_from_client(pDevice, pDevice->oss.fragmentSizeInFrames, pDevice->oss.pIntermediaryBuffer);
int bytesWritten = write(pDevice->oss.fd, pDevice->oss.pIntermediaryBuffer, pDevice->oss.fragmentSizeInFrames * pDevice->internalChannels * mal_get_bytes_per_sample(pDevice->internalFormat));
if (bytesWritten == -1) {
return mal_post_error(pDevice, MAL_LOG_LEVEL_ERROR, "[OSS] Failed to send initial chunk of data to the device.", MAL_FAILED_TO_SEND_DATA_TO_DEVICE);
}
} else {
// Capture. Do nothing.
}
return MAL_SUCCESS;
}
mal_result mal_device_stop__oss(mal_device* pDevice) mal_result mal_device_stop__oss(mal_device* pDevice)
{ {
mal_assert(pDevice != NULL); mal_assert(pDevice != NULL);
...@@ -18101,46 +18077,23 @@ mal_result mal_device_stop__oss(mal_device* pDevice) ...@@ -18101,46 +18077,23 @@ mal_result mal_device_stop__oss(mal_device* pDevice)
return MAL_SUCCESS; return MAL_SUCCESS;
} }
mal_result mal_device_break_main_loop__oss(mal_device* pDevice) mal_result mal_device_write__oss(mal_device* pDevice, const void* pPCMFrames, mal_uint32 pcmFrameCount)
{ {
mal_assert(pDevice != NULL); int resultOSS = write(pDevice->oss.fd, pPCMFrames, pcmFrameCount * mal_get_bytes_per_frame(pDevice->internalFormat, pDevice->internalChannels));
if (resultOSS < 0) {
return mal_post_error(pDevice, MAL_LOG_LEVEL_ERROR, "[OSS] Failed to send data from the client to the device.", MAL_FAILED_TO_SEND_DATA_TO_DEVICE);
}
pDevice->oss.breakFromMainLoop = MAL_TRUE;
return MAL_SUCCESS; return MAL_SUCCESS;
} }
mal_result mal_device_main_loop__oss(mal_device* pDevice) mal_result mal_device_read__oss(mal_device* pDevice, void* pPCMFrames, mal_uint32 pcmFrameCount)
{ {
mal_assert(pDevice != NULL); int resultOSS = read(pDevice->oss.fd, pPCMFrames, pcmFrameCount * mal_get_bytes_per_frame(pDevice->internalFormat, pDevice->internalChannels));
if (resultOSS < 0) {
pDevice->oss.breakFromMainLoop = MAL_FALSE;
while (!pDevice->oss.breakFromMainLoop) {
// Break from the main loop if the device isn't started anymore. Likely what's happened is the application
// has requested that the device be stopped.
if (!mal_device_is_started(pDevice)) {
break;
}
if (pDevice->type == mal_device_type_playback) {
// Playback.
mal_device__read_frames_from_client(pDevice, pDevice->oss.fragmentSizeInFrames, pDevice->oss.pIntermediaryBuffer);
int bytesWritten = write(pDevice->oss.fd, pDevice->oss.pIntermediaryBuffer, pDevice->oss.fragmentSizeInFrames * pDevice->internalChannels * mal_get_bytes_per_sample(pDevice->internalFormat));
if (bytesWritten < 0) {
return mal_post_error(pDevice, MAL_LOG_LEVEL_ERROR, "[OSS] Failed to send data from the client to the device.", MAL_FAILED_TO_SEND_DATA_TO_DEVICE);
}
} else {
// Capture.
int bytesRead = read(pDevice->oss.fd, pDevice->oss.pIntermediaryBuffer, pDevice->oss.fragmentSizeInFrames * mal_get_bytes_per_sample(pDevice->internalFormat));
if (bytesRead < 0) {
return mal_post_error(pDevice, MAL_LOG_LEVEL_ERROR, "[OSS] Failed to read data from the device to be sent to the client.", MAL_FAILED_TO_READ_DATA_FROM_DEVICE); return mal_post_error(pDevice, MAL_LOG_LEVEL_ERROR, "[OSS] Failed to read data from the device to be sent to the client.", MAL_FAILED_TO_READ_DATA_FROM_DEVICE);
} }
mal_uint32 framesRead = (mal_uint32)bytesRead / pDevice->internalChannels / mal_get_bytes_per_sample(pDevice->internalFormat);
mal_device__send_frames_to_client(pDevice, framesRead, pDevice->oss.pIntermediaryBuffer);
}
}
return MAL_SUCCESS; return MAL_SUCCESS;
} }
...@@ -18157,13 +18110,13 @@ mal_result mal_context_init__oss(mal_context* pContext) ...@@ -18157,13 +18110,13 @@ mal_result mal_context_init__oss(mal_context* pContext)
{ {
mal_assert(pContext != NULL); mal_assert(pContext != NULL);
// Try opening a temporary device first so we can get version information. This is closed at the end. /* Try opening a temporary device first so we can get version information. This is closed at the end. */
int fd = mal_open_temp_device__oss(); int fd = mal_open_temp_device__oss();
if (fd == -1) { if (fd == -1) {
return mal_context_post_error(pContext, NULL, MAL_LOG_LEVEL_ERROR, "[OSS] Failed to open temporary device for retrieving system properties.", MAL_NO_BACKEND); // Looks liks OSS isn't installed, or there are no available devices. return mal_context_post_error(pContext, NULL, MAL_LOG_LEVEL_ERROR, "[OSS] Failed to open temporary device for retrieving system properties.", MAL_NO_BACKEND); /* Looks liks OSS isn't installed, or there are no available devices. */
} }
// Grab the OSS version. /* Grab the OSS version. */
int ossVersion = 0; int ossVersion = 0;
int result = ioctl(fd, OSS_GETVERSION, &ossVersion); int result = ioctl(fd, OSS_GETVERSION, &ossVersion);
if (result == -1) { if (result == -1) {
...@@ -18180,15 +18133,15 @@ mal_result mal_context_init__oss(mal_context* pContext) ...@@ -18180,15 +18133,15 @@ mal_result mal_context_init__oss(mal_context* pContext)
pContext->onGetDeviceInfo = mal_context_get_device_info__oss; pContext->onGetDeviceInfo = mal_context_get_device_info__oss;
pContext->onDeviceInit = mal_device_init__oss; pContext->onDeviceInit = mal_device_init__oss;
pContext->onDeviceUninit = mal_device_uninit__oss; pContext->onDeviceUninit = mal_device_uninit__oss;
pContext->onDeviceStart = mal_device_start__oss; pContext->onDeviceStart = NULL; /* Not required for synchronous backends. */
pContext->onDeviceStop = mal_device_stop__oss; pContext->onDeviceStop = mal_device_stop__oss;
pContext->onDeviceBreakMainLoop = mal_device_break_main_loop__oss; pContext->onDeviceWrite = mal_device_write__oss;
pContext->onDeviceMainLoop = mal_device_main_loop__oss; pContext->onDeviceRead = mal_device_read__oss;
close(fd); close(fd);
return MAL_SUCCESS; return MAL_SUCCESS;
} }
#endif // OSS #endif /* OSS */
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#include <stdio.h> #include <stdio.h>
#define MINI_AL_IMPLEMENTATION
#include "../mini_al.h"
#define DR_WAV_IMPLEMENTATION #define DR_WAV_IMPLEMENTATION
#include "../extras/dr_wav.h" #include "../extras/dr_wav.h"
#define MINI_AL_IMPLEMENTATION
#include "../mini_al.h"
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
(void)argc; (void)argc;
(void)argv; (void)argv;
mal_result result; mal_result result;
mal_backend backend = mal_backend_alsa; mal_backend backend = mal_backend_oss;
mal_device_config deviceConfig = mal_device_config_init_default(NULL); mal_device_config deviceConfig = mal_device_config_init_default(NULL);
deviceConfig.format = mal_format_f32; deviceConfig.format = mal_format_f32;
deviceConfig.bufferSizeInFrames = 1024*4; deviceConfig.bufferSizeInFrames = 1024*8;
//deviceConfig.bufferSizeInMilliseconds = 80; //deviceConfig.bufferSizeInMilliseconds = 80;
deviceConfig.periods = 2; deviceConfig.periods = 2;
deviceConfig.shareMode = mal_share_mode_shared; deviceConfig.shareMode = mal_share_mode_shared;
...@@ -32,23 +32,27 @@ int main(int argc, char** argv) ...@@ -32,23 +32,27 @@ int main(int argc, char** argv)
printf("Is Passthrough: %s\n", device.dsp.isPassthrough ? "YES" : "NO"); printf("Is Passthrough: %s\n", device.dsp.isPassthrough ? "YES" : "NO");
printf("Format: %s -> %s\n", mal_get_format_name(device.format), mal_get_format_name(device.internalFormat)); printf("Format: %s -> %s\n", mal_get_format_name(device.format), mal_get_format_name(device.internalFormat));
printf("Channels: %d -> %d\n", device.channels, device.internalChannels);
printf("Sample Rate: %d -> %d\n", device.sampleRate, device.internalSampleRate); printf("Sample Rate: %d -> %d\n", device.sampleRate, device.internalSampleRate);
printf("Buffer Size In Frames: %d\n", device.bufferSizeInFrames); printf("Buffer Size In Frames: %d\n", device.bufferSizeInFrames);
drwav* pWav = drwav_open_file("res/private/song1_short_s16.wav"); mal_decoder_config decoderConfig = mal_decoder_config_init(mal_format_f32, device.channels, device.sampleRate);
if (pWav == NULL) { mal_decoder decoder;
printf("LOADING DECODER\n");
result = mal_decoder_init_file("res/sine_s16_mono_48000.wav", &decoderConfig, &decoder);
if (result != MAL_SUCCESS) {
printf("Failed to load sound file.\n"); printf("Failed to load sound file.\n");
} }
/* The device is started by just writing data to it. In our case we are just writing a sine wave. */ /* The device is started by just writing data to it. In our case we are just writing a sine wave. */
mal_sine_wave sineWave; mal_sine_wave sineWave;
mal_sine_wave_init(0.25, 400, device.sampleRate, &sineWave); mal_sine_wave_init(0.25, 400, device.sampleRate/2, &sineWave);
mal_bool32 stopped = MAL_FALSE; mal_bool32 stopped = MAL_FALSE;
while (!stopped) { while (!stopped) {
float buffer[4096*4]; float* pBuffer = buffer; float buffer[1024*32]; float* pBuffer = buffer;
mal_uint32 frameCount = (mal_uint32)mal_sine_wave_read_f32_ex(&sineWave, mal_countof(buffer) / device.channels, device.channels, mal_stream_layout_interleaved, &pBuffer); //mal_uint32 frameCount = (mal_uint32)mal_sine_wave_read_f32_ex(&sineWave, mal_countof(buffer) / device.channels, device.channels, mal_stream_layout_interleaved, &pBuffer);
//mal_uint32 frameCount = (mal_uint32)drwav_read_pcm_frames_f32(pWav, mal_countof(buffer) / device.channels, pBuffer); mal_uint32 frameCount = (mal_uint32)mal_decoder_read_pcm_frames(&decoder, mal_countof(buffer) / device.channels, pBuffer);
result = mal_device_write(&device, pBuffer, frameCount); result = mal_device_write(&device, pBuffer, frameCount);
if (result != MAL_SUCCESS) { if (result != MAL_SUCCESS) {
...@@ -85,7 +89,7 @@ int main(int argc, char** argv) ...@@ -85,7 +89,7 @@ int main(int argc, char** argv)
int counter = 0; int counter = 0;
mal_bool32 stopped = MAL_FALSE; mal_bool32 stopped = MAL_FALSE;
while (!stopped) { while (!stopped) {
float buffer[1024*16]; float buffer[1024*4];
mal_uint32 frameCount = mal_countof(buffer) / device.channels; mal_uint32 frameCount = mal_countof(buffer) / device.channels;
result = mal_device_read(&device, buffer, frameCount); result = mal_device_read(&device, buffer, frameCount);
...@@ -102,7 +106,7 @@ int main(int argc, char** argv) ...@@ -102,7 +106,7 @@ int main(int argc, char** argv)
} }
} }
drwav_close(pWav); mal_decoder_uninit(&decoder);
#endif #endif
printf("DONE\n"); printf("DONE\n");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment