alcModulator.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /**
  2. * OpenAL cross platform audio library
  3. * Copyright (C) 2009 by Chris Robinson.
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Library General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2 of the License, or (at your option) any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Library General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Library General Public
  15. * License along with this library; if not, write to the
  16. * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  17. * Boston, MA 02111-1307, USA.
  18. * Or go to http://www.gnu.org/copyleft/lgpl.html
  19. */
  20. #include "config.h"
  21. #include <math.h>
  22. #include <stdlib.h>
  23. #include "alMain.h"
  24. #include "alFilter.h"
  25. #include "alAuxEffectSlot.h"
  26. #include "alError.h"
  27. #include "alu.h"
  28. typedef struct ALmodulatorState {
  29. // Must be first in all effects!
  30. ALeffectState state;
  31. enum {
  32. SINUSOID,
  33. SAWTOOTH,
  34. SQUARE
  35. } Waveform;
  36. ALuint index;
  37. ALuint step;
  38. ALfp Gain[MAXCHANNELS];
  39. FILTER iirFilter;
  40. ALfp history[1];
  41. } ALmodulatorState;
  42. #define WAVEFORM_FRACBITS 16
  43. #define WAVEFORM_FRACMASK ((1<<WAVEFORM_FRACBITS)-1)
  44. static __inline ALfp sin_func(ALuint index)
  45. {
  46. return __sin(ALdfpMult(ALdfpDiv(int2ALdfp(index),double2ALdfp(1<<WAVEFORM_FRACBITS)), double2ALdfp(M_PI * 2.0f)));
  47. }
  48. static __inline ALfp saw_func(ALuint index)
  49. {
  50. return (ALfpDiv(int2ALfp(index*2), int2ALfp(1<<WAVEFORM_FRACBITS)) - int2ALfp(1));
  51. }
  52. static __inline ALfp square_func(ALuint index)
  53. {
  54. return int2ALfp((float)((index>>(WAVEFORM_FRACBITS-1))&1) ? -1 : 1);
  55. }
  56. static __inline ALfp hpFilter1P(FILTER *iir, ALuint offset, ALfp input)
  57. {
  58. ALfp *history = &iir->history[offset];
  59. ALfp a = iir->coeff;
  60. ALfp output = input;
  61. output = (output + ALfpMult((history[0]-output),a));
  62. history[0] = output;
  63. return (input - output);
  64. }
  65. static ALvoid ModulatorDestroy(ALeffectState *effect)
  66. {
  67. ALmodulatorState *state = (ALmodulatorState*)effect;
  68. free(state);
  69. }
  70. static ALboolean ModulatorDeviceUpdate(ALeffectState *effect, ALCdevice *Device)
  71. {
  72. ALmodulatorState *state = (ALmodulatorState*)effect;
  73. ALuint index;
  74. for(index = 0;index < MAXCHANNELS;index++)
  75. state->Gain[index] = int2ALfp(0);
  76. for(index = 0;index < Device->NumChan;index++)
  77. {
  78. Channel chan = Device->Speaker2Chan[index];
  79. state->Gain[chan] = int2ALfp(1);
  80. }
  81. return AL_TRUE;
  82. }
  83. static ALvoid ModulatorUpdate(ALeffectState *effect, ALCcontext *Context, const ALeffect *Effect)
  84. {
  85. ALmodulatorState *state = (ALmodulatorState*)effect;
  86. ALfp cw, a;
  87. a = int2ALfp(0);
  88. if(Effect->Modulator.Waveform == AL_RING_MODULATOR_SINUSOID)
  89. state->Waveform = SINUSOID;
  90. else if(Effect->Modulator.Waveform == AL_RING_MODULATOR_SAWTOOTH)
  91. state->Waveform = SAWTOOTH;
  92. else if(Effect->Modulator.Waveform == AL_RING_MODULATOR_SQUARE)
  93. state->Waveform = SQUARE;
  94. state->step = ALfp2int(ALfpDiv(ALfpMult(Effect->Modulator.Frequency,
  95. int2ALfp(1<<WAVEFORM_FRACBITS)),
  96. int2ALfp(Context->Device->Frequency)));
  97. if(!state->step)
  98. state->step = 1;
  99. cw = __cos(ALfpDiv(ALfpMult(float2ALfp(2.0*M_PI),
  100. Effect->Modulator.HighPassCutoff),
  101. int2ALfp(Context->Device->Frequency)));
  102. a = ((int2ALfp(2)-cw) -
  103. aluSqrt((aluPow((int2ALfp(2)-cw), int2ALfp(2)) - int2ALfp(1))));
  104. state->iirFilter.coeff = a;
  105. }
  106. static ALvoid ModulatorProcess(ALeffectState *effect, const ALeffectslot *Slot, ALuint SamplesToDo, const ALfp *SamplesIn, ALfp (*SamplesOut)[MAXCHANNELS])
  107. {
  108. ALmodulatorState *state = (ALmodulatorState*)effect;
  109. const ALfp gain = Slot->Gain;
  110. const ALuint step = state->step;
  111. ALuint index = state->index;
  112. ALfp samp;
  113. ALuint i;
  114. switch(state->Waveform)
  115. {
  116. case SINUSOID:
  117. for(i = 0;i < SamplesToDo;i++)
  118. {
  119. #ifdef APPORTABLE_OPTIMIZED_OUT
  120. #define FILTER_OUT(func) do { \
  121. samp = SamplesIn[i]; \
  122. \
  123. index += step; \
  124. index &= WAVEFORM_FRACMASK; \
  125. samp *= func(index); \
  126. \
  127. samp = hpFilter1P(&state->iirFilter, 0, samp); \
  128. \
  129. /* Apply slot gain */ \
  130. samp *= gain; \
  131. \
  132. SamplesOut[i][FRONT_LEFT] += state->Gain[FRONT_LEFT] * samp; \
  133. SamplesOut[i][FRONT_RIGHT] += state->Gain[FRONT_RIGHT] * samp; \
  134. SamplesOut[i][FRONT_CENTER] += state->Gain[FRONT_CENTER] * samp; \
  135. SamplesOut[i][SIDE_LEFT] += state->Gain[SIDE_LEFT] * samp; \
  136. SamplesOut[i][SIDE_RIGHT] += state->Gain[SIDE_RIGHT] * samp; \
  137. SamplesOut[i][BACK_LEFT] += state->Gain[BACK_LEFT] * samp; \
  138. SamplesOut[i][BACK_RIGHT] += state->Gain[BACK_RIGHT] * samp; \
  139. SamplesOut[i][BACK_CENTER] += state->Gain[BACK_CENTER] * samp; \
  140. } while(0)
  141. #else
  142. //Apportable optimized version
  143. #define FILTER_OUT(func) do { \
  144. samp = SamplesIn[i]; \
  145. \
  146. index += step; \
  147. index &= WAVEFORM_FRACMASK; \
  148. samp = ALfpMult(samp, func(index)); \
  149. \
  150. samp = hpFilter1P(&state->iirFilter, 0, samp); \
  151. \
  152. /* Apply slot gain */ \
  153. samp = ALfpMult(samp, gain); \
  154. \
  155. SamplesOut[i][FRONT_LEFT] += ALfpMult(state->Gain[FRONT_LEFT], samp); \
  156. SamplesOut[i][FRONT_RIGHT] += ALfpMult(state->Gain[FRONT_RIGHT], samp); \
  157. } while(0)
  158. #endif
  159. FILTER_OUT(sin_func);
  160. }
  161. break;
  162. case SAWTOOTH:
  163. for(i = 0;i < SamplesToDo;i++)
  164. {
  165. FILTER_OUT(saw_func);
  166. }
  167. break;
  168. case SQUARE:
  169. for(i = 0;i < SamplesToDo;i++)
  170. {
  171. FILTER_OUT(square_func);
  172. #undef FILTER_OUT
  173. }
  174. break;
  175. }
  176. state->index = index;
  177. }
  178. ALeffectState *ModulatorCreate(void)
  179. {
  180. ALmodulatorState *state;
  181. state = malloc(sizeof(*state));
  182. if(!state)
  183. return NULL;
  184. state->state.Destroy = ModulatorDestroy;
  185. state->state.DeviceUpdate = ModulatorDeviceUpdate;
  186. state->state.Update = ModulatorUpdate;
  187. state->state.Process = ModulatorProcess;
  188. state->index = 0;
  189. state->step = 1;
  190. state->iirFilter.coeff = int2ALfp(0);
  191. state->iirFilter.history[0] = int2ALfp(0);
  192. return &state->state;
  193. }