alMidi.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. #include "config.h"
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <limits.h>
  6. #include "alMain.h"
  7. #include "alMidi.h"
  8. #include "alError.h"
  9. #include "alThunk.h"
  10. #include "evtqueue.h"
  11. #include "rwlock.h"
  12. #include "alu.h"
  13. #include "midi/base.h"
  14. MidiSynth *SynthCreate(ALCdevice *device)
  15. {
  16. MidiSynth *synth = FSynth_create(device);
  17. if(!synth) synth = DSynth_create(device);
  18. return synth;
  19. }
  20. AL_API void AL_APIENTRY alMidiSoundfontSOFT(ALuint id)
  21. {
  22. alMidiSoundfontvSOFT(1, &id);
  23. }
  24. AL_API void AL_APIENTRY alMidiSoundfontvSOFT(ALsizei count, const ALuint *ids)
  25. {
  26. ALCdevice *device;
  27. ALCcontext *context;
  28. MidiSynth *synth;
  29. ALenum err;
  30. context = GetContextRef();
  31. if(!context) return;
  32. if(count < 0)
  33. SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
  34. device = context->Device;
  35. synth = device->Synth;
  36. WriteLock(&synth->Lock);
  37. if(synth->State == AL_PLAYING || synth->State == AL_PAUSED)
  38. alSetError(context, AL_INVALID_OPERATION);
  39. else
  40. {
  41. err = V(synth,selectSoundfonts)(context, count, ids);
  42. if(err != AL_NO_ERROR)
  43. alSetError(context, err);
  44. }
  45. WriteUnlock(&synth->Lock);
  46. done:
  47. ALCcontext_DecRef(context);
  48. }
  49. AL_API void AL_APIENTRY alMidiEventSOFT(ALuint64SOFT time, ALenum event, ALsizei channel, ALsizei param1, ALsizei param2)
  50. {
  51. ALCdevice *device;
  52. ALCcontext *context;
  53. ALenum err;
  54. context = GetContextRef();
  55. if(!context) return;
  56. if(!(event == AL_NOTEOFF_SOFT || event == AL_NOTEON_SOFT ||
  57. event == AL_KEYPRESSURE_SOFT || event == AL_CONTROLLERCHANGE_SOFT ||
  58. event == AL_PROGRAMCHANGE_SOFT || event == AL_CHANNELPRESSURE_SOFT ||
  59. event == AL_PITCHBEND_SOFT))
  60. SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
  61. if(!(channel >= 0 && channel <= 15))
  62. SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
  63. if(!(param1 >= 0 && param1 <= 127))
  64. SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
  65. if(!(param2 >= 0 && param2 <= 127))
  66. SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
  67. device = context->Device;
  68. ALCdevice_Lock(device);
  69. err = MidiSynth_insertEvent(device->Synth, time, event|channel, param1, param2);
  70. ALCdevice_Unlock(device);
  71. if(err != AL_NO_ERROR)
  72. alSetError(context, err);
  73. done:
  74. ALCcontext_DecRef(context);
  75. }
  76. AL_API void AL_APIENTRY alMidiSysExSOFT(ALuint64SOFT time, const ALbyte *data, ALsizei size)
  77. {
  78. ALCdevice *device;
  79. ALCcontext *context;
  80. ALenum err;
  81. ALsizei i;
  82. context = GetContextRef();
  83. if(!context) return;
  84. if(!data || size < 0)
  85. SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
  86. for(i = 0;i < size;i++)
  87. {
  88. if((data[i]&0x80))
  89. SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
  90. }
  91. device = context->Device;
  92. ALCdevice_Lock(device);
  93. err = MidiSynth_insertSysExEvent(device->Synth, time, data, size);
  94. ALCdevice_Unlock(device);
  95. if(err != AL_NO_ERROR)
  96. alSetError(context, err);
  97. done:
  98. ALCcontext_DecRef(context);
  99. }
  100. AL_API void AL_APIENTRY alMidiPlaySOFT(void)
  101. {
  102. ALCcontext *context;
  103. MidiSynth *synth;
  104. context = GetContextRef();
  105. if(!context) return;
  106. synth = context->Device->Synth;
  107. WriteLock(&synth->Lock);
  108. V(synth,setState)(AL_PLAYING);
  109. WriteUnlock(&synth->Lock);
  110. ALCcontext_DecRef(context);
  111. }
  112. AL_API void AL_APIENTRY alMidiPauseSOFT(void)
  113. {
  114. ALCcontext *context;
  115. MidiSynth *synth;
  116. context = GetContextRef();
  117. if(!context) return;
  118. synth = context->Device->Synth;
  119. WriteLock(&synth->Lock);
  120. V(synth,setState)(AL_PAUSED);
  121. WriteUnlock(&synth->Lock);
  122. ALCcontext_DecRef(context);
  123. }
  124. AL_API void AL_APIENTRY alMidiStopSOFT(void)
  125. {
  126. ALCdevice *device;
  127. ALCcontext *context;
  128. MidiSynth *synth;
  129. context = GetContextRef();
  130. if(!context) return;
  131. device = context->Device;
  132. synth = device->Synth;
  133. WriteLock(&synth->Lock);
  134. V(synth,setState)(AL_STOPPED);
  135. ALCdevice_Lock(device);
  136. V0(synth,stop)();
  137. ALCdevice_Unlock(device);
  138. WriteUnlock(&synth->Lock);
  139. ALCcontext_DecRef(context);
  140. }
  141. AL_API void AL_APIENTRY alMidiResetSOFT(void)
  142. {
  143. ALCdevice *device;
  144. ALCcontext *context;
  145. MidiSynth *synth;
  146. context = GetContextRef();
  147. if(!context) return;
  148. device = context->Device;
  149. synth = device->Synth;
  150. WriteLock(&synth->Lock);
  151. V(synth,setState)(AL_INITIAL);
  152. ALCdevice_Lock(device);
  153. V0(synth,reset)();
  154. ALCdevice_Unlock(device);
  155. WriteUnlock(&synth->Lock);
  156. ALCcontext_DecRef(context);
  157. }
  158. AL_API void AL_APIENTRY alMidiGainSOFT(ALfloat value)
  159. {
  160. ALCdevice *device;
  161. ALCcontext *context;
  162. context = GetContextRef();
  163. if(!context) return;
  164. if(!(value >= 0.0f && isfinite(value)))
  165. SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
  166. device = context->Device;
  167. V(device->Synth,setGain)(value);
  168. done:
  169. ALCcontext_DecRef(context);
  170. }