alFontsound.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972
  1. #include "config.h"
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include "alMain.h"
  5. #include "alMidi.h"
  6. #include "alError.h"
  7. #include "alThunk.h"
  8. #include "midi/base.h"
  9. extern inline struct ALfontsound *LookupFontsound(ALCdevice *device, ALuint id);
  10. extern inline struct ALfontsound *RemoveFontsound(ALCdevice *device, ALuint id);
  11. static void ALfontsound_Construct(ALfontsound *self);
  12. void ALfontsound_Destruct(ALfontsound *self);
  13. void ALfontsound_setPropi(ALfontsound *self, ALCcontext *context, ALenum param, ALint value);
  14. static ALsfmodulator *ALfontsound_getModStage(ALfontsound *self, ALsizei stage);
  15. void ALfontsound_setModStagei(ALfontsound *self, ALCcontext *context, ALsizei stage, ALenum param, ALint value);
  16. static void ALfontsound_getModStagei(ALfontsound *self, ALCcontext *context, ALsizei stage, ALenum param, ALint *values);
  17. AL_API void AL_APIENTRY alGenFontsoundsSOFT(ALsizei n, ALuint *ids)
  18. {
  19. ALCcontext *context;
  20. ALsizei cur = 0;
  21. context = GetContextRef();
  22. if(!context) return;
  23. if(!(n >= 0))
  24. SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
  25. for(cur = 0;cur < n;cur++)
  26. {
  27. ALfontsound *sound = NewFontsound(context);
  28. if(!sound)
  29. {
  30. alDeleteFontsoundsSOFT(cur, ids);
  31. break;
  32. }
  33. ids[cur] = sound->id;
  34. }
  35. done:
  36. ALCcontext_DecRef(context);
  37. }
  38. AL_API ALvoid AL_APIENTRY alDeleteFontsoundsSOFT(ALsizei n, const ALuint *ids)
  39. {
  40. ALCdevice *device;
  41. ALCcontext *context;
  42. ALfontsound *inst;
  43. ALsizei i;
  44. context = GetContextRef();
  45. if(!context) return;
  46. if(!(n >= 0))
  47. SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
  48. device = context->Device;
  49. for(i = 0;i < n;i++)
  50. {
  51. /* Check for valid ID */
  52. if((inst=LookupFontsound(device, ids[i])) == NULL)
  53. SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
  54. if(inst->ref != 0)
  55. SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
  56. }
  57. for(i = 0;i < n;i++)
  58. {
  59. if((inst=RemoveFontsound(device, ids[i])) == NULL)
  60. continue;
  61. ALfontsound_Destruct(inst);
  62. memset(inst, 0, sizeof(*inst));
  63. free(inst);
  64. }
  65. done:
  66. ALCcontext_DecRef(context);
  67. }
  68. AL_API ALboolean AL_APIENTRY alIsFontsoundSOFT(ALuint id)
  69. {
  70. ALCcontext *context;
  71. ALboolean ret;
  72. context = GetContextRef();
  73. if(!context) return AL_FALSE;
  74. ret = LookupFontsound(context->Device, id) ? AL_TRUE : AL_FALSE;
  75. ALCcontext_DecRef(context);
  76. return ret;
  77. }
  78. AL_API void AL_APIENTRY alFontsoundiSOFT(ALuint id, ALenum param, ALint value)
  79. {
  80. ALCdevice *device;
  81. ALCcontext *context;
  82. ALfontsound *sound;
  83. context = GetContextRef();
  84. if(!context) return;
  85. device = context->Device;
  86. if(!(sound=LookupFontsound(device, id)))
  87. SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
  88. if(sound->ref != 0)
  89. SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
  90. ALfontsound_setPropi(sound, context, param, value);
  91. done:
  92. ALCcontext_DecRef(context);
  93. }
  94. AL_API void AL_APIENTRY alFontsound2iSOFT(ALuint id, ALenum param, ALint value1, ALint value2)
  95. {
  96. ALCdevice *device;
  97. ALCcontext *context;
  98. ALfontsound *sound;
  99. context = GetContextRef();
  100. if(!context) return;
  101. device = context->Device;
  102. if(!(sound=LookupFontsound(device, id)))
  103. SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
  104. if(sound->ref != 0)
  105. SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
  106. switch(param)
  107. {
  108. case AL_KEY_RANGE_SOFT:
  109. if(!(value1 >= 0 && value1 <= 127 && value2 >= 0 && value2 <= 127 && value2 >= value1))
  110. SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
  111. sound->MinKey = value1;
  112. sound->MaxKey = value2;
  113. break;
  114. case AL_VELOCITY_RANGE_SOFT:
  115. if(!(value1 >= 0 && value1 <= 127 && value2 >= 0 && value2 <= 127 && value2 >= value1))
  116. SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
  117. sound->MinVelocity = value1;
  118. sound->MaxVelocity = value2;
  119. break;
  120. default:
  121. SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
  122. }
  123. done:
  124. ALCcontext_DecRef(context);
  125. }
  126. AL_API void AL_APIENTRY alFontsoundivSOFT(ALuint id, ALenum param, const ALint *values)
  127. {
  128. ALCdevice *device;
  129. ALCcontext *context;
  130. ALfontsound *sound;
  131. switch(param)
  132. {
  133. case AL_KEY_RANGE_SOFT:
  134. case AL_VELOCITY_RANGE_SOFT:
  135. alFontsound2iSOFT(id, param, values[0], values[1]);
  136. return;
  137. case AL_MOD_LFO_TO_PITCH_SOFT:
  138. case AL_VIBRATO_LFO_TO_PITCH_SOFT:
  139. case AL_MOD_ENV_TO_PITCH_SOFT:
  140. case AL_FILTER_CUTOFF_SOFT:
  141. case AL_FILTER_RESONANCE_SOFT:
  142. case AL_MOD_LFO_TO_FILTER_CUTOFF_SOFT:
  143. case AL_MOD_ENV_TO_FILTER_CUTOFF_SOFT:
  144. case AL_MOD_LFO_TO_VOLUME_SOFT:
  145. case AL_CHORUS_SEND_SOFT:
  146. case AL_REVERB_SEND_SOFT:
  147. case AL_PAN_SOFT:
  148. case AL_MOD_LFO_DELAY_SOFT:
  149. case AL_MOD_LFO_FREQUENCY_SOFT:
  150. case AL_VIBRATO_LFO_DELAY_SOFT:
  151. case AL_VIBRATO_LFO_FREQUENCY_SOFT:
  152. case AL_MOD_ENV_DELAYTIME_SOFT:
  153. case AL_MOD_ENV_ATTACKTIME_SOFT:
  154. case AL_MOD_ENV_HOLDTIME_SOFT:
  155. case AL_MOD_ENV_DECAYTIME_SOFT:
  156. case AL_MOD_ENV_SUSTAINVOLUME_SOFT:
  157. case AL_MOD_ENV_RELEASETIME_SOFT:
  158. case AL_MOD_ENV_KEY_TO_HOLDTIME_SOFT:
  159. case AL_MOD_ENV_KEY_TO_DECAYTIME_SOFT:
  160. case AL_VOLUME_ENV_DELAYTIME_SOFT:
  161. case AL_VOLUME_ENV_ATTACKTIME_SOFT:
  162. case AL_VOLUME_ENV_HOLDTIME_SOFT:
  163. case AL_VOLUME_ENV_DECAYTIME_SOFT:
  164. case AL_VOLUME_ENV_SUSTAINVOLUME_SOFT:
  165. case AL_VOLUME_ENV_RELEASETIME_SOFT:
  166. case AL_VOLUME_ENV_KEY_TO_HOLDTIME_SOFT:
  167. case AL_VOLUME_ENV_KEY_TO_DECAYTIME_SOFT:
  168. case AL_ATTENUATION_SOFT:
  169. case AL_TUNING_COARSE_SOFT:
  170. case AL_TUNING_FINE_SOFT:
  171. case AL_LOOP_MODE_SOFT:
  172. case AL_TUNING_SCALE_SOFT:
  173. case AL_EXCLUSIVE_CLASS_SOFT:
  174. case AL_SAMPLE_START_SOFT:
  175. case AL_SAMPLE_END_SOFT:
  176. case AL_SAMPLE_LOOP_START_SOFT:
  177. case AL_SAMPLE_LOOP_END_SOFT:
  178. case AL_SAMPLE_RATE_SOFT:
  179. case AL_BASE_KEY_SOFT:
  180. case AL_KEY_CORRECTION_SOFT:
  181. case AL_SAMPLE_TYPE_SOFT:
  182. case AL_FONTSOUND_LINK_SOFT:
  183. alFontsoundiSOFT(id, param, values[0]);
  184. return;
  185. }
  186. context = GetContextRef();
  187. if(!context) return;
  188. device = context->Device;
  189. if(!(sound=LookupFontsound(device, id)))
  190. SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
  191. if(sound->ref != 0)
  192. SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
  193. switch(param)
  194. {
  195. default:
  196. SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
  197. }
  198. done:
  199. ALCcontext_DecRef(context);
  200. }
  201. AL_API void AL_APIENTRY alGetFontsoundivSOFT(ALuint id, ALenum param, ALint *values)
  202. {
  203. ALCdevice *device;
  204. ALCcontext *context;
  205. const ALfontsound *sound;
  206. context = GetContextRef();
  207. if(!context) return;
  208. device = context->Device;
  209. if(!(sound=LookupFontsound(device, id)))
  210. SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
  211. switch(param)
  212. {
  213. case AL_MOD_LFO_TO_PITCH_SOFT:
  214. values[0] = sound->ModLfoToPitch;
  215. break;
  216. case AL_VIBRATO_LFO_TO_PITCH_SOFT:
  217. values[0] = sound->VibratoLfoToPitch;
  218. break;
  219. case AL_MOD_ENV_TO_PITCH_SOFT:
  220. values[0] = sound->ModEnvToPitch;
  221. break;
  222. case AL_FILTER_CUTOFF_SOFT:
  223. values[0] = sound->FilterCutoff;
  224. break;
  225. case AL_FILTER_RESONANCE_SOFT:
  226. values[0] = sound->FilterQ;
  227. break;
  228. case AL_MOD_LFO_TO_FILTER_CUTOFF_SOFT:
  229. values[0] = sound->ModLfoToFilterCutoff;
  230. break;
  231. case AL_MOD_ENV_TO_FILTER_CUTOFF_SOFT:
  232. values[0] = sound->ModEnvToFilterCutoff;
  233. break;
  234. case AL_MOD_LFO_TO_VOLUME_SOFT:
  235. values[0] = sound->ModLfoToVolume;
  236. break;
  237. case AL_CHORUS_SEND_SOFT:
  238. values[0] = sound->ChorusSend;
  239. break;
  240. case AL_REVERB_SEND_SOFT:
  241. values[0] = sound->ReverbSend;
  242. break;
  243. case AL_PAN_SOFT:
  244. values[0] = sound->Pan;
  245. break;
  246. case AL_MOD_LFO_DELAY_SOFT:
  247. values[0] = sound->ModLfo.Delay;
  248. break;
  249. case AL_MOD_LFO_FREQUENCY_SOFT:
  250. values[0] = sound->ModLfo.Frequency;
  251. break;
  252. case AL_VIBRATO_LFO_DELAY_SOFT:
  253. values[0] = sound->VibratoLfo.Delay;
  254. break;
  255. case AL_VIBRATO_LFO_FREQUENCY_SOFT:
  256. values[0] = sound->VibratoLfo.Frequency;
  257. break;
  258. case AL_MOD_ENV_DELAYTIME_SOFT:
  259. values[0] = sound->ModEnv.DelayTime;
  260. break;
  261. case AL_MOD_ENV_ATTACKTIME_SOFT:
  262. values[0] = sound->ModEnv.AttackTime;
  263. break;
  264. case AL_MOD_ENV_HOLDTIME_SOFT:
  265. values[0] = sound->ModEnv.HoldTime;
  266. break;
  267. case AL_MOD_ENV_DECAYTIME_SOFT:
  268. values[0] = sound->ModEnv.DecayTime;
  269. break;
  270. case AL_MOD_ENV_SUSTAINVOLUME_SOFT:
  271. values[0] = sound->ModEnv.SustainAttn;
  272. break;
  273. case AL_MOD_ENV_RELEASETIME_SOFT:
  274. values[0] = sound->ModEnv.ReleaseTime;
  275. break;
  276. case AL_MOD_ENV_KEY_TO_HOLDTIME_SOFT:
  277. values[0] = sound->ModEnv.KeyToHoldTime;
  278. break;
  279. case AL_MOD_ENV_KEY_TO_DECAYTIME_SOFT:
  280. values[0] = sound->ModEnv.KeyToDecayTime;
  281. break;
  282. case AL_VOLUME_ENV_DELAYTIME_SOFT:
  283. values[0] = sound->VolEnv.DelayTime;
  284. break;
  285. case AL_VOLUME_ENV_ATTACKTIME_SOFT:
  286. values[0] = sound->VolEnv.AttackTime;
  287. break;
  288. case AL_VOLUME_ENV_HOLDTIME_SOFT:
  289. values[0] = sound->VolEnv.HoldTime;
  290. break;
  291. case AL_VOLUME_ENV_DECAYTIME_SOFT:
  292. values[0] = sound->VolEnv.DecayTime;
  293. break;
  294. case AL_VOLUME_ENV_SUSTAINVOLUME_SOFT:
  295. values[0] = sound->VolEnv.SustainAttn;
  296. break;
  297. case AL_VOLUME_ENV_RELEASETIME_SOFT:
  298. values[0] = sound->VolEnv.ReleaseTime;
  299. break;
  300. case AL_VOLUME_ENV_KEY_TO_HOLDTIME_SOFT:
  301. values[0] = sound->VolEnv.KeyToHoldTime;
  302. break;
  303. case AL_VOLUME_ENV_KEY_TO_DECAYTIME_SOFT:
  304. values[0] = sound->VolEnv.KeyToDecayTime;
  305. break;
  306. case AL_KEY_RANGE_SOFT:
  307. values[0] = sound->MinKey;
  308. values[1] = sound->MaxKey;
  309. break;
  310. case AL_VELOCITY_RANGE_SOFT:
  311. values[0] = sound->MinVelocity;
  312. values[1] = sound->MaxVelocity;
  313. break;
  314. case AL_ATTENUATION_SOFT:
  315. values[0] = sound->Attenuation;
  316. break;
  317. case AL_TUNING_COARSE_SOFT:
  318. values[0] = sound->CoarseTuning;
  319. break;
  320. case AL_TUNING_FINE_SOFT:
  321. values[0] = sound->FineTuning;
  322. break;
  323. case AL_LOOP_MODE_SOFT:
  324. values[0] = sound->LoopMode;
  325. break;
  326. case AL_TUNING_SCALE_SOFT:
  327. values[0] = sound->TuningScale;
  328. break;
  329. case AL_EXCLUSIVE_CLASS_SOFT:
  330. values[0] = sound->ExclusiveClass;
  331. break;
  332. case AL_SAMPLE_START_SOFT:
  333. values[0] = sound->Start;
  334. break;
  335. case AL_SAMPLE_END_SOFT:
  336. values[0] = sound->End;
  337. break;
  338. case AL_SAMPLE_LOOP_START_SOFT:
  339. values[0] = sound->LoopStart;
  340. break;
  341. case AL_SAMPLE_LOOP_END_SOFT:
  342. values[0] = sound->LoopEnd;
  343. break;
  344. case AL_SAMPLE_RATE_SOFT:
  345. values[0] = sound->SampleRate;
  346. break;
  347. case AL_BASE_KEY_SOFT:
  348. values[0] = sound->PitchKey;
  349. break;
  350. case AL_KEY_CORRECTION_SOFT:
  351. values[0] = sound->PitchCorrection;
  352. break;
  353. case AL_SAMPLE_TYPE_SOFT:
  354. values[0] = sound->SampleType;
  355. break;
  356. case AL_FONTSOUND_LINK_SOFT:
  357. values[0] = (sound->Link ? sound->Link->id : 0);
  358. break;
  359. default:
  360. SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
  361. }
  362. done:
  363. ALCcontext_DecRef(context);
  364. }
  365. AL_API void AL_APIENTRY alFontsoundModulatoriSOFT(ALuint id, ALsizei stage, ALenum param, ALint value)
  366. {
  367. ALCdevice *device;
  368. ALCcontext *context;
  369. ALfontsound *sound;
  370. context = GetContextRef();
  371. if(!context) return;
  372. device = context->Device;
  373. if(!(sound=LookupFontsound(device, id)))
  374. SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
  375. ALfontsound_setModStagei(sound, context, stage, param, value);
  376. done:
  377. ALCcontext_DecRef(context);
  378. }
  379. AL_API void AL_APIENTRY alGetFontsoundModulatorivSOFT(ALuint id, ALsizei stage, ALenum param, ALint *values)
  380. {
  381. ALCdevice *device;
  382. ALCcontext *context;
  383. ALfontsound *sound;
  384. context = GetContextRef();
  385. if(!context) return;
  386. device = context->Device;
  387. if(!(sound=LookupFontsound(device, id)))
  388. SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
  389. ALfontsound_getModStagei(sound, context, stage, param, values);
  390. done:
  391. ALCcontext_DecRef(context);
  392. }
  393. ALfontsound *NewFontsound(ALCcontext *context)
  394. {
  395. ALCdevice *device = context->Device;
  396. ALfontsound *sound;
  397. ALenum err;
  398. sound = calloc(1, sizeof(*sound));
  399. if(!sound)
  400. SET_ERROR_AND_RETURN_VALUE(context, AL_OUT_OF_MEMORY, NULL);
  401. ALfontsound_Construct(sound);
  402. err = NewThunkEntry(&sound->id);
  403. if(err == AL_NO_ERROR)
  404. err = InsertUIntMapEntry(&device->FontsoundMap, sound->id, sound);
  405. if(err != AL_NO_ERROR)
  406. {
  407. ALfontsound_Destruct(sound);
  408. memset(sound, 0, sizeof(*sound));
  409. free(sound);
  410. SET_ERROR_AND_RETURN_VALUE(context, err, NULL);
  411. }
  412. return sound;
  413. }
  414. static void ALfontsound_Construct(ALfontsound *self)
  415. {
  416. self->ref = 0;
  417. self->MinKey = 0;
  418. self->MaxKey = 127;
  419. self->MinVelocity = 0;
  420. self->MaxVelocity = 127;
  421. self->ModLfoToPitch = 0;
  422. self->VibratoLfoToPitch = 0;
  423. self->ModEnvToPitch = 0;
  424. self->FilterCutoff = 13500;
  425. self->FilterQ = 0;
  426. self->ModLfoToFilterCutoff = 0;
  427. self->ModEnvToFilterCutoff = 0;
  428. self->ModLfoToVolume = 0;
  429. self->ChorusSend = 0;
  430. self->ReverbSend = 0;
  431. self->Pan = 0;
  432. self->ModLfo.Delay = 0;
  433. self->ModLfo.Frequency = 0;
  434. self->VibratoLfo.Delay = 0;
  435. self->VibratoLfo.Frequency = 0;
  436. self->ModEnv.DelayTime = -12000;
  437. self->ModEnv.AttackTime = -12000;
  438. self->ModEnv.HoldTime = -12000;
  439. self->ModEnv.DecayTime = -12000;
  440. self->ModEnv.SustainAttn = 0;
  441. self->ModEnv.ReleaseTime = -12000;
  442. self->ModEnv.KeyToHoldTime = 0;
  443. self->ModEnv.KeyToDecayTime = 0;
  444. self->VolEnv.DelayTime = -12000;
  445. self->VolEnv.AttackTime = -12000;
  446. self->VolEnv.HoldTime = -12000;
  447. self->VolEnv.DecayTime = -12000;
  448. self->VolEnv.SustainAttn = 0;
  449. self->VolEnv.ReleaseTime = -12000;
  450. self->VolEnv.KeyToHoldTime = 0;
  451. self->VolEnv.KeyToDecayTime = 0;
  452. self->Attenuation = 0;
  453. self->CoarseTuning = 0;
  454. self->FineTuning = 0;
  455. self->LoopMode = AL_NONE;
  456. self->TuningScale = 100;
  457. self->ExclusiveClass = 0;
  458. self->Start = 0;
  459. self->End = 0;
  460. self->LoopStart = 0;
  461. self->LoopEnd = 0;
  462. self->SampleRate = 0;
  463. self->PitchKey = 0;
  464. self->PitchCorrection = 0;
  465. self->SampleType = AL_MONO_SOFT;
  466. self->Link = NULL;
  467. InitUIntMap(&self->ModulatorMap, ~0);
  468. self->id = 0;
  469. }
  470. void ALfontsound_Destruct(ALfontsound *self)
  471. {
  472. ALsizei i;
  473. FreeThunkEntry(self->id);
  474. self->id = 0;
  475. if(self->Link)
  476. DecrementRef(&self->Link->ref);
  477. self->Link = NULL;
  478. for(i = 0;i < self->ModulatorMap.size;i++)
  479. {
  480. free(self->ModulatorMap.array[i].value);
  481. self->ModulatorMap.array[i].value = NULL;
  482. }
  483. ResetUIntMap(&self->ModulatorMap);
  484. }
  485. void ALfontsound_setPropi(ALfontsound *self, ALCcontext *context, ALenum param, ALint value)
  486. {
  487. ALfontsound *link;
  488. switch(param)
  489. {
  490. case AL_MOD_LFO_TO_PITCH_SOFT:
  491. self->ModLfoToPitch = value;
  492. break;
  493. case AL_VIBRATO_LFO_TO_PITCH_SOFT:
  494. self->VibratoLfoToPitch = value;
  495. break;
  496. case AL_MOD_ENV_TO_PITCH_SOFT:
  497. self->ModEnvToPitch = value;
  498. break;
  499. case AL_FILTER_CUTOFF_SOFT:
  500. self->FilterCutoff = value;
  501. break;
  502. case AL_FILTER_RESONANCE_SOFT:
  503. if(!(value >= 0))
  504. SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
  505. self->FilterQ = value;
  506. break;
  507. case AL_MOD_LFO_TO_FILTER_CUTOFF_SOFT:
  508. self->ModLfoToFilterCutoff = value;
  509. break;
  510. case AL_MOD_ENV_TO_FILTER_CUTOFF_SOFT:
  511. self->ModEnvToFilterCutoff = value;
  512. break;
  513. case AL_MOD_LFO_TO_VOLUME_SOFT:
  514. self->ModLfoToVolume = value;
  515. break;
  516. case AL_CHORUS_SEND_SOFT:
  517. if(!(value >= 0 && value <= 1000))
  518. SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
  519. self->ChorusSend = value;
  520. break;
  521. case AL_REVERB_SEND_SOFT:
  522. if(!(value >= 0 && value <= 1000))
  523. SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
  524. self->ReverbSend = value;
  525. break;
  526. case AL_PAN_SOFT:
  527. self->Pan = value;
  528. break;
  529. case AL_MOD_LFO_DELAY_SOFT:
  530. self->ModLfo.Delay = value;
  531. break;
  532. case AL_MOD_LFO_FREQUENCY_SOFT:
  533. self->ModLfo.Frequency = value;
  534. break;
  535. case AL_VIBRATO_LFO_DELAY_SOFT:
  536. self->VibratoLfo.Delay = value;
  537. break;
  538. case AL_VIBRATO_LFO_FREQUENCY_SOFT:
  539. self->VibratoLfo.Frequency = value;
  540. break;
  541. case AL_MOD_ENV_DELAYTIME_SOFT:
  542. self->ModEnv.DelayTime = value;
  543. break;
  544. case AL_MOD_ENV_ATTACKTIME_SOFT:
  545. self->ModEnv.AttackTime = value;
  546. break;
  547. case AL_MOD_ENV_HOLDTIME_SOFT:
  548. self->ModEnv.HoldTime = value;
  549. break;
  550. case AL_MOD_ENV_DECAYTIME_SOFT:
  551. self->ModEnv.DecayTime = value;
  552. break;
  553. case AL_MOD_ENV_SUSTAINVOLUME_SOFT:
  554. self->ModEnv.SustainAttn = value;
  555. break;
  556. case AL_MOD_ENV_RELEASETIME_SOFT:
  557. self->ModEnv.ReleaseTime = value;
  558. break;
  559. case AL_MOD_ENV_KEY_TO_HOLDTIME_SOFT:
  560. self->ModEnv.KeyToHoldTime = value;
  561. break;
  562. case AL_MOD_ENV_KEY_TO_DECAYTIME_SOFT:
  563. self->ModEnv.KeyToDecayTime = value;
  564. break;
  565. case AL_VOLUME_ENV_DELAYTIME_SOFT:
  566. self->VolEnv.DelayTime = value;
  567. break;
  568. case AL_VOLUME_ENV_ATTACKTIME_SOFT:
  569. self->VolEnv.AttackTime = value;
  570. break;
  571. case AL_VOLUME_ENV_HOLDTIME_SOFT:
  572. self->VolEnv.HoldTime = value;
  573. break;
  574. case AL_VOLUME_ENV_DECAYTIME_SOFT:
  575. self->VolEnv.DecayTime = value;
  576. break;
  577. case AL_VOLUME_ENV_SUSTAINVOLUME_SOFT:
  578. self->VolEnv.SustainAttn = value;
  579. break;
  580. case AL_VOLUME_ENV_RELEASETIME_SOFT:
  581. self->VolEnv.ReleaseTime = value;
  582. break;
  583. case AL_VOLUME_ENV_KEY_TO_HOLDTIME_SOFT:
  584. self->VolEnv.KeyToHoldTime = value;
  585. break;
  586. case AL_VOLUME_ENV_KEY_TO_DECAYTIME_SOFT:
  587. self->VolEnv.KeyToDecayTime = value;
  588. break;
  589. case AL_ATTENUATION_SOFT:
  590. if(!(value >= 0))
  591. SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
  592. self->Attenuation = value;
  593. break;
  594. case AL_TUNING_COARSE_SOFT:
  595. self->CoarseTuning = value;
  596. break;
  597. case AL_TUNING_FINE_SOFT:
  598. self->FineTuning = value;
  599. break;
  600. case AL_LOOP_MODE_SOFT:
  601. if(!(value == AL_NONE || value == AL_LOOP_CONTINUOUS_SOFT ||
  602. value == AL_LOOP_UNTIL_RELEASE_SOFT))
  603. SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
  604. self->LoopMode = value;
  605. break;
  606. case AL_TUNING_SCALE_SOFT:
  607. self->TuningScale = value;
  608. break;
  609. case AL_EXCLUSIVE_CLASS_SOFT:
  610. self->ExclusiveClass = value;
  611. break;
  612. case AL_SAMPLE_START_SOFT:
  613. self->Start = value;
  614. break;
  615. case AL_SAMPLE_END_SOFT:
  616. self->End = value;
  617. break;
  618. case AL_SAMPLE_LOOP_START_SOFT:
  619. self->LoopStart = value;
  620. break;
  621. case AL_SAMPLE_LOOP_END_SOFT:
  622. self->LoopEnd = value;
  623. break;
  624. case AL_SAMPLE_RATE_SOFT:
  625. if(!(value > 0))
  626. SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
  627. self->SampleRate = value;
  628. break;
  629. case AL_BASE_KEY_SOFT:
  630. if(!((value >= 0 && value <= 127) || value == 255))
  631. SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
  632. self->PitchKey = value;
  633. break;
  634. case AL_KEY_CORRECTION_SOFT:
  635. if(!(value >= -99 && value <= 99))
  636. SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
  637. self->PitchCorrection = value;
  638. break;
  639. case AL_SAMPLE_TYPE_SOFT:
  640. if(!(value == AL_MONO_SOFT || value == AL_RIGHT_SOFT || value == AL_LEFT_SOFT))
  641. SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
  642. self->SampleType = value;
  643. break;
  644. case AL_FONTSOUND_LINK_SOFT:
  645. if(!value)
  646. link = NULL;
  647. else
  648. {
  649. link = LookupFontsound(context->Device, value);
  650. if(!link)
  651. SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
  652. }
  653. if(link) IncrementRef(&link->ref);
  654. link = ExchangePtr((XchgPtr*)&self->Link, link);
  655. if(link) DecrementRef(&link->ref);
  656. break;
  657. default:
  658. SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
  659. }
  660. }
  661. static ALsfmodulator *ALfontsound_getModStage(ALfontsound *self, ALsizei stage)
  662. {
  663. ALsfmodulator *ret = LookupModulator(self, stage);
  664. if(!ret)
  665. {
  666. static const ALsfmodulator moddef = {
  667. { { AL_ONE_SOFT, AL_UNORM_SOFT, AL_LINEAR_SOFT },
  668. { AL_ONE_SOFT, AL_UNORM_SOFT, AL_LINEAR_SOFT }
  669. },
  670. 0,
  671. AL_LINEAR_SOFT,
  672. AL_NONE
  673. };
  674. ret = malloc(sizeof(*ret));
  675. *ret = moddef;
  676. InsertUIntMapEntry(&self->ModulatorMap, stage, ret);
  677. }
  678. return ret;
  679. }
  680. void ALfontsound_setModStagei(ALfontsound *self, ALCcontext *context, ALsizei stage, ALenum param, ALint value)
  681. {
  682. ALint srcidx = 0;
  683. if(self->ref != 0)
  684. SET_ERROR_AND_RETURN(context, AL_INVALID_OPERATION);
  685. switch(param)
  686. {
  687. case AL_SOURCE1_INPUT_SOFT:
  688. srcidx++;
  689. /* fall-through */
  690. case AL_SOURCE0_INPUT_SOFT:
  691. if(!(value == AL_ONE_SOFT || value == AL_NOTEON_VELOCITY_SOFT ||
  692. value == AL_NOTEON_KEY_SOFT || value == AL_KEYPRESSURE_SOFT ||
  693. value == AL_CHANNELPRESSURE_SOFT || value == AL_PITCHBEND_SOFT ||
  694. value == AL_PITCHBEND_SENSITIVITY_SOFT ||
  695. (value > 0 && value < 120 && !(value == 6 || (value >= 32 && value <= 63) ||
  696. (value >= 98 && value <= 101))
  697. )
  698. ))
  699. SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
  700. ALfontsound_getModStage(self, stage)->Source[srcidx].Input = value;
  701. break;
  702. case AL_SOURCE1_TYPE_SOFT:
  703. srcidx++;
  704. /* fall-through */
  705. case AL_SOURCE0_TYPE_SOFT:
  706. if(!(value == AL_UNORM_SOFT || value == AL_UNORM_REV_SOFT ||
  707. value == AL_SNORM_SOFT || value == AL_SNORM_REV_SOFT))
  708. SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
  709. ALfontsound_getModStage(self, stage)->Source[srcidx].Type = value;
  710. break;
  711. case AL_SOURCE1_FORM_SOFT:
  712. srcidx++;
  713. /* fall-through */
  714. case AL_SOURCE0_FORM_SOFT:
  715. if(!(value == AL_LINEAR_SOFT || value == AL_CONCAVE_SOFT ||
  716. value == AL_CONVEX_SOFT || value == AL_SWITCH_SOFT))
  717. SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
  718. ALfontsound_getModStage(self, stage)->Source[srcidx].Form = value;
  719. break;
  720. case AL_AMOUNT_SOFT:
  721. ALfontsound_getModStage(self, stage)->Amount = value;
  722. break;
  723. case AL_TRANSFORM_OP_SOFT:
  724. if(!(value == AL_LINEAR_SOFT || value == AL_ABSOLUTE_SOFT))
  725. SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
  726. ALfontsound_getModStage(self, stage)->TransformOp = value;
  727. break;
  728. case AL_DESTINATION_SOFT:
  729. if(!(value == AL_MOD_LFO_TO_PITCH_SOFT || value == AL_VIBRATO_LFO_TO_PITCH_SOFT ||
  730. value == AL_MOD_ENV_TO_PITCH_SOFT || value == AL_FILTER_CUTOFF_SOFT ||
  731. value == AL_FILTER_RESONANCE_SOFT || value == AL_MOD_LFO_TO_FILTER_CUTOFF_SOFT ||
  732. value == AL_MOD_ENV_TO_FILTER_CUTOFF_SOFT || value == AL_MOD_LFO_TO_VOLUME_SOFT ||
  733. value == AL_CHORUS_SEND_SOFT || value == AL_REVERB_SEND_SOFT || value == AL_PAN_SOFT ||
  734. value == AL_MOD_LFO_DELAY_SOFT || value == AL_MOD_LFO_FREQUENCY_SOFT ||
  735. value == AL_VIBRATO_LFO_DELAY_SOFT || value == AL_VIBRATO_LFO_FREQUENCY_SOFT ||
  736. value == AL_MOD_ENV_DELAYTIME_SOFT || value == AL_MOD_ENV_ATTACKTIME_SOFT ||
  737. value == AL_MOD_ENV_HOLDTIME_SOFT || value == AL_MOD_ENV_DECAYTIME_SOFT ||
  738. value == AL_MOD_ENV_SUSTAINVOLUME_SOFT || value == AL_MOD_ENV_RELEASETIME_SOFT ||
  739. value == AL_MOD_ENV_KEY_TO_HOLDTIME_SOFT || value == AL_MOD_ENV_KEY_TO_DECAYTIME_SOFT ||
  740. value == AL_VOLUME_ENV_DELAYTIME_SOFT || value == AL_VOLUME_ENV_ATTACKTIME_SOFT ||
  741. value == AL_VOLUME_ENV_HOLDTIME_SOFT || value == AL_VOLUME_ENV_DECAYTIME_SOFT ||
  742. value == AL_VOLUME_ENV_SUSTAINVOLUME_SOFT || value == AL_VOLUME_ENV_RELEASETIME_SOFT ||
  743. value == AL_VOLUME_ENV_KEY_TO_HOLDTIME_SOFT || value == AL_VOLUME_ENV_KEY_TO_DECAYTIME_SOFT ||
  744. value == AL_ATTENUATION_SOFT || value == AL_TUNING_COARSE_SOFT ||
  745. value == AL_TUNING_FINE_SOFT || value == AL_TUNING_SCALE_SOFT))
  746. SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
  747. ALfontsound_getModStage(self, stage)->Dest = value;
  748. break;
  749. default:
  750. SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
  751. }
  752. }
  753. static void ALfontsound_getModStagei(ALfontsound *self, ALCcontext *context, ALsizei stage, ALenum param, ALint *values)
  754. {
  755. ALsfmodulator *mod = LookupModulator(self, stage);
  756. ALint srcidx = 0;
  757. switch(param)
  758. {
  759. case AL_SOURCE1_INPUT_SOFT:
  760. srcidx++;
  761. /* fall-through */
  762. case AL_SOURCE0_INPUT_SOFT:
  763. values[0] = mod ? mod->Source[srcidx].Input : AL_ONE_SOFT;
  764. break;
  765. case AL_SOURCE1_TYPE_SOFT:
  766. srcidx++;
  767. /* fall-through */
  768. case AL_SOURCE0_TYPE_SOFT:
  769. values[0] = mod ? mod->Source[srcidx].Type : AL_UNORM_SOFT;
  770. break;
  771. case AL_SOURCE1_FORM_SOFT:
  772. srcidx++;
  773. /* fall-through */
  774. case AL_SOURCE0_FORM_SOFT:
  775. values[0] = mod ? mod->Source[srcidx].Form : AL_LINEAR_SOFT;
  776. break;
  777. case AL_AMOUNT_SOFT:
  778. values[0] = mod ? mod->Amount : 0;
  779. break;
  780. case AL_TRANSFORM_OP_SOFT:
  781. values[0] = mod ? mod->TransformOp : AL_LINEAR_SOFT;
  782. break;
  783. case AL_DESTINATION_SOFT:
  784. values[0] = mod ? mod->Dest : AL_NONE;
  785. break;
  786. default:
  787. SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
  788. }
  789. }
  790. /* ReleaseALFontsounds
  791. *
  792. * Called to destroy any fontsounds that still exist on the device
  793. */
  794. void ReleaseALFontsounds(ALCdevice *device)
  795. {
  796. ALsizei i;
  797. for(i = 0;i < device->FontsoundMap.size;i++)
  798. {
  799. ALfontsound *temp = device->FontsoundMap.array[i].value;
  800. device->FontsoundMap.array[i].value = NULL;
  801. ALfontsound_Destruct(temp);
  802. memset(temp, 0, sizeof(*temp));
  803. free(temp);
  804. }
  805. }