audioengine.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. #include "precompile.h"
  2. #include "audioengine.h"
  3. #include "audiolog.h"
  4. #include <time.h>
  5. #define DEFAULT_SIZE 1024
  6. struct audioengine_t
  7. {
  8. #ifdef _WIN32
  9. unsigned int timer_id;
  10. #else
  11. timer_t timer_id;
  12. #endif
  13. apr_array_header_t *arr_ctx;
  14. apr_thread_mutex_t *mtx;
  15. LARGE_INTEGER start_tick;
  16. LARGE_INTEGER tick;
  17. LARGE_INTEGER seq;
  18. };
  19. void audiocontext_signal(audiocontext_t *ctx);
  20. #ifdef _WIN32
  21. #else
  22. static unsigned long GetTickCount()
  23. {
  24. struct timespec ts;
  25. clock_gettime(CLOCK_MONOTONIC, &ts);
  26. return (ts.tv_sec * 1000 + ts.tv_nsec / 1000000);
  27. }
  28. #endif
  29. static __inline void GetTick(LARGE_INTEGER *last, LARGE_INTEGER *lt)
  30. {
  31. DWORD dwNow = GetTickCount();
  32. #ifdef _WIN32
  33. if (last->LowPart > dwNow) {
  34. lt->LowPart = dwNow;
  35. lt->HighPart = last->HighPart + 1;
  36. }
  37. else {
  38. lt->LowPart = dwNow;
  39. lt->HighPart = last->HighPart;
  40. }
  41. #else
  42. if (last->u.LowPart > dwNow) {
  43. lt->u.LowPart = dwNow;
  44. lt->u.HighPart = last->u.HighPart + 1;
  45. }
  46. else {
  47. lt->u.LowPart = dwNow;
  48. lt->u.HighPart = last->u.HighPart;
  49. }
  50. #endif // _WIN32
  51. }
  52. static void engine_on_clock(audioengine_t *e)
  53. {
  54. #ifdef _WIN32
  55. e->seq.LowPart++;
  56. if (e->seq.LowPart == 0)
  57. e->seq.HighPart++;
  58. #else
  59. e->seq.u.LowPart++;
  60. if (e->seq.u.LowPart == 0)
  61. e->seq.u.HighPart++;
  62. #endif // _WIN32
  63. apr_thread_mutex_lock(e->mtx);
  64. {
  65. int i;
  66. for (i = 0; i < e->arr_ctx->nelts; ++i) {
  67. audiocontext_t *ctx = APR_ARRAY_IDX(e->arr_ctx, i, audiocontext_t*);
  68. audiocontext_signal(ctx);
  69. //audio_log_v(AUDIO_LOG_LEVEL_INFO, "audiocontext_signal (%d) ********", i);
  70. }
  71. }
  72. apr_thread_mutex_unlock(e->mtx);
  73. }
  74. #ifdef _WIN32
  75. static void CALLBACK time_cb(UINT uTimerID,
  76. UINT uMsg,
  77. DWORD_PTR dwUser,
  78. DWORD_PTR dw1,
  79. DWORD_PTR dw2)
  80. {
  81. audioengine_t* e = (audioengine_t*)dwUser;
  82. LONGLONG diff;
  83. LONGLONG duration;
  84. GetTick(&e->tick, &e->tick);
  85. diff = e->tick.QuadPart - e->start_tick.QuadPart;
  86. duration = e->seq.QuadPart * FRAME_TIME;
  87. if (diff > duration + 100) {
  88. engine_on_clock(e);
  89. engine_on_clock(e);
  90. audio_log_v(AUDIO_LOG_LEVEL_ERROR, "time_cb swift, add one onclock!");
  91. }
  92. else if (diff > duration - 100) {
  93. engine_on_clock(e);
  94. }
  95. else {
  96. audio_log_v(AUDIO_LOG_LEVEL_ERROR, "time_cb swift, remove one onclock!");
  97. }
  98. }
  99. #else
  100. // »Øµ÷º¯Êý(SIGEV_THREAD)
  101. static void handler(union sigval si)
  102. {
  103. audioengine_t* e = (audioengine_t*)si.sival_ptr;
  104. LONGLONG diff = 0;
  105. LONGLONG duration = 0;
  106. GetTick(&e->tick, &e->tick);
  107. //audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d", __FUNCTION__, __LINE__);
  108. diff = e->tick.QuadPart - e->start_tick.QuadPart;
  109. duration = e->seq.QuadPart * FRAME_TIME;
  110. if (diff > duration + 100) {
  111. engine_on_clock(e);
  112. engine_on_clock(e);
  113. //audio_log_v(AUDIO_LOG_LEVEL_ERROR, "diff > duration + 100 time_cb swift, add one on clock!");
  114. }
  115. else if (diff > duration - 100) {
  116. engine_on_clock(e);
  117. //audio_log_v(AUDIO_LOG_LEVEL_ERROR, "diff > duration - 100 time_cb swift, add one on clock!");
  118. }
  119. else {
  120. audio_log_v(AUDIO_LOG_LEVEL_ERROR, "time_cb swift, remove one on clock!");
  121. }
  122. }
  123. #endif
  124. apr_status_t audioengine_create(apr_pool_t *pool, audioengine_t **p_engine)
  125. {
  126. apr_status_t status;
  127. audioengine_t *engine;
  128. engine = apr_palloc(pool, sizeof(audioengine_t));
  129. memset(engine, 0, sizeof(audioengine_t));
  130. engine->arr_ctx = apr_array_make(pool, DEFAULT_SIZE, sizeof(audiocontext_t*));
  131. if (!engine->arr_ctx) {
  132. return APR_ENOMEM;
  133. }
  134. status = apr_thread_mutex_create(&engine->mtx,
  135. APR_THREAD_MUTEX_NESTED, pool);
  136. if (status != APR_SUCCESS) {
  137. return status;
  138. }
  139. *p_engine = engine;
  140. return APR_SUCCESS;
  141. }
  142. void audioengine_destroy(audioengine_t *engine)
  143. {
  144. if (engine) {
  145. apr_thread_mutex_destroy(engine->mtx);
  146. }
  147. }
  148. apr_status_t audioengine_start(audioengine_t *e)
  149. {
  150. #ifdef _WIN32
  151. e->start_tick.LowPart = 0;
  152. e->start_tick.HighPart = 0;
  153. e->seq.LowPart = 0;
  154. e->seq.HighPart = 0;
  155. e->tick.LowPart = 0;
  156. e->tick.HighPart = 0;
  157. #else
  158. e->start_tick.u.LowPart = 0;
  159. e->start_tick.u.HighPart = 0;
  160. e->seq.u.LowPart = 0;
  161. e->seq.u.HighPart = 0;
  162. e->tick.u.LowPart = 0;
  163. e->tick.u.HighPart = 0;
  164. #endif // _WIN32
  165. GetTick(&e->start_tick, &e->start_tick);
  166. #ifdef _WIN32
  167. e->timer_id = timeSetEvent(FRAME_TIME, 0, &time_cb, (DWORD_PTR)e,
  168. TIME_PERIODIC | TIME_CALLBACK_FUNCTION | TIME_KILL_SYNCHRONOUS);
  169. #else
  170. struct sigevent sev;
  171. struct itimerspec its;
  172. /* Create the timer */
  173. memset(&sev, 0, sizeof(sev));
  174. sev.sigev_notify = SIGEV_THREAD;
  175. sev.sigev_notify_function = handler;
  176. sev.sigev_value.sival_ptr = e;
  177. if (timer_create(CLOCK_REALTIME, &sev, &e->timer_id) == -1)
  178. {
  179. audio_log_v(AUDIO_LOG_LEVEL_ERROR, "timer_create error.(%s)", strerror(errno));
  180. return -1;
  181. }
  182. its.it_value.tv_sec = 0;
  183. its.it_value.tv_nsec = 1000 * 1000 * FRAME_TIME;
  184. its.it_interval.tv_sec = its.it_value.tv_sec;
  185. its.it_interval.tv_nsec = its.it_value.tv_nsec;
  186. if (timer_settime(e->timer_id, 0, &its, NULL) == -1)
  187. {
  188. audio_log_v(AUDIO_LOG_LEVEL_ERROR, "timer_settime error.(%s)", strerror(errno));
  189. return -1;
  190. }
  191. #endif
  192. return e->timer_id ? APR_SUCCESS : apr_get_os_error();
  193. }
  194. void audioengine_stop(audioengine_t *e)
  195. {
  196. if (e) {
  197. #ifdef _WIN32
  198. timeKillEvent(e->timer_id);
  199. e->timer_id = 0;
  200. #else
  201. timer_delete(e->timer_id);
  202. e->timer_id = 0;
  203. #endif
  204. }
  205. }
  206. int audioengine_is_started(audioengine_t *e)
  207. {
  208. return e->timer_id != 0;
  209. }
  210. apr_status_t audioengine_start_context(audioengine_t *e, audiocontext_t *ctx)
  211. {
  212. if (!e || !ctx) {
  213. return APR_BADARG;
  214. }
  215. apr_thread_mutex_lock(e->mtx);
  216. APR_ARRAY_PUSH(e->arr_ctx, audiocontext_t*) = ctx;
  217. apr_thread_mutex_unlock(e->mtx);
  218. return APR_SUCCESS;
  219. }
  220. void audioengine_stop_context(audioengine_t *e, audiocontext_t *ctx)
  221. {
  222. if (e && ctx) {
  223. int i;
  224. apr_thread_mutex_lock(e->mtx);
  225. for (i = 0; i < e->arr_ctx->nelts; ++i) {
  226. if (ctx == APR_ARRAY_IDX(e->arr_ctx, i, audiocontext_t*)) {
  227. if (i < e->arr_ctx->nelts-1) {
  228. audiocontext_t *tmp = APR_ARRAY_IDX(e->arr_ctx, i, audiocontext_t*);
  229. APR_ARRAY_IDX(e->arr_ctx, i, audiocontext_t*) = APR_ARRAY_IDX(e->arr_ctx, e->arr_ctx->nelts-1, audiocontext_t*);
  230. APR_ARRAY_IDX(e->arr_ctx, e->arr_ctx->nelts-1, audiocontext_t*) = tmp;
  231. }
  232. apr_array_pop(e->arr_ctx);
  233. break;
  234. }
  235. }
  236. apr_thread_mutex_unlock(e->mtx);
  237. }
  238. }