audioengine.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. #include "precompile.h"
  2. #include "audioengine.h"
  3. #include "audiolog.h"
  4. #define DEFAULT_SIZE 1024
  5. struct audioengine_t
  6. {
  7. unsigned int timer_id;
  8. apr_array_header_t *arr_ctx;
  9. apr_thread_mutex_t *mtx;
  10. LARGE_INTEGER start_tick;
  11. LARGE_INTEGER tick;
  12. LARGE_INTEGER seq;
  13. };
  14. void audiocontext_signal(audiocontext_t *ctx);
  15. static __inline void GetTick(LARGE_INTEGER *last, LARGE_INTEGER *lt)
  16. {
  17. DWORD dwNow = GetTickCount();
  18. if (last->LowPart > dwNow) {
  19. lt->LowPart = dwNow;
  20. lt->HighPart = last->HighPart + 1;
  21. } else {
  22. lt->LowPart = dwNow;
  23. lt->HighPart = last->HighPart;
  24. }
  25. }
  26. static void engine_on_clock(audioengine_t *e)
  27. {
  28. e->seq.LowPart++;
  29. if (e->seq.LowPart == 0)
  30. e->seq.HighPart++;
  31. apr_thread_mutex_lock(e->mtx);
  32. {
  33. int i;
  34. for (i = 0; i < e->arr_ctx->nelts; ++i) {
  35. audiocontext_t *ctx = APR_ARRAY_IDX(e->arr_ctx, i, audiocontext_t*);
  36. audiocontext_signal(ctx);
  37. }
  38. }
  39. apr_thread_mutex_unlock(e->mtx);
  40. }
  41. static void CALLBACK time_cb(UINT uTimerID,
  42. UINT uMsg,
  43. DWORD_PTR dwUser,
  44. DWORD_PTR dw1,
  45. DWORD_PTR dw2)
  46. {
  47. audioengine_t *e = (audioengine_t*)dwUser;
  48. LONGLONG diff;
  49. LONGLONG duration;
  50. GetTick(&e->tick, &e->tick);
  51. diff = e->tick.QuadPart - e->start_tick.QuadPart;
  52. duration = e->seq.QuadPart * FRAME_TIME;
  53. if (diff > duration + 100) {
  54. engine_on_clock(e);
  55. engine_on_clock(e);
  56. AUDIO_LOG_ERROR("time_cb swift, add one onclock!");
  57. } else if (diff > duration-100) {
  58. engine_on_clock(e);
  59. } else {
  60. AUDIO_LOG_ERROR("time_cb swift, remove one onclock!");
  61. }
  62. }
  63. apr_status_t audioengine_create(apr_pool_t *pool, audioengine_t **p_engine)
  64. {
  65. apr_status_t status;
  66. audioengine_t *engine;
  67. engine = apr_palloc(pool, sizeof(audioengine_t));
  68. memset(engine, 0, sizeof(audioengine_t));
  69. engine->arr_ctx = apr_array_make(pool, DEFAULT_SIZE, sizeof(audiocontext_t*));
  70. if (!engine->arr_ctx) {
  71. return APR_ENOMEM;
  72. }
  73. status = apr_thread_mutex_create(&engine->mtx,
  74. APR_THREAD_MUTEX_NESTED, pool);
  75. if (status != APR_SUCCESS) {
  76. return status;
  77. }
  78. *p_engine = engine;
  79. return APR_SUCCESS;
  80. }
  81. void audioengine_destroy(audioengine_t *engine)
  82. {
  83. if (engine) {
  84. apr_thread_mutex_destroy(engine->mtx);
  85. }
  86. }
  87. apr_status_t audioengine_start(audioengine_t *e)
  88. {
  89. e->start_tick.LowPart = 0;
  90. e->start_tick.HighPart = 0;
  91. e->seq.LowPart = 0;
  92. e->seq.HighPart = 0;
  93. e->tick.LowPart = 0;
  94. e->tick.HighPart = 0;
  95. GetTick(&e->start_tick, &e->start_tick);
  96. e->timer_id = timeSetEvent(FRAME_TIME, 0, &time_cb, (DWORD_PTR)e,
  97. TIME_PERIODIC | TIME_CALLBACK_FUNCTION | TIME_KILL_SYNCHRONOUS);
  98. return e->timer_id ? APR_SUCCESS : apr_get_os_error();
  99. }
  100. void audioengine_stop(audioengine_t *e)
  101. {
  102. if (e) {
  103. timeKillEvent(e->timer_id);
  104. e->timer_id = 0;
  105. }
  106. }
  107. int audioengine_is_started(audioengine_t *e)
  108. {
  109. return e->timer_id != 0;
  110. }
  111. apr_status_t audioengine_start_context(audioengine_t *e, audiocontext_t *ctx)
  112. {
  113. if (!e || !ctx) {
  114. return APR_BADARG;
  115. }
  116. apr_thread_mutex_lock(e->mtx);
  117. APR_ARRAY_PUSH(e->arr_ctx, audiocontext_t*) = ctx;
  118. apr_thread_mutex_unlock(e->mtx);
  119. return APR_SUCCESS;
  120. }
  121. void audioengine_stop_context(audioengine_t *e, audiocontext_t *ctx)
  122. {
  123. if (e && ctx) {
  124. int i;
  125. apr_thread_mutex_lock(e->mtx);
  126. for (i = 0; i < e->arr_ctx->nelts; ++i) {
  127. if (ctx == APR_ARRAY_IDX(e->arr_ctx, i, audiocontext_t*)) {
  128. if (i < e->arr_ctx->nelts-1) {
  129. audiocontext_t *tmp = APR_ARRAY_IDX(e->arr_ctx, i, audiocontext_t*);
  130. APR_ARRAY_IDX(e->arr_ctx, i, audiocontext_t*) = APR_ARRAY_IDX(e->arr_ctx, e->arr_ctx->nelts-1, audiocontext_t*);
  131. APR_ARRAY_IDX(e->arr_ctx, e->arr_ctx->nelts-1, audiocontext_t*) = tmp;
  132. }
  133. apr_array_pop(e->arr_ctx);
  134. break;
  135. }
  136. }
  137. apr_thread_mutex_unlock(e->mtx);
  138. }
  139. }