173 #ifndef DR_SIZED_TYPES_DEFINED
174 #define DR_SIZED_TYPES_DEFINED
175 #if defined(_MSC_VER) && _MSC_VER < 1600
201 #ifndef DR_AUDIO_MAX_CHANNEL_COUNT
202 #define DR_AUDIO_MAX_CHANNEL_COUNT 16
205 #ifndef DR_AUDIO_MAX_EVENT_COUNT
206 #define DR_AUDIO_MAX_EVENT_COUNT 16
209 #define DR_AUDIO_EVENT_ID_STOP 0xFFFFFFFFFFFFFFFFULL
210 #define DR_AUDIO_EVENT_ID_PLAY 0xFFFFFFFFFFFFFFFEULL
213 #define DRA_RESULT_SUCCESS 0
214 #define DRA_RESULT_UNKNOWN_ERROR -1
215 #define DRA_RESULT_INVALID_ARGS -2
216 #define DRA_RESULT_OUT_OF_MEMORY -3
217 #define DRA_RESULT_FAILED_TO_OPEN_FILE -4
218 #define DRA_RESULT_NO_BACKEND -1024
219 #define DRA_RESULT_NO_BACKEND_DEVICE -1025
220 #define DRA_RESULT_NO_DECODER -1026
221 #define DRA_FAILED(result) ((result) != 0)
222 #define DRA_SUCCEEDED(result) ((result) == 0)
224 #define DRA_MIXER_FLAG_PAUSED (1 << 0)
746 #ifndef DR_AUDIO_NO_STDIO
763 #ifndef DR_AUDIO_NO_STDIO
892 #ifndef DR_AUDIO_NO_STDIO
936 #ifdef DR_AUDIO_IMPLEMENTATION
943 #define DR_AUDIO_INLINE static __forceinline
945 #define DR_AUDIO_INLINE static inline
948 #define DR_AUDIO_DEFAULT_CHANNEL_COUNT 2
949 #define DR_AUDIO_DEFAULT_SAMPLE_RATE 48000
950 #define DR_AUDIO_DEFAULT_LATENCY 100 // Milliseconds. TODO: Test this with very low values. DirectSound appears to not signal the fragment events when it's too small. With values of about 20 it sounds crackly.
951 #define DR_AUDIO_DEFAULT_FRAGMENT_COUNT 3 // The hardware buffer is divided up into latency-sized blocks. This controls that number. Must be at least 2.
953 #define DR_AUDIO_BACKEND_TYPE_NULL 0
954 #define DR_AUDIO_BACKEND_TYPE_DSOUND 1
955 #define DR_AUDIO_BACKEND_TYPE_ALSA 2
958 #define DR_AUDIO_HAS_WAV
959 #ifndef DR_WAV_NO_STDIO
960 #define DR_AUDIO_HAS_WAV_STDIO
964 #define DR_AUDIO_HAS_FLAC
965 #ifndef DR_FLAC_NO_STDIO
966 #define DR_AUDIO_HAS_FLAC_STDIO
969 #ifdef STB_VORBIS_INCLUDE_STB_VORBIS_H
970 #define DR_AUDIO_HAS_VORBIS
971 #ifndef STB_VORBIS_NO_STDIO
972 #define DR_AUDIO_HAS_VORBIS_STDIO
976 #if defined(DR_AUDIO_HAS_WAV) || \
977 defined(DR_AUDIO_HAS_FLAC) || \
978 defined(DR_AUDIO_HAS_VORBIS)
979 #define DR_AUDIO_HAS_EXTERNAL_DECODER
984 DR_AUDIO_INLINE
unsigned int dra_next_power_of_2(
unsigned int x)
997 DR_AUDIO_INLINE
unsigned int dra_prev_power_of_2(
unsigned int x)
999 return dra_next_power_of_2(x) >> 1;
1003 DR_AUDIO_INLINE
float dra_mixf(
float x,
float y,
float a)
1005 return x*(1-a) + y*a;
1018 #define DR_AUDIO_BASE_BACKEND_ATTRIBS \
1019 unsigned int type; \
1021 DR_AUDIO_BASE_BACKEND_ATTRIBS
1027 #define DR_AUDIO_BASE_BACKEND_DEVICE_ATTRIBS \
1028 dra_backend* pBackend; \
1029 dra_device_type type; \
1030 unsigned int channels; \
1031 unsigned int sampleRate; \
1032 unsigned int fragmentCount; \
1033 unsigned int samplesPerFragment; \
1035 DR_AUDIO_BASE_BACKEND_DEVICE_ATTRIBS
1043 #include <windows.h>
1046 typedef DWORD (* dra_thread_entry_proc)(LPVOID pData);
1048 dra_thread dra_thread_create(dra_thread_entry_proc entryProc,
void* pData)
1050 return (
dra_thread)CreateThread(
NULL, 0, (LPTHREAD_START_ROUTINE)entryProc, pData, 0,
NULL);
1055 CloseHandle((HANDLE)thread);
1060 WaitForSingleObject((HANDLE)thread, INFINITE);
1071 CloseHandle((HANDLE)mutex);
1076 WaitForSingleObject((HANDLE)mutex, INFINITE);
1081 SetEvent((HANDLE)mutex);
1087 return (
void*)CreateSemaphoreA(
NULL, initialValue, LONG_MAX,
NULL);
1092 CloseHandle((HANDLE)semaphore);
1097 return WaitForSingleObject((HANDLE)semaphore, INFINITE) == WAIT_OBJECT_0;
1102 return ReleaseSemaphore((HANDLE)semaphore, 1,
NULL) != 0;
1108 #ifndef DR_AUDIO_NO_DSOUND
1109 #define DR_AUDIO_ENABLE_DSOUND
1113 GUID DR_AUDIO_GUID_NULL = {0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
1115 static GUID _g_draGUID_IID_DirectSoundNotify = {0xb0210783, 0x89cd, 0x11d0, {0xaf, 0x08, 0x00, 0xa0, 0xc9, 0x25, 0xcd, 0x16}};
1116 static GUID _g_draGUID_IID_IDirectSoundCaptureBuffer8 = {0x00990df4, 0x0dbb, 0x4872, {0x83, 0x3e, 0x6d, 0x30, 0x3e, 0x80, 0xae, 0xb6}};
1117 static GUID _g_draGUID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = {0x00000003, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
1120 static GUID g_draGUID_IID_DirectSoundNotify = _g_draGUID_IID_DirectSoundNotify;
1121 static GUID g_draGUID_IID_IDirectSoundCaptureBuffer8 = _g_draGUID_IID_IDirectSoundCaptureBuffer8;
1124 static GUID* g_draGUID_IID_DirectSoundNotify = &_g_draGUID_IID_DirectSoundNotify;
1125 static GUID* g_draGUID_IID_IDirectSoundCaptureBuffer8 = &_g_draGUID_IID_IDirectSoundCaptureBuffer8;
1129 typedef HRESULT (WINAPI * pDirectSoundCreate8Proc)(LPCGUID pcGuidDevice, LPDIRECTSOUND8 *ppDS8, LPUNKNOWN pUnkOuter);
1130 typedef HRESULT (WINAPI * pDirectSoundEnumerateAProc)(LPDSENUMCALLBACKA pDSEnumCallback, LPVOID pContext);
1131 typedef HRESULT (WINAPI * pDirectSoundCaptureCreate8Proc)(LPCGUID pcGuidDevice, LPDIRECTSOUNDCAPTURE8 *ppDSC8, LPUNKNOWN pUnkOuter);
1132 typedef HRESULT (WINAPI * pDirectSoundCaptureEnumerateAProc)(LPDSENUMCALLBACKA pDSEnumCallback, LPVOID pContext);
1136 DR_AUDIO_BASE_BACKEND_ATTRIBS
1141 pDirectSoundCreate8Proc pDirectSoundCreate8;
1142 pDirectSoundEnumerateAProc pDirectSoundEnumerateA;
1143 pDirectSoundCaptureCreate8Proc pDirectSoundCaptureCreate8;
1144 pDirectSoundCaptureEnumerateAProc pDirectSoundCaptureEnumerateA;
1145 } dra_backend_dsound;
1149 DR_AUDIO_BASE_BACKEND_DEVICE_ATTRIBS
1156 LPDIRECTSOUNDBUFFER pDSPrimaryBuffer;
1160 LPDIRECTSOUNDBUFFER pDSSecondaryBuffer;
1164 LPDIRECTSOUNDCAPTURE8 pDSCapture;
1167 LPDIRECTSOUNDCAPTUREBUFFER8 pDSCaptureBuffer;
1171 LPDIRECTSOUNDNOTIFY pDSNotify;
1174 HANDLE pNotifyEvents[DR_AUDIO_DEFAULT_FRAGMENT_COUNT];
1180 unsigned int currentFragmentIndex;
1188 } dra_backend_device_dsound;
1192 unsigned int deviceID;
1193 unsigned int counter;
1195 } dra_dsound__device_enum_data;
1197 static BOOL
CALLBACK dra_dsound__get_device_guid_by_id__callback(LPGUID lpGuid, LPCSTR lpcstrDescription, LPCSTR lpcstrModule, LPVOID lpContext)
1199 (void)lpcstrDescription;
1202 dra_dsound__device_enum_data* pData = (dra_dsound__device_enum_data*)lpContext;
1203 assert(pData !=
NULL);
1205 if (pData->counter == pData->deviceID) {
1206 pData->pGuid = lpGuid;
1210 pData->counter += 1;
1214 const GUID* dra_dsound__get_playback_device_guid_by_id(
dra_backend* pBackend,
unsigned int deviceID)
1220 if (deviceID == 0) {
1224 dra_backend_dsound* pBackendDS = (dra_backend_dsound*)pBackend;
1225 if (pBackendDS ==
NULL) {
1232 dra_dsound__device_enum_data data = {0};
1233 data.deviceID = deviceID;
1234 pBackendDS->pDirectSoundEnumerateA(dra_dsound__get_device_guid_by_id__callback, &data);
1239 const GUID* dra_dsound__get_capture_device_guid_by_id(
dra_backend* pBackend,
unsigned int deviceID)
1245 if (deviceID == 0) {
1249 dra_backend_dsound* pBackendDS = (dra_backend_dsound*)pBackend;
1250 if (pBackendDS ==
NULL) {
1257 dra_dsound__device_enum_data data = {0};
1258 data.deviceID = deviceID;
1259 pBackendDS->pDirectSoundCaptureEnumerateA(dra_dsound__get_device_guid_by_id__callback, &data);
1266 dra_backend_dsound* pBackendDS = (dra_backend_dsound*)calloc(1,
sizeof(*pBackendDS));
1267 if (pBackendDS ==
NULL) {
1271 pBackendDS->type = DR_AUDIO_BACKEND_TYPE_DSOUND;
1273 pBackendDS->hDSoundDLL = LoadLibraryW(
L"dsound.dll");
1274 if (pBackendDS->hDSoundDLL ==
NULL) {
1278 pBackendDS->pDirectSoundCreate8 = (pDirectSoundCreate8Proc)GetProcAddress(pBackendDS->hDSoundDLL,
"DirectSoundCreate8");
1279 if (pBackendDS->pDirectSoundCreate8 ==
NULL){
1283 pBackendDS->pDirectSoundEnumerateA = (pDirectSoundEnumerateAProc)GetProcAddress(pBackendDS->hDSoundDLL,
"DirectSoundEnumerateA");
1284 if (pBackendDS->pDirectSoundEnumerateA ==
NULL){
1288 pBackendDS->pDirectSoundCaptureCreate8 = (pDirectSoundCaptureCreate8Proc)GetProcAddress(pBackendDS->hDSoundDLL,
"DirectSoundCaptureCreate8");
1289 if (pBackendDS->pDirectSoundCaptureCreate8 ==
NULL){
1293 pBackendDS->pDirectSoundCaptureEnumerateA = (pDirectSoundCaptureEnumerateAProc)GetProcAddress(pBackendDS->hDSoundDLL,
"DirectSoundCaptureEnumerateA");
1294 if (pBackendDS->pDirectSoundCaptureEnumerateA ==
NULL){
1302 if (pBackendDS !=
NULL) {
1303 if (pBackendDS->hDSoundDLL !=
NULL) {
1304 FreeLibrary(pBackendDS->hDSoundDLL);
1313 void dra_backend_delete_dsound(
dra_backend* pBackend)
1315 dra_backend_dsound* pBackendDS = (dra_backend_dsound*)pBackend;
1316 if (pBackendDS ==
NULL) {
1320 if (pBackendDS->hDSoundDLL !=
NULL) {
1321 FreeLibrary(pBackendDS->hDSoundDLL);
1329 dra_backend_device_dsound* pDeviceDS = (dra_backend_device_dsound*)pDevice;
1330 if (pDeviceDS ==
NULL) {
1334 if (pDeviceDS->pDSNotify) IDirectSoundNotify_Release(pDeviceDS->pDSNotify);
1337 if (pDeviceDS->pDSSecondaryBuffer) IDirectSoundBuffer_Release(pDeviceDS->pDSSecondaryBuffer);
1338 if (pDeviceDS->pDSPrimaryBuffer) IDirectSoundBuffer_Release(pDeviceDS->pDSPrimaryBuffer);
1339 if (pDeviceDS->pDS) IDirectSound_Release(pDeviceDS->pDS);
1341 if (pDeviceDS->pDSCaptureBuffer) IDirectSoundCaptureBuffer_Release(pDeviceDS->pDSCaptureBuffer);
1342 if (pDeviceDS->pDSCapture) IDirectSoundCapture_Release(pDeviceDS->pDSCapture);
1346 for (
int i = 0; i < DR_AUDIO_DEFAULT_FRAGMENT_COUNT; ++i) {
1347 CloseHandle(pDeviceDS->pNotifyEvents[i]);
1350 if (pDeviceDS->hStopEvent !=
NULL) {
1351 CloseHandle(pDeviceDS->hStopEvent);
1357 dra_backend_device* dra_backend_device_open_playback_dsound(
dra_backend* pBackend,
unsigned int deviceID,
unsigned int channels,
unsigned int sampleRate,
unsigned int latencyInMilliseconds)
1361 WAVEFORMATEXTENSIBLE* actualFormat;
1362 unsigned int sampleRateInMilliseconds;
1363 unsigned int proposedFramesPerFragment;
1364 unsigned int framesPerFragment;
1365 size_t fragmentSize;
1366 size_t hardwareBufferSize;
1368 dra_backend_dsound* pBackendDS = (dra_backend_dsound*)pBackend;
1369 if (pBackendDS ==
NULL) {
1373 dra_backend_device_dsound* pDeviceDS = (dra_backend_device_dsound*)calloc(1,
sizeof(*pDeviceDS));
1374 if (pDeviceDS ==
NULL) {
1378 if (channels == 0) {
1379 channels = DR_AUDIO_DEFAULT_CHANNEL_COUNT;
1382 pDeviceDS->pBackend = pBackend;
1384 pDeviceDS->channels = channels;
1385 pDeviceDS->sampleRate = sampleRate;
1387 hr = pBackendDS->pDirectSoundCreate8(dra_dsound__get_playback_device_guid_by_id(pBackend, deviceID), &pDeviceDS->pDS,
NULL);
1393 hr = IDirectSound_SetCooperativeLevel(pDeviceDS->pDS, GetForegroundWindow(), DSSCL_PRIORITY);
1400 DSBUFFERDESC descDSPrimary;
1401 memset(&descDSPrimary, 0,
sizeof(DSBUFFERDESC));
1402 descDSPrimary.dwSize =
sizeof(DSBUFFERDESC);
1403 descDSPrimary.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME;
1405 hr = IDirectSound_CreateSoundBuffer(pDeviceDS->pDS, &descDSPrimary, &pDeviceDS->pDSPrimaryBuffer,
NULL);
1416 WAVEFORMATEXTENSIBLE wf;
1417 memset(&wf, 0,
sizeof(wf));
1418 wf.Format.cbSize =
sizeof(wf);
1419 wf.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
1420 wf.Format.nChannels = (WORD)channels;
1421 wf.Format.nSamplesPerSec = (DWORD)sampleRate;
1422 wf.Format.wBitsPerSample =
sizeof(float)*8;
1423 wf.Format.nBlockAlign = (wf.Format.nChannels * wf.Format.wBitsPerSample) / 8;
1424 wf.Format.nAvgBytesPerSec = wf.Format.nBlockAlign * wf.Format.nSamplesPerSec;
1425 wf.Samples.wValidBitsPerSample = wf.Format.wBitsPerSample;
1426 wf.dwChannelMask = 0;
1427 wf.SubFormat = _g_draGUID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
1429 wf.dwChannelMask = ~(((DWORD)-1) << channels);
1432 hr = IDirectSoundBuffer_SetFormat(pDeviceDS->pDSPrimaryBuffer, (WAVEFORMATEX*)&wf);
1440 hr = IDirectSoundBuffer_GetFormat(pDeviceDS->pDSPrimaryBuffer,
NULL, 0, &requiredSize);
1446 actualFormat = (WAVEFORMATEXTENSIBLE*)rawdata;
1447 hr = IDirectSoundBuffer_GetFormat(pDeviceDS->pDSPrimaryBuffer, (WAVEFORMATEX*)actualFormat, requiredSize,
NULL);
1452 pDeviceDS->channels = actualFormat->Format.nChannels;
1453 pDeviceDS->sampleRate = actualFormat->Format.nSamplesPerSec;
1456 pDeviceDS->fragmentCount = DR_AUDIO_DEFAULT_FRAGMENT_COUNT;
1463 sampleRateInMilliseconds = pDeviceDS->sampleRate / 1000;
1464 if (sampleRateInMilliseconds == 0) {
1465 sampleRateInMilliseconds = 1;
1470 proposedFramesPerFragment = sampleRateInMilliseconds * latencyInMilliseconds;
1471 framesPerFragment = dra_prev_power_of_2(proposedFramesPerFragment);
1472 if (framesPerFragment == 0) {
1473 framesPerFragment = 2;
1476 pDeviceDS->samplesPerFragment = framesPerFragment * pDeviceDS->channels;
1478 fragmentSize = pDeviceDS->samplesPerFragment *
sizeof(float);
1479 hardwareBufferSize = fragmentSize * pDeviceDS->fragmentCount;
1480 assert(hardwareBufferSize > 0);
1495 DSBUFFERDESC descDS;
1496 memset(&descDS, 0,
sizeof(DSBUFFERDESC));
1497 descDS.dwSize =
sizeof(DSBUFFERDESC);
1498 descDS.dwFlags = DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2;
1499 descDS.dwBufferBytes = (DWORD)hardwareBufferSize;
1500 descDS.lpwfxFormat = (WAVEFORMATEX*)&wf;
1501 hr = IDirectSound_CreateSoundBuffer(pDeviceDS->pDS, &descDS, &pDeviceDS->pDSSecondaryBuffer,
NULL);
1509 hr = IDirectSoundBuffer8_QueryInterface(pDeviceDS->pDSSecondaryBuffer, g_draGUID_IID_DirectSoundNotify, (
void**)&pDeviceDS->pDSNotify);
1514 DSBPOSITIONNOTIFY notifyPoints[DR_AUDIO_DEFAULT_FRAGMENT_COUNT];
1515 for (
int i = 0; i < DR_AUDIO_DEFAULT_FRAGMENT_COUNT; ++i)
1518 if (pDeviceDS->pNotifyEvents[i] ==
NULL) {
1522 notifyPoints[i].dwOffset = (DWORD)(i * fragmentSize);
1523 notifyPoints[i].hEventNotify = pDeviceDS->pNotifyEvents[i];
1526 hr = IDirectSoundNotify_SetNotificationPositions(pDeviceDS->pDSNotify, DR_AUDIO_DEFAULT_FRAGMENT_COUNT, notifyPoints);
1536 if (pDeviceDS->hStopEvent ==
NULL) {
1547 dra_backend_device* dra_backend_device_open_capture_dsound(
dra_backend* pBackend,
unsigned int deviceID,
unsigned int channels,
unsigned int sampleRate,
unsigned int latencyInMilliseconds)
1549 (void)latencyInMilliseconds;
1552 unsigned int sampleRateInMilliseconds;
1553 unsigned int proposedFramesPerFragment;
1554 unsigned int framesPerFragment;
1555 size_t fragmentSize;
1556 size_t hardwareBufferSize;
1558 dra_backend_dsound* pBackendDS = (dra_backend_dsound*)pBackend;
1559 if (pBackendDS ==
NULL) {
1563 dra_backend_device_dsound* pDeviceDS = (dra_backend_device_dsound*)calloc(1,
sizeof(*pDeviceDS));
1564 if (pDeviceDS ==
NULL) {
1568 if (channels == 0) {
1569 channels = DR_AUDIO_DEFAULT_CHANNEL_COUNT;
1572 pDeviceDS->pBackend = pBackend;
1574 pDeviceDS->channels = channels;
1575 pDeviceDS->sampleRate = sampleRate;
1577 hr = pBackendDS->pDirectSoundCaptureCreate8(dra_dsound__get_capture_device_guid_by_id(pBackend, deviceID), &pDeviceDS->pDSCapture,
NULL);
1582 pDeviceDS->fragmentCount = DR_AUDIO_DEFAULT_FRAGMENT_COUNT;
1588 sampleRateInMilliseconds = pDeviceDS->sampleRate / 1000;
1589 if (sampleRateInMilliseconds == 0) {
1590 sampleRateInMilliseconds = 1;
1595 proposedFramesPerFragment = sampleRateInMilliseconds * latencyInMilliseconds;
1596 framesPerFragment = dra_prev_power_of_2(proposedFramesPerFragment);
1597 if (framesPerFragment == 0) {
1598 framesPerFragment = 2;
1601 pDeviceDS->samplesPerFragment = framesPerFragment * pDeviceDS->channels;
1603 fragmentSize = pDeviceDS->samplesPerFragment *
sizeof(float);
1604 hardwareBufferSize = fragmentSize * pDeviceDS->fragmentCount;
1605 assert(hardwareBufferSize > 0);
1608 WAVEFORMATEXTENSIBLE wf;
1609 memset(&wf, 0,
sizeof(wf));
1610 wf.Format.cbSize =
sizeof(wf);
1611 wf.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
1612 wf.Format.nChannels = (WORD)channels;
1613 wf.Format.nSamplesPerSec = (DWORD)sampleRate;
1614 wf.Format.wBitsPerSample =
sizeof(float)*8;
1615 wf.Format.nBlockAlign = (wf.Format.nChannels * wf.Format.wBitsPerSample) / 8;
1616 wf.Format.nAvgBytesPerSec = wf.Format.nBlockAlign * wf.Format.nSamplesPerSec;
1617 wf.Samples.wValidBitsPerSample = wf.Format.wBitsPerSample;
1618 wf.dwChannelMask = 0;
1619 wf.SubFormat = _g_draGUID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
1621 wf.dwChannelMask = ~(((DWORD)-1) << channels);
1624 DSCBUFFERDESC descDS;
1625 memset(&descDS, 0,
sizeof(descDS));
1626 descDS.dwSize =
sizeof(descDS);
1628 descDS.dwBufferBytes = (DWORD)hardwareBufferSize;
1629 descDS.lpwfxFormat = (WAVEFORMATEX*)&wf;
1631 LPDIRECTSOUNDCAPTUREBUFFER pDSCB_Temp;
1632 hr = IDirectSoundCapture_CreateCaptureBuffer(pDeviceDS->pDSCapture, &descDS, &pDSCB_Temp,
NULL);
1637 hr = IDirectSoundCapture_QueryInterface(pDSCB_Temp, g_draGUID_IID_IDirectSoundCaptureBuffer8, (LPVOID*)&pDeviceDS->pDSCaptureBuffer);
1638 IDirectSoundCaptureBuffer_Release(pDSCB_Temp);
1646 hr = IDirectSoundCaptureBuffer8_QueryInterface(pDeviceDS->pDSCaptureBuffer, g_draGUID_IID_DirectSoundNotify, (
void**)&pDeviceDS->pDSNotify);
1651 DSBPOSITIONNOTIFY notifyPoints[DR_AUDIO_DEFAULT_FRAGMENT_COUNT];
1652 for (
int i = 0; i < DR_AUDIO_DEFAULT_FRAGMENT_COUNT; ++i)
1655 if (pDeviceDS->pNotifyEvents[i] ==
NULL) {
1659 notifyPoints[i].dwOffset = (DWORD)(((i+1) * fragmentSize) % hardwareBufferSize);
1660 notifyPoints[i].hEventNotify = pDeviceDS->pNotifyEvents[i];
1663 hr = IDirectSoundNotify_SetNotificationPositions(pDeviceDS->pDSNotify, DR_AUDIO_DEFAULT_FRAGMENT_COUNT, notifyPoints);
1672 if (pDeviceDS->hStopEvent ==
NULL) {
1686 return dra_backend_device_open_playback_dsound(pBackend, deviceID, channels, sampleRate, latencyInMilliseconds);
1688 return dra_backend_device_open_capture_dsound(pBackend, deviceID, channels, sampleRate, latencyInMilliseconds);
1694 dra_backend_device_dsound* pDeviceDS = (dra_backend_device_dsound*)pDevice;
1695 if (pDeviceDS ==
NULL) {
1700 IDirectSoundBuffer_Play(pDeviceDS->pDSSecondaryBuffer, 0, 0, DSBPLAY_LOOPING);
1702 IDirectSoundCaptureBuffer8_Start(pDeviceDS->pDSCaptureBuffer, DSCBSTART_LOOPING);
1708 dra_backend_device_dsound* pDeviceDS = (dra_backend_device_dsound*)pDevice;
1709 if (pDeviceDS ==
NULL) {
1716 IDirectSoundBuffer_GetStatus(pDeviceDS->pDSSecondaryBuffer, &status);
1717 if ((status & DSBSTATUS_PLAYING) == 0) {
1722 IDirectSoundBuffer_Stop(pDeviceDS->pDSSecondaryBuffer);
1723 IDirectSoundBuffer_SetCurrentPosition(pDeviceDS->pDSSecondaryBuffer, 0);
1727 IDirectSoundCaptureBuffer8_GetStatus(pDeviceDS->pDSCaptureBuffer, &status);
1728 if ((status & DSBSTATUS_PLAYING) == 0) {
1734 IDirectSoundCaptureBuffer_Stop(pDeviceDS->pDSCaptureBuffer);
1739 SetEvent(pDeviceDS->hStopEvent);
1744 dra_backend_device_dsound* pDeviceDS = (dra_backend_device_dsound*)pDevice;
1745 if (pDeviceDS ==
NULL) {
1749 unsigned int eventCount = DR_AUDIO_DEFAULT_FRAGMENT_COUNT + 1;
1750 HANDLE eventHandles[DR_AUDIO_DEFAULT_FRAGMENT_COUNT + 1];
1751 memcpy(eventHandles, pDeviceDS->pNotifyEvents,
sizeof(HANDLE) * DR_AUDIO_DEFAULT_FRAGMENT_COUNT);
1752 eventHandles[DR_AUDIO_DEFAULT_FRAGMENT_COUNT] = pDeviceDS->hStopEvent;
1754 DWORD rc = WaitForMultipleObjects(DR_AUDIO_DEFAULT_FRAGMENT_COUNT + 1, eventHandles,
FALSE, INFINITE);
1755 if (rc >= WAIT_OBJECT_0 && rc < eventCount)
1757 unsigned int eventIndex = rc - WAIT_OBJECT_0;
1758 HANDLE hEvent = eventHandles[eventIndex];
1761 if (hEvent == pDeviceDS->hStopEvent) {
1766 pDeviceDS->currentFragmentIndex = eventIndex;
1773 void* dra_backend_device_map_next_fragment(
dra_backend_device* pDevice,
size_t* pSamplesInFragmentOut)
1775 assert(pSamplesInFragmentOut !=
NULL);
1777 dra_backend_device_dsound* pDeviceDS = (dra_backend_device_dsound*)pDevice;
1778 if (pDeviceDS ==
NULL) {
1782 if (pDeviceDS->pLockPtr !=
NULL) {
1790 DWORD dwBytes = pDeviceDS->samplesPerFragment *
sizeof(float);
1793 IDirectSoundBuffer_GetStatus(pDeviceDS->pDSSecondaryBuffer, &status);
1794 if ((status & DSBSTATUS_PLAYING) != 0) {
1795 dwOffset = (((pDeviceDS->currentFragmentIndex + 1) % pDeviceDS->fragmentCount) * pDeviceDS->samplesPerFragment) *
sizeof(
float);
1798 HRESULT hr = IDirectSoundBuffer_Lock(pDeviceDS->pDSSecondaryBuffer, dwOffset, dwBytes, &pDeviceDS->pLockPtr, &pDeviceDS->lockSize,
NULL,
NULL, 0);
1803 DWORD dwOffset = (pDeviceDS->currentFragmentIndex * pDeviceDS->samplesPerFragment) *
sizeof(
float);
1804 DWORD dwBytes = pDeviceDS->samplesPerFragment *
sizeof(float);
1806 HRESULT hr = IDirectSoundCaptureBuffer8_Lock(pDeviceDS->pDSCaptureBuffer, dwOffset, dwBytes, &pDeviceDS->pLockPtr, &pDeviceDS->lockSize,
NULL,
NULL, 0);
1812 *pSamplesInFragmentOut = pDeviceDS->samplesPerFragment;
1813 return pDeviceDS->pLockPtr;
1818 dra_backend_device_dsound* pDeviceDS = (dra_backend_device_dsound*)pDevice;
1819 if (pDeviceDS ==
NULL) {
1823 if (pDeviceDS->pLockPtr ==
NULL) {
1828 IDirectSoundBuffer_Unlock(pDeviceDS->pDSSecondaryBuffer, pDeviceDS->pLockPtr, pDeviceDS->lockSize,
NULL, 0);
1830 IDirectSoundCaptureBuffer8_Unlock(pDeviceDS->pDSCaptureBuffer, pDeviceDS->pLockPtr, pDeviceDS->lockSize,
NULL, 0);
1833 pDeviceDS->pLockPtr =
NULL;
1834 pDeviceDS->lockSize = 0;
1836 #endif // DR_AUDIO_NO_SOUND
1841 #include <sys/syscall.h>
1842 #include <sys/types.h>
1843 #include <pthread.h>
1845 #include <semaphore.h>
1848 typedef void* (* dra_thread_entry_proc)(
void* pData);
1850 dra_thread dra_thread_create(dra_thread_entry_proc entryProc,
void* pData)
1853 if (pthread_create(&thread,
NULL, entryProc, pData) != 0) {
1867 pthread_join((pthread_t)thread,
NULL);
1874 pthread_mutex_t* mutex = (pthread_mutex_t*)malloc(
sizeof(pthread_mutex_t));
1875 if (pthread_mutex_init(mutex,
NULL) != 0) {
1885 pthread_mutex_destroy((pthread_mutex_t*)mutex);
1890 pthread_mutex_lock((pthread_mutex_t*)mutex);
1895 pthread_mutex_unlock((pthread_mutex_t*)mutex);
1901 sem_t* semaphore = (sem_t*)malloc(
sizeof(sem_t));
1902 if (sem_init(semaphore, 0, (
unsigned int)initialValue) == -1) {
1912 sem_close((sem_t*)semaphore);
1917 return sem_wait((sem_t*)semaphore) != -1;
1922 return sem_post((sem_t*)semaphore) != -1;
1928 #ifndef DR_AUDIO_NO_ALSA
1929 #define DR_AUDIO_ENABLE_ALSA
1930 #include <alsa/asoundlib.h>
1934 DR_AUDIO_BASE_BACKEND_ATTRIBS
1941 DR_AUDIO_BASE_BACKEND_DEVICE_ATTRIBS
1944 snd_pcm_t* deviceALSA;
1953 float* pIntermediaryBuffer;
1954 } dra_backend_device_alsa;
1957 static dr_bool32 dra_alsa__get_device_name_by_id(
dra_backend* pBackend,
unsigned int deviceID,
char* deviceNameOut)
1959 assert(pBackend !=
NULL);
1960 assert(deviceNameOut !=
NULL);
1962 deviceNameOut[0] =
'\0';
1964 if (deviceID == 0) {
1965 strcpy(deviceNameOut,
"default");
1970 unsigned int iDevice = 0;
1973 if (snd_device_name_hint(-1,
"pcm", (
void***)&deviceHints) < 0) {
1978 char** nextDeviceHint = deviceHints;
1979 while (*nextDeviceHint !=
NULL && iDevice < deviceID) {
1980 nextDeviceHint += 1;
1985 if (iDevice == deviceID) {
1986 strcpy(deviceNameOut, snd_device_name_get_hint(*nextDeviceHint,
"NAME"));
1990 snd_device_name_free_hint((
void**)deviceHints);
1999 dra_backend_alsa* pBackendALSA = (dra_backend_alsa*)calloc(1,
sizeof(*pBackendALSA));
2000 if (pBackendALSA ==
NULL) {
2004 pBackendALSA->type = DR_AUDIO_BACKEND_TYPE_ALSA;
2011 if (pBackendALSA !=
NULL) {
2019 void dra_backend_delete_alsa(
dra_backend* pBackend)
2021 dra_backend_alsa* pBackendALSA = (dra_backend_alsa*)pBackend;
2022 if (pBackendALSA ==
NULL) {
2032 dra_backend_device_alsa* pDeviceALSA = (dra_backend_device_alsa*)pDevice;
2033 if (pDeviceALSA ==
NULL) {
2037 if (pDeviceALSA->deviceALSA !=
NULL) {
2038 snd_pcm_close(pDeviceALSA->deviceALSA);
2041 free(pDeviceALSA->pIntermediaryBuffer);
2045 dra_backend_device* dra_backend_device_open_playback_alsa(
dra_backend* pBackend,
unsigned int deviceID,
unsigned int channels,
unsigned int sampleRate,
unsigned int latencyInMilliseconds)
2047 unsigned int periods;
2049 size_t sampleRateInMilliseconds;
2050 unsigned int proposedFramesPerFragment;
2051 unsigned int framesPerFragment;
2052 snd_pcm_sw_params_t* pSWParams;
2054 dra_backend_alsa* pBackendALSA = (dra_backend_alsa*)pBackend;
2055 if (pBackendALSA ==
NULL) {
2059 snd_pcm_hw_params_t* pHWParams =
NULL;
2061 dra_backend_device_alsa* pDeviceALSA = (dra_backend_device_alsa*)calloc(1,
sizeof(*pDeviceALSA));
2062 if (pDeviceALSA ==
NULL) {
2066 pDeviceALSA->pBackend = pBackend;
2068 pDeviceALSA->channels = channels;
2069 pDeviceALSA->sampleRate = sampleRate;
2071 char deviceName[1024];
2072 if (!dra_alsa__get_device_name_by_id(pBackend, deviceID, deviceName)) {
2076 if (snd_pcm_open(&pDeviceALSA->deviceALSA, deviceName, SND_PCM_STREAM_PLAYBACK, 0) < 0) {
2081 if (snd_pcm_hw_params_malloc(&pHWParams) < 0) {
2085 if (snd_pcm_hw_params_any(pDeviceALSA->deviceALSA, pHWParams) < 0) {
2089 if (snd_pcm_hw_params_set_access(pDeviceALSA->deviceALSA, pHWParams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {
2093 if (snd_pcm_hw_params_set_format(pDeviceALSA->deviceALSA, pHWParams, SND_PCM_FORMAT_FLOAT_LE) < 0) {
2098 if (snd_pcm_hw_params_set_rate_near(pDeviceALSA->deviceALSA, pHWParams, &sampleRate, 0) < 0) {
2102 if (snd_pcm_hw_params_set_channels_near(pDeviceALSA->deviceALSA, pHWParams, &channels) < 0) {
2106 pDeviceALSA->sampleRate = sampleRate;
2107 pDeviceALSA->channels = channels;
2109 periods = DR_AUDIO_DEFAULT_FRAGMENT_COUNT;
2111 if (snd_pcm_hw_params_set_periods_near(pDeviceALSA->deviceALSA, pHWParams, &periods, &dir) < 0) {
2116 pDeviceALSA->fragmentCount = periods;
2121 sampleRateInMilliseconds = pDeviceALSA->sampleRate / 1000;
2122 if (sampleRateInMilliseconds == 0) {
2123 sampleRateInMilliseconds = 1;
2135 proposedFramesPerFragment = sampleRateInMilliseconds * latencyInMilliseconds;
2136 framesPerFragment = dra_prev_power_of_2(proposedFramesPerFragment);
2137 if (framesPerFragment == 0) {
2138 framesPerFragment = 2;
2141 pDeviceALSA->samplesPerFragment = framesPerFragment * pDeviceALSA->channels;
2143 if (snd_pcm_hw_params_set_buffer_size(pDeviceALSA->deviceALSA, pHWParams, framesPerFragment * pDeviceALSA->fragmentCount) < 0) {
2149 if (snd_pcm_hw_params(pDeviceALSA->deviceALSA, pHWParams) < 0) {
2153 snd_pcm_hw_params_free(pHWParams);
2160 if (snd_pcm_sw_params_malloc(&pSWParams) < 0) {
2164 if (snd_pcm_sw_params_current(pDeviceALSA->deviceALSA, pSWParams) != 0) {
2168 if (snd_pcm_sw_params_set_start_threshold(pDeviceALSA->deviceALSA, pSWParams, framesPerFragment) != 0) {
2171 if (snd_pcm_sw_params_set_avail_min(pDeviceALSA->deviceALSA, pSWParams, framesPerFragment) != 0) {
2175 if (snd_pcm_sw_params(pDeviceALSA->deviceALSA, pSWParams) != 0) {
2178 snd_pcm_sw_params_free(pSWParams);
2182 pDeviceALSA->isBufferMapped =
DR_FALSE;
2183 pDeviceALSA->pIntermediaryBuffer = (
float*)malloc(pDeviceALSA->samplesPerFragment *
sizeof(
float));
2184 if (pDeviceALSA->pIntermediaryBuffer ==
NULL) {
2192 snd_pcm_hw_params_free(pHWParams);
2195 if (pDeviceALSA !=
NULL) {
2196 if (pDeviceALSA->deviceALSA !=
NULL) {
2197 snd_pcm_close(pDeviceALSA->deviceALSA);
2200 free(pDeviceALSA->pIntermediaryBuffer);
2207 dra_backend_device* dra_backend_device_open_capture_alsa(
dra_backend* pBackend,
unsigned int deviceID,
unsigned int channels,
unsigned int sampleRate,
unsigned int latencyInMilliseconds)
2209 unsigned int periods;
2211 size_t sampleRateInMilliseconds;
2212 unsigned int proposedFramesPerFragment;
2213 unsigned int framesPerFragment;
2214 snd_pcm_sw_params_t* pSWParams;
2216 dra_backend_alsa* pBackendALSA = (dra_backend_alsa*)pBackend;
2217 if (pBackendALSA ==
NULL) {
2221 snd_pcm_hw_params_t* pHWParams =
NULL;
2223 dra_backend_device_alsa* pDeviceALSA = (dra_backend_device_alsa*)calloc(1,
sizeof(*pDeviceALSA));
2224 if (pDeviceALSA ==
NULL) {
2228 pDeviceALSA->pBackend = pBackend;
2230 pDeviceALSA->channels = channels;
2231 pDeviceALSA->sampleRate = sampleRate;
2233 char deviceName[1024];
2234 if (!dra_alsa__get_device_name_by_id(pBackend, deviceID, deviceName)) {
2238 if (snd_pcm_open(&pDeviceALSA->deviceALSA, deviceName, SND_PCM_STREAM_CAPTURE, 0) < 0) {
2243 if (snd_pcm_hw_params_malloc(&pHWParams) < 0) {
2247 if (snd_pcm_hw_params_any(pDeviceALSA->deviceALSA, pHWParams) < 0) {
2251 if (snd_pcm_hw_params_set_access(pDeviceALSA->deviceALSA, pHWParams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {
2255 if (snd_pcm_hw_params_set_format(pDeviceALSA->deviceALSA, pHWParams, SND_PCM_FORMAT_FLOAT_LE) < 0) {
2260 if (snd_pcm_hw_params_set_rate_near(pDeviceALSA->deviceALSA, pHWParams, &sampleRate, 0) < 0) {
2264 if (snd_pcm_hw_params_set_channels_near(pDeviceALSA->deviceALSA, pHWParams, &channels) < 0) {
2268 pDeviceALSA->sampleRate = sampleRate;
2269 pDeviceALSA->channels = channels;
2271 periods = DR_AUDIO_DEFAULT_FRAGMENT_COUNT;
2273 if (snd_pcm_hw_params_set_periods_near(pDeviceALSA->deviceALSA, pHWParams, &periods, &dir) < 0) {
2278 pDeviceALSA->fragmentCount = periods;
2283 sampleRateInMilliseconds = pDeviceALSA->sampleRate / 1000;
2284 if (sampleRateInMilliseconds == 0) {
2285 sampleRateInMilliseconds = 1;
2297 proposedFramesPerFragment = sampleRateInMilliseconds * latencyInMilliseconds;
2298 framesPerFragment = dra_prev_power_of_2(proposedFramesPerFragment);
2299 if (framesPerFragment == 0) {
2300 framesPerFragment = 2;
2303 pDeviceALSA->samplesPerFragment = framesPerFragment * pDeviceALSA->channels;
2305 if (snd_pcm_hw_params_set_buffer_size(pDeviceALSA->deviceALSA, pHWParams, framesPerFragment * pDeviceALSA->fragmentCount) < 0) {
2311 if (snd_pcm_hw_params(pDeviceALSA->deviceALSA, pHWParams) < 0) {
2315 snd_pcm_hw_params_free(pHWParams);
2322 if (snd_pcm_sw_params_malloc(&pSWParams) < 0) {
2326 if (snd_pcm_sw_params_current(pDeviceALSA->deviceALSA, pSWParams) != 0) {
2330 if (snd_pcm_sw_params_set_start_threshold(pDeviceALSA->deviceALSA, pSWParams, framesPerFragment) != 0) {
2333 if (snd_pcm_sw_params_set_avail_min(pDeviceALSA->deviceALSA, pSWParams, framesPerFragment) != 0) {
2337 if (snd_pcm_sw_params(pDeviceALSA->deviceALSA, pSWParams) != 0) {
2340 snd_pcm_sw_params_free(pSWParams);
2343 pDeviceALSA->isBufferMapped =
DR_FALSE;
2344 pDeviceALSA->pIntermediaryBuffer = (
float*)malloc(pDeviceALSA->samplesPerFragment *
sizeof(
float));
2345 if (pDeviceALSA->pIntermediaryBuffer ==
NULL) {
2359 return dra_backend_device_open_playback_alsa(pBackend, deviceID, channels, sampleRate, latencyInMilliseconds);
2361 return dra_backend_device_open_capture_alsa(pBackend, deviceID, channels, sampleRate, latencyInMilliseconds);
2368 dra_backend_device_alsa* pDeviceALSA = (dra_backend_device_alsa*)pDevice;
2369 if (pDeviceALSA ==
NULL) {
2373 snd_pcm_prepare(pDeviceALSA->deviceALSA);
2374 pDeviceALSA->isPlaying =
DR_TRUE;
2379 dra_backend_device_alsa* pDeviceALSA = (dra_backend_device_alsa*)pDevice;
2380 if (pDeviceALSA ==
NULL) {
2384 snd_pcm_drop(pDeviceALSA->deviceALSA);
2390 dra_backend_device_alsa* pDeviceALSA = (dra_backend_device_alsa*)pDevice;
2391 if (pDeviceALSA ==
NULL) {
2395 if (!pDeviceALSA->isPlaying) {
2400 int result = snd_pcm_wait(pDeviceALSA->deviceALSA, -1);
2405 if (result == -EPIPE) {
2407 snd_pcm_prepare(pDeviceALSA->deviceALSA);
2411 snd_pcm_uframes_t frameCount = pDeviceALSA->samplesPerFragment / pDeviceALSA->channels;
2412 snd_pcm_sframes_t framesRead = snd_pcm_readi(pDeviceALSA->deviceALSA, pDeviceALSA->pIntermediaryBuffer, frameCount);
2413 if (framesRead > 0) {
2417 if (framesRead == -EPIPE) {
2419 snd_pcm_prepare(pDeviceALSA->deviceALSA);
2427 void* dra_backend_device_map_next_fragment(
dra_backend_device* pDevice,
size_t* pSamplesInFragmentOut)
2429 assert(pSamplesInFragmentOut !=
NULL);
2431 dra_backend_device_alsa* pDeviceALSA = (dra_backend_device_alsa*)pDevice;
2432 if (pDeviceALSA ==
NULL) {
2436 if (pDeviceALSA->isBufferMapped) {
2444 *pSamplesInFragmentOut = pDeviceALSA->samplesPerFragment;
2445 return pDeviceALSA->pIntermediaryBuffer;
2450 dra_backend_device_alsa* pDeviceALSA = (dra_backend_device_alsa*)pDevice;
2451 if (pDeviceALSA ==
NULL) {
2455 if (pDeviceALSA->isBufferMapped) {
2461 snd_pcm_writei(pDeviceALSA->deviceALSA, pDeviceALSA->pIntermediaryBuffer, pDeviceALSA->samplesPerFragment / pDeviceALSA->channels);
2464 #endif // DR_AUDIO_NO_ALSA
2468 void dra_thread_wait_and_delete(
dra_thread thread)
2470 dra_thread_wait(thread);
2471 dra_thread_delete(thread);
2479 #ifdef DR_AUDIO_ENABLE_DSOUND
2480 pBackend = dra_backend_create_dsound();
2481 if (pBackend !=
NULL) {
2486 #ifdef DR_AUDIO_ENABLE_ALSA
2487 pBackend = dra_backend_create_alsa();
2488 if (pBackend !=
NULL) {
2499 if (pBackend ==
NULL) {
2503 #ifdef DR_AUDIO_ENABLE_DSOUND
2504 if (pBackend->type == DR_AUDIO_BACKEND_TYPE_DSOUND) {
2505 dra_backend_delete_dsound(pBackend);
2510 #ifdef DR_AUDIO_ENABLE_ALSA
2511 if (pBackend->type == DR_AUDIO_BACKEND_TYPE_ALSA) {
2512 dra_backend_delete_alsa(pBackend);
2524 if (pBackend ==
NULL) {
2528 #ifdef DR_AUDIO_ENABLE_DSOUND
2529 if (pBackend->type == DR_AUDIO_BACKEND_TYPE_DSOUND) {
2530 return dra_backend_device_open_dsound(pBackend, type, deviceID, channels, sampleRate, latencyInMilliseconds);
2534 #ifdef DR_AUDIO_ENABLE_ALSA
2535 if (pBackend->type == DR_AUDIO_BACKEND_TYPE_ALSA) {
2536 return dra_backend_device_open_alsa(pBackend, type, deviceID, channels, sampleRate, latencyInMilliseconds);
2548 if (pDevice ==
NULL) {
2552 assert(pDevice->pBackend !=
NULL);
2554 #ifdef DR_AUDIO_ENABLE_DSOUND
2555 if (pDevice->pBackend->type == DR_AUDIO_BACKEND_TYPE_DSOUND) {
2556 dra_backend_device_close_dsound(pDevice);
2561 #ifdef DR_AUDIO_ENABLE_ALSA
2562 if (pDevice->pBackend->type == DR_AUDIO_BACKEND_TYPE_ALSA) {
2563 dra_backend_device_close_alsa(pDevice);
2594 float* dra_voice__next_frame(
dra_voice* pVoice);
2597 size_t dra_voice__next_frames(
dra_voice* pVoice,
size_t frameCount,
float* pSamplesOut);
2603 memset(pContext, 0,
sizeof(*pContext));
2606 pContext->
pBackend = dra_backend_create();
2617 dra_backend_delete(pContext->
pBackend);
2626 if (pContext ==
NULL) {
2636 *ppContext = pContext;
2642 if (pContext ==
NULL)
return;
2651 if (pQueue ==
NULL || pEvent ==
NULL) {
2655 dra_mutex_lock(pQueue->
lock);
2662 if (pNewEvents ==
NULL) {
2666 for (
size_t i = 0; i < pQueue->
eventCount; ++i) {
2680 dra_mutex_unlock(pQueue->
lock);
2685 if (pQueue ==
NULL || pVoice ==
NULL) {
2689 dra_mutex_lock(pQueue->
lock);
2692 for (
size_t i = 0; i < pQueue->
eventCount; ++i) {
2694 if (pEvent->
pVoice == pVoice) {
2700 dra_mutex_unlock(pQueue->
lock);
2705 if (pQueue ==
NULL || pEventOut ==
NULL) {
2710 dra_mutex_lock(pQueue->
lock);
2719 dra_mutex_unlock(pQueue->
lock);
2726 if (pQueue ==
NULL) {
2731 while (dra_event_queue__next_event(pQueue, &nextEvent)) {
2732 if (nextEvent.
proc) {
2741 assert(pDevice !=
NULL);
2749 assert(pDevice !=
NULL);
2750 dra_mutex_lock(pDevice->
mutex);
2755 assert(pDevice !=
NULL);
2756 dra_mutex_unlock(pDevice->
mutex);
2761 assert(pDevice !=
NULL);
2767 assert(pDevice !=
NULL);
2769 size_t samplesInFragment;
2770 void* pSampleData = dra_backend_device_map_next_fragment(pDevice->
pBackendDevice, &samplesInFragment);
2771 if (pSampleData ==
NULL) {
2776 size_t framesInFragment = samplesInFragment / pDevice->
channels;
2787 if (framesMixed == 0) {
2797 assert(pDevice !=
NULL);
2799 dra_device__lock(pDevice);
2802 if (!dra_device__is_playing_nolock(pDevice))
2811 dra_device__unlock(pDevice);
2816 assert(pDevice !=
NULL);
2818 dra_device__lock(pDevice);
2821 if (dra_device__is_playing_nolock(pDevice))
2829 dra_device__unlock(pDevice);
2832 void dra_device__voice_playback_count_inc(
dra_device* pDevice)
2834 assert(pDevice !=
NULL);
2836 dra_device__lock(pDevice);
2841 dra_device__unlock(pDevice);
2844 void dra_device__voice_playback_count_dec(
dra_device* pDevice)
2846 dra_device__lock(pDevice);
2850 dra_device__unlock(pDevice);
2855 DWORD dra_device__thread_proc(LPVOID pData)
2857 void* dra_device__thread_proc(
void* pData)
2861 assert(pDevice !=
NULL);
2878 dra_device__mix_next_fragment(pDevice);
2885 dra_event_queue__post_events(&pDevice->
eventQueue);
2890 dra_event_queue__post_events(&pDevice->
eventQueue);
2893 dra_device__stop(pDevice);
2896 dra_device__mix_next_fragment(pDevice);
2899 void* pSampleData = dra_backend_device_map_next_fragment(pDevice->
pBackendDevice, &sampleCount);
2900 if (pSampleData !=
NULL) {
2912 dra_event_queue__post_events(&pDevice->
eventQueue);
2928 if (pContext ==
NULL) {
2929 pContext = (
dra_context*)malloc(
sizeof(*pContext));
2930 if (pContext ==
NULL) {
2942 if (sampleRate == 0) sampleRate = DR_AUDIO_DEFAULT_SAMPLE_RATE;
2943 if (latencyInMilliseconds == 0) latencyInMilliseconds = DR_AUDIO_DEFAULT_LATENCY;
2948 memset(pDevice, 0,
sizeof(*pDevice));
2952 pDevice->
pBackendDevice = dra_backend_device_open(pContext->
pBackend, type, deviceID, channels, sampleRate, latencyInMilliseconds);
2962 pDevice->
mutex = dra_mutex_create();
2988 pDevice->
thread = dra_thread_create(dra_device__thread_proc, pDevice);
2997 if (pDevice !=
NULL) {
3014 return dra_device_init_ex(pContext, type, 0, 0, DR_AUDIO_DEFAULT_SAMPLE_RATE, DR_AUDIO_DEFAULT_LATENCY, pDevice);
3022 dra_device__lock(pDevice);
3026 dra_device__unlock(pDevice);
3029 dra_device__stop(pDevice);
3033 dra_thread_wait_and_delete(pDevice->
thread);
3052 dra_mutex_delete(pDevice->
mutex);
3074 if (pDevice ==
NULL) {
3084 *ppDevice = pDevice;
3090 return dra_device_create_ex(pContext, type, 0, 0, DR_AUDIO_DEFAULT_SAMPLE_RATE, DR_AUDIO_DEFAULT_LATENCY, ppDevice);
3095 if (pDevice ==
NULL)
return;
3105 dra_device__play(pDevice);
3113 dra_device__stop(pDevice);
3119 if (pDevice ==
NULL)
return;
3135 size_t extraDataSize = (size_t)pDevice->
pBackendDevice->samplesPerFragment *
sizeof(
float) * 2;
3137 if (pMixer ==
NULL) {
3158 if (pMixer ==
NULL)
return;
3172 if (pMixer ==
NULL || pSubmixer ==
NULL) {
3198 if (pMixer ==
NULL || pSubmixer ==
NULL) {
3232 if (pMixer ==
NULL) {
3243 if (pMixer ==
NULL || pVoice ==
NULL) {
3269 if (pMixer ==
NULL || pVoice ==
NULL) {
3300 if (pMixer ==
NULL) {
3311 if (pMixer ==
NULL) {
3320 if (pMixer ==
NULL) {
3329 if (pMixer ==
NULL) {
3342 size_t framesMixed = 0;
3352 size_t framesJustRead = dra_voice__next_frames(pVoice, frameCount, pMixer->
pNextSamplesToMix);
3353 for (
size_t i = 0; i < framesJustRead * pMixer->
pDevice->
channels; ++i) {
3358 if (framesJustRead < frameCount)
3369 if (framesMixed < framesJustRead) {
3370 framesMixed = framesJustRead;
3379 for (
size_t i = 0; i < framesJustMixed * pMixer->
pDevice->
channels; ++i) {
3383 if (framesMixed < framesJustMixed) {
3384 framesMixed = framesJustMixed;
3391 for (
size_t i = 0; i < samplesMixed; ++i) {
3414 if (pMixer ==
NULL) {
3428 if (pMixer ==
NULL) {
3444 if (pMixer ==
NULL) {
3448 if (ppVoicesOut ==
NULL) {
3454 ppVoicesOut[
count] = pVoice;
3463 if (pMixer ==
NULL) {
3467 if (ppVoicesOut ==
NULL) {
3484 if (pMixer ==
NULL)
return;
3490 if (pMixer ==
NULL)
return;
3495 dra_device__play(pMixer->
pDevice);
3516 if ((sizeInBytes % (bytesPerSample * channels)) != 0) {
3522 if (pVoice ==
NULL) {
3534 pVoice->
frameCount = sizeInBytes / (bytesPerSample * channels);
3540 if (pInitialData !=
NULL) {
3541 memcpy(pVoice->
pData, pInitialData, sizeInBytes);
3571 if (pVoice ==
NULL)
return;
3588 if (pVoice ==
NULL) {
3593 dra_device__voice_playback_count_inc(pVoice->
pDevice);
3606 dra_device__play(pVoice->
pDevice);
3611 if (pVoice ==
NULL) {
3619 dra_device__voice_playback_count_dec(pVoice->
pDevice);
3629 if (pVoice ==
NULL) {
3638 if (pVoice ==
NULL) {
3648 if (pVoice ==
NULL) {
3657 if (pVoice ==
NULL) {
3665 void dra_f32_to_f32(
float* pOut,
const float* pIn,
size_t sampleCount)
3667 memcpy(pOut, pIn, sampleCount *
sizeof(
float));
3670 void dra_s32_to_f32(
float* pOut,
const dr_int32* pIn,
size_t sampleCount)
3673 for (
size_t i = 0; i < sampleCount; ++i) {
3674 pOut[i] = pIn[i] / 2147483648.0f;
3678 void dra_s24_to_f32(
float* pOut,
const dr_uint8* pIn,
size_t sampleCount)
3681 for (
size_t i = 0; i < sampleCount; ++i) {
3687 pOut[i] = sample32 / 2147483648.0f;
3691 void dra_s16_to_f32(
float* pOut,
const dr_int16* pIn,
size_t sampleCount)
3694 for (
size_t i = 0; i < sampleCount; ++i) {
3695 pOut[i] = pIn[i] / 32768.0f;
3699 void dra_u8_to_f32(
float* pOut,
const dr_uint8* pIn,
size_t sampleCount)
3702 for (
size_t i = 0; i < sampleCount; ++i) {
3703 pOut[i] = (pIn[i] / 127.5f) - 1;
3710 void dra_to_f32(
float* pOut,
const void* pIn,
size_t sampleCount,
dra_format format)
3716 dra_f32_to_f32(pOut, (
float*)pIn, sampleCount);
3721 dra_s32_to_f32(pOut, (
dr_int32*)pIn, sampleCount);
3726 dra_s24_to_f32(pOut, (
dr_uint8*)pIn, sampleCount);
3731 dra_s16_to_f32(pOut, (
dr_int16*)pIn, sampleCount);
3736 dra_u8_to_f32(pOut, (
dr_uint8*)pIn, sampleCount);
3748 void dra_shuffle_channels__generic_inc(
float* pOut,
const float* pIn,
unsigned int channelsOut,
unsigned int channelsIn)
3753 assert(channelsOut > channelsIn);
3755 for (
unsigned int i = 0; i < channelsIn; ++i) {
3760 for (
unsigned int i = channelsIn; i < channelsOut; ++i) {
3765 void dra_shuffle_channels__generic_dec(
float* pOut,
const float* pIn,
unsigned int channelsOut,
unsigned int channelsIn)
3769 assert(channelsOut < channelsIn);
3773 for (
unsigned int i = 0; i < channelsOut; ++i) {
3778 void dra_shuffle_channels(
float* pOut,
const float* pIn,
unsigned int channelsOut,
unsigned int channelsIn)
3780 assert(channelsOut != 0);
3781 assert(channelsIn != 0);
3783 if (channelsOut == channelsIn) {
3784 for (
unsigned int i = 0; i < channelsOut; ++i) {
3793 for (
unsigned int i = 0; i < channelsOut; ++i) {
3801 if (channelsOut == 1)
3804 pOut[0] = (pIn[0] + pIn[1]) * 0.5f;
3809 dra_shuffle_channels__generic_inc(pOut, pIn, channelsOut, channelsIn);
3815 if (channelsOut == 1)
3819 for (
unsigned int i = 0; i < channelsIn; ++i) {
3823 pOut[0] = total / channelsIn;
3827 if (channelsOut > channelsIn) {
3828 dra_shuffle_channels__generic_inc(pOut, pIn, channelsOut, channelsIn);
3830 dra_shuffle_channels__generic_dec(pOut, pIn, channelsOut, channelsIn);
3838 float dra_voice__get_sample_rate_factor(
dra_voice* pVoice)
3840 if (pVoice ==
NULL) {
3847 void dra_voice__unsignal_playback_events(
dra_voice* pVoice)
3856 float* dra_voice__next_frame(
dra_voice* pVoice)
3858 if (pVoice ==
NULL) {
3875 dra_voice__unsignal_playback_events(pVoice);
3893 unsigned int channelsIn = pVoice->
channels;
3900 dra_shuffle_channels(pOut, (
float*)pVoice->
pData + sampleOffset, channelsOut, channelsIn);
3902 sampleOffset = pVoice->
currentReadPos * (channelsIn * bytesPerSample);
3903 dra_to_f32(tempFrame, (
dr_uint8*)pVoice->
pData + sampleOffset, channelsIn, pVoice->
format);
3904 dra_shuffle_channels(pOut, tempFrame, channelsOut, channelsIn);
3910 dra_voice__unsignal_playback_events(pVoice);
3918 unsigned int sampleRateIn = pVoice->
sampleRate;
3920 unsigned int channelsIn = pVoice->
channels;
3923 float factor = (float)sampleRateOut / (
float)sampleRateIn;
3924 float invfactor = 1 / factor;
3936 dr_uint64 nextFrameIndexIn = prevFrameIndexIn + 1;
3937 if (nextFrameIndexIn >= pVoice->
frameCount) {
3941 if (prevFrameIndexIn != pVoice->
src.
data.linear.prevFrameIndex)
3943 dr_uint64 sampleOffset = prevFrameIndexIn * (channelsIn * bytesPerSample);
3946 sampleOffset = nextFrameIndexIn * (channelsIn * bytesPerSample);
3949 pVoice->
src.
data.linear.prevFrameIndex = prevFrameIndexIn;
3952 float alpha = timeIn - prevFrameIndexIn;
3954 for (
unsigned int i = 0; i < pVoice->
channels; ++i) {
3955 frame[i] = dra_mixf(pVoice->
src.
data.linear.prevFrame[i], pVoice->
src.
data.linear.nextFrame[i], alpha);
3958 dra_shuffle_channels(pOut, frame, channelsOut, channelsIn);
3965 dra_voice__unsignal_playback_events(pVoice);
3973 size_t dra_voice__next_frames(
dra_voice* pVoice,
size_t frameCount,
float* pSamplesOut)
3977 size_t framesRead = 0;
3981 float* pNextFrame =
NULL;
3982 while ((framesRead < frameCount) && (pNextFrame = dra_voice__next_frame(pVoice)) !=
NULL) {
3983 memcpy(pSamplesOut, pNextFrame, pVoice->
pDevice->
channels *
sizeof(
float));
3988 float sampleRateFactor = dra_voice__get_sample_rate_factor(pVoice);
3992 dr_uint64 currentReadPosLocal = (prevReadPosLocal + (framesRead * pVoice->
channels)) % totalSampleCount;
4007 if (pVoice ==
NULL) {
4020 if (pVoice ==
NULL) {
4033 if (pVoice ==
NULL) {
4053 if (pVoice ==
NULL) {
4070 if (pVoice ==
NULL) {
4079 if (pVoice ==
NULL) {
4094 pVoice->
src.
data.linear.prevFrameIndex = 0;
4104 if (pVoice ==
NULL) {
4109 if (sample > totalSampleCount) {
4119 if (pData ==
NULL) {
4124 if (sampleCount > totalSamplesRemaining) {
4125 sampleCount = totalSamplesRemaining;
4145 unsigned int lookup[] = {
4153 return lookup[format];
4164 #ifndef DR_AUDIO_NO_STDIO
4165 static FILE* dra__fopen(
const char* filePath)
4169 if (fopen_s(&pFile, filePath,
"rb") != 0) {
4173 pFile = fopen(filePath,
"rb");
4174 if (pFile ==
NULL) {
4179 return (FILE*)pFile;
4181 #endif //DR_AUDIO_NO_STDIO
4186 #ifdef DR_AUDIO_HAS_WAV
4187 size_t dra_decoder_on_read__wav(
void* pUserData,
void* pDataOut,
size_t bytesToRead)
4190 assert(pDecoder !=
NULL);
4198 assert(pDecoder !=
NULL);
4204 void dra_decoder_on_delete__wav(
void* pBackendDecoder)
4207 assert(pWav !=
NULL);
4212 dr_uint64 dra_decoder_on_read_samples__wav(
void* pBackendDecoder,
dr_uint64 samplesToRead,
float* pSamplesOut)
4215 assert(pWav !=
NULL);
4217 return drwav_read_f32(pWav, samplesToRead, pSamplesOut);
4223 assert(pWav !=
NULL);
4225 return drwav_seek_to_sample(pWav, sample);
4231 assert(pDecoder !=
NULL);
4232 assert(pWav !=
NULL);
4239 pDecoder->
onDelete = dra_decoder_on_delete__wav;
4246 drwav* pWav = drwav_open(dra_decoder_on_read__wav, dra_decoder_on_seek__wav, pDecoder);
4251 dra_decoder_init__wav(pDecoder, pWav);
4255 dr_bool32 dra_decoder_open_memory__wav(
dra_decoder* pDecoder,
const void* pData,
size_t dataSize)
4257 drwav* pWav = drwav_open_memory(pData, dataSize);
4262 dra_decoder_init__wav(pDecoder, pWav);
4266 #ifdef DR_AUDIO_HAS_WAV_STDIO
4269 drwav* pWav = drwav_open_file(filePath);
4274 dra_decoder_init__wav(pDecoder, pWav);
4280 #ifdef DR_AUDIO_HAS_FLAC
4281 size_t dra_decoder_on_read__flac(
void* pUserData,
void* pDataOut,
size_t bytesToRead)
4284 assert(pDecoder !=
NULL);
4292 assert(pDecoder !=
NULL);
4298 void dra_decoder_on_delete__flac(
void* pBackendDecoder)
4301 assert(pFlac !=
NULL);
4306 dr_uint64 dra_decoder_on_read_samples__flac(
void* pBackendDecoder,
dr_uint64 samplesToRead,
float* pSamplesOut)
4309 assert(pFlac !=
NULL);
4311 dr_uint64 samplesRead = drflac_read_s32(pFlac, samplesToRead, (
dr_int32*)pSamplesOut);
4313 dra_s32_to_f32(pSamplesOut, (
dr_int32*)pSamplesOut, (
size_t)samplesRead);
4320 assert(pFlac !=
NULL);
4322 return drflac_seek_to_sample(pFlac, sample);
4328 assert(pDecoder !=
NULL);
4329 assert(pFlac !=
NULL);
4336 pDecoder->
onDelete = dra_decoder_on_delete__flac;
4337 pDecoder->
onReadSamples = dra_decoder_on_read_samples__flac;
4338 pDecoder->
onSeekSamples = dra_decoder_on_seek_samples__flac;
4343 drflac* pFlac =
drflac_open(dra_decoder_on_read__flac, dra_decoder_on_seek__flac, pDecoder);
4344 if (pFlac ==
NULL) {
4348 dra_decoder_init__flac(pDecoder, pFlac);
4352 dr_bool32 dra_decoder_open_memory__flac(
dra_decoder* pDecoder,
const void* pData,
size_t dataSize)
4355 if (pFlac ==
NULL) {
4359 dra_decoder_init__flac(pDecoder, pFlac);
4363 #ifdef DR_AUDIO_HAS_FLAC_STDIO
4367 if (pFlac ==
NULL) {
4371 dra_decoder_init__flac(pDecoder, pFlac);
4377 #ifdef DR_AUDIO_HAS_VORBIS
4378 void dra_decoder_on_delete__vorbis(
void* pBackendDecoder)
4381 assert(pVorbis !=
NULL);
4386 dr_uint64 dra_decoder_on_read_samples__vorbis(
void* pBackendDecoder,
dr_uint64 samplesToRead,
float* pSamplesOut)
4389 assert(pVorbis !=
NULL);
4395 dr_bool32 dra_decoder_on_seek_samples__vorbis(
void* pBackendDecoder,
dr_uint64 sample)
4398 assert(pVorbis !=
NULL);
4406 assert(pDecoder !=
NULL);
4407 assert(pVorbis !=
NULL);
4416 pDecoder->
onDelete = dra_decoder_on_delete__vorbis;
4417 pDecoder->
onReadSamples = dra_decoder_on_read_samples__vorbis;
4418 pDecoder->
onSeekSamples = dra_decoder_on_seek_samples__vorbis;
4430 dr_bool32 dra_decoder_open_memory__vorbis(
dra_decoder* pDecoder,
const void* pData,
size_t dataSize)
4433 if (pVorbis ==
NULL) {
4437 dra_decoder_init__vorbis(pDecoder, pVorbis);
4441 #ifdef DR_AUDIO_HAS_VORBIS_STDIO
4445 if (pVorbis ==
NULL) {
4449 dra_decoder_init__vorbis(pDecoder, pVorbis);
4458 memset(pDecoder, 0,
sizeof(*pDecoder));
4462 pDecoder->
onRead = onRead;
4463 pDecoder->
onSeek = onSeek;
4466 #ifdef DR_AUDIO_HAS_WAV_STDIO
4467 if (dra_decoder_open__wav(pDecoder)) {
4472 #ifdef DR_AUDIO_HAS_FLAC_STDIO
4473 if (dra_decoder_open__flac(pDecoder)) {
4478 #ifdef DR_AUDIO_HAS_VORBIS_STDIO
4479 if (dra_decoder_open__vorbis(pDecoder)) {
4490 size_t dra_decoder__on_read_memory(
void* pUserData,
void* pDataOut,
size_t bytesToRead)
4493 assert(memoryStream !=
NULL);
4497 if (bytesToRead > bytesRemaining) {
4498 bytesToRead = bytesRemaining;
4501 if (bytesToRead > 0) {
4511 assert(memoryStream !=
NULL);
4515 if (memoryStream->
currentReadPos + offset <= memoryStream->dataSize) {
4521 if ((
dr_uint32)offset <= memoryStream->dataSize) {
4534 memset(pDecoder, 0,
sizeof(*pDecoder));
4539 #if defined(DR_AUDIO_HAS_WAV)
4540 if (dra_decoder_open_memory__wav(pDecoder, pData, dataSize)) {
4544 #if defined(DR_AUDIO_HAS_FLAC)
4545 if (dra_decoder_open_memory__flac(pDecoder, pData, dataSize)) {
4549 #if defined(DR_AUDIO_HAS_VORBIS)
4550 if (dra_decoder_open_memory__vorbis(pDecoder, pData, dataSize)) {
4557 memoryStream.
data = (
const unsigned char*)pData;
4572 #ifndef DR_AUDIO_NO_STDIO
4573 size_t dra_decoder__on_read_stdio(
void* pUserData,
void* pDataOut,
size_t bytesToRead)
4575 return fread(pDataOut, 1, bytesToRead, (FILE*)pUserData);
4585 memset(pDecoder, 0,
sizeof(*pDecoder));
4590 #if defined(DR_AUDIO_HAS_WAV) && defined(DR_AUDIO_HAS_WAV_STDIO)
4591 if (dra_decoder_open_file__wav(pDecoder, filePath)) {
4595 #if defined(DR_AUDIO_HAS_FLAC) && defined(DR_AUDIO_HAS_FLAC_STDIO)
4596 if (dra_decoder_open_file__flac(pDecoder, filePath)) {
4600 #if defined(DR_AUDIO_HAS_VORBIS) && defined(DR_AUDIO_HAS_VORBIS_STDIO)
4601 if (dra_decoder_open_file__vorbis(pDecoder, filePath)) {
4608 FILE* pFile = dra__fopen(filePath);
4609 if (pFile ==
NULL) {
4625 if (pDecoder ==
NULL) {
4633 #ifndef DR_AUDIO_NO_STDIO
4634 if (pDecoder->
onRead == dra_decoder__on_read_stdio) {
4642 if (pDecoder ==
NULL || pSamplesOut ==
NULL) {
4651 if (pDecoder ==
NULL) {
4659 float* dra_decoder__full_decode_and_close(
dra_decoder* pDecoder,
unsigned int* channelsOut,
unsigned int* sampleRateOut,
dr_uint64* totalSampleCountOut)
4661 assert(pDecoder !=
NULL);
4663 float* pSampleData =
NULL;
4666 if (totalSampleCount == 0)
4670 size_t sampleDataBufferSize =
sizeof(buffer);
4671 pSampleData = (
float*)malloc(sampleDataBufferSize);
4672 if (pSampleData ==
NULL) {
4679 if (((totalSampleCount + samplesRead) *
sizeof(float)) > sampleDataBufferSize) {
4680 sampleDataBufferSize *= 2;
4681 float* pNewSampleData = (
float*)realloc(pSampleData, sampleDataBufferSize);
4682 if (pNewSampleData ==
NULL) {
4687 pSampleData = pNewSampleData;
4690 memcpy(pSampleData + totalSampleCount, buffer, (
size_t)(samplesRead*
sizeof(
float)));
4691 totalSampleCount += samplesRead;
4696 memset(pSampleData + totalSampleCount, 0, (
size_t)(sampleDataBufferSize - totalSampleCount*
sizeof(
float)));
4700 dr_uint64 dataSize = totalSampleCount *
sizeof(float);
4701 if (dataSize > SIZE_MAX) {
4705 pSampleData = (
float*)malloc((
size_t)dataSize);
4706 if (pSampleData ==
NULL) {
4718 if (channelsOut) *channelsOut = pDecoder->
channels;
4719 if (sampleRateOut) *sampleRateOut = pDecoder->
sampleRate;
4720 if (totalSampleCountOut) *totalSampleCountOut = totalSampleCount;
4733 if (channels) *channels = 0;
4734 if (sampleRate) *sampleRate = 0;
4735 if (totalSampleCount) *totalSampleCount = 0;
4743 return dra_decoder__full_decode_and_close(&
decoder, channels, sampleRate, totalSampleCount);
4749 if (channels) *channels = 0;
4750 if (sampleRate) *sampleRate = 0;
4751 if (totalSampleCount) *totalSampleCount = 0;
4759 return dra_decoder__full_decode_and_close(&
decoder, channels, sampleRate, totalSampleCount);
4762 #ifndef DR_AUDIO_NO_STDIO
4766 if (channels) *channels = 0;
4767 if (sampleRate) *sampleRate = 0;
4768 if (totalSampleCount) *totalSampleCount = 0;
4776 return dra_decoder__full_decode_and_close(&
decoder, channels, sampleRate, totalSampleCount);
4784 #ifndef DR_AUDIO_NO_STDIO
4789 unsigned int channels;
4790 unsigned int sampleRate;
4793 if (pSampleData ==
NULL) {
4810 if (pWorld ==
NULL) {
4837 if (pWorld ==
NULL) {
4849 void dra_sound_world__on_inline_sound_stop(
dr_uint64 eventID,
void* pUserData)
4854 assert(pSound !=
NULL);
4861 if (pWorld ==
NULL || pDesc ==
NULL) {
4868 if (pSound ==
NULL) {
4872 if (pMixer !=
NULL) {
4882 if (pWorld ==
NULL || pDesc ==
NULL) {
4895 if (pWorld ==
NULL) {
4902 if (voiceCount == 0) {
4907 if (ppVoices ==
NULL) {
4912 assert(voiceCount != 0);
4914 for (
size_t iVoice = 0; iVoice < voiceCount; ++iVoice) {
4923 if (pWorld ==
NULL) {
4935 if (pWorld ==
NULL) {
4951 assert(pSound !=
NULL);
4957 assert(pSound !=
NULL);
4963 assert(chunkSizeInSamples > 0);
4966 if (samplesRead == 0 && !pSound->
isLooping) {
4971 if (samplesRead == chunkSizeInSamples) {
4975 assert(samplesRead > 0);
4976 assert(samplesRead < chunkSizeInSamples);
4987 while (samplesRead < chunkSizeInSamples) {
4992 dr_uint64 samplesRemaining = chunkSizeInSamples - samplesRead;
4994 if (samplesJustRead == 0) {
4998 samplesRead += samplesJustRead;
5004 void dra_sound__on_read_next_chunk(
dr_uint64 eventID,
void* pUserData)
5007 assert(pSound !=
NULL);
5017 if (!dra_sound__read_next_chunk(pSound, sampleOffset)) {
5025 if (pWorld ==
NULL) {
5033 if (pSound ==
NULL) {
5039 pSound->
desc = *pDesc;
5041 isStreaming = dra_sound__is_streaming(pSound);
5064 if (!dra_sound__read_next_chunk(pSound, 0)) {
5078 void dra_sound__on_delete_decoder(
dra_sound* pSound)
5081 assert(pDecoder !=
NULL);
5090 assert(pDecoder !=
NULL);
5098 assert(pDecoder !=
NULL);
5103 #ifndef DR_AUDIO_NO_STDIO
5106 if (pWorld ==
NULL || filePath ==
NULL) {
5111 if (pDecoder ==
NULL) {
5127 desc.
onDelete = dra_sound__on_delete_decoder;
5128 desc.
onRead = dra_sound__on_read_decoder;
5129 desc.
onSeek = dra_sound__on_seek_decoder;
5145 if (pSound ==
NULL) {
5163 if (pSound ==
NULL) {
5168 if (dra_sound__is_streaming(pSound)) {
5179 if (pSound ==
NULL) {
5189 if (pSound ==
NULL) {
5193 if (pMixer ==
NULL) {
5211 #endif //DR_AUDIO_IMPLEMENTATION