77 #define DRAUDIO_MAX_DEVICE_COUNT 16
78 #define DRAUDIO_MAX_MARKER_COUNT 4
79 #define DRAUDIO_MAX_MESSAGE_QUEUE_SIZE 1024 // The maximum number of messages that can be cached in the internal message queues.
82 #if defined(_WIN32) && !defined(DRAUDIO_NO_DIRECTSOUND)
83 #define DRAUDIO_BUILD_DSOUND
87 #define DRAUDIO_EVENT_ID_STOP 0xFFFFFFFF
88 #define DRAUDIO_EVENT_ID_PAUSE 0xFFFFFFFE
89 #define DRAUDIO_EVENT_ID_PLAY 0xFFFFFFFD
90 #define DRAUDIO_EVENT_ID_MARKER 0
92 #define DRAUDIO_ENABLE_3D (1 << 0)
93 #define DRAUDIO_RELATIVE_3D (1 << 1) // <-- Uses relative 3D positioning by default instead of absolute. Only used if DRAUDIO_ENABLE_3D is also specified.
260 #ifdef DRAUDIO_BUILD_DSOUND
759 #ifdef DR_AUDIO_IMPLEMENTATION
768 #ifndef DRAUDIO_PRIVATE
769 #define DRAUDIO_PRIVATE
777 int draudio_strcpy(
char* dst,
size_t dstSizeInBytes,
const char* src)
779 #if defined(_MSC_VER)
780 return strcpy_s(dst, dstSizeInBytes, src);
785 if (dstSizeInBytes == 0) {
794 const char* iSrc = src;
795 size_t remainingSizeInBytes = dstSizeInBytes;
796 while (remainingSizeInBytes > 0 && iSrc[0] !=
'\0')
802 remainingSizeInBytes -= 1;
805 if (remainingSizeInBytes > 0) {
817 typedef void (* draudio_delete_context_proc)(
draudio_context* pContext);
819 typedef void (* draudio_delete_output_device_proc)(
draudio_device* pDevice);
820 typedef unsigned int (* draudio_get_output_device_count_proc)(
draudio_context* pContext);
823 typedef void (* draudio_delete_buffer_proc)(
draudio_buffer* pBuffer);
824 typedef unsigned int (* draudio_get_buffer_extra_data_size_proc)(
draudio_buffer* pBuffer);
825 typedef void* (* draudio_get_buffer_extra_data_proc)(
draudio_buffer* pBuffer);
826 typedef void (* draudio_set_buffer_data_proc)(
draudio_buffer* pBuffer,
size_t offset,
const void* pData,
size_t dataSizeInBytes);
827 typedef void (* draudio_play_proc)(
draudio_buffer* pBuffer,
bool loop);
831 typedef void (* draudio_set_playback_position_proc)(
draudio_buffer* pBuffer,
unsigned int position);
832 typedef unsigned int (* draudio_get_playback_position_proc)(
draudio_buffer* pBuffer);
833 typedef void (* draudio_set_pan_proc)(
draudio_buffer* pBuffer,
float pan);
835 typedef void (* draudio_set_volume_proc)(
draudio_buffer* pBuffer,
float volume);
836 typedef float (* draudio_get_volume_proc)(
draudio_buffer* pBuffer);
837 typedef void (* draudio_remove_markers_proc)(
draudio_buffer* pBuffer);
842 typedef void (* draudio_set_position_proc)(
draudio_buffer* pBuffer,
float x,
float y,
float z);
843 typedef void (* draudio_get_position_proc)(
draudio_buffer* pBuffer,
float* pPosOut);
844 typedef void (* draudio_set_listener_position_proc)(
draudio_device* pDevice,
float x,
float y,
float z);
845 typedef void (* draudio_get_listener_position_proc)(
draudio_device* pDevice,
float* pPosOut);
846 typedef void (* draudio_set_listener_orientation_proc)(
draudio_device* pDevice,
float forwardX,
float forwardY,
float forwardZ,
float upX,
float upY,
float upZ);
847 typedef void (* draudio_get_listener_orientation_proc)(
draudio_device* pDevice,
float* pForwardOut,
float* pUpOut);
854 draudio_delete_context_proc delete_context;
855 draudio_create_output_device_proc create_output_device;
856 draudio_delete_output_device_proc delete_output_device;
857 draudio_get_output_device_count_proc get_output_device_count;
858 draudio_get_output_device_info_proc get_output_device_info;
859 draudio_create_buffer_proc create_buffer;
860 draudio_delete_buffer_proc delete_buffer;
861 draudio_get_buffer_extra_data_size_proc get_buffer_extra_data_size;
862 draudio_get_buffer_extra_data_proc get_buffer_extra_data;
863 draudio_set_buffer_data_proc set_buffer_data;
864 draudio_play_proc play;
865 draudio_pause_proc pause;
866 draudio_stop_proc stop;
867 draudio_get_playback_state_proc get_playback_state;
868 draudio_set_playback_position_proc set_playback_position;
869 draudio_get_playback_position_proc get_playback_position;
870 draudio_set_pan_proc set_pan;
871 draudio_get_pan_proc get_pan;
872 draudio_set_volume_proc set_volume;
873 draudio_get_volume_proc get_volume;
874 draudio_remove_markers_proc remove_markers;
875 draudio_register_marker_callback_proc register_marker_callback;
876 draudio_register_stop_callback_proc register_stop_callback;
877 draudio_register_pause_callback_proc register_pause_callback;
878 draudio_register_play_callback_proc register_play_callback;
879 draudio_set_position_proc set_position;
880 draudio_get_position_proc get_position;
881 draudio_set_listener_position_proc set_listener_position;
882 draudio_get_listener_position_proc get_listener_position;
883 draudio_set_listener_orientation_proc set_listener_orientation;
884 draudio_get_listener_orientation_proc get_listener_orientation;
885 draudio_set_3d_mode_proc set_3d_mode;
886 draudio_get_3d_mode_proc get_3d_mode;
896 bool markedForDeletion;
918 bool markedForDeletion;
926 #ifdef DRAUDIO_BUILD_DSOUND
927 pContext = draudio_create_context_dsound();
928 if (pContext !=
NULL) {
936 assert(pContext ==
NULL);
942 if (pContext ==
NULL) {
946 pContext->delete_context(pContext);
963 if (pContext ==
NULL) {
967 return pContext->get_output_device_count(pContext);
972 if (pContext ==
NULL) {
976 if (pInfoOut ==
NULL) {
980 return pContext->get_output_device_info(pContext, deviceIndex, pInfoOut);
986 if (pContext ==
NULL) {
990 draudio_device* pDevice = pContext->create_output_device(pContext, deviceIndex);
993 pDevice->markedForDeletion =
false;
1001 if (pDevice ==
NULL) {
1006 if (pDevice->markedForDeletion) {
1011 pDevice->markedForDeletion =
true;
1013 assert(pDevice->pContext !=
NULL);
1014 pDevice->pContext->delete_output_device(pDevice);
1020 if (pDevice ==
NULL) {
1024 if (pBufferDesc ==
NULL) {
1028 assert(pDevice->pContext !=
NULL);
1030 draudio_buffer* pBuffer = pDevice->pContext->create_buffer(pDevice, pBufferDesc, extraDataSize);
1031 if (pBuffer !=
NULL)
1035 pBuffer->pDevice = pDevice;
1036 pBuffer->stopCallback = nullcb;
1037 pBuffer->pauseCallback = nullcb;
1038 pBuffer->playCallback = nullcb;
1039 pBuffer->isLooping =
false;
1040 pBuffer->markedForDeletion =
false;
1048 if (pBuffer ==
NULL) {
1053 if (pBuffer->markedForDeletion) {
1058 pBuffer->markedForDeletion =
true;
1071 assert(pBuffer->pDevice !=
NULL);
1072 assert(pBuffer->pDevice->pContext !=
NULL);
1073 pBuffer->pDevice->pContext->delete_buffer(pBuffer);
1079 if (pBuffer ==
NULL) {
1083 assert(pBuffer->pDevice !=
NULL);
1084 assert(pBuffer->pDevice->pContext !=
NULL);
1085 return pBuffer->pDevice->pContext->get_buffer_extra_data_size(pBuffer);
1090 if (pBuffer ==
NULL) {
1094 assert(pBuffer->pDevice !=
NULL);
1095 assert(pBuffer->pDevice->pContext !=
NULL);
1096 return pBuffer->pDevice->pContext->get_buffer_extra_data(pBuffer);
1102 if (pBuffer ==
NULL) {
1106 if (pData ==
NULL) {
1110 assert(pBuffer->pDevice !=
NULL);
1111 assert(pBuffer->pDevice->pContext !=
NULL);
1112 pBuffer->pDevice->pContext->set_buffer_data(pBuffer, offset, pData, dataSizeInBytes);
1117 if (pBuffer ==
NULL) {
1121 pBuffer->isLooping = loop;
1123 assert(pBuffer->pDevice !=
NULL);
1124 assert(pBuffer->pDevice->pContext !=
NULL);
1125 pBuffer->pDevice->pContext->play(pBuffer, loop);
1130 if (pBuffer ==
NULL) {
1134 assert(pBuffer->pDevice !=
NULL);
1135 assert(pBuffer->pDevice->pContext !=
NULL);
1136 pBuffer->pDevice->pContext->pause(pBuffer);
1141 if (pBuffer ==
NULL) {
1145 assert(pBuffer->pDevice !=
NULL);
1146 assert(pBuffer->pDevice->pContext !=
NULL);
1147 pBuffer->pDevice->pContext->stop(pBuffer);
1152 if (pBuffer ==
NULL) {
1156 assert(pBuffer->pDevice !=
NULL);
1157 assert(pBuffer->pDevice->pContext !=
NULL);
1158 return pBuffer->pDevice->pContext->get_playback_state(pBuffer);
1163 if (pBuffer ==
NULL) {
1167 return pBuffer->isLooping;
1173 if (pBuffer ==
NULL) {
1177 assert(pBuffer->pDevice !=
NULL);
1178 assert(pBuffer->pDevice->pContext !=
NULL);
1179 pBuffer->pDevice->pContext->set_playback_position(pBuffer, position);
1184 if (pBuffer ==
NULL) {
1188 assert(pBuffer->pDevice !=
NULL);
1189 assert(pBuffer->pDevice->pContext !=
NULL);
1190 return pBuffer->pDevice->pContext->get_playback_position(pBuffer);
1196 if (pBuffer ==
NULL) {
1200 assert(pBuffer->pDevice !=
NULL);
1201 assert(pBuffer->pDevice->pContext !=
NULL);
1202 pBuffer->pDevice->pContext->set_pan(pBuffer, pan);
1207 if (pBuffer ==
NULL) {
1211 assert(pBuffer->pDevice !=
NULL);
1212 assert(pBuffer->pDevice->pContext !=
NULL);
1213 return pBuffer->pDevice->pContext->get_pan(pBuffer);
1219 if (pBuffer ==
NULL) {
1223 assert(pBuffer->pDevice !=
NULL);
1224 assert(pBuffer->pDevice->pContext !=
NULL);
1225 pBuffer->pDevice->pContext->set_volume(pBuffer, volume);
1230 if (pBuffer ==
NULL) {
1234 assert(pBuffer->pDevice !=
NULL);
1235 assert(pBuffer->pDevice->pContext !=
NULL);
1236 return pBuffer->pDevice->pContext->get_volume(pBuffer);
1242 if (pBuffer ==
NULL) {
1246 assert(pBuffer->pDevice !=
NULL);
1247 assert(pBuffer->pDevice->pContext !=
NULL);
1248 pBuffer->pDevice->pContext->remove_markers(pBuffer);
1253 if (pBuffer ==
NULL) {
1268 assert(pBuffer->pDevice !=
NULL);
1269 assert(pBuffer->pDevice->pContext !=
NULL);
1270 return pBuffer->pDevice->pContext->register_marker_callback(pBuffer, offsetInBytes, callback, eventID, pUserData);
1275 if (pBuffer ==
NULL) {
1283 pBuffer->stopCallback.callback = callback;
1284 pBuffer->stopCallback.pUserData = pUserData;
1286 assert(pBuffer->pDevice !=
NULL);
1287 assert(pBuffer->pDevice->pContext !=
NULL);
1288 return pBuffer->pDevice->pContext->register_stop_callback(pBuffer, callback, pUserData);
1293 if (pBuffer ==
NULL) {
1301 pBuffer->pauseCallback.callback = callback;
1302 pBuffer->pauseCallback.pUserData = pUserData;
1304 assert(pBuffer->pDevice !=
NULL);
1305 assert(pBuffer->pDevice->pContext !=
NULL);
1306 return pBuffer->pDevice->pContext->register_pause_callback(pBuffer, callback, pUserData);
1311 if (pBuffer ==
NULL) {
1319 pBuffer->playCallback.callback = callback;
1320 pBuffer->playCallback.pUserData = pUserData;
1322 assert(pBuffer->pDevice !=
NULL);
1323 assert(pBuffer->pDevice->pContext !=
NULL);
1324 return pBuffer->pDevice->pContext->register_play_callback(pBuffer, callback, pUserData);
1330 if (pBuffer !=
NULL) {
1331 return pBuffer->stopCallback;
1340 if (pBuffer !=
NULL) {
1341 return pBuffer->pauseCallback;
1350 if (pBuffer !=
NULL) {
1351 return pBuffer->playCallback;
1361 if (pBuffer ==
NULL) {
1365 assert(pBuffer->pDevice !=
NULL);
1366 assert(pBuffer->pDevice->pContext !=
NULL);
1367 pBuffer->pDevice->pContext->set_position(pBuffer, x, y, z);
1372 if (pBuffer ==
NULL) {
1376 if (pPosOut ==
NULL) {
1380 assert(pBuffer->pDevice !=
NULL);
1381 assert(pBuffer->pDevice->pContext !=
NULL);
1382 pBuffer->pDevice->pContext->get_position(pBuffer, pPosOut);
1388 if (pDevice ==
NULL) {
1392 pDevice->pContext->set_listener_position(pDevice, x, y, z);
1397 if (pDevice ==
NULL || pPosOut ==
NULL) {
1401 pDevice->pContext->get_listener_position(pDevice, pPosOut);
1406 if (pDevice ==
NULL) {
1410 pDevice->pContext->set_listener_orientation(pDevice, forwardX, forwardY, forwardZ, upX, upY, upZ);
1415 if (pDevice ==
NULL) {
1419 pDevice->pContext->get_listener_orientation(pDevice, pForwardOut, pUpOut);
1425 if (pBuffer ==
NULL) {
1429 assert(pBuffer->pDevice !=
NULL);
1430 assert(pBuffer->pDevice->pContext !=
NULL);
1431 pBuffer->pDevice->pContext->set_3d_mode(pBuffer, mode);
1436 if (pBuffer ==
NULL) {
1440 assert(pBuffer->pDevice !=
NULL);
1441 assert(pBuffer->pDevice->pContext !=
NULL);
1442 return pBuffer->pDevice->pContext->get_3d_mode(pBuffer);
1474 #include <windows.h>
1481 InitializeCriticalSection((LPCRITICAL_SECTION)mutex);
1489 DeleteCriticalSection((LPCRITICAL_SECTION)mutex);
1495 EnterCriticalSection((LPCRITICAL_SECTION)mutex);
1500 LeaveCriticalSection((LPCRITICAL_SECTION)mutex);
1503 #include <pthread.h>
1507 pthread_mutex_t* mutex = malloc(
sizeof(pthread_mutex_t));
1508 if (pthread_mutex_init(mutex,
NULL) != 0) {
1518 pthread_mutex_destroy(mutex);
1523 pthread_mutex_lock(mutex);
1528 pthread_mutex_unlock(mutex);
1536 #define DRAUDIO_STREAMING_MARKER_0 DRAUDIO_EVENT_ID_MARKER + 0
1537 #define DRAUDIO_STREAMING_MARKER_1 DRAUDIO_EVENT_ID_MARKER + 1
1539 #define DRAUDIO_STREAMING_CHUNK_INVALID 0
1550 bool stopAtEndOfCurrentChunk;
1553 bool isLoopingEnabled;
1556 size_t extraDataSize;
1562 unsigned char pTempChunkData[1];
1564 } ea_streaming_buffer_data;
1567 bool ea_streaming_buffer_load_next_chunk(
draudio_buffer* pBuffer, ea_streaming_buffer_data* pStreamingData,
size_t offset,
size_t chunkSize)
1569 assert(pStreamingData !=
NULL);
1570 assert(pStreamingData->callbacks.read !=
NULL);
1571 assert(pStreamingData->callbacks.seek !=
NULL);
1572 assert(pStreamingData->chunkSize >= chunkSize);
1575 if (chunkSize == 0) {
1580 if (!pStreamingData->callbacks.read(pStreamingData->callbacks.pUserData, pStreamingData->pTempChunkData, chunkSize, &bytesRead))
1587 pStreamingData->stopAtEndOfCurrentChunk =
false;
1591 if (chunkSize > bytesRead)
1598 if (pStreamingData->isLoopingEnabled)
1600 pStreamingData->callbacks.seek(pStreamingData->callbacks.pUserData, 0);
1601 return ea_streaming_buffer_load_next_chunk(pBuffer, pStreamingData, offset + bytesRead, chunkSize - bytesRead);
1605 memset(pStreamingData->pTempChunkData + bytesRead, 0, chunkSize - bytesRead);
1606 draudio_set_buffer_data(pBuffer, offset + bytesRead, pStreamingData->pTempChunkData + bytesRead, chunkSize - bytesRead);
1608 pStreamingData->stopAtEndOfCurrentChunk =
true;
1615 void ea_steaming_buffer_marker_callback(
draudio_buffer* pBuffer,
unsigned int eventID,
void *pUserData)
1617 ea_streaming_buffer_data* pStreamingData = (ea_streaming_buffer_data*)pUserData;
1618 assert(pStreamingData !=
NULL);
1621 if (eventID == DRAUDIO_STREAMING_MARKER_0) {
1622 offset = pStreamingData->chunkSize;
1625 if (pStreamingData->stopAtEndOfCurrentChunk)
1627 if (!pStreamingData->atStart) {
1633 ea_streaming_buffer_load_next_chunk(pBuffer, pStreamingData, offset, pStreamingData->chunkSize);
1636 pStreamingData->atStart =
false;
1646 if (pBufferDesc ==
NULL) {
1659 if (pBuffer ==
NULL) {
1665 assert(pStreamingData !=
NULL);
1667 pStreamingData->callbacks = callbacks;
1668 pStreamingData->atStart =
true;
1669 pStreamingData->stopAtEndOfCurrentChunk =
false;
1670 pStreamingData->isLoopingEnabled =
false;
1671 pStreamingData->chunkSize = chunkSize;
1685 if (pBuffer ==
NULL) {
1690 assert(pStreamingData !=
NULL);
1692 return pStreamingData->extraDataSize;
1697 if (pBuffer ==
NULL) {
1702 assert(pStreamingData !=
NULL);
1704 return ((
char*)pStreamingData->pTempChunkData) + pStreamingData->chunkSize;
1710 if (pBuffer ==
NULL) {
1716 assert(pStreamingData !=
NULL);
1722 pStreamingData->atStart =
true;
1723 pStreamingData->callbacks.seek(pStreamingData->callbacks.pUserData, 0);
1725 if (!ea_streaming_buffer_load_next_chunk(pBuffer, pStreamingData, 0, pStreamingData->chunkSize))
1733 pStreamingData->isLoopingEnabled = loop;
1741 if (pBuffer ==
NULL) {
1746 assert(pStreamingData !=
NULL);
1748 return pStreamingData->isLoopingEnabled;
1759 DRAUDIO_PRIVATE
draudio_bool draudio_on_sound_read_callback(
void* pUserData,
void* pDataOut,
size_t bytesToRead,
size_t* bytesReadOut)
1762 assert(pSound !=
NULL);
1765 bool result =
false;
1769 result = pSound->
onRead(pSound, pDataOut, bytesToRead, bytesReadOut);
1777 DRAUDIO_PRIVATE
static draudio_bool draudio_on_sound_seek_callback(
void* pUserData,
size_t offsetInBytesFromStart)
1780 assert(pSound !=
NULL);
1783 bool result =
false;
1787 result = pSound->
onSeek(pSound, offsetInBytesFromStart);
1796 DRAUDIO_PRIVATE
static void draudio_inline_sound_stop_callback(
draudio_buffer* pBuffer,
unsigned int eventID,
void *pUserData)
1801 assert(pBuffer !=
NULL);
1803 assert(pUserData !=
NULL);
1810 DRAUDIO_PRIVATE
void draudio_prepend_sound(
draudio_sound* pSound)
1812 assert(pSound !=
NULL);
1829 DRAUDIO_PRIVATE
void draudio_remove_sound_nolock(
draudio_sound* pSound)
1831 assert(pSound !=
NULL);
1848 DRAUDIO_PRIVATE
bool draudio_is_inline_sound(
draudio_sound* pSound)
1850 assert(pSound !=
NULL);
1871 if (pWorld ==
NULL) {
1888 if (pWorld ==
NULL) {
1898 if (pSound ==
NULL) {
1925 streamingCallbacks.
read = draudio_on_sound_read_callback;
1926 streamingCallbacks.
seek = draudio_on_sound_seek_callback;
1952 draudio_prepend_sound(pSound);
1959 if (pSound ==
NULL) {
1975 draudio_remove_sound_nolock(pSound);
1980 if (draudio_is_inline_sound(pSound)) {
2005 if (pWorld ==
NULL) {
2017 if (pSound ==
NULL) {
2030 if (pSound ==
NULL) {
2044 if (pSound !=
NULL) {
2055 if (pSound !=
NULL) {
2062 if (pSound !=
NULL) {
2069 if (pSound ==
NULL) {
2078 if (pSound ==
NULL) {
2093 if (pWorld ==
NULL) {
2113 if (pWorld ==
NULL) {
2134 if (pWorld ==
NULL) {
2156 if (pWorld ==
NULL) {
2174 if (pWorld ==
NULL) {
2193 if (pSound !=
NULL) {
2200 if (pSound !=
NULL) {
2207 if (pSound !=
NULL) {
2215 if (pSound !=
NULL) {
2223 if (pSound !=
NULL) {
2230 if (pSound ==
NULL) {
2265 #ifdef DRAUDIO_BUILD_DSOUND
2266 #include <windows.h>
2273 GUID DRAUDIO_GUID_NULL = {0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
2278 #define DRAUDIO_MESSAGE_ID_UNKNOWN 0
2279 #define DRAUDIO_MESSAGE_ID_EVENT 1
2280 #define DRAUDIO_MESSAGE_ID_DELETE_BUFFER 2
2281 #define DRAUDIO_MESSAGE_ID_DELETE_DEVICE 3
2282 #define DRAUDIO_MESSAGE_ID_TERMINATE_THREAD 4
2303 unsigned int eventID;
2314 LPDIRECTSOUNDBUFFER8 pDSBuffer;
2317 LPDIRECTSOUND3DBUFFER pDSBuffer3D;
2320 LPDIRECTSOUNDNOTIFY pDSNotify;
2331 LPDIRECTSOUNDBUFFER pDSPrimaryBuffer;
2334 LPDIRECTSOUND3DLISTENER pDSListener;
2343 } draudio_message_dsound;
2356 unsigned int messageCount;
2359 unsigned int iFirstMessage;
2365 HANDLE hMessageSemaphore;
2368 HANDLE hMessageHandlingThread;
2373 } draudio_message_queue_dsound;
2377 DWORD WINAPI MessageHandlingThread_DSound(draudio_message_queue_dsound* pQueue);
2380 void draudio_post_message_dsound(draudio_message_queue_dsound* pQueue, draudio_message_dsound msg);
2385 bool draudio_init_message_queue_dsound(draudio_message_queue_dsound* pQueue)
2387 if (pQueue ==
NULL) {
2391 pQueue->messageCount = 0;
2392 pQueue->iFirstMessage = 0;
2395 if (pQueue->queueLock ==
NULL) {
2400 if (pQueue->hMessageSemaphore ==
NULL)
2406 pQueue->hMessageHandlingThread = CreateThread(
NULL, 0, (LPTHREAD_START_ROUTINE)MessageHandlingThread_DSound, pQueue, 0,
NULL);
2407 if (pQueue->hMessageHandlingThread ==
NULL)
2409 CloseHandle(pQueue->hMessageSemaphore);
2414 pQueue->isDeleted =
false;
2420 void draudio_uninit_message_queue_dsound(draudio_message_queue_dsound* pQueue)
2424 draudio_message_dsound msg;
2425 msg.id = DRAUDIO_MESSAGE_ID_TERMINATE_THREAD;
2426 draudio_post_message_dsound(pQueue, msg);
2430 WaitForSingleObject(pQueue->hMessageHandlingThread, INFINITE);
2433 CloseHandle(pQueue->hMessageHandlingThread);
2434 pQueue->hMessageHandlingThread =
NULL;
2436 CloseHandle(pQueue->hMessageSemaphore);
2437 pQueue->hMessageSemaphore =
NULL;
2440 pQueue->isDeleted =
true;
2443 pQueue->messageCount = 0;
2444 pQueue->iFirstMessage = 0;
2449 pQueue->queueLock =
NULL;
2453 void draudio_post_message_dsound(draudio_message_queue_dsound* pQueue, draudio_message_dsound msg)
2455 assert(pQueue !=
NULL);
2457 if (pQueue->isDeleted) {
2466 pQueue->messageCount += 1;
2468 ReleaseSemaphore(pQueue->hMessageSemaphore, 1,
NULL);
2479 bool draudio_next_message_dsound(draudio_message_queue_dsound* pQueue, draudio_message_dsound* pMsgOut)
2481 if (WaitForSingleObject(pQueue->hMessageSemaphore, INFINITE) == WAIT_OBJECT_0)
2483 draudio_message_dsound msg;
2484 msg.id = DRAUDIO_MESSAGE_ID_UNKNOWN;
2488 assert(pQueue->messageCount > 0);
2490 msg = pQueue->messages[pQueue->iFirstMessage];
2493 pQueue->messageCount -= 1;
2498 if (pMsgOut !=
NULL) {
2502 return msg.id != DRAUDIO_MESSAGE_ID_TERMINATE_THREAD;
2509 DWORD WINAPI MessageHandlingThread_DSound(draudio_message_queue_dsound* pQueue)
2511 assert(pQueue !=
NULL);
2513 draudio_message_dsound msg;
2514 while (draudio_next_message_dsound(pQueue, &msg))
2516 assert(msg.id != DRAUDIO_MESSAGE_ID_TERMINATE_THREAD);
2520 case DRAUDIO_MESSAGE_ID_EVENT:
2522 assert(msg.data.callback_event.callback !=
NULL);
2524 msg.data.callback_event.callback(msg.pBuffer, msg.data.callback_event.eventID, msg.data.callback_event.pUserData);
2528 case DRAUDIO_MESSAGE_ID_DELETE_BUFFER:
2530 if (msg.data.delete_buffer.pDSNotify !=
NULL) {
2531 IDirectSoundNotify_Release(msg.data.delete_buffer.pDSNotify);
2534 if (msg.data.delete_buffer.pDSBuffer3D !=
NULL) {
2535 IDirectSound3DBuffer_Release(msg.data.delete_buffer.pDSBuffer3D);
2538 if (msg.data.delete_buffer.pDSBuffer !=
NULL) {
2539 IDirectSoundBuffer8_Release(msg.data.delete_buffer.pDSBuffer);
2546 case DRAUDIO_MESSAGE_ID_DELETE_DEVICE:
2548 if (msg.data.delete_device.pDSListener !=
NULL) {
2549 IDirectSound3DListener_Release(msg.data.delete_device.pDSListener);
2552 if (msg.data.delete_device.pDSPrimaryBuffer !=
NULL) {
2553 IDirectSoundBuffer_Release(msg.data.delete_device.pDSPrimaryBuffer);
2556 if (msg.data.delete_device.pDS !=
NULL) {
2557 IDirectSound_Release(msg.data.delete_device.pDS);
2560 free(msg.data.delete_device.pDevice);
2580 void draudio_deactivate_buffer_events_dsound(
draudio_buffer* pBuffer);
2585 typedef struct draudio_event_manager_dsound draudio_event_manager_dsound;
2586 typedef struct draudio_event_dsound draudio_event_dsound;
2588 struct draudio_event_dsound
2591 draudio_event_manager_dsound* pEventManager;
2603 unsigned int eventID;
2612 draudio_event_dsound* pNextEvent;
2615 draudio_event_dsound* pPrevEvent;
2618 struct draudio_event_manager_dsound
2621 draudio_message_queue_dsound* pMessageQueue;
2628 HANDLE hTerminateEvent;
2631 HANDLE hRefreshEvent;
2640 HANDLE hEventCompletionLock;
2644 draudio_event_dsound* pFirstEvent;
2647 draudio_event_dsound* pLastEvent;
2652 void draudio_lock_events_dsound(draudio_event_manager_dsound* pEventManager)
2658 void draudio_unlock_events_dsound(draudio_event_manager_dsound* pEventManager)
2668 void draudio_remove_event_dsound_nolock(draudio_event_dsound* pEvent)
2670 assert(pEvent !=
NULL);
2672 draudio_event_manager_dsound* pEventManager = pEvent->pEventManager;
2673 assert(pEventManager !=
NULL);
2675 if (pEventManager->pFirstEvent == pEvent) {
2676 pEventManager->pFirstEvent = pEvent->pNextEvent;
2679 if (pEventManager->pLastEvent == pEvent) {
2680 pEventManager->pLastEvent = pEvent->pPrevEvent;
2684 if (pEvent->pPrevEvent !=
NULL) {
2685 pEvent->pPrevEvent->pNextEvent = pEvent->pNextEvent;
2688 if (pEvent->pNextEvent !=
NULL) {
2689 pEvent->pNextEvent->pPrevEvent = pEvent->pPrevEvent;
2692 pEvent->pNextEvent =
NULL;
2693 pEvent->pPrevEvent =
NULL;
2697 void draudio_remove_event_dsound(draudio_event_dsound* pEvent)
2699 assert(pEvent !=
NULL);
2701 draudio_event_manager_dsound* pEventManager = pEvent->pEventManager;
2702 draudio_lock_events_dsound(pEventManager);
2704 draudio_remove_event_dsound_nolock(pEvent);
2706 draudio_unlock_events_dsound(pEventManager);
2710 void draudio_append_event_dsound(draudio_event_dsound* pEvent)
2712 assert(pEvent !=
NULL);
2714 draudio_event_manager_dsound* pEventManager = pEvent->pEventManager;
2715 draudio_lock_events_dsound(pEventManager);
2717 draudio_remove_event_dsound_nolock(pEvent);
2719 assert(pEvent->pNextEvent ==
NULL);
2721 if (pEventManager->pLastEvent !=
NULL) {
2722 pEvent->pPrevEvent = pEventManager->pLastEvent;
2723 pEvent->pPrevEvent->pNextEvent = pEvent;
2726 if (pEventManager->pFirstEvent ==
NULL) {
2727 pEventManager->pFirstEvent = pEvent;
2730 pEventManager->pLastEvent = pEvent;
2732 draudio_unlock_events_dsound(pEventManager);
2735 void draudio_refresh_worker_thread_event_queue(draudio_event_manager_dsound* pEventManager)
2737 assert(pEventManager !=
NULL);
2745 SetEvent(pEventManager->hRefreshEvent);
2748 WaitForSingleObject(pEventManager->hEventCompletionLock, INFINITE);
2755 void draudio_close_win32_event_handle_dsound(draudio_event_dsound* pEvent)
2757 assert(pEvent !=
NULL);
2758 assert(pEvent->pEventManager !=
NULL);
2764 draudio_refresh_worker_thread_event_queue(pEvent->pEventManager);
2767 CloseHandle(pEvent->hEvent);
2768 pEvent->hEvent =
NULL;
2775 assert(pEvent !=
NULL);
2777 pEvent->callback = callback;
2778 pEvent->pUserData = pUserData;
2780 draudio_refresh_worker_thread_event_queue(pEvent->pEventManager);
2790 draudio_event_dsound* pEvent = (draudio_event_dsound*)malloc(
sizeof(draudio_event_dsound));
2793 pEvent->pEventManager = pEventManager;
2795 pEvent->callback =
NULL;
2796 pEvent->pBuffer = pBuffer;
2797 pEvent->eventID = eventID;
2798 pEvent->pUserData =
NULL;
2799 pEvent->markerOffset = 0;
2800 pEvent->pNextEvent =
NULL;
2801 pEvent->pPrevEvent =
NULL;
2804 draudio_append_event_dsound(pEvent);
2808 draudio_update_event_dsound(pEvent, callback, pUserData);
2818 void draudio_delete_event_dsound(draudio_event_dsound* pEvent)
2820 assert(pEvent !=
NULL);
2823 pEvent->pBuffer =
NULL;
2824 pEvent->callback =
NULL;
2825 pEvent->eventID = 0;
2826 pEvent->pUserData =
NULL;
2827 pEvent->markerOffset = 0;
2830 draudio_remove_event_dsound(pEvent);
2833 if (pEvent->hEvent !=
NULL) {
2834 draudio_close_win32_event_handle_dsound(pEvent);
2844 unsigned int draudio_gather_events_dsound(draudio_event_manager_dsound *pEventManager, HANDLE* pHandlesOut, draudio_event_dsound** ppEventsOut,
unsigned int outputBufferSize)
2846 assert(pEventManager !=
NULL);
2847 assert(pHandlesOut !=
NULL);
2848 assert(ppEventsOut !=
NULL);
2849 assert(outputBufferSize >= 2);
2852 draudio_lock_events_dsound(pEventManager);
2854 pHandlesOut[0] = pEventManager->hTerminateEvent;
2855 ppEventsOut[0] =
NULL;
2857 pHandlesOut[1] = pEventManager->hRefreshEvent;
2858 ppEventsOut[1] =
NULL;
2861 draudio_event_dsound* pEvent = pEventManager->pFirstEvent;
2862 while (i < outputBufferSize && pEvent !=
NULL)
2864 if (pEvent->hEvent !=
NULL)
2866 pHandlesOut[i] = pEvent->hEvent;
2867 ppEventsOut[i] = pEvent;
2872 pEvent = pEvent->pNextEvent;
2875 draudio_unlock_events_dsound(pEventManager);
2881 DWORD WINAPI DSound_EventWorkerThreadProc(draudio_event_manager_dsound *pEventManager)
2883 if (pEventManager !=
NULL)
2885 HANDLE hTerminateEvent = pEventManager->hTerminateEvent;
2886 HANDLE hRefreshEvent = pEventManager->hRefreshEvent;
2888 HANDLE eventHandles[1024];
2889 draudio_event_dsound* events[1024];
2890 unsigned int eventCount = draudio_gather_events_dsound(pEventManager, eventHandles, events, 1024);
2892 bool requestedRefresh =
false;
2895 if (requestedRefresh)
2897 eventCount = draudio_gather_events_dsound(pEventManager, eventHandles, events, 1024);
2900 SetEvent(pEventManager->hEventCompletionLock);
2901 requestedRefresh =
false;
2906 DWORD rc = WaitForMultipleObjects(eventCount, eventHandles,
FALSE, INFINITE);
2907 if (rc >= WAIT_OBJECT_0 && rc < eventCount)
2909 const unsigned int eventIndex = rc - WAIT_OBJECT_0;
2910 HANDLE hEvent = eventHandles[eventIndex];
2912 if (hEvent == hTerminateEvent)
2918 if (hEvent == hRefreshEvent)
2920 assert(hRefreshEvent == pEventManager->hRefreshEvent);
2923 requestedRefresh =
true;
2929 draudio_event_dsound* pEvent = events[eventIndex];
2930 if (pEvent->callback !=
NULL)
2932 assert(pEvent->hEvent == hEvent);
2938 if (!isStopEventButNotStopped)
2941 draudio_message_dsound msg;
2942 msg.id = DRAUDIO_MESSAGE_ID_EVENT;
2943 msg.pBuffer = pEvent->pBuffer;
2944 msg.data.callback_event.callback = pEvent->callback;
2945 msg.data.callback_event.eventID = pEvent->eventID;
2946 msg.data.callback_event.pUserData = pEvent->pUserData;
2947 draudio_post_message_dsound(pEventManager->pMessageQueue, msg);
2959 bool draudio_init_event_manager_dsound(draudio_event_manager_dsound* pEventManager, draudio_message_queue_dsound* pMessageQueue)
2961 assert(pEventManager !=
NULL);
2962 assert(pMessageQueue !=
NULL);
2964 pEventManager->pMessageQueue = pMessageQueue;
2967 if (hTerminateEvent ==
NULL) {
2972 if (hRefreshEvent ==
NULL)
2974 CloseHandle(hTerminateEvent);
2979 if (refreshMutex ==
NULL)
2981 CloseHandle(hTerminateEvent);
2982 CloseHandle(hRefreshEvent);
2987 if (mainLock ==
NULL)
2989 CloseHandle(hTerminateEvent);
2990 CloseHandle(hRefreshEvent);
2996 if (hEventCompletionLock ==
NULL)
2998 CloseHandle(hTerminateEvent);
2999 CloseHandle(hRefreshEvent);
3006 HANDLE hThread = CreateThread(
NULL, 0, (LPTHREAD_START_ROUTINE)DSound_EventWorkerThreadProc, pEventManager, 0,
NULL);
3007 if (hThread ==
NULL)
3009 CloseHandle(hTerminateEvent);
3010 CloseHandle(hRefreshEvent);
3013 CloseHandle(hEventCompletionLock);
3018 pEventManager->hTerminateEvent = hTerminateEvent;
3019 pEventManager->hRefreshEvent = hRefreshEvent;
3020 pEventManager->refreshMutex = refreshMutex;
3021 pEventManager->mainLock = mainLock;
3022 pEventManager->hEventCompletionLock = hEventCompletionLock;
3023 pEventManager->hThread = hThread;
3025 pEventManager->pFirstEvent =
NULL;
3026 pEventManager->pLastEvent =
NULL;
3037 void draudio_uninit_event_manager_dsound(draudio_event_manager_dsound* pEventManager)
3039 assert(pEventManager !=
NULL);
3043 while (pEventManager->pFirstEvent !=
NULL) {
3044 draudio_delete_event_dsound(pEventManager->pFirstEvent);
3050 SignalObjectAndWait(pEventManager->hTerminateEvent, pEventManager->hThread, INFINITE,
FALSE);
3053 CloseHandle(pEventManager->hThread);
3054 pEventManager->hThread =
NULL;
3058 CloseHandle(pEventManager->hTerminateEvent);
3059 pEventManager->hTerminateEvent =
NULL;
3061 CloseHandle(pEventManager->hRefreshEvent);
3062 pEventManager->hRefreshEvent =
NULL;
3065 pEventManager->refreshMutex =
NULL;
3068 pEventManager->mainLock =
NULL;
3071 CloseHandle(pEventManager->hEventCompletionLock);
3072 pEventManager->hEventCompletionLock =
NULL;
3078 static GUID _g_DSListenerGUID = {0x279AFA84, 0x4981, 0x11CE, {0xA5, 0x21, 0x00, 0x20, 0xAF, 0x0B, 0xE5, 0x60}};
3079 static GUID _g_DirectSoundBuffer8GUID = {0x6825a449, 0x7524, 0x4d82, {0x92, 0x0f, 0x50, 0xe3, 0x6a, 0xb3, 0xab, 0x1e}};
3080 static GUID _g_DirectSound3DBuffer8GUID = {0x279AFA86, 0x4981, 0x11CE, {0xA5, 0x21, 0x00, 0x20, 0xAF, 0x0B, 0xE5, 0x60}};
3081 static GUID _g_DirectSoundNotifyGUID = {0xb0210783, 0x89cd, 0x11d0, {0xaf, 0x08, 0x00, 0xa0, 0xc9, 0x25, 0xcd, 0x16}};
3082 static GUID _g_KSDATAFORMAT_SUBTYPE_PCM_GUID = {0x00000001, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
3083 static GUID _g_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT_GUID = {0x00000003, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
3086 static GUID g_DSListenerGUID = _g_DSListenerGUID;
3087 static GUID g_DirectSoundBuffer8GUID = _g_DirectSoundBuffer8GUID;
3088 static GUID g_DirectSound3DBuffer8GUID = _g_DirectSound3DBuffer8GUID;
3089 static GUID g_DirectSoundNotifyGUID = _g_DirectSoundNotifyGUID;
3090 static GUID g_KSDATAFORMAT_SUBTYPE_PCM_GUID = _g_KSDATAFORMAT_SUBTYPE_PCM_GUID;
3091 static GUID g_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT_GUID = _g_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT_GUID;
3093 static GUID* g_DSListenerGUID = &_g_DSListenerGUID;
3094 static GUID* g_DirectSoundBuffer8GUID = &_g_DirectSoundBuffer8GUID;
3095 static GUID* g_DirectSound3DBuffer8GUID = &_g_DirectSound3DBuffer8GUID;
3096 static GUID* g_DirectSoundNotifyGUID = &_g_DirectSoundNotifyGUID;
3097 static GUID* g_KSDATAFORMAT_SUBTYPE_PCM_GUID = &_g_KSDATAFORMAT_SUBTYPE_PCM_GUID;
3098 static GUID* g_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT_GUID = &_g_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT_GUID;
3102 typedef HRESULT (WINAPI * pDirectSoundCreate8Proc)(LPCGUID pcGuidDevice, LPDIRECTSOUND8 *ppDS8, LPUNKNOWN pUnkOuter);
3103 typedef HRESULT (WINAPI * pDirectSoundEnumerateAProc)(LPDSENUMCALLBACKA pDSEnumCallback, LPVOID pContext);
3104 typedef HRESULT (WINAPI * pDirectSoundCaptureCreate8Proc)(LPCGUID pcGuidDevice, LPDIRECTSOUNDCAPTURE8 *ppDSC8, LPUNKNOWN pUnkOuter);
3105 typedef HRESULT (WINAPI * pDirectSoundCaptureEnumerateAProc)(LPDSENUMCALLBACKA pDSEnumCallback, LPVOID pContext);
3116 char moduleName[256];
3118 } draudio_device_info_dsound;
3129 pDirectSoundCreate8Proc pDirectSoundCreate8;
3130 pDirectSoundEnumerateAProc pDirectSoundEnumerateA;
3131 pDirectSoundCaptureCreate8Proc pDirectSoundCaptureCreate8;
3132 pDirectSoundCaptureEnumerateAProc pDirectSoundCaptureEnumerateA;
3137 unsigned int outputDeviceCount;
3145 unsigned int inputDeviceCount;
3152 draudio_event_manager_dsound eventManager;
3156 draudio_message_queue_dsound messageQueue;
3158 } draudio_context_dsound;
3169 LPDIRECTSOUNDBUFFER pDSPrimaryBuffer;
3172 LPDIRECTSOUND3DLISTENER pDSListener;
3174 } draudio_device_dsound;
3182 LPDIRECTSOUNDBUFFER8 pDSBuffer;
3185 LPDIRECTSOUND3DBUFFER pDSBuffer3D;
3188 LPDIRECTSOUNDNOTIFY pDSNotify;
3195 unsigned int markerEventCount;
3201 draudio_event_dsound* pStopEvent;
3204 draudio_event_dsound* pPauseEvent;
3207 draudio_event_dsound* pPlayEvent;
3211 unsigned int extraDataSize;
3214 unsigned char pExtraData[1];
3216 } draudio_buffer_dsound;
3219 void draudio_activate_buffer_events_dsound(
draudio_buffer* pBuffer)
3221 draudio_buffer_dsound* pBufferDS = (draudio_buffer_dsound*)pBuffer;
3222 assert(pBufferDS !=
NULL);
3224 unsigned int dwPositionNotifies = 0;
3228 if (pBufferDS->pStopEvent !=
NULL)
3230 LPDSBPOSITIONNOTIFY pN = n + dwPositionNotifies;
3231 pN->dwOffset = DSBPN_OFFSETSTOP;
3232 pN->hEventNotify = pBufferDS->pStopEvent->hEvent;
3234 dwPositionNotifies += 1;
3238 for (
unsigned int iMarker = 0; iMarker < pBufferDS->markerEventCount; ++iMarker)
3240 LPDSBPOSITIONNOTIFY pN = n + dwPositionNotifies;
3241 pN->dwOffset = pBufferDS->pMarkerEvents[iMarker]->markerOffset;
3242 pN->hEventNotify = pBufferDS->pMarkerEvents[iMarker]->hEvent;
3244 dwPositionNotifies += 1;
3248 HRESULT hr = IDirectSoundNotify_SetNotificationPositions(pBufferDS->pDSNotify, dwPositionNotifies, n);
3251 printf(
"WARNING: FAILED TO CREATE DIRECTSOUND NOTIFIERS\n");
3258 void draudio_deactivate_buffer_events_dsound(
draudio_buffer* pBuffer)
3260 draudio_buffer_dsound* pBufferDS = (draudio_buffer_dsound*)pBuffer;
3261 assert(pBufferDS !=
NULL);
3264 HRESULT hr = IDirectSoundNotify_SetNotificationPositions(pBufferDS->pDSNotify, 0,
NULL);
3267 printf(
"WARNING: FAILED TO CLEAR DIRECTSOUND NOTIFIERS\n");
3277 draudio_context_dsound* pContextDS = (draudio_context_dsound*)pContext;
3278 assert(pContextDS !=
NULL);
3280 draudio_uninit_event_manager_dsound(&pContextDS->eventManager);
3283 draudio_uninit_message_queue_dsound(&pContextDS->messageQueue);
3285 FreeLibrary(pContextDS->hDSoundDLL);
3290 unsigned int draudio_get_output_device_count_dsound(
draudio_context* pContext)
3292 draudio_context_dsound* pContextDS = (draudio_context_dsound*)pContext;
3293 assert(pContextDS !=
NULL);
3295 return pContextDS->outputDeviceCount;
3300 draudio_context_dsound* pContextDS = (draudio_context_dsound*)pContext;
3301 assert(pContextDS !=
NULL);
3302 assert(pInfoOut !=
NULL);
3304 if (deviceIndex >= pContextDS->outputDeviceCount) {
3309 draudio_strcpy(pInfoOut->
description,
sizeof(pInfoOut->
description), pContextDS->outputDeviceInfo[deviceIndex].description);
3317 draudio_context_dsound* pContextDS = (draudio_context_dsound*)pContext;
3318 assert(pContextDS !=
NULL);
3320 if (deviceIndex >= pContextDS->outputDeviceCount) {
3329 if (deviceIndex == 0) {
3330 hr = pContextDS->pDirectSoundCreate8(
NULL, &pDS,
NULL);
3332 hr = pContextDS->pDirectSoundCreate8(&pContextDS->outputDeviceInfo[deviceIndex].guid, &pDS,
NULL);
3341 hr = IDirectSound_SetCooperativeLevel(pDS, GetForegroundWindow(), DSSCL_EXCLUSIVE);
3343 IDirectSound_Release(pDS);
3349 DSBUFFERDESC descDSPrimary;
3350 memset(&descDSPrimary, 0,
sizeof(DSBUFFERDESC));
3351 descDSPrimary.dwSize =
sizeof(DSBUFFERDESC);
3352 descDSPrimary.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRL3D;
3353 descDSPrimary.guid3DAlgorithm = DRAUDIO_GUID_NULL;
3355 LPDIRECTSOUNDBUFFER pDSPrimaryBuffer;
3356 hr = IDirectSound_CreateSoundBuffer(pDS, &descDSPrimary, &pDSPrimaryBuffer,
NULL);
3358 IDirectSound_Release(pDS);
3363 WAVEFORMATIEEEFLOATEX wf = {0};
3364 wf.Format.cbSize =
sizeof(wf);
3365 wf.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
3366 wf.Format.nChannels = 2;
3367 wf.Format.nSamplesPerSec = 48000;
3368 wf.Format.wBitsPerSample = 32;
3369 wf.Format.nBlockAlign = (wf.Format.nChannels * wf.Format.wBitsPerSample) / 8;
3370 wf.Format.nAvgBytesPerSec = wf.Format.nBlockAlign * wf.Format.nSamplesPerSec;
3371 wf.Samples.wValidBitsPerSample = wf.Format.wBitsPerSample;
3372 wf.dwChannelMask = 0;
3373 wf.SubFormat = _g_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT_GUID;
3374 hr = IDirectSoundBuffer_SetFormat(pDSPrimaryBuffer, (WAVEFORMATEX*)&wf);
3376 IDirectSoundBuffer_Release(pDSPrimaryBuffer);
3377 IDirectSound_Release(pDS);
3383 LPDIRECTSOUND3DLISTENER pDSListener =
NULL;
3384 hr = IDirectSound3DListener_QueryInterface(pDSPrimaryBuffer, g_DSListenerGUID, (LPVOID*)&pDSListener);
3386 IDirectSoundBuffer_Release(pDSPrimaryBuffer);
3387 IDirectSound_Release(pDS);
3392 draudio_device_dsound* pDeviceDS = (draudio_device_dsound*)malloc(
sizeof(draudio_device_dsound));
3393 if (pDeviceDS !=
NULL)
3395 pDeviceDS->base.pContext = pContext;
3396 pDeviceDS->pDS = pDS;
3397 pDeviceDS->pDSPrimaryBuffer = pDSPrimaryBuffer;
3398 pDeviceDS->pDSListener = pDSListener;
3404 IDirectSound3DListener_Release(pDSListener);
3405 IDirectSoundBuffer_Release(pDeviceDS->pDSPrimaryBuffer);
3406 IDirectSound_Release(pDS);
3411 void draudio_delete_output_device_dsound(
draudio_device* pDevice)
3413 draudio_device_dsound* pDeviceDS = (draudio_device_dsound*)pDevice;
3414 assert(pDeviceDS !=
NULL);
3416 draudio_context_dsound* pContextDS = (draudio_context_dsound*)pDevice->pContext;
3417 assert(pContextDS !=
NULL);
3421 draudio_message_dsound msg;
3422 msg.id = DRAUDIO_MESSAGE_ID_DELETE_DEVICE;
3424 msg.data.delete_device.pDSListener = pDeviceDS->pDSListener;
3425 msg.data.delete_device.pDSPrimaryBuffer = pDeviceDS->pDSPrimaryBuffer;
3426 msg.data.delete_device.pDS = pDeviceDS->pDS;
3427 msg.data.delete_device.pDevice = pDevice;
3428 draudio_post_message_dsound(&pContextDS->messageQueue, msg);
3431 IDirectSound3DListener_Release(pDeviceDS->pDSListener);
3432 IDirectSoundBuffer_Release(pDeviceDS->pDSPrimaryBuffer);
3433 IDirectSound_Release(pDeviceDS->pDS);
3441 draudio_device_dsound* pDeviceDS = (draudio_device_dsound*)pDevice;
3442 assert(pDeviceDS !=
NULL);
3443 assert(pBufferDesc !=
NULL);
3450 WAVEFORMATIEEEFLOATEX wf = {0};
3451 wf.Format.cbSize =
sizeof(wf);
3452 wf.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
3453 wf.Format.nChannels = (WORD)pBufferDesc->
channels;
3454 wf.Format.nSamplesPerSec = pBufferDesc->
sampleRate;
3455 wf.Format.wBitsPerSample = (WORD)pBufferDesc->
bitsPerSample;
3456 wf.Format.nBlockAlign = (wf.Format.nChannels * wf.Format.wBitsPerSample) / 8;
3457 wf.Format.nAvgBytesPerSec = wf.Format.nBlockAlign * wf.Format.nSamplesPerSec;
3458 wf.Samples.wValidBitsPerSample = wf.Format.wBitsPerSample;
3459 wf.dwChannelMask = 0;
3462 wf.SubFormat = _g_KSDATAFORMAT_SUBTYPE_PCM_GUID;
3464 wf.SubFormat = _g_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT_GUID;
3474 DSBUFFERDESC descDS;
3475 memset(&descDS, 0,
sizeof(DSBUFFERDESC));
3476 descDS.dwSize =
sizeof(DSBUFFERDESC);
3477 descDS.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_GLOBALFOCUS;
3478 descDS.dwBufferBytes = (DWORD)pBufferDesc->
sizeInBytes;
3479 descDS.lpwfxFormat = (WAVEFORMATEX*)&wf;
3481 LPDIRECTSOUNDBUFFER8 pDSBuffer =
NULL;
3482 LPDIRECTSOUND3DBUFFER pDSBuffer3D =
NULL;
3486 descDS.dwFlags |= DSBCAPS_CTRLPAN;
3488 LPDIRECTSOUNDBUFFER pDSBufferTemp;
3489 HRESULT hr = IDirectSound_CreateSoundBuffer(pDeviceDS->pDS, &descDS, &pDSBufferTemp,
NULL);
3494 hr = IDirectSoundBuffer_QueryInterface(pDSBufferTemp, g_DirectSoundBuffer8GUID, (
void**)&pDSBuffer);
3496 IDirectSoundBuffer_Release(pDSBufferTemp);
3499 IDirectSoundBuffer_Release(pDSBufferTemp);
3504 descDS.dwFlags |= DSBCAPS_CTRL3D;
3505 descDS.guid3DAlgorithm = DS3DALG_DEFAULT;
3507 LPDIRECTSOUNDBUFFER pDSBufferTemp;
3508 HRESULT hr = IDirectSound_CreateSoundBuffer(pDeviceDS->pDS, &descDS, &pDSBufferTemp,
NULL);
3513 hr = IDirectSoundBuffer_QueryInterface(pDSBufferTemp, g_DirectSoundBuffer8GUID, (
void**)&pDSBuffer);
3515 IDirectSoundBuffer_Release(pDSBufferTemp);
3518 IDirectSoundBuffer_Release(pDSBufferTemp);
3521 hr = IDirectSoundBuffer_QueryInterface(pDSBuffer, g_DirectSound3DBuffer8GUID, (
void**)&pDSBuffer3D);
3526 IDirectSound3DBuffer_SetPosition(pDSBuffer3D, 0, 0, 0, DS3D_IMMEDIATE);
3529 IDirectSound3DBuffer_SetMode(pDSBuffer3D, DS3DMODE_HEADRELATIVE, DS3D_IMMEDIATE);
3536 LPDIRECTSOUNDNOTIFY pDSNotify;
3537 HRESULT hr = IDirectSoundBuffer8_QueryInterface(pDSBuffer, g_DirectSoundNotifyGUID, (
void**)&pDSNotify);
3539 IDirectSound3DBuffer_Release(pDSBuffer3D);
3540 IDirectSoundBuffer8_Release(pDSBuffer);
3545 draudio_buffer_dsound* pBufferDS = (draudio_buffer_dsound*)malloc(
sizeof(draudio_buffer_dsound) -
sizeof(pBufferDS->pExtraData) + extraDataSize);
3546 if (pBufferDS ==
NULL) {
3547 IDirectSound3DBuffer_Release(pDSBuffer3D);
3548 IDirectSoundBuffer8_Release(pDSBuffer);
3552 pBufferDS->base.pDevice = pDevice;
3553 pBufferDS->pDSBuffer = pDSBuffer;
3554 pBufferDS->pDSBuffer3D = pDSBuffer3D;
3555 pBufferDS->pDSNotify = pDSNotify;
3558 pBufferDS->markerEventCount = 0;
3559 memset(pBufferDS->pMarkerEvents, 0,
sizeof(pBufferDS->pMarkerEvents));
3560 pBufferDS->pStopEvent =
NULL;
3561 pBufferDS->pPauseEvent =
NULL;
3562 pBufferDS->pPlayEvent =
NULL;
3576 draudio_buffer_dsound* pBufferDS = (draudio_buffer_dsound*)pBuffer;
3577 assert(pBufferDS !=
NULL);
3578 assert(pBuffer->pDevice !=
NULL);
3580 draudio_context_dsound* pContextDS = (draudio_context_dsound*)pBuffer->pDevice->pContext;
3581 assert(pContextDS !=
NULL);
3585 draudio_deactivate_buffer_events_dsound(pBuffer);
3588 draudio_message_dsound msg;
3589 msg.id = DRAUDIO_MESSAGE_ID_DELETE_BUFFER;
3590 msg.pBuffer = pBuffer;
3591 msg.data.delete_buffer.pDSNotify = pBufferDS->pDSNotify;
3592 msg.data.delete_buffer.pDSBuffer3D = pBufferDS->pDSBuffer3D;
3593 msg.data.delete_buffer.pDSBuffer = pBufferDS->pDSBuffer;
3594 draudio_post_message_dsound(&pContextDS->messageQueue, msg);
3597 if (pBufferDS->pDSNotify !=
NULL) {
3598 IDirectSoundNotify_Release(pBufferDS->pDSNotify);
3601 if (pBufferDS->pDSBuffer3D !=
NULL) {
3602 IDirectSound3DBuffer_Release(pBufferDS->pDSBuffer3D);
3605 if (pBufferDS->pDSBuffer !=
NULL) {
3606 IDirectSoundBuffer8_Release(pBufferDS->pDSBuffer);
3614 unsigned int draudio_get_buffer_extra_data_size_dsound(
draudio_buffer* pBuffer)
3616 draudio_buffer_dsound* pBufferDS = (draudio_buffer_dsound*)pBuffer;
3617 assert(pBufferDS !=
NULL);
3619 return pBufferDS->extraDataSize;
3622 void* draudio_get_buffer_extra_data_dsound(
draudio_buffer* pBuffer)
3624 draudio_buffer_dsound* pBufferDS = (draudio_buffer_dsound*)pBuffer;
3625 assert(pBufferDS !=
NULL);
3627 return pBufferDS->pExtraData;
3631 void draudio_set_buffer_data_dsound(
draudio_buffer* pBuffer,
size_t offset,
const void* pData,
size_t dataSizeInBytes)
3633 draudio_buffer_dsound* pBufferDS = (draudio_buffer_dsound*)pBuffer;
3634 assert(pBufferDS !=
NULL);
3635 assert(pData !=
NULL);
3639 HRESULT hr = IDirectSoundBuffer8_Lock(pBufferDS->pDSBuffer, (DWORD)offset, (DWORD)dataSizeInBytes, &lpvWrite, &dwLength,
NULL,
NULL, 0);
3644 assert(dataSizeInBytes <= dwLength);
3645 memcpy(lpvWrite, pData, dataSizeInBytes);
3647 hr = IDirectSoundBuffer8_Unlock(pBufferDS->pDSBuffer, lpvWrite, dwLength,
NULL, 0);
3656 draudio_buffer_dsound* pBufferDS = (draudio_buffer_dsound*)pBuffer;
3657 assert(pBufferDS !=
NULL);
3659 bool postEvent =
true;
3667 draudio_activate_buffer_events_dsound(pBuffer);
3673 dwFlags |= DSBPLAY_LOOPING;
3677 IDirectSoundBuffer8_Play(pBufferDS->pDSBuffer, 0, 0, dwFlags);
3680 if (pBufferDS->pPlayEvent !=
NULL && postEvent) {
3681 SetEvent(pBufferDS->pPlayEvent->hEvent);
3687 draudio_buffer_dsound* pBufferDS = (draudio_buffer_dsound*)pBuffer;
3688 assert(pBufferDS !=
NULL);
3693 IDirectSoundBuffer8_Stop(pBufferDS->pDSBuffer);
3696 if (pBufferDS->pPlayEvent !=
NULL) {
3697 SetEvent(pBufferDS->pPauseEvent->hEvent);
3704 draudio_buffer_dsound* pBufferDS = (draudio_buffer_dsound*)pBuffer;
3705 assert(pBufferDS !=
NULL);
3710 IDirectSoundBuffer8_Stop(pBufferDS->pDSBuffer);
3711 IDirectSoundBuffer8_SetCurrentPosition(pBufferDS->pDSBuffer, 0);
3716 IDirectSoundBuffer8_SetCurrentPosition(pBufferDS->pDSBuffer, 0);
3718 if (pBufferDS->pStopEvent !=
NULL) {
3719 SetEvent(pBufferDS->pStopEvent->hEvent);
3726 draudio_buffer_dsound* pBufferDS = (draudio_buffer_dsound*)pBuffer;
3727 assert(pBufferDS !=
NULL);
3729 return pBufferDS->playbackState;
3733 void draudio_set_playback_position_dsound(
draudio_buffer* pBuffer,
unsigned int position)
3735 draudio_buffer_dsound* pBufferDS = (draudio_buffer_dsound*)pBuffer;
3736 assert(pBufferDS !=
NULL);
3738 IDirectSoundBuffer8_SetCurrentPosition(pBufferDS->pDSBuffer, position);
3741 unsigned int draudio_get_playback_position_dsound(
draudio_buffer* pBuffer)
3743 draudio_buffer_dsound* pBufferDS = (draudio_buffer_dsound*)pBuffer;
3744 assert(pBufferDS !=
NULL);
3747 HRESULT hr = IDirectSoundBuffer8_GetCurrentPosition(pBufferDS->pDSBuffer, &position,
NULL);
3758 draudio_buffer_dsound* pBufferDS = (draudio_buffer_dsound*)pBuffer;
3759 assert(pBufferDS !=
NULL);
3763 panDB = DSBPAN_CENTER;
3766 panDB = DSBPAN_RIGHT;
3767 }
else if (pan < -1) {
3768 panDB = DSBPAN_LEFT;
3771 panDB = (LONG)((20*log10f(1 + pan)) * 100);
3773 panDB = -(LONG)((20*log10f(1 - pan)) * 100);
3778 IDirectSoundBuffer_SetPan(pBufferDS->pDSBuffer, panDB);
3783 draudio_buffer_dsound* pBufferDS = (draudio_buffer_dsound*)pBuffer;
3784 assert(pBufferDS !=
NULL);
3787 HRESULT hr = IDirectSoundBuffer_GetPan(pBufferDS->pDSBuffer, &panDB);
3794 return -(1 - (float)(1.0f / powf(10.0f, -panDB / (20.0f*100.0f))));
3798 return (1 - (
float)(1.0f / powf(10.0f, panDB / (20.0f*100.0f))));
3805 void draudio_set_volume_dsound(
draudio_buffer* pBuffer,
float volume)
3807 draudio_buffer_dsound* pBufferDS = (draudio_buffer_dsound*)pBuffer;
3808 assert(pBufferDS !=
NULL);
3813 volumeDB = (LONG)((20*log10f(volume)) * 100);
3815 volumeDB = DSBVOLUME_MAX;
3818 volumeDB = DSBVOLUME_MIN;
3821 IDirectSoundBuffer_SetVolume(pBufferDS->pDSBuffer, volumeDB);
3826 draudio_buffer_dsound* pBufferDS = (draudio_buffer_dsound*)pBuffer;
3827 assert(pBufferDS !=
NULL);
3830 HRESULT hr = IDirectSoundBuffer_GetVolume(pBufferDS->pDSBuffer, &volumeDB);
3835 return (
float)(1.0f / powf(10.0f, -volumeDB / (20.0f*100.0f)));
3841 draudio_buffer_dsound* pBufferDS = (draudio_buffer_dsound*)pBuffer;
3842 assert(pBufferDS !=
NULL);
3844 for (
unsigned int iMarker = 0; iMarker < pBufferDS->markerEventCount; ++iMarker)
3846 if (pBufferDS->pMarkerEvents[iMarker] !=
NULL) {
3847 draudio_delete_event_dsound(pBufferDS->pMarkerEvents[iMarker]);
3848 pBufferDS->pMarkerEvents[iMarker] =
NULL;
3852 pBufferDS->markerEventCount = 0;
3857 draudio_buffer_dsound* pBufferDS = (draudio_buffer_dsound*)pBuffer;
3858 assert(pBufferDS !=
NULL);
3866 draudio_context_dsound* pContextDS = (draudio_context_dsound*)pBuffer->pDevice->pContext;
3867 assert(pContextDS !=
NULL);
3869 draudio_event_dsound* pEvent = draudio_create_event_dsound(&pContextDS->eventManager, callback, pBuffer, eventID, pUserData);
3870 if (pEvent ==
NULL) {
3875 pEvent->markerOffset = (DWORD)offsetInBytes;
3877 pBufferDS->pMarkerEvents[pBufferDS->markerEventCount] = pEvent;
3878 pBufferDS->markerEventCount += 1;
3885 draudio_buffer_dsound* pBufferDS = (draudio_buffer_dsound*)pBuffer;
3886 assert(pBufferDS !=
NULL);
3888 if (callback ==
NULL)
3890 if (pBufferDS->pStopEvent !=
NULL) {
3891 draudio_delete_event_dsound(pBufferDS->pStopEvent);
3892 pBufferDS->pStopEvent =
NULL;
3899 draudio_context_dsound* pContextDS = (draudio_context_dsound*)pBuffer->pDevice->pContext;
3902 if (pBufferDS->pStopEvent !=
NULL) {
3903 draudio_update_event_dsound(pBufferDS->pStopEvent, callback, pUserData);
3905 pBufferDS->pStopEvent = draudio_create_event_dsound(&pContextDS->eventManager, callback, pBuffer,
DRAUDIO_EVENT_ID_STOP, pUserData);
3908 return pBufferDS->pStopEvent !=
NULL;
3914 draudio_buffer_dsound* pBufferDS = (draudio_buffer_dsound*)pBuffer;
3915 assert(pBufferDS !=
NULL);
3917 if (callback ==
NULL)
3919 if (pBufferDS->pPauseEvent !=
NULL) {
3920 draudio_delete_event_dsound(pBufferDS->pPauseEvent);
3921 pBufferDS->pPauseEvent =
NULL;
3928 draudio_context_dsound* pContextDS = (draudio_context_dsound*)pBuffer->pDevice->pContext;
3931 if (pBufferDS->pPauseEvent !=
NULL) {
3932 draudio_update_event_dsound(pBufferDS->pPauseEvent, callback, pUserData);
3934 pBufferDS->pPauseEvent = draudio_create_event_dsound(&pContextDS->eventManager, callback, pBuffer,
DRAUDIO_EVENT_ID_PAUSE, pUserData);
3937 return pBufferDS->pPauseEvent !=
NULL;
3943 draudio_buffer_dsound* pBufferDS = (draudio_buffer_dsound*)pBuffer;
3944 assert(pBufferDS !=
NULL);
3946 if (callback ==
NULL)
3948 if (pBufferDS->pPlayEvent !=
NULL) {
3949 draudio_delete_event_dsound(pBufferDS->pPlayEvent);
3950 pBufferDS->pPlayEvent =
NULL;
3957 draudio_context_dsound* pContextDS = (draudio_context_dsound*)pBuffer->pDevice->pContext;
3960 if (pBufferDS->pPlayEvent !=
NULL) {
3961 draudio_update_event_dsound(pBufferDS->pPlayEvent, callback, pUserData);
3963 pBufferDS->pPlayEvent = draudio_create_event_dsound(&pContextDS->eventManager, callback, pBuffer,
DRAUDIO_EVENT_ID_PLAY, pUserData);
3966 return pBufferDS->pPlayEvent !=
NULL;
3972 void draudio_set_position_dsound(
draudio_buffer* pBuffer,
float x,
float y,
float z)
3974 draudio_buffer_dsound* pBufferDS = (draudio_buffer_dsound*)pBuffer;
3975 assert(pBufferDS !=
NULL);
3977 if (pBufferDS->pDSBuffer3D !=
NULL) {
3978 IDirectSound3DBuffer_SetPosition(pBufferDS->pDSBuffer3D, x, y, z, DS3D_IMMEDIATE);
3982 void draudio_get_position_dsound(
draudio_buffer* pBuffer,
float* pPosOut)
3984 draudio_buffer_dsound* pBufferDS = (draudio_buffer_dsound*)pBuffer;
3985 assert(pBufferDS !=
NULL);
3986 assert(pPosOut !=
NULL);
3988 if (pBufferDS->pDSBuffer3D !=
NULL)
3991 IDirectSound3DBuffer_GetPosition(pBufferDS->pDSBuffer3D, &pos);
4006 void draudio_set_listener_position_dsound(
draudio_device* pDevice,
float x,
float y,
float z)
4008 draudio_device_dsound* pDeviceDS = (draudio_device_dsound*)pDevice;
4009 assert(pDeviceDS !=
NULL);
4011 IDirectSound3DListener_SetPosition(pDeviceDS->pDSListener, x, y, z, DS3D_IMMEDIATE);
4014 void draudio_get_listener_position_dsound(
draudio_device* pDevice,
float* pPosOut)
4016 draudio_device_dsound* pDeviceDS = (draudio_device_dsound*)pDevice;
4017 assert(pDeviceDS !=
NULL);
4018 assert(pPosOut !=
NULL);
4021 IDirectSound3DListener_GetPosition(pDeviceDS->pDSListener, &pos);
4029 void draudio_set_listener_orientation_dsound(
draudio_device* pDevice,
float forwardX,
float forwardY,
float forwardZ,
float upX,
float upY,
float upZ)
4031 draudio_device_dsound* pDeviceDS = (draudio_device_dsound*)pDevice;
4032 assert(pDeviceDS !=
NULL);
4034 IDirectSound3DListener_SetOrientation(pDeviceDS->pDSListener, forwardX, forwardY, forwardZ, upX, upY, upZ, DS3D_IMMEDIATE);
4037 void draudio_get_listener_orientation_dsound(
draudio_device* pDevice,
float* pForwardOut,
float* pUpOut)
4039 draudio_device_dsound* pDeviceDS = (draudio_device_dsound*)pDevice;
4040 assert(pDeviceDS !=
NULL);
4041 assert(pForwardOut !=
NULL);
4042 assert(pUpOut !=
NULL);
4046 IDirectSound3DListener_GetOrientation(pDeviceDS->pDSListener, &forward, &up);
4048 pForwardOut[0] = forward.x;
4049 pForwardOut[1] = forward.y;
4050 pForwardOut[2] = forward.z;
4059 draudio_buffer_dsound* pBufferDS = (draudio_buffer_dsound*)pBuffer;
4060 assert(pBufferDS !=
NULL);
4062 if (pBufferDS->pDSBuffer3D ==
NULL) {
4067 DWORD dwMode = DS3DMODE_NORMAL;
4069 dwMode = DS3DMODE_HEADRELATIVE;
4071 dwMode = DS3DMODE_DISABLE;
4074 IDirectSound3DBuffer_SetMode(pBufferDS->pDSBuffer3D, dwMode, DS3D_IMMEDIATE);
4079 draudio_buffer_dsound* pBufferDS = (draudio_buffer_dsound*)pBuffer;
4080 assert(pBufferDS !=
NULL);
4082 if (pBufferDS->pDSBuffer3D ==
NULL) {
4088 if (FAILED(IDirectSound3DBuffer_GetMode(pBufferDS->pDSBuffer3D, &dwMode))) {
4093 if (dwMode == DS3DMODE_NORMAL) {
4097 if (dwMode == DS3DMODE_HEADRELATIVE) {
4105 static BOOL
CALLBACK DSEnumCallback_OutputDevices(LPGUID lpGuid, LPCSTR lpcstrDescription, LPCSTR lpcstrModule, LPVOID lpContext)
4112 draudio_context_dsound* pContextDS = (draudio_context_dsound*)lpContext;
4113 assert(pContextDS !=
NULL);
4117 if (lpGuid !=
NULL) {
4118 memcpy(&pContextDS->outputDeviceInfo[pContextDS->outputDeviceCount].guid, lpGuid,
sizeof(GUID));
4120 memset(&pContextDS->outputDeviceInfo[pContextDS->outputDeviceCount].guid, 0,
sizeof(GUID));
4123 draudio_strcpy(pContextDS->outputDeviceInfo[pContextDS->outputDeviceCount].description, 256, lpcstrDescription);
4124 draudio_strcpy(pContextDS->outputDeviceInfo[pContextDS->outputDeviceCount].moduleName, 256, lpcstrModule);
4126 pContextDS->outputDeviceCount += 1;
4136 static BOOL
CALLBACK DSEnumCallback_InputDevices(LPGUID lpGuid, LPCSTR lpcstrDescription, LPCSTR lpcstrModule, LPVOID lpContext)
4143 draudio_context_dsound* pContextDS = (draudio_context_dsound*)lpContext;
4144 assert(pContextDS !=
NULL);
4148 if (lpGuid !=
NULL) {
4149 memcpy(&pContextDS->inputDeviceInfo[pContextDS->inputDeviceCount].guid, lpGuid,
sizeof(GUID));
4151 memset(&pContextDS->inputDeviceInfo[pContextDS->inputDeviceCount].guid, 0,
sizeof(GUID));
4154 draudio_strcpy(pContextDS->inputDeviceInfo[pContextDS->inputDeviceCount].description, 256, lpcstrDescription);
4155 draudio_strcpy(pContextDS->inputDeviceInfo[pContextDS->inputDeviceCount].moduleName, 256, lpcstrModule);
4157 pContextDS->inputDeviceCount += 1;
4170 HMODULE hDSoundDLL = LoadLibraryW(
L"dsound.dll");
4171 if (hDSoundDLL ==
NULL) {
4177 pDirectSoundCreate8Proc pDirectSoundCreate8 = (pDirectSoundCreate8Proc)GetProcAddress(hDSoundDLL,
"DirectSoundCreate8");
4178 if (pDirectSoundCreate8 ==
NULL){
4179 FreeLibrary(hDSoundDLL);
4183 pDirectSoundEnumerateAProc pDirectSoundEnumerateA = (pDirectSoundEnumerateAProc)GetProcAddress(hDSoundDLL,
"DirectSoundEnumerateA");
4184 if (pDirectSoundEnumerateA ==
NULL){
4185 FreeLibrary(hDSoundDLL);
4189 pDirectSoundCaptureCreate8Proc pDirectSoundCaptureCreate8 = (pDirectSoundCaptureCreate8Proc)GetProcAddress(hDSoundDLL,
"DirectSoundCaptureCreate8");
4190 if (pDirectSoundCaptureCreate8 ==
NULL) {
4191 FreeLibrary(hDSoundDLL);
4195 pDirectSoundCaptureEnumerateAProc pDirectSoundCaptureEnumerateA = (pDirectSoundCaptureEnumerateAProc)GetProcAddress(hDSoundDLL,
"DirectSoundCaptureEnumerateA");
4196 if (pDirectSoundCaptureEnumerateA ==
NULL ){
4197 FreeLibrary(hDSoundDLL);
4204 draudio_context_dsound* pContext = (draudio_context_dsound*)malloc(
sizeof(draudio_context_dsound));
4205 if (pContext !=
NULL)
4207 pContext->base.delete_context = draudio_delete_context_dsound;
4208 pContext->base.create_output_device = draudio_create_output_device_dsound;
4209 pContext->base.delete_output_device = draudio_delete_output_device_dsound;
4210 pContext->base.get_output_device_count = draudio_get_output_device_count_dsound;
4211 pContext->base.get_output_device_info = draudio_get_output_device_info_dsound;
4212 pContext->base.create_buffer = draudio_create_buffer_dsound;
4213 pContext->base.delete_buffer = draudio_delete_buffer_dsound;
4214 pContext->base.get_buffer_extra_data_size = draudio_get_buffer_extra_data_size_dsound;
4215 pContext->base.get_buffer_extra_data = draudio_get_buffer_extra_data_dsound;
4216 pContext->base.set_buffer_data = draudio_set_buffer_data_dsound;
4217 pContext->base.play = draudio_play_dsound;
4218 pContext->base.pause = draudio_pause_dsound;
4219 pContext->base.stop = draudio_stop_dsound;
4220 pContext->base.get_playback_state = draudio_get_playback_state_dsound;
4221 pContext->base.set_playback_position = draudio_set_playback_position_dsound;
4222 pContext->base.get_playback_position = draudio_get_playback_position_dsound;
4223 pContext->base.set_pan = draudio_set_pan_dsound;
4224 pContext->base.get_pan = draudio_get_pan_dsound;
4225 pContext->base.set_volume = draudio_set_volume_dsound;
4226 pContext->base.get_volume = draudio_get_volume_dsound;
4227 pContext->base.remove_markers = draudio_remove_markers_dsound;
4228 pContext->base.register_marker_callback = draudio_register_marker_callback_dsound;
4229 pContext->base.register_stop_callback = draudio_register_stop_callback_dsound;
4230 pContext->base.register_pause_callback = draudio_register_pause_callback_dsound;
4231 pContext->base.register_play_callback = draudio_register_play_callback_dsound;
4232 pContext->base.set_position = draudio_set_position_dsound;
4233 pContext->base.get_position = draudio_get_position_dsound;
4234 pContext->base.set_listener_position = draudio_set_listener_position_dsound;
4235 pContext->base.get_listener_position = draudio_get_listener_position_dsound;
4236 pContext->base.set_listener_orientation = draudio_set_listener_orientation_dsound;
4237 pContext->base.get_listener_orientation = draudio_get_listener_orientation_dsound;
4238 pContext->base.set_3d_mode = draudio_set_3d_mode_dsound;
4239 pContext->base.get_3d_mode = draudio_get_3d_mode_dsound;
4241 pContext->hDSoundDLL = hDSoundDLL;
4242 pContext->pDirectSoundCreate8 = pDirectSoundCreate8;
4243 pContext->pDirectSoundEnumerateA = pDirectSoundEnumerateA;
4244 pContext->pDirectSoundCaptureCreate8 = pDirectSoundCaptureCreate8;
4245 pContext->pDirectSoundCaptureEnumerateA = pDirectSoundCaptureEnumerateA;
4248 pContext->outputDeviceCount = 0;
4249 pContext->pDirectSoundEnumerateA(DSEnumCallback_OutputDevices, pContext);
4252 pContext->inputDeviceCount = 0;
4253 pContext->pDirectSoundCaptureEnumerateA(DSEnumCallback_InputDevices, pContext);
4256 if (!draudio_init_message_queue_dsound(&pContext->messageQueue) || !draudio_init_event_manager_dsound(&pContext->eventManager, &pContext->messageQueue))
4259 FreeLibrary(hDSoundDLL);
4268 #endif // !DRAUDIO_BUILD_DSOUND
4281 #include <xaudio2.h>