├── .gitignore ├── AL ├── aldc.c ├── alut.c ├── mojoal.c └── private │ ├── atomics.c │ ├── converters.c │ ├── core.c │ ├── data_queue.c │ ├── device.c │ ├── endian.c │ ├── errors.c │ └── streams.c ├── CMakeLists.txt ├── LICENSE ├── Makefile ├── README.md ├── dc-build.sh ├── include └── AL │ ├── al.h │ ├── alc.h │ └── alut.h └── samples ├── GLdc └── include │ └── GL │ ├── gl.h │ ├── glext.h │ ├── glkos.h │ └── glu.h ├── Makefile ├── basic ├── Makefile ├── main.c └── romdisk │ ├── PLACEHOLDER │ └── test.wav ├── helicopter ├── Makefile ├── main.c └── romdisk │ ├── PLACEHOLDER │ └── test.wav └── streaming ├── Makefile ├── main.c └── romdisk ├── PLACEHOLDER ├── file_1.wav └── test.wav /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | *.img 10 | 11 | # Linker output 12 | *.ilk 13 | *.map 14 | *.exp 15 | 16 | # Precompiled Headers 17 | *.gch 18 | *.pch 19 | 20 | # Libraries 21 | *.lib 22 | *.a 23 | *.la 24 | *.lo 25 | 26 | # Shared objects (inc. Windows DLLs) 27 | *.dll 28 | *.so 29 | *.so.* 30 | *.dylib 31 | 32 | # Executables 33 | *.exe 34 | *.out 35 | *.app 36 | *.i*86 37 | *.x86_64 38 | *.hex 39 | 40 | # Debug files 41 | *.dSYM/ 42 | *.su 43 | *.idb 44 | *.pdb 45 | 46 | # Kernel Module Compile Results 47 | *.mod* 48 | *.cmd 49 | .tmp_versions/ 50 | modules.order 51 | Module.symvers 52 | Mkfile.old 53 | dkms.conf 54 | -------------------------------------------------------------------------------- /AL/aldc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is essentially a copy-paste of the minimum code from SDL required to power MojoAL, with the exception 3 | * of the audio device code which is Dreamcast specific. 4 | * 5 | * It's quick and dirty, but it's also the fastest way to get some kind of OpenAL implementation on the DC without 6 | * doing it from scratch 7 | */ 8 | 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | 20 | /* Sometimes I get undefined errors about this... weird */ 21 | #ifndef M_PI 22 | #define M_PI 3.14159265358979323846264338327950288 23 | #endif 24 | 25 | #include "private/core.c" 26 | #include "private/endian.c" 27 | #include "private/errors.c" 28 | #include "private/atomics.c" 29 | #include "private/data_queue.c" 30 | #include "private/streams.c" 31 | #include "private/converters.c" 32 | #include "private/device.c" 33 | -------------------------------------------------------------------------------- /AL/alut.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "../include/AL/alut.h" 5 | 6 | 7 | static ALenum ALUT_ERROR = ALUT_ERROR_NO_ERROR; 8 | 9 | AL_API ALboolean AL_APIENTRY alutInit(int *argcp, char **argv) { 10 | return AL_TRUE; 11 | } 12 | 13 | AL_API ALboolean AL_APIENTRY alutInitWithoutContext(int *argcp, char **argv) { 14 | return AL_TRUE; 15 | } 16 | 17 | AL_API ALboolean AL_APIENTRY alutExit(void) { 18 | return AL_TRUE; 19 | } 20 | 21 | AL_API ALenum AL_APIENTRY alutGetError() { 22 | ALenum result = ALUT_ERROR; 23 | ALUT_ERROR = ALUT_ERROR_NO_ERROR; 24 | return result; 25 | } 26 | 27 | AL_API const ALchar* AL_APIENTRY alutGetErrorString(ALenum error) { 28 | switch(error) { 29 | case ALUT_ERROR_NO_ERROR: return "No Error"; 30 | /* FIXME */ 31 | default: 32 | return "Undescribed error"; 33 | } 34 | } 35 | 36 | static inline ALenum to_al_format(short channels, short samples) 37 | { 38 | ALboolean stereo = (channels > 1); 39 | 40 | switch (samples) { 41 | case 16: 42 | if (stereo) 43 | return AL_FORMAT_STEREO16; 44 | else 45 | return AL_FORMAT_MONO16; 46 | case 8: 47 | if (stereo) 48 | return AL_FORMAT_STEREO8; 49 | else 50 | return AL_FORMAT_MONO8; 51 | default: 52 | return -1; 53 | } 54 | } 55 | 56 | static ALboolean is_big_endian() { 57 | int a = 1; 58 | return !((char*)&a)[0]; 59 | } 60 | 61 | static int convert_to_int(char* buffer, int len) { 62 | int i = 0; 63 | int a = 0; 64 | if (!is_big_endian()) 65 | for (; i> 3) & 0x1f); 28 | SDL_AtomicLock(&locks[index]); 29 | } 30 | 31 | static inline void leaveLock(void *a) { 32 | uintptr_t index = ((((uintptr_t)a) >> 3) & 0x1f); 33 | SDL_AtomicUnlock(&locks[index]); 34 | } 35 | 36 | SDL_bool SDL_AtomicTryLock(SDL_SpinLock *lock) 37 | { 38 | #ifdef _arch_dreamcast 39 | /* Terrible terrible damage */ 40 | static mutex_t *_spinlock_mutex; 41 | 42 | if (!_spinlock_mutex) { 43 | _spinlock_mutex = (mutex_t*) malloc(sizeof(mutex_t)); 44 | /* Race condition on first lock... */ 45 | mutex_init(_spinlock_mutex, MUTEX_TYPE_NORMAL); 46 | } 47 | 48 | mutex_lock(_spinlock_mutex); 49 | 50 | if (*lock == 0) { 51 | *lock = 1; 52 | mutex_unlock(_spinlock_mutex); 53 | return SDL_TRUE; 54 | } else { 55 | mutex_unlock(_spinlock_mutex); 56 | return SDL_FALSE; 57 | } 58 | #else 59 | return SDL_TRUE; 60 | #endif 61 | } 62 | 63 | SDL_bool SDL_HasSSE() { 64 | #ifdef _arch_dreamcast 65 | return SDL_FALSE; 66 | #else 67 | return SDL_TRUE; 68 | #endif 69 | } 70 | 71 | void SDL_AtomicLock(SDL_SpinLock *lock) { 72 | int iterations = 0; 73 | /* FIXME: Should we have an eventual timeout? */ 74 | while (!SDL_AtomicTryLock(lock)) { 75 | if (iterations < 32) { 76 | iterations++; 77 | PAUSE_INSTRUCTION(); 78 | } else { 79 | /* !!! FIXME: this doesn't definitely give up the current timeslice, it does different things on various platforms. */ 80 | SDL_Delay(0); 81 | } 82 | } 83 | } 84 | 85 | void SDL_AtomicUnlock(SDL_SpinLock *lock) { 86 | *lock = 0; 87 | } 88 | 89 | SDL_bool SDL_AtomicCAS(SDL_atomic_t *a, int oldval, int newval) { 90 | SDL_bool retval = SDL_FALSE; 91 | 92 | enterLock(a); 93 | if (a->value == oldval) { 94 | a->value = newval; 95 | retval = SDL_TRUE; 96 | } 97 | leaveLock(a); 98 | 99 | return retval; 100 | } 101 | 102 | SDL_bool SDL_AtomicCASPtr(void* *a, void *oldval, void *newval) { 103 | SDL_bool retval = SDL_FALSE; 104 | 105 | enterLock(a); 106 | if (*a == oldval) { 107 | *a = newval; 108 | retval = SDL_TRUE; 109 | } 110 | leaveLock(a); 111 | 112 | return retval; 113 | } 114 | 115 | int SDL_AtomicSet(SDL_atomic_t *a, int v) { 116 | int value; 117 | do { 118 | value = a->value; 119 | } while (!SDL_AtomicCAS(a, value, v)); 120 | return value; 121 | } 122 | 123 | int SDL_AtomicAdd(SDL_atomic_t *a, int v) 124 | { 125 | int value; 126 | do { 127 | value = a->value; 128 | } while (!SDL_AtomicCAS(a, value, (value + v))); 129 | return value; 130 | } 131 | 132 | void* SDL_AtomicSetPtr(void* *a, void* v) 133 | { 134 | void* value; 135 | do { 136 | value = *a; 137 | } while (!SDL_AtomicCASPtr(a, value, v)); 138 | return value; 139 | } 140 | 141 | void* SDL_AtomicGetPtr(void* *a) 142 | { 143 | void* value = *a; 144 | SDL_CompilerBarrier(); 145 | return value; 146 | } 147 | 148 | int SDL_AtomicGet(SDL_atomic_t *a) 149 | { 150 | int value = a->value; 151 | SDL_CompilerBarrier(); 152 | return value; 153 | } 154 | -------------------------------------------------------------------------------- /AL/private/converters.c: -------------------------------------------------------------------------------- 1 | #define DIVBY128 0.0078125f 2 | #define DIVBY32768 0.000030517578125f 3 | #define DIVBY8388607 0.00000011920930376163766f 4 | 5 | void 6 | SDL_Convert_S8_to_F32(SDL_AudioCVT *cvt, SDL_AudioFormat format) 7 | { 8 | const Sint8 *src = ((const Sint8 *) (cvt->buf + cvt->len_cvt)) - 1; 9 | float *dst = ((float *) (cvt->buf + cvt->len_cvt * 4)) - 1; 10 | int i; 11 | 12 | for (i = cvt->len_cvt; i; --i, --src, --dst) { 13 | *dst = ((float) *src) * DIVBY128; 14 | } 15 | 16 | cvt->len_cvt *= 4; 17 | if (cvt->filters[++cvt->filter_index]) { 18 | cvt->filters[cvt->filter_index](cvt, AUDIO_F32SYS); 19 | } 20 | } 21 | 22 | void 23 | SDL_Convert_U8_to_F32(SDL_AudioCVT *cvt, SDL_AudioFormat format) 24 | { 25 | const Uint8 *src = ((const Uint8 *) (cvt->buf + cvt->len_cvt)) - 1; 26 | float *dst = ((float *) (cvt->buf + cvt->len_cvt * 4)) - 1; 27 | int i; 28 | 29 | for (i = cvt->len_cvt; i; --i, --src, --dst) { 30 | *dst = (((float) *src) * DIVBY128) - 1.0f; 31 | } 32 | 33 | cvt->len_cvt *= 4; 34 | if (cvt->filters[++cvt->filter_index]) { 35 | cvt->filters[cvt->filter_index](cvt, AUDIO_F32SYS); 36 | } 37 | } 38 | 39 | void 40 | SDL_Convert_S16_to_F32(SDL_AudioCVT *cvt, SDL_AudioFormat format) 41 | { 42 | const Sint16 *src = ((const Sint16 *) (cvt->buf + cvt->len_cvt)) - 1; 43 | float *dst = ((float *) (cvt->buf + cvt->len_cvt * 2)) - 1; 44 | int i; 45 | 46 | for (i = cvt->len_cvt / sizeof (Sint16); i; --i, --src, --dst) { 47 | *dst = ((float) *src) * DIVBY32768; 48 | } 49 | 50 | cvt->len_cvt *= 2; 51 | if (cvt->filters[++cvt->filter_index]) { 52 | cvt->filters[cvt->filter_index](cvt, AUDIO_F32SYS); 53 | } 54 | } 55 | 56 | void 57 | SDL_Convert_U16_to_F32(SDL_AudioCVT *cvt, SDL_AudioFormat format) 58 | { 59 | const Uint16 *src = ((const Uint16 *) (cvt->buf + cvt->len_cvt)) - 1; 60 | float *dst = ((float *) (cvt->buf + cvt->len_cvt * 2)) - 1; 61 | int i; 62 | 63 | for (i = cvt->len_cvt / sizeof (Uint16); i; --i, --src, --dst) { 64 | *dst = (((float) *src) * DIVBY32768) - 1.0f; 65 | } 66 | 67 | cvt->len_cvt *= 2; 68 | if (cvt->filters[++cvt->filter_index]) { 69 | cvt->filters[cvt->filter_index](cvt, AUDIO_F32SYS); 70 | } 71 | } 72 | 73 | void 74 | SDL_Convert_S32_to_F32(SDL_AudioCVT *cvt, SDL_AudioFormat format) 75 | { 76 | const Sint32 *src = (const Sint32 *) cvt->buf; 77 | float *dst = (float *) cvt->buf; 78 | int i; 79 | 80 | for (i = cvt->len_cvt / sizeof (Sint32); i; --i, ++src, ++dst) { 81 | *dst = ((float) (*src>>8)) * DIVBY8388607; 82 | } 83 | 84 | if (cvt->filters[++cvt->filter_index]) { 85 | cvt->filters[cvt->filter_index](cvt, AUDIO_F32SYS); 86 | } 87 | } 88 | 89 | void 90 | SDL_Convert_F32_to_S8(SDL_AudioCVT *cvt, SDL_AudioFormat format) 91 | { 92 | const float *src = (const float *) cvt->buf; 93 | Sint8 *dst = (Sint8 *) cvt->buf; 94 | int i; 95 | 96 | for (i = cvt->len_cvt / sizeof (float); i; --i, ++src, ++dst) { 97 | const float sample = *src; 98 | if (sample >= 1.0f) { 99 | *dst = 127; 100 | } else if (sample <= -1.0f) { 101 | *dst = -128; 102 | } else { 103 | *dst = (Sint8)(sample * 127.0f); 104 | } 105 | } 106 | 107 | cvt->len_cvt /= 4; 108 | if (cvt->filters[++cvt->filter_index]) { 109 | cvt->filters[cvt->filter_index](cvt, AUDIO_S8); 110 | } 111 | } 112 | 113 | void 114 | SDL_Convert_F32_to_U8(SDL_AudioCVT *cvt, SDL_AudioFormat format) 115 | { 116 | const float *src = (const float *) cvt->buf; 117 | Uint8 *dst = (Uint8 *) cvt->buf; 118 | int i; 119 | 120 | for (i = cvt->len_cvt / sizeof (float); i; --i, ++src, ++dst) { 121 | const float sample = *src; 122 | if (sample >= 1.0f) { 123 | *dst = 255; 124 | } else if (sample <= -1.0f) { 125 | *dst = 0; 126 | } else { 127 | *dst = (Uint8)((sample + 1.0f) * 127.0f); 128 | } 129 | } 130 | 131 | cvt->len_cvt /= 4; 132 | if (cvt->filters[++cvt->filter_index]) { 133 | cvt->filters[cvt->filter_index](cvt, AUDIO_U8); 134 | } 135 | } 136 | 137 | void 138 | SDL_Convert_F32_to_S16(SDL_AudioCVT *cvt, SDL_AudioFormat format) 139 | { 140 | const float *src = (const float *) cvt->buf; 141 | Sint16 *dst = (Sint16 *) cvt->buf; 142 | int i; 143 | 144 | for (i = cvt->len_cvt / sizeof (float); i; --i, ++src, ++dst) { 145 | const float sample = *src; 146 | if (sample >= 1.0f) { 147 | *dst = 32767; 148 | } else if (sample <= -1.0f) { 149 | *dst = -32768; 150 | } else { 151 | *dst = (Sint16)(sample * 32767.0f); 152 | } 153 | } 154 | 155 | cvt->len_cvt /= 2; 156 | if (cvt->filters[++cvt->filter_index]) { 157 | cvt->filters[cvt->filter_index](cvt, AUDIO_S16SYS); 158 | } 159 | } 160 | 161 | void 162 | SDL_Convert_F32_to_U16(SDL_AudioCVT *cvt, SDL_AudioFormat format) 163 | { 164 | const float *src = (const float *) cvt->buf; 165 | Uint16 *dst = (Uint16 *) cvt->buf; 166 | int i; 167 | 168 | for (i = cvt->len_cvt / sizeof (float); i; --i, ++src, ++dst) { 169 | const float sample = *src; 170 | if (sample >= 1.0f) { 171 | *dst = 65535; 172 | } else if (sample <= -1.0f) { 173 | *dst = 0; 174 | } else { 175 | *dst = (Uint16)((sample + 1.0f) * 32767.0f); 176 | } 177 | } 178 | 179 | cvt->len_cvt /= 2; 180 | if (cvt->filters[++cvt->filter_index]) { 181 | cvt->filters[cvt->filter_index](cvt, AUDIO_U16SYS); 182 | } 183 | } 184 | 185 | void 186 | SDL_Convert_F32_to_S32(SDL_AudioCVT *cvt, SDL_AudioFormat format) 187 | { 188 | const float *src = (const float *) cvt->buf; 189 | Sint32 *dst = (Sint32 *) cvt->buf; 190 | int i; 191 | 192 | for (i = cvt->len_cvt / sizeof (float); i; --i, ++src, ++dst) { 193 | const float sample = *src; 194 | if (sample >= 1.0f) { 195 | *dst = 2147483647; 196 | } else if (sample <= -1.0f) { 197 | *dst = (Sint32) -2147483648LL; 198 | } else { 199 | *dst = ((Sint32)(sample * 8388607.0f)) << 8; 200 | } 201 | } 202 | 203 | if (cvt->filters[++cvt->filter_index]) { 204 | cvt->filters[cvt->filter_index](cvt, AUDIO_S32SYS); 205 | } 206 | } 207 | 208 | 209 | -------------------------------------------------------------------------------- /AL/private/core.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | #define SDL_LIL_ENDIAN 1234 4 | #define SDL_BYTEORDER SDL_LIL_ENDIAN 5 | #define SDL_MAX_SINT32 ((Sint32)0x7FFFFFFF) 6 | #if (defined(__GNUC__) && (__GNUC__ <= 2)) || defined(__CC_ARM) || defined(__cplusplus) 7 | #define SDL_VARIABLE_LENGTH_ARRAY 1 8 | #else 9 | #define SDL_VARIABLE_LENGTH_ARRAY 10 | #endif 11 | 12 | #define SDL_zerop(x) SDL_memset((x), 0, sizeof(*(x))) 13 | 14 | typedef uint8_t Uint8; 15 | typedef uint16_t Uint16; 16 | typedef uint32_t Uint32; 17 | typedef uint64_t Uint64; 18 | typedef int8_t Sint8; 19 | typedef int16_t Sint16; 20 | typedef int32_t Sint32; 21 | 22 | #define SDL_MAX_SINT32 ((Sint32)0x7FFFFFFF) 23 | 24 | typedef enum { 25 | SDL_FALSE = 0, 26 | SDL_TRUE = 1 27 | } SDL_bool; 28 | 29 | #define SDLCALL 30 | #define DECLSPEC __attribute__ ((visibility("default"))) 31 | 32 | #define SDL_memcpy(dst, src, len) memcpy(dst, src, len) 33 | #define SDL_malloc malloc 34 | #define SDL_calloc calloc 35 | #define SDL_realloc realloc 36 | #define SDL_free free 37 | #define SDL_memset memset 38 | #define SDL_memmove memmove 39 | #define SDL_cosf cos 40 | #define SDL_sinf sin 41 | #define SDL_sqrt sqrt 42 | #define SDL_pow pow 43 | #define SDL_ceil ceil 44 | 45 | #define SDL_min(x, y) (((x) < (y)) ? (x) : (y)) 46 | #define SDL_max(x, y) (((x) > (y)) ? (x) : (y)) 47 | #define SDL_abs abs 48 | 49 | #define SDL_sqrtf sqrtf 50 | #define SDL_powf powf 51 | #define SDL_acosf acosf 52 | 53 | #define SDL_strdup strdup 54 | #define SDL_strcasecmp strcasecmp 55 | #define SDL_strlen strlen 56 | #define SDL_assert assert 57 | #define SDL_strcmp strcmp 58 | #define SDL_zero(x) SDL_memset(&(x), 0, sizeof((x))) 59 | 60 | #ifdef __STRICT_ANSI__ 61 | char *strdup(const char *); 62 | #endif 63 | 64 | static inline size_t SDL_strlcpy(char *dst, const char *src, size_t maxlen) { 65 | size_t srclen = SDL_strlen(src); 66 | if (maxlen > 0) { 67 | size_t len = SDL_min(srclen, maxlen - 1); 68 | SDL_memcpy(dst, src, len); 69 | dst[len] = '\0'; 70 | } 71 | 72 | return srclen; 73 | } 74 | 75 | #define SDL_arraysize(array) (sizeof(array)/sizeof(array[0])) 76 | 77 | #define SDL_static_cast(type, expression) ((type)(expression)) 78 | #define SDL_FORCE_INLINE __attribute__((always_inline)) static __inline__ 79 | 80 | #define SDL_Delay thd_sleep 81 | 82 | int SDL_InitSubSystem(Uint32 flags) { 83 | return 0; 84 | } 85 | 86 | void SDL_QuitSubSystem(Uint32 flags) { 87 | 88 | } 89 | -------------------------------------------------------------------------------- /AL/private/data_queue.c: -------------------------------------------------------------------------------- 1 | 2 | typedef struct SDL_DataQueuePacket 3 | { 4 | size_t datalen; /* bytes currently in use in this packet. */ 5 | size_t startpos; /* bytes currently consumed in this packet. */ 6 | struct SDL_DataQueuePacket *next; /* next item in linked list. */ 7 | Uint8 data[SDL_VARIABLE_LENGTH_ARRAY]; /* packet data */ 8 | } SDL_DataQueuePacket; 9 | 10 | struct SDL_DataQueue 11 | { 12 | SDL_DataQueuePacket *head; /* device fed from here. */ 13 | SDL_DataQueuePacket *tail; /* queue fills to here. */ 14 | SDL_DataQueuePacket *pool; /* these are unused packets. */ 15 | size_t packet_size; /* size of new packets */ 16 | size_t queued_bytes; /* number of bytes of data in the queue. */ 17 | }; 18 | 19 | typedef struct SDL_DataQueue SDL_DataQueue; 20 | 21 | static void 22 | SDL_FreeDataQueueList(SDL_DataQueuePacket *packet) 23 | { 24 | while (packet) { 25 | SDL_DataQueuePacket *next = packet->next; 26 | SDL_free(packet); 27 | packet = next; 28 | } 29 | } 30 | 31 | 32 | /* this all expects that you managed thread safety elsewhere. */ 33 | 34 | SDL_DataQueue * 35 | SDL_NewDataQueue(const size_t _packetlen, const size_t initialslack) 36 | { 37 | SDL_DataQueue *queue = (SDL_DataQueue *) SDL_malloc(sizeof (SDL_DataQueue)); 38 | 39 | if (!queue) { 40 | SDL_OutOfMemory(); 41 | return NULL; 42 | } else { 43 | const size_t packetlen = _packetlen ? _packetlen : 1024; 44 | const size_t wantpackets = (initialslack + (packetlen - 1)) / packetlen; 45 | size_t i; 46 | 47 | SDL_zerop(queue); 48 | queue->packet_size = packetlen; 49 | 50 | for (i = 0; i < wantpackets; i++) { 51 | SDL_DataQueuePacket *packet = (SDL_DataQueuePacket *) SDL_malloc(sizeof (SDL_DataQueuePacket) + packetlen); 52 | if (packet) { /* don't care if this fails, we'll deal later. */ 53 | packet->datalen = 0; 54 | packet->startpos = 0; 55 | packet->next = queue->pool; 56 | queue->pool = packet; 57 | } 58 | } 59 | } 60 | 61 | return queue; 62 | } 63 | 64 | void 65 | SDL_FreeDataQueue(SDL_DataQueue *queue) 66 | { 67 | if (queue) { 68 | SDL_FreeDataQueueList(queue->head); 69 | SDL_FreeDataQueueList(queue->pool); 70 | SDL_free(queue); 71 | } 72 | } 73 | 74 | void 75 | SDL_ClearDataQueue(SDL_DataQueue *queue, const size_t slack) 76 | { 77 | const size_t packet_size = queue ? queue->packet_size : 1; 78 | const size_t slackpackets = (slack + (packet_size-1)) / packet_size; 79 | SDL_DataQueuePacket *packet; 80 | SDL_DataQueuePacket *prev = NULL; 81 | size_t i; 82 | 83 | if (!queue) { 84 | return; 85 | } 86 | 87 | packet = queue->head; 88 | 89 | /* merge the available pool and the current queue into one list. */ 90 | if (packet) { 91 | queue->tail->next = queue->pool; 92 | } else { 93 | packet = queue->pool; 94 | } 95 | 96 | /* Remove the queued packets from the device. */ 97 | queue->tail = NULL; 98 | queue->head = NULL; 99 | queue->queued_bytes = 0; 100 | queue->pool = packet; 101 | 102 | /* Optionally keep some slack in the pool to reduce malloc pressure. */ 103 | for (i = 0; packet && (i < slackpackets); i++) { 104 | prev = packet; 105 | packet = packet->next; 106 | } 107 | 108 | if (prev) { 109 | prev->next = NULL; 110 | } else { 111 | queue->pool = NULL; 112 | } 113 | 114 | SDL_FreeDataQueueList(packet); /* free extra packets */ 115 | } 116 | 117 | static SDL_DataQueuePacket * 118 | AllocateDataQueuePacket(SDL_DataQueue *queue) 119 | { 120 | SDL_DataQueuePacket *packet; 121 | 122 | SDL_assert(queue != NULL); 123 | 124 | packet = queue->pool; 125 | if (packet != NULL) { 126 | /* we have one available in the pool. */ 127 | queue->pool = packet->next; 128 | } else { 129 | /* Have to allocate a new one! */ 130 | packet = (SDL_DataQueuePacket *) SDL_malloc(sizeof (SDL_DataQueuePacket) + queue->packet_size); 131 | if (packet == NULL) { 132 | return NULL; 133 | } 134 | } 135 | 136 | packet->datalen = 0; 137 | packet->startpos = 0; 138 | packet->next = NULL; 139 | 140 | SDL_assert((queue->head != NULL) == (queue->queued_bytes != 0)); 141 | if (queue->tail == NULL) { 142 | queue->head = packet; 143 | } else { 144 | queue->tail->next = packet; 145 | } 146 | queue->tail = packet; 147 | return packet; 148 | } 149 | 150 | 151 | int 152 | SDL_WriteToDataQueue(SDL_DataQueue *queue, const void *_data, const size_t _len) 153 | { 154 | size_t len = _len; 155 | const Uint8 *data = (const Uint8 *) _data; 156 | const size_t packet_size = queue ? queue->packet_size : 0; 157 | SDL_DataQueuePacket *orighead; 158 | SDL_DataQueuePacket *origtail; 159 | size_t origlen; 160 | size_t datalen; 161 | 162 | if (!queue) { 163 | return SDL_InvalidParamError("queue"); 164 | } 165 | 166 | orighead = queue->head; 167 | origtail = queue->tail; 168 | origlen = origtail ? origtail->datalen : 0; 169 | 170 | while (len > 0) { 171 | SDL_DataQueuePacket *packet = queue->tail; 172 | SDL_assert(!packet || (packet->datalen <= packet_size)); 173 | if (!packet || (packet->datalen >= packet_size)) { 174 | /* tail packet missing or completely full; we need a new packet. */ 175 | packet = AllocateDataQueuePacket(queue); 176 | if (!packet) { 177 | /* uhoh, reset so we've queued nothing new, free what we can. */ 178 | if (!origtail) { 179 | packet = queue->head; /* whole queue. */ 180 | } else { 181 | packet = origtail->next; /* what we added to existing queue. */ 182 | origtail->next = NULL; 183 | origtail->datalen = origlen; 184 | } 185 | queue->head = orighead; 186 | queue->tail = origtail; 187 | queue->pool = NULL; 188 | 189 | SDL_FreeDataQueueList(packet); /* give back what we can. */ 190 | return SDL_OutOfMemory(); 191 | } 192 | } 193 | 194 | datalen = SDL_min(len, packet_size - packet->datalen); 195 | SDL_memcpy(packet->data + packet->datalen, data, datalen); 196 | data += datalen; 197 | len -= datalen; 198 | packet->datalen += datalen; 199 | queue->queued_bytes += datalen; 200 | } 201 | 202 | return 0; 203 | } 204 | 205 | size_t 206 | SDL_PeekIntoDataQueue(SDL_DataQueue *queue, void *_buf, const size_t _len) 207 | { 208 | size_t len = _len; 209 | Uint8 *buf = (Uint8 *) _buf; 210 | Uint8 *ptr = buf; 211 | SDL_DataQueuePacket *packet; 212 | 213 | if (!queue) { 214 | return 0; 215 | } 216 | 217 | for (packet = queue->head; len && packet; packet = packet->next) { 218 | const size_t avail = packet->datalen - packet->startpos; 219 | const size_t cpy = SDL_min(len, avail); 220 | SDL_assert(queue->queued_bytes >= avail); 221 | 222 | SDL_memcpy(ptr, packet->data + packet->startpos, cpy); 223 | ptr += cpy; 224 | len -= cpy; 225 | } 226 | 227 | return (size_t) (ptr - buf); 228 | } 229 | 230 | size_t 231 | SDL_ReadFromDataQueue(SDL_DataQueue *queue, void *_buf, const size_t _len) 232 | { 233 | size_t len = _len; 234 | Uint8 *buf = (Uint8 *) _buf; 235 | Uint8 *ptr = buf; 236 | SDL_DataQueuePacket *packet; 237 | 238 | if (!queue) { 239 | return 0; 240 | } 241 | 242 | while ((len > 0) && ((packet = queue->head) != NULL)) { 243 | const size_t avail = packet->datalen - packet->startpos; 244 | const size_t cpy = SDL_min(len, avail); 245 | SDL_assert(queue->queued_bytes >= avail); 246 | 247 | SDL_memcpy(ptr, packet->data + packet->startpos, cpy); 248 | packet->startpos += cpy; 249 | ptr += cpy; 250 | queue->queued_bytes -= cpy; 251 | len -= cpy; 252 | 253 | if (packet->startpos == packet->datalen) { /* packet is done, put it in the pool. */ 254 | queue->head = packet->next; 255 | SDL_assert((packet->next != NULL) || (packet == queue->tail)); 256 | packet->next = queue->pool; 257 | queue->pool = packet; 258 | } 259 | } 260 | 261 | SDL_assert((queue->head != NULL) == (queue->queued_bytes != 0)); 262 | 263 | if (queue->head == NULL) { 264 | queue->tail = NULL; /* in case we drained the queue entirely. */ 265 | } 266 | 267 | return (size_t) (ptr - buf); 268 | } 269 | 270 | size_t 271 | SDL_CountDataQueue(SDL_DataQueue *queue) 272 | { 273 | return queue ? queue->queued_bytes : 0; 274 | } 275 | 276 | void * 277 | SDL_ReserveSpaceInDataQueue(SDL_DataQueue *queue, const size_t len) 278 | { 279 | SDL_DataQueuePacket *packet; 280 | 281 | if (!queue) { 282 | SDL_InvalidParamError("queue"); 283 | return NULL; 284 | } else if (len == 0) { 285 | SDL_InvalidParamError("len"); 286 | return NULL; 287 | } else if (len > queue->packet_size) { 288 | SDL_SetError("len is larger than packet size"); 289 | return NULL; 290 | } 291 | 292 | packet = queue->head; 293 | if (packet) { 294 | const size_t avail = queue->packet_size - packet->datalen; 295 | if (len <= avail) { /* we can use the space at end of this packet. */ 296 | void *retval = packet->data + packet->datalen; 297 | packet->datalen += len; 298 | queue->queued_bytes += len; 299 | return retval; 300 | } 301 | } 302 | 303 | /* Need a fresh packet. */ 304 | packet = AllocateDataQueuePacket(queue); 305 | if (!packet) { 306 | SDL_OutOfMemory(); 307 | return NULL; 308 | } 309 | 310 | packet->datalen = len; 311 | queue->queued_bytes += len; 312 | return packet->data; 313 | } 314 | -------------------------------------------------------------------------------- /AL/private/device.c: -------------------------------------------------------------------------------- 1 | 2 | #define DREAMCAST_AUDIO_DEVICE_NAME "Yamaha AICA Stereo Device" 3 | 4 | #ifndef _arch_dreamcast 5 | typedef uint32_t snd_stream_hnd_t; 6 | const snd_stream_hnd_t SND_STREAM_INVALID = -1; 7 | #else 8 | static kthread_t* THREAD = NULL; 9 | static mutex_t DEVICE_MUTEX = MUTEX_INITIALIZER; 10 | #endif 11 | 12 | // This is the spec that MojoAL asked for 13 | static SDL_AudioSpec DESIRED_SPEC; 14 | 15 | // This is the spec that we're passing to KOS 16 | static SDL_AudioSpec OBTAINED_SPEC; 17 | 18 | // We then convert the format into this dest buffer 19 | static Uint8* DEST_BUFFER = NULL; 20 | 21 | static SDL_AudioStatus STATUS = SDL_AUDIO_STOPPED; 22 | static snd_stream_hnd_t STREAM_HANDLE = SND_STREAM_INVALID; 23 | static volatile SDL_bool RUNNING = SDL_TRUE; 24 | 25 | /* MojoAL submits stream data as floats, we leverage 26 | * the SDL coversion stuff to convert it into little endian 27 | * bytes */ 28 | static SDL_AudioStream* STREAM = NULL; 29 | 30 | static const SDL_AudioDeviceID DEVICE_ID = 2; 31 | 32 | int SDL_GetNumAudioDevices(int iscapture) { 33 | if(iscapture) { 34 | return 0; 35 | } else { 36 | return 1; 37 | } 38 | } 39 | 40 | const char *SDL_GetAudioDeviceName(int index, int iscapture) { 41 | if(index == 0 && !iscapture) { 42 | return DREAMCAST_AUDIO_DEVICE_NAME; 43 | } else { 44 | return NULL; 45 | } 46 | } 47 | 48 | SDL_AudioStatus SDL_GetAudioDeviceStatus(SDL_AudioDeviceID dev) { 49 | assert(dev == DEVICE_ID); 50 | return STATUS; 51 | } 52 | 53 | void SDL_PauseAudioDevice(SDL_AudioDeviceID dev, int pause_on) { 54 | assert(dev == DEVICE_ID); 55 | if(!pause_on) // printf("Unpausing audio\n"); 56 | STATUS = (pause_on) ? SDL_AUDIO_PAUSED : SDL_AUDIO_PLAYING; 57 | } 58 | 59 | void SDL_LockAudioDevice(SDL_AudioDeviceID dev) { 60 | #ifdef _arch_dreamcast 61 | mutex_lock(&DEVICE_MUTEX); 62 | #endif 63 | } 64 | 65 | void SDL_UnlockAudioDevice(SDL_AudioDeviceID dev) { 66 | #ifdef _arch_dreamcast 67 | mutex_unlock(&DEVICE_MUTEX); 68 | #endif 69 | } 70 | 71 | #ifdef _arch_dreamcast 72 | void* stream_callback(snd_stream_hnd_t hnd, int smp_req, int *smp_recv) { 73 | static const int SAMPLES = 4096; 74 | static Uint8 BUFFER[4096]; 75 | 76 | //printf("KOS requested %d bytes\n", smp_req); 77 | 78 | // smp_req == spec.size because that's what we passed 79 | // when initalizing the KOS stream 80 | assert(STREAM_HANDLE != SND_STREAM_INVALID); 81 | 82 | SDL_LockAudioDevice(1); 83 | 84 | assert(hnd == STREAM_HANDLE); 85 | 86 | // Fill the buffer from SDL 87 | while (SDL_AudioStreamAvailable(STREAM) < smp_req) { 88 | if(STATUS == SDL_AUDIO_PAUSED) { 89 | // printf("Playing silence...(stream is paused)\n"); 90 | SDL_memset(BUFFER, DESIRED_SPEC.silence, SAMPLES); 91 | } else { 92 | // printf("Gathering data...\n"); 93 | OBTAINED_SPEC.callback(DESIRED_SPEC.userdata, BUFFER, SAMPLES); 94 | } 95 | int rc = SDL_AudioStreamPut(STREAM, BUFFER, SAMPLES); 96 | assert(rc != -1); 97 | if(rc == -1) { 98 | fprintf(stderr, "Error putting audiostream data!!\n"); 99 | } 100 | } 101 | 102 | SDL_UnlockAudioDevice(1); 103 | 104 | // printf("Converting buffer of size %u...\n", (unsigned int) DESIRED_SPEC.size); 105 | // printf("%d bytes available...\n", available); 106 | /* snd_stream sometimes requests more samples than the buffer size 107 | * we told it about! */ 108 | int to_get = (smp_req < OBTAINED_SPEC.size) ? smp_req : OBTAINED_SPEC.size; 109 | int gotten = SDL_AudioStreamGet(STREAM, DEST_BUFFER, to_get); 110 | 111 | assert(gotten != -1); 112 | assert(gotten <= OBTAINED_SPEC.size); 113 | 114 | *smp_recv = gotten; 115 | 116 | //printf("Returning buffer to KOS (%d)...\n", gotten); 117 | // Return it to KOS 118 | return DEST_BUFFER; 119 | } 120 | #endif 121 | 122 | int stream_thread(void *arg) { 123 | STREAM_HANDLE = snd_stream_alloc(&stream_callback, OBTAINED_SPEC.size); 124 | assert(STREAM_HANDLE != SND_STREAM_INVALID); 125 | snd_stream_start(STREAM_HANDLE, OBTAINED_SPEC.freq, OBTAINED_SPEC.channels == 2); 126 | 127 | while(RUNNING) { 128 | #ifdef _arch_dreamcast 129 | int ret = snd_stream_poll(STREAM_HANDLE); 130 | assert(ret == 0); 131 | if(ret != 0) { 132 | fprintf(stderr, "Error polling the stream!!\n"); 133 | } 134 | 135 | thd_pass(); 136 | #endif 137 | } 138 | 139 | snd_stream_stop(STREAM_HANDLE); 140 | snd_stream_destroy(STREAM_HANDLE); 141 | snd_stream_shutdown(); 142 | 143 | // printf("Thread exit!\n"); 144 | return 0; 145 | } 146 | 147 | void SDL_CalculateAudioSpec(SDL_AudioSpec * spec) { 148 | switch (spec->format) { 149 | case AUDIO_U8: 150 | spec->silence = 0x80; 151 | break; 152 | default: 153 | spec->silence = 0x00; 154 | break; 155 | } 156 | spec->size = SDL_AUDIO_BITSIZE(spec->format) / 8; 157 | spec->size *= spec->channels; 158 | spec->size *= spec->samples; 159 | } 160 | 161 | SDL_AudioDeviceID SDL_OpenAudioDevice( 162 | const char* device, 163 | int iscapture, 164 | const SDL_AudioSpec* desired, 165 | SDL_AudioSpec* obtained, 166 | int allowed_changes) { 167 | 168 | // We should check device here, but, mojoAL passes NULL 169 | // for the const char* and for some reason checking for 170 | // NULL doesn't work and the world ends horrifically, so 171 | // we don't check device here. 172 | 173 | if(iscapture) { 174 | SDL_SetError("No capture devices supported\n"); 175 | return 0; 176 | } 177 | 178 | assert(STREAM_HANDLE == SND_STREAM_INVALID); 179 | 180 | if(STREAM_HANDLE != SND_STREAM_INVALID) { 181 | return 0; 182 | } 183 | 184 | memcpy(&DESIRED_SPEC, desired, sizeof(SDL_AudioSpec)); 185 | memcpy(&OBTAINED_SPEC, desired, sizeof(SDL_AudioSpec)); 186 | 187 | OBTAINED_SPEC.format = AUDIO_S16LSB; 188 | OBTAINED_SPEC.channels = 2; 189 | 190 | SDL_CalculateAudioSpec(&DESIRED_SPEC); 191 | SDL_CalculateAudioSpec(&OBTAINED_SPEC); 192 | 193 | if(obtained) { 194 | memcpy(obtained, &OBTAINED_SPEC, sizeof(SDL_AudioSpec)); 195 | } 196 | 197 | // This is what mojoAL submits 198 | assert(desired->format == AUDIO_F32LSB); 199 | 200 | DEST_BUFFER = (Uint8*) malloc(OBTAINED_SPEC.size); 201 | 202 | STREAM = SDL_NewAudioStream( 203 | DESIRED_SPEC.format, DESIRED_SPEC.channels, DESIRED_SPEC.freq, 204 | OBTAINED_SPEC.format, OBTAINED_SPEC.channels, OBTAINED_SPEC.freq 205 | ); 206 | 207 | assert(STREAM); 208 | 209 | // All things start paused! 210 | STATUS = SDL_AUDIO_PAUSED; 211 | 212 | #ifdef _arch_dreamcast 213 | // FIXME: Move to SDL_init(); 214 | int rc = snd_stream_init(); 215 | assert(rc == 0); 216 | if(rc != 0) { 217 | fprintf(stderr, "Error initializing the stream!!\n"); 218 | } 219 | 220 | assert(OBTAINED_SPEC.size < SND_STREAM_BUFFER_MAX); 221 | 222 | // printf("Desired Frequency is: %d\n", DESIRED_SPEC.freq); 223 | // printf("Desired Channels: %d\n", DESIRED_SPEC.channels); 224 | // printf("Desired Samples: %d\n", DESIRED_SPEC.samples); 225 | 226 | // printf("Starting stream...\n"); 227 | // printf("Frequency is: %d\n", OBTAINED_SPEC.freq); 228 | // printf("Channels: %d\n", OBTAINED_SPEC.channels); 229 | 230 | THREAD = thd_create(1, (void*)stream_thread, NULL); 231 | #endif 232 | return DEVICE_ID; 233 | } 234 | 235 | void SDL_CloseAudioDevice(SDL_AudioDeviceID dev) { 236 | if(dev != DEVICE_ID) { 237 | return; 238 | } 239 | 240 | // FIXME: Should be atomic 241 | RUNNING = SDL_FALSE; 242 | 243 | #ifdef _arch_dreamcast 244 | // printf("Destroying stream!\n"); 245 | thd_join(THREAD, NULL); 246 | #endif 247 | 248 | SDL_FreeAudioStream(STREAM); 249 | } 250 | -------------------------------------------------------------------------------- /AL/private/endian.c: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | SDL_FORCE_INLINE Uint16 SDL_Swap16(Uint16 x) { 5 | return SDL_static_cast(Uint16, ((x << 8) | (x >> 8))); 6 | } 7 | 8 | SDL_FORCE_INLINE Uint32 SDL_Swap32(Uint32 x) { 9 | return SDL_static_cast(Uint32, ((x << 24) | ((x << 8) & 0x00FF0000) | 10 | ((x >> 8) & 0x0000FF00) | (x >> 24))); 11 | } 12 | 13 | SDL_FORCE_INLINE Uint64 SDL_Swap64(Uint64 x) 14 | { 15 | Uint32 hi, lo; 16 | 17 | /* Separate into high and low 32-bit values and swap them */ 18 | lo = SDL_static_cast(Uint32, x & 0xFFFFFFFF); 19 | x >>= 32; 20 | hi = SDL_static_cast(Uint32, x & 0xFFFFFFFF); 21 | x = SDL_Swap32(lo); 22 | x <<= 32; 23 | x |= SDL_Swap32(hi); 24 | return (x); 25 | } 26 | -------------------------------------------------------------------------------- /AL/private/errors.c: -------------------------------------------------------------------------------- 1 | typedef enum 2 | { 3 | SDL_NO_ERROR, 4 | SDL_ENOMEM, 5 | SDL_EFREAD, 6 | SDL_EFWRITE, 7 | SDL_EFSEEK, 8 | SDL_UNSUPPORTED, 9 | SDL_LASTERROR, 10 | SDL_UNKNOWN_ERROR 11 | } SDL_errorcode; 12 | 13 | #define SDL_OutOfMemory() SDL_Error(SDL_ENOMEM) 14 | #define SDL_InvalidParamError(param) SDL_SetError("Parameter '%s' is invalid", (param)) 15 | 16 | static SDL_errorcode error = SDL_NO_ERROR; 17 | 18 | /* This doesn't behave list SDL_Error, but more like GL errors */ 19 | int SDL_Error(SDL_errorcode code) { 20 | if(error == SDL_NO_ERROR) { 21 | fprintf(stderr, "OpenAL Error occurred: %d\n", code); 22 | error = code; 23 | } 24 | 25 | return -1; 26 | } 27 | 28 | 29 | /* Lazy hack */ 30 | 31 | int SDL_SetError(const char* msg, ...) { 32 | fprintf(stderr, msg); 33 | SDL_Error(SDL_UNKNOWN_ERROR); 34 | return -1; 35 | } 36 | -------------------------------------------------------------------------------- /AL/private/streams.c: -------------------------------------------------------------------------------- 1 | 2 | // ----------------- AUDIO -------------------- 3 | 4 | #define SDL_AUDIO_MASK_BITSIZE (0xFF) 5 | #define SDL_AUDIO_MASK_DATATYPE (1<<8) 6 | #define SDL_AUDIO_MASK_ENDIAN (1<<12) 7 | #define SDL_AUDIO_MASK_SIGNED (1<<15) 8 | #define SDL_AUDIO_BITSIZE(x) (x & SDL_AUDIO_MASK_BITSIZE) 9 | #define SDL_AUDIO_ISFLOAT(x) (x & SDL_AUDIO_MASK_DATATYPE) 10 | #define SDL_AUDIO_ISBIGENDIAN(x) (x & SDL_AUDIO_MASK_ENDIAN) 11 | #define SDL_AUDIO_ISSIGNED(x) (x & SDL_AUDIO_MASK_SIGNED) 12 | #define SDL_AUDIO_ISINT(x) (!SDL_AUDIO_ISFLOAT(x)) 13 | #define SDL_AUDIO_ISLITTLEENDIAN(x) (!SDL_AUDIO_ISBIGENDIAN(x)) 14 | #define SDL_AUDIO_ISUNSIGNED(x) (!SDL_AUDIO_ISSIGNED(x)) 15 | 16 | #define SDL_INIT_AUDIO 0x00000010 17 | 18 | #define AUDIO_U8 0x0008 /**< Unsigned 8-bit samples */ 19 | #define AUDIO_S8 0x8008 /**< Signed 8-bit samples */ 20 | #define AUDIO_U16LSB 0x0010 /**< Unsigned 16-bit samples */ 21 | #define AUDIO_S16LSB 0x8010 /**< Signed 16-bit samples */ 22 | #define AUDIO_U16MSB 0x1010 /**< As above, but big-endian byte order */ 23 | #define AUDIO_S16MSB 0x9010 /**< As above, but big-endian byte order */ 24 | #define AUDIO_U16 AUDIO_U16LSB 25 | #define AUDIO_S16 AUDIO_S16LSB 26 | 27 | #define AUDIO_S32LSB 0x8020 /**< 32-bit integer samples */ 28 | #define AUDIO_S32MSB 0x9020 /**< As above, but big-endian byte order */ 29 | #define AUDIO_S32 AUDIO_S32LSB 30 | 31 | #define AUDIO_F32LSB 0x8120 /**< 32-bit floating point samples */ 32 | #define AUDIO_F32MSB 0x9120 /**< As above, but big-endian byte order */ 33 | #define AUDIO_F32 AUDIO_F32LSB 34 | 35 | /* Little endian */ 36 | #define AUDIO_U16SYS AUDIO_U16LSB 37 | #define AUDIO_S16SYS AUDIO_S16LSB 38 | #define AUDIO_S32SYS AUDIO_S32LSB 39 | #define AUDIO_F32SYS AUDIO_F32LSB 40 | 41 | /* this is opaque to the outside world. */ 42 | struct _SDL_AudioStream; 43 | typedef struct _SDL_AudioStream SDL_AudioStream; 44 | typedef Uint32 SDL_AudioDeviceID; 45 | typedef Uint16 SDL_AudioFormat; 46 | 47 | 48 | typedef struct{ 49 | int freq; 50 | Uint16 format; 51 | Uint8 channels; 52 | Uint8 silence; 53 | Uint16 samples; 54 | Uint32 size; 55 | void (*callback)(void *userdata, Uint8 *stream, int len); 56 | void *userdata; 57 | } SDL_AudioSpec; 58 | 59 | typedef enum 60 | { 61 | SDL_AUDIO_STOPPED = 0, 62 | SDL_AUDIO_PLAYING, 63 | SDL_AUDIO_PAUSED 64 | } SDL_AudioStatus; 65 | 66 | struct SDL_AudioCVT; 67 | typedef void (SDLCALL * SDL_AudioFilter) (struct SDL_AudioCVT * cvt, SDL_AudioFormat format); 68 | 69 | #define SDL_AUDIOCVT_MAX_FILTERS 9 70 | 71 | typedef struct SDL_AudioCVT 72 | { 73 | int needed; /**< Set to 1 if conversion possible */ 74 | SDL_AudioFormat src_format; /**< Source audio format */ 75 | SDL_AudioFormat dst_format; /**< Target audio format */ 76 | double rate_incr; /**< Rate conversion increment */ 77 | Uint8 *buf; /**< Buffer to hold entire audio data */ 78 | int len; /**< Length of original audio buffer */ 79 | int len_cvt; /**< Length of converted audio buffer */ 80 | int len_mult; /**< buffer must be len*len_mult big */ 81 | double len_ratio; /**< Given len, final size is len*len_ratio */ 82 | SDL_AudioFilter filters[SDL_AUDIOCVT_MAX_FILTERS + 1]; /**< NULL-terminated list of filter functions */ 83 | int filter_index; /**< Current audio conversion function */ 84 | } SDL_AudioCVT; 85 | 86 | /* SDL's resampler uses a "bandlimited interpolation" algorithm: 87 | https://ccrma.stanford.edu/~jos/resample/ */ 88 | 89 | #define RESAMPLER_ZERO_CROSSINGS 5 90 | #define RESAMPLER_BITS_PER_SAMPLE 16 91 | #define RESAMPLER_SAMPLES_PER_ZERO_CROSSING (1 << ((RESAMPLER_BITS_PER_SAMPLE / 2) + 1)) 92 | #define RESAMPLER_FILTER_SIZE ((RESAMPLER_SAMPLES_PER_ZERO_CROSSING * RESAMPLER_ZERO_CROSSINGS) + 1) 93 | 94 | static int ResamplerPadding(const int inrate, const int outrate) { 95 | if (inrate == outrate) { 96 | return 0; 97 | } else if (inrate > outrate) { 98 | return (int) SDL_ceil(((float) (RESAMPLER_SAMPLES_PER_ZERO_CROSSING * inrate) / ((float) outrate))); 99 | } 100 | return RESAMPLER_SAMPLES_PER_ZERO_CROSSING; 101 | } 102 | 103 | typedef int (*SDL_ResampleAudioStreamFunc)(SDL_AudioStream *stream, const void *inbuf, const int inbuflen, void *outbuf, const int outbuflen); 104 | typedef void (*SDL_ResetAudioStreamResamplerFunc)(SDL_AudioStream *stream); 105 | typedef void (*SDL_CleanupAudioStreamResamplerFunc)(SDL_AudioStream *stream); 106 | 107 | 108 | struct _SDL_AudioStream 109 | { 110 | SDL_AudioCVT cvt_before_resampling; 111 | SDL_AudioCVT cvt_after_resampling; 112 | SDL_DataQueue *queue; 113 | SDL_bool first_run; 114 | Uint8 *staging_buffer; 115 | int staging_buffer_size; 116 | int staging_buffer_filled; 117 | Uint8 *work_buffer_base; /* maybe unaligned pointer from SDL_realloc(). */ 118 | int work_buffer_len; 119 | int src_sample_frame_size; 120 | SDL_AudioFormat src_format; 121 | Uint8 src_channels; 122 | int src_rate; 123 | int dst_sample_frame_size; 124 | SDL_AudioFormat dst_format; 125 | Uint8 dst_channels; 126 | int dst_rate; 127 | double rate_incr; 128 | Uint8 pre_resample_channels; 129 | int packetlen; 130 | int resampler_padding_samples; 131 | float *resampler_padding; 132 | void *resampler_state; 133 | SDL_ResampleAudioStreamFunc resampler_func; 134 | SDL_ResetAudioStreamResamplerFunc reset_resampler_func; 135 | SDL_CleanupAudioStreamResamplerFunc cleanup_resampler_func; 136 | }; 137 | 138 | int SDL_BuildAudioCVT(SDL_AudioCVT * cvt, SDL_AudioFormat src_fmt, Uint8 src_channels, int src_rate, 139 | SDL_AudioFormat dst_fmt, Uint8 dst_channels, int dst_rate); 140 | 141 | int SDL_ConvertAudio(SDL_AudioCVT * cvt); 142 | 143 | void SDL_Convert_U8_to_F32(SDL_AudioCVT *cvt, SDL_AudioFormat format); 144 | void SDL_Convert_S8_to_F32(SDL_AudioCVT *cvt, SDL_AudioFormat format); 145 | void SDL_Convert_S16_to_F32(SDL_AudioCVT *cvt, SDL_AudioFormat format); 146 | void SDL_Convert_U16_to_F32(SDL_AudioCVT *cvt, SDL_AudioFormat format); 147 | void SDL_Convert_S32_to_F32(SDL_AudioCVT *cvt, SDL_AudioFormat format); 148 | 149 | void SDL_Convert_F32_to_U8(SDL_AudioCVT *cvt, SDL_AudioFormat format); 150 | void SDL_Convert_F32_to_S8(SDL_AudioCVT *cvt, SDL_AudioFormat format); 151 | void SDL_Convert_F32_to_S16(SDL_AudioCVT *cvt, SDL_AudioFormat format); 152 | void SDL_Convert_F32_to_U16(SDL_AudioCVT *cvt, SDL_AudioFormat format); 153 | void SDL_Convert_F32_to_S32(SDL_AudioCVT *cvt, SDL_AudioFormat format); 154 | 155 | /* This is a "modified" bessel function, so you can't use POSIX j0() */ 156 | static double bessel(const double x) 157 | { 158 | const double xdiv2 = x / 2.0; 159 | double i0 = 1.0f; 160 | double f = 1.0f; 161 | int i = 1; 162 | 163 | while (SDL_TRUE) { 164 | const double diff = SDL_pow(xdiv2, i * 2) / SDL_pow(f, 2); 165 | if (diff < 1.0e-21f) { 166 | break; 167 | } 168 | i0 += diff; 169 | i++; 170 | f *= (double) i; 171 | } 172 | 173 | return i0; 174 | } 175 | 176 | /* build kaiser table with cardinal sine applied to it, and array of differences between elements. */ 177 | static void kaiser_and_sinc(float *table, float *diffs, const int tablelen, const double beta) 178 | { 179 | const int lenm1 = tablelen - 1; 180 | const int lenm1div2 = lenm1 / 2; 181 | int i; 182 | 183 | table[0] = 1.0f; 184 | for (i = 1; i < tablelen; i++) { 185 | const double kaiser = bessel(beta * SDL_sqrt(1.0 - SDL_pow(((i - lenm1) / 2.0) / lenm1div2, 2.0))) / bessel(beta); 186 | table[tablelen - i] = (float) kaiser; 187 | } 188 | 189 | for (i = 1; i < tablelen; i++) { 190 | const float x = (((float) i) / ((float) RESAMPLER_SAMPLES_PER_ZERO_CROSSING)) * ((float) M_PI); 191 | table[i] *= SDL_sinf(x) / x; 192 | diffs[i - 1] = table[i] - table[i - 1]; 193 | } 194 | diffs[lenm1] = 0.0f; 195 | } 196 | 197 | static SDL_SpinLock ResampleFilterSpinlock = 0; 198 | static float *ResamplerFilter = NULL; 199 | static float *ResamplerFilterDifference = NULL; 200 | 201 | int SDL_PrepareResampleFilter(void) { 202 | SDL_AtomicLock(&ResampleFilterSpinlock); 203 | if (!ResamplerFilter) { 204 | /* if dB > 50, beta=(0.1102 * (dB - 8.7)), according to Matlab. */ 205 | const double dB = 80.0; 206 | const double beta = 0.1102 * (dB - 8.7); 207 | const size_t alloclen = RESAMPLER_FILTER_SIZE * sizeof (float); 208 | 209 | ResamplerFilter = (float *) SDL_malloc(alloclen); 210 | if (!ResamplerFilter) { 211 | SDL_AtomicUnlock(&ResampleFilterSpinlock); 212 | return SDL_OutOfMemory(); 213 | } 214 | 215 | ResamplerFilterDifference = (float *) SDL_malloc(alloclen); 216 | if (!ResamplerFilterDifference) { 217 | SDL_free(ResamplerFilter); 218 | ResamplerFilter = NULL; 219 | SDL_AtomicUnlock(&ResampleFilterSpinlock); 220 | return SDL_OutOfMemory(); 221 | } 222 | kaiser_and_sinc(ResamplerFilter, ResamplerFilterDifference, RESAMPLER_FILTER_SIZE, beta); 223 | } 224 | SDL_AtomicUnlock(&ResampleFilterSpinlock); 225 | return 0; 226 | } 227 | 228 | static void SDL_ResetAudioStreamResampler(SDL_AudioStream *stream) 229 | { 230 | /* set all the padding to silence. */ 231 | const int len = stream->resampler_padding_samples; 232 | SDL_memset(stream->resampler_state, '\0', len * sizeof (float)); 233 | } 234 | 235 | static void SDL_CleanupAudioStreamResampler(SDL_AudioStream *stream) 236 | { 237 | SDL_free(stream->resampler_state); 238 | } 239 | 240 | /* lpadding and rpadding are expected to be buffers of (ResamplePadding(inrate, outrate) * chans * sizeof (float)) bytes. */ 241 | static int 242 | SDL_ResampleAudio(const int chans, const int inrate, const int outrate, 243 | const float *lpadding, const float *rpadding, 244 | const float *inbuf, const int inbuflen, 245 | float *outbuf, const int outbuflen) 246 | { 247 | const double finrate = (double) inrate; 248 | const double outtimeincr = 1.0 / ((float) outrate); 249 | const double ratio = ((float) outrate) / ((float) inrate); 250 | const int paddinglen = ResamplerPadding(inrate, outrate); 251 | const int framelen = chans * (int)sizeof (float); 252 | const int inframes = inbuflen / framelen; 253 | const int wantedoutframes = (int) ((inbuflen / framelen) * ratio); /* outbuflen isn't total to write, it's total available. */ 254 | const int maxoutframes = outbuflen / framelen; 255 | const int outframes = SDL_min(wantedoutframes, maxoutframes); 256 | float *dst = outbuf; 257 | double outtime = 0.0; 258 | int i, j, chan; 259 | 260 | for (i = 0; i < outframes; i++) { 261 | const int srcindex = (int) (outtime * inrate); 262 | const double intime = ((double) srcindex) / finrate; 263 | const double innexttime = ((double) (srcindex + 1)) / finrate; 264 | const double interpolation1 = 1.0 - ((innexttime - outtime) / (innexttime - intime)); 265 | const int filterindex1 = (int) (interpolation1 * RESAMPLER_SAMPLES_PER_ZERO_CROSSING); 266 | const double interpolation2 = 1.0 - interpolation1; 267 | const int filterindex2 = (int) (interpolation2 * RESAMPLER_SAMPLES_PER_ZERO_CROSSING); 268 | 269 | for (chan = 0; chan < chans; chan++) { 270 | float outsample = 0.0f; 271 | 272 | /* do this twice to calculate the sample, once for the "left wing" and then same for the right. */ 273 | /* !!! FIXME: do both wings in one loop */ 274 | for (j = 0; (filterindex1 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)) < RESAMPLER_FILTER_SIZE; j++) { 275 | const int srcframe = srcindex - j; 276 | /* !!! FIXME: we can bubble this conditional out of here by doing a pre loop. */ 277 | const float insample = (srcframe < 0) ? lpadding[((paddinglen + srcframe) * chans) + chan] : inbuf[(srcframe * chans) + chan]; 278 | outsample += (float)(insample * (ResamplerFilter[filterindex1 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)] + (interpolation1 * ResamplerFilterDifference[filterindex1 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)]))); 279 | } 280 | 281 | for (j = 0; (filterindex2 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)) < RESAMPLER_FILTER_SIZE; j++) { 282 | const int srcframe = srcindex + 1 + j; 283 | /* !!! FIXME: we can bubble this conditional out of here by doing a post loop. */ 284 | const float insample = (srcframe >= inframes) ? rpadding[((srcframe - inframes) * chans) + chan] : inbuf[(srcframe * chans) + chan]; 285 | outsample += (float)(insample * (ResamplerFilter[filterindex2 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)] + (interpolation2 * ResamplerFilterDifference[filterindex2 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)]))); 286 | } 287 | *(dst++) = outsample; 288 | } 289 | 290 | outtime += outtimeincr; 291 | } 292 | 293 | return outframes * chans * sizeof (float); 294 | } 295 | 296 | static int SDL_ResampleAudioStream(SDL_AudioStream *stream, const void *_inbuf, const int inbuflen, void *_outbuf, const int outbuflen) 297 | { 298 | const Uint8 *inbufend = ((const Uint8 *) _inbuf) + inbuflen; 299 | const float *inbuf = (const float *) _inbuf; 300 | float *outbuf = (float *) _outbuf; 301 | const int chans = (int) stream->pre_resample_channels; 302 | const int inrate = stream->src_rate; 303 | const int outrate = stream->dst_rate; 304 | const int paddingsamples = stream->resampler_padding_samples; 305 | const int paddingbytes = paddingsamples * sizeof (float); 306 | float *lpadding = (float *) stream->resampler_state; 307 | const float *rpadding = (const float *) inbufend; /* we set this up so there are valid padding samples at the end of the input buffer. */ 308 | const int cpy = SDL_min(inbuflen, paddingbytes); 309 | int retval; 310 | 311 | SDL_assert(inbuf != ((const float *) outbuf)); /* SDL_AudioStreamPut() shouldn't allow in-place resamples. */ 312 | 313 | retval = SDL_ResampleAudio(chans, inrate, outrate, lpadding, rpadding, inbuf, inbuflen, outbuf, outbuflen); 314 | 315 | /* update our left padding with end of current input, for next run. */ 316 | SDL_memcpy((lpadding + paddingsamples) - (cpy / sizeof (float)), inbufend - cpy, cpy); 317 | return retval; 318 | } 319 | 320 | void SDL_FreeAudioStream(SDL_AudioStream *stream) { 321 | if (stream) { 322 | if (stream->cleanup_resampler_func) { 323 | stream->cleanup_resampler_func(stream); 324 | } 325 | SDL_FreeDataQueue(stream->queue); 326 | SDL_free(stream->staging_buffer); 327 | SDL_free(stream->work_buffer_base); 328 | SDL_free(stream->resampler_padding); 329 | SDL_free(stream); 330 | } 331 | } 332 | 333 | SDL_AudioStream * SDL_NewAudioStream( 334 | const SDL_AudioFormat src_format, 335 | const Uint8 src_channels, 336 | const int src_rate, 337 | const SDL_AudioFormat dst_format, 338 | const Uint8 dst_channels, 339 | const int dst_rate 340 | ) { 341 | 342 | const int packetlen = 4096; /* !!! FIXME: good enough for now. */ 343 | Uint8 pre_resample_channels; 344 | SDL_AudioStream *retval; 345 | 346 | retval = (SDL_AudioStream *) SDL_calloc(1, sizeof (SDL_AudioStream)); 347 | if (!retval) { 348 | return NULL; 349 | } 350 | 351 | /* If increasing channels, do it after resampling, since we'd just 352 | do more work to resample duplicate channels. If we're decreasing, do 353 | it first so we resample the interpolated data instead of interpolating 354 | the resampled data (!!! FIXME: decide if that works in practice, though!). */ 355 | pre_resample_channels = SDL_min(src_channels, dst_channels); 356 | 357 | retval->first_run = SDL_TRUE; 358 | retval->src_sample_frame_size = (SDL_AUDIO_BITSIZE(src_format) / 8) * src_channels; 359 | retval->src_format = src_format; 360 | retval->src_channels = src_channels; 361 | retval->src_rate = src_rate; 362 | retval->dst_sample_frame_size = (SDL_AUDIO_BITSIZE(dst_format) / 8) * dst_channels; 363 | retval->dst_format = dst_format; 364 | retval->dst_channels = dst_channels; 365 | retval->dst_rate = dst_rate; 366 | retval->pre_resample_channels = pre_resample_channels; 367 | retval->packetlen = packetlen; 368 | retval->rate_incr = ((double) dst_rate) / ((double) src_rate); 369 | retval->resampler_padding_samples = ResamplerPadding(retval->src_rate, retval->dst_rate) * pre_resample_channels; 370 | retval->resampler_padding = (float *) SDL_calloc(retval->resampler_padding_samples ? retval->resampler_padding_samples : 1, sizeof (float)); 371 | 372 | if (retval->resampler_padding == NULL) { 373 | SDL_FreeAudioStream(retval); 374 | SDL_OutOfMemory(); 375 | return NULL; 376 | } 377 | 378 | retval->staging_buffer_size = ((retval->resampler_padding_samples / retval->pre_resample_channels) * retval->src_sample_frame_size); 379 | if (retval->staging_buffer_size > 0) { 380 | retval->staging_buffer = (Uint8 *) SDL_malloc(retval->staging_buffer_size); 381 | if (retval->staging_buffer == NULL) { 382 | SDL_FreeAudioStream(retval); 383 | SDL_OutOfMemory(); 384 | return NULL; 385 | } 386 | } 387 | 388 | /* Not resampling? It's an easy conversion (and maybe not even that!) */ 389 | if (src_rate == dst_rate) { 390 | retval->cvt_before_resampling.needed = SDL_FALSE; 391 | if (SDL_BuildAudioCVT(&retval->cvt_after_resampling, src_format, src_channels, dst_rate, dst_format, dst_channels, dst_rate) < 0) { 392 | SDL_FreeAudioStream(retval); 393 | return NULL; /* SDL_BuildAudioCVT should have called SDL_SetError. */ 394 | } 395 | } else { 396 | /* Don't resample at first. Just get us to Float32 format. */ 397 | /* !!! FIXME: convert to int32 on devices without hardware float. */ 398 | if (SDL_BuildAudioCVT(&retval->cvt_before_resampling, src_format, src_channels, src_rate, AUDIO_F32SYS, pre_resample_channels, src_rate) < 0) { 399 | SDL_FreeAudioStream(retval); 400 | return NULL; /* SDL_BuildAudioCVT should have called SDL_SetError. */ 401 | } 402 | 403 | if (!retval->resampler_func) { 404 | retval->resampler_state = SDL_calloc(retval->resampler_padding_samples, sizeof (float)); 405 | if (!retval->resampler_state) { 406 | SDL_FreeAudioStream(retval); 407 | SDL_OutOfMemory(); 408 | return NULL; 409 | } 410 | 411 | if (SDL_PrepareResampleFilter() < 0) { 412 | SDL_free(retval->resampler_state); 413 | retval->resampler_state = NULL; 414 | SDL_FreeAudioStream(retval); 415 | return NULL; 416 | } 417 | 418 | retval->resampler_func = SDL_ResampleAudioStream; 419 | retval->reset_resampler_func = SDL_ResetAudioStreamResampler; 420 | retval->cleanup_resampler_func = SDL_CleanupAudioStreamResampler; 421 | } 422 | 423 | /* Convert us to the final format after resampling. */ 424 | if (SDL_BuildAudioCVT(&retval->cvt_after_resampling, AUDIO_F32SYS, pre_resample_channels, dst_rate, dst_format, dst_channels, dst_rate) < 0) { 425 | SDL_FreeAudioStream(retval); 426 | return NULL; /* SDL_BuildAudioCVT should have called SDL_SetError. */ 427 | } 428 | } 429 | 430 | retval->queue = SDL_NewDataQueue(packetlen, packetlen * 2); 431 | if (!retval->queue) { 432 | SDL_FreeAudioStream(retval); 433 | return NULL; /* SDL_NewDataQueue should have called SDL_SetError. */ 434 | } 435 | 436 | return retval; 437 | } 438 | 439 | static Uint8 * EnsureStreamBufferSize(SDL_AudioStream *stream, const int newlen) { 440 | Uint8 *ptr; 441 | size_t offset; 442 | 443 | if (stream->work_buffer_len >= newlen) { 444 | ptr = stream->work_buffer_base; 445 | } else { 446 | ptr = (Uint8 *) SDL_realloc(stream->work_buffer_base, newlen + 32); 447 | if (!ptr) { 448 | SDL_OutOfMemory(); 449 | return NULL; 450 | } 451 | /* Make sure we're aligned to 16 bytes for SIMD code. */ 452 | stream->work_buffer_base = ptr; 453 | stream->work_buffer_len = newlen; 454 | } 455 | 456 | offset = ((size_t) ptr) & 15; 457 | return offset ? ptr + (16 - offset) : ptr; 458 | } 459 | 460 | static int SDL_AudioStreamPutInternal(SDL_AudioStream *stream, const void *buf, int len, int *maxputbytes) 461 | { 462 | int buflen = len; 463 | int workbuflen; 464 | Uint8 *workbuf; 465 | Uint8 *resamplebuf = NULL; 466 | int resamplebuflen = 0; 467 | int neededpaddingbytes; 468 | int paddingbytes; 469 | 470 | /* !!! FIXME: several converters can take advantage of SIMD, but only 471 | !!! FIXME: if the data is aligned to 16 bytes. EnsureStreamBufferSize() 472 | !!! FIXME: guarantees the buffer will align, but the 473 | !!! FIXME: converters will iterate over the data backwards if 474 | !!! FIXME: the output grows, and this means we won't align if buflen 475 | !!! FIXME: isn't a multiple of 16. In these cases, we should chop off 476 | !!! FIXME: a few samples at the end and convert them separately. */ 477 | 478 | /* no padding prepended on first run. */ 479 | neededpaddingbytes = stream->resampler_padding_samples * sizeof (float); 480 | paddingbytes = stream->first_run ? 0 : neededpaddingbytes; 481 | stream->first_run = SDL_FALSE; 482 | 483 | /* Make sure the work buffer can hold all the data we need at once... */ 484 | workbuflen = buflen; 485 | if (stream->cvt_before_resampling.needed) { 486 | workbuflen *= stream->cvt_before_resampling.len_mult; 487 | } 488 | 489 | if (stream->dst_rate != stream->src_rate) { 490 | /* resamples can't happen in place, so make space for second buf. */ 491 | const int framesize = stream->pre_resample_channels * sizeof (float); 492 | const int frames = workbuflen / framesize; 493 | resamplebuflen = ((int) SDL_ceil(frames * stream->rate_incr)) * framesize; 494 | workbuflen += resamplebuflen; 495 | } 496 | 497 | if (stream->cvt_after_resampling.needed) { 498 | /* !!! FIXME: buffer might be big enough already? */ 499 | workbuflen *= stream->cvt_after_resampling.len_mult; 500 | } 501 | 502 | workbuflen += neededpaddingbytes; 503 | 504 | workbuf = EnsureStreamBufferSize(stream, workbuflen); 505 | if (!workbuf) { 506 | return -1; /* probably out of memory. */ 507 | } 508 | 509 | resamplebuf = workbuf; /* default if not resampling. */ 510 | 511 | SDL_memcpy(workbuf + paddingbytes, buf, buflen); 512 | 513 | if (stream->cvt_before_resampling.needed) { 514 | stream->cvt_before_resampling.buf = workbuf + paddingbytes; 515 | stream->cvt_before_resampling.len = buflen; 516 | if (SDL_ConvertAudio(&stream->cvt_before_resampling) == -1) { 517 | return -1; /* uhoh! */ 518 | } 519 | buflen = stream->cvt_before_resampling.len_cvt; 520 | } 521 | 522 | if (stream->dst_rate != stream->src_rate) { 523 | /* save off some samples at the end; they are used for padding now so 524 | the resampler is coherent and then used at the start of the next 525 | put operation. Prepend last put operation's padding, too. */ 526 | 527 | /* prepend prior put's padding. :P */ 528 | if (paddingbytes) { 529 | SDL_memcpy(workbuf, stream->resampler_padding, paddingbytes); 530 | buflen += paddingbytes; 531 | } 532 | 533 | /* save off the data at the end for the next run. */ 534 | SDL_memcpy(stream->resampler_padding, workbuf + (buflen - neededpaddingbytes), neededpaddingbytes); 535 | 536 | resamplebuf = workbuf + buflen; /* skip to second piece of workbuf. */ 537 | SDL_assert(buflen >= neededpaddingbytes); 538 | if (buflen > neededpaddingbytes) { 539 | buflen = stream->resampler_func(stream, workbuf, buflen - neededpaddingbytes, resamplebuf, resamplebuflen); 540 | } else { 541 | buflen = 0; 542 | } 543 | } 544 | 545 | if (stream->cvt_after_resampling.needed && (buflen > 0)) { 546 | stream->cvt_after_resampling.buf = resamplebuf; 547 | stream->cvt_after_resampling.len = buflen; 548 | if (SDL_ConvertAudio(&stream->cvt_after_resampling) == -1) { 549 | return -1; /* uhoh! */ 550 | } 551 | buflen = stream->cvt_after_resampling.len_cvt; 552 | } 553 | 554 | if (maxputbytes) { 555 | const int maxbytes = *maxputbytes; 556 | if (buflen > maxbytes) 557 | buflen = maxbytes; 558 | *maxputbytes -= buflen; 559 | } 560 | 561 | /* resamplebuf holds the final output, even if we didn't resample. */ 562 | return buflen ? SDL_WriteToDataQueue(stream->queue, resamplebuf, buflen) : 0; 563 | } 564 | 565 | int SDL_AudioStreamFlush(SDL_AudioStream *stream) 566 | { 567 | if (!stream) { 568 | return SDL_InvalidParamError("stream"); 569 | } 570 | 571 | /* shouldn't use a staging buffer if we're not resampling. */ 572 | SDL_assert((stream->dst_rate != stream->src_rate) || (stream->staging_buffer_filled == 0)); 573 | 574 | if (stream->staging_buffer_filled > 0) { 575 | /* push the staging buffer + silence. We need to flush out not just 576 | the staging buffer, but the piece that the stream was saving off 577 | for right-side resampler padding. */ 578 | const SDL_bool first_run = stream->first_run; 579 | const int filled = stream->staging_buffer_filled; 580 | int actual_input_frames = filled / stream->src_sample_frame_size; 581 | if (!first_run) 582 | actual_input_frames += stream->resampler_padding_samples / stream->pre_resample_channels; 583 | 584 | if (actual_input_frames > 0) { /* don't bother if nothing to flush. */ 585 | /* This is how many bytes we're expecting without silence appended. */ 586 | int flush_remaining = ((int) SDL_ceil(actual_input_frames * stream->rate_incr)) * stream->dst_sample_frame_size; 587 | 588 | SDL_memset(stream->staging_buffer + filled, '\0', stream->staging_buffer_size - filled); 589 | if (SDL_AudioStreamPutInternal(stream, stream->staging_buffer, stream->staging_buffer_size, &flush_remaining) < 0) { 590 | return -1; 591 | } 592 | 593 | /* we have flushed out (or initially filled) the pending right-side 594 | resampler padding, but we need to push more silence to guarantee 595 | the staging buffer is fully flushed out, too. */ 596 | SDL_memset(stream->staging_buffer, '\0', filled); 597 | if (SDL_AudioStreamPutInternal(stream, stream->staging_buffer, stream->staging_buffer_size, &flush_remaining) < 0) { 598 | return -1; 599 | } 600 | } 601 | } 602 | 603 | stream->staging_buffer_filled = 0; 604 | stream->first_run = SDL_TRUE; 605 | 606 | return 0; 607 | } 608 | 609 | int SDL_AudioStreamPut(SDL_AudioStream *stream, const void *buf, int len) 610 | { 611 | /* !!! FIXME: several converters can take advantage of SIMD, but only 612 | !!! FIXME: if the data is aligned to 16 bytes. EnsureStreamBufferSize() 613 | !!! FIXME: guarantees the buffer will align, but the 614 | !!! FIXME: converters will iterate over the data backwards if 615 | !!! FIXME: the output grows, and this means we won't align if buflen 616 | !!! FIXME: isn't a multiple of 16. In these cases, we should chop off 617 | !!! FIXME: a few samples at the end and convert them separately. */ 618 | 619 | if (!stream) { 620 | return SDL_InvalidParamError("stream"); 621 | } else if (!buf) { 622 | return SDL_InvalidParamError("buf"); 623 | } else if (len == 0) { 624 | return 0; /* nothing to do. */ 625 | } else if ((len % stream->src_sample_frame_size) != 0) { 626 | return SDL_SetError("Can't add partial sample frames"); 627 | } 628 | 629 | if (!stream->cvt_before_resampling.needed && 630 | (stream->dst_rate == stream->src_rate) && 631 | !stream->cvt_after_resampling.needed) { 632 | 633 | return SDL_WriteToDataQueue(stream->queue, buf, len); 634 | } 635 | 636 | while (len > 0) { 637 | int amount; 638 | 639 | /* If we don't have a staging buffer or we're given enough data that 640 | we don't need to store it for later, skip the staging process. 641 | */ 642 | if (!stream->staging_buffer_filled && len >= stream->staging_buffer_size) { 643 | return SDL_AudioStreamPutInternal(stream, buf, len, NULL); 644 | } 645 | 646 | /* If there's not enough data to fill the staging buffer, just save it */ 647 | if ((stream->staging_buffer_filled + len) < stream->staging_buffer_size) { 648 | SDL_memcpy(stream->staging_buffer + stream->staging_buffer_filled, buf, len); 649 | stream->staging_buffer_filled += len; 650 | return 0; 651 | } 652 | 653 | /* Fill the staging buffer, process it, and continue */ 654 | amount = (stream->staging_buffer_size - stream->staging_buffer_filled); 655 | SDL_assert(amount > 0); 656 | SDL_memcpy(stream->staging_buffer + stream->staging_buffer_filled, buf, amount); 657 | stream->staging_buffer_filled = 0; 658 | if (SDL_AudioStreamPutInternal(stream, stream->staging_buffer, stream->staging_buffer_size, NULL) < 0) { 659 | return -1; 660 | } 661 | buf = (void *)((Uint8 *)buf + amount); 662 | len -= amount; 663 | } 664 | return 0; 665 | } 666 | 667 | int SDL_AudioStreamGet(SDL_AudioStream *stream, void *buf, int len) { 668 | if (!stream) { 669 | return SDL_InvalidParamError("stream"); 670 | } else if (!buf) { 671 | return SDL_InvalidParamError("buf"); 672 | } else if (len <= 0) { 673 | return 0; /* nothing to do. */ 674 | } else if ((len % stream->dst_sample_frame_size) != 0) { 675 | return SDL_SetError("Can't request partial sample frames"); 676 | } 677 | 678 | return (int) SDL_ReadFromDataQueue(stream->queue, buf, len); 679 | } 680 | 681 | int SDL_AudioStreamAvailable(SDL_AudioStream *stream) 682 | { 683 | return stream ? (int) SDL_CountDataQueue(stream->queue) : 0; 684 | } 685 | 686 | static SDL_bool SDL_SupportedAudioFormat(const SDL_AudioFormat fmt) { 687 | switch (fmt) { 688 | case AUDIO_U8: 689 | case AUDIO_S8: 690 | case AUDIO_U16LSB: 691 | case AUDIO_S16LSB: 692 | case AUDIO_U16MSB: 693 | case AUDIO_S16MSB: 694 | case AUDIO_S32LSB: 695 | case AUDIO_S32MSB: 696 | case AUDIO_F32LSB: 697 | case AUDIO_F32MSB: 698 | return SDL_TRUE; /* supported. */ 699 | 700 | default: 701 | break; 702 | } 703 | 704 | return SDL_FALSE; /* unsupported. */ 705 | } 706 | 707 | static SDL_bool SDL_SupportedChannelCount(const int channels) { 708 | switch (channels) { 709 | case 1: /* mono */ 710 | case 2: /* stereo */ 711 | case 4: /* quad */ 712 | case 6: /* 5.1 */ 713 | case 8: /* 7.1 */ 714 | return SDL_TRUE; /* supported. */ 715 | 716 | default: 717 | break; 718 | } 719 | 720 | return SDL_FALSE; /* unsupported. */ 721 | } 722 | 723 | static int SDL_AddAudioCVTFilter(SDL_AudioCVT *cvt, const SDL_AudioFilter filter) { 724 | if (cvt->filter_index >= SDL_AUDIOCVT_MAX_FILTERS) { 725 | return SDL_SetError("Too many filters needed for conversion, exceeded maximum of %d", SDL_AUDIOCVT_MAX_FILTERS); 726 | } 727 | if (filter == NULL) { 728 | return SDL_SetError("Audio filter pointer is NULL"); 729 | } 730 | cvt->filters[cvt->filter_index++] = filter; 731 | cvt->filters[cvt->filter_index] = NULL; /* Moving terminator */ 732 | return 0; 733 | } 734 | 735 | static void SDLCALL SDL_Convert_Byteswap(SDL_AudioCVT *cvt, SDL_AudioFormat format) { 736 | switch (SDL_AUDIO_BITSIZE(format)) { 737 | #define CASESWAP(b) \ 738 | case b: { \ 739 | Uint##b *ptr = (Uint##b *) cvt->buf; \ 740 | int i; \ 741 | for (i = cvt->len_cvt / sizeof (*ptr); i; --i, ++ptr) { \ 742 | *ptr = SDL_Swap##b(*ptr); \ 743 | } \ 744 | break; \ 745 | } 746 | 747 | CASESWAP(16); 748 | CASESWAP(32); 749 | CASESWAP(64); 750 | 751 | #undef CASESWAP 752 | 753 | default: SDL_assert(!"unhandled byteswap datatype!"); break; 754 | } 755 | 756 | if (cvt->filters[++cvt->filter_index]) { 757 | /* flip endian flag for data. */ 758 | if (format & SDL_AUDIO_MASK_ENDIAN) { 759 | format &= ~SDL_AUDIO_MASK_ENDIAN; 760 | } else { 761 | format |= SDL_AUDIO_MASK_ENDIAN; 762 | } 763 | cvt->filters[cvt->filter_index](cvt, format); 764 | } 765 | } 766 | 767 | static int SDL_BuildAudioTypeCVTToFloat(SDL_AudioCVT *cvt, const SDL_AudioFormat src_fmt) { 768 | int retval = 0; /* 0 == no conversion necessary. */ 769 | 770 | if ((SDL_AUDIO_ISBIGENDIAN(src_fmt) != 0) == (SDL_BYTEORDER == SDL_LIL_ENDIAN)) { 771 | if (SDL_AddAudioCVTFilter(cvt, SDL_Convert_Byteswap) < 0) { 772 | return -1; 773 | } 774 | retval = 1; /* added a converter. */ 775 | } 776 | 777 | if (!SDL_AUDIO_ISFLOAT(src_fmt)) { 778 | const Uint16 src_bitsize = SDL_AUDIO_BITSIZE(src_fmt); 779 | const Uint16 dst_bitsize = 32; 780 | SDL_AudioFilter filter = NULL; 781 | 782 | switch (src_fmt & ~SDL_AUDIO_MASK_ENDIAN) { 783 | case AUDIO_S8: filter = SDL_Convert_S8_to_F32; break; 784 | case AUDIO_U8: filter = SDL_Convert_U8_to_F32; break; 785 | case AUDIO_S16: filter = SDL_Convert_S16_to_F32; break; 786 | case AUDIO_U16: filter = SDL_Convert_U16_to_F32; break; 787 | case AUDIO_S32: filter = SDL_Convert_S32_to_F32; break; 788 | default: SDL_assert(!"Unexpected audio format!"); break; 789 | } 790 | 791 | if (!filter) { 792 | return SDL_SetError("No conversion from source format to float available"); 793 | } 794 | 795 | if (SDL_AddAudioCVTFilter(cvt, filter) < 0) { 796 | return -1; 797 | } 798 | if (src_bitsize < dst_bitsize) { 799 | const int mult = (dst_bitsize / src_bitsize); 800 | cvt->len_mult *= mult; 801 | cvt->len_ratio *= mult; 802 | } else if (src_bitsize > dst_bitsize) { 803 | cvt->len_ratio /= (src_bitsize / dst_bitsize); 804 | } 805 | 806 | retval = 1; /* added a converter. */ 807 | } 808 | 809 | return retval; 810 | } 811 | 812 | /* Convert from stereo to mono. Average left and right. */ 813 | static void SDLCALL 814 | SDL_ConvertStereoToMono(SDL_AudioCVT * cvt, SDL_AudioFormat format) 815 | { 816 | float *dst = (float *) cvt->buf; 817 | const float *src = dst; 818 | int i; 819 | 820 | SDL_assert(format == AUDIO_F32SYS); 821 | 822 | for (i = cvt->len_cvt / 8; i; --i, src += 2) { 823 | *(dst++) = (src[0] + src[1]) * 0.5f; 824 | } 825 | 826 | cvt->len_cvt /= 2; 827 | if (cvt->filters[++cvt->filter_index]) { 828 | cvt->filters[cvt->filter_index] (cvt, format); 829 | } 830 | } 831 | 832 | 833 | /* Convert from 5.1 to stereo. Average left and right, distribute center, discard LFE. */ 834 | static void SDLCALL 835 | SDL_Convert51ToStereo(SDL_AudioCVT * cvt, SDL_AudioFormat format) 836 | { 837 | float *dst = (float *) cvt->buf; 838 | const float *src = dst; 839 | int i; 840 | 841 | SDL_assert(format == AUDIO_F32SYS); 842 | 843 | /* SDL's 5.1 layout: FL+FR+FC+LFE+BL+BR */ 844 | for (i = cvt->len_cvt / (sizeof (float) * 6); i; --i, src += 6, dst += 2) { 845 | const float front_center_distributed = src[2] * 0.5f; 846 | dst[0] = (src[0] + front_center_distributed + src[4]) / 2.5f; /* left */ 847 | dst[1] = (src[1] + front_center_distributed + src[5]) / 2.5f; /* right */ 848 | } 849 | 850 | cvt->len_cvt /= 3; 851 | if (cvt->filters[++cvt->filter_index]) { 852 | cvt->filters[cvt->filter_index] (cvt, format); 853 | } 854 | } 855 | 856 | 857 | /* Convert from quad to stereo. Average left and right. */ 858 | static void SDLCALL 859 | SDL_ConvertQuadToStereo(SDL_AudioCVT * cvt, SDL_AudioFormat format) 860 | { 861 | float *dst = (float *) cvt->buf; 862 | const float *src = dst; 863 | int i; 864 | 865 | SDL_assert(format == AUDIO_F32SYS); 866 | 867 | for (i = cvt->len_cvt / (sizeof (float) * 4); i; --i, src += 4, dst += 2) { 868 | dst[0] = (src[0] + src[2]) * 0.5f; /* left */ 869 | dst[1] = (src[1] + src[3]) * 0.5f; /* right */ 870 | } 871 | 872 | cvt->len_cvt /= 2; 873 | if (cvt->filters[++cvt->filter_index]) { 874 | cvt->filters[cvt->filter_index] (cvt, format); 875 | } 876 | } 877 | 878 | 879 | /* Convert from 7.1 to 5.1. Distribute sides across front and back. */ 880 | static void SDLCALL 881 | SDL_Convert71To51(SDL_AudioCVT * cvt, SDL_AudioFormat format) 882 | { 883 | float *dst = (float *) cvt->buf; 884 | const float *src = dst; 885 | int i; 886 | 887 | SDL_assert(format == AUDIO_F32SYS); 888 | 889 | for (i = cvt->len_cvt / (sizeof (float) * 8); i; --i, src += 8, dst += 6) { 890 | const float surround_left_distributed = src[6] * 0.5f; 891 | const float surround_right_distributed = src[7] * 0.5f; 892 | dst[0] = (src[0] + surround_left_distributed) / 1.5f; /* FL */ 893 | dst[1] = (src[1] + surround_right_distributed) / 1.5f; /* FR */ 894 | dst[2] = src[2] / 1.5f; /* CC */ 895 | dst[3] = src[3] / 1.5f; /* LFE */ 896 | dst[4] = (src[4] + surround_left_distributed) / 1.5f; /* BL */ 897 | dst[5] = (src[5] + surround_right_distributed) / 1.5f; /* BR */ 898 | } 899 | 900 | cvt->len_cvt /= 8; 901 | cvt->len_cvt *= 6; 902 | if (cvt->filters[++cvt->filter_index]) { 903 | cvt->filters[cvt->filter_index] (cvt, format); 904 | } 905 | } 906 | 907 | 908 | /* Convert from 5.1 to quad. Distribute center across front, discard LFE. */ 909 | static void SDLCALL 910 | SDL_Convert51ToQuad(SDL_AudioCVT * cvt, SDL_AudioFormat format) 911 | { 912 | float *dst = (float *) cvt->buf; 913 | const float *src = dst; 914 | int i; 915 | 916 | SDL_assert(format == AUDIO_F32SYS); 917 | 918 | /* SDL's 4.0 layout: FL+FR+BL+BR */ 919 | /* SDL's 5.1 layout: FL+FR+FC+LFE+BL+BR */ 920 | for (i = cvt->len_cvt / (sizeof (float) * 6); i; --i, src += 6, dst += 4) { 921 | const float front_center_distributed = src[2] * 0.5f; 922 | dst[0] = (src[0] + front_center_distributed) / 1.5f; /* FL */ 923 | dst[1] = (src[1] + front_center_distributed) / 1.5f; /* FR */ 924 | dst[2] = src[4] / 1.5f; /* BL */ 925 | dst[3] = src[5] / 1.5f; /* BR */ 926 | } 927 | 928 | cvt->len_cvt /= 6; 929 | cvt->len_cvt *= 4; 930 | if (cvt->filters[++cvt->filter_index]) { 931 | cvt->filters[cvt->filter_index] (cvt, format); 932 | } 933 | } 934 | 935 | 936 | /* Upmix mono to stereo (by duplication) */ 937 | static void SDLCALL 938 | SDL_ConvertMonoToStereo(SDL_AudioCVT * cvt, SDL_AudioFormat format) 939 | { 940 | const float *src = (const float *) (cvt->buf + cvt->len_cvt); 941 | float *dst = (float *) (cvt->buf + cvt->len_cvt * 2); 942 | int i; 943 | 944 | SDL_assert(format == AUDIO_F32SYS); 945 | 946 | for (i = cvt->len_cvt / sizeof (float); i; --i) { 947 | src--; 948 | dst -= 2; 949 | dst[0] = dst[1] = *src; 950 | } 951 | 952 | cvt->len_cvt *= 2; 953 | if (cvt->filters[++cvt->filter_index]) { 954 | cvt->filters[cvt->filter_index] (cvt, format); 955 | } 956 | } 957 | 958 | 959 | /* Upmix stereo to a pseudo-5.1 stream */ 960 | static void SDLCALL 961 | SDL_ConvertStereoTo51(SDL_AudioCVT * cvt, SDL_AudioFormat format) 962 | { 963 | int i; 964 | float lf, rf, ce; 965 | const float *src = (const float *) (cvt->buf + cvt->len_cvt); 966 | float *dst = (float *) (cvt->buf + cvt->len_cvt * 3); 967 | 968 | SDL_assert(format == AUDIO_F32SYS); 969 | 970 | for (i = cvt->len_cvt / (sizeof(float) * 2); i; --i) { 971 | dst -= 6; 972 | src -= 2; 973 | lf = src[0]; 974 | rf = src[1]; 975 | ce = (lf + rf) * 0.5f; 976 | /* !!! FIXME: FL and FR may clip */ 977 | dst[0] = lf + (lf - ce); /* FL */ 978 | dst[1] = rf + (rf - ce); /* FR */ 979 | dst[2] = ce; /* FC */ 980 | dst[3] = 0; /* LFE (only meant for special LFE effects) */ 981 | dst[4] = lf; /* BL */ 982 | dst[5] = rf; /* BR */ 983 | } 984 | 985 | cvt->len_cvt *= 3; 986 | if (cvt->filters[++cvt->filter_index]) { 987 | cvt->filters[cvt->filter_index] (cvt, format); 988 | } 989 | } 990 | 991 | 992 | /* Upmix quad to a pseudo-5.1 stream */ 993 | static void SDLCALL 994 | SDL_ConvertQuadTo51(SDL_AudioCVT * cvt, SDL_AudioFormat format) 995 | { 996 | int i; 997 | float lf, rf, lb, rb, ce; 998 | const float *src = (const float *) (cvt->buf + cvt->len_cvt); 999 | float *dst = (float *) (cvt->buf + cvt->len_cvt * 3 / 2); 1000 | 1001 | SDL_assert(format == AUDIO_F32SYS); 1002 | SDL_assert(cvt->len_cvt % (sizeof(float) * 4) == 0); 1003 | 1004 | for (i = cvt->len_cvt / (sizeof(float) * 4); i; --i) { 1005 | dst -= 6; 1006 | src -= 4; 1007 | lf = src[0]; 1008 | rf = src[1]; 1009 | lb = src[2]; 1010 | rb = src[3]; 1011 | ce = (lf + rf) * 0.5f; 1012 | /* !!! FIXME: FL and FR may clip */ 1013 | dst[0] = lf + (lf - ce); /* FL */ 1014 | dst[1] = rf + (rf - ce); /* FR */ 1015 | dst[2] = ce; /* FC */ 1016 | dst[3] = 0; /* LFE (only meant for special LFE effects) */ 1017 | dst[4] = lb; /* BL */ 1018 | dst[5] = rb; /* BR */ 1019 | } 1020 | 1021 | cvt->len_cvt = cvt->len_cvt * 3 / 2; 1022 | if (cvt->filters[++cvt->filter_index]) { 1023 | cvt->filters[cvt->filter_index] (cvt, format); 1024 | } 1025 | } 1026 | 1027 | 1028 | /* Upmix stereo to a pseudo-4.0 stream (by duplication) */ 1029 | static void SDLCALL 1030 | SDL_ConvertStereoToQuad(SDL_AudioCVT * cvt, SDL_AudioFormat format) 1031 | { 1032 | const float *src = (const float *) (cvt->buf + cvt->len_cvt); 1033 | float *dst = (float *) (cvt->buf + cvt->len_cvt * 2); 1034 | float lf, rf; 1035 | int i; 1036 | 1037 | SDL_assert(format == AUDIO_F32SYS); 1038 | 1039 | for (i = cvt->len_cvt / (sizeof(float) * 2); i; --i) { 1040 | dst -= 4; 1041 | src -= 2; 1042 | lf = src[0]; 1043 | rf = src[1]; 1044 | dst[0] = lf; /* FL */ 1045 | dst[1] = rf; /* FR */ 1046 | dst[2] = lf; /* BL */ 1047 | dst[3] = rf; /* BR */ 1048 | } 1049 | 1050 | cvt->len_cvt *= 2; 1051 | if (cvt->filters[++cvt->filter_index]) { 1052 | cvt->filters[cvt->filter_index] (cvt, format); 1053 | } 1054 | } 1055 | 1056 | 1057 | /* Upmix 5.1 to 7.1 */ 1058 | static void SDLCALL 1059 | SDL_Convert51To71(SDL_AudioCVT * cvt, SDL_AudioFormat format) 1060 | { 1061 | float lf, rf, lb, rb, ls, rs; 1062 | int i; 1063 | const float *src = (const float *) (cvt->buf + cvt->len_cvt); 1064 | float *dst = (float *) (cvt->buf + cvt->len_cvt * 4 / 3); 1065 | 1066 | SDL_assert(format == AUDIO_F32SYS); 1067 | SDL_assert(cvt->len_cvt % (sizeof(float) * 6) == 0); 1068 | 1069 | for (i = cvt->len_cvt / (sizeof(float) * 6); i; --i) { 1070 | dst -= 8; 1071 | src -= 6; 1072 | lf = src[0]; 1073 | rf = src[1]; 1074 | lb = src[4]; 1075 | rb = src[5]; 1076 | ls = (lf + lb) * 0.5f; 1077 | rs = (rf + rb) * 0.5f; 1078 | /* !!! FIXME: these four may clip */ 1079 | lf += lf - ls; 1080 | rf += rf - ls; 1081 | lb += lb - ls; 1082 | rb += rb - ls; 1083 | dst[3] = src[3]; /* LFE */ 1084 | dst[2] = src[2]; /* FC */ 1085 | dst[7] = rs; /* SR */ 1086 | dst[6] = ls; /* SL */ 1087 | dst[5] = rb; /* BR */ 1088 | dst[4] = lb; /* BL */ 1089 | dst[1] = rf; /* FR */ 1090 | dst[0] = lf; /* FL */ 1091 | } 1092 | 1093 | cvt->len_cvt = cvt->len_cvt * 4 / 3; 1094 | 1095 | if (cvt->filters[++cvt->filter_index]) { 1096 | cvt->filters[cvt->filter_index] (cvt, format); 1097 | } 1098 | } 1099 | 1100 | static int 1101 | SDL_BuildAudioTypeCVTFromFloat(SDL_AudioCVT *cvt, const SDL_AudioFormat dst_fmt) 1102 | { 1103 | int retval = 0; /* 0 == no conversion necessary. */ 1104 | 1105 | if (!SDL_AUDIO_ISFLOAT(dst_fmt)) { 1106 | const Uint16 dst_bitsize = SDL_AUDIO_BITSIZE(dst_fmt); 1107 | const Uint16 src_bitsize = 32; 1108 | SDL_AudioFilter filter = NULL; 1109 | switch (dst_fmt & ~SDL_AUDIO_MASK_ENDIAN) { 1110 | case AUDIO_S8: filter = SDL_Convert_F32_to_S8; break; 1111 | case AUDIO_U8: filter = SDL_Convert_F32_to_U8; break; 1112 | case AUDIO_S16: filter = SDL_Convert_F32_to_S16; break; 1113 | case AUDIO_U16: filter = SDL_Convert_F32_to_U16; break; 1114 | case AUDIO_S32: filter = SDL_Convert_F32_to_S32; break; 1115 | default: SDL_assert(!"Unexpected audio format!"); break; 1116 | } 1117 | 1118 | if (!filter) { 1119 | return SDL_SetError("No conversion from float to destination format available"); 1120 | } 1121 | 1122 | if (SDL_AddAudioCVTFilter(cvt, filter) < 0) { 1123 | return -1; 1124 | } 1125 | if (src_bitsize < dst_bitsize) { 1126 | const int mult = (dst_bitsize / src_bitsize); 1127 | cvt->len_mult *= mult; 1128 | cvt->len_ratio *= mult; 1129 | } else if (src_bitsize > dst_bitsize) { 1130 | cvt->len_ratio /= (src_bitsize / dst_bitsize); 1131 | } 1132 | retval = 1; /* added a converter. */ 1133 | } 1134 | 1135 | if ((SDL_AUDIO_ISBIGENDIAN(dst_fmt) != 0) == (SDL_BYTEORDER == SDL_LIL_ENDIAN)) { 1136 | if (SDL_AddAudioCVTFilter(cvt, SDL_Convert_Byteswap) < 0) { 1137 | return -1; 1138 | } 1139 | retval = 1; /* added a converter. */ 1140 | } 1141 | 1142 | return retval; 1143 | } 1144 | 1145 | static void SDL_ResampleCVT(SDL_AudioCVT *cvt, const int chans, const SDL_AudioFormat format) { 1146 | /* !!! FIXME in 2.1: there are ten slots in the filter list, and the theoretical maximum we use is six (seven with NULL terminator). 1147 | !!! FIXME in 2.1: We need to store data for this resampler, because the cvt structure doesn't store the original sample rates, 1148 | !!! FIXME in 2.1: so we steal the ninth and tenth slot. :( */ 1149 | const int inrate = (int) (size_t) cvt->filters[SDL_AUDIOCVT_MAX_FILTERS-1]; 1150 | const int outrate = (int) (size_t) cvt->filters[SDL_AUDIOCVT_MAX_FILTERS]; 1151 | const float *src = (const float *) cvt->buf; 1152 | const int srclen = cvt->len_cvt; 1153 | /*float *dst = (float *) cvt->buf; 1154 | const int dstlen = (cvt->len * cvt->len_mult);*/ 1155 | /* !!! FIXME: remove this if we can get the resampler to work in-place again. */ 1156 | float *dst = (float *) (cvt->buf + srclen); 1157 | const int dstlen = (cvt->len * cvt->len_mult) - srclen; 1158 | const int requestedpadding = ResamplerPadding(inrate, outrate); 1159 | int paddingsamples; 1160 | float *padding; 1161 | 1162 | if (requestedpadding < SDL_MAX_SINT32 / chans) { 1163 | paddingsamples = requestedpadding * chans; 1164 | } else { 1165 | paddingsamples = 0; 1166 | } 1167 | SDL_assert(format == AUDIO_F32SYS); 1168 | 1169 | /* we keep no streaming state here, so pad with silence on both ends. */ 1170 | padding = (float *) SDL_calloc(paddingsamples ? paddingsamples : 1, sizeof (float)); 1171 | if (!padding) { 1172 | SDL_OutOfMemory(); 1173 | return; 1174 | } 1175 | 1176 | cvt->len_cvt = SDL_ResampleAudio(chans, inrate, outrate, padding, padding, src, srclen, dst, dstlen); 1177 | 1178 | SDL_free(padding); 1179 | 1180 | SDL_memmove(cvt->buf, dst, cvt->len_cvt); /* !!! FIXME: remove this if we can get the resampler to work in-place again. */ 1181 | 1182 | if (cvt->filters[++cvt->filter_index]) { 1183 | cvt->filters[cvt->filter_index](cvt, format); 1184 | } 1185 | } 1186 | 1187 | /* !!! FIXME: We only have this macro salsa because SDL_AudioCVT doesn't 1188 | !!! FIXME: store channel info, so we have to have function entry 1189 | !!! FIXME: points for each supported channel count and multiple 1190 | !!! FIXME: vs arbitrary. When we rev the ABI, clean this up. */ 1191 | #define RESAMPLER_FUNCS(chans) \ 1192 | static void SDLCALL \ 1193 | SDL_ResampleCVT_c##chans(SDL_AudioCVT *cvt, SDL_AudioFormat format) { \ 1194 | SDL_ResampleCVT(cvt, chans, format); \ 1195 | } 1196 | RESAMPLER_FUNCS(1) 1197 | RESAMPLER_FUNCS(2) 1198 | RESAMPLER_FUNCS(4) 1199 | RESAMPLER_FUNCS(6) 1200 | RESAMPLER_FUNCS(8) 1201 | #undef RESAMPLER_FUNCS 1202 | 1203 | static SDL_AudioFilter ChooseCVTResampler(const int dst_channels) { 1204 | switch (dst_channels) { 1205 | case 1: return SDL_ResampleCVT_c1; 1206 | case 2: return SDL_ResampleCVT_c2; 1207 | case 4: return SDL_ResampleCVT_c4; 1208 | case 6: return SDL_ResampleCVT_c6; 1209 | case 8: return SDL_ResampleCVT_c8; 1210 | default: break; 1211 | } 1212 | 1213 | return NULL; 1214 | } 1215 | 1216 | static int 1217 | SDL_BuildAudioResampleCVT(SDL_AudioCVT * cvt, const int dst_channels, 1218 | const int src_rate, const int dst_rate) 1219 | { 1220 | SDL_AudioFilter filter; 1221 | 1222 | if (src_rate == dst_rate) { 1223 | return 0; /* no conversion necessary. */ 1224 | } 1225 | 1226 | filter = ChooseCVTResampler(dst_channels); 1227 | if (filter == NULL) { 1228 | return SDL_SetError("No conversion available for these rates"); 1229 | } 1230 | 1231 | if (SDL_PrepareResampleFilter() < 0) { 1232 | return -1; 1233 | } 1234 | 1235 | /* Update (cvt) with filter details... */ 1236 | if (SDL_AddAudioCVTFilter(cvt, filter) < 0) { 1237 | return -1; 1238 | } 1239 | 1240 | /* !!! FIXME in 2.1: there are ten slots in the filter list, and the theoretical maximum we use is six (seven with NULL terminator). 1241 | !!! FIXME in 2.1: We need to store data for this resampler, because the cvt structure doesn't store the original sample rates, 1242 | !!! FIXME in 2.1: so we steal the ninth and tenth slot. :( */ 1243 | if (cvt->filter_index >= (SDL_AUDIOCVT_MAX_FILTERS-2)) { 1244 | return SDL_SetError("Too many filters needed for conversion, exceeded maximum of %d", SDL_AUDIOCVT_MAX_FILTERS-2); 1245 | } 1246 | cvt->filters[SDL_AUDIOCVT_MAX_FILTERS-1] = (SDL_AudioFilter) (size_t) src_rate; 1247 | cvt->filters[SDL_AUDIOCVT_MAX_FILTERS] = (SDL_AudioFilter) (size_t) dst_rate; 1248 | 1249 | if (src_rate < dst_rate) { 1250 | const double mult = ((double) dst_rate) / ((double) src_rate); 1251 | cvt->len_mult *= (int) SDL_ceil(mult); 1252 | cvt->len_ratio *= mult; 1253 | } else { 1254 | cvt->len_ratio /= ((double) src_rate) / ((double) dst_rate); 1255 | } 1256 | 1257 | /* !!! FIXME: remove this if we can get the resampler to work in-place again. */ 1258 | /* the buffer is big enough to hold the destination now, but 1259 | we need it large enough to hold a separate scratch buffer. */ 1260 | cvt->len_mult *= 2; 1261 | 1262 | return 1; /* added a converter. */ 1263 | } 1264 | 1265 | int SDL_BuildAudioCVT(SDL_AudioCVT * cvt, SDL_AudioFormat src_fmt, Uint8 src_channels, int src_rate, 1266 | SDL_AudioFormat dst_fmt, Uint8 dst_channels, int dst_rate) { 1267 | 1268 | /* Sanity check target pointer */ 1269 | if (cvt == NULL) { 1270 | return SDL_InvalidParamError("cvt"); 1271 | } 1272 | 1273 | /* Make sure we zero out the audio conversion before error checking */ 1274 | SDL_zerop(cvt); 1275 | 1276 | if (!SDL_SupportedAudioFormat(src_fmt)) { 1277 | fprintf(stderr, "%0x", src_fmt); 1278 | return SDL_SetError("Invalid source format"); 1279 | } else if (!SDL_SupportedAudioFormat(dst_fmt)) { 1280 | return SDL_SetError("Invalid destination format"); 1281 | } else if (!SDL_SupportedChannelCount(src_channels)) { 1282 | return SDL_SetError("Invalid source channels"); 1283 | } else if (!SDL_SupportedChannelCount(dst_channels)) { 1284 | return SDL_SetError("Invalid destination channels"); 1285 | } else if (src_rate == 0) { 1286 | return SDL_SetError("Source rate is zero"); 1287 | } else if (dst_rate == 0) { 1288 | return SDL_SetError("Destination rate is zero"); 1289 | } 1290 | 1291 | /* Start off with no conversion necessary */ 1292 | cvt->src_format = src_fmt; 1293 | cvt->dst_format = dst_fmt; 1294 | cvt->needed = 0; 1295 | cvt->filter_index = 0; 1296 | SDL_zero(cvt->filters); 1297 | cvt->len_mult = 1; 1298 | cvt->len_ratio = 1.0; 1299 | cvt->rate_incr = ((double) dst_rate) / ((double) src_rate); 1300 | 1301 | /* Type conversion goes like this now: 1302 | - byteswap to CPU native format first if necessary. 1303 | - convert to native Float32 if necessary. 1304 | - resample and change channel count if necessary. 1305 | - convert back to native format. 1306 | - byteswap back to foreign format if necessary. 1307 | The expectation is we can process data faster in float32 1308 | (possibly with SIMD), and making several passes over the same 1309 | buffer is likely to be CPU cache-friendly, avoiding the 1310 | biggest performance hit in modern times. Previously we had 1311 | (script-generated) custom converters for every data type and 1312 | it was a bloat on SDL compile times and final library size. */ 1313 | 1314 | /* see if we can skip float conversion entirely. */ 1315 | if (src_rate == dst_rate && src_channels == dst_channels) { 1316 | if (src_fmt == dst_fmt) { 1317 | return 0; 1318 | } 1319 | 1320 | /* just a byteswap needed? */ 1321 | if ((src_fmt & ~SDL_AUDIO_MASK_ENDIAN) == (dst_fmt & ~SDL_AUDIO_MASK_ENDIAN)) { 1322 | if (SDL_AddAudioCVTFilter(cvt, SDL_Convert_Byteswap) < 0) { 1323 | return -1; 1324 | } 1325 | cvt->needed = 1; 1326 | return 1; 1327 | } 1328 | } 1329 | 1330 | /* Convert data types, if necessary. Updates (cvt). */ 1331 | if (SDL_BuildAudioTypeCVTToFloat(cvt, src_fmt) < 0) { 1332 | return -1; /* shouldn't happen, but just in case... */ 1333 | } 1334 | 1335 | /* Channel conversion */ 1336 | if (src_channels < dst_channels) { 1337 | /* Upmixing */ 1338 | /* Mono -> Stereo [-> ...] */ 1339 | if ((src_channels == 1) && (dst_channels > 1)) { 1340 | if (SDL_AddAudioCVTFilter(cvt, SDL_ConvertMonoToStereo) < 0) { 1341 | return -1; 1342 | } 1343 | cvt->len_mult *= 2; 1344 | src_channels = 2; 1345 | cvt->len_ratio *= 2; 1346 | } 1347 | /* [Mono ->] Stereo -> 5.1 [-> 7.1] */ 1348 | if ((src_channels == 2) && (dst_channels >= 6)) { 1349 | if (SDL_AddAudioCVTFilter(cvt, SDL_ConvertStereoTo51) < 0) { 1350 | return -1; 1351 | } 1352 | src_channels = 6; 1353 | cvt->len_mult *= 3; 1354 | cvt->len_ratio *= 3; 1355 | } 1356 | /* Quad -> 5.1 [-> 7.1] */ 1357 | if ((src_channels == 4) && (dst_channels >= 6)) { 1358 | if (SDL_AddAudioCVTFilter(cvt, SDL_ConvertQuadTo51) < 0) { 1359 | return -1; 1360 | } 1361 | src_channels = 6; 1362 | cvt->len_mult = (cvt->len_mult * 3 + 1) / 2; 1363 | cvt->len_ratio *= 1.5; 1364 | } 1365 | /* [[Mono ->] Stereo ->] 5.1 -> 7.1 */ 1366 | if ((src_channels == 6) && (dst_channels == 8)) { 1367 | if (SDL_AddAudioCVTFilter(cvt, SDL_Convert51To71) < 0) { 1368 | return -1; 1369 | } 1370 | src_channels = 8; 1371 | cvt->len_mult = (cvt->len_mult * 4 + 2) / 3; 1372 | /* Should be numerically exact with every valid input to this 1373 | function */ 1374 | cvt->len_ratio = cvt->len_ratio * 4 / 3; 1375 | } 1376 | /* [Mono ->] Stereo -> Quad */ 1377 | if ((src_channels == 2) && (dst_channels == 4)) { 1378 | if (SDL_AddAudioCVTFilter(cvt, SDL_ConvertStereoToQuad) < 0) { 1379 | return -1; 1380 | } 1381 | src_channels = 4; 1382 | cvt->len_mult *= 2; 1383 | cvt->len_ratio *= 2; 1384 | } 1385 | } else if (src_channels > dst_channels) { 1386 | /* Downmixing */ 1387 | /* 7.1 -> 5.1 [-> Stereo [-> Mono]] */ 1388 | /* 7.1 -> 5.1 [-> Quad] */ 1389 | if ((src_channels == 8) && (dst_channels <= 6)) { 1390 | if (SDL_AddAudioCVTFilter(cvt, SDL_Convert71To51) < 0) { 1391 | return -1; 1392 | } 1393 | src_channels = 6; 1394 | cvt->len_ratio *= 0.75; 1395 | } 1396 | /* [7.1 ->] 5.1 -> Stereo [-> Mono] */ 1397 | if ((src_channels == 6) && (dst_channels <= 2)) { 1398 | if (SDL_AddAudioCVTFilter(cvt, SDL_Convert51ToStereo) < 0) { 1399 | return -1; 1400 | } 1401 | src_channels = 2; 1402 | cvt->len_ratio /= 3; 1403 | } 1404 | /* 5.1 -> Quad */ 1405 | if ((src_channels == 6) && (dst_channels == 4)) { 1406 | if (SDL_AddAudioCVTFilter(cvt, SDL_Convert51ToQuad) < 0) { 1407 | return -1; 1408 | } 1409 | src_channels = 4; 1410 | cvt->len_ratio = cvt->len_ratio * 2 / 3; 1411 | } 1412 | /* Quad -> Stereo [-> Mono] */ 1413 | if ((src_channels == 4) && (dst_channels <= 2)) { 1414 | if (SDL_AddAudioCVTFilter(cvt, SDL_ConvertQuadToStereo) < 0) { 1415 | return -1; 1416 | } 1417 | src_channels = 2; 1418 | cvt->len_ratio /= 2; 1419 | } 1420 | /* [... ->] Stereo -> Mono */ 1421 | if ((src_channels == 2) && (dst_channels == 1)) { 1422 | SDL_AudioFilter filter = NULL; 1423 | 1424 | filter = SDL_ConvertStereoToMono; 1425 | 1426 | if (SDL_AddAudioCVTFilter(cvt, filter) < 0) { 1427 | return -1; 1428 | } 1429 | 1430 | src_channels = 1; 1431 | cvt->len_ratio /= 2; 1432 | } 1433 | } 1434 | 1435 | if (src_channels != dst_channels) { 1436 | /* All combinations of supported channel counts should have been 1437 | handled by now, but let's be defensive */ 1438 | return SDL_SetError("Invalid channel combination"); 1439 | } 1440 | 1441 | /* Do rate conversion, if necessary. Updates (cvt). */ 1442 | if (SDL_BuildAudioResampleCVT(cvt, dst_channels, src_rate, dst_rate) < 0) { 1443 | return -1; /* shouldn't happen, but just in case... */ 1444 | } 1445 | 1446 | /* Move to final data type. */ 1447 | if (SDL_BuildAudioTypeCVTFromFloat(cvt, dst_fmt) < 0) { 1448 | return -1; /* shouldn't happen, but just in case... */ 1449 | } 1450 | 1451 | cvt->needed = (cvt->filter_index != 0); 1452 | return (cvt->needed); 1453 | } 1454 | 1455 | int SDL_ConvertAudio(SDL_AudioCVT * cvt) 1456 | { 1457 | /* !!! FIXME: (cvt) should be const; stack-copy it here. */ 1458 | /* !!! FIXME: (actually, we can't...len_cvt needs to be updated. Grr.) */ 1459 | 1460 | /* Make sure there's data to convert */ 1461 | if (cvt->buf == NULL) { 1462 | return SDL_SetError("No buffer allocated for conversion"); 1463 | } 1464 | 1465 | /* Return okay if no conversion is necessary */ 1466 | cvt->len_cvt = cvt->len; 1467 | if (cvt->filters[0] == NULL) { 1468 | return 0; 1469 | } 1470 | 1471 | /* Set up the conversion and go! */ 1472 | cvt->filter_index = 0; 1473 | cvt->filters[0] (cvt, cvt->src_format); 1474 | return 0; 1475 | } 1476 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(ALdc) 2 | 3 | 4 | add_library( 5 | ALdc 6 | AL/aldc.c 7 | AL/mojoal.c 8 | AL/private/converters.c 9 | AL/private/data_queue.c 10 | AL/private/device.c 11 | AL/private/errors.c 12 | ) 13 | 14 | add_executable(basic samples/basic/main.c) 15 | target_link_libraries(basic ALdc m) 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Luke Benstead 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # KallistiOS ##version## 2 | # 3 | # kos-ports/libgl Makefile 4 | # Copyright (C) 2013, 2014 Josh Pearson 5 | # Copyright (C) 2014 Lawrence Sebald 6 | # Copyright (C) 2018 Luke Benstead 7 | 8 | TARGET = libAL.a 9 | OBJS = AL/mojoal.o AL/aldc.o AL/alut.o 10 | 11 | SUBDIRS = 12 | 13 | KOS_CFLAGS += -ffast-math -O3 -Iinclude -Wall -Werror 14 | 15 | link: 16 | $(KOS_AR) rcs $(TARGET) $(OBJS) 17 | 18 | build: $(OBJS) link 19 | 20 | 21 | samples: build 22 | $(KOS_MAKE) -C samples all 23 | 24 | defaultall: create_kos_link $(OBJS) subdirs linklib samples 25 | 26 | include $(KOS_BASE)/addons/Makefile.prefab 27 | 28 | # creates the kos link to the headers 29 | create_kos_link: 30 | rm -f ../include/AL 31 | ln -s ../ALdc/include/AL ../include/ 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ALdc is a port of MojoAL to the Dreamcast. It's been achieved by porting the necessary parts of SDL2 and then writing a custom SDL audio device which sends the stream in to the Kallistios snd_stream code. It supports core OpenAL 1.1 and seems to work really well! 2 | 3 | This library (along with GLdc) is part of the Simulant engine project and was necessary to get Simulant's audio functionality working on the Dreamcast. 4 | 5 | ALdc inherits the zlib licensing of upstream MojoAL and SDL 2 (GLdc is MIT, Simulant is LGPL/proprietary) which means you can legally ship it compiled into Dreamcast binaries. 6 | 7 | Huge thanks to Ryan C. Gordon for MojoAL, and special thanks to mrneo240 for solving the buffering issues I was having, as well as his streaming sample contribution. Finally big shout out to everyone on the Simulant Discord who helped test on various emulators! -------------------------------------------------------------------------------- /dc-build.sh: -------------------------------------------------------------------------------- 1 | docker run -v `pwd`:/libAL:Z kazade/dreamcast-sdk /bin/sh -c "source /etc/bash.bashrc; cd /libAL; make clean && make samples" 2 | -------------------------------------------------------------------------------- /include/AL/al.h: -------------------------------------------------------------------------------- 1 | #ifndef AL_AL_H 2 | #define AL_AL_H 3 | 4 | #if defined(__cplusplus) 5 | extern "C" { 6 | #endif 7 | 8 | #ifndef AL_API 9 | #if defined(AL_LIBTYPE_STATIC) 10 | #define AL_API 11 | #elif defined(_WIN32) 12 | #define AL_API __declspec(dllimport) 13 | #else 14 | #define AL_API extern 15 | #endif 16 | #endif 17 | 18 | #if defined(_WIN32) 19 | #define AL_APIENTRY __cdecl 20 | #else 21 | #define AL_APIENTRY 22 | #endif 23 | 24 | 25 | /** Deprecated macro. */ 26 | #define OPENAL 27 | #define ALAPI AL_API 28 | #define ALAPIENTRY AL_APIENTRY 29 | #define AL_INVALID (-1) 30 | #define AL_ILLEGAL_ENUM AL_INVALID_ENUM 31 | #define AL_ILLEGAL_COMMAND AL_INVALID_OPERATION 32 | 33 | /** Supported AL version. */ 34 | #define AL_VERSION_1_0 35 | #define AL_VERSION_1_1 36 | 37 | /** 8-bit boolean */ 38 | typedef char ALboolean; 39 | 40 | /** character */ 41 | typedef char ALchar; 42 | 43 | /** signed 8-bit 2's complement integer */ 44 | typedef signed char ALbyte; 45 | 46 | /** unsigned 8-bit integer */ 47 | typedef unsigned char ALubyte; 48 | 49 | /** signed 16-bit 2's complement integer */ 50 | typedef short ALshort; 51 | 52 | /** unsigned 16-bit integer */ 53 | typedef unsigned short ALushort; 54 | 55 | /** signed 32-bit 2's complement integer */ 56 | typedef int ALint; 57 | 58 | /** unsigned 32-bit integer */ 59 | typedef unsigned int ALuint; 60 | 61 | /** non-negative 32-bit binary integer size */ 62 | typedef int ALsizei; 63 | 64 | /** enumerated 32-bit value */ 65 | typedef int ALenum; 66 | 67 | /** 32-bit IEEE754 floating-point */ 68 | typedef float ALfloat; 69 | 70 | /** 64-bit IEEE754 floating-point */ 71 | typedef double ALdouble; 72 | 73 | /** void type (for opaque pointers only) */ 74 | typedef void ALvoid; 75 | 76 | 77 | /* Enumerant values begin at column 50. No tabs. */ 78 | 79 | /** "no distance model" or "no buffer" */ 80 | #define AL_NONE 0 81 | 82 | /** Boolean False. */ 83 | #define AL_FALSE 0 84 | 85 | /** Boolean True. */ 86 | #define AL_TRUE 1 87 | 88 | 89 | /** 90 | * Relative source. 91 | * Type: ALboolean 92 | * Range: [AL_TRUE, AL_FALSE] 93 | * Default: AL_FALSE 94 | * 95 | * Specifies if the Source has relative coordinates. 96 | */ 97 | #define AL_SOURCE_RELATIVE 0x202 98 | 99 | 100 | /** 101 | * Inner cone angle, in degrees. 102 | * Type: ALint, ALfloat 103 | * Range: [0 - 360] 104 | * Default: 360 105 | * 106 | * The angle covered by the inner cone, where the source will not attenuate. 107 | */ 108 | #define AL_CONE_INNER_ANGLE 0x1001 109 | 110 | /** 111 | * Outer cone angle, in degrees. 112 | * Range: [0 - 360] 113 | * Default: 360 114 | * 115 | * The angle covered by the outer cone, where the source will be fully 116 | * attenuated. 117 | */ 118 | #define AL_CONE_OUTER_ANGLE 0x1002 119 | 120 | /** 121 | * Source pitch. 122 | * Type: ALfloat 123 | * Range: [0.5 - 2.0] 124 | * Default: 1.0 125 | * 126 | * A multiplier for the frequency (sample rate) of the source's buffer. 127 | */ 128 | #define AL_PITCH 0x1003 129 | 130 | /** 131 | * Source or listener position. 132 | * Type: ALfloat[3], ALint[3] 133 | * Default: {0, 0, 0} 134 | * 135 | * The source or listener location in three dimensional space. 136 | * 137 | * OpenAL, like OpenGL, uses a right handed coordinate system, where in a 138 | * frontal default view X (thumb) points right, Y points up (index finger), and 139 | * Z points towards the viewer/camera (middle finger). 140 | * 141 | * To switch from a left handed coordinate system, flip the sign on the Z 142 | * coordinate. 143 | */ 144 | #define AL_POSITION 0x1004 145 | 146 | /** 147 | * Source direction. 148 | * Type: ALfloat[3], ALint[3] 149 | * Default: {0, 0, 0} 150 | * 151 | * Specifies the current direction in local space. 152 | * A zero-length vector specifies an omni-directional source (cone is ignored). 153 | */ 154 | #define AL_DIRECTION 0x1005 155 | 156 | /** 157 | * Source or listener velocity. 158 | * Type: ALfloat[3], ALint[3] 159 | * Default: {0, 0, 0} 160 | * 161 | * Specifies the current velocity in local space. 162 | */ 163 | #define AL_VELOCITY 0x1006 164 | 165 | /** 166 | * Source looping. 167 | * Type: ALboolean 168 | * Range: [AL_TRUE, AL_FALSE] 169 | * Default: AL_FALSE 170 | * 171 | * Specifies whether source is looping. 172 | */ 173 | #define AL_LOOPING 0x1007 174 | 175 | /** 176 | * Source buffer. 177 | * Type: ALuint 178 | * Range: any valid Buffer. 179 | * 180 | * Specifies the buffer to provide sound samples. 181 | */ 182 | #define AL_BUFFER 0x1009 183 | 184 | /** 185 | * Source or listener gain. 186 | * Type: ALfloat 187 | * Range: [0.0 - ] 188 | * 189 | * A value of 1.0 means unattenuated. Each division by 2 equals an attenuation 190 | * of about -6dB. Each multiplicaton by 2 equals an amplification of about 191 | * +6dB. 192 | * 193 | * A value of 0.0 is meaningless with respect to a logarithmic scale; it is 194 | * silent. 195 | */ 196 | #define AL_GAIN 0x100A 197 | 198 | /** 199 | * Minimum source gain. 200 | * Type: ALfloat 201 | * Range: [0.0 - 1.0] 202 | * 203 | * The minimum gain allowed for a source, after distance and cone attenation is 204 | * applied (if applicable). 205 | */ 206 | #define AL_MIN_GAIN 0x100D 207 | 208 | /** 209 | * Maximum source gain. 210 | * Type: ALfloat 211 | * Range: [0.0 - 1.0] 212 | * 213 | * The maximum gain allowed for a source, after distance and cone attenation is 214 | * applied (if applicable). 215 | */ 216 | #define AL_MAX_GAIN 0x100E 217 | 218 | /** 219 | * Listener orientation. 220 | * Type: ALfloat[6] 221 | * Default: {0.0, 0.0, -1.0, 0.0, 1.0, 0.0} 222 | * 223 | * Effectively two three dimensional vectors. The first vector is the front (or 224 | * "at") and the second is the top (or "up"). 225 | * 226 | * Both vectors are in local space. 227 | */ 228 | #define AL_ORIENTATION 0x100F 229 | 230 | /** 231 | * Source state (query only). 232 | * Type: ALint 233 | * Range: [AL_INITIAL, AL_PLAYING, AL_PAUSED, AL_STOPPED] 234 | */ 235 | #define AL_SOURCE_STATE 0x1010 236 | 237 | /** Source state value. */ 238 | #define AL_INITIAL 0x1011 239 | #define AL_PLAYING 0x1012 240 | #define AL_PAUSED 0x1013 241 | #define AL_STOPPED 0x1014 242 | 243 | /** 244 | * Source Buffer Queue size (query only). 245 | * Type: ALint 246 | * 247 | * The number of buffers queued using alSourceQueueBuffers, minus the buffers 248 | * removed with alSourceUnqueueBuffers. 249 | */ 250 | #define AL_BUFFERS_QUEUED 0x1015 251 | 252 | /** 253 | * Source Buffer Queue processed count (query only). 254 | * Type: ALint 255 | * 256 | * The number of queued buffers that have been fully processed, and can be 257 | * removed with alSourceUnqueueBuffers. 258 | * 259 | * Looping sources will never fully process buffers because they will be set to 260 | * play again for when the source loops. 261 | */ 262 | #define AL_BUFFERS_PROCESSED 0x1016 263 | 264 | /** 265 | * Source reference distance. 266 | * Type: ALfloat 267 | * Range: [0.0 - ] 268 | * Default: 1.0 269 | * 270 | * The distance in units that no attenuation occurs. 271 | * 272 | * At 0.0, no distance attenuation ever occurs on non-linear attenuation models. 273 | */ 274 | #define AL_REFERENCE_DISTANCE 0x1020 275 | 276 | /** 277 | * Source rolloff factor. 278 | * Type: ALfloat 279 | * Range: [0.0 - ] 280 | * Default: 1.0 281 | * 282 | * Multiplier to exaggerate or diminish distance attenuation. 283 | * 284 | * At 0.0, no distance attenuation ever occurs. 285 | */ 286 | #define AL_ROLLOFF_FACTOR 0x1021 287 | 288 | /** 289 | * Outer cone gain. 290 | * Type: ALfloat 291 | * Range: [0.0 - 1.0] 292 | * Default: 0.0 293 | * 294 | * The gain attenuation applied when the listener is outside of the source's 295 | * outer cone. 296 | */ 297 | #define AL_CONE_OUTER_GAIN 0x1022 298 | 299 | /** 300 | * Source maximum distance. 301 | * Type: ALfloat 302 | * Range: [0.0 - ] 303 | * Default: +inf 304 | * 305 | * The distance above which the source is not attenuated any further with a 306 | * clamped distance model, or where attenuation reaches 0.0 gain for linear 307 | * distance models with a default rolloff factor. 308 | */ 309 | #define AL_MAX_DISTANCE 0x1023 310 | 311 | /** Source buffer position, in seconds */ 312 | #define AL_SEC_OFFSET 0x1024 313 | /** Source buffer position, in sample frames */ 314 | #define AL_SAMPLE_OFFSET 0x1025 315 | /** Source buffer position, in bytes */ 316 | #define AL_BYTE_OFFSET 0x1026 317 | 318 | /** 319 | * Source type (query only). 320 | * Type: ALint 321 | * Range: [AL_STATIC, AL_STREAMING, AL_UNDETERMINED] 322 | * 323 | * A Source is Static if a Buffer has been attached using AL_BUFFER. 324 | * 325 | * A Source is Streaming if one or more Buffers have been attached using 326 | * alSourceQueueBuffers. 327 | * 328 | * A Source is Undetermined when it has the NULL buffer attached using 329 | * AL_BUFFER. 330 | */ 331 | #define AL_SOURCE_TYPE 0x1027 332 | 333 | /** Source type value. */ 334 | #define AL_STATIC 0x1028 335 | #define AL_STREAMING 0x1029 336 | #define AL_UNDETERMINED 0x1030 337 | 338 | /** Buffer format specifier. */ 339 | #define AL_FORMAT_MONO8 0x1100 340 | #define AL_FORMAT_MONO16 0x1101 341 | #define AL_FORMAT_STEREO8 0x1102 342 | #define AL_FORMAT_STEREO16 0x1103 343 | 344 | /** Buffer frequency (query only). */ 345 | #define AL_FREQUENCY 0x2001 346 | /** Buffer bits per sample (query only). */ 347 | #define AL_BITS 0x2002 348 | /** Buffer channel count (query only). */ 349 | #define AL_CHANNELS 0x2003 350 | /** Buffer data size (query only). */ 351 | #define AL_SIZE 0x2004 352 | 353 | /** 354 | * Buffer state. 355 | * 356 | * Not for public use. 357 | */ 358 | #define AL_UNUSED 0x2010 359 | #define AL_PENDING 0x2011 360 | #define AL_PROCESSED 0x2012 361 | 362 | 363 | /** No error. */ 364 | #define AL_NO_ERROR 0 365 | 366 | /** Invalid name paramater passed to AL call. */ 367 | #define AL_INVALID_NAME 0xA001 368 | 369 | /** Invalid enum parameter passed to AL call. */ 370 | #define AL_INVALID_ENUM 0xA002 371 | 372 | /** Invalid value parameter passed to AL call. */ 373 | #define AL_INVALID_VALUE 0xA003 374 | 375 | /** Illegal AL call. */ 376 | #define AL_INVALID_OPERATION 0xA004 377 | 378 | /** Not enough memory. */ 379 | #define AL_OUT_OF_MEMORY 0xA005 380 | 381 | 382 | /** Context string: Vendor ID. */ 383 | #define AL_VENDOR 0xB001 384 | /** Context string: Version. */ 385 | #define AL_VERSION 0xB002 386 | /** Context string: Renderer ID. */ 387 | #define AL_RENDERER 0xB003 388 | /** Context string: Space-separated extension list. */ 389 | #define AL_EXTENSIONS 0xB004 390 | 391 | 392 | /** 393 | * Doppler scale. 394 | * Type: ALfloat 395 | * Range: [0.0 - ] 396 | * Default: 1.0 397 | * 398 | * Scale for source and listener velocities. 399 | */ 400 | #define AL_DOPPLER_FACTOR 0xC000 401 | AL_API void AL_APIENTRY alDopplerFactor(ALfloat value); 402 | 403 | /** 404 | * Doppler velocity (deprecated). 405 | * 406 | * A multiplier applied to the Speed of Sound. 407 | */ 408 | #define AL_DOPPLER_VELOCITY 0xC001 409 | AL_API void AL_APIENTRY alDopplerVelocity(ALfloat value); 410 | 411 | /** 412 | * Speed of Sound, in units per second. 413 | * Type: ALfloat 414 | * Range: [0.0001 - ] 415 | * Default: 343.3 416 | * 417 | * The speed at which sound waves are assumed to travel, when calculating the 418 | * doppler effect. 419 | */ 420 | #define AL_SPEED_OF_SOUND 0xC003 421 | AL_API void AL_APIENTRY alSpeedOfSound(ALfloat value); 422 | 423 | /** 424 | * Distance attenuation model. 425 | * Type: ALint 426 | * Range: [AL_NONE, AL_INVERSE_DISTANCE, AL_INVERSE_DISTANCE_CLAMPED, 427 | * AL_LINEAR_DISTANCE, AL_LINEAR_DISTANCE_CLAMPED, 428 | * AL_EXPONENT_DISTANCE, AL_EXPONENT_DISTANCE_CLAMPED] 429 | * Default: AL_INVERSE_DISTANCE_CLAMPED 430 | * 431 | * The model by which sources attenuate with distance. 432 | * 433 | * None - No distance attenuation. 434 | * Inverse - Doubling the distance halves the source gain. 435 | * Linear - Linear gain scaling between the reference and max distances. 436 | * Exponent - Exponential gain dropoff. 437 | * 438 | * Clamped variations work like the non-clamped counterparts, except the 439 | * distance calculated is clamped between the reference and max distances. 440 | */ 441 | #define AL_DISTANCE_MODEL 0xD000 442 | AL_API void AL_APIENTRY alDistanceModel(ALenum distanceModel); 443 | 444 | /** Distance model value. */ 445 | #define AL_INVERSE_DISTANCE 0xD001 446 | #define AL_INVERSE_DISTANCE_CLAMPED 0xD002 447 | #define AL_LINEAR_DISTANCE 0xD003 448 | #define AL_LINEAR_DISTANCE_CLAMPED 0xD004 449 | #define AL_EXPONENT_DISTANCE 0xD005 450 | #define AL_EXPONENT_DISTANCE_CLAMPED 0xD006 451 | 452 | /** Renderer State management. */ 453 | AL_API void AL_APIENTRY alEnable(ALenum capability); 454 | AL_API void AL_APIENTRY alDisable(ALenum capability); 455 | AL_API ALboolean AL_APIENTRY alIsEnabled(ALenum capability); 456 | 457 | /** State retrieval. */ 458 | AL_API const ALchar* AL_APIENTRY alGetString(ALenum param); 459 | AL_API void AL_APIENTRY alGetBooleanv(ALenum param, ALboolean *values); 460 | AL_API void AL_APIENTRY alGetIntegerv(ALenum param, ALint *values); 461 | AL_API void AL_APIENTRY alGetFloatv(ALenum param, ALfloat *values); 462 | AL_API void AL_APIENTRY alGetDoublev(ALenum param, ALdouble *values); 463 | AL_API ALboolean AL_APIENTRY alGetBoolean(ALenum param); 464 | AL_API ALint AL_APIENTRY alGetInteger(ALenum param); 465 | AL_API ALfloat AL_APIENTRY alGetFloat(ALenum param); 466 | AL_API ALdouble AL_APIENTRY alGetDouble(ALenum param); 467 | 468 | /** 469 | * Error retrieval. 470 | * 471 | * Obtain the first error generated in the AL context since the last check. 472 | */ 473 | AL_API ALenum AL_APIENTRY alGetError(void); 474 | 475 | /** 476 | * Extension support. 477 | * 478 | * Query for the presence of an extension, and obtain any appropriate function 479 | * pointers and enum values. 480 | */ 481 | AL_API ALboolean AL_APIENTRY alIsExtensionPresent(const ALchar *extname); 482 | AL_API void* AL_APIENTRY alGetProcAddress(const ALchar *fname); 483 | AL_API ALenum AL_APIENTRY alGetEnumValue(const ALchar *ename); 484 | 485 | 486 | /** Set Listener parameters */ 487 | AL_API void AL_APIENTRY alListenerf(ALenum param, ALfloat value); 488 | AL_API void AL_APIENTRY alListener3f(ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); 489 | AL_API void AL_APIENTRY alListenerfv(ALenum param, const ALfloat *values); 490 | AL_API void AL_APIENTRY alListeneri(ALenum param, ALint value); 491 | AL_API void AL_APIENTRY alListener3i(ALenum param, ALint value1, ALint value2, ALint value3); 492 | AL_API void AL_APIENTRY alListeneriv(ALenum param, const ALint *values); 493 | 494 | /** Get Listener parameters */ 495 | AL_API void AL_APIENTRY alGetListenerf(ALenum param, ALfloat *value); 496 | AL_API void AL_APIENTRY alGetListener3f(ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); 497 | AL_API void AL_APIENTRY alGetListenerfv(ALenum param, ALfloat *values); 498 | AL_API void AL_APIENTRY alGetListeneri(ALenum param, ALint *value); 499 | AL_API void AL_APIENTRY alGetListener3i(ALenum param, ALint *value1, ALint *value2, ALint *value3); 500 | AL_API void AL_APIENTRY alGetListeneriv(ALenum param, ALint *values); 501 | 502 | 503 | /** Create Source objects. */ 504 | AL_API void AL_APIENTRY alGenSources(ALsizei n, ALuint *sources); 505 | /** Delete Source objects. */ 506 | AL_API void AL_APIENTRY alDeleteSources(ALsizei n, const ALuint *sources); 507 | /** Verify a handle is a valid Source. */ 508 | AL_API ALboolean AL_APIENTRY alIsSource(ALuint source); 509 | 510 | /** Set Source parameters. */ 511 | AL_API void AL_APIENTRY alSourcef(ALuint source, ALenum param, ALfloat value); 512 | AL_API void AL_APIENTRY alSource3f(ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); 513 | AL_API void AL_APIENTRY alSourcefv(ALuint source, ALenum param, const ALfloat *values); 514 | AL_API void AL_APIENTRY alSourcei(ALuint source, ALenum param, ALint value); 515 | AL_API void AL_APIENTRY alSource3i(ALuint source, ALenum param, ALint value1, ALint value2, ALint value3); 516 | AL_API void AL_APIENTRY alSourceiv(ALuint source, ALenum param, const ALint *values); 517 | 518 | /** Get Source parameters. */ 519 | AL_API void AL_APIENTRY alGetSourcef(ALuint source, ALenum param, ALfloat *value); 520 | AL_API void AL_APIENTRY alGetSource3f(ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); 521 | AL_API void AL_APIENTRY alGetSourcefv(ALuint source, ALenum param, ALfloat *values); 522 | AL_API void AL_APIENTRY alGetSourcei(ALuint source, ALenum param, ALint *value); 523 | AL_API void AL_APIENTRY alGetSource3i(ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3); 524 | AL_API void AL_APIENTRY alGetSourceiv(ALuint source, ALenum param, ALint *values); 525 | 526 | 527 | /** Play, replay, or resume (if paused) a list of Sources */ 528 | AL_API void AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources); 529 | /** Stop a list of Sources */ 530 | AL_API void AL_APIENTRY alSourceStopv(ALsizei n, const ALuint *sources); 531 | /** Rewind a list of Sources */ 532 | AL_API void AL_APIENTRY alSourceRewindv(ALsizei n, const ALuint *sources); 533 | /** Pause a list of Sources */ 534 | AL_API void AL_APIENTRY alSourcePausev(ALsizei n, const ALuint *sources); 535 | 536 | /** Play, replay, or resume a Source */ 537 | AL_API void AL_APIENTRY alSourcePlay(ALuint source); 538 | /** Stop a Source */ 539 | AL_API void AL_APIENTRY alSourceStop(ALuint source); 540 | /** Rewind a Source (set playback postiton to beginning) */ 541 | AL_API void AL_APIENTRY alSourceRewind(ALuint source); 542 | /** Pause a Source */ 543 | AL_API void AL_APIENTRY alSourcePause(ALuint source); 544 | 545 | /** Queue buffers onto a source */ 546 | AL_API void AL_APIENTRY alSourceQueueBuffers(ALuint source, ALsizei nb, const ALuint *buffers); 547 | /** Unqueue processed buffers from a source */ 548 | AL_API void AL_APIENTRY alSourceUnqueueBuffers(ALuint source, ALsizei nb, ALuint *buffers); 549 | 550 | 551 | /** Create Buffer objects */ 552 | AL_API void AL_APIENTRY alGenBuffers(ALsizei n, ALuint *buffers); 553 | /** Delete Buffer objects */ 554 | AL_API void AL_APIENTRY alDeleteBuffers(ALsizei n, const ALuint *buffers); 555 | /** Verify a handle is a valid Buffer */ 556 | AL_API ALboolean AL_APIENTRY alIsBuffer(ALuint buffer); 557 | 558 | /** Specifies the data to be copied into a buffer */ 559 | AL_API void AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq); 560 | 561 | /** Set Buffer parameters, */ 562 | AL_API void AL_APIENTRY alBufferf(ALuint buffer, ALenum param, ALfloat value); 563 | AL_API void AL_APIENTRY alBuffer3f(ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); 564 | AL_API void AL_APIENTRY alBufferfv(ALuint buffer, ALenum param, const ALfloat *values); 565 | AL_API void AL_APIENTRY alBufferi(ALuint buffer, ALenum param, ALint value); 566 | AL_API void AL_APIENTRY alBuffer3i(ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3); 567 | AL_API void AL_APIENTRY alBufferiv(ALuint buffer, ALenum param, const ALint *values); 568 | 569 | /** Get Buffer parameters. */ 570 | AL_API void AL_APIENTRY alGetBufferf(ALuint buffer, ALenum param, ALfloat *value); 571 | AL_API void AL_APIENTRY alGetBuffer3f(ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); 572 | AL_API void AL_APIENTRY alGetBufferfv(ALuint buffer, ALenum param, ALfloat *values); 573 | AL_API void AL_APIENTRY alGetBufferi(ALuint buffer, ALenum param, ALint *value); 574 | AL_API void AL_APIENTRY alGetBuffer3i(ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3); 575 | AL_API void AL_APIENTRY alGetBufferiv(ALuint buffer, ALenum param, ALint *values); 576 | 577 | /** Pointer-to-function type, useful for dynamically getting AL entry points. */ 578 | typedef void (AL_APIENTRY *LPALENABLE)(ALenum capability); 579 | typedef void (AL_APIENTRY *LPALDISABLE)(ALenum capability); 580 | typedef ALboolean (AL_APIENTRY *LPALISENABLED)(ALenum capability); 581 | typedef const ALchar* (AL_APIENTRY *LPALGETSTRING)(ALenum param); 582 | typedef void (AL_APIENTRY *LPALGETBOOLEANV)(ALenum param, ALboolean *values); 583 | typedef void (AL_APIENTRY *LPALGETINTEGERV)(ALenum param, ALint *values); 584 | typedef void (AL_APIENTRY *LPALGETFLOATV)(ALenum param, ALfloat *values); 585 | typedef void (AL_APIENTRY *LPALGETDOUBLEV)(ALenum param, ALdouble *values); 586 | typedef ALboolean (AL_APIENTRY *LPALGETBOOLEAN)(ALenum param); 587 | typedef ALint (AL_APIENTRY *LPALGETINTEGER)(ALenum param); 588 | typedef ALfloat (AL_APIENTRY *LPALGETFLOAT)(ALenum param); 589 | typedef ALdouble (AL_APIENTRY *LPALGETDOUBLE)(ALenum param); 590 | typedef ALenum (AL_APIENTRY *LPALGETERROR)(void); 591 | typedef ALboolean (AL_APIENTRY *LPALISEXTENSIONPRESENT)(const ALchar *extname); 592 | typedef void* (AL_APIENTRY *LPALGETPROCADDRESS)(const ALchar *fname); 593 | typedef ALenum (AL_APIENTRY *LPALGETENUMVALUE)(const ALchar *ename); 594 | typedef void (AL_APIENTRY *LPALLISTENERF)(ALenum param, ALfloat value); 595 | typedef void (AL_APIENTRY *LPALLISTENER3F)(ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); 596 | typedef void (AL_APIENTRY *LPALLISTENERFV)(ALenum param, const ALfloat *values); 597 | typedef void (AL_APIENTRY *LPALLISTENERI)(ALenum param, ALint value); 598 | typedef void (AL_APIENTRY *LPALLISTENER3I)(ALenum param, ALint value1, ALint value2, ALint value3); 599 | typedef void (AL_APIENTRY *LPALLISTENERIV)(ALenum param, const ALint *values); 600 | typedef void (AL_APIENTRY *LPALGETLISTENERF)(ALenum param, ALfloat *value); 601 | typedef void (AL_APIENTRY *LPALGETLISTENER3F)(ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); 602 | typedef void (AL_APIENTRY *LPALGETLISTENERFV)(ALenum param, ALfloat *values); 603 | typedef void (AL_APIENTRY *LPALGETLISTENERI)(ALenum param, ALint *value); 604 | typedef void (AL_APIENTRY *LPALGETLISTENER3I)(ALenum param, ALint *value1, ALint *value2, ALint *value3); 605 | typedef void (AL_APIENTRY *LPALGETLISTENERIV)(ALenum param, ALint *values); 606 | typedef void (AL_APIENTRY *LPALGENSOURCES)(ALsizei n, ALuint *sources); 607 | typedef void (AL_APIENTRY *LPALDELETESOURCES)(ALsizei n, const ALuint *sources); 608 | typedef ALboolean (AL_APIENTRY *LPALISSOURCE)(ALuint source); 609 | typedef void (AL_APIENTRY *LPALSOURCEF)(ALuint source, ALenum param, ALfloat value); 610 | typedef void (AL_APIENTRY *LPALSOURCE3F)(ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); 611 | typedef void (AL_APIENTRY *LPALSOURCEFV)(ALuint source, ALenum param, const ALfloat *values); 612 | typedef void (AL_APIENTRY *LPALSOURCEI)(ALuint source, ALenum param, ALint value); 613 | typedef void (AL_APIENTRY *LPALSOURCE3I)(ALuint source, ALenum param, ALint value1, ALint value2, ALint value3); 614 | typedef void (AL_APIENTRY *LPALSOURCEIV)(ALuint source, ALenum param, const ALint *values); 615 | typedef void (AL_APIENTRY *LPALGETSOURCEF)(ALuint source, ALenum param, ALfloat *value); 616 | typedef void (AL_APIENTRY *LPALGETSOURCE3F)(ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); 617 | typedef void (AL_APIENTRY *LPALGETSOURCEFV)(ALuint source, ALenum param, ALfloat *values); 618 | typedef void (AL_APIENTRY *LPALGETSOURCEI)(ALuint source, ALenum param, ALint *value); 619 | typedef void (AL_APIENTRY *LPALGETSOURCE3I)(ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3); 620 | typedef void (AL_APIENTRY *LPALGETSOURCEIV)(ALuint source, ALenum param, ALint *values); 621 | typedef void (AL_APIENTRY *LPALSOURCEPLAYV)(ALsizei n, const ALuint *sources); 622 | typedef void (AL_APIENTRY *LPALSOURCESTOPV)(ALsizei n, const ALuint *sources); 623 | typedef void (AL_APIENTRY *LPALSOURCEREWINDV)(ALsizei n, const ALuint *sources); 624 | typedef void (AL_APIENTRY *LPALSOURCEPAUSEV)(ALsizei n, const ALuint *sources); 625 | typedef void (AL_APIENTRY *LPALSOURCEPLAY)(ALuint source); 626 | typedef void (AL_APIENTRY *LPALSOURCESTOP)(ALuint source); 627 | typedef void (AL_APIENTRY *LPALSOURCEREWIND)(ALuint source); 628 | typedef void (AL_APIENTRY *LPALSOURCEPAUSE)(ALuint source); 629 | typedef void (AL_APIENTRY *LPALSOURCEQUEUEBUFFERS)(ALuint source, ALsizei nb, const ALuint *buffers); 630 | typedef void (AL_APIENTRY *LPALSOURCEUNQUEUEBUFFERS)(ALuint source, ALsizei nb, ALuint *buffers); 631 | typedef void (AL_APIENTRY *LPALGENBUFFERS)(ALsizei n, ALuint *buffers); 632 | typedef void (AL_APIENTRY *LPALDELETEBUFFERS)(ALsizei n, const ALuint *buffers); 633 | typedef ALboolean (AL_APIENTRY *LPALISBUFFER)(ALuint buffer); 634 | typedef void (AL_APIENTRY *LPALBUFFERDATA)(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq); 635 | typedef void (AL_APIENTRY *LPALBUFFERF)(ALuint buffer, ALenum param, ALfloat value); 636 | typedef void (AL_APIENTRY *LPALBUFFER3F)(ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); 637 | typedef void (AL_APIENTRY *LPALBUFFERFV)(ALuint buffer, ALenum param, const ALfloat *values); 638 | typedef void (AL_APIENTRY *LPALBUFFERI)(ALuint buffer, ALenum param, ALint value); 639 | typedef void (AL_APIENTRY *LPALBUFFER3I)(ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3); 640 | typedef void (AL_APIENTRY *LPALBUFFERIV)(ALuint buffer, ALenum param, const ALint *values); 641 | typedef void (AL_APIENTRY *LPALGETBUFFERF)(ALuint buffer, ALenum param, ALfloat *value); 642 | typedef void (AL_APIENTRY *LPALGETBUFFER3F)(ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); 643 | typedef void (AL_APIENTRY *LPALGETBUFFERFV)(ALuint buffer, ALenum param, ALfloat *values); 644 | typedef void (AL_APIENTRY *LPALGETBUFFERI)(ALuint buffer, ALenum param, ALint *value); 645 | typedef void (AL_APIENTRY *LPALGETBUFFER3I)(ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3); 646 | typedef void (AL_APIENTRY *LPALGETBUFFERIV)(ALuint buffer, ALenum param, ALint *values); 647 | typedef void (AL_APIENTRY *LPALDOPPLERFACTOR)(ALfloat value); 648 | typedef void (AL_APIENTRY *LPALDOPPLERVELOCITY)(ALfloat value); 649 | typedef void (AL_APIENTRY *LPALSPEEDOFSOUND)(ALfloat value); 650 | typedef void (AL_APIENTRY *LPALDISTANCEMODEL)(ALenum distanceModel); 651 | 652 | #if defined(__cplusplus) 653 | } /* extern "C" */ 654 | #endif 655 | 656 | #endif /* AL_AL_H */ 657 | -------------------------------------------------------------------------------- /include/AL/alc.h: -------------------------------------------------------------------------------- 1 | #ifndef AL_ALC_H 2 | #define AL_ALC_H 3 | 4 | #if defined(__cplusplus) 5 | extern "C" { 6 | #endif 7 | 8 | #ifndef ALC_API 9 | #if defined(AL_LIBTYPE_STATIC) 10 | #define ALC_API 11 | #elif defined(_WIN32) 12 | #define ALC_API __declspec(dllimport) 13 | #else 14 | #define ALC_API extern 15 | #endif 16 | #endif 17 | 18 | #if defined(_WIN32) 19 | #define ALC_APIENTRY __cdecl 20 | #else 21 | #define ALC_APIENTRY 22 | #endif 23 | 24 | 25 | /** Deprecated macro. */ 26 | #define ALCAPI ALC_API 27 | #define ALCAPIENTRY ALC_APIENTRY 28 | #define ALC_INVALID 0 29 | 30 | /** Supported ALC version? */ 31 | #define ALC_VERSION_0_1 1 32 | 33 | /** Opaque device handle */ 34 | typedef struct ALCdevice_struct ALCdevice; 35 | /** Opaque context handle */ 36 | typedef struct ALCcontext_struct ALCcontext; 37 | 38 | /** 8-bit boolean */ 39 | typedef char ALCboolean; 40 | 41 | /** character */ 42 | typedef char ALCchar; 43 | 44 | /** signed 8-bit 2's complement integer */ 45 | typedef signed char ALCbyte; 46 | 47 | /** unsigned 8-bit integer */ 48 | typedef unsigned char ALCubyte; 49 | 50 | /** signed 16-bit 2's complement integer */ 51 | typedef short ALCshort; 52 | 53 | /** unsigned 16-bit integer */ 54 | typedef unsigned short ALCushort; 55 | 56 | /** signed 32-bit 2's complement integer */ 57 | typedef int ALCint; 58 | 59 | /** unsigned 32-bit integer */ 60 | typedef unsigned int ALCuint; 61 | 62 | /** non-negative 32-bit binary integer size */ 63 | typedef int ALCsizei; 64 | 65 | /** enumerated 32-bit value */ 66 | typedef int ALCenum; 67 | 68 | /** 32-bit IEEE754 floating-point */ 69 | typedef float ALCfloat; 70 | 71 | /** 64-bit IEEE754 floating-point */ 72 | typedef double ALCdouble; 73 | 74 | /** void type (for opaque pointers only) */ 75 | typedef void ALCvoid; 76 | 77 | 78 | /* Enumerant values begin at column 50. No tabs. */ 79 | 80 | /** Boolean False. */ 81 | #define ALC_FALSE 0 82 | 83 | /** Boolean True. */ 84 | #define ALC_TRUE 1 85 | 86 | /** Context attribute: Hz. */ 87 | #define ALC_FREQUENCY 0x1007 88 | 89 | /** Context attribute: Hz. */ 90 | #define ALC_REFRESH 0x1008 91 | 92 | /** Context attribute: AL_TRUE or AL_FALSE. */ 93 | #define ALC_SYNC 0x1009 94 | 95 | /** Context attribute: requested Mono (3D) Sources. */ 96 | #define ALC_MONO_SOURCES 0x1010 97 | 98 | /** Context attribute: requested Stereo Sources. */ 99 | #define ALC_STEREO_SOURCES 0x1011 100 | 101 | /** No error. */ 102 | #define ALC_NO_ERROR 0 103 | 104 | /** Invalid device handle. */ 105 | #define ALC_INVALID_DEVICE 0xA001 106 | 107 | /** Invalid context handle. */ 108 | #define ALC_INVALID_CONTEXT 0xA002 109 | 110 | /** Invalid enum parameter passed to an ALC call. */ 111 | #define ALC_INVALID_ENUM 0xA003 112 | 113 | /** Invalid value parameter passed to an ALC call. */ 114 | #define ALC_INVALID_VALUE 0xA004 115 | 116 | /** Out of memory. */ 117 | #define ALC_OUT_OF_MEMORY 0xA005 118 | 119 | 120 | /** Runtime ALC version. */ 121 | #define ALC_MAJOR_VERSION 0x1000 122 | #define ALC_MINOR_VERSION 0x1001 123 | 124 | /** Context attribute list properties. */ 125 | #define ALC_ATTRIBUTES_SIZE 0x1002 126 | #define ALC_ALL_ATTRIBUTES 0x1003 127 | 128 | /** String for the default device specifier. */ 129 | #define ALC_DEFAULT_DEVICE_SPECIFIER 0x1004 130 | /** 131 | * String for the given device's specifier. 132 | * 133 | * If device handle is NULL, it is instead a null-char separated list of 134 | * strings of known device specifiers (list ends with an empty string). 135 | */ 136 | #define ALC_DEVICE_SPECIFIER 0x1005 137 | /** String for space-separated list of ALC extensions. */ 138 | #define ALC_EXTENSIONS 0x1006 139 | 140 | 141 | /** Capture extension */ 142 | #define ALC_EXT_CAPTURE 1 143 | /** 144 | * String for the given capture device's specifier. 145 | * 146 | * If device handle is NULL, it is instead a null-char separated list of 147 | * strings of known capture device specifiers (list ends with an empty string). 148 | */ 149 | #define ALC_CAPTURE_DEVICE_SPECIFIER 0x310 150 | /** String for the default capture device specifier. */ 151 | #define ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER 0x311 152 | /** Number of sample frames available for capture. */ 153 | #define ALC_CAPTURE_SAMPLES 0x312 154 | 155 | 156 | /** Enumerate All extension */ 157 | #define ALC_ENUMERATE_ALL_EXT 1 158 | /** String for the default extended device specifier. */ 159 | #define ALC_DEFAULT_ALL_DEVICES_SPECIFIER 0x1012 160 | /** 161 | * String for the given extended device's specifier. 162 | * 163 | * If device handle is NULL, it is instead a null-char separated list of 164 | * strings of known extended device specifiers (list ends with an empty string). 165 | */ 166 | #define ALC_ALL_DEVICES_SPECIFIER 0x1013 167 | 168 | 169 | /** Context management. */ 170 | ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint* attrlist); 171 | ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context); 172 | ALC_API void ALC_APIENTRY alcProcessContext(ALCcontext *context); 173 | ALC_API void ALC_APIENTRY alcSuspendContext(ALCcontext *context); 174 | ALC_API void ALC_APIENTRY alcDestroyContext(ALCcontext *context); 175 | ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void); 176 | ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *context); 177 | 178 | /** Device management. */ 179 | ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *devicename); 180 | ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device); 181 | 182 | 183 | /** 184 | * Error support. 185 | * 186 | * Obtain the most recent Device error. 187 | */ 188 | ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device); 189 | 190 | /** 191 | * Extension support. 192 | * 193 | * Query for the presence of an extension, and obtain any appropriate 194 | * function pointers and enum values. 195 | */ 196 | ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extname); 197 | ALC_API void* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcname); 198 | ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumname); 199 | 200 | /** Query function. */ 201 | ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *device, ALCenum param); 202 | ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values); 203 | 204 | /** Capture function. */ 205 | ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize); 206 | ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device); 207 | ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device); 208 | ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device); 209 | ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples); 210 | 211 | /** Pointer-to-function type, useful for dynamically getting ALC entry points. */ 212 | typedef ALCcontext* (ALC_APIENTRY *LPALCCREATECONTEXT)(ALCdevice *device, const ALCint *attrlist); 213 | typedef ALCboolean (ALC_APIENTRY *LPALCMAKECONTEXTCURRENT)(ALCcontext *context); 214 | typedef void (ALC_APIENTRY *LPALCPROCESSCONTEXT)(ALCcontext *context); 215 | typedef void (ALC_APIENTRY *LPALCSUSPENDCONTEXT)(ALCcontext *context); 216 | typedef void (ALC_APIENTRY *LPALCDESTROYCONTEXT)(ALCcontext *context); 217 | typedef ALCcontext* (ALC_APIENTRY *LPALCGETCURRENTCONTEXT)(void); 218 | typedef ALCdevice* (ALC_APIENTRY *LPALCGETCONTEXTSDEVICE)(ALCcontext *context); 219 | typedef ALCdevice* (ALC_APIENTRY *LPALCOPENDEVICE)(const ALCchar *devicename); 220 | typedef ALCboolean (ALC_APIENTRY *LPALCCLOSEDEVICE)(ALCdevice *device); 221 | typedef ALCenum (ALC_APIENTRY *LPALCGETERROR)(ALCdevice *device); 222 | typedef ALCboolean (ALC_APIENTRY *LPALCISEXTENSIONPRESENT)(ALCdevice *device, const ALCchar *extname); 223 | typedef void* (ALC_APIENTRY *LPALCGETPROCADDRESS)(ALCdevice *device, const ALCchar *funcname); 224 | typedef ALCenum (ALC_APIENTRY *LPALCGETENUMVALUE)(ALCdevice *device, const ALCchar *enumname); 225 | typedef const ALCchar* (ALC_APIENTRY *LPALCGETSTRING)(ALCdevice *device, ALCenum param); 226 | typedef void (ALC_APIENTRY *LPALCGETINTEGERV)(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values); 227 | typedef ALCdevice* (ALC_APIENTRY *LPALCCAPTUREOPENDEVICE)(const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize); 228 | typedef ALCboolean (ALC_APIENTRY *LPALCCAPTURECLOSEDEVICE)(ALCdevice *device); 229 | typedef void (ALC_APIENTRY *LPALCCAPTURESTART)(ALCdevice *device); 230 | typedef void (ALC_APIENTRY *LPALCCAPTURESTOP)(ALCdevice *device); 231 | typedef void (ALC_APIENTRY *LPALCCAPTURESAMPLES)(ALCdevice *device, ALCvoid *buffer, ALCsizei samples); 232 | 233 | #if defined(__cplusplus) 234 | } 235 | #endif 236 | 237 | #endif /* AL_ALC_H */ 238 | -------------------------------------------------------------------------------- /include/AL/alut.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "al.h" 4 | 5 | #if defined(__cplusplus) 6 | extern "C" { 7 | #endif 8 | 9 | #define ALUT_API_MAJOR_VERSION 1 10 | #define ALUT_API_MINOR_VERSION 1 11 | 12 | #define ALUT_ERROR_NO_ERROR 0 13 | #define ALUT_ERROR_OUT_OF_MEMORY 0x200 14 | #define ALUT_ERROR_INVALID_ENUM 0x201 15 | #define ALUT_ERROR_INVALID_VALUE 0x202 16 | #define ALUT_ERROR_INVALID_OPERATION 0x203 17 | #define ALUT_ERROR_NO_CURRENT_CONTEXT 0x204 18 | #define ALUT_ERROR_AL_ERROR_ON_ENTRY 0x205 19 | #define ALUT_ERROR_ALC_ERROR_ON_ENTRY 0x206 20 | #define ALUT_ERROR_OPEN_DEVICE 0x207 21 | #define ALUT_ERROR_CLOSE_DEVICE 0x208 22 | #define ALUT_ERROR_CREATE_CONTEXT 0x209 23 | #define ALUT_ERROR_MAKE_CONTEXT_CURRENT 0x20A 24 | #define ALUT_ERROR_DESTROY_CONTEXT 0x20B 25 | #define ALUT_ERROR_GEN_BUFFERS 0x20C 26 | #define ALUT_ERROR_BUFFER_DATA 0x20D 27 | #define ALUT_ERROR_IO_ERROR 0x20E 28 | #define ALUT_ERROR_UNSUPPORTED_FILE_TYPE 0x20F 29 | #define ALUT_ERROR_UNSUPPORTED_FILE_SUBTYPE 0x210 30 | #define ALUT_ERROR_CORRUPT_OR_TRUNCATED_DATA 0x211 31 | 32 | AL_API ALboolean AL_APIENTRY alutInit(int *argcp, char **argv); 33 | AL_API ALboolean AL_APIENTRY alutInitWithoutContext(int *argcp, char **argv); 34 | AL_API ALboolean AL_APIENTRY alutExit(void); 35 | 36 | AL_API ALenum AL_APIENTRY alutGetError(); 37 | AL_API const ALchar* AL_APIENTRY alutGetErrorString(ALenum error); 38 | 39 | AL_API void AL_APIENTRY alutLoadWAVFile (ALbyte *filename, 40 | ALenum *format, 41 | void **data, 42 | ALsizei *size, 43 | ALsizei *frequency); 44 | 45 | AL_API void AL_APIENTRY alutUnloadWAV (ALenum format, ALvoid *data, ALsizei size, ALsizei frequency); 46 | 47 | #if defined(__cplusplus) 48 | } 49 | #endif 50 | -------------------------------------------------------------------------------- /samples/GLdc/include/GL/gl.h: -------------------------------------------------------------------------------- 1 | /* KallistiGL for KallistiOS ##version## 2 | 3 | libgl/gl.h 4 | Copyright (C) 2013-2014 Josh "PH3NOM" Pearson 5 | Copyright (C) 2014, 2016 Lawrence Sebald 6 | 7 | Some functionality adapted from the original KOS libgl: 8 | Copyright (C) 2001 Dan Potter 9 | Copyright (C) 2002 Benoit Miller 10 | 11 | This API implements much but not all of the OpenGL 1.1 for KallistiOS. 12 | */ 13 | 14 | #ifndef __GL_GL_H 15 | #define __GL_GL_H 16 | 17 | #include 18 | __BEGIN_DECLS 19 | 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | /* Primitive Types taken from GL for compatability */ 30 | /* Not all types are implemented in Open GL DC V.1.0 */ 31 | #define GL_POINTS 0x01 32 | #define GL_LINES 0x02 33 | #define GL_LINE_LOOP 0x03 34 | #define GL_LINE_STRIP 0x04 35 | #define GL_TRIANGLES 0x05 36 | #define GL_TRIANGLE_STRIP 0x06 37 | #define GL_TRIANGLE_FAN 0x07 38 | #define GL_QUADS 0x08 39 | #define GL_QUAD_STRIP 0x09 40 | #define GL_POLYGON 0x0A 41 | 42 | /* FrontFaceDirection */ 43 | #define GL_CW 0x0900 44 | #define GL_CCW 0x0901 45 | 46 | #define GL_FRONT 0x0404 47 | #define GL_BACK 0x0405 48 | #define GL_FRONT_AND_BACK 0x0408 49 | #define GL_CULL_FACE 0x0B44 50 | #define GL_CULL_FACE_MODE 0x0B45 51 | #define GL_FRONT_FACE 0x0B46 52 | 53 | /* Scissor box */ 54 | #define GL_SCISSOR_TEST 0x0008 /* capability bit */ 55 | #define GL_SCISSOR_BOX 0x0C10 56 | 57 | /* Matrix modes */ 58 | #define GL_MATRIX_MODE 0x0BA0 59 | #define GL_MODELVIEW 0x1700 60 | #define GL_PROJECTION 0x1701 61 | #define GL_TEXTURE 0x1702 62 | 63 | #define GL_MODELVIEW_MATRIX 0x0BA6 64 | #define GL_PROJECTION_MATRIX 0x0BA7 65 | #define GL_TEXTURE_MATRIX 0x0BA8 66 | 67 | /* Depth buffer */ 68 | #define GL_NEVER 0x0200 69 | #define GL_LESS 0x0201 70 | #define GL_EQUAL 0x0202 71 | #define GL_LEQUAL 0x0203 72 | #define GL_GREATER 0x0204 73 | #define GL_NOTEQUAL 0x0205 74 | #define GL_GEQUAL 0x0206 75 | #define GL_ALWAYS 0x0207 76 | #define GL_DEPTH_TEST 0x0B71 77 | #define GL_DEPTH_BITS 0x0D56 78 | #define GL_DEPTH_CLEAR_VALUE 0x0B73 79 | #define GL_DEPTH_FUNC 0x0B74 80 | #define GL_DEPTH_RANGE 0x0B70 81 | #define GL_DEPTH_WRITEMASK 0x0B72 82 | #define GL_DEPTH_COMPONENT 0x1902 83 | 84 | /* Blending: Simply Need to Map GL constants to PVR constants */ 85 | #define GL_BLEND_DST 0x0BE0 86 | #define GL_BLEND_SRC 0x0BE1 87 | #define GL_BLEND 0x0BE2 /* capability bit */ 88 | 89 | #define GL_ZERO 0x0 90 | #define GL_ONE 0x1 91 | #define GL_SRC_COLOR 0x0300 92 | #define GL_ONE_MINUS_SRC_COLOR 0x0301 93 | #define GL_SRC_ALPHA 0x0302 94 | #define GL_ONE_MINUS_SRC_ALPHA 0x0303 95 | #define GL_DST_ALPHA 0x0304 96 | #define GL_ONE_MINUS_DST_ALPHA 0x0305 97 | #define GL_DST_COLOR 0x0306 98 | #define GL_ONE_MINUS_DST_COLOR 0x0307 99 | #define GL_SRC_ALPHA_SATURATE 0x0308 100 | 101 | /* Misc texture constants */ 102 | #define GL_TEXTURE_2D 0x0001 /* capability bit */ 103 | #define GL_TEXTURE_WRAP_S 0x2802 104 | #define GL_TEXTURE_WRAP_T 0x2803 105 | #define GL_TEXTURE_MAG_FILTER 0x2800 106 | #define GL_TEXTURE_MIN_FILTER 0x2801 107 | #define GL_REPEAT 0x2901 108 | #define GL_CLAMP 0x2900 109 | 110 | /* Texture Environment */ 111 | #define GL_TEXTURE_ENV_MODE 0x2200 112 | #define GL_REPLACE 0x1E01 113 | #define GL_MODULATE 0x2100 114 | #define GL_DECAL 0x2101 115 | 116 | /* TextureMagFilter */ 117 | #define GL_NEAREST 0x2600 118 | #define GL_LINEAR 0x2601 119 | 120 | /* Texture mapping */ 121 | #define GL_TEXTURE_ENV 0x2300 122 | #define GL_TEXTURE_ENV_COLOR 0x2201 123 | #define GL_NEAREST_MIPMAP_NEAREST 0x2700 124 | #define GL_NEAREST_MIPMAP_LINEAR 0x2702 125 | #define GL_LINEAR_MIPMAP_NEAREST 0x2701 126 | #define GL_LINEAR_MIPMAP_LINEAR 0x2703 127 | 128 | #define GL_TEXTURE_BINDING_2D 0x8069 129 | 130 | /* TextureUnit */ 131 | #define GL_TEXTURE0 0x84C0 132 | #define GL_TEXTURE1 0x84C1 133 | #define GL_TEXTURE2 0x84C2 134 | #define GL_TEXTURE3 0x84C3 135 | #define GL_TEXTURE4 0x84C4 136 | #define GL_TEXTURE5 0x84C5 137 | #define GL_TEXTURE6 0x84C6 138 | #define GL_TEXTURE7 0x84C7 139 | #define GL_TEXTURE8 0x84C8 140 | #define GL_TEXTURE9 0x84C9 141 | #define GL_TEXTURE10 0x84CA 142 | #define GL_TEXTURE11 0x84CB 143 | #define GL_TEXTURE12 0x84CC 144 | #define GL_TEXTURE13 0x84CD 145 | #define GL_TEXTURE14 0x84CE 146 | #define GL_TEXTURE15 0x84CF 147 | #define GL_TEXTURE16 0x84D0 148 | #define GL_TEXTURE17 0x84D1 149 | #define GL_TEXTURE18 0x84D2 150 | #define GL_TEXTURE19 0x84D3 151 | #define GL_TEXTURE20 0x84D4 152 | #define GL_TEXTURE21 0x84D5 153 | #define GL_TEXTURE22 0x84D6 154 | #define GL_TEXTURE23 0x84D7 155 | #define GL_TEXTURE24 0x84D8 156 | #define GL_TEXTURE25 0x84D9 157 | #define GL_TEXTURE26 0x84DA 158 | #define GL_TEXTURE27 0x84DB 159 | #define GL_TEXTURE28 0x84DC 160 | #define GL_TEXTURE29 0x84DD 161 | #define GL_TEXTURE30 0x84DE 162 | #define GL_TEXTURE31 0x84DF 163 | #define GL_ACTIVE_TEXTURE 0x84E0 164 | #define GL_CLIENT_ACTIVE_TEXTURE 0x84E1 165 | 166 | #define GL_CURRENT_BIT 0x00000001 167 | #define GL_POINT_BIT 0x00000002 168 | #define GL_LINE_BIT 0x00000004 169 | #define GL_POLYGON_BIT 0x00000008 170 | #define GL_POLYGON_STIPPLE_BIT 0x00000010 171 | #define GL_PIXEL_MODE_BIT 0x00000020 172 | #define GL_LIGHTING_BIT 0x00000040 173 | #define GL_FOG_BIT 0x00000080 174 | #define GL_DEPTH_BUFFER_BIT 0x00000100 175 | #define GL_ACCUM_BUFFER_BIT 0x00000200 176 | #define GL_STENCIL_BUFFER_BIT 0x00000400 177 | #define GL_VIEWPORT_BIT 0x00000800 178 | #define GL_TRANSFORM_BIT 0x00001000 179 | #define GL_ENABLE_BIT 0x00002000 180 | #define GL_COLOR_BUFFER_BIT 0x00004000 181 | #define GL_HINT_BIT 0x00008000 182 | #define GL_EVAL_BIT 0x00010000 183 | #define GL_LIST_BIT 0x00020000 184 | #define GL_TEXTURE_BIT 0x00040000 185 | #define GL_SCISSOR_BIT 0x00080000 186 | #define GL_ALL_ATTRIB_BITS 0x000FFFFF 187 | 188 | /* Fog */ 189 | #define GL_FOG 0x0004 /* capability bit */ 190 | #define GL_FOG_MODE 0x0B65 191 | #define GL_FOG_DENSITY 0x0B62 192 | #define GL_FOG_COLOR 0x0B66 193 | #define GL_FOG_INDEX 0x0B61 194 | #define GL_FOG_START 0x0B63 195 | #define GL_FOG_END 0x0B64 196 | #define GL_LINEAR 0x2601 197 | #define GL_EXP 0x0800 198 | #define GL_EXP2 0x0801 199 | 200 | /* Hints - Not used by the API, only here for compatibility */ 201 | #define GL_DONT_CARE 0x1100 202 | #define GL_FASTEST 0x1101 203 | #define GL_NICEST 0x1102 204 | #define GL_PERSPECTIVE_CORRECTION_HINT 0x0C50 205 | #define GL_POINT_SMOOTH_HINT 0x0C51 206 | #define GL_LINE_SMOOTH_HINT 0x0C52 207 | #define GL_POLYGON_SMOOTH_HINT 0x0C53 208 | #define GL_FOG_HINT 0x0C54 209 | 210 | /* Lighting constants */ 211 | #define GL_LIGHTING 0x0b50 212 | 213 | #define GL_LIGHT0 0x4000 214 | #define GL_LIGHT1 0x4001 215 | #define GL_LIGHT2 0x4002 216 | #define GL_LIGHT3 0x4003 217 | #define GL_LIGHT4 0x4004 218 | #define GL_LIGHT5 0x4005 219 | #define GL_LIGHT6 0x4006 220 | #define GL_LIGHT7 0x4007 221 | #define GL_LIGHT8 0x4008 222 | #define GL_LIGHT9 0x4009 223 | #define GL_LIGHT10 0x400A 224 | #define GL_LIGHT11 0x400B 225 | #define GL_LIGHT12 0x400C 226 | #define GL_LIGHT13 0x400D 227 | #define GL_LIGHT14 0x400E 228 | #define GL_LIGHT15 0x400F 229 | 230 | /* EXT_separate_specular_color.txt */ 231 | #define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8 232 | #define GL_SINGLE_COLOR 0x81F9 233 | #define GL_SEPARATE_SPECULAR_COLOR 0x81FA 234 | 235 | /* glPolygonOffset */ 236 | #define GL_POLYGON_OFFSET_FACTOR 0x8038 237 | #define GL_POLYGON_OFFSET_UNITS 0x2A00 238 | #define GL_POLYGON_OFFSET_POINT 0x2A01 239 | #define GL_POLYGON_OFFSET_LINE 0x2A02 240 | #define GL_POLYGON_OFFSET_FILL 0x8037 241 | 242 | /* Client state caps */ 243 | #define GL_VERTEX_ARRAY 0x8074 244 | #define GL_NORMAL_ARRAY 0x8075 245 | #define GL_COLOR_ARRAY 0x8076 246 | #define GL_INDEX_ARRAY 0x8077 247 | #define GL_TEXTURE_COORD_ARRAY 0x8078 248 | 249 | /* LightParameter */ 250 | #define GL_AMBIENT 0x1200 251 | #define GL_DIFFUSE 0x1201 252 | #define GL_SPECULAR 0x1202 253 | #define GL_POSITION 0x1203 254 | #define GL_SPOT_DIRECTION 0x1204 255 | #define GL_SPOT_EXPONENT 0x1205 256 | #define GL_SPOT_CUTOFF 0x1206 257 | #define GL_CONSTANT_ATTENUATION 0x1207 258 | #define GL_LINEAR_ATTENUATION 0x1208 259 | #define GL_QUADRATIC_ATTENUATION 0x1209 260 | 261 | /* MaterialParameter */ 262 | #define GL_EMISSION 0x1600 263 | #define GL_SHININESS 0x1601 264 | #define GL_AMBIENT_AND_DIFFUSE 0x1602 265 | #define GL_COLOR_INDEXES 0x1603 266 | #define GL_COLOR_MATERIAL 0x0B57 267 | #define GL_COLOR_MATERIAL_FACE 0x0B55 268 | #define GL_COLOR_MATERIAL_PARAMETER 0x0B56 269 | #define GL_NORMALIZE 0x0BA1 270 | #define GL_LIGHT_MODEL_TWO_SIDE 0x0B52 271 | #define GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51 272 | #define GL_LIGHT_MODEL_AMBIENT 0x0B53 273 | #define GL_FRONT_AND_BACK 0x0408 274 | #define GL_FRONT 0x0404 275 | #define GL_BACK 0x0405 276 | 277 | #define GL_SHADE_MODEL 0x0b54 278 | #define GL_FLAT 0x1d00 279 | #define GL_SMOOTH 0x1d01 280 | 281 | /* Data types */ 282 | #define GL_BYTE 0x1400 283 | #define GL_UNSIGNED_BYTE 0x1401 284 | #define GL_SHORT 0x1402 285 | #define GL_UNSIGNED_SHORT 0x1403 286 | #define GL_INT 0x1404 287 | #define GL_UNSIGNED_INT 0x1405 288 | #define GL_FLOAT 0x1406 289 | #define GL_DOUBLE 0x140A 290 | #define GL_2_BYTES 0x1407 291 | #define GL_3_BYTES 0x1408 292 | #define GL_4_BYTES 0x1409 293 | 294 | /* ErrorCode */ 295 | #define GL_NO_ERROR 0 296 | #define GL_INVALID_ENUM 0x0500 297 | #define GL_INVALID_VALUE 0x0501 298 | #define GL_INVALID_OPERATION 0x0502 299 | #define GL_STACK_OVERFLOW 0x0503 300 | #define GL_STACK_UNDERFLOW 0x0504 301 | #define GL_OUT_OF_MEMORY 0x0505 302 | 303 | /* GetPName */ 304 | #define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12 305 | #define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22 306 | #define GL_ALIASED_POINT_SIZE_RANGE 0x846D 307 | #define GL_ALIASED_LINE_WIDTH_RANGE 0x846E 308 | #define GL_IMPLEMENTATION_COLOR_READ_TYPE_OES 0x8B9A 309 | #define GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES 0x8B9B 310 | #define GL_MAX_LIGHTS 0x0D31 311 | #define GL_MAX_TEXTURE_SIZE 0x0D33 312 | #define GL_MAX_MODELVIEW_STACK_DEPTH 0x0D36 313 | #define GL_MAX_PROJECTION_STACK_DEPTH 0x0D38 314 | #define GL_MAX_TEXTURE_STACK_DEPTH 0x0D39 315 | #define GL_MAX_VIEWPORT_DIMS 0x0D3A 316 | #define GL_MAX_ELEMENTS_VERTICES 0x80E8 317 | #define GL_MAX_ELEMENTS_INDICES 0x80E9 318 | #define GL_MAX_TEXTURE_UNITS 0x84E2 319 | #define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 320 | #define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 321 | #define GL_SUBPIXEL_BITS 0x0D50 322 | #define GL_RED_BITS 0x0D52 323 | #define GL_GREEN_BITS 0x0D53 324 | #define GL_BLUE_BITS 0x0D54 325 | #define GL_ALPHA_BITS 0x0D55 326 | #define GL_DEPTH_BITS 0x0D56 327 | #define GL_STENCIL_BITS 0x0D57 328 | 329 | /* StringName */ 330 | #define GL_VENDOR 0x1F00 331 | #define GL_RENDERER 0x1F01 332 | #define GL_VERSION 0x1F02 333 | #define GL_EXTENSIONS 0x1F03 334 | 335 | /* GL KOS Texture Matrix Enable Bit */ 336 | #define GL_KOS_TEXTURE_MATRIX 0x002F 337 | 338 | #define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 339 | #define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 340 | #define GL_UNSIGNED_SHORT_5_6_5 0x8363 341 | #define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 342 | #define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 343 | #define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 344 | 345 | #define GL_COLOR_INDEX 0x1900 346 | #define GL_RED 0x1903 347 | #define GL_GREEN 0x1904 348 | #define GL_BLUE 0x1905 349 | #define GL_ALPHA 0x1906 350 | #define GL_RGB 0x1907 351 | #define GL_RGBA 0x1908 352 | #define GL_LUMINANCE 0x1909 353 | #define GL_LUMINANCE_ALPHA 0x190A 354 | #define GL_BGRA 0x80E1 355 | #define GL_INTENSITY 0x8049 356 | #define GL_RGB4 0x804F 357 | #define GL_RGB5 0x8050 358 | #define GL_RGB8 0x8051 359 | #define GL_RGB10 0x8052 360 | #define GL_RGB12 0x8053 361 | #define GL_RGB16 0x8054 362 | #define GL_RGBA2 0x8055 363 | #define GL_RGBA4 0x8056 364 | #define GL_RGB5_A1 0x8057 365 | #define GL_RGBA8 0x8058 366 | #define GL_RGB10_A2 0x8059 367 | #define GL_RGBA12 0x805A 368 | #define GL_RGBA16 0x805B 369 | 370 | #define GLbyte char 371 | #define GLshort short 372 | #define GLint int 373 | #define GLfloat float 374 | #define GLdouble float 375 | #define GLvoid void 376 | #define GLushort unsigned short 377 | #define GLuint unsigned int 378 | #define GLenum unsigned int 379 | #define GLsizei unsigned int 380 | #define GLfixed const unsigned int 381 | #define GLclampf float 382 | #define GLubyte unsigned char 383 | #define GLbitfield unsigned int 384 | #define GLboolean unsigned char 385 | #define GL_FALSE 0 386 | #define GL_TRUE 1 387 | 388 | /* Stubs for portability */ 389 | #define GL_ALPHA_TEST 0x0BC0 390 | #define GL_STENCIL_TEST 0x0B90 391 | #define GL_UNPACK_ALIGNMENT 0x0CF5 392 | 393 | #define GLAPI extern 394 | #define APIENTRY 395 | 396 | GLAPI void APIENTRY glFlush(); 397 | GLAPI void APIENTRY glFinish(); 398 | 399 | /* Start Submission of Primitive Data */ 400 | /* Currently Supported Primitive Types: 401 | -GL_POINTS ( does NOT work with glDrawArrays )( ZClipping NOT supported ) 402 | -GL_TRIANGLES ( works with glDrawArrays )( ZClipping supported ) 403 | -GL_TRIANLGLE_STRIP ( works with glDrawArrays )( ZClipping supported ) 404 | -GL_QUADS ( works with glDrawArrays )( ZClipping supported ) 405 | **/ 406 | GLAPI void APIENTRY glBegin(GLenum mode); 407 | 408 | /* Finish Submission of Primitive Data */ 409 | GLAPI void APIENTRY glEnd(); 410 | 411 | /* Primitive Texture Coordinate Submission */ 412 | GLAPI void APIENTRY glTexCoord2f(GLfloat u, GLfloat v); 413 | GLAPI void APIENTRY glTexCoord2fv(const GLfloat *uv); 414 | 415 | /* Primitive Color Submission */ 416 | GLAPI void APIENTRY glColor1ui(GLuint argb); 417 | GLAPI void APIENTRY glColor4ub(GLubyte r, GLubyte g, GLubyte b, GLubyte a); 418 | GLAPI void APIENTRY glColor3f(GLfloat r, GLfloat g, GLfloat b); 419 | GLAPI void APIENTRY glColor3ub(GLubyte r, GLubyte g, GLubyte b); 420 | GLAPI void APIENTRY glColor3fv(const GLfloat *rgb); 421 | GLAPI void APIENTRY glColor4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a); 422 | GLAPI void APIENTRY glColor4fv(const GLfloat *rgba); 423 | 424 | /* Primitive Normal Submission */ 425 | GLAPI void APIENTRY glNormal3f(GLfloat x, GLfloat y, GLfloat z); 426 | #define glNormal3i glNormal3f 427 | GLAPI void APIENTRY glNormal3fv(const GLfloat *xyz); 428 | #define glNormal3iv glNormal3fv 429 | 430 | /* Primitive 2D Position Submission */ 431 | GLAPI void APIENTRY glVertex2f(GLfloat x, GLfloat y); 432 | #define glVertex2i glVertex2f 433 | GLAPI void APIENTRY glVertex2fv(const GLfloat *xy); 434 | #define glVertex2iv glVertex2fv 435 | 436 | /* Primitive 3D Position Submission */ 437 | GLAPI void APIENTRY glVertex3f(GLfloat, GLfloat, GLfloat); 438 | GLAPI void APIENTRY glVertex3fv(const GLfloat *); 439 | 440 | /* 2D Non-Textured Rectangle Submission */ 441 | GLAPI GLvoid APIENTRY glRectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2); 442 | #define glRectd glRectf 443 | GLAPI GLvoid APIENTRY glRectfv(const GLfloat *v1, const GLfloat *v2); 444 | #define glRectdv glRectfv 445 | GLAPI GLvoid APIENTRY glRecti(GLint x1, GLint y1, GLint x2, GLint y2); 446 | #define glRects glRecti 447 | GLAPI GLvoid APIENTRY glRectiv(const GLint *v1, const GLint *v2); 448 | #define glRectsv glRectiv 449 | 450 | /* Enable / Disable Capability */ 451 | /* Currently Supported Capabilities: 452 | GL_TEXTURE_2D 453 | GL_BLEND 454 | GL_DEPTH_TEST 455 | GL_LIGHTING 456 | GL_SCISSOR_TEST 457 | GL_FOG 458 | GL_CULL_FACE 459 | GL_KOS_NEARZ_CLIPPING 460 | GL_KOS_TEXTURE_MATRIX 461 | */ 462 | GLAPI void APIENTRY glEnable(GLenum cap); 463 | GLAPI void APIENTRY glDisable(GLenum cap); 464 | 465 | /* Clear Caps */ 466 | GLAPI void APIENTRY glClear(GLuint mode); 467 | GLAPI void APIENTRY glClearColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a); 468 | 469 | GLAPI void APIENTRY glReadBuffer(GLenum mode); 470 | GLAPI void APIENTRY glDrawBuffer(GLenum mode); 471 | 472 | /* Depth Testing */ 473 | GLAPI void APIENTRY glClearDepth(GLfloat depth); 474 | GLAPI void APIENTRY glClearDepthf(GLfloat depth); 475 | GLAPI void APIENTRY glDepthMask(GLboolean flag); 476 | GLAPI void APIENTRY glDepthFunc(GLenum func); 477 | 478 | /* Hints */ 479 | /* Currently Supported Capabilities: 480 | GL_PERSPECTIVE_CORRECTION_HINT - This will Enable Texture Super-Sampling on the PVR */ 481 | GLAPI void APIENTRY glHint(GLenum target, GLenum mode); 482 | 483 | /* Culling */ 484 | GLAPI void APIENTRY glFrontFace(GLenum mode); 485 | GLAPI void APIENTRY glCullFace(GLenum mode); 486 | 487 | /* Shading - Flat or Goraud */ 488 | GLAPI void APIENTRY glShadeModel(GLenum mode); 489 | 490 | /* Blending */ 491 | GLAPI void APIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor); 492 | 493 | /* Texturing */ 494 | GLAPI void APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param); 495 | GLAPI void APIENTRY glTexEnvi(GLenum target, GLenum pname, GLint param); 496 | GLAPI void APIENTRY glTexEnvf(GLenum target, GLenum pname, GLfloat param); 497 | 498 | GLAPI GLboolean APIENTRY glIsTexture(GLuint texture); 499 | GLAPI void APIENTRY glGenTextures(GLsizei n, GLuint *textures); 500 | GLAPI void APIENTRY glDeleteTextures(GLsizei n, GLuint *textures); 501 | GLAPI void APIENTRY glBindTexture(GLenum target, GLuint texture); 502 | 503 | /* Loads texture from SH4 RAM into PVR VRAM applying color conversion if needed */ 504 | /* internalformat must be one of the following constants: 505 | GL_RGB 506 | GL_RGBA 507 | 508 | format must be the same as internalformat 509 | 510 | if internal format is GL_RGB, type must be one of the following constants: 511 | GL_BYTE 512 | GL_UNSIGNED_BYTE 513 | GL_SHORT 514 | GL_UNSIGNED_SHORT 515 | GL_FLOAT 516 | GL_UNSIGNED_SHORT_5_6_5 517 | GL_UNSIGNED_SHORT_5_6_5_TWID 518 | 519 | if internal format is GL_RGBA, type must be one of the following constants: 520 | GL_BYTE 521 | GL_UNSIGNED_BYTE 522 | GL_SHORT 523 | GL_UNSIGNED_SHORT 524 | GL_FLOAT 525 | GL_UNSIGNED_SHORT_4_4_4_4 526 | GL_UNSIGNED_SHORT_4_4_4_4_TWID 527 | GL_UNSIGNED_SHORT_1_5_5_5 528 | GL_UNSIGNED_SHORT_1_5_5_5_TWID 529 | */ 530 | GLAPI void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat, 531 | GLsizei width, GLsizei height, GLint border, 532 | GLenum format, GLenum type, const GLvoid *data); 533 | 534 | GLAPI void APIENTRY glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); 535 | GLAPI void APIENTRY glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); 536 | GLAPI void APIENTRY glCopyTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); 537 | GLAPI void APIENTRY glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); 538 | GLAPI void APIENTRY glCopyTexImage1D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); 539 | GLAPI void APIENTRY glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels); 540 | 541 | 542 | /* GL Array API - Only GL_TRIANGLES, GL_TRIANGLE_STRIP, and GL_QUADS are supported */ 543 | GLAPI void APIENTRY glVertexPointer(GLint size, GLenum type, 544 | GLsizei stride, const GLvoid *pointer); 545 | 546 | GLAPI void APIENTRY glTexCoordPointer(GLint size, GLenum type, 547 | GLsizei stride, const GLvoid *pointer); 548 | 549 | /* If a Normal Pointer is set and GL Lighting has been enabled, 550 | Vertex Lighting will be used instead of glColorPointer */ 551 | GLAPI void APIENTRY glNormalPointer(GLenum type, GLsizei stride, const GLvoid *pointer); 552 | 553 | /* Use either this OR glNormalPointer to color vertices, NOT both */ 554 | GLAPI void APIENTRY glColorPointer(GLint size, GLenum type, 555 | GLsizei stride, const GLvoid *pointer); 556 | 557 | /* Array Data Submission */ 558 | GLAPI void APIENTRY glDrawArrays(GLenum mode, GLint first, GLsizei count); 559 | GLAPI void APIENTRY glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); 560 | 561 | GLAPI void APIENTRY glEnableClientState(GLenum cap); 562 | GLAPI void APIENTRY glDisableClientState(GLenum cap); 563 | 564 | /* Transformation / Matrix Functions */ 565 | 566 | GLAPI void APIENTRY glMatrixMode(GLenum mode); 567 | 568 | GLAPI void APIENTRY glLoadIdentity(); 569 | 570 | GLAPI void APIENTRY glLoadMatrixf(const GLfloat *m); 571 | GLAPI void APIENTRY glLoadTransposeMatrixf(const GLfloat *m); 572 | GLAPI void APIENTRY glMultMatrixf(const GLfloat *m); 573 | GLAPI void APIENTRY glMultTransposeMatrixf(const GLfloat *m); 574 | 575 | GLAPI void APIENTRY glPushMatrix(); 576 | GLAPI void APIENTRY glPopMatrix(); 577 | 578 | GLAPI void APIENTRY glTranslatef(GLfloat x, GLfloat y, GLfloat z); 579 | #define glTranslated glTranslatef 580 | 581 | GLAPI void APIENTRY glScalef(GLfloat x, GLfloat y, GLfloat z); 582 | #define glScaled glScalef 583 | 584 | GLAPI void APIENTRY glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z); 585 | #define glRotated glRotatef 586 | 587 | GLAPI void APIENTRY glOrtho(GLfloat left, GLfloat right, 588 | GLfloat bottom, GLfloat top, 589 | GLfloat znear, GLfloat zfar); 590 | 591 | GLAPI void APIENTRY glViewport(GLint x, GLint y, GLsizei width, GLsizei height); 592 | 593 | GLAPI void APIENTRY glScissor(GLint x, GLint y, GLsizei width, GLsizei height); 594 | 595 | GLAPI void APIENTRY glKosGetMatrix(GLenum mode, GLfloat *params); 596 | 597 | GLAPI void APIENTRY glFrustum(GLfloat left, GLfloat right, 598 | GLfloat bottom, GLfloat top, 599 | GLfloat znear, GLfloat zfar); 600 | 601 | /* Fog Functions - client must enable GL_FOG for this to take effect */ 602 | GLAPI void APIENTRY glFogi(GLenum pname, GLint param); 603 | GLAPI void APIENTRY glFogf(GLenum pname, GLfloat param); 604 | GLAPI void APIENTRY glFogfv(GLenum pname, const GLfloat *params); 605 | 606 | /* Lighting Functions - client must enable GL_LIGHTING for this to take effect */ 607 | 608 | /* Set Individual Light Parameters */ 609 | GLAPI void APIENTRY glLightfv(GLenum light, GLenum pname, const GLfloat *params); 610 | GLAPI void APIENTRY glLightf(GLenum light, GLenum pname, GLfloat param); 611 | 612 | GLAPI void APIENTRY glLightModelf(GLenum pname, const GLfloat param); 613 | GLAPI void APIENTRY glLightModeli(GLenum pname, const GLint param); 614 | GLAPI void APIENTRY glLightModelfv(GLenum pname, const GLfloat *params); 615 | GLAPI void APIENTRY glLightModeliv(GLenum pname, const GLint *params); 616 | 617 | 618 | /* Set Global Material Parameters */ 619 | GLAPI void APIENTRY glMateriali(GLenum face, GLenum pname, const GLint param); 620 | GLAPI void APIENTRY glMaterialf(GLenum face, GLenum pname, const GLfloat param); 621 | GLAPI void APIENTRY glMaterialfv(GLenum face, GLenum pname, const GLfloat *params); 622 | GLAPI void APIENTRY glColorMaterial(GLenum face, GLenum mode); 623 | 624 | /* glGet Functions */ 625 | GLAPI void APIENTRY glGetBooleanv(GLenum pname, GLboolean* params); 626 | GLAPI void APIENTRY glGetIntegerv(GLenum pname, GLint *params); 627 | GLAPI void APIENTRY glGetFloatv(GLenum pname, GLfloat *params); 628 | GLAPI GLboolean APIENTRY glIsEnabled(GLenum cap); 629 | GLAPI const GLubyte* APIENTRY glGetString(GLenum name); 630 | 631 | /* Error handling */ 632 | GLAPI GLenum APIENTRY glGetError(void); 633 | 634 | /* Non Operational Stubs for portability */ 635 | GLAPI void APIENTRY glAlphaFunc(GLenum func, GLclampf ref); 636 | GLAPI void APIENTRY glLineWidth(GLfloat width); 637 | GLAPI void APIENTRY glPolygonOffset(GLfloat factor, GLfloat units); 638 | GLAPI void APIENTRY glGetTexParameteriv(GLenum target, GLenum pname, GLint * params); 639 | GLAPI void APIENTRY glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); 640 | GLAPI void APIENTRY glPixelStorei(GLenum pname, GLint param); 641 | 642 | __END_DECLS 643 | 644 | #endif /* !__GL_GL_H */ 645 | -------------------------------------------------------------------------------- /samples/GLdc/include/GL/glext.h: -------------------------------------------------------------------------------- 1 | /* KallistiGL for KallistiOS ##version## 2 | 3 | libgl/glext.h 4 | Copyright (C) 2014 Josh Pearson 5 | Copyright (c) 2007-2013 The Khronos Group Inc. 6 | */ 7 | 8 | #ifndef __GL_GLEXT_H 9 | #define __GL_GLEXT_H 10 | 11 | #include 12 | __BEGIN_DECLS 13 | 14 | #define GL_TEXTURE0_ARB 0x84C0 15 | #define GL_TEXTURE1_ARB 0x84C1 16 | #define GL_TEXTURE2_ARB 0x84C2 17 | #define GL_TEXTURE3_ARB 0x84C3 18 | #define GL_TEXTURE4_ARB 0x84C4 19 | #define GL_TEXTURE5_ARB 0x84C5 20 | #define GL_TEXTURE6_ARB 0x84C6 21 | #define GL_TEXTURE7_ARB 0x84C7 22 | #define GL_TEXTURE8_ARB 0x84C8 23 | #define GL_TEXTURE9_ARB 0x84C9 24 | #define GL_TEXTURE10_ARB 0x84CA 25 | #define GL_TEXTURE11_ARB 0x84CB 26 | #define GL_TEXTURE12_ARB 0x84CC 27 | #define GL_TEXTURE13_ARB 0x84CD 28 | #define GL_TEXTURE14_ARB 0x84CE 29 | #define GL_TEXTURE15_ARB 0x84CF 30 | #define GL_TEXTURE16_ARB 0x84D0 31 | #define GL_TEXTURE17_ARB 0x84D1 32 | #define GL_TEXTURE18_ARB 0x84D2 33 | #define GL_TEXTURE19_ARB 0x84D3 34 | #define GL_TEXTURE20_ARB 0x84D4 35 | #define GL_TEXTURE21_ARB 0x84D5 36 | #define GL_TEXTURE22_ARB 0x84D6 37 | #define GL_TEXTURE23_ARB 0x84D7 38 | #define GL_TEXTURE24_ARB 0x84D8 39 | #define GL_TEXTURE25_ARB 0x84D9 40 | #define GL_TEXTURE26_ARB 0x84DA 41 | #define GL_TEXTURE27_ARB 0x84DB 42 | #define GL_TEXTURE28_ARB 0x84DC 43 | #define GL_TEXTURE29_ARB 0x84DD 44 | #define GL_TEXTURE30_ARB 0x84DE 45 | #define GL_TEXTURE31_ARB 0x84DF 46 | #define GL_ACTIVE_TEXTURE_ARB 0x84E0 47 | #define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1 48 | #define GL_MAX_TEXTURE_UNITS_ARB 0x84E2 49 | 50 | #define GL_CLAMP_TO_EDGE 0x812F 51 | 52 | #define GL_TRANSPOSE_MODELVIEW_MATRIX_ARB 0x84E3 53 | #define GL_TRANSPOSE_PROJECTION_MATRIX_ARB 0x84E4 54 | #define GL_TRANSPOSE_TEXTURE_MATRIX_ARB 0x84E5 55 | #define GL_TRANSPOSE_COLOR_MATRIX_ARB 0x84E6 56 | 57 | #define GL_MULTISAMPLE_ARB 0x809D 58 | #define GL_SAMPLE_ALPHA_TO_COVERAGE_ARB 0x809E 59 | #define GL_SAMPLE_ALPHA_TO_ONE_ARB 0x809F 60 | #define GL_SAMPLE_COVERAGE_ARB 0x80A0 61 | #define GL_SAMPLE_BUFFERS_ARB 0x80A8 62 | #define GL_SAMPLES_ARB 0x80A9 63 | #define GL_SAMPLE_COVERAGE_VALUE_ARB 0x80AA 64 | #define GL_SAMPLE_COVERAGE_INVERT_ARB 0x80AB 65 | #define GL_MULTISAMPLE_BIT_ARB 0x20000000 66 | 67 | #define GL_NORMAL_MAP_ARB 0x8511 68 | #define GL_REFLECTION_MAP_ARB 0x8512 69 | #define GL_TEXTURE_CUBE_MAP_ARB 0x8513 70 | #define GL_TEXTURE_BINDING_CUBE_MAP_ARB 0x8514 71 | #define GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x8515 72 | #define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x8516 73 | #define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x8517 74 | #define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x8518 75 | #define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x8519 76 | #define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x851A 77 | #define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B 78 | #define GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB 0x851C 79 | 80 | #define GL_COMPRESSED_ALPHA_ARB 0x84E9 81 | #define GL_COMPRESSED_LUMINANCE_ARB 0x84EA 82 | #define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB 83 | #define GL_COMPRESSED_INTENSITY_ARB 0x84EC 84 | #define GL_COMPRESSED_RGB_ARB 0x84ED 85 | #define GL_COMPRESSED_RGBA_ARB 0x84EE 86 | #define GL_TEXTURE_COMPRESSION_HINT_ARB 0x84EF 87 | #define GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB 0x86A0 88 | #define GL_TEXTURE_COMPRESSED_ARB 0x86A1 89 | #define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2 90 | #define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3 91 | 92 | #define GL_COLOR_ATTACHMENT0_EXT 0x8CE0 93 | #define GL_COLOR_ATTACHMENT1_EXT 0x8CE1 94 | #define GL_COLOR_ATTACHMENT2_EXT 0x8CE2 95 | #define GL_COLOR_ATTACHMENT3_EXT 0x8CE3 96 | #define GL_COLOR_ATTACHMENT4_EXT 0x8CE4 97 | #define GL_COLOR_ATTACHMENT5_EXT 0x8CE5 98 | #define GL_COLOR_ATTACHMENT6_EXT 0x8CE6 99 | #define GL_COLOR_ATTACHMENT7_EXT 0x8CE7 100 | #define GL_COLOR_ATTACHMENT8_EXT 0x8CE8 101 | #define GL_COLOR_ATTACHMENT9_EXT 0x8CE9 102 | #define GL_COLOR_ATTACHMENT10_EXT 0x8CEA 103 | #define GL_COLOR_ATTACHMENT11_EXT 0x8CEB 104 | #define GL_COLOR_ATTACHMENT12_EXT 0x8CEC 105 | #define GL_COLOR_ATTACHMENT13_EXT 0x8CED 106 | #define GL_COLOR_ATTACHMENT14_EXT 0x8CEE 107 | #define GL_COLOR_ATTACHMENT15_EXT 0x8CEF 108 | #define GL_DEPTH_ATTACHMENT_EXT 0x8D00 109 | #define GL_STENCIL_ATTACHMENT_EXT 0x8D20 110 | #define GL_FRAMEBUFFER_EXT 0x8D40 111 | #define GL_RENDERBUFFER_EXT 0x8D41 112 | #define GL_RENDERBUFFER_WIDTH_EXT 0x8D42 113 | #define GL_RENDERBUFFER_HEIGHT_EXT 0x8D43 114 | #define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44 115 | 116 | #define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5 117 | #define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6 118 | #define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7 119 | #define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB 120 | #define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC 121 | #define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD 122 | #define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506 123 | 124 | /* Multitexture extensions */ 125 | GLAPI void APIENTRY glActiveTextureARB(GLenum texture); 126 | GLAPI void APIENTRY glClientActiveTextureARB(GLenum texture); 127 | GLAPI void APIENTRY glMultiTexCoord2fARB(GLenum target, GLfloat s, GLfloat t); 128 | 129 | GLAPI void APIENTRY glGenFramebuffersEXT(GLsizei n, GLuint* framebuffers); 130 | GLAPI void APIENTRY glDeleteFramebuffersEXT(GLsizei n, const GLuint* framebuffers); 131 | GLAPI void APIENTRY glBindFramebufferEXT(GLenum target, GLuint framebuffer); 132 | GLAPI void APIENTRY glFramebufferTexture2DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); 133 | GLAPI void APIENTRY glGenerateMipmapEXT(GLenum target); 134 | GLAPI GLenum APIENTRY glCheckFramebufferStatusEXT(GLenum target); 135 | GLAPI GLboolean APIENTRY glIsFramebufferEXT(GLuint framebuffer); 136 | 137 | /* ext_paletted_texture */ 138 | #define GL_COLOR_INDEX1_EXT 0x80E2 139 | #define GL_COLOR_INDEX2_EXT 0x80E3 140 | #define GL_COLOR_INDEX4_EXT 0x80E4 141 | #define GL_COLOR_INDEX8_EXT 0x80E5 142 | #define GL_COLOR_INDEX12_EXT 0x80E6 143 | #define GL_COLOR_INDEX16_EXT 0x80E7 144 | 145 | #define GL_COLOR_TABLE_FORMAT_EXT 0x80D8 146 | #define GL_COLOR_TABLE_WIDTH_EXT 0x80D9 147 | #define GL_COLOR_TABLE_RED_SIZE_EXT 0x80DA 148 | #define GL_COLOR_TABLE_GREEN_SIZE_EXT 0x80DB 149 | #define GL_COLOR_TABLE_BLUE_SIZE_EXT 0x80DC 150 | #define GL_COLOR_TABLE_ALPHA_SIZE_EXT 0x80DD 151 | #define GL_COLOR_TABLE_LUMINANCE_SIZE_EXT 0x80DE 152 | #define GL_COLOR_TABLE_INTENSITY_SIZE_EXT 0x80DF 153 | 154 | #define GL_TEXTURE_INDEX_SIZE_EXT 0x80ED 155 | 156 | #define GL_SHARED_TEXTURE_PALETTE_EXT 0x81FB 157 | 158 | GLAPI void APIENTRY glColorTableEXT(GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *data); 159 | GLAPI void APIENTRY glColorSubTableEXT(GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data); 160 | GLAPI void APIENTRY glGetColorTableEXT(GLenum target, GLenum format, GLenum type, GLvoid *data); 161 | GLAPI void APIENTRY glGetColorTableParameterivEXT(GLenum target, GLenum pname, GLint *params); 162 | GLAPI void APIENTRY glGetColorTableParameterfvEXT(GLenum target, GLenum pname, GLfloat *params); 163 | 164 | /* Loads VQ compressed texture from SH4 RAM into PVR VRAM */ 165 | /* internalformat must be one of the following constants: 166 | GL_UNSIGNED_SHORT_5_6_5_VQ 167 | GL_UNSIGNED_SHORT_5_6_5_VQ_TWID 168 | GL_UNSIGNED_SHORT_4_4_4_4_VQ 169 | GL_UNSIGNED_SHORT_4_4_4_4_VQ_TWID 170 | GL_UNSIGNED_SHORT_1_5_5_5_VQ 171 | GL_UNSIGNED_SHORT_1_5_5_5_VQ_TWID 172 | */ 173 | GLAPI void APIENTRY glCompressedTexImage2DARB(GLenum target, 174 | GLint level, 175 | GLenum internalformat, 176 | GLsizei width, 177 | GLsizei height, 178 | GLint border, 179 | GLsizei imageSize, 180 | const GLvoid *data); 181 | 182 | 183 | /* Core aliases */ 184 | #define GL_INVALID_FRAMEBUFFER_OPERATION GL_INVALID_FRAMEBUFFER_OPERATION_EXT 185 | 186 | #define glActiveTexture glActiveTextureARB 187 | #define glClientActiveTexture glClientActiveTextureARB 188 | #define glMultiTexCoord2f glMultiTexCoord2fARB 189 | 190 | #define glGenerateMipmap glGenerateMipmapEXT 191 | #define glCompressedTexImage2D glCompressedTexImage2DARB 192 | 193 | __END_DECLS 194 | 195 | #endif /* !__GL_GLEXT_H */ 196 | -------------------------------------------------------------------------------- /samples/GLdc/include/GL/glkos.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "gl.h" 4 | 5 | __BEGIN_DECLS 6 | 7 | /* 8 | * Dreamcast specific compressed + twiddled formats. 9 | * We use constants from the range 0xEEE0 onwards 10 | * to avoid trampling any real GL constants (this is in the middle of the 11 | * any_vendor_future_use range defined in the GL enum.spec file. 12 | */ 13 | #define GL_UNSIGNED_SHORT_5_6_5_TWID_KOS 0xEEE0 14 | #define GL_UNSIGNED_SHORT_1_5_5_5_REV_TWID_KOS 0xEEE2 15 | #define GL_UNSIGNED_SHORT_4_4_4_4_REV_TWID_KOS 0xEEE3 16 | 17 | #define GL_COMPRESSED_RGB_565_VQ_KOS 0xEEE4 18 | #define GL_COMPRESSED_ARGB_1555_VQ_KOS 0xEEE6 19 | #define GL_COMPRESSED_ARGB_4444_VQ_KOS 0xEEE7 20 | 21 | #define GL_COMPRESSED_RGB_565_VQ_TWID_KOS 0xEEE8 22 | #define GL_COMPRESSED_ARGB_1555_VQ_TWID_KOS 0xEEEA 23 | #define GL_COMPRESSED_ARGB_4444_VQ_TWID_KOS 0xEEEB 24 | 25 | #define GL_COMPRESSED_RGB_565_VQ_MIPMAP_KOS 0xEEEC 26 | #define GL_COMPRESSED_ARGB_1555_VQ_MIPMAP_KOS 0xEEED 27 | #define GL_COMPRESSED_ARGB_4444_VQ_MIPMAP_KOS 0xEEEE 28 | 29 | #define GL_COMPRESSED_RGB_565_VQ_MIPMAP_TWID_KOS 0xEEEF 30 | #define GL_COMPRESSED_ARGB_1555_VQ_MIPMAP_TWID_KOS 0xEEF0 31 | #define GL_COMPRESSED_ARGB_4444_VQ_MIPMAP_TWID_KOS 0xEEF1 32 | 33 | #define GL_NEARZ_CLIPPING_KOS 0xEEFA 34 | 35 | #define GL_UNSIGNED_BYTE_TWID_KOS 0xEEFB 36 | 37 | 38 | /* Initialize the GL pipeline. GL will initialize the PVR. */ 39 | GLAPI void APIENTRY glKosInit(); 40 | 41 | typedef struct { 42 | /* If GL_TRUE, enables pvr autosorting, this *will* break glDepthFunc/glDepthTest */ 43 | GLboolean autosort_enabled; 44 | 45 | /* The internal format for paletted textures, must be GL_RGBA4 (default) or GL_RGBA8 */ 46 | GLenum internal_palette_format; 47 | 48 | /* Initial capacity of each of the OP, TR and PT lists in vertices */ 49 | GLuint initial_op_capacity; 50 | GLuint initial_tr_capacity; 51 | GLuint initial_pt_capacity; 52 | GLuint initial_immediate_capacity; 53 | } GLdcConfig; 54 | 55 | 56 | GLAPI void APIENTRY glKosInitConfig(GLdcConfig* config); 57 | 58 | /* Usage: 59 | * 60 | * GLdcConfig config; 61 | * glKosInitConfig(&config); 62 | * 63 | * config.autosort_enabled = GL_TRUE; 64 | * 65 | * glKosInitEx(&config); 66 | */ 67 | GLAPI void APIENTRY glKosInitEx(GLdcConfig* config); 68 | GLAPI void APIENTRY glKosSwapBuffers(); 69 | 70 | /* 71 | * CUSTOM EXTENSION multiple_shared_palette_KOS 72 | * 73 | * This extension allows using up to 4 different shared palettes 74 | * with ColorTableEXT. The following constants are provided 75 | * to use as targets for ColorTableExt: 76 | * 77 | * - SHARED_TEXTURE_PALETTE_0_KOS 78 | * - SHARED_TEXTURE_PALETTE_1_KOS 79 | * - SHARED_TEXTURE_PALETTE_2_KOS 80 | * - SHARED_TEXTURE_PALETTE_3_KOS 81 | * 82 | * In this use case SHARED_TEXTURE_PALETTE_0_KOS is interchangable with SHARED_TEXTURE_PALETTE_EXT 83 | * (both refer to the first shared palette). 84 | * 85 | * To select which palette a texture uses, a new pname is accepted by TexParameteri: SHARED_TEXTURE_BANK_KOS 86 | * by default textures use shared palette 0. 87 | */ 88 | 89 | #define GL_SHARED_TEXTURE_PALETTE_0_KOS 0xEEFC 90 | #define GL_SHARED_TEXTURE_PALETTE_1_KOS 0xEEFD 91 | #define GL_SHARED_TEXTURE_PALETTE_2_KOS 0xEEFE 92 | #define GL_SHARED_TEXTURE_PALETTE_3_KOS 0xEEFF 93 | 94 | /* Pass to glTexParameteri to set the shared bank */ 95 | #define GL_SHARED_TEXTURE_BANK_KOS 0xEF00 96 | 97 | __END_DECLS 98 | 99 | -------------------------------------------------------------------------------- /samples/GLdc/include/GL/glu.h: -------------------------------------------------------------------------------- 1 | /* KallistiGL for KallistiOS ##version## 2 | 3 | libgl/glu.h 4 | Copyright (C) 2013-2014 Josh "PH3NOM" Pearson 5 | Copyright (C) 2016 Lawrence Sebald 6 | 7 | Some functionality adapted from the original KOS libgl: 8 | Copyright (C) 2001 Dan Potter 9 | Copyright (C) 2002 Benoit Miller 10 | 11 | */ 12 | 13 | #ifndef __GL_GLU_H 14 | #define __GL_GLU_H 15 | 16 | #include 17 | __BEGIN_DECLS 18 | 19 | #ifndef BUILD_LIBGL 20 | #include 21 | #endif 22 | 23 | #define GLU_FALSE 0 24 | #define GLU_TRUE 1 25 | 26 | GLAPI void APIENTRY gluOrtho2D(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top); 27 | 28 | /* gluPerspective - Set the Perspective for Rendering. */ 29 | GLAPI void APIENTRY gluPerspective(GLdouble fovy, GLdouble aspect, 30 | GLdouble zNear, GLdouble zFar); 31 | 32 | /* gluLookAt - Set Camera Position for Rendering. */ 33 | GLAPI void APIENTRY gluLookAt(GLfloat eyex, GLfloat eyey, GLfloat eyez, 34 | GLfloat centerx, GLfloat centery, GLfloat centerz, 35 | GLfloat upx, GLfloat upy, GLfloat upz); 36 | 37 | GLAPI const GLubyte* APIENTRY gluErrorString(GLenum error); 38 | 39 | __END_DECLS 40 | 41 | #endif /* !__GL_GLU_H */ 42 | -------------------------------------------------------------------------------- /samples/Makefile: -------------------------------------------------------------------------------- 1 | 2 | # Manipulate the CFLAGS to look our *our* version of the library and includes 3 | INC_DIR = $(abspath ../include) 4 | LIB_DIR = $(abspath ../) 5 | export CFLAGS := $(CFLAGS) -I $(INC_DIR) 6 | export OBJEXTRA := $(LIB_DIR)/libAL.a 7 | 8 | 9 | all: 10 | $(KOS_MAKE) -C basic all 11 | $(KOS_MAKE) -C helicopter all 12 | $(KOS_MAKE) -C streaming all 13 | 14 | -------------------------------------------------------------------------------- /samples/basic/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = basic.elf 2 | OBJS = main.o 3 | 4 | all: rm-elf $(TARGET) 5 | 6 | include $(KOS_BASE)/Makefile.rules 7 | 8 | clean: 9 | -rm -f $(TARGET) $(OBJS) romdisk.* 10 | 11 | rm-elf: 12 | -rm -f $(TARGET) romdisk.* 13 | 14 | $(TARGET): $(OBJS) romdisk.o 15 | $(KOS_CC) $(KOS_CFLAGS) $(KOS_LDFLAGS) -o $(TARGET) $(KOS_START) \ 16 | $(OBJS) romdisk.o $(OBJEXTRA) -lm -lkosutils $(KOS_LIBS) 17 | 18 | romdisk.img: 19 | $(KOS_GENROMFS) -f romdisk.img -d romdisk -v 20 | 21 | romdisk.o: romdisk.img 22 | $(KOS_BASE)/utils/bin2o/bin2o romdisk.img romdisk romdisk.o 23 | 24 | run: $(TARGET) 25 | $(KOS_LOADER) $(TARGET) 26 | 27 | dist: 28 | rm -f $(OBJS) romdisk.o romdisk.img 29 | $(KOS_STRIP) $(TARGET) 30 | -------------------------------------------------------------------------------- /samples/basic/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenAL example 3 | * 4 | * Copyright(C) Florian Fainelli 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | 18 | #ifdef _arch_dreamcast 19 | extern uint8 romdisk[]; 20 | KOS_INIT_ROMDISK(romdisk); 21 | #endif 22 | 23 | static void list_audio_devices(const ALCchar *devices) 24 | { 25 | const ALCchar *device = devices, *next = devices + 1; 26 | size_t len = 0; 27 | 28 | fprintf(stdout, "Devices list:\n"); 29 | fprintf(stdout, "----------\n"); 30 | while (device && *device != '\0' && next && *next != '\0') { 31 | fprintf(stdout, "%s\n", device); 32 | len = strlen(device); 33 | device += (len + 1); 34 | next += (len + 2); 35 | } 36 | fprintf(stdout, "----------\n"); 37 | } 38 | 39 | #define TEST_ERROR(_msg) \ 40 | error = alGetError(); \ 41 | if (error != AL_NO_ERROR) { \ 42 | fprintf(stderr, "ERROR: "); \ 43 | fprintf(stderr, _msg "\n"); \ 44 | return -1; \ 45 | } 46 | 47 | static inline ALenum to_al_format(short channels, short samples) 48 | { 49 | bool stereo = (channels > 1); 50 | 51 | switch (samples) { 52 | case 16: 53 | if (stereo) 54 | return AL_FORMAT_STEREO16; 55 | else 56 | return AL_FORMAT_MONO16; 57 | case 8: 58 | if (stereo) 59 | return AL_FORMAT_STEREO8; 60 | else 61 | return AL_FORMAT_MONO8; 62 | default: 63 | return -1; 64 | } 65 | } 66 | 67 | static bool is_big_endian() { 68 | int a = 1; 69 | return !((char*)&a)[0]; 70 | } 71 | 72 | int convert_to_int(char* buffer, int len) { 73 | int i = 0; 74 | int a = 0; 75 | if (!is_big_endian()) 76 | for (; i 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | extern uint8 romdisk[]; 20 | KOS_INIT_ROMDISK(romdisk); 21 | 22 | typedef struct { 23 | float x, y, z; 24 | } Vec3; 25 | 26 | Vec3 vec3_init(float x, float y, float z) { 27 | Vec3 ret; 28 | ret.x = x; 29 | ret.y = y; 30 | ret.z = z; 31 | return ret; 32 | } 33 | 34 | Vec3 vec3_add(const Vec3* lhs, const Vec3* rhs) { 35 | Vec3 ret; 36 | ret.x = lhs->x + rhs->x; 37 | ret.y = lhs->y + rhs->y; 38 | ret.z = lhs->z + rhs->z; 39 | return ret; 40 | } 41 | 42 | Vec3 vec3_sub(const Vec3* lhs, const Vec3* rhs) { 43 | Vec3 ret; 44 | ret.x = lhs->x - rhs->x; 45 | ret.y = lhs->y - rhs->y; 46 | ret.z = lhs->z - rhs->z; 47 | return ret; 48 | } 49 | 50 | Vec3 vec3_scale(const Vec3* lhs, float x) { 51 | Vec3 ret; 52 | ret.x = lhs->x * x; 53 | ret.y = lhs->y * x; 54 | ret.z = lhs->z * x; 55 | return ret; 56 | } 57 | 58 | Vec3 vec3_cross(const Vec3* lhs, const Vec3* rhs) { 59 | Vec3 ret; 60 | ret.x = (lhs->y * rhs->z) - (lhs->z * rhs->y); 61 | ret.y = (lhs->z * rhs->x) - (lhs->x * rhs->z); 62 | ret.z = (lhs->x * rhs->y) - (lhs->y * rhs->x); 63 | return ret; 64 | } 65 | 66 | float vec3_length(const Vec3* v) { 67 | return sqrtf((v->x * v->x) + (v->y * v->y) + (v->z * v->z)); 68 | } 69 | 70 | Vec3 vec3_normalize(const Vec3* v) { 71 | Vec3 ret; 72 | float l = 1.0f / vec3_length(v); 73 | ret.x = v->x * l; 74 | ret.y = v->y * l; 75 | ret.z = v->z * l; 76 | return ret; 77 | } 78 | 79 | void render_helicopter(Vec3 position, Vec3 direction) { 80 | int i = 0; 81 | Vec3 up = vec3_init(0, 1, 0); 82 | Vec3 r = vec3_cross(&direction, &up); 83 | Vec3 two_dir = vec3_scale(&direction, 2.0f); 84 | 85 | Vec3 front = vec3_add(&position, &direction); 86 | Vec3 back = vec3_sub(&position, &two_dir); 87 | Vec3 top = vec3_add(&position, &up); 88 | Vec3 bottom = vec3_sub(&position, &up); 89 | Vec3 right = vec3_add(&position, &r); 90 | Vec3 left = vec3_sub(&position, &r); 91 | 92 | glColor3f(1.0f, 0.0f, 0.0f); 93 | glBegin(GL_TRIANGLES); 94 | glVertex3fv((float*) &front); 95 | glVertex3fv((float*) &left); 96 | glVertex3fv((float*) &top); 97 | 98 | glVertex3fv((float*) &front); 99 | glVertex3fv((float*) &bottom); 100 | glVertex3fv((float*) &left); 101 | 102 | glVertex3fv((float*) &front); 103 | glVertex3fv((float*) &top); 104 | glVertex3fv((float*) &right); 105 | 106 | glVertex3fv((float*) &front); 107 | glVertex3fv((float*) &right); 108 | glVertex3fv((float*) &bottom); 109 | 110 | glVertex3fv((float*) &top); 111 | glVertex3fv((float*) &right); 112 | glVertex3fv((float*) &back); 113 | 114 | glVertex3fv((float*) &right); 115 | glVertex3fv((float*) &bottom); 116 | glVertex3fv((float*) &back); 117 | 118 | glVertex3fv((float*) &top); 119 | glVertex3fv((float*) &back); 120 | glVertex3fv((float*) &left); 121 | 122 | glVertex3fv((float*) &left); 123 | glVertex3fv((float*) &back); 124 | glVertex3fv((float*) &bottom); 125 | glEnd(); 126 | 127 | 128 | const float R = 2.0f; 129 | const float TWOPI = 3.14159f * 2.0f; 130 | 131 | glColor3f(0.7, 0.7, 0.7); 132 | glBegin(GL_TRIANGLE_FAN); 133 | for(i = 0; i < 20; ++i) { 134 | float x = R * sin(i * TWOPI / 18); 135 | float z = R * cos(i * TWOPI / 18); 136 | glVertex3f(position.x + x, top.y + 0.5, position.z + z); 137 | } 138 | glEnd(); 139 | } 140 | 141 | ALCdevice* device = NULL; 142 | ALCcontext* context = NULL; 143 | ALuint source = 0; 144 | ALuint buffer = 0; 145 | 146 | /* A general OpenGL initialization function. Sets all of the initial parameters. */ 147 | void InitGL(int Width, int Height) // We call this right after our OpenGL window is created. 148 | { 149 | glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // This Will Clear The Background Color To Black 150 | glClearDepth(1.0); // Enables Clearing Of The Depth Buffer 151 | glDepthFunc(GL_LEQUAL); // The Type Of Depth Test To Do 152 | glEnable(GL_DEPTH_TEST); // Enables Depth Testing 153 | glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading 154 | 155 | glMatrixMode(GL_PROJECTION); 156 | glLoadIdentity(); // Reset The Projection Matrix 157 | 158 | gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f); // Calculate The Aspect Ratio Of The Window 159 | 160 | glMatrixMode(GL_MODELVIEW); 161 | glClearColor(0.0f, 0.0f, 1.0f, 1.0f); 162 | 163 | const ALCchar* defaultDeviceName = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER); 164 | device = alcOpenDevice(defaultDeviceName); 165 | assert(device); 166 | 167 | context = alcCreateContext(device, NULL); 168 | assert(context); 169 | alcMakeContextCurrent(context); 170 | 171 | ALvoid *data; 172 | ALsizei size, freq; 173 | ALenum format; 174 | 175 | alGetError(); 176 | 177 | alutInit(0, NULL); 178 | alutLoadWAVFile((ALbyte*) "/rd/test.wav", &format, &data, &size, &freq); 179 | assert(alutGetError() == ALUT_ERROR_NO_ERROR); 180 | 181 | alGenSources((ALuint)1, &source); 182 | alSourcei(source, AL_LOOPING, AL_TRUE); 183 | 184 | alGenBuffers(1, &buffer); 185 | alBufferData(buffer, format, data, size, freq); 186 | alSourcei(source, AL_BUFFER, buffer); 187 | alSourcePlay(source); 188 | 189 | ALfloat listenerOri[] = { 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f }; 190 | alListenerfv(AL_ORIENTATION, listenerOri); 191 | 192 | alSourcef(source, AL_PITCH, 1); 193 | alSourcef(source, AL_GAIN, 1); 194 | } 195 | 196 | /* The function called when our window is resized (which shouldn't happen, because we're fullscreen) */ 197 | void ReSizeGLScene(int Width, int Height) 198 | { 199 | if (Height == 0) // Prevent A Divide By Zero If The Window Is Too Small 200 | Height = 1; 201 | 202 | glViewport(0, 0, Width, Height); // Reset The Current Viewport And Perspective Transformation 203 | 204 | glMatrixMode(GL_PROJECTION); 205 | glLoadIdentity(); 206 | 207 | gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f); 208 | glMatrixMode(GL_MODELVIEW); 209 | } 210 | 211 | 212 | /* The main drawing function. */ 213 | void DrawGLScene() 214 | { 215 | static float t = 0.0f; 216 | const float r = 10.0f; 217 | 218 | t += 0.01f; 219 | 220 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer 221 | glLoadIdentity(); // Reset The View 222 | 223 | Vec3 pos = vec3_init(sin(t) * r, 0, cos(t) * r); 224 | Vec3 target = vec3_init(sin(t + 0.1) * r, 0, cos(t + 0.1) * r); 225 | 226 | Vec3 dir = vec3_sub(&target, &pos); 227 | vec3_normalize(&dir); 228 | 229 | alSource3f(source, AL_POSITION, pos.x, pos.y, pos.z); 230 | alSource3f(source, AL_VELOCITY, dir.x, dir.y, dir.z); 231 | 232 | render_helicopter(pos, dir); 233 | 234 | glKosSwapBuffers(); 235 | } 236 | 237 | int main(int argc, char **argv) 238 | { 239 | glKosInit(); 240 | 241 | InitGL(640, 480); 242 | ReSizeGLScene(640, 480); 243 | 244 | while(1) { 245 | DrawGLScene(); 246 | } 247 | 248 | return 0; 249 | } 250 | -------------------------------------------------------------------------------- /samples/helicopter/romdisk/PLACEHOLDER: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kazade/ALdc/d5672e2556d8433ed2e348d1bb27487a5285a03a/samples/helicopter/romdisk/PLACEHOLDER -------------------------------------------------------------------------------- /samples/helicopter/romdisk/test.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kazade/ALdc/d5672e2556d8433ed2e348d1bb27487a5285a03a/samples/helicopter/romdisk/test.wav -------------------------------------------------------------------------------- /samples/streaming/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = streaming.elf 2 | OBJS = main.o 3 | 4 | all: rm-elf $(TARGET) 5 | 6 | include $(KOS_BASE)/Makefile.rules 7 | 8 | clean: 9 | -rm -f $(TARGET) $(OBJS) romdisk.* 10 | 11 | rm-elf: 12 | -rm -f $(TARGET) romdisk.* 13 | 14 | $(TARGET): $(OBJS) romdisk.o 15 | $(KOS_CC) $(KOS_CFLAGS) $(KOS_LDFLAGS) -o $(TARGET) $(KOS_START) \ 16 | $(OBJS) romdisk.o $(OBJEXTRA) -L../GL -lGLdc -I../GL -lm -lkosutils $(KOS_LIBS) 17 | 18 | romdisk.img: 19 | $(KOS_GENROMFS) -f romdisk.img -d romdisk -v 20 | 21 | romdisk.o: romdisk.img 22 | $(KOS_BASE)/utils/bin2o/bin2o romdisk.img romdisk romdisk.o 23 | 24 | run: $(TARGET) 25 | $(KOS_LOADER) $(TARGET) 26 | 27 | dist: 28 | rm -f $(OBJS) romdisk.o romdisk.img 29 | $(KOS_STRIP) $(TARGET) 30 | -------------------------------------------------------------------------------- /samples/streaming/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Streaming OpenAL Sample 3 | * 4 | * Copyright (c) Florian Fainelli 5 | * Copyright (c) 2019 HaydenKow 6 | * Copyright (c) 2019 Luke Benstead 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | #include 20 | 21 | extern uint8 romdisk[]; 22 | KOS_INIT_ROMDISK(romdisk); 23 | 24 | static void list_audio_devices(const ALCchar *devices) 25 | { 26 | const ALCchar *device = devices, *next = devices + 1; 27 | size_t len = 0; 28 | 29 | fprintf(stdout, "Devices list:\n"); 30 | fprintf(stdout, "----------\n"); 31 | while (device && *device != '\0' && next && *next != '\0') 32 | { 33 | fprintf(stdout, "%s\n", device); 34 | len = strlen(device); 35 | device += (len + 1); 36 | next += (len + 2); 37 | } 38 | fprintf(stdout, "----------\n"); 39 | } 40 | 41 | #define TEST_ERROR(_msg) \ 42 | error = alGetError(); \ 43 | if (error != AL_NO_ERROR) \ 44 | { \ 45 | fprintf(stderr, "ERROR: "); \ 46 | fprintf(stderr, _msg "\n"); \ 47 | return -1; \ 48 | } 49 | 50 | static inline ALenum to_al_format(short channels, short samples) 51 | { 52 | bool stereo = (channels > 1); 53 | 54 | switch (samples) 55 | { 56 | case 16: 57 | if (stereo) 58 | return AL_FORMAT_STEREO16; 59 | else 60 | return AL_FORMAT_MONO16; 61 | case 8: 62 | if (stereo) 63 | return AL_FORMAT_STEREO8; 64 | else 65 | return AL_FORMAT_MONO8; 66 | default: 67 | return -1; 68 | } 69 | } 70 | 71 | static bool is_big_endian() 72 | { 73 | int a = 1; 74 | return !((char *)&a)[0]; 75 | } 76 | 77 | int convert_to_int(char *buffer, int len) 78 | { 79 | int i = 0; 80 | int a = 0; 81 | if (!is_big_endian()) 82 | for (; i < len; i++) 83 | ((char *)&a)[i] = buffer[i]; 84 | else 85 | for (; i < len; i++) 86 | ((char *)&a)[3 - i] = buffer[i]; 87 | return a; 88 | } 89 | 90 | static FILE *in; 91 | #define DATA_CHUNK_SIZE (1024 * 64) 92 | 93 | static const int WAV_data_start = 44; 94 | static int WAV_size; 95 | #define MIN(a, b) (((a) < (b)) ? (a) : (b)) 96 | #define MAX(a, b) (((a) > (b)) ? (a) : (b)) 97 | 98 | static void WAVE_buffer(void *data) 99 | { 100 | 101 | int spare = WAV_size - ftell(in); 102 | int read = fread(data, 1, MIN(DATA_CHUNK_SIZE, spare), in); 103 | printf("Reading WAV: read: %d spare:%d\n", read, spare); 104 | if (read < DATA_CHUNK_SIZE) 105 | { 106 | printf("Writing silence\n"); 107 | fseek(in, WAV_data_start, SEEK_SET); 108 | memset(&((char *)data)[read], 0, DATA_CHUNK_SIZE - read); 109 | //fread(&((char*)data)[read], DATA_CHUNK_SIZE-read, 1, in); 110 | } 111 | } 112 | 113 | ALboolean LoadWAVFile(const char *filename, ALenum *format, ALsizei *size, ALsizei *freq) 114 | { 115 | char buffer[4]; 116 | 117 | in = fopen(filename, "rb"); 118 | if (!in) 119 | { 120 | fprintf(stderr, "Couldn't open file\n"); 121 | return AL_FALSE; 122 | } 123 | fseek(in, 0, SEEK_END); 124 | WAV_size = ftell(in); 125 | fseek(in, 0, SEEK_SET); 126 | 127 | fread(buffer, 4, sizeof(char), in); 128 | 129 | if (strncmp(buffer, "RIFF", 4) != 0) 130 | { 131 | fprintf(stderr, "Not a valid wave file\n"); 132 | return AL_FALSE; 133 | } 134 | 135 | fread(buffer, 4, sizeof(char), in); 136 | fread(buffer, 4, sizeof(char), in); //WAVE 137 | fread(buffer, 4, sizeof(char), in); //fmt 138 | fread(buffer, 4, sizeof(char), in); //16 139 | fread(buffer, 2, sizeof(char), in); //1 140 | fread(buffer, 2, sizeof(char), in); 141 | 142 | int chan = convert_to_int(buffer, 2); 143 | fread(buffer, 4, sizeof(char), in); 144 | *freq = convert_to_int(buffer, 4); 145 | fread(buffer, 4, sizeof(char), in); 146 | fread(buffer, 2, sizeof(char), in); 147 | fread(buffer, 2, sizeof(char), in); 148 | int bps = convert_to_int(buffer, 2); 149 | fread(buffer, 4, sizeof(char), in); //data 150 | fread(buffer, 4, sizeof(char), in); 151 | *size = (ALsizei)convert_to_int(buffer, 4); 152 | //*data = (ALvoid*) malloc(DATA_CHUNK_SIZE * sizeof(char)); 153 | //fread(*data, DATA_CHUNK_SIZE, sizeof(char), in); 154 | 155 | if (chan == 1) 156 | { 157 | *format = (bps == 8) ? AL_FORMAT_MONO8 : AL_FORMAT_MONO16; 158 | } 159 | else 160 | { 161 | *format = (bps == 8) ? AL_FORMAT_STEREO8 : AL_FORMAT_STEREO16; 162 | } 163 | 164 | //fclose(in); 165 | 166 | printf("Loaded WAV file!\n"); 167 | 168 | return AL_TRUE; 169 | } 170 | 171 | ALCenum error; 172 | 173 | int setupHelicopter(void) 174 | { 175 | ALuint source, buffer; 176 | ALsizei size, freq; 177 | ALenum format; 178 | ALvoid *data; 179 | 180 | alGenSources((ALuint)1, &source); 181 | TEST_ERROR("source generation"); 182 | 183 | alSourcef(source, AL_PITCH, 1); 184 | TEST_ERROR("source pitch"); 185 | alSourcef(source, AL_GAIN, 1); 186 | TEST_ERROR("source gain"); 187 | alSource3f(source, AL_POSITION, 0, 0, 0); 188 | TEST_ERROR("source position"); 189 | alSource3f(source, AL_VELOCITY, 0, 0, 0); 190 | TEST_ERROR("source velocity"); 191 | alSourcei(source, AL_LOOPING, AL_FALSE); 192 | TEST_ERROR("source looping"); 193 | 194 | alGenBuffers(1, &buffer); 195 | TEST_ERROR("buffer generation"); 196 | 197 | if (!LoadWAVFile("/rd/test.wav", &format, &size, &freq)) { 198 | return -1; 199 | } 200 | 201 | data = (ALvoid *)malloc(size); 202 | fread(data, size, sizeof(char), in); 203 | fclose(in); 204 | TEST_ERROR("loading wav file"); 205 | 206 | alBufferData(buffer, format, data, size, freq); 207 | TEST_ERROR("buffer copy"); 208 | free(data); 209 | alSourcei(source, AL_BUFFER, buffer); 210 | TEST_ERROR("buffer binding"); 211 | 212 | alSourcei(source, AL_LOOPING, 1); 213 | alSourcePlay(source); 214 | TEST_ERROR("source playing"); 215 | 216 | return 0; 217 | } 218 | int main(int argc, char **argv) 219 | { 220 | ALboolean enumeration; 221 | const ALCchar *defaultDeviceName = argv[1]; 222 | ALCdevice *device; 223 | ALCcontext *context; 224 | ALsizei size, freq; 225 | ALenum format; 226 | ALuint source; 227 | ALfloat listenerOri[] = {0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f}; 228 | ALint source_state; 229 | 230 | enumeration = alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT"); 231 | if (enumeration == AL_FALSE) 232 | fprintf(stderr, "enumeration extension not available\n"); 233 | 234 | list_audio_devices(alcGetString(NULL, ALC_DEVICE_SPECIFIER)); 235 | 236 | if (!defaultDeviceName) 237 | defaultDeviceName = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER); 238 | 239 | device = alcOpenDevice(defaultDeviceName); 240 | if (!device) 241 | { 242 | fprintf(stderr, "unable to open default device\n"); 243 | return -1; 244 | } 245 | 246 | // fprintf(stdout, "Device: %s\n", alcGetString(device, ALC_DEVICE_SPECIFIER)); 247 | 248 | alGetError(); 249 | 250 | context = alcCreateContext(device, NULL); 251 | if (!alcMakeContextCurrent(context)) 252 | { 253 | fprintf(stderr, "failed to make default context\n"); 254 | return -1; 255 | } 256 | TEST_ERROR("make default context"); 257 | 258 | /* set orientation */ 259 | alListener3f(AL_POSITION, 0, 0, 1.0f); 260 | TEST_ERROR("listener position"); 261 | alListener3f(AL_VELOCITY, 0, 0, 0); 262 | TEST_ERROR("listener velocity"); 263 | alListenerfv(AL_ORIENTATION, listenerOri); 264 | TEST_ERROR("listener orientation"); 265 | 266 | setupHelicopter(); 267 | 268 | alGenSources((ALuint)1, &source); 269 | TEST_ERROR("source generation"); 270 | 271 | alSourcef(source, AL_PITCH, 1); 272 | TEST_ERROR("source pitch"); 273 | alSourcef(source, AL_GAIN, 1); 274 | TEST_ERROR("source gain"); 275 | alSource3f(source, AL_POSITION, 0, 0, 0); 276 | TEST_ERROR("source position"); 277 | alSource3f(source, AL_VELOCITY, 0, 0, 0); 278 | TEST_ERROR("source velocity"); 279 | //alSourcei(source, AL_LOOPING, AL_FALSE); 280 | TEST_ERROR("source looping"); 281 | 282 | // This example uses 4 buffers and 1 source 283 | static ALuint buffer[4]; 284 | 285 | alGenSources((ALsizei)1, &source); 286 | alGenBuffers((ALsizei)4, buffer); 287 | TEST_ERROR("buffer generation"); 288 | 289 | if (!LoadWAVFile("/rd/file_1.wav", &format, &size, &freq)) 290 | { 291 | return -1; 292 | } 293 | 294 | ALvoid *data; 295 | 296 | int i; 297 | // Fill all the buffers with audio data from the wave file 298 | for (i = 0; i < 4; i++) 299 | { 300 | data = malloc(DATA_CHUNK_SIZE); 301 | WAVE_buffer(data); 302 | alBufferData(buffer[i], format, data, DATA_CHUNK_SIZE, freq); 303 | free(data); 304 | alSourceQueueBuffers(source, 1, &buffer[i]); 305 | } 306 | TEST_ERROR("loading wav file"); 307 | 308 | ALint iBuffersProcessed; 309 | ALint iTotalBuffersProcessed; 310 | ALuint uiBuffer; 311 | // Buffer queuing loop must operate in a new thread 312 | iBuffersProcessed = 0; 313 | 314 | alSourcePlay(source); 315 | TEST_ERROR("source playing"); 316 | 317 | while (1) 318 | { 319 | alGetSourcei(source, AL_SOURCE_STATE, &source_state); 320 | TEST_ERROR("source state get"); 321 | while (source_state == AL_PLAYING) 322 | { 323 | alGetSourcei(source, AL_BUFFERS_PROCESSED, &iBuffersProcessed); 324 | 325 | // Buffer queuing loop must operate in a new thread 326 | iBuffersProcessed = 0; 327 | alGetSourcei(source, AL_BUFFERS_PROCESSED, &iBuffersProcessed); 328 | 329 | iTotalBuffersProcessed += iBuffersProcessed; 330 | 331 | // For each processed buffer, remove it from the source queue, read the next chunk of 332 | // audio data from the file, fill the buffer with new data, and add it to the source queue 333 | while (iBuffersProcessed) 334 | { 335 | // Remove the buffer from the queue (uiBuffer contains the buffer ID for the dequeued buffer) 336 | uiBuffer = 0; 337 | alSourceUnqueueBuffers(source, 1, &uiBuffer); 338 | 339 | // Read more pData audio data (if there is any) 340 | data = malloc(DATA_CHUNK_SIZE); 341 | WAVE_buffer(data); 342 | // Copy audio data to buffer 343 | alBufferData(uiBuffer, format, data, DATA_CHUNK_SIZE, freq); 344 | free(data); 345 | // Insert the audio buffer to the source queue 346 | alSourceQueueBuffers(source, 1, &uiBuffer); 347 | 348 | iBuffersProcessed--; 349 | } 350 | 351 | alGetSourcei(source, AL_SOURCE_STATE, &source_state); 352 | TEST_ERROR("source state get"); 353 | thd_pass(); 354 | } 355 | } 356 | fclose(in); 357 | 358 | /* exit context */ 359 | alDeleteSources(1, &source); 360 | alDeleteBuffers(4, &buffer[0]); 361 | device = alcGetContextsDevice(context); 362 | alcMakeContextCurrent(NULL); 363 | alcDestroyContext(context); 364 | alcCloseDevice(device); 365 | 366 | return 0; 367 | } 368 | -------------------------------------------------------------------------------- /samples/streaming/romdisk/PLACEHOLDER: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kazade/ALdc/d5672e2556d8433ed2e348d1bb27487a5285a03a/samples/streaming/romdisk/PLACEHOLDER -------------------------------------------------------------------------------- /samples/streaming/romdisk/file_1.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kazade/ALdc/d5672e2556d8433ed2e348d1bb27487a5285a03a/samples/streaming/romdisk/file_1.wav -------------------------------------------------------------------------------- /samples/streaming/romdisk/test.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kazade/ALdc/d5672e2556d8433ed2e348d1bb27487a5285a03a/samples/streaming/romdisk/test.wav --------------------------------------------------------------------------------