| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | #define SG_BUILD_LIBRARY |
| 16 | #include <siege/audio/buffer.h> |
| 17 | |
| 18 | #include <stdlib.h> |
| 19 | #include <string.h> |
| 20 | |
| 21 | #include <al.h> |
| 22 | #include <alc.h> |
| 23 | |
| 24 | #include "../internal/stb/stb_vorbis.h" |
| 25 | |
| 26 | |
| 27 | #define ALBUF(x)(*(ALuint*)(x)->handle) (*(ALuint*)(x)->handle) |
| 28 | |
| 29 | |
| 30 | static void* toStereo(SGuint channels, void* data, size_t* datalen, ALuint* alformat) |
| 31 | { |
| 32 | void* odata = data; |
| 33 | if(channels == 2) |
| 6 | | Assuming 'channels' is not equal to 2 | |
|
| |
| 34 | { |
| 35 | if(*alformat == AL_FORMAT_MONO80x1100) |
| 36 | *alformat = AL_FORMAT_STEREO80x1102; |
| 37 | else |
| 38 | *alformat = AL_FORMAT_STEREO160x1103; |
| 39 | } |
| 40 | else if(channels > 2) |
| 8 | | Assuming 'channels' is > 2 | |
|
| |
| 41 | { |
| 42 | SGuint chan; |
| 43 | SGuint i; |
| 44 | long double sum1; |
| 45 | long double sum2; |
| 46 | int num1; |
| 47 | int num2; |
| 48 | if(*alformat == AL_FORMAT_MONO80x1100) |
| |
| 49 | { |
| 50 | odata = malloc(*datalen * sizeof(SGubyte)); |
| 51 | memcpy(odata, data, *datalen * sizeof(SGubyte)); |
| 52 | |
| 53 | *alformat = AL_FORMAT_STEREO80x1102; |
| 54 | SGubyte* bdata = (SGubyte*) odata; |
| 55 | |
| 56 | for(i = 0; i < *datalen; i += channels) |
| 57 | { |
| 58 | sum1 = 0; |
| 59 | num1 = 0; |
| 60 | sum2 = 0; |
| 61 | num2 = 0; |
| 62 | |
| 63 | if(channels % 2 != 0) |
| 64 | { |
| 65 | chan = 1; |
| 66 | sum1 += bdata[i / channels] * 0.5L; |
| 67 | num1++; |
| 68 | sum2 += bdata[i / channels] * 0.5L; |
| 69 | num2++; |
| 70 | } |
| 71 | else |
| 72 | chan = 0; |
| 73 | for(; chan < channels; chan++) |
| 74 | { |
| 75 | if(chan % 2 == 0) |
| 76 | { |
| 77 | sum1 += bdata[i + chan]; |
| 78 | num1++; |
| 79 | } |
| 80 | else |
| 81 | { |
| 82 | sum2 += bdata[i + chan]; |
| 83 | num2++; |
| 84 | } |
| 85 | } |
| 86 | bdata[i / channels ] = (SGubyte)(sum1 / num1); |
| 87 | bdata[i / channels + 1] = (SGubyte)(sum2 / num2); |
| 88 | } |
| 89 | } |
| 90 | else |
| 91 | { |
| 92 | odata = malloc(*datalen * sizeof(SGushort)); |
| 11 | | Call to 'malloc' has an allocation size of 0 bytes |
|
| 93 | memcpy(odata, data, *datalen * sizeof(SGushort)); |
| 94 | |
| 95 | *alformat = AL_FORMAT_STEREO160x1103; |
| 96 | SGshort* sdata = (SGshort*) odata; |
| 97 | |
| 98 | for(i = 0; i < *datalen / 2; i += channels) |
| 99 | { |
| 100 | sum1 = 0; |
| 101 | num1 = 0; |
| 102 | sum2 = 0; |
| 103 | num2 = 0; |
| 104 | |
| 105 | if(channels % 2 != 0) |
| 106 | { |
| 107 | chan = 1; |
| 108 | sum1 += sdata[i / channels] * 0.5L; |
| 109 | num1++; |
| 110 | sum2 += sdata[i / channels] * 0.5L; |
| 111 | num2++; |
| 112 | } |
| 113 | else |
| 114 | chan = 0; |
| 115 | for(; chan < channels; chan++) |
| 116 | { |
| 117 | if(chan % 2 == 0) |
| 118 | { |
| 119 | sum1 += sdata[i + chan]; |
| 120 | num1++; |
| 121 | } |
| 122 | else |
| 123 | { |
| 124 | sum2 += sdata[i + chan]; |
| 125 | num2++; |
| 126 | } |
| 127 | } |
| 128 | sdata[i / channels ] = (SGushort)(sum1 / num1); |
| 129 | sdata[i / channels + 1] = (SGushort)(sum2 / num2); |
| 130 | } |
| 131 | } |
| 132 | *datalen = *datalen / channels * 2; |
| 133 | } |
| 134 | return odata; |
| 135 | } |
| 136 | |
| 137 | SGAudioBuffer* SG_CALL__cdecl sgAudioBufferCreateStream(SGStream* stream, SGbool delstream) |
| 138 | { |
| 139 | if(!stream || !stream->read || !stream->seek || !stream->tell) return NULL((void*)0); |
| 140 | |
| 141 | SGAudioBuffer* buffer = malloc(sizeof(SGAudioBuffer)); |
| 142 | if(!buffer) goto error; |
| 143 | |
| 144 | buffer->stream = stream; |
| 145 | buffer->del = delstream; |
| 146 | |
| 147 | buffer->handle = malloc(sizeof(ALuint)); |
| 148 | if(!buffer->handle) goto error; |
| 149 | alGenBuffers(1, buffer->handle); |
| 150 | |
| 151 | SGuint channels; |
| 152 | SGuint format; |
| 153 | SGuint frequency; |
| 154 | void* data = NULL((void*)0); |
| 155 | SGuint datalen; |
| 156 | SGuint nsamples; |
| 157 | |
| 158 | void* buf = NULL((void*)0); |
| 159 | int error = 0; |
| 160 | stb_vorbis* stb = NULL((void*)0); |
| 161 | stb_vorbis_info info; |
| 162 | |
| 163 | SGlong pos = sgStreamTell(stream); |
| 164 | SGlong size = sgStreamTellSize(stream); |
| 165 | size -= pos; |
| 166 | if(pos < 0 || size < 0) |
| 167 | goto lderr; |
| 168 | |
| 169 | buf = malloc(size); |
| 170 | if(sgStreamRead(stream, buf, 1, size) != size) |
| 171 | goto lderr; |
| 172 | |
| 173 | stb = stb_vorbis_open_memory(buf, size, &error, NULL((void*)0)); |
| 174 | if(!stb) goto lderr; |
| 175 | |
| 176 | info = stb_vorbis_get_info(stb); |
| 177 | channels = info.channels; |
| 178 | frequency = info.sample_rate; |
| 179 | format = SG_AUDIO_FORMAT_S160x02; |
| 180 | |
| 181 | nsamples = stb_vorbis_stream_length_in_samples(stb); |
| 182 | datalen = 2 * nsamples * channels; |
| 183 | data = malloc(datalen); |
| 184 | |
| 185 | datalen = 2 * stb_vorbis_get_samples_short_interleaved(stb, info.channels, data, datalen / 2); |
| 186 | |
| 187 | sgAudioBufferSetData(buffer, channels, format, frequency, data, datalen); |
| 188 | free(data); |
| 189 | |
| 190 | lderr: |
| 191 | if(stb) |
| 192 | stb_vorbis_close(stb); |
| 193 | if(buf) |
| 194 | free(buf); |
| 195 | return buffer; |
| 196 | |
| 197 | error: |
| 198 | if(buffer) |
| 199 | free(buffer); |
| 200 | return NULL((void*)0); |
| 201 | } |
| 202 | SGAudioBuffer* SG_CALL__cdecl sgAudioBufferCreateFile(const char* fname) |
| 203 | { |
| 204 | return sgAudioBufferCreateStream(sgStreamCreateFile(fname, "r"), SG_TRUE1); |
| 205 | } |
| 206 | void SG_CALL__cdecl sgAudioBufferDestroy(SGAudioBuffer* buffer) |
| 207 | { |
| 208 | if(buffer == NULL((void*)0)) |
| 209 | return; |
| 210 | |
| 211 | alDeleteBuffers(1, buffer->handle); |
| 212 | free(buffer->handle); |
| 213 | if(buffer->del) |
| 214 | sgStreamDestroy(buffer->stream); |
| 215 | free(buffer); |
| 216 | } |
| 217 | |
| 218 | void SG_CALL__cdecl sgAudioBufferSetData(SGAudioBuffer* buffer, SGuint channels, SGuint format, SGuint frequency, void* data, size_t datalen) |
| 219 | { |
| 220 | |
| 221 | ALuint alformat; |
| 222 | |
| 223 | SGuint i; |
| 224 | SGubyte* bdata = (SGubyte*)data; |
| 225 | SGshort* scur; |
| 226 | SGint* icur; |
| 227 | SGfloat* fcur; |
| 228 | SGdouble* dcur; |
| 229 | switch(format) |
| 1 | Control jumps to 'case 11:' at line 302 | |
|
| 230 | { |
| 231 | case SG_AUDIO_FORMAT_S80x01: |
| 232 | alformat = AL_FORMAT_MONO80x1100; |
| 233 | for(i = 0; i < datalen; i++) |
| 234 | bdata[i] = bdata[i] + 0x80; |
| 235 | break; |
| 236 | case SG_AUDIO_FORMAT_S160x02: |
| 237 | alformat = AL_FORMAT_MONO160x1101; |
| 238 | break; |
| 239 | case SG_AUDIO_FORMAT_S240x03: |
| 240 | alformat = AL_FORMAT_MONO160x1101; |
| 241 | for(i = 0; i < datalen; i += 3) |
| 242 | { |
| 243 | icur = (SGint*)&bdata[i]; |
| 244 | scur = (SGshort*)&bdata[i / 3 * 2]; |
| 245 | *scur = (SGshort)((*icur >> 8) / 256.0L); |
| 246 | } |
| 247 | datalen = datalen / 3 * 2; |
| 248 | break; |
| 249 | case SG_AUDIO_FORMAT_S320x04: |
| 250 | alformat = AL_FORMAT_MONO160x1101; |
| 251 | for(i = 0; i < datalen; i += 4) |
| 252 | { |
| 253 | icur = (SGint*)&bdata[i]; |
| 254 | scur = (SGshort*)&bdata[i / 4 * 2]; |
| 255 | *scur = (SGshort)(*icur / 65536.0L); |
| 256 | } |
| 257 | datalen = datalen / 4 * 2; |
| 258 | break; |
| 259 | |
| 260 | case SG_AUDIO_FORMAT_U80x05: |
| 261 | alformat = AL_FORMAT_MONO80x1100; |
| 262 | break; |
| 263 | case SG_AUDIO_FORMAT_U160x06: |
| 264 | alformat = AL_FORMAT_MONO160x1101; |
| 265 | for(i = 0; i < datalen; i += 2) |
| 266 | { |
| 267 | scur = (SGshort*)&bdata[i]; |
| 268 | *scur = *scur - 0x7FFF; |
| 269 | } |
| 270 | break; |
| 271 | case SG_AUDIO_FORMAT_U240x07: |
| 272 | alformat = AL_FORMAT_MONO160x1101; |
| 273 | for(i = 0; i < datalen; i += 3) |
| 274 | { |
| 275 | icur = (SGint*)&bdata[i]; |
| 276 | scur = (SGshort*)&bdata[i / 3 * 2]; |
| 277 | *scur = (SGshort)((*icur >> 8) / 256.0L) - 0x7FFF; |
| 278 | } |
| 279 | datalen = datalen / 3 * 2; |
| 280 | break; |
| 281 | case SG_AUDIO_FORMAT_U320x08: |
| 282 | alformat = AL_FORMAT_MONO160x1101; |
| 283 | for(i = 0; i < datalen; i += 4) |
| 284 | { |
| 285 | icur = (SGint*)&bdata[i]; |
| 286 | scur = (SGshort*)&bdata[i / 4 * 2]; |
| 287 | *scur = (SGshort)(*icur / 65536.0L) - 0x7FFF; |
| 288 | } |
| 289 | datalen = datalen / 4 * 2; |
| 290 | break; |
| 291 | |
| 292 | case SG_AUDIO_FORMAT_F0x0A: |
| 293 | alformat = AL_FORMAT_MONO160x1101; |
| 294 | for(i = 0; i < datalen; i += 4) |
| 295 | { |
| 296 | fcur = (SGfloat*)&bdata[i]; |
| 297 | scur = (SGshort*)&bdata[i / 4 * 2]; |
| 298 | *scur = (SGshort)(*fcur * 0xFFFF); |
| 299 | } |
| 300 | datalen = datalen / 4 * 2; |
| 301 | break; |
| 302 | case SG_AUDIO_FORMAT_D0x0B: |
| 303 | alformat = AL_FORMAT_MONO160x1101; |
| 304 | for(i = 0; i < datalen; i += 8) |
| 2 | | Assuming 'i' is >= 'datalen' | |
|
| 3 | | Loop condition is false. Execution continues on line 310 | |
|
| 305 | { |
| 306 | dcur = (SGdouble*)&bdata[i]; |
| 307 | scur = (SGshort*)&bdata[i / 8 * 2]; |
| 308 | *scur = (SGshort)(*dcur * 0xFFFF); |
| 309 | } |
| 310 | datalen = datalen / 8 * 2; |
| 311 | break; |
| 4 | | Execution continues on line 315 | |
|
| 312 | default: |
| 313 | return; |
| 314 | } |
| 315 | void* odata = toStereo(channels, data, &datalen, &alformat); |
| |
| 316 | alBufferData(ALBUF(buffer)(*(ALuint*)(buffer)->handle), alformat, odata, datalen, frequency); |
| 317 | if(data != odata) |
| 318 | free(odata); |
| 319 | } |