alBuffer.c 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305
  1. /**
  2. * OpenAL cross platform audio library
  3. * Copyright (C) 1999-2007 by authors.
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Library General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2 of the License, or (at your option) any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Library General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Library General Public
  15. * License along with this library; if not, write to the
  16. * Free Software Foundation, Inc.,
  17. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  18. * Or go to http://www.gnu.org/copyleft/lgpl.html
  19. */
  20. #include "config.h"
  21. #include <stdlib.h>
  22. #include <stdio.h>
  23. #include <assert.h>
  24. #include <limits.h>
  25. #ifdef HAVE_MALLOC_H
  26. #include <malloc.h>
  27. #endif
  28. #include "alMain.h"
  29. #include "alu.h"
  30. #include "alError.h"
  31. #include "alBuffer.h"
  32. #include "sample_cvt.h"
  33. extern inline void LockBufferList(ALCdevice *device);
  34. extern inline void UnlockBufferList(ALCdevice *device);
  35. extern inline ALsizei FrameSizeFromUserFmt(enum UserFmtChannels chans, enum UserFmtType type);
  36. extern inline ALsizei FrameSizeFromFmt(enum FmtChannels chans, enum FmtType type);
  37. static ALbuffer *AllocBuffer(ALCcontext *context);
  38. static void FreeBuffer(ALCdevice *device, ALbuffer *buffer);
  39. static const ALchar *NameFromUserFmtType(enum UserFmtType type);
  40. static void LoadData(ALCcontext *context, ALbuffer *buffer, ALuint freq, ALsizei size,
  41. enum UserFmtChannels SrcChannels, enum UserFmtType SrcType,
  42. const ALvoid *data, ALbitfieldSOFT access);
  43. static ALboolean DecomposeUserFormat(ALenum format, enum UserFmtChannels *chans, enum UserFmtType *type);
  44. static ALsizei SanitizeAlignment(enum UserFmtType type, ALsizei align);
  45. static inline ALbuffer *LookupBuffer(ALCdevice *device, ALuint id)
  46. {
  47. BufferSubList *sublist;
  48. ALuint lidx = (id-1) >> 6;
  49. ALsizei slidx = (id-1) & 0x3f;
  50. if(UNLIKELY(lidx >= VECTOR_SIZE(device->BufferList)))
  51. return NULL;
  52. sublist = &VECTOR_ELEM(device->BufferList, lidx);
  53. if(UNLIKELY(sublist->FreeMask & (U64(1)<<slidx)))
  54. return NULL;
  55. return sublist->Buffers + slidx;
  56. }
  57. #define INVALID_STORAGE_MASK ~(AL_MAP_READ_BIT_SOFT | AL_MAP_WRITE_BIT_SOFT | AL_PRESERVE_DATA_BIT_SOFT | AL_MAP_PERSISTENT_BIT_SOFT)
  58. #define MAP_READ_WRITE_FLAGS (AL_MAP_READ_BIT_SOFT | AL_MAP_WRITE_BIT_SOFT)
  59. #define INVALID_MAP_FLAGS ~(AL_MAP_READ_BIT_SOFT | AL_MAP_WRITE_BIT_SOFT | AL_MAP_PERSISTENT_BIT_SOFT)
  60. AL_API ALvoid AL_APIENTRY alGenBuffers(ALsizei n, ALuint *buffers)
  61. {
  62. ALCcontext *context;
  63. ALsizei cur = 0;
  64. context = GetContextRef();
  65. if(!context) return;
  66. if(!(n >= 0))
  67. alSetError(context, AL_INVALID_VALUE, "Generating %d buffers", n);
  68. else for(cur = 0;cur < n;cur++)
  69. {
  70. ALbuffer *buffer = AllocBuffer(context);
  71. if(!buffer)
  72. {
  73. alDeleteBuffers(cur, buffers);
  74. break;
  75. }
  76. buffers[cur] = buffer->id;
  77. }
  78. ALCcontext_DecRef(context);
  79. }
  80. AL_API ALvoid AL_APIENTRY alDeleteBuffers(ALsizei n, const ALuint *buffers)
  81. {
  82. ALCdevice *device;
  83. ALCcontext *context;
  84. ALbuffer *ALBuf;
  85. ALsizei i;
  86. context = GetContextRef();
  87. if(!context) return;
  88. device = context->Device;
  89. LockBufferList(device);
  90. if(UNLIKELY(n < 0))
  91. {
  92. alSetError(context, AL_INVALID_VALUE, "Deleting %d buffers", n);
  93. goto done;
  94. }
  95. for(i = 0;i < n;i++)
  96. {
  97. if(!buffers[i])
  98. continue;
  99. /* Check for valid Buffer ID, and make sure it's not in use. */
  100. if((ALBuf=LookupBuffer(device, buffers[i])) == NULL)
  101. {
  102. alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffers[i]);
  103. goto done;
  104. }
  105. if(ReadRef(&ALBuf->ref) != 0)
  106. {
  107. alSetError(context, AL_INVALID_OPERATION, "Deleting in-use buffer %u", buffers[i]);
  108. goto done;
  109. }
  110. }
  111. for(i = 0;i < n;i++)
  112. {
  113. if((ALBuf=LookupBuffer(device, buffers[i])) != NULL)
  114. FreeBuffer(device, ALBuf);
  115. }
  116. done:
  117. UnlockBufferList(device);
  118. ALCcontext_DecRef(context);
  119. }
  120. AL_API ALboolean AL_APIENTRY alIsBuffer(ALuint buffer)
  121. {
  122. ALCcontext *context;
  123. ALboolean ret;
  124. context = GetContextRef();
  125. if(!context) return AL_FALSE;
  126. LockBufferList(context->Device);
  127. ret = ((!buffer || LookupBuffer(context->Device, buffer)) ?
  128. AL_TRUE : AL_FALSE);
  129. UnlockBufferList(context->Device);
  130. ALCcontext_DecRef(context);
  131. return ret;
  132. }
  133. AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq)
  134. { alBufferStorageSOFT(buffer, format, data, size, freq, 0); }
  135. AL_API void AL_APIENTRY alBufferStorageSOFT(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq, ALbitfieldSOFT flags)
  136. {
  137. enum UserFmtChannels srcchannels = UserFmtMono;
  138. enum UserFmtType srctype = UserFmtUByte;
  139. ALCdevice *device;
  140. ALCcontext *context;
  141. ALbuffer *albuf;
  142. context = GetContextRef();
  143. if(!context) return;
  144. device = context->Device;
  145. LockBufferList(device);
  146. if(UNLIKELY((albuf=LookupBuffer(device, buffer)) == NULL))
  147. alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
  148. else if(UNLIKELY(size < 0))
  149. alSetError(context, AL_INVALID_VALUE, "Negative storage size %d", size);
  150. else if(UNLIKELY(freq < 1))
  151. alSetError(context, AL_INVALID_VALUE, "Invalid sample rate %d", freq);
  152. else if(UNLIKELY((flags&INVALID_STORAGE_MASK) != 0))
  153. alSetError(context, AL_INVALID_VALUE, "Invalid storage flags 0x%x",
  154. flags&INVALID_STORAGE_MASK);
  155. else if(UNLIKELY((flags&AL_MAP_PERSISTENT_BIT_SOFT) && !(flags&MAP_READ_WRITE_FLAGS)))
  156. alSetError(context, AL_INVALID_VALUE,
  157. "Declaring persistently mapped storage without read or write access");
  158. else if(UNLIKELY(DecomposeUserFormat(format, &srcchannels, &srctype) == AL_FALSE))
  159. alSetError(context, AL_INVALID_ENUM, "Invalid format 0x%04x", format);
  160. else
  161. LoadData(context, albuf, freq, size, srcchannels, srctype, data, flags);
  162. UnlockBufferList(device);
  163. ALCcontext_DecRef(context);
  164. }
  165. AL_API void* AL_APIENTRY alMapBufferSOFT(ALuint buffer, ALsizei offset, ALsizei length, ALbitfieldSOFT access)
  166. {
  167. void *retval = NULL;
  168. ALCdevice *device;
  169. ALCcontext *context;
  170. ALbuffer *albuf;
  171. context = GetContextRef();
  172. if(!context) return retval;
  173. device = context->Device;
  174. LockBufferList(device);
  175. if(UNLIKELY((albuf=LookupBuffer(device, buffer)) == NULL))
  176. alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
  177. else if(UNLIKELY((access&INVALID_MAP_FLAGS) != 0))
  178. alSetError(context, AL_INVALID_VALUE, "Invalid map flags 0x%x", access&INVALID_MAP_FLAGS);
  179. else if(UNLIKELY(!(access&MAP_READ_WRITE_FLAGS)))
  180. alSetError(context, AL_INVALID_VALUE, "Mapping buffer %u without read or write access",
  181. buffer);
  182. else
  183. {
  184. ALbitfieldSOFT unavailable = (albuf->Access^access) & access;
  185. if(UNLIKELY(ReadRef(&albuf->ref) != 0 && !(access&AL_MAP_PERSISTENT_BIT_SOFT)))
  186. alSetError(context, AL_INVALID_OPERATION,
  187. "Mapping in-use buffer %u without persistent mapping", buffer);
  188. else if(UNLIKELY(albuf->MappedAccess != 0))
  189. alSetError(context, AL_INVALID_OPERATION, "Mapping already-mapped buffer %u", buffer);
  190. else if(UNLIKELY((unavailable&AL_MAP_READ_BIT_SOFT)))
  191. alSetError(context, AL_INVALID_VALUE,
  192. "Mapping buffer %u for reading without read access", buffer);
  193. else if(UNLIKELY((unavailable&AL_MAP_WRITE_BIT_SOFT)))
  194. alSetError(context, AL_INVALID_VALUE,
  195. "Mapping buffer %u for writing without write access", buffer);
  196. else if(UNLIKELY((unavailable&AL_MAP_PERSISTENT_BIT_SOFT)))
  197. alSetError(context, AL_INVALID_VALUE,
  198. "Mapping buffer %u persistently without persistent access", buffer);
  199. else if(UNLIKELY(offset < 0 || offset >= albuf->OriginalSize ||
  200. length <= 0 || length > albuf->OriginalSize - offset))
  201. alSetError(context, AL_INVALID_VALUE, "Mapping invalid range %d+%d for buffer %u",
  202. offset, length, buffer);
  203. else
  204. {
  205. retval = (ALbyte*)albuf->data + offset;
  206. albuf->MappedAccess = access;
  207. albuf->MappedOffset = offset;
  208. albuf->MappedSize = length;
  209. }
  210. }
  211. UnlockBufferList(device);
  212. ALCcontext_DecRef(context);
  213. return retval;
  214. }
  215. AL_API void AL_APIENTRY alUnmapBufferSOFT(ALuint buffer)
  216. {
  217. ALCdevice *device;
  218. ALCcontext *context;
  219. ALbuffer *albuf;
  220. context = GetContextRef();
  221. if(!context) return;
  222. device = context->Device;
  223. LockBufferList(device);
  224. if((albuf=LookupBuffer(device, buffer)) == NULL)
  225. alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
  226. else if(albuf->MappedAccess == 0)
  227. alSetError(context, AL_INVALID_OPERATION, "Unmapping unmapped buffer %u", buffer);
  228. else
  229. {
  230. albuf->MappedAccess = 0;
  231. albuf->MappedOffset = 0;
  232. albuf->MappedSize = 0;
  233. }
  234. UnlockBufferList(device);
  235. ALCcontext_DecRef(context);
  236. }
  237. AL_API void AL_APIENTRY alFlushMappedBufferSOFT(ALuint buffer, ALsizei offset, ALsizei length)
  238. {
  239. ALCdevice *device;
  240. ALCcontext *context;
  241. ALbuffer *albuf;
  242. context = GetContextRef();
  243. if(!context) return;
  244. device = context->Device;
  245. LockBufferList(device);
  246. if(UNLIKELY((albuf=LookupBuffer(device, buffer)) == NULL))
  247. alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
  248. else if(UNLIKELY(!(albuf->MappedAccess&AL_MAP_WRITE_BIT_SOFT)))
  249. alSetError(context, AL_INVALID_OPERATION,
  250. "Flushing buffer %u while not mapped for writing", buffer);
  251. else if(UNLIKELY(offset < albuf->MappedOffset ||
  252. offset >= albuf->MappedOffset+albuf->MappedSize ||
  253. length <= 0 || length > albuf->MappedOffset+albuf->MappedSize-offset))
  254. alSetError(context, AL_INVALID_VALUE, "Flushing invalid range %d+%d on buffer %u",
  255. offset, length, buffer);
  256. else
  257. {
  258. /* FIXME: Need to use some method of double-buffering for the mixer and
  259. * app to hold separate memory, which can be safely transfered
  260. * asynchronously. Currently we just say the app shouldn't write where
  261. * OpenAL's reading, and hope for the best...
  262. */
  263. ATOMIC_THREAD_FENCE(almemory_order_seq_cst);
  264. }
  265. UnlockBufferList(device);
  266. ALCcontext_DecRef(context);
  267. }
  268. AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer, ALenum format, const ALvoid *data, ALsizei offset, ALsizei length)
  269. {
  270. enum UserFmtChannels srcchannels = UserFmtMono;
  271. enum UserFmtType srctype = UserFmtUByte;
  272. ALCdevice *device;
  273. ALCcontext *context;
  274. ALbuffer *albuf;
  275. context = GetContextRef();
  276. if(!context) return;
  277. device = context->Device;
  278. LockBufferList(device);
  279. if(UNLIKELY((albuf=LookupBuffer(device, buffer)) == NULL))
  280. alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
  281. else if(UNLIKELY(DecomposeUserFormat(format, &srcchannels, &srctype) == AL_FALSE))
  282. alSetError(context, AL_INVALID_ENUM, "Invalid format 0x%04x", format);
  283. else
  284. {
  285. ALsizei unpack_align, align;
  286. ALsizei byte_align;
  287. ALsizei frame_size;
  288. ALsizei num_chans;
  289. void *dst;
  290. unpack_align = ATOMIC_LOAD_SEQ(&albuf->UnpackAlign);
  291. align = SanitizeAlignment(srctype, unpack_align);
  292. if(UNLIKELY(align < 1))
  293. alSetError(context, AL_INVALID_VALUE, "Invalid unpack alignment %d", unpack_align);
  294. else if(UNLIKELY((long)srcchannels != (long)albuf->FmtChannels ||
  295. srctype != albuf->OriginalType))
  296. alSetError(context, AL_INVALID_ENUM, "Unpacking data with mismatched format");
  297. else if(UNLIKELY(align != albuf->OriginalAlign))
  298. alSetError(context, AL_INVALID_VALUE,
  299. "Unpacking data with alignment %u does not match original alignment %u",
  300. align, albuf->OriginalAlign);
  301. else if(UNLIKELY(albuf->MappedAccess != 0))
  302. alSetError(context, AL_INVALID_OPERATION, "Unpacking data into mapped buffer %u",
  303. buffer);
  304. else
  305. {
  306. num_chans = ChannelsFromFmt(albuf->FmtChannels);
  307. frame_size = num_chans * BytesFromFmt(albuf->FmtType);
  308. if(albuf->OriginalType == UserFmtIMA4)
  309. byte_align = ((align-1)/2 + 4) * num_chans;
  310. else if(albuf->OriginalType == UserFmtMSADPCM)
  311. byte_align = ((align-2)/2 + 7) * num_chans;
  312. else
  313. byte_align = align * frame_size;
  314. if(UNLIKELY(offset < 0 || length < 0 || offset > albuf->OriginalSize ||
  315. length > albuf->OriginalSize-offset))
  316. alSetError(context, AL_INVALID_VALUE, "Invalid data sub-range %d+%d on buffer %u",
  317. offset, length, buffer);
  318. else if(UNLIKELY((offset%byte_align) != 0))
  319. alSetError(context, AL_INVALID_VALUE,
  320. "Sub-range offset %d is not a multiple of frame size %d (%d unpack alignment)",
  321. offset, byte_align, align);
  322. else if(UNLIKELY((length%byte_align) != 0))
  323. alSetError(context, AL_INVALID_VALUE,
  324. "Sub-range length %d is not a multiple of frame size %d (%d unpack alignment)",
  325. length, byte_align, align);
  326. else
  327. {
  328. /* offset -> byte offset, length -> sample count */
  329. offset = offset/byte_align * align * frame_size;
  330. length = length/byte_align * align;
  331. dst = (ALbyte*)albuf->data + offset;
  332. if(srctype == UserFmtIMA4 && albuf->FmtType == FmtShort)
  333. Convert_ALshort_ALima4(dst, data, num_chans, length, align);
  334. else if(srctype == UserFmtMSADPCM && albuf->FmtType == FmtShort)
  335. Convert_ALshort_ALmsadpcm(dst, data, num_chans, length, align);
  336. else
  337. {
  338. assert((long)srctype == (long)albuf->FmtType);
  339. memcpy(dst, data, length*frame_size);
  340. }
  341. }
  342. }
  343. }
  344. UnlockBufferList(device);
  345. ALCcontext_DecRef(context);
  346. }
  347. AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint UNUSED(buffer),
  348. ALuint UNUSED(samplerate), ALenum UNUSED(internalformat), ALsizei UNUSED(samples),
  349. ALenum UNUSED(channels), ALenum UNUSED(type), const ALvoid *UNUSED(data))
  350. {
  351. ALCcontext *context;
  352. context = GetContextRef();
  353. if(!context) return;
  354. alSetError(context, AL_INVALID_OPERATION, "alBufferSamplesSOFT not supported");
  355. ALCcontext_DecRef(context);
  356. }
  357. AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint UNUSED(buffer),
  358. ALsizei UNUSED(offset), ALsizei UNUSED(samples),
  359. ALenum UNUSED(channels), ALenum UNUSED(type), const ALvoid *UNUSED(data))
  360. {
  361. ALCcontext *context;
  362. context = GetContextRef();
  363. if(!context) return;
  364. alSetError(context, AL_INVALID_OPERATION, "alBufferSubSamplesSOFT not supported");
  365. ALCcontext_DecRef(context);
  366. }
  367. AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint UNUSED(buffer),
  368. ALsizei UNUSED(offset), ALsizei UNUSED(samples),
  369. ALenum UNUSED(channels), ALenum UNUSED(type), ALvoid *UNUSED(data))
  370. {
  371. ALCcontext *context;
  372. context = GetContextRef();
  373. if(!context) return;
  374. alSetError(context, AL_INVALID_OPERATION, "alGetBufferSamplesSOFT not supported");
  375. ALCcontext_DecRef(context);
  376. }
  377. AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum UNUSED(format))
  378. {
  379. ALCcontext *context;
  380. context = GetContextRef();
  381. if(!context) return AL_FALSE;
  382. alSetError(context, AL_INVALID_OPERATION, "alIsBufferFormatSupportedSOFT not supported");
  383. ALCcontext_DecRef(context);
  384. return AL_FALSE;
  385. }
  386. AL_API void AL_APIENTRY alBufferf(ALuint buffer, ALenum param, ALfloat UNUSED(value))
  387. {
  388. ALCdevice *device;
  389. ALCcontext *context;
  390. context = GetContextRef();
  391. if(!context) return;
  392. device = context->Device;
  393. LockBufferList(device);
  394. if(UNLIKELY(LookupBuffer(device, buffer) == NULL))
  395. alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
  396. else switch(param)
  397. {
  398. default:
  399. alSetError(context, AL_INVALID_ENUM, "Invalid buffer float property 0x%04x", param);
  400. }
  401. UnlockBufferList(device);
  402. ALCcontext_DecRef(context);
  403. }
  404. AL_API void AL_APIENTRY alBuffer3f(ALuint buffer, ALenum param, ALfloat UNUSED(value1), ALfloat UNUSED(value2), ALfloat UNUSED(value3))
  405. {
  406. ALCdevice *device;
  407. ALCcontext *context;
  408. context = GetContextRef();
  409. if(!context) return;
  410. device = context->Device;
  411. LockBufferList(device);
  412. if(UNLIKELY(LookupBuffer(device, buffer) == NULL))
  413. alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
  414. else switch(param)
  415. {
  416. default:
  417. alSetError(context, AL_INVALID_ENUM, "Invalid buffer 3-float property 0x%04x", param);
  418. }
  419. UnlockBufferList(device);
  420. ALCcontext_DecRef(context);
  421. }
  422. AL_API void AL_APIENTRY alBufferfv(ALuint buffer, ALenum param, const ALfloat *values)
  423. {
  424. ALCdevice *device;
  425. ALCcontext *context;
  426. context = GetContextRef();
  427. if(!context) return;
  428. device = context->Device;
  429. LockBufferList(device);
  430. if(UNLIKELY(LookupBuffer(device, buffer) == NULL))
  431. alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
  432. else if(UNLIKELY(!values))
  433. alSetError(context, AL_INVALID_VALUE, "NULL pointer");
  434. else switch(param)
  435. {
  436. default:
  437. alSetError(context, AL_INVALID_ENUM, "Invalid buffer float-vector property 0x%04x", param);
  438. }
  439. UnlockBufferList(device);
  440. ALCcontext_DecRef(context);
  441. }
  442. AL_API void AL_APIENTRY alBufferi(ALuint buffer, ALenum param, ALint value)
  443. {
  444. ALCdevice *device;
  445. ALCcontext *context;
  446. ALbuffer *albuf;
  447. context = GetContextRef();
  448. if(!context) return;
  449. device = context->Device;
  450. LockBufferList(device);
  451. if(UNLIKELY((albuf=LookupBuffer(device, buffer)) == NULL))
  452. alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
  453. else switch(param)
  454. {
  455. case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
  456. if(UNLIKELY(value < 0))
  457. alSetError(context, AL_INVALID_VALUE, "Invalid unpack block alignment %d", value);
  458. else
  459. ATOMIC_STORE_SEQ(&albuf->UnpackAlign, value);
  460. break;
  461. case AL_PACK_BLOCK_ALIGNMENT_SOFT:
  462. if(UNLIKELY(value < 0))
  463. alSetError(context, AL_INVALID_VALUE, "Invalid pack block alignment %d", value);
  464. else
  465. ATOMIC_STORE_SEQ(&albuf->PackAlign, value);
  466. break;
  467. default:
  468. alSetError(context, AL_INVALID_ENUM, "Invalid buffer integer property 0x%04x", param);
  469. }
  470. UnlockBufferList(device);
  471. ALCcontext_DecRef(context);
  472. }
  473. AL_API void AL_APIENTRY alBuffer3i(ALuint buffer, ALenum param, ALint UNUSED(value1), ALint UNUSED(value2), ALint UNUSED(value3))
  474. {
  475. ALCdevice *device;
  476. ALCcontext *context;
  477. context = GetContextRef();
  478. if(!context) return;
  479. device = context->Device;
  480. LockBufferList(device);
  481. if(UNLIKELY(LookupBuffer(device, buffer) == NULL))
  482. alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
  483. else switch(param)
  484. {
  485. default:
  486. alSetError(context, AL_INVALID_ENUM, "Invalid buffer 3-integer property 0x%04x", param);
  487. }
  488. UnlockBufferList(device);
  489. ALCcontext_DecRef(context);
  490. }
  491. AL_API void AL_APIENTRY alBufferiv(ALuint buffer, ALenum param, const ALint *values)
  492. {
  493. ALCdevice *device;
  494. ALCcontext *context;
  495. ALbuffer *albuf;
  496. if(values)
  497. {
  498. switch(param)
  499. {
  500. case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
  501. case AL_PACK_BLOCK_ALIGNMENT_SOFT:
  502. alBufferi(buffer, param, values[0]);
  503. return;
  504. }
  505. }
  506. context = GetContextRef();
  507. if(!context) return;
  508. device = context->Device;
  509. LockBufferList(device);
  510. if(UNLIKELY((albuf=LookupBuffer(device, buffer)) == NULL))
  511. alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
  512. else if(UNLIKELY(!values))
  513. alSetError(context, AL_INVALID_VALUE, "NULL pointer");
  514. else switch(param)
  515. {
  516. case AL_LOOP_POINTS_SOFT:
  517. if(UNLIKELY(ReadRef(&albuf->ref) != 0))
  518. alSetError(context, AL_INVALID_OPERATION, "Modifying in-use buffer %u's loop points",
  519. buffer);
  520. else if(UNLIKELY(values[0] >= values[1] || values[0] < 0 || values[1] > albuf->SampleLen))
  521. alSetError(context, AL_INVALID_VALUE, "Invalid loop point range %d -> %d o buffer %u",
  522. values[0], values[1], buffer);
  523. else
  524. {
  525. albuf->LoopStart = values[0];
  526. albuf->LoopEnd = values[1];
  527. }
  528. break;
  529. default:
  530. alSetError(context, AL_INVALID_ENUM, "Invalid buffer integer-vector property 0x%04x",
  531. param);
  532. }
  533. UnlockBufferList(device);
  534. ALCcontext_DecRef(context);
  535. }
  536. AL_API ALvoid AL_APIENTRY alGetBufferf(ALuint buffer, ALenum param, ALfloat *value)
  537. {
  538. ALCdevice *device;
  539. ALCcontext *context;
  540. ALbuffer *albuf;
  541. context = GetContextRef();
  542. if(!context) return;
  543. device = context->Device;
  544. LockBufferList(device);
  545. if(UNLIKELY((albuf=LookupBuffer(device, buffer)) == NULL))
  546. alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
  547. else if(UNLIKELY(!value))
  548. alSetError(context, AL_INVALID_VALUE, "NULL pointer");
  549. else switch(param)
  550. {
  551. default:
  552. alSetError(context, AL_INVALID_ENUM, "Invalid buffer float property 0x%04x", param);
  553. }
  554. UnlockBufferList(device);
  555. ALCcontext_DecRef(context);
  556. }
  557. AL_API void AL_APIENTRY alGetBuffer3f(ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3)
  558. {
  559. ALCdevice *device;
  560. ALCcontext *context;
  561. context = GetContextRef();
  562. if(!context) return;
  563. device = context->Device;
  564. LockBufferList(device);
  565. if(UNLIKELY(LookupBuffer(device, buffer) == NULL))
  566. alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
  567. else if(UNLIKELY(!value1 || !value2 || !value3))
  568. alSetError(context, AL_INVALID_VALUE, "NULL pointer");
  569. else switch(param)
  570. {
  571. default:
  572. alSetError(context, AL_INVALID_ENUM, "Invalid buffer 3-float property 0x%04x", param);
  573. }
  574. UnlockBufferList(device);
  575. ALCcontext_DecRef(context);
  576. }
  577. AL_API void AL_APIENTRY alGetBufferfv(ALuint buffer, ALenum param, ALfloat *values)
  578. {
  579. ALCdevice *device;
  580. ALCcontext *context;
  581. switch(param)
  582. {
  583. case AL_SEC_LENGTH_SOFT:
  584. alGetBufferf(buffer, param, values);
  585. return;
  586. }
  587. context = GetContextRef();
  588. if(!context) return;
  589. device = context->Device;
  590. LockBufferList(device);
  591. if(UNLIKELY(LookupBuffer(device, buffer) == NULL))
  592. alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
  593. else if(UNLIKELY(!values))
  594. alSetError(context, AL_INVALID_VALUE, "NULL pointer");
  595. else switch(param)
  596. {
  597. default:
  598. alSetError(context, AL_INVALID_ENUM, "Invalid buffer float-vector property 0x%04x", param);
  599. }
  600. UnlockBufferList(device);
  601. ALCcontext_DecRef(context);
  602. }
  603. AL_API ALvoid AL_APIENTRY alGetBufferi(ALuint buffer, ALenum param, ALint *value)
  604. {
  605. ALCdevice *device;
  606. ALCcontext *context;
  607. ALbuffer *albuf;
  608. context = GetContextRef();
  609. if(!context) return;
  610. device = context->Device;
  611. LockBufferList(device);
  612. if(UNLIKELY((albuf=LookupBuffer(device, buffer)) == NULL))
  613. alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
  614. else if(UNLIKELY(!value))
  615. alSetError(context, AL_INVALID_VALUE, "NULL pointer");
  616. else switch(param)
  617. {
  618. case AL_FREQUENCY:
  619. *value = albuf->Frequency;
  620. break;
  621. case AL_BITS:
  622. *value = BytesFromFmt(albuf->FmtType) * 8;
  623. break;
  624. case AL_CHANNELS:
  625. *value = ChannelsFromFmt(albuf->FmtChannels);
  626. break;
  627. case AL_SIZE:
  628. *value = albuf->SampleLen * FrameSizeFromFmt(albuf->FmtChannels,
  629. albuf->FmtType);
  630. break;
  631. case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
  632. *value = ATOMIC_LOAD_SEQ(&albuf->UnpackAlign);
  633. break;
  634. case AL_PACK_BLOCK_ALIGNMENT_SOFT:
  635. *value = ATOMIC_LOAD_SEQ(&albuf->PackAlign);
  636. break;
  637. default:
  638. alSetError(context, AL_INVALID_ENUM, "Invalid buffer integer property 0x%04x", param);
  639. }
  640. UnlockBufferList(device);
  641. ALCcontext_DecRef(context);
  642. }
  643. AL_API void AL_APIENTRY alGetBuffer3i(ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3)
  644. {
  645. ALCdevice *device;
  646. ALCcontext *context;
  647. context = GetContextRef();
  648. if(!context) return;
  649. device = context->Device;
  650. LockBufferList(device);
  651. if(UNLIKELY(LookupBuffer(device, buffer) == NULL))
  652. alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
  653. else if(UNLIKELY(!value1 || !value2 || !value3))
  654. alSetError(context, AL_INVALID_VALUE, "NULL pointer");
  655. else switch(param)
  656. {
  657. default:
  658. alSetError(context, AL_INVALID_ENUM, "Invalid buffer 3-integer property 0x%04x", param);
  659. }
  660. UnlockBufferList(device);
  661. ALCcontext_DecRef(context);
  662. }
  663. AL_API void AL_APIENTRY alGetBufferiv(ALuint buffer, ALenum param, ALint *values)
  664. {
  665. ALCdevice *device;
  666. ALCcontext *context;
  667. ALbuffer *albuf;
  668. switch(param)
  669. {
  670. case AL_FREQUENCY:
  671. case AL_BITS:
  672. case AL_CHANNELS:
  673. case AL_SIZE:
  674. case AL_INTERNAL_FORMAT_SOFT:
  675. case AL_BYTE_LENGTH_SOFT:
  676. case AL_SAMPLE_LENGTH_SOFT:
  677. case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
  678. case AL_PACK_BLOCK_ALIGNMENT_SOFT:
  679. alGetBufferi(buffer, param, values);
  680. return;
  681. }
  682. context = GetContextRef();
  683. if(!context) return;
  684. device = context->Device;
  685. LockBufferList(device);
  686. if(UNLIKELY((albuf=LookupBuffer(device, buffer)) == NULL))
  687. alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
  688. else if(UNLIKELY(!values))
  689. alSetError(context, AL_INVALID_VALUE, "NULL pointer");
  690. else switch(param)
  691. {
  692. case AL_LOOP_POINTS_SOFT:
  693. values[0] = albuf->LoopStart;
  694. values[1] = albuf->LoopEnd;
  695. break;
  696. default:
  697. alSetError(context, AL_INVALID_ENUM, "Invalid buffer integer-vector property 0x%04x",
  698. param);
  699. }
  700. UnlockBufferList(device);
  701. ALCcontext_DecRef(context);
  702. }
  703. static const ALchar *NameFromUserFmtType(enum UserFmtType type)
  704. {
  705. switch(type)
  706. {
  707. case UserFmtUByte: return "Unsigned Byte";
  708. case UserFmtShort: return "Signed Short";
  709. case UserFmtFloat: return "Float32";
  710. case UserFmtDouble: return "Float64";
  711. case UserFmtMulaw: return "muLaw";
  712. case UserFmtAlaw: return "aLaw";
  713. case UserFmtIMA4: return "IMA4 ADPCM";
  714. case UserFmtMSADPCM: return "MSADPCM";
  715. }
  716. return "<internal type error>";
  717. }
  718. /*
  719. * LoadData
  720. *
  721. * Loads the specified data into the buffer, using the specified format.
  722. */
  723. static void LoadData(ALCcontext *context, ALbuffer *ALBuf, ALuint freq, ALsizei size, enum UserFmtChannels SrcChannels, enum UserFmtType SrcType, const ALvoid *data, ALbitfieldSOFT access)
  724. {
  725. enum FmtChannels DstChannels = FmtMono;
  726. enum FmtType DstType = FmtUByte;
  727. ALsizei NumChannels, FrameSize;
  728. ALsizei SrcByteAlign;
  729. ALsizei unpackalign;
  730. ALsizei newsize;
  731. ALsizei frames;
  732. ALsizei align;
  733. if(UNLIKELY(ReadRef(&ALBuf->ref) != 0 || ALBuf->MappedAccess != 0))
  734. SETERR_RETURN(context, AL_INVALID_OPERATION,, "Modifying storage for in-use buffer %u",
  735. ALBuf->id);
  736. /* Currently no channel configurations need to be converted. */
  737. switch(SrcChannels)
  738. {
  739. case UserFmtMono: DstChannels = FmtMono; break;
  740. case UserFmtStereo: DstChannels = FmtStereo; break;
  741. case UserFmtRear: DstChannels = FmtRear; break;
  742. case UserFmtQuad: DstChannels = FmtQuad; break;
  743. case UserFmtX51: DstChannels = FmtX51; break;
  744. case UserFmtX61: DstChannels = FmtX61; break;
  745. case UserFmtX71: DstChannels = FmtX71; break;
  746. case UserFmtBFormat2D: DstChannels = FmtBFormat2D; break;
  747. case UserFmtBFormat3D: DstChannels = FmtBFormat3D; break;
  748. }
  749. if(UNLIKELY((long)SrcChannels != (long)DstChannels))
  750. SETERR_RETURN(context, AL_INVALID_ENUM,, "Invalid format");
  751. /* IMA4 and MSADPCM convert to 16-bit short. */
  752. switch(SrcType)
  753. {
  754. case UserFmtUByte: DstType = FmtUByte; break;
  755. case UserFmtShort: DstType = FmtShort; break;
  756. case UserFmtFloat: DstType = FmtFloat; break;
  757. case UserFmtDouble: DstType = FmtDouble; break;
  758. case UserFmtAlaw: DstType = FmtAlaw; break;
  759. case UserFmtMulaw: DstType = FmtMulaw; break;
  760. case UserFmtIMA4: DstType = FmtShort; break;
  761. case UserFmtMSADPCM: DstType = FmtShort; break;
  762. }
  763. /* TODO: Currently we can only map samples when they're not converted. To
  764. * allow it would need some kind of double-buffering to hold onto a copy of
  765. * the original data.
  766. */
  767. if((access&MAP_READ_WRITE_FLAGS))
  768. {
  769. if(UNLIKELY((long)SrcType != (long)DstType))
  770. SETERR_RETURN(context, AL_INVALID_VALUE,, "%s samples cannot be mapped",
  771. NameFromUserFmtType(SrcType));
  772. }
  773. unpackalign = ATOMIC_LOAD_SEQ(&ALBuf->UnpackAlign);
  774. if(UNLIKELY((align=SanitizeAlignment(SrcType, unpackalign)) < 1))
  775. SETERR_RETURN(context, AL_INVALID_VALUE,, "Invalid unpack alignment %d for %s samples",
  776. unpackalign, NameFromUserFmtType(SrcType));
  777. if((access&AL_PRESERVE_DATA_BIT_SOFT))
  778. {
  779. /* Can only preserve data with the same format and alignment. */
  780. if(UNLIKELY(ALBuf->FmtChannels != DstChannels || ALBuf->OriginalType != SrcType))
  781. SETERR_RETURN(context, AL_INVALID_VALUE,, "Preserving data of mismatched format");
  782. if(UNLIKELY(ALBuf->OriginalAlign != align))
  783. SETERR_RETURN(context, AL_INVALID_VALUE,, "Preserving data of mismatched alignment");
  784. }
  785. /* Convert the input/source size in bytes to sample frames using the unpack
  786. * block alignment.
  787. */
  788. if(SrcType == UserFmtIMA4)
  789. SrcByteAlign = ((align-1)/2 + 4) * ChannelsFromUserFmt(SrcChannels);
  790. else if(SrcType == UserFmtMSADPCM)
  791. SrcByteAlign = ((align-2)/2 + 7) * ChannelsFromUserFmt(SrcChannels);
  792. else
  793. SrcByteAlign = align * FrameSizeFromUserFmt(SrcChannels, SrcType);
  794. if(UNLIKELY((size%SrcByteAlign) != 0))
  795. SETERR_RETURN(context, AL_INVALID_VALUE,,
  796. "Data size %d is not a multiple of frame size %d (%d unpack alignment)",
  797. size, SrcByteAlign, align);
  798. if(UNLIKELY(size / SrcByteAlign > INT_MAX / align))
  799. SETERR_RETURN(context, AL_OUT_OF_MEMORY,,
  800. "Buffer size overflow, %d blocks x %d samples per block", size/SrcByteAlign, align);
  801. frames = size / SrcByteAlign * align;
  802. /* Convert the sample frames to the number of bytes needed for internal
  803. * storage.
  804. */
  805. NumChannels = ChannelsFromFmt(DstChannels);
  806. FrameSize = NumChannels * BytesFromFmt(DstType);
  807. if(UNLIKELY(frames > INT_MAX/FrameSize))
  808. SETERR_RETURN(context, AL_OUT_OF_MEMORY,,
  809. "Buffer size overflow, %d frames x %d bytes per frame", frames, FrameSize);
  810. newsize = frames*FrameSize;
  811. /* Round up to the next 16-byte multiple. This could reallocate only when
  812. * increasing or the new size is less than half the current, but then the
  813. * buffer's AL_SIZE would not be very reliable for accounting buffer memory
  814. * usage, and reporting the real size could cause problems for apps that
  815. * use AL_SIZE to try to get the buffer's play length.
  816. */
  817. if(LIKELY(newsize <= INT_MAX-15))
  818. newsize = (newsize+15) & ~0xf;
  819. if(newsize != ALBuf->BytesAlloc)
  820. {
  821. void *temp = al_malloc(16, (size_t)newsize);
  822. if(UNLIKELY(!temp && newsize))
  823. SETERR_RETURN(context, AL_OUT_OF_MEMORY,, "Failed to allocate %d bytes of storage",
  824. newsize);
  825. if((access&AL_PRESERVE_DATA_BIT_SOFT))
  826. {
  827. ALsizei tocopy = mini(newsize, ALBuf->BytesAlloc);
  828. if(tocopy > 0) memcpy(temp, ALBuf->data, tocopy);
  829. }
  830. al_free(ALBuf->data);
  831. ALBuf->data = temp;
  832. ALBuf->BytesAlloc = newsize;
  833. }
  834. if(SrcType == UserFmtIMA4)
  835. {
  836. assert(DstType == FmtShort);
  837. if(data != NULL && ALBuf->data != NULL)
  838. Convert_ALshort_ALima4(ALBuf->data, data, NumChannels, frames, align);
  839. ALBuf->OriginalAlign = align;
  840. }
  841. else if(SrcType == UserFmtMSADPCM)
  842. {
  843. assert(DstType == FmtShort);
  844. if(data != NULL && ALBuf->data != NULL)
  845. Convert_ALshort_ALmsadpcm(ALBuf->data, data, NumChannels, frames, align);
  846. ALBuf->OriginalAlign = align;
  847. }
  848. else
  849. {
  850. assert((long)SrcType == (long)DstType);
  851. if(data != NULL && ALBuf->data != NULL)
  852. memcpy(ALBuf->data, data, frames*FrameSize);
  853. ALBuf->OriginalAlign = 1;
  854. }
  855. ALBuf->OriginalSize = size;
  856. ALBuf->OriginalType = SrcType;
  857. ALBuf->Frequency = freq;
  858. ALBuf->FmtChannels = DstChannels;
  859. ALBuf->FmtType = DstType;
  860. ALBuf->Access = access;
  861. ALBuf->SampleLen = frames;
  862. ALBuf->LoopStart = 0;
  863. ALBuf->LoopEnd = ALBuf->SampleLen;
  864. }
  865. ALsizei BytesFromUserFmt(enum UserFmtType type)
  866. {
  867. switch(type)
  868. {
  869. case UserFmtUByte: return sizeof(ALubyte);
  870. case UserFmtShort: return sizeof(ALshort);
  871. case UserFmtFloat: return sizeof(ALfloat);
  872. case UserFmtDouble: return sizeof(ALdouble);
  873. case UserFmtMulaw: return sizeof(ALubyte);
  874. case UserFmtAlaw: return sizeof(ALubyte);
  875. case UserFmtIMA4: break; /* not handled here */
  876. case UserFmtMSADPCM: break; /* not handled here */
  877. }
  878. return 0;
  879. }
  880. ALsizei ChannelsFromUserFmt(enum UserFmtChannels chans)
  881. {
  882. switch(chans)
  883. {
  884. case UserFmtMono: return 1;
  885. case UserFmtStereo: return 2;
  886. case UserFmtRear: return 2;
  887. case UserFmtQuad: return 4;
  888. case UserFmtX51: return 6;
  889. case UserFmtX61: return 7;
  890. case UserFmtX71: return 8;
  891. case UserFmtBFormat2D: return 3;
  892. case UserFmtBFormat3D: return 4;
  893. }
  894. return 0;
  895. }
  896. static ALboolean DecomposeUserFormat(ALenum format, enum UserFmtChannels *chans,
  897. enum UserFmtType *type)
  898. {
  899. static const struct {
  900. ALenum format;
  901. enum UserFmtChannels channels;
  902. enum UserFmtType type;
  903. } list[] = {
  904. { AL_FORMAT_MONO8, UserFmtMono, UserFmtUByte },
  905. { AL_FORMAT_MONO16, UserFmtMono, UserFmtShort },
  906. { AL_FORMAT_MONO_FLOAT32, UserFmtMono, UserFmtFloat },
  907. { AL_FORMAT_MONO_DOUBLE_EXT, UserFmtMono, UserFmtDouble },
  908. { AL_FORMAT_MONO_IMA4, UserFmtMono, UserFmtIMA4 },
  909. { AL_FORMAT_MONO_MSADPCM_SOFT, UserFmtMono, UserFmtMSADPCM },
  910. { AL_FORMAT_MONO_MULAW, UserFmtMono, UserFmtMulaw },
  911. { AL_FORMAT_MONO_ALAW_EXT, UserFmtMono, UserFmtAlaw },
  912. { AL_FORMAT_STEREO8, UserFmtStereo, UserFmtUByte },
  913. { AL_FORMAT_STEREO16, UserFmtStereo, UserFmtShort },
  914. { AL_FORMAT_STEREO_FLOAT32, UserFmtStereo, UserFmtFloat },
  915. { AL_FORMAT_STEREO_DOUBLE_EXT, UserFmtStereo, UserFmtDouble },
  916. { AL_FORMAT_STEREO_IMA4, UserFmtStereo, UserFmtIMA4 },
  917. { AL_FORMAT_STEREO_MSADPCM_SOFT, UserFmtStereo, UserFmtMSADPCM },
  918. { AL_FORMAT_STEREO_MULAW, UserFmtStereo, UserFmtMulaw },
  919. { AL_FORMAT_STEREO_ALAW_EXT, UserFmtStereo, UserFmtAlaw },
  920. { AL_FORMAT_REAR8, UserFmtRear, UserFmtUByte },
  921. { AL_FORMAT_REAR16, UserFmtRear, UserFmtShort },
  922. { AL_FORMAT_REAR32, UserFmtRear, UserFmtFloat },
  923. { AL_FORMAT_REAR_MULAW, UserFmtRear, UserFmtMulaw },
  924. { AL_FORMAT_QUAD8_LOKI, UserFmtQuad, UserFmtUByte },
  925. { AL_FORMAT_QUAD16_LOKI, UserFmtQuad, UserFmtShort },
  926. { AL_FORMAT_QUAD8, UserFmtQuad, UserFmtUByte },
  927. { AL_FORMAT_QUAD16, UserFmtQuad, UserFmtShort },
  928. { AL_FORMAT_QUAD32, UserFmtQuad, UserFmtFloat },
  929. { AL_FORMAT_QUAD_MULAW, UserFmtQuad, UserFmtMulaw },
  930. { AL_FORMAT_51CHN8, UserFmtX51, UserFmtUByte },
  931. { AL_FORMAT_51CHN16, UserFmtX51, UserFmtShort },
  932. { AL_FORMAT_51CHN32, UserFmtX51, UserFmtFloat },
  933. { AL_FORMAT_51CHN_MULAW, UserFmtX51, UserFmtMulaw },
  934. { AL_FORMAT_61CHN8, UserFmtX61, UserFmtUByte },
  935. { AL_FORMAT_61CHN16, UserFmtX61, UserFmtShort },
  936. { AL_FORMAT_61CHN32, UserFmtX61, UserFmtFloat },
  937. { AL_FORMAT_61CHN_MULAW, UserFmtX61, UserFmtMulaw },
  938. { AL_FORMAT_71CHN8, UserFmtX71, UserFmtUByte },
  939. { AL_FORMAT_71CHN16, UserFmtX71, UserFmtShort },
  940. { AL_FORMAT_71CHN32, UserFmtX71, UserFmtFloat },
  941. { AL_FORMAT_71CHN_MULAW, UserFmtX71, UserFmtMulaw },
  942. { AL_FORMAT_BFORMAT2D_8, UserFmtBFormat2D, UserFmtUByte },
  943. { AL_FORMAT_BFORMAT2D_16, UserFmtBFormat2D, UserFmtShort },
  944. { AL_FORMAT_BFORMAT2D_FLOAT32, UserFmtBFormat2D, UserFmtFloat },
  945. { AL_FORMAT_BFORMAT2D_MULAW, UserFmtBFormat2D, UserFmtMulaw },
  946. { AL_FORMAT_BFORMAT3D_8, UserFmtBFormat3D, UserFmtUByte },
  947. { AL_FORMAT_BFORMAT3D_16, UserFmtBFormat3D, UserFmtShort },
  948. { AL_FORMAT_BFORMAT3D_FLOAT32, UserFmtBFormat3D, UserFmtFloat },
  949. { AL_FORMAT_BFORMAT3D_MULAW, UserFmtBFormat3D, UserFmtMulaw },
  950. };
  951. ALuint i;
  952. for(i = 0;i < COUNTOF(list);i++)
  953. {
  954. if(list[i].format == format)
  955. {
  956. *chans = list[i].channels;
  957. *type = list[i].type;
  958. return AL_TRUE;
  959. }
  960. }
  961. return AL_FALSE;
  962. }
  963. ALsizei BytesFromFmt(enum FmtType type)
  964. {
  965. switch(type)
  966. {
  967. case FmtUByte: return sizeof(ALubyte);
  968. case FmtShort: return sizeof(ALshort);
  969. case FmtFloat: return sizeof(ALfloat);
  970. case FmtDouble: return sizeof(ALdouble);
  971. case FmtMulaw: return sizeof(ALubyte);
  972. case FmtAlaw: return sizeof(ALubyte);
  973. }
  974. return 0;
  975. }
  976. ALsizei ChannelsFromFmt(enum FmtChannels chans)
  977. {
  978. switch(chans)
  979. {
  980. case FmtMono: return 1;
  981. case FmtStereo: return 2;
  982. case FmtRear: return 2;
  983. case FmtQuad: return 4;
  984. case FmtX51: return 6;
  985. case FmtX61: return 7;
  986. case FmtX71: return 8;
  987. case FmtBFormat2D: return 3;
  988. case FmtBFormat3D: return 4;
  989. }
  990. return 0;
  991. }
  992. static ALsizei SanitizeAlignment(enum UserFmtType type, ALsizei align)
  993. {
  994. if(align < 0)
  995. return 0;
  996. if(align == 0)
  997. {
  998. if(type == UserFmtIMA4)
  999. {
  1000. /* Here is where things vary:
  1001. * nVidia and Apple use 64+1 sample frames per block -> block_size=36 bytes per channel
  1002. * Most PC sound software uses 2040+1 sample frames per block -> block_size=1024 bytes per channel
  1003. */
  1004. return 65;
  1005. }
  1006. if(type == UserFmtMSADPCM)
  1007. return 64;
  1008. return 1;
  1009. }
  1010. if(type == UserFmtIMA4)
  1011. {
  1012. /* IMA4 block alignment must be a multiple of 8, plus 1. */
  1013. if((align&7) == 1) return align;
  1014. return 0;
  1015. }
  1016. if(type == UserFmtMSADPCM)
  1017. {
  1018. /* MSADPCM block alignment must be a multiple of 2. */
  1019. if((align&1) == 0) return align;
  1020. return 0;
  1021. }
  1022. return align;
  1023. }
  1024. static ALbuffer *AllocBuffer(ALCcontext *context)
  1025. {
  1026. ALCdevice *device = context->Device;
  1027. BufferSubList *sublist, *subend;
  1028. ALbuffer *buffer = NULL;
  1029. ALsizei lidx = 0;
  1030. ALsizei slidx;
  1031. almtx_lock(&device->BufferLock);
  1032. sublist = VECTOR_BEGIN(device->BufferList);
  1033. subend = VECTOR_END(device->BufferList);
  1034. for(;sublist != subend;++sublist)
  1035. {
  1036. if(sublist->FreeMask)
  1037. {
  1038. slidx = CTZ64(sublist->FreeMask);
  1039. buffer = sublist->Buffers + slidx;
  1040. break;
  1041. }
  1042. ++lidx;
  1043. }
  1044. if(UNLIKELY(!buffer))
  1045. {
  1046. const BufferSubList empty_sublist = { 0, NULL };
  1047. /* Don't allocate so many list entries that the 32-bit ID could
  1048. * overflow...
  1049. */
  1050. if(UNLIKELY(VECTOR_SIZE(device->BufferList) >= 1<<25))
  1051. {
  1052. almtx_unlock(&device->BufferLock);
  1053. alSetError(context, AL_OUT_OF_MEMORY, "Too many buffers allocated");
  1054. return NULL;
  1055. }
  1056. lidx = (ALsizei)VECTOR_SIZE(device->BufferList);
  1057. VECTOR_PUSH_BACK(device->BufferList, empty_sublist);
  1058. sublist = &VECTOR_BACK(device->BufferList);
  1059. sublist->FreeMask = ~U64(0);
  1060. sublist->Buffers = al_calloc(16, sizeof(ALbuffer)*64);
  1061. if(UNLIKELY(!sublist->Buffers))
  1062. {
  1063. VECTOR_POP_BACK(device->BufferList);
  1064. almtx_unlock(&device->BufferLock);
  1065. alSetError(context, AL_OUT_OF_MEMORY, "Failed to allocate buffer batch");
  1066. return NULL;
  1067. }
  1068. slidx = 0;
  1069. buffer = sublist->Buffers + slidx;
  1070. }
  1071. memset(buffer, 0, sizeof(*buffer));
  1072. /* Add 1 to avoid buffer ID 0. */
  1073. buffer->id = ((lidx<<6) | slidx) + 1;
  1074. sublist->FreeMask &= ~(U64(1)<<slidx);
  1075. almtx_unlock(&device->BufferLock);
  1076. return buffer;
  1077. }
  1078. static void FreeBuffer(ALCdevice *device, ALbuffer *buffer)
  1079. {
  1080. ALuint id = buffer->id - 1;
  1081. ALsizei lidx = id >> 6;
  1082. ALsizei slidx = id & 0x3f;
  1083. al_free(buffer->data);
  1084. memset(buffer, 0, sizeof(*buffer));
  1085. VECTOR_ELEM(device->BufferList, lidx).FreeMask |= U64(1) << slidx;
  1086. }
  1087. /*
  1088. * ReleaseALBuffers()
  1089. *
  1090. * INTERNAL: Called to destroy any buffers that still exist on the device
  1091. */
  1092. ALvoid ReleaseALBuffers(ALCdevice *device)
  1093. {
  1094. BufferSubList *sublist = VECTOR_BEGIN(device->BufferList);
  1095. BufferSubList *subend = VECTOR_END(device->BufferList);
  1096. size_t leftover = 0;
  1097. for(;sublist != subend;++sublist)
  1098. {
  1099. ALuint64 usemask = ~sublist->FreeMask;
  1100. while(usemask)
  1101. {
  1102. ALsizei idx = CTZ64(usemask);
  1103. ALbuffer *buffer = sublist->Buffers + idx;
  1104. al_free(buffer->data);
  1105. memset(buffer, 0, sizeof(*buffer));
  1106. ++leftover;
  1107. usemask &= ~(U64(1) << idx);
  1108. }
  1109. sublist->FreeMask = ~usemask;
  1110. }
  1111. if(leftover > 0)
  1112. WARN("(%p) Deleted "SZFMT" Buffer%s\n", device, leftover, (leftover==1)?"":"s");
  1113. }