FAudio.c 84 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204
  1. /* FAudio - XAudio Reimplementation for FNA
  2. *
  3. * Copyright (c) 2011-2021 Ethan Lee, Luigi Auriemma, and the MonoGame Team
  4. *
  5. * This software is provided 'as-is', without any express or implied warranty.
  6. * In no event will the authors be held liable for any damages arising from
  7. * the use of this software.
  8. *
  9. * Permission is granted to anyone to use this software for any purpose,
  10. * including commercial applications, and to alter it and redistribute it
  11. * freely, subject to the following restrictions:
  12. *
  13. * 1. The origin of this software must not be misrepresented; you must not
  14. * claim that you wrote the original software. If you use this software in a
  15. * product, an acknowledgment in the product documentation would be
  16. * appreciated but is not required.
  17. *
  18. * 2. Altered source versions must be plainly marked as such, and must not be
  19. * misrepresented as being the original software.
  20. *
  21. * 3. This notice may not be removed or altered from any source distribution.
  22. *
  23. * Ethan "flibitijibibo" Lee <flibitijibibo@flibitijibibo.com>
  24. *
  25. */
  26. #include "FAudio_internal.h"
  27. #define MAKE_SUBFORMAT_GUID(guid, fmt) \
  28. FAudioGUID DATAFORMAT_SUBTYPE_##guid = \
  29. { \
  30. (uint16_t) (fmt), \
  31. 0x0000, \
  32. 0x0010, \
  33. { \
  34. 0x80, \
  35. 0x00, \
  36. 0x00, \
  37. 0xAA, \
  38. 0x00, \
  39. 0x38, \
  40. 0x9B, \
  41. 0x71 \
  42. } \
  43. }
  44. MAKE_SUBFORMAT_GUID(PCM, 1);
  45. MAKE_SUBFORMAT_GUID(ADPCM, 2);
  46. MAKE_SUBFORMAT_GUID(IEEE_FLOAT, 3);
  47. MAKE_SUBFORMAT_GUID(XMAUDIO2, FAUDIO_FORMAT_XMAUDIO2);
  48. MAKE_SUBFORMAT_GUID(WMAUDIO2, FAUDIO_FORMAT_WMAUDIO2);
  49. MAKE_SUBFORMAT_GUID(WMAUDIO3, FAUDIO_FORMAT_WMAUDIO3);
  50. MAKE_SUBFORMAT_GUID(WMAUDIO_LOSSLESS, FAUDIO_FORMAT_WMAUDIO_LOSSLESS);
  51. #undef MAKE_SUBFORMAT_GUID
  52. #ifdef FAUDIO_DUMP_VOICES
  53. static void FAudio_DUMPVOICE_Init(const FAudioSourceVoice *voice);
  54. static void FAudio_DUMPVOICE_Finalize(const FAudioSourceVoice *voice);
  55. static void FAudio_DUMPVOICE_WriteBuffer(
  56. const FAudioSourceVoice *voice,
  57. const FAudioBuffer *pBuffer,
  58. const FAudioBufferWMA *pBufferWMA,
  59. const uint32_t playBegin,
  60. const uint32_t playLength
  61. );
  62. #endif /* FAUDIO_DUMP_VOICES */
  63. /* FAudio Version */
  64. uint32_t FAudioLinkedVersion(void)
  65. {
  66. return FAUDIO_COMPILED_VERSION;
  67. }
  68. /* FAudio Interface */
  69. uint32_t FAudioCreate(
  70. FAudio **ppFAudio,
  71. uint32_t Flags,
  72. FAudioProcessor XAudio2Processor
  73. ) {
  74. FAudioCOMConstructEXT(ppFAudio, FAUDIO_TARGET_VERSION);
  75. FAudio_Initialize(*ppFAudio, Flags, XAudio2Processor);
  76. return 0;
  77. }
  78. uint32_t FAudioCOMConstructEXT(FAudio **ppFAudio, uint8_t version)
  79. {
  80. return FAudioCOMConstructWithCustomAllocatorEXT(
  81. ppFAudio,
  82. version,
  83. FAudio_malloc,
  84. FAudio_free,
  85. FAudio_realloc
  86. );
  87. }
  88. uint32_t FAudioCreateWithCustomAllocatorEXT(
  89. FAudio **ppFAudio,
  90. uint32_t Flags,
  91. FAudioProcessor XAudio2Processor,
  92. FAudioMallocFunc customMalloc,
  93. FAudioFreeFunc customFree,
  94. FAudioReallocFunc customRealloc
  95. ) {
  96. FAudioCOMConstructWithCustomAllocatorEXT(
  97. ppFAudio,
  98. FAUDIO_TARGET_VERSION,
  99. customMalloc,
  100. customFree,
  101. customRealloc
  102. );
  103. FAudio_Initialize(*ppFAudio, Flags, XAudio2Processor);
  104. return 0;
  105. }
  106. uint32_t FAudioCOMConstructWithCustomAllocatorEXT(
  107. FAudio **ppFAudio,
  108. uint8_t version,
  109. FAudioMallocFunc customMalloc,
  110. FAudioFreeFunc customFree,
  111. FAudioReallocFunc customRealloc
  112. ) {
  113. #ifndef FAUDIO_DISABLE_DEBUGCONFIGURATION
  114. FAudioDebugConfiguration debugInit = {0};
  115. #endif /* FAUDIO_DISABLE_DEBUGCONFIGURATION */
  116. FAudio_PlatformAddRef();
  117. *ppFAudio = (FAudio*) customMalloc(sizeof(FAudio));
  118. FAudio_zero(*ppFAudio, sizeof(FAudio));
  119. (*ppFAudio)->version = version;
  120. #ifndef FAUDIO_DISABLE_DEBUGCONFIGURATION
  121. FAudio_SetDebugConfiguration(*ppFAudio, &debugInit, NULL);
  122. #endif /* FAUDIO_DISABLE_DEBUGCONFIGURATION */
  123. (*ppFAudio)->sourceLock = FAudio_PlatformCreateMutex();
  124. LOG_MUTEX_CREATE((*ppFAudio), (*ppFAudio)->sourceLock)
  125. (*ppFAudio)->submixLock = FAudio_PlatformCreateMutex();
  126. LOG_MUTEX_CREATE((*ppFAudio), (*ppFAudio)->submixLock)
  127. (*ppFAudio)->callbackLock = FAudio_PlatformCreateMutex();
  128. LOG_MUTEX_CREATE((*ppFAudio), (*ppFAudio)->callbackLock)
  129. (*ppFAudio)->operationLock = FAudio_PlatformCreateMutex();
  130. LOG_MUTEX_CREATE((*ppFAudio), (*ppFAudio)->operationLock)
  131. (*ppFAudio)->pMalloc = customMalloc;
  132. (*ppFAudio)->pFree = customFree;
  133. (*ppFAudio)->pRealloc = customRealloc;
  134. (*ppFAudio)->refcount = 1;
  135. return 0;
  136. }
  137. uint32_t FAudio_AddRef(FAudio *audio)
  138. {
  139. LOG_API_ENTER(audio)
  140. audio->refcount += 1;
  141. LOG_API_EXIT(audio)
  142. return audio->refcount;
  143. }
  144. uint32_t FAudio_Release(FAudio *audio)
  145. {
  146. uint32_t refcount;
  147. LOG_API_ENTER(audio)
  148. audio->refcount -= 1;
  149. refcount = audio->refcount;
  150. if (audio->refcount == 0)
  151. {
  152. FAudio_OPERATIONSET_ClearAll(audio);
  153. FAudio_StopEngine(audio);
  154. audio->pFree(audio->decodeCache);
  155. audio->pFree(audio->resampleCache);
  156. audio->pFree(audio->effectChainCache);
  157. LOG_MUTEX_DESTROY(audio, audio->sourceLock)
  158. FAudio_PlatformDestroyMutex(audio->sourceLock);
  159. LOG_MUTEX_DESTROY(audio, audio->submixLock)
  160. FAudio_PlatformDestroyMutex(audio->submixLock);
  161. LOG_MUTEX_DESTROY(audio, audio->callbackLock)
  162. FAudio_PlatformDestroyMutex(audio->callbackLock);
  163. LOG_MUTEX_DESTROY(audio, audio->operationLock)
  164. FAudio_PlatformDestroyMutex(audio->operationLock);
  165. audio->pFree(audio);
  166. FAudio_PlatformRelease();
  167. }
  168. else
  169. {
  170. LOG_API_EXIT(audio)
  171. }
  172. return refcount;
  173. }
  174. uint32_t FAudio_GetDeviceCount(FAudio *audio, uint32_t *pCount)
  175. {
  176. LOG_API_ENTER(audio)
  177. *pCount = FAudio_PlatformGetDeviceCount();
  178. LOG_API_EXIT(audio)
  179. return 0;
  180. }
  181. uint32_t FAudio_GetDeviceDetails(
  182. FAudio *audio,
  183. uint32_t Index,
  184. FAudioDeviceDetails *pDeviceDetails
  185. ) {
  186. uint32_t result;
  187. LOG_API_ENTER(audio)
  188. result = FAudio_PlatformGetDeviceDetails(Index, pDeviceDetails);
  189. LOG_API_EXIT(audio)
  190. return result;
  191. }
  192. uint32_t FAudio_Initialize(
  193. FAudio *audio,
  194. uint32_t Flags,
  195. FAudioProcessor XAudio2Processor
  196. ) {
  197. LOG_API_ENTER(audio)
  198. FAudio_assert(Flags == 0 || Flags == FAUDIO_DEBUG_ENGINE);
  199. FAudio_assert(XAudio2Processor == FAUDIO_DEFAULT_PROCESSOR);
  200. audio->initFlags = Flags;
  201. /* FIXME: This is lazy... */
  202. audio->decodeCache = (float*) audio->pMalloc(sizeof(float));
  203. audio->resampleCache = (float*) audio->pMalloc(sizeof(float));
  204. audio->decodeSamples = 1;
  205. audio->resampleSamples = 1;
  206. FAudio_StartEngine(audio);
  207. LOG_API_EXIT(audio)
  208. return 0;
  209. }
  210. uint32_t FAudio_RegisterForCallbacks(
  211. FAudio *audio,
  212. FAudioEngineCallback *pCallback
  213. ) {
  214. LOG_API_ENTER(audio)
  215. LinkedList_AddEntry(
  216. &audio->callbacks,
  217. pCallback,
  218. audio->callbackLock,
  219. audio->pMalloc
  220. );
  221. LOG_API_EXIT(audio)
  222. return 0;
  223. }
  224. void FAudio_UnregisterForCallbacks(
  225. FAudio *audio,
  226. FAudioEngineCallback *pCallback
  227. ) {
  228. LOG_API_ENTER(audio)
  229. LinkedList_RemoveEntry(
  230. &audio->callbacks,
  231. pCallback,
  232. audio->callbackLock,
  233. audio->pFree
  234. );
  235. LOG_API_EXIT(audio)
  236. }
  237. uint32_t FAudio_CreateSourceVoice(
  238. FAudio *audio,
  239. FAudioSourceVoice **ppSourceVoice,
  240. const FAudioWaveFormatEx *pSourceFormat,
  241. uint32_t Flags,
  242. float MaxFrequencyRatio,
  243. FAudioVoiceCallback *pCallback,
  244. const FAudioVoiceSends *pSendList,
  245. const FAudioEffectChain *pEffectChain
  246. ) {
  247. uint32_t i;
  248. LOG_API_ENTER(audio)
  249. LOG_FORMAT(audio, pSourceFormat)
  250. *ppSourceVoice = (FAudioSourceVoice*) audio->pMalloc(sizeof(FAudioVoice));
  251. FAudio_zero(*ppSourceVoice, sizeof(FAudioSourceVoice));
  252. (*ppSourceVoice)->audio = audio;
  253. (*ppSourceVoice)->type = FAUDIO_VOICE_SOURCE;
  254. (*ppSourceVoice)->flags = Flags;
  255. (*ppSourceVoice)->filter.Type = FAUDIO_DEFAULT_FILTER_TYPE;
  256. (*ppSourceVoice)->filter.Frequency = FAUDIO_DEFAULT_FILTER_FREQUENCY;
  257. (*ppSourceVoice)->filter.OneOverQ = FAUDIO_DEFAULT_FILTER_ONEOVERQ;
  258. (*ppSourceVoice)->sendLock = FAudio_PlatformCreateMutex();
  259. LOG_MUTEX_CREATE(audio, (*ppSourceVoice)->sendLock)
  260. (*ppSourceVoice)->effectLock = FAudio_PlatformCreateMutex();
  261. LOG_MUTEX_CREATE(audio, (*ppSourceVoice)->effectLock)
  262. (*ppSourceVoice)->filterLock = FAudio_PlatformCreateMutex();
  263. LOG_MUTEX_CREATE(audio, (*ppSourceVoice)->filterLock)
  264. (*ppSourceVoice)->volumeLock = FAudio_PlatformCreateMutex();
  265. LOG_MUTEX_CREATE(audio, (*ppSourceVoice)->volumeLock)
  266. /* Source Properties */
  267. FAudio_assert(MaxFrequencyRatio <= FAUDIO_MAX_FREQ_RATIO);
  268. (*ppSourceVoice)->src.maxFreqRatio = MaxFrequencyRatio;
  269. if ( pSourceFormat->wFormatTag == FAUDIO_FORMAT_PCM ||
  270. pSourceFormat->wFormatTag == FAUDIO_FORMAT_IEEE_FLOAT ||
  271. pSourceFormat->wFormatTag == FAUDIO_FORMAT_WMAUDIO2 )
  272. {
  273. FAudioWaveFormatExtensible *fmtex = (FAudioWaveFormatExtensible*) audio->pMalloc(
  274. sizeof(FAudioWaveFormatExtensible)
  275. );
  276. /* convert PCM to EXTENSIBLE */
  277. fmtex->Format.wFormatTag = FAUDIO_FORMAT_EXTENSIBLE;
  278. fmtex->Format.nChannels = pSourceFormat->nChannels;
  279. fmtex->Format.nSamplesPerSec = pSourceFormat->nSamplesPerSec;
  280. fmtex->Format.nAvgBytesPerSec = pSourceFormat->nAvgBytesPerSec;
  281. fmtex->Format.nBlockAlign = pSourceFormat->nBlockAlign;
  282. fmtex->Format.wBitsPerSample = pSourceFormat->wBitsPerSample;
  283. fmtex->Format.cbSize = sizeof(FAudioWaveFormatExtensible) - sizeof(FAudioWaveFormatEx);
  284. fmtex->Samples.wValidBitsPerSample = pSourceFormat->wBitsPerSample;
  285. fmtex->dwChannelMask = 0;
  286. if (pSourceFormat->wFormatTag == FAUDIO_FORMAT_PCM)
  287. {
  288. FAudio_memcpy(&fmtex->SubFormat, &DATAFORMAT_SUBTYPE_PCM, sizeof(FAudioGUID));
  289. }
  290. else if (pSourceFormat->wFormatTag == FAUDIO_FORMAT_IEEE_FLOAT)
  291. {
  292. FAudio_memcpy(&fmtex->SubFormat, &DATAFORMAT_SUBTYPE_IEEE_FLOAT, sizeof(FAudioGUID));
  293. }
  294. else if (pSourceFormat->wFormatTag == FAUDIO_FORMAT_WMAUDIO2)
  295. {
  296. FAudio_memcpy(&fmtex->SubFormat, &DATAFORMAT_SUBTYPE_WMAUDIO2, sizeof(FAudioGUID));
  297. }
  298. (*ppSourceVoice)->src.format = &fmtex->Format;
  299. }
  300. else if (pSourceFormat->wFormatTag == FAUDIO_FORMAT_MSADPCM)
  301. {
  302. FAudioADPCMWaveFormat *fmtex = (FAudioADPCMWaveFormat*) audio->pMalloc(
  303. sizeof(FAudioADPCMWaveFormat)
  304. );
  305. /* Copy what we can, ideally the sizes match! */
  306. size_t cbSize = sizeof(FAudioWaveFormatEx) + pSourceFormat->cbSize;
  307. FAudio_memcpy(
  308. fmtex,
  309. pSourceFormat,
  310. FAudio_min(cbSize, sizeof(FAudioADPCMWaveFormat))
  311. );
  312. if (cbSize < sizeof(FAudioADPCMWaveFormat))
  313. {
  314. FAudio_zero(
  315. ((uint8_t*) fmtex) + cbSize,
  316. sizeof(FAudioADPCMWaveFormat) - cbSize
  317. );
  318. }
  319. /* XAudio2 does not validate this input! */
  320. fmtex->wfx.cbSize = sizeof(FAudioADPCMWaveFormat) - sizeof(FAudioWaveFormatEx);
  321. fmtex->wSamplesPerBlock = ((
  322. fmtex->wfx.nBlockAlign / fmtex->wfx.nChannels
  323. ) - 6) * 2;
  324. (*ppSourceVoice)->src.format = &fmtex->wfx;
  325. }
  326. else if (pSourceFormat->wFormatTag == FAUDIO_FORMAT_XMAUDIO2)
  327. {
  328. FAudioXMA2WaveFormat *fmtex = (FAudioXMA2WaveFormat*) audio->pMalloc(
  329. sizeof(FAudioXMA2WaveFormat)
  330. );
  331. /* Copy what we can, ideally the sizes match! */
  332. size_t cbSize = sizeof(FAudioWaveFormatEx) + pSourceFormat->cbSize;
  333. FAudio_memcpy(
  334. fmtex,
  335. pSourceFormat,
  336. FAudio_min(cbSize, sizeof(FAudioXMA2WaveFormat))
  337. );
  338. if (cbSize < sizeof(FAudioXMA2WaveFormat))
  339. {
  340. FAudio_zero(
  341. ((uint8_t*) fmtex) + cbSize,
  342. sizeof(FAudioADPCMWaveFormat) - cbSize
  343. );
  344. }
  345. /* Does XAudio2 validate this input?! */
  346. fmtex->wfx.cbSize = sizeof(FAudioXMA2WaveFormat) - sizeof(FAudioWaveFormatEx);
  347. (*ppSourceVoice)->src.format = &fmtex->wfx;
  348. }
  349. else
  350. {
  351. /* direct copy anything else */
  352. (*ppSourceVoice)->src.format = (FAudioWaveFormatEx*) audio->pMalloc(
  353. sizeof(FAudioWaveFormatEx) + pSourceFormat->cbSize
  354. );
  355. FAudio_memcpy(
  356. (*ppSourceVoice)->src.format,
  357. pSourceFormat,
  358. sizeof(FAudioWaveFormatEx) + pSourceFormat->cbSize
  359. );
  360. }
  361. (*ppSourceVoice)->src.callback = pCallback;
  362. (*ppSourceVoice)->src.active = 0;
  363. (*ppSourceVoice)->src.freqRatio = 1.0f;
  364. (*ppSourceVoice)->src.totalSamples = 0;
  365. (*ppSourceVoice)->src.bufferList = NULL;
  366. (*ppSourceVoice)->src.flushList = NULL;
  367. (*ppSourceVoice)->src.bufferLock = FAudio_PlatformCreateMutex();
  368. LOG_MUTEX_CREATE(audio, (*ppSourceVoice)->src.bufferLock)
  369. if ((*ppSourceVoice)->src.format->wFormatTag == FAUDIO_FORMAT_EXTENSIBLE)
  370. {
  371. FAudioWaveFormatExtensible *fmtex = (FAudioWaveFormatExtensible*) (*ppSourceVoice)->src.format;
  372. #define COMPARE_GUID(type) \
  373. (FAudio_memcmp( \
  374. &fmtex->SubFormat, \
  375. &DATAFORMAT_SUBTYPE_##type, \
  376. sizeof(FAudioGUID) \
  377. ) == 0)
  378. if (COMPARE_GUID(PCM))
  379. {
  380. #define DECODER(bit) \
  381. if (fmtex->Format.wBitsPerSample == bit) \
  382. { \
  383. (*ppSourceVoice)->src.decode = FAudio_INTERNAL_DecodePCM##bit; \
  384. }
  385. DECODER(16)
  386. else DECODER(8)
  387. else DECODER(24)
  388. else DECODER(32)
  389. else
  390. {
  391. LOG_ERROR(
  392. audio,
  393. "Unrecognized wBitsPerSample: %d",
  394. fmtex->Format.wBitsPerSample
  395. )
  396. FAudio_assert(0 && "Unrecognized wBitsPerSample!");
  397. }
  398. #undef DECODER
  399. }
  400. else if (COMPARE_GUID(IEEE_FLOAT))
  401. {
  402. /* FIXME: Weird behavior!
  403. * Prototype creates a source with the IEEE_FLOAT tag,
  404. * but it's actually PCM16. It seems to prioritize
  405. * wBitsPerSample over the format tag. Not sure if we
  406. * should fold this section into the section above...?
  407. * -flibit
  408. */
  409. if (fmtex->Format.wBitsPerSample == 16)
  410. {
  411. (*ppSourceVoice)->src.decode = FAudio_INTERNAL_DecodePCM16;
  412. }
  413. else
  414. {
  415. (*ppSourceVoice)->src.decode = FAudio_INTERNAL_DecodePCM32F;
  416. }
  417. }
  418. else if ( COMPARE_GUID(WMAUDIO2) ||
  419. COMPARE_GUID(WMAUDIO3) ||
  420. COMPARE_GUID(WMAUDIO_LOSSLESS) )
  421. {
  422. #ifdef HAVE_WMADEC
  423. if (FAudio_WMADEC_init(*ppSourceVoice, fmtex->SubFormat.Data1) != 0)
  424. {
  425. (*ppSourceVoice)->src.decode = FAudio_INTERNAL_DecodeWMAERROR;
  426. }
  427. #else
  428. FAudio_assert(0 && "xWMA is not supported!");
  429. (*ppSourceVoice)->src.decode = FAudio_INTERNAL_DecodeWMAERROR;
  430. #endif /* HAVE_WMADEC */
  431. }
  432. else
  433. {
  434. FAudio_assert(0 && "Unsupported WAVEFORMATEXTENSIBLE subtype!");
  435. }
  436. #undef COMPARE_GUID
  437. }
  438. else if ((*ppSourceVoice)->src.format->wFormatTag == FAUDIO_FORMAT_XMAUDIO2)
  439. {
  440. #ifdef HAVE_WMADEC
  441. if (FAudio_WMADEC_init(*ppSourceVoice, FAUDIO_FORMAT_XMAUDIO2) != 0)
  442. {
  443. (*ppSourceVoice)->src.decode = FAudio_INTERNAL_DecodeWMAERROR;
  444. }
  445. #else
  446. FAudio_assert(0 && "XMA2 is not supported!");
  447. (*ppSourceVoice)->src.decode = FAudio_INTERNAL_DecodeWMAERROR;
  448. #endif /* HAVE_WMADEC */
  449. }
  450. else if ((*ppSourceVoice)->src.format->wFormatTag == FAUDIO_FORMAT_MSADPCM)
  451. {
  452. (*ppSourceVoice)->src.decode = ((*ppSourceVoice)->src.format->nChannels == 2) ?
  453. FAudio_INTERNAL_DecodeStereoMSADPCM :
  454. FAudio_INTERNAL_DecodeMonoMSADPCM;
  455. }
  456. else
  457. {
  458. FAudio_assert(0 && "Unsupported format tag!");
  459. }
  460. if ((*ppSourceVoice)->src.format->nChannels == 1)
  461. {
  462. (*ppSourceVoice)->src.resample = FAudio_INTERNAL_ResampleMono;
  463. }
  464. else if ((*ppSourceVoice)->src.format->nChannels == 2)
  465. {
  466. (*ppSourceVoice)->src.resample = FAudio_INTERNAL_ResampleStereo;
  467. }
  468. else
  469. {
  470. (*ppSourceVoice)->src.resample = FAudio_INTERNAL_ResampleGeneric;
  471. }
  472. (*ppSourceVoice)->src.curBufferOffset = 0;
  473. /* Sends/Effects */
  474. FAudio_INTERNAL_VoiceOutputFrequency(*ppSourceVoice, pSendList);
  475. FAudioVoice_SetEffectChain(*ppSourceVoice, pEffectChain);
  476. /* Default Levels */
  477. (*ppSourceVoice)->volume = 1.0f;
  478. (*ppSourceVoice)->channelVolume = (float*) audio->pMalloc(
  479. sizeof(float) * (*ppSourceVoice)->outputChannels
  480. );
  481. for (i = 0; i < (*ppSourceVoice)->outputChannels; i += 1)
  482. {
  483. (*ppSourceVoice)->channelVolume[i] = 1.0f;
  484. }
  485. FAudioVoice_SetOutputVoices(*ppSourceVoice, pSendList);
  486. /* Filters */
  487. if (Flags & FAUDIO_VOICE_USEFILTER)
  488. {
  489. (*ppSourceVoice)->filterState = (FAudioFilterState*) audio->pMalloc(
  490. sizeof(FAudioFilterState) * (*ppSourceVoice)->src.format->nChannels
  491. );
  492. FAudio_zero(
  493. (*ppSourceVoice)->filterState,
  494. sizeof(FAudioFilterState) * (*ppSourceVoice)->src.format->nChannels
  495. );
  496. }
  497. /* Sample Storage */
  498. (*ppSourceVoice)->src.decodeSamples = (uint32_t) (FAudio_ceil(
  499. (double) audio->updateSize *
  500. (double) MaxFrequencyRatio *
  501. (double) (*ppSourceVoice)->src.format->nSamplesPerSec /
  502. (double) audio->master->master.inputSampleRate
  503. )) + EXTRA_DECODE_PADDING * (*ppSourceVoice)->src.format->nChannels;
  504. FAudio_INTERNAL_ResizeDecodeCache(
  505. audio,
  506. ((*ppSourceVoice)->src.decodeSamples + EXTRA_DECODE_PADDING) * (*ppSourceVoice)->src.format->nChannels
  507. );
  508. LOG_INFO(audio, "-> %p", (void*) (*ppSourceVoice))
  509. /* Add to list, finally. */
  510. LinkedList_PrependEntry(
  511. &audio->sources,
  512. *ppSourceVoice,
  513. audio->sourceLock,
  514. audio->pMalloc
  515. );
  516. FAudio_AddRef(audio);
  517. #ifdef FAUDIO_DUMP_VOICES
  518. FAudio_DUMPVOICE_Init(*ppSourceVoice);
  519. #endif /* FAUDIO_DUMP_VOICES */
  520. LOG_API_EXIT(audio)
  521. return 0;
  522. }
  523. uint32_t FAudio_CreateSubmixVoice(
  524. FAudio *audio,
  525. FAudioSubmixVoice **ppSubmixVoice,
  526. uint32_t InputChannels,
  527. uint32_t InputSampleRate,
  528. uint32_t Flags,
  529. uint32_t ProcessingStage,
  530. const FAudioVoiceSends *pSendList,
  531. const FAudioEffectChain *pEffectChain
  532. ) {
  533. uint32_t i;
  534. LOG_API_ENTER(audio)
  535. *ppSubmixVoice = (FAudioSubmixVoice*) audio->pMalloc(sizeof(FAudioVoice));
  536. FAudio_zero(*ppSubmixVoice, sizeof(FAudioSubmixVoice));
  537. (*ppSubmixVoice)->audio = audio;
  538. (*ppSubmixVoice)->type = FAUDIO_VOICE_SUBMIX;
  539. (*ppSubmixVoice)->flags = Flags;
  540. (*ppSubmixVoice)->filter.Type = FAUDIO_DEFAULT_FILTER_TYPE;
  541. (*ppSubmixVoice)->filter.Frequency = FAUDIO_DEFAULT_FILTER_FREQUENCY;
  542. (*ppSubmixVoice)->filter.OneOverQ = FAUDIO_DEFAULT_FILTER_ONEOVERQ;
  543. (*ppSubmixVoice)->sendLock = FAudio_PlatformCreateMutex();
  544. LOG_MUTEX_CREATE(audio, (*ppSubmixVoice)->sendLock)
  545. (*ppSubmixVoice)->effectLock = FAudio_PlatformCreateMutex();
  546. LOG_MUTEX_CREATE(audio, (*ppSubmixVoice)->effectLock)
  547. (*ppSubmixVoice)->filterLock = FAudio_PlatformCreateMutex();
  548. LOG_MUTEX_CREATE(audio, (*ppSubmixVoice)->filterLock)
  549. (*ppSubmixVoice)->volumeLock = FAudio_PlatformCreateMutex();
  550. LOG_MUTEX_CREATE(audio, (*ppSubmixVoice)->volumeLock)
  551. /* Submix Properties */
  552. (*ppSubmixVoice)->mix.inputChannels = InputChannels;
  553. (*ppSubmixVoice)->mix.inputSampleRate = InputSampleRate;
  554. (*ppSubmixVoice)->mix.processingStage = ProcessingStage;
  555. /* Resampler */
  556. if (InputChannels == 1)
  557. {
  558. (*ppSubmixVoice)->mix.resample = FAudio_INTERNAL_ResampleMono;
  559. }
  560. else if (InputChannels == 2)
  561. {
  562. (*ppSubmixVoice)->mix.resample = FAudio_INTERNAL_ResampleStereo;
  563. }
  564. else
  565. {
  566. (*ppSubmixVoice)->mix.resample = FAudio_INTERNAL_ResampleGeneric;
  567. }
  568. /* Sample Storage */
  569. (*ppSubmixVoice)->mix.inputSamples = ((uint32_t) FAudio_ceil(
  570. audio->updateSize *
  571. (double) InputSampleRate /
  572. (double) audio->master->master.inputSampleRate
  573. ) + EXTRA_DECODE_PADDING) * InputChannels;
  574. (*ppSubmixVoice)->mix.inputCache = (float*) audio->pMalloc(
  575. sizeof(float) * (*ppSubmixVoice)->mix.inputSamples
  576. );
  577. FAudio_zero( /* Zero this now, for the first update */
  578. (*ppSubmixVoice)->mix.inputCache,
  579. sizeof(float) * (*ppSubmixVoice)->mix.inputSamples
  580. );
  581. /* Sends/Effects */
  582. FAudio_INTERNAL_VoiceOutputFrequency(*ppSubmixVoice, pSendList);
  583. FAudioVoice_SetEffectChain(*ppSubmixVoice, pEffectChain);
  584. /* Default Levels */
  585. (*ppSubmixVoice)->volume = 1.0f;
  586. (*ppSubmixVoice)->channelVolume = (float*) audio->pMalloc(
  587. sizeof(float) * (*ppSubmixVoice)->outputChannels
  588. );
  589. for (i = 0; i < (*ppSubmixVoice)->outputChannels; i += 1)
  590. {
  591. (*ppSubmixVoice)->channelVolume[i] = 1.0f;
  592. }
  593. FAudioVoice_SetOutputVoices(*ppSubmixVoice, pSendList);
  594. /* Filters */
  595. if (Flags & FAUDIO_VOICE_USEFILTER)
  596. {
  597. (*ppSubmixVoice)->filterState = (FAudioFilterState*) audio->pMalloc(
  598. sizeof(FAudioFilterState) * InputChannels
  599. );
  600. FAudio_zero(
  601. (*ppSubmixVoice)->filterState,
  602. sizeof(FAudioFilterState) * InputChannels
  603. );
  604. }
  605. /* Add to list, finally. */
  606. FAudio_INTERNAL_InsertSubmixSorted(
  607. &audio->submixes,
  608. *ppSubmixVoice,
  609. audio->submixLock,
  610. audio->pMalloc
  611. );
  612. FAudio_AddRef(audio);
  613. LOG_API_EXIT(audio)
  614. return 0;
  615. }
  616. uint32_t FAudio_CreateMasteringVoice(
  617. FAudio *audio,
  618. FAudioMasteringVoice **ppMasteringVoice,
  619. uint32_t InputChannels,
  620. uint32_t InputSampleRate,
  621. uint32_t Flags,
  622. uint32_t DeviceIndex,
  623. const FAudioEffectChain *pEffectChain
  624. ) {
  625. FAudioDeviceDetails details;
  626. LOG_API_ENTER(audio)
  627. /* For now we only support one allocated master voice at a time */
  628. FAudio_assert(audio->master == NULL);
  629. if (FAudio_GetDeviceDetails(audio, DeviceIndex, &details) != 0)
  630. {
  631. return FAUDIO_E_INVALID_CALL;
  632. }
  633. *ppMasteringVoice = (FAudioMasteringVoice*) audio->pMalloc(sizeof(FAudioVoice));
  634. FAudio_zero(*ppMasteringVoice, sizeof(FAudioMasteringVoice));
  635. (*ppMasteringVoice)->audio = audio;
  636. (*ppMasteringVoice)->type = FAUDIO_VOICE_MASTER;
  637. (*ppMasteringVoice)->flags = Flags;
  638. (*ppMasteringVoice)->effectLock = FAudio_PlatformCreateMutex();
  639. LOG_MUTEX_CREATE(audio, (*ppMasteringVoice)->effectLock)
  640. (*ppMasteringVoice)->volumeLock = FAudio_PlatformCreateMutex();
  641. LOG_MUTEX_CREATE(audio, (*ppMasteringVoice)->volumeLock)
  642. /* Default Levels */
  643. (*ppMasteringVoice)->volume = 1.0f;
  644. /* Master Properties */
  645. (*ppMasteringVoice)->master.inputChannels = (InputChannels == FAUDIO_DEFAULT_CHANNELS) ?
  646. details.OutputFormat.Format.nChannels :
  647. InputChannels;
  648. (*ppMasteringVoice)->master.inputSampleRate = (InputSampleRate == FAUDIO_DEFAULT_SAMPLERATE) ?
  649. details.OutputFormat.Format.nSamplesPerSec :
  650. InputSampleRate;
  651. /* Sends/Effects */
  652. FAudio_zero(&(*ppMasteringVoice)->sends, sizeof(FAudioVoiceSends));
  653. FAudioVoice_SetEffectChain(*ppMasteringVoice, pEffectChain);
  654. /* This is now safe enough to assign */
  655. audio->master = *ppMasteringVoice;
  656. /* Build the device format.
  657. * The most unintuitive part of this is the use of outputChannels
  658. * instead of master.inputChannels. Bizarrely, the effect chain can
  659. * dictate the _actual_ output channel count, and when the channel count
  660. * mismatches, we have to add a staging buffer for effects to process on
  661. * before ultimately copying the final result to the device. ARGH.
  662. */
  663. WriteWaveFormatExtensible(
  664. &audio->mixFormat,
  665. audio->master->outputChannels,
  666. audio->master->master.inputSampleRate,
  667. &DATAFORMAT_SUBTYPE_IEEE_FLOAT
  668. );
  669. /* Platform Device */
  670. FAudio_AddRef(audio);
  671. FAudio_PlatformInit(
  672. audio,
  673. audio->initFlags,
  674. DeviceIndex,
  675. &audio->mixFormat,
  676. &audio->updateSize,
  677. &audio->platform
  678. );
  679. if (audio->platform == NULL)
  680. {
  681. FAudioVoice_DestroyVoice(*ppMasteringVoice);
  682. *ppMasteringVoice = NULL;
  683. /* Not the best code, but it's probably true? */
  684. return FAUDIO_E_DEVICE_INVALIDATED;
  685. }
  686. audio->master->outputChannels = audio->mixFormat.Format.nChannels;
  687. audio->master->master.inputSampleRate = audio->mixFormat.Format.nSamplesPerSec;
  688. /* Effect Chain Cache */
  689. if ((*ppMasteringVoice)->master.inputChannels != (*ppMasteringVoice)->outputChannels)
  690. {
  691. (*ppMasteringVoice)->master.effectCache = (float*) audio->pMalloc(
  692. sizeof(float) *
  693. audio->updateSize *
  694. (*ppMasteringVoice)->master.inputChannels
  695. );
  696. }
  697. LOG_API_EXIT(audio)
  698. return 0;
  699. }
  700. uint32_t FAudio_CreateMasteringVoice8(
  701. FAudio *audio,
  702. FAudioMasteringVoice **ppMasteringVoice,
  703. uint32_t InputChannels,
  704. uint32_t InputSampleRate,
  705. uint32_t Flags,
  706. uint16_t *szDeviceId,
  707. const FAudioEffectChain *pEffectChain,
  708. FAudioStreamCategory StreamCategory
  709. ) {
  710. uint32_t DeviceIndex, retval;
  711. LOG_API_ENTER(audio)
  712. /* Eventually, we'll want the old CreateMastering to call the new one.
  713. * That will depend on us being able to use DeviceID though.
  714. * For now, use our little ID hack to turn szDeviceId into DeviceIndex.
  715. * -flibit
  716. */
  717. if (szDeviceId == NULL || szDeviceId[0] == 0)
  718. {
  719. DeviceIndex = 0;
  720. }
  721. else
  722. {
  723. DeviceIndex = szDeviceId[0] - L'0';
  724. if (DeviceIndex > FAudio_PlatformGetDeviceCount())
  725. {
  726. DeviceIndex = 0;
  727. }
  728. }
  729. /* Note that StreamCategory is ignored! */
  730. retval = FAudio_CreateMasteringVoice(
  731. audio,
  732. ppMasteringVoice,
  733. InputChannels,
  734. InputSampleRate,
  735. Flags,
  736. DeviceIndex,
  737. pEffectChain
  738. );
  739. LOG_API_EXIT(audio)
  740. return retval;
  741. }
  742. void FAudio_SetEngineProcedureEXT(
  743. FAudio *audio,
  744. FAudioEngineProcedureEXT clientEngineProc,
  745. void *user
  746. ) {
  747. LOG_API_ENTER(audio)
  748. audio->pClientEngineProc = clientEngineProc;
  749. audio->clientEngineUser = user;
  750. LOG_API_EXIT(audio)
  751. }
  752. uint32_t FAudio_StartEngine(FAudio *audio)
  753. {
  754. LOG_API_ENTER(audio)
  755. audio->active = 1;
  756. LOG_API_EXIT(audio)
  757. return 0;
  758. }
  759. void FAudio_StopEngine(FAudio *audio)
  760. {
  761. LOG_API_ENTER(audio)
  762. audio->active = 0;
  763. FAudio_OPERATIONSET_CommitAll(audio);
  764. FAudio_OPERATIONSET_Execute(audio);
  765. LOG_API_EXIT(audio)
  766. }
  767. uint32_t FAudio_CommitOperationSet(FAudio *audio, uint32_t OperationSet)
  768. {
  769. LOG_API_ENTER(audio)
  770. if (OperationSet == FAUDIO_COMMIT_ALL)
  771. {
  772. FAudio_OPERATIONSET_CommitAll(audio);
  773. }
  774. else
  775. {
  776. FAudio_OPERATIONSET_Commit(audio, OperationSet);
  777. }
  778. LOG_API_EXIT(audio)
  779. return 0;
  780. }
  781. uint32_t FAudio_CommitChanges(FAudio *audio)
  782. {
  783. FAudio_Log(
  784. "IF YOU CAN READ THIS, YOUR PROGRAM IS ABOUT TO BREAK!"
  785. "\n\nEither you or somebody else is using FAudio_CommitChanges,"
  786. "\nwhen they should be using FAudio_CommitOperationSet instead."
  787. "\n\nIf your program calls this, move to CommitOperationSet."
  788. "\n\nIf somebody else is calling this, find out who it is and"
  789. "\nfile a bug report with them ASAP."
  790. );
  791. /* Seriously, this is like the worst possible thing short of no-oping.
  792. * For the love-a Pete, just migrate, do it, what is wrong with you
  793. */
  794. return FAudio_CommitOperationSet(audio, FAUDIO_COMMIT_ALL);
  795. }
  796. void FAudio_GetPerformanceData(
  797. FAudio *audio,
  798. FAudioPerformanceData *pPerfData
  799. ) {
  800. LinkedList *list;
  801. FAudioSourceVoice *source;
  802. LOG_API_ENTER(audio)
  803. FAudio_zero(pPerfData, sizeof(FAudioPerformanceData));
  804. FAudio_PlatformLockMutex(audio->sourceLock);
  805. LOG_MUTEX_LOCK(audio, audio->sourceLock)
  806. list = audio->sources;
  807. while (list != NULL)
  808. {
  809. source = (FAudioSourceVoice*) list->entry;
  810. pPerfData->TotalSourceVoiceCount += 1;
  811. if (source->src.active)
  812. {
  813. pPerfData->ActiveSourceVoiceCount += 1;
  814. }
  815. list = list->next;
  816. }
  817. FAudio_PlatformUnlockMutex(audio->sourceLock);
  818. LOG_MUTEX_UNLOCK(audio, audio->sourceLock)
  819. FAudio_PlatformLockMutex(audio->submixLock);
  820. LOG_MUTEX_LOCK(audio, audio->submixLock)
  821. list = audio->submixes;
  822. while (list != NULL)
  823. {
  824. pPerfData->ActiveSubmixVoiceCount += 1;
  825. list = list->next;
  826. }
  827. FAudio_PlatformUnlockMutex(audio->submixLock);
  828. LOG_MUTEX_UNLOCK(audio, audio->submixLock)
  829. if (audio->master != NULL)
  830. {
  831. /* estimate, should use real latency from platform */
  832. pPerfData->CurrentLatencyInSamples = 2 * audio->updateSize;
  833. }
  834. LOG_API_EXIT(audio)
  835. }
  836. void FAudio_SetDebugConfiguration(
  837. FAudio *audio,
  838. FAudioDebugConfiguration *pDebugConfiguration,
  839. void* pReserved
  840. ) {
  841. #ifndef FAUDIO_DISABLE_DEBUGCONFIGURATION
  842. char *env;
  843. LOG_API_ENTER(audio)
  844. FAudio_memcpy(
  845. &audio->debug,
  846. pDebugConfiguration,
  847. sizeof(FAudioDebugConfiguration)
  848. );
  849. env = FAudio_getenv("FAUDIO_LOG_EVERYTHING");
  850. if (env != NULL && *env == '1')
  851. {
  852. audio->debug.TraceMask = (
  853. FAUDIO_LOG_ERRORS |
  854. FAUDIO_LOG_WARNINGS |
  855. FAUDIO_LOG_INFO |
  856. FAUDIO_LOG_DETAIL |
  857. FAUDIO_LOG_API_CALLS |
  858. FAUDIO_LOG_FUNC_CALLS |
  859. FAUDIO_LOG_TIMING |
  860. FAUDIO_LOG_LOCKS |
  861. FAUDIO_LOG_MEMORY |
  862. FAUDIO_LOG_STREAMING
  863. );
  864. audio->debug.LogThreadID = 1;
  865. audio->debug.LogFunctionName = 1;
  866. audio->debug.LogTiming = 1;
  867. }
  868. #define CHECK_ENV(type) \
  869. env = FAudio_getenv("FAUDIO_LOG_" #type); \
  870. if (env != NULL) \
  871. { \
  872. if (*env == '1') \
  873. { \
  874. audio->debug.TraceMask |= FAUDIO_LOG_##type; \
  875. } \
  876. else \
  877. { \
  878. audio->debug.TraceMask &= ~FAUDIO_LOG_##type; \
  879. } \
  880. }
  881. CHECK_ENV(ERRORS)
  882. CHECK_ENV(WARNINGS)
  883. CHECK_ENV(INFO)
  884. CHECK_ENV(DETAIL)
  885. CHECK_ENV(API_CALLS)
  886. CHECK_ENV(FUNC_CALLS)
  887. CHECK_ENV(TIMING)
  888. CHECK_ENV(LOCKS)
  889. CHECK_ENV(MEMORY)
  890. CHECK_ENV(STREAMING)
  891. #undef CHECK_ENV
  892. #define CHECK_ENV(envvar, boolvar) \
  893. env = FAudio_getenv("FAUDIO_LOG_LOG" #envvar); \
  894. if (env != NULL) \
  895. { \
  896. audio->debug.Log##boolvar = (*env == '1'); \
  897. }
  898. CHECK_ENV(THREADID, ThreadID)
  899. CHECK_ENV(FILELINE, Fileline)
  900. CHECK_ENV(FUNCTIONNAME, FunctionName)
  901. CHECK_ENV(TIMING, Timing)
  902. #undef CHECK_ENV
  903. LOG_API_EXIT(audio)
  904. #endif /* FAUDIO_DISABLE_DEBUGCONFIGURATION */
  905. }
  906. void FAudio_GetProcessingQuantum(
  907. FAudio *audio,
  908. uint32_t *quantumNumerator,
  909. uint32_t *quantumDenominator
  910. ) {
  911. FAudio_assert(audio->master != NULL);
  912. if (quantumNumerator != NULL)
  913. {
  914. *quantumNumerator = audio->updateSize;
  915. }
  916. if (quantumDenominator != NULL)
  917. {
  918. *quantumDenominator = audio->master->master.inputSampleRate;
  919. }
  920. }
  921. /* FAudioVoice Interface */
  922. static void FAudio_RecalcMixMatrix(FAudioVoice *voice, uint32_t sendIndex)
  923. {
  924. uint32_t oChan, s, d;
  925. FAudioVoice *out = voice->sends.pSends[sendIndex].pOutputVoice;
  926. float volume, *matrix = voice->mixCoefficients[sendIndex];
  927. if (voice->type == FAUDIO_VOICE_SUBMIX)
  928. {
  929. volume = 1.f;
  930. }
  931. else
  932. {
  933. volume = voice->volume;
  934. }
  935. if (out->type == FAUDIO_VOICE_MASTER)
  936. {
  937. oChan = out->master.inputChannels;
  938. }
  939. else
  940. {
  941. oChan = out->mix.inputChannels;
  942. }
  943. for (d = 0; d < oChan; d += 1)
  944. {
  945. for (s = 0; s < voice->outputChannels; s += 1)
  946. {
  947. matrix[d * voice->outputChannels + s] = volume *
  948. voice->channelVolume[s] *
  949. voice->sendCoefficients[sendIndex][d * voice->outputChannels + s];
  950. }
  951. }
  952. }
  953. void FAudioVoice_GetVoiceDetails(
  954. FAudioVoice *voice,
  955. FAudioVoiceDetails *pVoiceDetails
  956. ) {
  957. LOG_API_ENTER(voice->audio)
  958. pVoiceDetails->CreationFlags = voice->flags;
  959. pVoiceDetails->ActiveFlags = voice->flags;
  960. if (voice->type == FAUDIO_VOICE_SOURCE)
  961. {
  962. pVoiceDetails->InputChannels = voice->src.format->nChannels;
  963. pVoiceDetails->InputSampleRate = voice->src.format->nSamplesPerSec;
  964. }
  965. else if (voice->type == FAUDIO_VOICE_SUBMIX)
  966. {
  967. pVoiceDetails->InputChannels = voice->mix.inputChannels;
  968. pVoiceDetails->InputSampleRate = voice->mix.inputSampleRate;
  969. }
  970. else if (voice->type == FAUDIO_VOICE_MASTER)
  971. {
  972. pVoiceDetails->InputChannels = voice->master.inputChannels;
  973. pVoiceDetails->InputSampleRate = voice->master.inputSampleRate;
  974. }
  975. else
  976. {
  977. FAudio_assert(0 && "Unknown voice type!");
  978. }
  979. LOG_API_EXIT(voice->audio)
  980. }
  981. uint32_t FAudioVoice_SetOutputVoices(
  982. FAudioVoice *voice,
  983. const FAudioVoiceSends *pSendList
  984. ) {
  985. uint32_t i;
  986. uint32_t outChannels;
  987. FAudioVoiceSends defaultSends;
  988. FAudioSendDescriptor defaultSend;
  989. LOG_API_ENTER(voice->audio)
  990. if (voice->type == FAUDIO_VOICE_MASTER)
  991. {
  992. LOG_API_EXIT(voice->audio)
  993. return FAUDIO_E_INVALID_CALL;
  994. }
  995. FAudio_PlatformLockMutex(voice->sendLock);
  996. LOG_MUTEX_LOCK(voice->audio, voice->sendLock)
  997. if (FAudio_INTERNAL_VoiceOutputFrequency(voice, pSendList) != 0)
  998. {
  999. LOG_ERROR(
  1000. voice->audio,
  1001. "%s",
  1002. "Changing the sample rate while an effect chain is attached is invalid!"
  1003. )
  1004. FAudio_PlatformUnlockMutex(voice->sendLock);
  1005. LOG_MUTEX_UNLOCK(voice->audio, voice->sendLock)
  1006. LOG_API_EXIT(voice->audio)
  1007. return FAUDIO_E_INVALID_CALL;
  1008. }
  1009. FAudio_PlatformLockMutex(voice->volumeLock);
  1010. LOG_MUTEX_LOCK(voice->audio, voice->volumeLock)
  1011. /* FIXME: This is lazy... */
  1012. for (i = 0; i < voice->sends.SendCount; i += 1)
  1013. {
  1014. voice->audio->pFree(voice->sendCoefficients[i]);
  1015. }
  1016. if (voice->sendCoefficients != NULL)
  1017. {
  1018. voice->audio->pFree(voice->sendCoefficients);
  1019. }
  1020. for (i = 0; i < voice->sends.SendCount; i += 1)
  1021. {
  1022. voice->audio->pFree(voice->mixCoefficients[i]);
  1023. }
  1024. if (voice->mixCoefficients != NULL)
  1025. {
  1026. voice->audio->pFree(voice->mixCoefficients);
  1027. }
  1028. if (voice->sendMix != NULL)
  1029. {
  1030. voice->audio->pFree(voice->sendMix);
  1031. }
  1032. if (voice->sendFilter != NULL)
  1033. {
  1034. voice->audio->pFree(voice->sendFilter);
  1035. voice->sendFilter = NULL;
  1036. }
  1037. if (voice->sendFilterState != NULL)
  1038. {
  1039. for (i = 0; i < voice->sends.SendCount; i += 1)
  1040. {
  1041. if (voice->sendFilterState[i] != NULL)
  1042. {
  1043. voice->audio->pFree(voice->sendFilterState[i]);
  1044. }
  1045. }
  1046. voice->audio->pFree(voice->sendFilterState);
  1047. voice->sendFilterState = NULL;
  1048. }
  1049. if (voice->sends.pSends != NULL)
  1050. {
  1051. voice->audio->pFree(voice->sends.pSends);
  1052. }
  1053. if (pSendList == NULL)
  1054. {
  1055. /* Default to the mastering voice as output */
  1056. defaultSend.Flags = 0;
  1057. defaultSend.pOutputVoice = voice->audio->master;
  1058. defaultSends.SendCount = 1;
  1059. defaultSends.pSends = &defaultSend;
  1060. pSendList = &defaultSends;
  1061. }
  1062. else if (pSendList->SendCount == 0)
  1063. {
  1064. /* No sends? Nothing to do... */
  1065. voice->sendCoefficients = NULL;
  1066. voice->mixCoefficients = NULL;
  1067. voice->sendMix = NULL;
  1068. FAudio_zero(&voice->sends, sizeof(FAudioVoiceSends));
  1069. FAudio_PlatformUnlockMutex(voice->volumeLock);
  1070. LOG_MUTEX_UNLOCK(voice->audio, voice->volumeLock)
  1071. FAudio_PlatformUnlockMutex(voice->sendLock);
  1072. LOG_MUTEX_UNLOCK(voice->audio, voice->sendLock)
  1073. LOG_API_EXIT(voice->audio)
  1074. return 0;
  1075. }
  1076. /* Copy send list */
  1077. voice->sends.SendCount = pSendList->SendCount;
  1078. voice->sends.pSends = (FAudioSendDescriptor*) voice->audio->pMalloc(
  1079. pSendList->SendCount * sizeof(FAudioSendDescriptor)
  1080. );
  1081. FAudio_memcpy(
  1082. voice->sends.pSends,
  1083. pSendList->pSends,
  1084. pSendList->SendCount * sizeof(FAudioSendDescriptor)
  1085. );
  1086. /* Allocate/Reset default output matrix, mixer function, filters */
  1087. voice->sendCoefficients = (float**) voice->audio->pMalloc(
  1088. sizeof(float*) * pSendList->SendCount
  1089. );
  1090. voice->mixCoefficients = (float**) voice->audio->pMalloc(
  1091. sizeof(float*) * pSendList->SendCount
  1092. );
  1093. voice->sendMix = (FAudioMixCallback*) voice->audio->pMalloc(
  1094. sizeof(FAudioMixCallback) * pSendList->SendCount
  1095. );
  1096. for (i = 0; i < pSendList->SendCount; i += 1)
  1097. {
  1098. if (pSendList->pSends[i].pOutputVoice->type == FAUDIO_VOICE_MASTER)
  1099. {
  1100. outChannels = pSendList->pSends[i].pOutputVoice->master.inputChannels;
  1101. }
  1102. else
  1103. {
  1104. outChannels = pSendList->pSends[i].pOutputVoice->mix.inputChannels;
  1105. }
  1106. voice->sendCoefficients[i] = (float*) voice->audio->pMalloc(
  1107. sizeof(float) * voice->outputChannels * outChannels
  1108. );
  1109. voice->mixCoefficients[i] = (float*) voice->audio->pMalloc(
  1110. sizeof(float) * voice->outputChannels * outChannels
  1111. );
  1112. FAudio_assert(voice->outputChannels > 0 && voice->outputChannels < 9);
  1113. FAudio_assert(outChannels > 0 && outChannels < 9);
  1114. FAudio_memcpy(
  1115. voice->sendCoefficients[i],
  1116. FAUDIO_INTERNAL_MATRIX_DEFAULTS[voice->outputChannels - 1][outChannels - 1],
  1117. voice->outputChannels * outChannels * sizeof(float)
  1118. );
  1119. FAudio_RecalcMixMatrix(voice, i);
  1120. if (voice->outputChannels == 1)
  1121. {
  1122. if (outChannels == 1)
  1123. {
  1124. voice->sendMix[i] = FAudio_INTERNAL_Mix_1in_1out_Scalar;
  1125. }
  1126. else if (outChannels == 2)
  1127. {
  1128. voice->sendMix[i] = FAudio_INTERNAL_Mix_1in_2out_Scalar;
  1129. }
  1130. else if (outChannels == 6)
  1131. {
  1132. voice->sendMix[i] = FAudio_INTERNAL_Mix_1in_6out_Scalar;
  1133. }
  1134. else if (outChannels == 8)
  1135. {
  1136. voice->sendMix[i] = FAudio_INTERNAL_Mix_1in_8out_Scalar;
  1137. }
  1138. else
  1139. {
  1140. voice->sendMix[i] = FAudio_INTERNAL_Mix_Generic;
  1141. }
  1142. }
  1143. else if (voice->outputChannels == 2)
  1144. {
  1145. if (outChannels == 1)
  1146. {
  1147. voice->sendMix[i] = FAudio_INTERNAL_Mix_2in_1out_Scalar;
  1148. }
  1149. else if (outChannels == 2)
  1150. {
  1151. voice->sendMix[i] = FAudio_INTERNAL_Mix_2in_2out_Scalar;
  1152. }
  1153. else if (outChannels == 6)
  1154. {
  1155. voice->sendMix[i] = FAudio_INTERNAL_Mix_2in_6out_Scalar;
  1156. }
  1157. else if (outChannels == 8)
  1158. {
  1159. voice->sendMix[i] = FAudio_INTERNAL_Mix_2in_8out_Scalar;
  1160. }
  1161. else
  1162. {
  1163. voice->sendMix[i] = FAudio_INTERNAL_Mix_Generic;
  1164. }
  1165. }
  1166. else
  1167. {
  1168. voice->sendMix[i] = FAudio_INTERNAL_Mix_Generic;
  1169. }
  1170. if (pSendList->pSends[i].Flags & FAUDIO_SEND_USEFILTER)
  1171. {
  1172. /* Allocate the whole send filter array if needed... */
  1173. if (voice->sendFilter == NULL)
  1174. {
  1175. voice->sendFilter = (FAudioFilterParameters*) voice->audio->pMalloc(
  1176. sizeof(FAudioFilterParameters) * pSendList->SendCount
  1177. );
  1178. }
  1179. if (voice->sendFilterState == NULL)
  1180. {
  1181. voice->sendFilterState = (FAudioFilterState**) voice->audio->pMalloc(
  1182. sizeof(FAudioFilterState*) * pSendList->SendCount
  1183. );
  1184. FAudio_zero(
  1185. voice->sendFilterState,
  1186. sizeof(FAudioFilterState*) * pSendList->SendCount
  1187. );
  1188. }
  1189. /* ... then fill in this send's filter data */
  1190. voice->sendFilter[i].Type = FAUDIO_DEFAULT_FILTER_TYPE;
  1191. voice->sendFilter[i].Frequency = FAUDIO_DEFAULT_FILTER_FREQUENCY;
  1192. voice->sendFilter[i].OneOverQ = FAUDIO_DEFAULT_FILTER_ONEOVERQ;
  1193. voice->sendFilterState[i] = (FAudioFilterState*) voice->audio->pMalloc(
  1194. sizeof(FAudioFilterState) * outChannels
  1195. );
  1196. FAudio_zero(
  1197. voice->sendFilterState[i],
  1198. sizeof(FAudioFilterState) * outChannels
  1199. );
  1200. }
  1201. }
  1202. FAudio_PlatformUnlockMutex(voice->volumeLock);
  1203. LOG_MUTEX_UNLOCK(voice->audio, voice->volumeLock)
  1204. FAudio_PlatformUnlockMutex(voice->sendLock);
  1205. LOG_MUTEX_UNLOCK(voice->audio, voice->sendLock)
  1206. LOG_API_EXIT(voice->audio)
  1207. return 0;
  1208. }
  1209. uint32_t FAudioVoice_SetEffectChain(
  1210. FAudioVoice *voice,
  1211. const FAudioEffectChain *pEffectChain
  1212. ) {
  1213. uint32_t i;
  1214. FAPO *fapo;
  1215. uint32_t channelCount;
  1216. FAudioVoiceDetails voiceDetails;
  1217. FAPORegistrationProperties *pProps;
  1218. FAudioWaveFormatExtensible srcFmt, dstFmt;
  1219. FAPOLockForProcessBufferParameters srcLockParams, dstLockParams;
  1220. LOG_API_ENTER(voice->audio)
  1221. FAudioVoice_GetVoiceDetails(voice, &voiceDetails);
  1222. /* SetEffectChain must not change the number of output channels once the voice has been created */
  1223. if (pEffectChain == NULL && voice->outputChannels != 0)
  1224. {
  1225. /* cannot remove an effect chain that changes the number of channels */
  1226. if (voice->outputChannels != voiceDetails.InputChannels)
  1227. {
  1228. LOG_ERROR(
  1229. voice->audio,
  1230. "%s",
  1231. "Cannot remove effect chain that changes the number of channels"
  1232. )
  1233. FAudio_assert(0 && "Cannot remove effect chain that changes the number of channels");
  1234. LOG_API_EXIT(voice->audio)
  1235. return FAUDIO_E_INVALID_CALL;
  1236. }
  1237. }
  1238. if (pEffectChain != NULL && voice->outputChannels != 0)
  1239. {
  1240. uint32_t lst = pEffectChain->EffectCount - 1;
  1241. /* new effect chain must have same number of output channels */
  1242. if (voice->outputChannels != pEffectChain->pEffectDescriptors[lst].OutputChannels)
  1243. {
  1244. LOG_ERROR(
  1245. voice->audio,
  1246. "%s",
  1247. "New effect chain must have same number of output channels as the old chain"
  1248. )
  1249. FAudio_assert(0 && "New effect chain must have same number of output channels as the old chain");
  1250. LOG_API_EXIT(voice->audio)
  1251. return FAUDIO_E_INVALID_CALL;
  1252. }
  1253. }
  1254. FAudio_PlatformLockMutex(voice->effectLock);
  1255. LOG_MUTEX_LOCK(voice->audio, voice->effectLock)
  1256. if (pEffectChain == NULL)
  1257. {
  1258. FAudio_INTERNAL_FreeEffectChain(voice);
  1259. FAudio_zero(&voice->effects, sizeof(voice->effects));
  1260. voice->outputChannels = voiceDetails.InputChannels;
  1261. }
  1262. else
  1263. {
  1264. /* Validate incoming chain before changing the current chain */
  1265. /* These are always the same, so just write them now. */
  1266. srcLockParams.pFormat = &srcFmt.Format;
  1267. dstLockParams.pFormat = &dstFmt.Format;
  1268. if (voice->type == FAUDIO_VOICE_SOURCE)
  1269. {
  1270. srcLockParams.MaxFrameCount = voice->src.resampleSamples;
  1271. dstLockParams.MaxFrameCount = voice->src.resampleSamples;
  1272. }
  1273. else if (voice->type == FAUDIO_VOICE_SUBMIX)
  1274. {
  1275. srcLockParams.MaxFrameCount = voice->mix.outputSamples;
  1276. dstLockParams.MaxFrameCount = voice->mix.outputSamples;
  1277. }
  1278. else if (voice->type == FAUDIO_VOICE_MASTER)
  1279. {
  1280. srcLockParams.MaxFrameCount = voice->audio->updateSize;
  1281. dstLockParams.MaxFrameCount = voice->audio->updateSize;
  1282. }
  1283. /* The first source is the voice input data... */
  1284. srcFmt.Format.wBitsPerSample = 32;
  1285. srcFmt.Format.wFormatTag = FAUDIO_FORMAT_EXTENSIBLE;
  1286. srcFmt.Format.nChannels = voiceDetails.InputChannels;
  1287. srcFmt.Format.nSamplesPerSec = voiceDetails.InputSampleRate;
  1288. srcFmt.Format.nBlockAlign = srcFmt.Format.nChannels * (srcFmt.Format.wBitsPerSample / 8);
  1289. srcFmt.Format.nAvgBytesPerSec = srcFmt.Format.nSamplesPerSec * srcFmt.Format.nBlockAlign;
  1290. srcFmt.Format.cbSize = sizeof(FAudioWaveFormatExtensible) - sizeof(FAudioWaveFormatEx);
  1291. srcFmt.Samples.wValidBitsPerSample = srcFmt.Format.wBitsPerSample;
  1292. srcFmt.dwChannelMask = 0;
  1293. FAudio_memcpy(&srcFmt.SubFormat, &DATAFORMAT_SUBTYPE_IEEE_FLOAT, sizeof(FAudioGUID));
  1294. FAudio_memcpy(&dstFmt, &srcFmt, sizeof(srcFmt));
  1295. for (i = 0; i < pEffectChain->EffectCount; i += 1)
  1296. {
  1297. fapo = pEffectChain->pEffectDescriptors[i].pEffect;
  1298. /* ... then we get this effect's format... */
  1299. dstFmt.Format.nChannels = pEffectChain->pEffectDescriptors[i].OutputChannels;
  1300. dstFmt.Format.nBlockAlign = dstFmt.Format.nChannels * (dstFmt.Format.wBitsPerSample / 8);
  1301. dstFmt.Format.nAvgBytesPerSec = dstFmt.Format.nSamplesPerSec * dstFmt.Format.nBlockAlign;
  1302. /* FIXME: This error needs to be found _before_ we start
  1303. * shredding the voice's state. This function is highly
  1304. * destructive so any errors need to be found at the
  1305. * beginning, not in the middle! We can't undo this!
  1306. * -flibit
  1307. */
  1308. if (fapo->LockForProcess(fapo, 1, &srcLockParams, 1, &dstLockParams))
  1309. {
  1310. LOG_ERROR(
  1311. voice->audio,
  1312. "%s",
  1313. "Effect output format not supported"
  1314. )
  1315. FAudio_assert(0 && "Effect output format not supported");
  1316. FAudio_PlatformUnlockMutex(voice->effectLock);
  1317. LOG_MUTEX_UNLOCK(voice->audio, voice->effectLock)
  1318. LOG_API_EXIT(voice->audio)
  1319. return FAUDIO_E_UNSUPPORTED_FORMAT;
  1320. }
  1321. /* Okay, now this effect is the source and the next
  1322. * effect will be the destination. Repeat until no
  1323. * effects left.
  1324. */
  1325. FAudio_memcpy(&srcFmt, &dstFmt, sizeof(srcFmt));
  1326. }
  1327. FAudio_INTERNAL_FreeEffectChain(voice);
  1328. FAudio_INTERNAL_AllocEffectChain(
  1329. voice,
  1330. pEffectChain
  1331. );
  1332. /* check if in-place processing is supported */
  1333. channelCount = voiceDetails.InputChannels;
  1334. for (i = 0; i < voice->effects.count; i += 1)
  1335. {
  1336. fapo = voice->effects.desc[i].pEffect;
  1337. if (fapo->GetRegistrationProperties(fapo, &pProps) == 0)
  1338. {
  1339. voice->effects.inPlaceProcessing[i] = (pProps->Flags & FAPO_FLAG_INPLACE_SUPPORTED) == FAPO_FLAG_INPLACE_SUPPORTED;
  1340. voice->effects.inPlaceProcessing[i] &= (channelCount == voice->effects.desc[i].OutputChannels);
  1341. channelCount = voice->effects.desc[i].OutputChannels;
  1342. /* Fails if in-place processing is mandatory and
  1343. * the chain forces us to do otherwise...
  1344. */
  1345. FAudio_assert(
  1346. !(pProps->Flags & FAPO_FLAG_INPLACE_REQUIRED) ||
  1347. voice->effects.inPlaceProcessing[i]
  1348. );
  1349. voice->audio->pFree(pProps);
  1350. }
  1351. }
  1352. voice->outputChannels = channelCount;
  1353. }
  1354. FAudio_PlatformUnlockMutex(voice->effectLock);
  1355. LOG_MUTEX_UNLOCK(voice->audio, voice->effectLock)
  1356. LOG_API_EXIT(voice->audio)
  1357. return 0;
  1358. }
  1359. uint32_t FAudioVoice_EnableEffect(
  1360. FAudioVoice *voice,
  1361. uint32_t EffectIndex,
  1362. uint32_t OperationSet
  1363. ) {
  1364. LOG_API_ENTER(voice->audio)
  1365. if (OperationSet != FAUDIO_COMMIT_NOW && voice->audio->active)
  1366. {
  1367. FAudio_OPERATIONSET_QueueEnableEffect(
  1368. voice,
  1369. EffectIndex,
  1370. OperationSet
  1371. );
  1372. LOG_API_EXIT(voice->audio)
  1373. return 0;
  1374. }
  1375. FAudio_PlatformLockMutex(voice->effectLock);
  1376. LOG_MUTEX_LOCK(voice->audio, voice->effectLock)
  1377. voice->effects.desc[EffectIndex].InitialState = 1;
  1378. FAudio_PlatformUnlockMutex(voice->effectLock);
  1379. LOG_MUTEX_UNLOCK(voice->audio, voice->effectLock)
  1380. LOG_API_EXIT(voice->audio)
  1381. return 0;
  1382. }
  1383. uint32_t FAudioVoice_DisableEffect(
  1384. FAudioVoice *voice,
  1385. uint32_t EffectIndex,
  1386. uint32_t OperationSet
  1387. ) {
  1388. LOG_API_ENTER(voice->audio)
  1389. if (OperationSet != FAUDIO_COMMIT_NOW && voice->audio->active)
  1390. {
  1391. FAudio_OPERATIONSET_QueueDisableEffect(
  1392. voice,
  1393. EffectIndex,
  1394. OperationSet
  1395. );
  1396. LOG_API_EXIT(voice->audio)
  1397. return 0;
  1398. }
  1399. FAudio_PlatformLockMutex(voice->effectLock);
  1400. LOG_MUTEX_LOCK(voice->audio, voice->effectLock)
  1401. voice->effects.desc[EffectIndex].InitialState = 0;
  1402. FAudio_PlatformUnlockMutex(voice->effectLock);
  1403. LOG_MUTEX_UNLOCK(voice->audio, voice->effectLock)
  1404. LOG_API_EXIT(voice->audio)
  1405. return 0;
  1406. }
  1407. void FAudioVoice_GetEffectState(
  1408. FAudioVoice *voice,
  1409. uint32_t EffectIndex,
  1410. int32_t *pEnabled
  1411. ) {
  1412. LOG_API_ENTER(voice->audio)
  1413. FAudio_PlatformLockMutex(voice->effectLock);
  1414. LOG_MUTEX_LOCK(voice->audio, voice->effectLock)
  1415. *pEnabled = voice->effects.desc[EffectIndex].InitialState;
  1416. FAudio_PlatformUnlockMutex(voice->effectLock);
  1417. LOG_MUTEX_UNLOCK(voice->audio, voice->effectLock)
  1418. LOG_API_EXIT(voice->audio)
  1419. }
  1420. uint32_t FAudioVoice_SetEffectParameters(
  1421. FAudioVoice *voice,
  1422. uint32_t EffectIndex,
  1423. const void *pParameters,
  1424. uint32_t ParametersByteSize,
  1425. uint32_t OperationSet
  1426. ) {
  1427. LOG_API_ENTER(voice->audio)
  1428. if (OperationSet != FAUDIO_COMMIT_NOW && voice->audio->active)
  1429. {
  1430. FAudio_OPERATIONSET_QueueSetEffectParameters(
  1431. voice,
  1432. EffectIndex,
  1433. pParameters,
  1434. ParametersByteSize,
  1435. OperationSet
  1436. );
  1437. LOG_API_EXIT(voice->audio)
  1438. return 0;
  1439. }
  1440. if (voice->effects.parameters[EffectIndex] == NULL)
  1441. {
  1442. voice->effects.parameters[EffectIndex] = voice->audio->pMalloc(
  1443. ParametersByteSize
  1444. );
  1445. voice->effects.parameterSizes[EffectIndex] = ParametersByteSize;
  1446. }
  1447. FAudio_PlatformLockMutex(voice->effectLock);
  1448. LOG_MUTEX_LOCK(voice->audio, voice->effectLock)
  1449. if (voice->effects.parameterSizes[EffectIndex] < ParametersByteSize)
  1450. {
  1451. voice->effects.parameters[EffectIndex] = voice->audio->pRealloc(
  1452. voice->effects.parameters[EffectIndex],
  1453. ParametersByteSize
  1454. );
  1455. voice->effects.parameterSizes[EffectIndex] = ParametersByteSize;
  1456. }
  1457. FAudio_memcpy(
  1458. voice->effects.parameters[EffectIndex],
  1459. pParameters,
  1460. ParametersByteSize
  1461. );
  1462. voice->effects.parameterUpdates[EffectIndex] = 1;
  1463. FAudio_PlatformUnlockMutex(voice->effectLock);
  1464. LOG_MUTEX_UNLOCK(voice->audio, voice->effectLock)
  1465. LOG_API_EXIT(voice->audio)
  1466. return 0;
  1467. }
  1468. uint32_t FAudioVoice_GetEffectParameters(
  1469. FAudioVoice *voice,
  1470. uint32_t EffectIndex,
  1471. void *pParameters,
  1472. uint32_t ParametersByteSize
  1473. ) {
  1474. FAPO *fapo;
  1475. LOG_API_ENTER(voice->audio)
  1476. FAudio_PlatformLockMutex(voice->effectLock);
  1477. LOG_MUTEX_LOCK(voice->audio, voice->effectLock)
  1478. fapo = voice->effects.desc[EffectIndex].pEffect;
  1479. fapo->GetParameters(fapo, pParameters, ParametersByteSize);
  1480. FAudio_PlatformUnlockMutex(voice->effectLock);
  1481. LOG_MUTEX_UNLOCK(voice->audio, voice->effectLock)
  1482. LOG_API_EXIT(voice->audio)
  1483. return 0;
  1484. }
  1485. uint32_t FAudioVoice_SetFilterParameters(
  1486. FAudioVoice *voice,
  1487. const FAudioFilterParameters *pParameters,
  1488. uint32_t OperationSet
  1489. ) {
  1490. LOG_API_ENTER(voice->audio)
  1491. if (OperationSet != FAUDIO_COMMIT_NOW && voice->audio->active)
  1492. {
  1493. FAudio_OPERATIONSET_QueueSetFilterParameters(
  1494. voice,
  1495. pParameters,
  1496. OperationSet
  1497. );
  1498. LOG_API_EXIT(voice->audio)
  1499. return 0;
  1500. }
  1501. /* MSDN: "This method is usable only on source and submix voices and
  1502. * has no effect on mastering voices."
  1503. */
  1504. if (voice->type == FAUDIO_VOICE_MASTER)
  1505. {
  1506. LOG_API_EXIT(voice->audio)
  1507. return 0;
  1508. }
  1509. if (!(voice->flags & FAUDIO_VOICE_USEFILTER))
  1510. {
  1511. LOG_API_EXIT(voice->audio)
  1512. return 0;
  1513. }
  1514. FAudio_PlatformLockMutex(voice->filterLock);
  1515. LOG_MUTEX_LOCK(voice->audio, voice->filterLock)
  1516. FAudio_memcpy(
  1517. &voice->filter,
  1518. pParameters,
  1519. sizeof(FAudioFilterParameters)
  1520. );
  1521. FAudio_PlatformUnlockMutex(voice->filterLock);
  1522. LOG_MUTEX_UNLOCK(voice->audio, voice->filterLock)
  1523. LOG_API_EXIT(voice->audio)
  1524. return 0;
  1525. }
  1526. void FAudioVoice_GetFilterParameters(
  1527. FAudioVoice *voice,
  1528. FAudioFilterParameters *pParameters
  1529. ) {
  1530. LOG_API_ENTER(voice->audio)
  1531. /* MSDN: "This method is usable only on source and submix voices and
  1532. * has no effect on mastering voices."
  1533. */
  1534. if (voice->type == FAUDIO_VOICE_MASTER)
  1535. {
  1536. LOG_API_EXIT(voice->audio)
  1537. return;
  1538. }
  1539. if (!(voice->flags & FAUDIO_VOICE_USEFILTER))
  1540. {
  1541. LOG_API_EXIT(voice->audio)
  1542. return;
  1543. }
  1544. FAudio_PlatformLockMutex(voice->filterLock);
  1545. LOG_MUTEX_LOCK(voice->audio, voice->filterLock)
  1546. FAudio_memcpy(
  1547. pParameters,
  1548. &voice->filter,
  1549. sizeof(FAudioFilterParameters)
  1550. );
  1551. FAudio_PlatformUnlockMutex(voice->filterLock);
  1552. LOG_MUTEX_UNLOCK(voice->audio, voice->filterLock)
  1553. LOG_API_EXIT(voice->audio)
  1554. }
  1555. uint32_t FAudioVoice_SetOutputFilterParameters(
  1556. FAudioVoice *voice,
  1557. FAudioVoice *pDestinationVoice,
  1558. const FAudioFilterParameters *pParameters,
  1559. uint32_t OperationSet
  1560. ) {
  1561. uint32_t i;
  1562. LOG_API_ENTER(voice->audio)
  1563. if (OperationSet != FAUDIO_COMMIT_NOW && voice->audio->active)
  1564. {
  1565. FAudio_OPERATIONSET_QueueSetOutputFilterParameters(
  1566. voice,
  1567. pDestinationVoice,
  1568. pParameters,
  1569. OperationSet
  1570. );
  1571. LOG_API_EXIT(voice->audio)
  1572. return 0;
  1573. }
  1574. /* MSDN: "This method is usable only on source and submix voices and
  1575. * has no effect on mastering voices."
  1576. */
  1577. if (voice->type == FAUDIO_VOICE_MASTER)
  1578. {
  1579. LOG_API_EXIT(voice->audio)
  1580. return 0;
  1581. }
  1582. FAudio_PlatformLockMutex(voice->sendLock);
  1583. LOG_MUTEX_LOCK(voice->audio, voice->sendLock)
  1584. /* Find the send index */
  1585. if (pDestinationVoice == NULL && voice->sends.SendCount == 1)
  1586. {
  1587. pDestinationVoice = voice->sends.pSends[0].pOutputVoice;
  1588. }
  1589. for (i = 0; i < voice->sends.SendCount; i += 1)
  1590. {
  1591. if (pDestinationVoice == voice->sends.pSends[i].pOutputVoice)
  1592. {
  1593. break;
  1594. }
  1595. }
  1596. if (i >= voice->sends.SendCount)
  1597. {
  1598. LOG_ERROR(
  1599. voice->audio,
  1600. "Destination not attached to source: %p %p",
  1601. (void*) voice,
  1602. (void*) pDestinationVoice
  1603. )
  1604. FAudio_PlatformUnlockMutex(voice->sendLock);
  1605. LOG_MUTEX_UNLOCK(voice->audio, voice->sendLock)
  1606. LOG_API_EXIT(voice->audio)
  1607. return FAUDIO_E_INVALID_CALL;
  1608. }
  1609. if (!(voice->sends.pSends[i].Flags & FAUDIO_SEND_USEFILTER))
  1610. {
  1611. FAudio_PlatformUnlockMutex(voice->sendLock);
  1612. LOG_MUTEX_UNLOCK(voice->audio, voice->sendLock)
  1613. LOG_API_EXIT(voice->audio)
  1614. return 0;
  1615. }
  1616. /* Set the filter parameters, finally. */
  1617. FAudio_memcpy(
  1618. &voice->sendFilter[i],
  1619. pParameters,
  1620. sizeof(FAudioFilterParameters)
  1621. );
  1622. FAudio_PlatformUnlockMutex(voice->sendLock);
  1623. LOG_MUTEX_UNLOCK(voice->audio, voice->sendLock)
  1624. LOG_API_EXIT(voice->audio)
  1625. return 0;
  1626. }
  1627. void FAudioVoice_GetOutputFilterParameters(
  1628. FAudioVoice *voice,
  1629. FAudioVoice *pDestinationVoice,
  1630. FAudioFilterParameters *pParameters
  1631. ) {
  1632. uint32_t i;
  1633. LOG_API_ENTER(voice->audio)
  1634. /* MSDN: "This method is usable only on source and submix voices and
  1635. * has no effect on mastering voices."
  1636. */
  1637. if (voice->type == FAUDIO_VOICE_MASTER)
  1638. {
  1639. LOG_API_EXIT(voice->audio)
  1640. return;
  1641. }
  1642. FAudio_PlatformLockMutex(voice->sendLock);
  1643. LOG_MUTEX_LOCK(voice->audio, voice->sendLock)
  1644. /* Find the send index */
  1645. if (pDestinationVoice == NULL && voice->sends.SendCount == 1)
  1646. {
  1647. pDestinationVoice = voice->sends.pSends[0].pOutputVoice;
  1648. }
  1649. for (i = 0; i < voice->sends.SendCount; i += 1)
  1650. {
  1651. if (pDestinationVoice == voice->sends.pSends[i].pOutputVoice)
  1652. {
  1653. break;
  1654. }
  1655. }
  1656. if (i >= voice->sends.SendCount)
  1657. {
  1658. LOG_ERROR(
  1659. voice->audio,
  1660. "Destination not attached to source: %p %p",
  1661. (void*) voice,
  1662. (void*) pDestinationVoice
  1663. )
  1664. FAudio_PlatformUnlockMutex(voice->sendLock);
  1665. LOG_MUTEX_UNLOCK(voice->audio, voice->sendLock)
  1666. LOG_API_EXIT(voice->audio)
  1667. return;
  1668. }
  1669. if (!(voice->sends.pSends[i].Flags & FAUDIO_SEND_USEFILTER))
  1670. {
  1671. FAudio_PlatformUnlockMutex(voice->sendLock);
  1672. LOG_MUTEX_UNLOCK(voice->audio, voice->sendLock)
  1673. LOG_API_EXIT(voice->audio)
  1674. return;
  1675. }
  1676. /* Set the filter parameters, finally. */
  1677. FAudio_memcpy(
  1678. pParameters,
  1679. &voice->sendFilter[i],
  1680. sizeof(FAudioFilterParameters)
  1681. );
  1682. FAudio_PlatformUnlockMutex(voice->sendLock);
  1683. LOG_MUTEX_UNLOCK(voice->audio, voice->sendLock)
  1684. LOG_API_EXIT(voice->audio)
  1685. }
  1686. uint32_t FAudioVoice_SetVolume(
  1687. FAudioVoice *voice,
  1688. float Volume,
  1689. uint32_t OperationSet
  1690. ) {
  1691. uint32_t i;
  1692. LOG_API_ENTER(voice->audio)
  1693. if (OperationSet != FAUDIO_COMMIT_NOW && voice->audio->active)
  1694. {
  1695. FAudio_OPERATIONSET_QueueSetVolume(
  1696. voice,
  1697. Volume,
  1698. OperationSet
  1699. );
  1700. LOG_API_EXIT(voice->audio)
  1701. return 0;
  1702. }
  1703. FAudio_PlatformLockMutex(voice->sendLock);
  1704. LOG_MUTEX_LOCK(voice->audio, voice->sendLock)
  1705. FAudio_PlatformLockMutex(voice->volumeLock);
  1706. LOG_MUTEX_LOCK(voice->audio, voice->volumeLock)
  1707. voice->volume = FAudio_clamp(
  1708. Volume,
  1709. -FAUDIO_MAX_VOLUME_LEVEL,
  1710. FAUDIO_MAX_VOLUME_LEVEL
  1711. );
  1712. for (i = 0; i < voice->sends.SendCount; i += 1)
  1713. {
  1714. FAudio_RecalcMixMatrix(voice, i);
  1715. }
  1716. FAudio_PlatformUnlockMutex(voice->volumeLock);
  1717. LOG_MUTEX_UNLOCK(voice->audio, voice->volumeLock)
  1718. FAudio_PlatformUnlockMutex(voice->sendLock);
  1719. LOG_MUTEX_UNLOCK(voice->audio, voice->sendLock)
  1720. LOG_API_EXIT(voice->audio)
  1721. return 0;
  1722. }
  1723. void FAudioVoice_GetVolume(
  1724. FAudioVoice *voice,
  1725. float *pVolume
  1726. ) {
  1727. LOG_API_ENTER(voice->audio)
  1728. *pVolume = voice->volume;
  1729. LOG_API_EXIT(voice->audio)
  1730. }
  1731. uint32_t FAudioVoice_SetChannelVolumes(
  1732. FAudioVoice *voice,
  1733. uint32_t Channels,
  1734. const float *pVolumes,
  1735. uint32_t OperationSet
  1736. ) {
  1737. uint32_t i;
  1738. LOG_API_ENTER(voice->audio)
  1739. if (OperationSet != FAUDIO_COMMIT_NOW && voice->audio->active)
  1740. {
  1741. FAudio_OPERATIONSET_QueueSetChannelVolumes(
  1742. voice,
  1743. Channels,
  1744. pVolumes,
  1745. OperationSet
  1746. );
  1747. LOG_API_EXIT(voice->audio)
  1748. return 0;
  1749. }
  1750. if (pVolumes == NULL)
  1751. {
  1752. LOG_API_EXIT(voice->audio)
  1753. return FAUDIO_E_INVALID_CALL;
  1754. }
  1755. if (voice->type == FAUDIO_VOICE_MASTER)
  1756. {
  1757. LOG_API_EXIT(voice->audio)
  1758. return FAUDIO_E_INVALID_CALL;
  1759. }
  1760. if (voice->audio->version > 7 && Channels != voice->outputChannels)
  1761. {
  1762. LOG_API_EXIT(voice->audio)
  1763. return FAUDIO_E_INVALID_CALL;
  1764. }
  1765. FAudio_PlatformLockMutex(voice->sendLock);
  1766. LOG_MUTEX_LOCK(voice->audio, voice->sendLock)
  1767. FAudio_PlatformLockMutex(voice->volumeLock);
  1768. LOG_MUTEX_LOCK(voice->audio, voice->volumeLock)
  1769. FAudio_memcpy(
  1770. voice->channelVolume,
  1771. pVolumes,
  1772. sizeof(float) * Channels
  1773. );
  1774. for (i = 0; i < voice->sends.SendCount; i += 1)
  1775. {
  1776. FAudio_RecalcMixMatrix(voice, i);
  1777. }
  1778. FAudio_PlatformUnlockMutex(voice->volumeLock);
  1779. LOG_MUTEX_UNLOCK(voice->audio, voice->volumeLock)
  1780. FAudio_PlatformUnlockMutex(voice->sendLock);
  1781. LOG_MUTEX_UNLOCK(voice->audio, voice->sendLock)
  1782. LOG_API_EXIT(voice->audio)
  1783. return 0;
  1784. }
  1785. void FAudioVoice_GetChannelVolumes(
  1786. FAudioVoice *voice,
  1787. uint32_t Channels,
  1788. float *pVolumes
  1789. ) {
  1790. LOG_API_ENTER(voice->audio)
  1791. FAudio_PlatformLockMutex(voice->volumeLock);
  1792. LOG_MUTEX_LOCK(voice->audio, voice->volumeLock)
  1793. FAudio_memcpy(
  1794. pVolumes,
  1795. voice->channelVolume,
  1796. sizeof(float) * Channels
  1797. );
  1798. FAudio_PlatformUnlockMutex(voice->volumeLock);
  1799. LOG_MUTEX_UNLOCK(voice->audio, voice->volumeLock)
  1800. LOG_API_EXIT(voice->audio)
  1801. }
  1802. uint32_t FAudioVoice_SetOutputMatrix(
  1803. FAudioVoice *voice,
  1804. FAudioVoice *pDestinationVoice,
  1805. uint32_t SourceChannels,
  1806. uint32_t DestinationChannels,
  1807. const float *pLevelMatrix,
  1808. uint32_t OperationSet
  1809. ) {
  1810. uint32_t i, result = 0;
  1811. LOG_API_ENTER(voice->audio)
  1812. if (OperationSet != FAUDIO_COMMIT_NOW && voice->audio->active)
  1813. {
  1814. FAudio_OPERATIONSET_QueueSetOutputMatrix(
  1815. voice,
  1816. pDestinationVoice,
  1817. SourceChannels,
  1818. DestinationChannels,
  1819. pLevelMatrix,
  1820. OperationSet
  1821. );
  1822. LOG_API_EXIT(voice->audio)
  1823. return 0;
  1824. }
  1825. FAudio_PlatformLockMutex(voice->sendLock);
  1826. LOG_MUTEX_LOCK(voice->audio, voice->sendLock)
  1827. /* Find the send index */
  1828. if (pDestinationVoice == NULL && voice->sends.SendCount == 1)
  1829. {
  1830. pDestinationVoice = voice->sends.pSends[0].pOutputVoice;
  1831. }
  1832. FAudio_assert(pDestinationVoice != NULL);
  1833. for (i = 0; i < voice->sends.SendCount; i += 1)
  1834. {
  1835. if (pDestinationVoice == voice->sends.pSends[i].pOutputVoice)
  1836. {
  1837. break;
  1838. }
  1839. }
  1840. if (i >= voice->sends.SendCount)
  1841. {
  1842. LOG_ERROR(
  1843. voice->audio,
  1844. "Destination not attached to source: %p %p",
  1845. (void*) voice,
  1846. (void*) pDestinationVoice
  1847. )
  1848. result = FAUDIO_E_INVALID_CALL;
  1849. goto end;
  1850. }
  1851. /* Verify the Source/Destination channel count */
  1852. if (SourceChannels != voice->outputChannels)
  1853. {
  1854. LOG_ERROR(
  1855. voice->audio,
  1856. "SourceChannels not equal to voice channel count: %p %d %d",
  1857. (void*) voice,
  1858. SourceChannels,
  1859. voice->outputChannels
  1860. )
  1861. result = FAUDIO_E_INVALID_CALL;
  1862. goto end;
  1863. }
  1864. if (pDestinationVoice->type == FAUDIO_VOICE_MASTER)
  1865. {
  1866. if (DestinationChannels != pDestinationVoice->master.inputChannels)
  1867. {
  1868. LOG_ERROR(
  1869. voice->audio,
  1870. "DestinationChannels not equal to master channel count: %p %d %d",
  1871. (void*) pDestinationVoice,
  1872. DestinationChannels,
  1873. pDestinationVoice->master.inputChannels
  1874. )
  1875. result = FAUDIO_E_INVALID_CALL;
  1876. goto end;
  1877. }
  1878. }
  1879. else
  1880. {
  1881. if (DestinationChannels != pDestinationVoice->mix.inputChannels)
  1882. {
  1883. LOG_ERROR(
  1884. voice->audio,
  1885. "DestinationChannels not equal to submix channel count: %p %d %d",
  1886. (void*) pDestinationVoice,
  1887. DestinationChannels,
  1888. pDestinationVoice->mix.inputChannels
  1889. )
  1890. result = FAUDIO_E_INVALID_CALL;
  1891. goto end;
  1892. }
  1893. }
  1894. /* Set the matrix values, finally */
  1895. FAudio_PlatformLockMutex(voice->volumeLock);
  1896. LOG_MUTEX_LOCK(voice->audio, voice->volumeLock)
  1897. FAudio_memcpy(
  1898. voice->sendCoefficients[i],
  1899. pLevelMatrix,
  1900. sizeof(float) * SourceChannels * DestinationChannels
  1901. );
  1902. FAudio_RecalcMixMatrix(voice, i);
  1903. FAudio_PlatformUnlockMutex(voice->volumeLock);
  1904. LOG_MUTEX_UNLOCK(voice->audio, voice->volumeLock)
  1905. end:
  1906. FAudio_PlatformUnlockMutex(voice->sendLock);
  1907. LOG_MUTEX_UNLOCK(voice->audio, voice->sendLock)
  1908. LOG_API_EXIT(voice->audio)
  1909. return result;
  1910. }
  1911. void FAudioVoice_GetOutputMatrix(
  1912. FAudioVoice *voice,
  1913. FAudioVoice *pDestinationVoice,
  1914. uint32_t SourceChannels,
  1915. uint32_t DestinationChannels,
  1916. float *pLevelMatrix
  1917. ) {
  1918. uint32_t i;
  1919. LOG_API_ENTER(voice->audio)
  1920. FAudio_PlatformLockMutex(voice->sendLock);
  1921. LOG_MUTEX_LOCK(voice->audio, voice->sendLock)
  1922. /* Find the send index */
  1923. for (i = 0; i < voice->sends.SendCount; i += 1)
  1924. {
  1925. if (pDestinationVoice == voice->sends.pSends[i].pOutputVoice)
  1926. {
  1927. break;
  1928. }
  1929. }
  1930. if (i >= voice->sends.SendCount)
  1931. {
  1932. LOG_ERROR(
  1933. voice->audio,
  1934. "Destination not attached to source: %p %p",
  1935. (void*) voice,
  1936. (void*) pDestinationVoice
  1937. )
  1938. FAudio_PlatformUnlockMutex(voice->sendLock);
  1939. LOG_MUTEX_UNLOCK(voice->audio, voice->sendLock)
  1940. LOG_API_EXIT(voice->audio)
  1941. return;
  1942. }
  1943. /* Verify the Source/Destination channel count */
  1944. if (voice->type == FAUDIO_VOICE_SOURCE)
  1945. {
  1946. FAudio_assert(SourceChannels == voice->src.format->nChannels);
  1947. }
  1948. else
  1949. {
  1950. FAudio_assert(SourceChannels == voice->mix.inputChannels);
  1951. }
  1952. if (pDestinationVoice->type == FAUDIO_VOICE_MASTER)
  1953. {
  1954. FAudio_assert(DestinationChannels == pDestinationVoice->master.inputChannels);
  1955. }
  1956. else
  1957. {
  1958. FAudio_assert(DestinationChannels == pDestinationVoice->mix.inputChannels);
  1959. }
  1960. /* Get the matrix values, finally */
  1961. FAudio_memcpy(
  1962. pLevelMatrix,
  1963. voice->sendCoefficients[i],
  1964. sizeof(float) * SourceChannels * DestinationChannels
  1965. );
  1966. FAudio_PlatformUnlockMutex(voice->sendLock);
  1967. LOG_MUTEX_UNLOCK(voice->audio, voice->sendLock)
  1968. LOG_API_EXIT(voice->audio)
  1969. }
  1970. void FAudioVoice_DestroyVoice(FAudioVoice *voice)
  1971. {
  1972. uint32_t i;
  1973. LOG_API_ENTER(voice->audio)
  1974. /* TODO: Check for dependencies and remove from audio graph first! */
  1975. FAudio_OPERATIONSET_ClearAllForVoice(voice);
  1976. if (voice->type == FAUDIO_VOICE_SOURCE)
  1977. {
  1978. FAudioBufferEntry *entry, *next;
  1979. #ifdef FAUDIO_DUMP_VOICES
  1980. FAudio_DUMPVOICE_Finalize((FAudioSourceVoice*) voice);
  1981. #endif /* FAUDIO_DUMP_VOICES */
  1982. FAudio_PlatformLockMutex(voice->audio->sourceLock);
  1983. LOG_MUTEX_LOCK(voice->audio, voice->audio->sourceLock)
  1984. while (voice == voice->audio->processingSource)
  1985. {
  1986. FAudio_PlatformUnlockMutex(voice->audio->sourceLock);
  1987. LOG_MUTEX_UNLOCK(voice->audio, voice->audio->sourceLock)
  1988. FAudio_PlatformLockMutex(voice->audio->sourceLock);
  1989. LOG_MUTEX_LOCK(voice->audio, voice->audio->sourceLock)
  1990. }
  1991. LinkedList_RemoveEntry(
  1992. &voice->audio->sources,
  1993. voice,
  1994. voice->audio->sourceLock,
  1995. voice->audio->pFree
  1996. );
  1997. FAudio_PlatformUnlockMutex(voice->audio->sourceLock);
  1998. LOG_MUTEX_UNLOCK(voice->audio, voice->audio->sourceLock)
  1999. entry = voice->src.bufferList;
  2000. while (entry != NULL)
  2001. {
  2002. next = entry->next;
  2003. voice->audio->pFree(entry);
  2004. entry = next;
  2005. }
  2006. entry = voice->src.flushList;
  2007. while (entry != NULL)
  2008. {
  2009. next = entry->next;
  2010. voice->audio->pFree(entry);
  2011. entry = next;
  2012. }
  2013. voice->audio->pFree(voice->src.format);
  2014. LOG_MUTEX_DESTROY(voice->audio, voice->src.bufferLock)
  2015. FAudio_PlatformDestroyMutex(voice->src.bufferLock);
  2016. #ifdef HAVE_WMADEC
  2017. if (voice->src.wmadec)
  2018. {
  2019. FAudio_WMADEC_free(voice);
  2020. }
  2021. #endif /* HAVE_WMADEC */
  2022. }
  2023. else if (voice->type == FAUDIO_VOICE_SUBMIX)
  2024. {
  2025. /* Remove submix from list */
  2026. LinkedList_RemoveEntry(
  2027. &voice->audio->submixes,
  2028. voice,
  2029. voice->audio->submixLock,
  2030. voice->audio->pFree
  2031. );
  2032. /* Delete submix data */
  2033. voice->audio->pFree(voice->mix.inputCache);
  2034. }
  2035. else if (voice->type == FAUDIO_VOICE_MASTER)
  2036. {
  2037. if (voice->audio->platform != NULL)
  2038. {
  2039. FAudio_PlatformQuit(voice->audio->platform);
  2040. voice->audio->platform = NULL;
  2041. }
  2042. if (voice->master.effectCache != NULL)
  2043. {
  2044. voice->audio->pFree(voice->master.effectCache);
  2045. }
  2046. voice->audio->master = NULL;
  2047. }
  2048. if (voice->sendLock != NULL)
  2049. {
  2050. FAudio_PlatformLockMutex(voice->sendLock);
  2051. LOG_MUTEX_LOCK(voice->audio, voice->sendLock)
  2052. for (i = 0; i < voice->sends.SendCount; i += 1)
  2053. {
  2054. voice->audio->pFree(voice->sendCoefficients[i]);
  2055. }
  2056. if (voice->sendCoefficients != NULL)
  2057. {
  2058. voice->audio->pFree(voice->sendCoefficients);
  2059. }
  2060. for (i = 0; i < voice->sends.SendCount; i += 1)
  2061. {
  2062. voice->audio->pFree(voice->mixCoefficients[i]);
  2063. }
  2064. if (voice->mixCoefficients != NULL)
  2065. {
  2066. voice->audio->pFree(voice->mixCoefficients);
  2067. }
  2068. if (voice->sendMix != NULL)
  2069. {
  2070. voice->audio->pFree(voice->sendMix);
  2071. }
  2072. if (voice->sendFilter != NULL)
  2073. {
  2074. voice->audio->pFree(voice->sendFilter);
  2075. }
  2076. if (voice->sendFilterState != NULL)
  2077. {
  2078. for (i = 0; i < voice->sends.SendCount; i += 1)
  2079. {
  2080. if (voice->sendFilterState[i] != NULL)
  2081. {
  2082. voice->audio->pFree(voice->sendFilterState[i]);
  2083. }
  2084. }
  2085. voice->audio->pFree(voice->sendFilterState);
  2086. }
  2087. if (voice->sends.pSends != NULL)
  2088. {
  2089. voice->audio->pFree(voice->sends.pSends);
  2090. }
  2091. FAudio_PlatformUnlockMutex(voice->sendLock);
  2092. LOG_MUTEX_UNLOCK(voice->audio, voice->sendLock)
  2093. LOG_MUTEX_DESTROY(voice->audio, voice->sendLock)
  2094. FAudio_PlatformDestroyMutex(voice->sendLock);
  2095. }
  2096. if (voice->effectLock != NULL)
  2097. {
  2098. FAudio_PlatformLockMutex(voice->effectLock);
  2099. LOG_MUTEX_LOCK(voice->audio, voice->effectLock)
  2100. FAudio_INTERNAL_FreeEffectChain(voice);
  2101. FAudio_PlatformUnlockMutex(voice->effectLock);
  2102. LOG_MUTEX_UNLOCK(voice->audio, voice->effectLock)
  2103. LOG_MUTEX_DESTROY(voice->audio, voice->effectLock)
  2104. FAudio_PlatformDestroyMutex(voice->effectLock);
  2105. }
  2106. if (voice->filterLock != NULL)
  2107. {
  2108. FAudio_PlatformLockMutex(voice->filterLock);
  2109. LOG_MUTEX_LOCK(voice->audio, voice->filterLock)
  2110. if (voice->filterState != NULL)
  2111. {
  2112. voice->audio->pFree(voice->filterState);
  2113. }
  2114. FAudio_PlatformUnlockMutex(voice->filterLock);
  2115. LOG_MUTEX_UNLOCK(voice->audio, voice->filterLock)
  2116. LOG_MUTEX_DESTROY(voice->audio, voice->filterLock)
  2117. FAudio_PlatformDestroyMutex(voice->filterLock);
  2118. }
  2119. if (voice->volumeLock != NULL)
  2120. {
  2121. FAudio_PlatformLockMutex(voice->volumeLock);
  2122. LOG_MUTEX_LOCK(voice->audio, voice->volumeLock)
  2123. if (voice->channelVolume != NULL)
  2124. {
  2125. voice->audio->pFree(voice->channelVolume);
  2126. }
  2127. FAudio_PlatformUnlockMutex(voice->volumeLock);
  2128. LOG_MUTEX_UNLOCK(voice->audio, voice->volumeLock)
  2129. LOG_MUTEX_DESTROY(voice->audio, voice->volumeLock)
  2130. FAudio_PlatformDestroyMutex(voice->volumeLock);
  2131. }
  2132. LOG_API_EXIT(voice->audio)
  2133. FAudio_Release(voice->audio);
  2134. voice->audio->pFree(voice);
  2135. }
  2136. /* FAudioSourceVoice Interface */
  2137. uint32_t FAudioSourceVoice_Start(
  2138. FAudioSourceVoice *voice,
  2139. uint32_t Flags,
  2140. uint32_t OperationSet
  2141. ) {
  2142. LOG_API_ENTER(voice->audio)
  2143. if (OperationSet != FAUDIO_COMMIT_NOW && voice->audio->active)
  2144. {
  2145. FAudio_OPERATIONSET_QueueStart(
  2146. voice,
  2147. Flags,
  2148. OperationSet
  2149. );
  2150. LOG_API_EXIT(voice->audio)
  2151. return 0;
  2152. }
  2153. FAudio_assert(voice->type == FAUDIO_VOICE_SOURCE);
  2154. FAudio_assert(Flags == 0);
  2155. voice->src.active = 1;
  2156. LOG_API_EXIT(voice->audio)
  2157. return 0;
  2158. }
  2159. uint32_t FAudioSourceVoice_Stop(
  2160. FAudioSourceVoice *voice,
  2161. uint32_t Flags,
  2162. uint32_t OperationSet
  2163. ) {
  2164. LOG_API_ENTER(voice->audio)
  2165. if (OperationSet != FAUDIO_COMMIT_NOW && voice->audio->active)
  2166. {
  2167. FAudio_OPERATIONSET_QueueStop(
  2168. voice,
  2169. Flags,
  2170. OperationSet
  2171. );
  2172. LOG_API_EXIT(voice->audio)
  2173. return 0;
  2174. }
  2175. FAudio_assert(voice->type == FAUDIO_VOICE_SOURCE);
  2176. if (Flags & FAUDIO_PLAY_TAILS)
  2177. {
  2178. voice->src.active = 2;
  2179. }
  2180. else
  2181. {
  2182. voice->src.active = 0;
  2183. }
  2184. LOG_API_EXIT(voice->audio)
  2185. return 0;
  2186. }
  2187. uint32_t FAudioSourceVoice_SubmitSourceBuffer(
  2188. FAudioSourceVoice *voice,
  2189. const FAudioBuffer *pBuffer,
  2190. const FAudioBufferWMA *pBufferWMA
  2191. ) {
  2192. uint32_t adpcmMask, *adpcmByteCount;
  2193. uint32_t playBegin, playLength, loopBegin, loopLength;
  2194. FAudioBufferEntry *entry, *list;
  2195. LOG_API_ENTER(voice->audio)
  2196. LOG_INFO(
  2197. voice->audio,
  2198. "%p: {Flags: 0x%x, AudioBytes: %u, pAudioData: %p, Play: %u + %u, Loop: %u + %u x %u}",
  2199. (void*) voice,
  2200. pBuffer->Flags,
  2201. pBuffer->AudioBytes,
  2202. (const void*) pBuffer->pAudioData,
  2203. pBuffer->PlayBegin,
  2204. pBuffer->PlayLength,
  2205. pBuffer->LoopBegin,
  2206. pBuffer->LoopLength,
  2207. pBuffer->LoopCount
  2208. )
  2209. FAudio_assert(voice->type == FAUDIO_VOICE_SOURCE);
  2210. #ifdef HAVE_WMADEC
  2211. FAudio_assert( (voice->src.wmadec != NULL && (pBufferWMA != NULL ||
  2212. (voice->src.format->wFormatTag == FAUDIO_FORMAT_XMAUDIO2 ||
  2213. voice->src.format->wFormatTag == FAUDIO_FORMAT_EXTENSIBLE))) ||
  2214. (voice->src.wmadec == NULL && (pBufferWMA == NULL && voice->src.format->wFormatTag != FAUDIO_FORMAT_XMAUDIO2)) );
  2215. #endif /* HAVE_WMADEC */
  2216. /* Start off with whatever they just sent us... */
  2217. playBegin = pBuffer->PlayBegin;
  2218. playLength = pBuffer->PlayLength;
  2219. loopBegin = pBuffer->LoopBegin;
  2220. loopLength = pBuffer->LoopLength;
  2221. /* "LoopBegin/LoopLength must be zero if LoopCount is 0" */
  2222. if (pBuffer->LoopCount == 0 && (loopBegin > 0 || loopLength > 0))
  2223. {
  2224. LOG_API_EXIT(voice->audio)
  2225. return FAUDIO_E_INVALID_CALL;
  2226. }
  2227. /* PlayLength Default */
  2228. if (playLength == 0)
  2229. {
  2230. if (voice->src.format->wFormatTag == FAUDIO_FORMAT_MSADPCM)
  2231. {
  2232. FAudioADPCMWaveFormat *fmtex = (FAudioADPCMWaveFormat*) voice->src.format;
  2233. playLength = (
  2234. pBuffer->AudioBytes /
  2235. fmtex->wfx.nBlockAlign *
  2236. fmtex->wSamplesPerBlock
  2237. ) - playBegin;
  2238. }
  2239. else if (voice->src.format->wFormatTag == FAUDIO_FORMAT_XMAUDIO2)
  2240. {
  2241. FAudioXMA2WaveFormat *fmtex = (FAudioXMA2WaveFormat*) voice->src.format;
  2242. playLength = fmtex->dwSamplesEncoded - playBegin;
  2243. }
  2244. else if (pBufferWMA != NULL)
  2245. {
  2246. playLength = (
  2247. pBufferWMA->pDecodedPacketCumulativeBytes[pBufferWMA->PacketCount - 1] /
  2248. (voice->src.format->nChannels * voice->src.format->wBitsPerSample / 8)
  2249. ) - playBegin;
  2250. }
  2251. else
  2252. {
  2253. playLength = (
  2254. pBuffer->AudioBytes /
  2255. voice->src.format->nBlockAlign
  2256. ) - playBegin;
  2257. }
  2258. }
  2259. if (pBuffer->LoopCount > 0 && pBufferWMA == NULL && voice->src.format->wFormatTag != FAUDIO_FORMAT_XMAUDIO2)
  2260. {
  2261. /* "The value of LoopBegin must be less than PlayBegin + PlayLength" */
  2262. if (loopBegin >= (playBegin + playLength))
  2263. {
  2264. LOG_API_EXIT(voice->audio)
  2265. return FAUDIO_E_INVALID_CALL;
  2266. }
  2267. /* LoopLength Default */
  2268. if (loopLength == 0)
  2269. {
  2270. loopLength = playBegin + playLength - loopBegin;
  2271. }
  2272. /* "The value of LoopBegin + LoopLength must be greater than PlayBegin
  2273. * and less than PlayBegin + PlayLength"
  2274. */
  2275. if ( voice->audio->version > 7 && (
  2276. (loopBegin + loopLength) <= playBegin ||
  2277. (loopBegin + loopLength) > (playBegin + playLength)) )
  2278. {
  2279. LOG_API_EXIT(voice->audio)
  2280. return FAUDIO_E_INVALID_CALL;
  2281. }
  2282. }
  2283. /* For ADPCM, round down to the nearest sample block size */
  2284. if (voice->src.format->wFormatTag == FAUDIO_FORMAT_MSADPCM)
  2285. {
  2286. adpcmMask = ((FAudioADPCMWaveFormat*) voice->src.format)->wSamplesPerBlock;
  2287. playBegin -= playBegin % adpcmMask;
  2288. playLength -= playLength % adpcmMask;
  2289. loopBegin -= loopBegin % adpcmMask;
  2290. loopLength -= loopLength % adpcmMask;
  2291. /* This is basically a const_cast... */
  2292. adpcmByteCount = (uint32_t*) &pBuffer->AudioBytes;
  2293. *adpcmByteCount = (
  2294. pBuffer->AudioBytes / voice->src.format->nBlockAlign
  2295. ) * voice->src.format->nBlockAlign;
  2296. }
  2297. else if (pBufferWMA != NULL || voice->src.format->wFormatTag == FAUDIO_FORMAT_XMAUDIO2)
  2298. {
  2299. /* WMA only supports looping the whole buffer */
  2300. loopBegin = 0;
  2301. loopLength = playBegin + playLength;
  2302. }
  2303. /* Allocate, now that we have valid input */
  2304. entry = (FAudioBufferEntry*) voice->audio->pMalloc(sizeof(FAudioBufferEntry));
  2305. FAudio_memcpy(&entry->buffer, pBuffer, sizeof(FAudioBuffer));
  2306. entry->buffer.PlayBegin = playBegin;
  2307. entry->buffer.PlayLength = playLength;
  2308. entry->buffer.LoopBegin = loopBegin;
  2309. entry->buffer.LoopLength = loopLength;
  2310. if (pBufferWMA != NULL)
  2311. {
  2312. FAudio_memcpy(&entry->bufferWMA, pBufferWMA, sizeof(FAudioBufferWMA));
  2313. }
  2314. entry->next = NULL;
  2315. if ( voice->audio->version <= 7 && (
  2316. entry->buffer.LoopCount > 0 &&
  2317. entry->buffer.LoopBegin + entry->buffer.LoopLength <= entry->buffer.PlayBegin))
  2318. {
  2319. entry->buffer.LoopCount = 0;
  2320. }
  2321. #ifdef FAUDIO_DUMP_VOICES
  2322. /* dumping current buffer, append into "data" section */
  2323. if (pBuffer->pAudioData != NULL && playLength > 0)
  2324. {
  2325. FAudio_DUMPVOICE_WriteBuffer(voice, pBuffer, pBufferWMA, playBegin, playLength);
  2326. }
  2327. #endif /* FAUDIO_DUMP_VOICES */
  2328. /* Submit! */
  2329. FAudio_PlatformLockMutex(voice->src.bufferLock);
  2330. LOG_MUTEX_LOCK(voice->audio, voice->src.bufferLock)
  2331. if (voice->src.bufferList == NULL)
  2332. {
  2333. voice->src.bufferList = entry;
  2334. voice->src.curBufferOffset = entry->buffer.PlayBegin;
  2335. voice->src.newBuffer = 1;
  2336. }
  2337. else
  2338. {
  2339. list = voice->src.bufferList;
  2340. while (list->next != NULL)
  2341. {
  2342. list = list->next;
  2343. }
  2344. list->next = entry;
  2345. /* For some bizarre reason we get scenarios where a buffer is freed, only to
  2346. * have the allocator give us the exact same address and somehow get a single
  2347. * buffer referencing itself. I don't even know.
  2348. */
  2349. FAudio_assert(list != entry);
  2350. }
  2351. LOG_INFO(
  2352. voice->audio,
  2353. "%p: appended buffer %p",
  2354. (void*) voice,
  2355. (void*) &entry->buffer
  2356. )
  2357. FAudio_PlatformUnlockMutex(voice->src.bufferLock);
  2358. LOG_MUTEX_UNLOCK(voice->audio, voice->src.bufferLock)
  2359. LOG_API_EXIT(voice->audio)
  2360. return 0;
  2361. }
  2362. uint32_t FAudioSourceVoice_FlushSourceBuffers(
  2363. FAudioSourceVoice *voice
  2364. ) {
  2365. FAudioBufferEntry *entry, *latest;
  2366. LOG_API_ENTER(voice->audio)
  2367. FAudio_assert(voice->type == FAUDIO_VOICE_SOURCE);
  2368. FAudio_PlatformLockMutex(voice->src.bufferLock);
  2369. LOG_MUTEX_LOCK(voice->audio, voice->src.bufferLock)
  2370. /* If the source is playing, don't flush the active buffer */
  2371. entry = voice->src.bufferList;
  2372. if ((voice->src.active == 1) && entry != NULL && !voice->src.newBuffer)
  2373. {
  2374. entry = entry->next;
  2375. voice->src.bufferList->next = NULL;
  2376. }
  2377. else
  2378. {
  2379. voice->src.curBufferOffset = 0;
  2380. voice->src.bufferList = NULL;
  2381. voice->src.newBuffer = 0;
  2382. }
  2383. /* Move them to the pending flush list */
  2384. if (entry != NULL)
  2385. {
  2386. if (voice->src.flushList == NULL)
  2387. {
  2388. voice->src.flushList = entry;
  2389. }
  2390. else
  2391. {
  2392. latest = voice->src.flushList;
  2393. while (latest->next != NULL)
  2394. {
  2395. latest = latest->next;
  2396. }
  2397. latest->next = entry;
  2398. }
  2399. }
  2400. FAudio_PlatformUnlockMutex(voice->src.bufferLock);
  2401. LOG_MUTEX_UNLOCK(voice->audio, voice->src.bufferLock)
  2402. LOG_API_EXIT(voice->audio)
  2403. return 0;
  2404. }
  2405. uint32_t FAudioSourceVoice_Discontinuity(
  2406. FAudioSourceVoice *voice
  2407. ) {
  2408. FAudioBufferEntry *buf;
  2409. LOG_API_ENTER(voice->audio)
  2410. FAudio_assert(voice->type == FAUDIO_VOICE_SOURCE);
  2411. FAudio_PlatformLockMutex(voice->src.bufferLock);
  2412. LOG_MUTEX_LOCK(voice->audio, voice->src.bufferLock)
  2413. if (voice->src.bufferList != NULL)
  2414. {
  2415. for (buf = voice->src.bufferList; buf->next != NULL; buf = buf->next);
  2416. buf->buffer.Flags |= FAUDIO_END_OF_STREAM;
  2417. }
  2418. FAudio_PlatformUnlockMutex(voice->src.bufferLock);
  2419. LOG_MUTEX_UNLOCK(voice->audio, voice->src.bufferLock)
  2420. LOG_API_EXIT(voice->audio)
  2421. return 0;
  2422. }
  2423. uint32_t FAudioSourceVoice_ExitLoop(
  2424. FAudioSourceVoice *voice,
  2425. uint32_t OperationSet
  2426. ) {
  2427. LOG_API_ENTER(voice->audio)
  2428. if (OperationSet != FAUDIO_COMMIT_NOW && voice->audio->active)
  2429. {
  2430. FAudio_OPERATIONSET_QueueExitLoop(
  2431. voice,
  2432. OperationSet
  2433. );
  2434. LOG_API_EXIT(voice->audio)
  2435. return 0;
  2436. }
  2437. FAudio_assert(voice->type == FAUDIO_VOICE_SOURCE);
  2438. FAudio_PlatformLockMutex(voice->src.bufferLock);
  2439. LOG_MUTEX_LOCK(voice->audio, voice->src.bufferLock)
  2440. if (voice->src.bufferList != NULL)
  2441. {
  2442. voice->src.bufferList->buffer.LoopCount = 0;
  2443. }
  2444. FAudio_PlatformUnlockMutex(voice->src.bufferLock);
  2445. LOG_MUTEX_UNLOCK(voice->audio, voice->src.bufferLock)
  2446. LOG_API_EXIT(voice->audio)
  2447. return 0;
  2448. }
  2449. void FAudioSourceVoice_GetState(
  2450. FAudioSourceVoice *voice,
  2451. FAudioVoiceState *pVoiceState,
  2452. uint32_t Flags
  2453. ) {
  2454. FAudioBufferEntry *entry;
  2455. LOG_API_ENTER(voice->audio)
  2456. FAudio_assert(voice->type == FAUDIO_VOICE_SOURCE);
  2457. FAudio_PlatformLockMutex(voice->src.bufferLock);
  2458. LOG_MUTEX_LOCK(voice->audio, voice->src.bufferLock)
  2459. if (!(Flags & FAUDIO_VOICE_NOSAMPLESPLAYED))
  2460. {
  2461. pVoiceState->SamplesPlayed = voice->src.totalSamples;
  2462. }
  2463. pVoiceState->BuffersQueued = 0;
  2464. pVoiceState->pCurrentBufferContext = NULL;
  2465. if (voice->src.bufferList != NULL)
  2466. {
  2467. entry = voice->src.bufferList;
  2468. if (!voice->src.newBuffer)
  2469. {
  2470. pVoiceState->pCurrentBufferContext = entry->buffer.pContext;
  2471. }
  2472. do
  2473. {
  2474. pVoiceState->BuffersQueued += 1;
  2475. entry = entry->next;
  2476. } while (entry != NULL);
  2477. }
  2478. /* Pending flushed buffers also count */
  2479. entry = voice->src.flushList;
  2480. while (entry != NULL)
  2481. {
  2482. pVoiceState->BuffersQueued += 1;
  2483. entry = entry->next;
  2484. }
  2485. LOG_INFO(
  2486. voice->audio,
  2487. "-> {pCurrentBufferContext: %p, BuffersQueued: %u, SamplesPlayed: %"FAudio_PRIu64"}",
  2488. pVoiceState->pCurrentBufferContext, pVoiceState->BuffersQueued,
  2489. pVoiceState->SamplesPlayed
  2490. )
  2491. FAudio_PlatformUnlockMutex(voice->src.bufferLock);
  2492. LOG_MUTEX_UNLOCK(voice->audio, voice->src.bufferLock)
  2493. LOG_API_EXIT(voice->audio)
  2494. }
  2495. uint32_t FAudioSourceVoice_SetFrequencyRatio(
  2496. FAudioSourceVoice *voice,
  2497. float Ratio,
  2498. uint32_t OperationSet
  2499. ) {
  2500. LOG_API_ENTER(voice->audio)
  2501. if (OperationSet != FAUDIO_COMMIT_NOW && voice->audio->active)
  2502. {
  2503. FAudio_OPERATIONSET_QueueSetFrequencyRatio(
  2504. voice,
  2505. Ratio,
  2506. OperationSet
  2507. );
  2508. LOG_API_EXIT(voice->audio)
  2509. return 0;
  2510. }
  2511. FAudio_assert(voice->type == FAUDIO_VOICE_SOURCE);
  2512. if (voice->flags & FAUDIO_VOICE_NOPITCH)
  2513. {
  2514. LOG_API_EXIT(voice->audio)
  2515. return 0;
  2516. }
  2517. voice->src.freqRatio = FAudio_clamp(
  2518. Ratio,
  2519. FAUDIO_MIN_FREQ_RATIO,
  2520. voice->src.maxFreqRatio
  2521. );
  2522. LOG_API_EXIT(voice->audio)
  2523. return 0;
  2524. }
  2525. void FAudioSourceVoice_GetFrequencyRatio(
  2526. FAudioSourceVoice *voice,
  2527. float *pRatio
  2528. ) {
  2529. LOG_API_ENTER(voice->audio)
  2530. FAudio_assert(voice->type == FAUDIO_VOICE_SOURCE);
  2531. *pRatio = voice->src.freqRatio;
  2532. LOG_API_EXIT(voice->audio)
  2533. }
  2534. uint32_t FAudioSourceVoice_SetSourceSampleRate(
  2535. FAudioSourceVoice *voice,
  2536. uint32_t NewSourceSampleRate
  2537. ) {
  2538. uint32_t outSampleRate;
  2539. uint32_t newDecodeSamples, newResampleSamples;
  2540. LOG_API_ENTER(voice->audio)
  2541. FAudio_assert(voice->type == FAUDIO_VOICE_SOURCE);
  2542. FAudio_assert( NewSourceSampleRate >= FAUDIO_MIN_SAMPLE_RATE &&
  2543. NewSourceSampleRate <= FAUDIO_MAX_SAMPLE_RATE );
  2544. FAudio_PlatformLockMutex(voice->src.bufferLock);
  2545. LOG_MUTEX_LOCK(voice->audio, voice->src.bufferLock)
  2546. if ( voice->audio->version > 7 &&
  2547. voice->src.bufferList != NULL )
  2548. {
  2549. FAudio_PlatformUnlockMutex(voice->src.bufferLock);
  2550. LOG_MUTEX_UNLOCK(voice->audio, voice->src.bufferLock)
  2551. LOG_API_EXIT(voice->audio)
  2552. return FAUDIO_E_INVALID_CALL;
  2553. }
  2554. FAudio_PlatformUnlockMutex(voice->src.bufferLock);
  2555. LOG_MUTEX_UNLOCK(voice->audio, voice->src.bufferLock)
  2556. voice->src.format->nSamplesPerSec = NewSourceSampleRate;
  2557. /* Resize decode cache */
  2558. newDecodeSamples = (uint32_t) FAudio_ceil(
  2559. voice->audio->updateSize *
  2560. (double) voice->src.maxFreqRatio *
  2561. (double) NewSourceSampleRate /
  2562. (double) voice->audio->master->master.inputSampleRate
  2563. ) + EXTRA_DECODE_PADDING * voice->src.format->nChannels;
  2564. FAudio_INTERNAL_ResizeDecodeCache(
  2565. voice->audio,
  2566. (newDecodeSamples + EXTRA_DECODE_PADDING) * voice->src.format->nChannels
  2567. );
  2568. voice->src.decodeSamples = newDecodeSamples;
  2569. FAudio_PlatformLockMutex(voice->sendLock);
  2570. LOG_MUTEX_LOCK(voice->audio, voice->sendLock)
  2571. if (voice->sends.SendCount == 0)
  2572. {
  2573. FAudio_PlatformUnlockMutex(voice->sendLock);
  2574. LOG_MUTEX_UNLOCK(voice->audio, voice->sendLock)
  2575. LOG_API_EXIT(voice->audio)
  2576. return 0;
  2577. }
  2578. outSampleRate = voice->sends.pSends[0].pOutputVoice->type == FAUDIO_VOICE_MASTER ?
  2579. voice->sends.pSends[0].pOutputVoice->master.inputSampleRate :
  2580. voice->sends.pSends[0].pOutputVoice->mix.inputSampleRate;
  2581. newResampleSamples = (uint32_t) (FAudio_ceil(
  2582. (double) voice->audio->updateSize *
  2583. (double) outSampleRate /
  2584. (double) voice->audio->master->master.inputSampleRate
  2585. ));
  2586. voice->src.resampleSamples = newResampleSamples;
  2587. FAudio_PlatformUnlockMutex(voice->sendLock);
  2588. LOG_MUTEX_UNLOCK(voice->audio, voice->sendLock)
  2589. LOG_API_EXIT(voice->audio)
  2590. return 0;
  2591. }
  2592. /* FAudioMasteringVoice Interface */
  2593. FAUDIOAPI uint32_t FAudioMasteringVoice_GetChannelMask(
  2594. FAudioMasteringVoice *voice,
  2595. uint32_t *pChannelMask
  2596. ) {
  2597. LOG_API_ENTER(voice->audio)
  2598. FAudio_assert(voice->type == FAUDIO_VOICE_MASTER);
  2599. FAudio_assert(pChannelMask != NULL);
  2600. *pChannelMask = voice->audio->mixFormat.dwChannelMask;
  2601. LOG_API_EXIT(voice->audio)
  2602. return 0;
  2603. }
  2604. #ifdef FAUDIO_DUMP_VOICES
  2605. static inline FAudioIOStreamOut *DumpVoices_fopen(
  2606. const FAudioSourceVoice *voice,
  2607. const FAudioWaveFormatEx *format,
  2608. const char *mode,
  2609. const char *ext
  2610. ) {
  2611. char loc[64];
  2612. uint16_t format_tag = format->wFormatTag;
  2613. uint16_t format_ex_tag = 0;
  2614. if (format->wFormatTag == FAUDIO_FORMAT_EXTENSIBLE)
  2615. {
  2616. /* get the GUID of the extended subformat */
  2617. const FAudioWaveFormatExtensible *format_ex =
  2618. (const FAudioWaveFormatExtensible*) format;
  2619. format_ex_tag = (uint16_t) (format_ex->SubFormat.Data1);
  2620. }
  2621. FAudio_snprintf(
  2622. loc,
  2623. sizeof(loc),
  2624. "FA_fmt_0x%04X_0x%04X_0x%016lX%s.wav",
  2625. format_tag,
  2626. format_ex_tag,
  2627. (uint64_t) voice,
  2628. ext
  2629. );
  2630. FAudioIOStreamOut *fileOut = FAudio_fopen_out(loc, mode);
  2631. return fileOut;
  2632. }
  2633. static inline void DumpVoices_finalize_section(
  2634. const FAudioSourceVoice *voice,
  2635. const FAudioWaveFormatEx *format,
  2636. const char *section /* one of "data" or "dpds" */
  2637. ) {
  2638. /* data file only contains the real data bytes */
  2639. FAudioIOStreamOut *io_data = DumpVoices_fopen(voice, format, "rb", section);
  2640. if (!io_data)
  2641. {
  2642. return;
  2643. }
  2644. FAudio_PlatformLockMutex((FAudioMutex) io_data->lock);
  2645. size_t file_size_data = io_data->size(io_data->data);
  2646. if (file_size_data == 0)
  2647. {
  2648. /* nothing to do */
  2649. /* close data file */
  2650. FAudio_PlatformUnlockMutex((FAudioMutex) io_data->lock);
  2651. FAudio_close_out(io_data);
  2652. return;
  2653. }
  2654. /* we got some data: append data section to main file */
  2655. FAudioIOStreamOut *io = DumpVoices_fopen(voice, format, "ab", "");
  2656. if (!io)
  2657. {
  2658. /* close data file */
  2659. FAudio_PlatformUnlockMutex((FAudioMutex) io_data->lock);
  2660. FAudio_close_out(io_data);
  2661. return;
  2662. }
  2663. /* data sub-chunk - 8 bytes + data */
  2664. /* SubChunk2ID - 4 --> "data" or "dpds" */
  2665. io->write(io->data, section, 4, 1);
  2666. /* Subchunk2Size - 4 */
  2667. uint32_t chunk_size = (uint32_t)file_size_data;
  2668. io->write(io->data, &chunk_size, 4, 1);
  2669. /* data */
  2670. /* fill in data bytes */
  2671. uint8_t buffer[1024*1024];
  2672. size_t count;
  2673. while((count = io_data->read(io_data->data, (void*) buffer, 1, 1024*1024)) > 0)
  2674. {
  2675. io->write(io->data, (void*) buffer, 1, count);
  2676. }
  2677. /* close data file */
  2678. FAudio_PlatformUnlockMutex((FAudioMutex) io_data->lock);
  2679. FAudio_close_out(io_data);
  2680. /* close main file */
  2681. FAudio_PlatformUnlockMutex((FAudioMutex) io->lock);
  2682. FAudio_close_out(io);
  2683. }
  2684. static void FAudio_DUMPVOICE_Init(const FAudioSourceVoice *voice)
  2685. {
  2686. const FAudioWaveFormatEx *format = voice->src.format;
  2687. FAudioIOStreamOut *io = DumpVoices_fopen(voice, format, "wb", "");
  2688. if (!io)
  2689. {
  2690. return;
  2691. }
  2692. FAudio_PlatformLockMutex((FAudioMutex) io->lock);
  2693. /* another GREAT ressource
  2694. * https://wiki.multimedia.cx/index.php/Microsoft_xWMA
  2695. */
  2696. /* wave file format taken from
  2697. * http://soundfile.sapp.org/doc/WaveFormat
  2698. * https://sites.google.com/site/musicgapi/technical-documents/wav-file-format
  2699. * |52 49|46 46|52 4A|02 00|
  2700. * |c1 sz|af|nc|sp rt|bt rt|
  2701. * |ba|bs|da ta|c2 sz|
  2702. * | R I F F |chunk size |W A V E |f m t |
  2703. * 19026
  2704. * | 52 49 46 46 52 4A 02 00 57 41 56 45 66 6D 74 20 | RIFFRJ..WAVEfmt
  2705. * | subchnk size|fmt |nChan |samplerate |byte rate |
  2706. * | 50 | 2 |2 |11025 |11289 |
  2707. * | 32 00 00 00 02 00 02 00 11 2B 00 00 19 2C 00 00 | 2........+...,..
  2708. * |blkaln|bps |efmt |XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX|
  2709. * | 512 |4 |32 |500 |7 |256 |0 |512 |
  2710. * | 512 |4 |32 |459252 |256 |
  2711. * | 00 02|04 00 20 00 F4 01 07 00 00 01 00 00 00 02 | .... .ô.........
  2712. * | XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX |
  2713. * |
  2714. * | 00 FF 00 00 00 00 C0 00 40 00 F0 00 00 00 CC 01 | .ÿ....À.@.ð...Ì.
  2715. * | XXXXXXXXXXXXXXXXXX|d a t a |chunk size |XXXXX |
  2716. * | | |18944 | |
  2717. * | 30 FF 88 01 18 FF 64 61 74 61 00 4A 02 00 00 00 | 0ÿ...ÿdata.J....
  2718. */
  2719. uint16_t cbSize = format->cbSize;
  2720. const char *formatFourcc = "WAVE";
  2721. uint16_t wFormatTag = format->wFormatTag;
  2722. /* special handling for WMAUDIO2 */
  2723. if (wFormatTag == FAUDIO_FORMAT_EXTENSIBLE && cbSize >= 22)
  2724. {
  2725. const FAudioWaveFormatExtensible *format_ex =
  2726. (const FAudioWaveFormatExtensible*) format;
  2727. uint16_t format_ex_tag = (uint16_t) (format_ex->SubFormat.Data1);
  2728. if (format_ex_tag == FAUDIO_FORMAT_WMAUDIO2)
  2729. {
  2730. cbSize = 0;
  2731. formatFourcc = "XWMA";
  2732. wFormatTag = FAUDIO_FORMAT_WMAUDIO2;
  2733. }
  2734. }
  2735. { /* RIFF chunk descriptor - 12 byte */
  2736. /* ChunkID - 4 */
  2737. io->write(io->data, "RIFF", 4, 1);
  2738. /* ChunkSize - 4 */
  2739. uint32_t filesize = 0; /* the real file size is written in finalize step */
  2740. io->write(io->data, &filesize, 4, 1);
  2741. /* Format - 4 */
  2742. io->write(io->data, formatFourcc, 4, 1);
  2743. }
  2744. { /* fmt sub-chunk 24 */
  2745. /* Subchunk1ID - 4 */
  2746. io->write(io->data, "fmt ", 4, 1);
  2747. /* Subchunk1Size - 4 */
  2748. /* 18 byte for WAVEFORMATEX and cbSize for WAVEFORMATEXTENDED */
  2749. uint32_t chunk_data_size = 18 + (uint32_t) cbSize;
  2750. io->write(io->data, &chunk_data_size, 4, 1);
  2751. /* AudioFormat - 2 */
  2752. io->write(io->data, &wFormatTag, 2, 1);
  2753. /* NumChannels - 2 */
  2754. io->write(io->data, &format->nChannels, 2, 1);
  2755. /* SampleRate - 4 */
  2756. io->write(io->data, &format->nSamplesPerSec, 4, 1);
  2757. /* ByteRate - 4 */
  2758. /* SampleRate * NumChannels * BitsPerSample/8 */
  2759. io->write(io->data, &format->nAvgBytesPerSec, 4, 1);
  2760. /* BlockAlign - 2 */
  2761. /* NumChannels * BitsPerSample/8 */
  2762. io->write(io->data, &format->nBlockAlign, 2, 1);
  2763. /* BitsPerSample - 2 */
  2764. io->write(io->data, &format->wBitsPerSample, 2, 1);
  2765. }
  2766. /* in case of extensible audio format write the additional data to the file */
  2767. {
  2768. /* always write the cbSize */
  2769. io->write(io->data, &cbSize, 2, 1);
  2770. if (cbSize >= 22)
  2771. {
  2772. /* we have a WAVEFORMATEXTENSIBLE struct to write */
  2773. const FAudioWaveFormatExtensible *format_ex =
  2774. (const FAudioWaveFormatExtensible*) format;
  2775. io->write(io->data, &format_ex->Samples.wValidBitsPerSample, 2, 1);
  2776. io->write(io->data, &format_ex->dwChannelMask, 4, 1);
  2777. /* write FAudioGUID */
  2778. io->write(io->data, &format_ex->SubFormat.Data1, 4, 1);
  2779. io->write(io->data, &format_ex->SubFormat.Data2, 2, 1);
  2780. io->write(io->data, &format_ex->SubFormat.Data3, 2, 1);
  2781. io->write(io->data, &format_ex->SubFormat.Data4, 1, 8);
  2782. }
  2783. if (format->cbSize > 22)
  2784. {
  2785. /* fill up the remaining cbSize bytes with zeros */
  2786. uint8_t zero = 0;
  2787. for (uint16_t i=23; i<=format->cbSize; i++)
  2788. {
  2789. io->write(io->data, &zero, 1, 1);
  2790. }
  2791. }
  2792. }
  2793. { /* dpds sub-chunk - optional - 8 bytes + bufferWMA uint32_t samples */
  2794. /* create file to hold the bufferWMA samples */
  2795. FAudioIOStreamOut *io_dpds = DumpVoices_fopen(voice, format, "wb", "dpds");
  2796. FAudio_close_out(io_dpds);
  2797. /* io_dpds file will be filled by SubmitBuffer */
  2798. }
  2799. { /* data sub-chunk - 8 bytes + data */
  2800. /* create file to hold the data samples */
  2801. FAudioIOStreamOut *io_data = DumpVoices_fopen(voice, format, "wb", "data");
  2802. FAudio_close_out(io_data);
  2803. /* io_data file will be filled by SubmitBuffer */
  2804. }
  2805. FAudio_PlatformUnlockMutex((FAudioMutex) io->lock);
  2806. FAudio_close_out(io);
  2807. }
  2808. static void FAudio_DUMPVOICE_Finalize(const FAudioSourceVoice *voice)
  2809. {
  2810. const FAudioWaveFormatEx *format = voice->src.format;
  2811. /* add dpds subchunk - optional */
  2812. DumpVoices_finalize_section(voice, format, "dpds");
  2813. /* add data subchunk */
  2814. DumpVoices_finalize_section(voice, format, "data");
  2815. /* open main file to update filesize */
  2816. FAudioIOStreamOut *io = DumpVoices_fopen(voice, format, "r+b", "");
  2817. if (!io)
  2818. {
  2819. return;
  2820. }
  2821. FAudio_PlatformLockMutex((FAudioMutex) io->lock);
  2822. size_t file_size = io->size(io->data);
  2823. if (file_size >= 44)
  2824. {
  2825. /* update filesize */
  2826. uint32_t chunk_size = (uint32_t)(file_size - 8);
  2827. io->seek(io->data, 4, FAUDIO_SEEK_SET);
  2828. io->write(io->data, &chunk_size, 4, 1);
  2829. }
  2830. FAudio_PlatformUnlockMutex((FAudioMutex) io->lock);
  2831. FAudio_close_out(io);
  2832. }
  2833. static void FAudio_DUMPVOICE_WriteBuffer(
  2834. const FAudioSourceVoice *voice,
  2835. const FAudioBuffer *pBuffer,
  2836. const FAudioBufferWMA *pBufferWMA,
  2837. const uint32_t playBegin,
  2838. const uint32_t playLength
  2839. ) {
  2840. FAudioIOStreamOut *io_data = DumpVoices_fopen(voice, voice->src.format, "ab", "data");
  2841. if (io_data == NULL)
  2842. {
  2843. return;
  2844. }
  2845. FAudio_PlatformLockMutex((FAudioMutex) io_data->lock);
  2846. if (pBufferWMA != NULL)
  2847. {
  2848. /* dump encoded buffer contents */
  2849. if (pBufferWMA->PacketCount > 0)
  2850. {
  2851. FAudioIOStreamOut *io_dpds = DumpVoices_fopen(voice, voice->src.format, "ab", "dpds");
  2852. if (io_dpds)
  2853. {
  2854. FAudio_PlatformLockMutex((FAudioMutex) io_dpds->lock);
  2855. /* write to dpds file */
  2856. io_dpds->write(io_dpds->data, pBufferWMA->pDecodedPacketCumulativeBytes, sizeof(uint32_t), pBufferWMA->PacketCount);
  2857. FAudio_PlatformUnlockMutex((FAudioMutex) io_dpds->lock);
  2858. FAudio_close_out(io_dpds);
  2859. }
  2860. /* write buffer contents to data file */
  2861. io_data->write(io_data->data, pBuffer->pAudioData, sizeof(uint8_t), pBuffer->AudioBytes);
  2862. }
  2863. }
  2864. else
  2865. {
  2866. /* dump unencoded buffer contents */
  2867. uint16_t bytesPerFrame = (voice->src.format->nChannels * voice->src.format->wBitsPerSample / 8);
  2868. FAudio_assert(bytesPerFrame > 0);
  2869. const void *pAudioDataBegin = pBuffer->pAudioData + playBegin*bytesPerFrame;
  2870. io_data->write(io_data->data, pAudioDataBegin, bytesPerFrame, playLength);
  2871. }
  2872. FAudio_PlatformUnlockMutex((FAudioMutex) io_data->lock);
  2873. FAudio_close_out(io_data);
  2874. }
  2875. #endif /* FAUDIO_DUMP_VOICES */
  2876. /* vim: set noexpandtab shiftwidth=8 tabstop=8: */