123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272 |
- #include "precompile.h"
- #include "audioengine.h"
- #include "audiolog.h"
- #include <time.h>
- #define DEFAULT_SIZE 1024
- struct audioengine_t
- {
- #ifdef _WIN32
- unsigned int timer_id;
- #else
- timer_t timer_id;
- #endif
- apr_array_header_t *arr_ctx;
- apr_thread_mutex_t *mtx;
- LARGE_INTEGER start_tick;
- LARGE_INTEGER tick;
- LARGE_INTEGER seq;
- };
- void audiocontext_signal(audiocontext_t *ctx);
- #ifdef _WIN32
- #else
- static unsigned long GetTickCount()
- {
- struct timespec ts;
- clock_gettime(CLOCK_MONOTONIC, &ts);
- return (ts.tv_sec * 1000 + ts.tv_nsec / 1000000);
- }
- #endif
- static __inline void GetTick(LARGE_INTEGER *last, LARGE_INTEGER *lt)
- {
- DWORD dwNow = GetTickCount();
- #ifdef _WIN32
- if (last->LowPart > dwNow) {
- lt->LowPart = dwNow;
- lt->HighPart = last->HighPart + 1;
- }
- else {
- lt->LowPart = dwNow;
- lt->HighPart = last->HighPart;
- }
- #else
- if (last->u.LowPart > dwNow) {
- lt->u.LowPart = dwNow;
- lt->u.HighPart = last->u.HighPart + 1;
- }
- else {
- lt->u.LowPart = dwNow;
- lt->u.HighPart = last->u.HighPart;
- }
- #endif // _WIN32
- }
- static void engine_on_clock(audioengine_t *e)
- {
- #ifdef _WIN32
- e->seq.LowPart++;
- if (e->seq.LowPart == 0)
- e->seq.HighPart++;
- #else
- e->seq.u.LowPart++;
- if (e->seq.u.LowPart == 0)
- e->seq.u.HighPart++;
- #endif // _WIN32
- apr_thread_mutex_lock(e->mtx);
- {
- int i;
- for (i = 0; i < e->arr_ctx->nelts; ++i) {
- audiocontext_t *ctx = APR_ARRAY_IDX(e->arr_ctx, i, audiocontext_t*);
- audiocontext_signal(ctx);
- //audio_log_v(AUDIO_LOG_LEVEL_INFO, "audiocontext_signal (%d) ********", i);
- }
- }
- apr_thread_mutex_unlock(e->mtx);
- }
- #ifdef _WIN32
- static void CALLBACK time_cb(UINT uTimerID,
- UINT uMsg,
- DWORD_PTR dwUser,
- DWORD_PTR dw1,
- DWORD_PTR dw2)
- {
- audioengine_t* e = (audioengine_t*)dwUser;
- LONGLONG diff;
- LONGLONG duration;
- GetTick(&e->tick, &e->tick);
- diff = e->tick.QuadPart - e->start_tick.QuadPart;
- duration = e->seq.QuadPart * FRAME_TIME;
- if (diff > duration + 100) {
- engine_on_clock(e);
- engine_on_clock(e);
- audio_log_v(AUDIO_LOG_LEVEL_ERROR, "time_cb swift, add one onclock!");
- }
- else if (diff > duration - 100) {
- engine_on_clock(e);
- }
- else {
- audio_log_v(AUDIO_LOG_LEVEL_ERROR, "time_cb swift, remove one onclock!");
- }
- }
- #else
- // »Øµ÷º¯Êý(SIGEV_THREAD)
- static void handler(union sigval si)
- {
- audioengine_t* e = (audioengine_t*)si.sival_ptr;
- LONGLONG diff = 0;
- LONGLONG duration = 0;
- GetTick(&e->tick, &e->tick);
- //audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d", __FUNCTION__, __LINE__);
- diff = e->tick.QuadPart - e->start_tick.QuadPart;
- duration = e->seq.QuadPart * FRAME_TIME;
- if (diff > duration + 100) {
- engine_on_clock(e);
- engine_on_clock(e);
- //audio_log_v(AUDIO_LOG_LEVEL_ERROR, "diff > duration + 100 time_cb swift, add one on clock!");
- }
- else if (diff > duration - 100) {
- engine_on_clock(e);
- //audio_log_v(AUDIO_LOG_LEVEL_ERROR, "diff > duration - 100 time_cb swift, add one on clock!");
- }
- else {
- audio_log_v(AUDIO_LOG_LEVEL_ERROR, "time_cb swift, remove one on clock!");
- }
- }
- #endif
- apr_status_t audioengine_create(apr_pool_t *pool, audioengine_t **p_engine)
- {
- apr_status_t status;
- audioengine_t *engine;
- engine = apr_palloc(pool, sizeof(audioengine_t));
- memset(engine, 0, sizeof(audioengine_t));
- engine->arr_ctx = apr_array_make(pool, DEFAULT_SIZE, sizeof(audiocontext_t*));
- if (!engine->arr_ctx) {
- return APR_ENOMEM;
- }
- status = apr_thread_mutex_create(&engine->mtx,
- APR_THREAD_MUTEX_NESTED, pool);
- if (status != APR_SUCCESS) {
- return status;
- }
- *p_engine = engine;
- return APR_SUCCESS;
- }
- void audioengine_destroy(audioengine_t *engine)
- {
- if (engine) {
- apr_thread_mutex_destroy(engine->mtx);
- }
- }
- apr_status_t audioengine_start(audioengine_t *e)
- {
- #ifdef _WIN32
- e->start_tick.LowPart = 0;
- e->start_tick.HighPart = 0;
- e->seq.LowPart = 0;
- e->seq.HighPart = 0;
- e->tick.LowPart = 0;
- e->tick.HighPart = 0;
- #else
- e->start_tick.u.LowPart = 0;
- e->start_tick.u.HighPart = 0;
- e->seq.u.LowPart = 0;
- e->seq.u.HighPart = 0;
- e->tick.u.LowPart = 0;
- e->tick.u.HighPart = 0;
- #endif // _WIN32
- GetTick(&e->start_tick, &e->start_tick);
- #ifdef _WIN32
- e->timer_id = timeSetEvent(FRAME_TIME, 0, &time_cb, (DWORD_PTR)e,
- TIME_PERIODIC | TIME_CALLBACK_FUNCTION | TIME_KILL_SYNCHRONOUS);
- #else
- struct sigevent sev;
- struct itimerspec its;
- /* Create the timer */
- memset(&sev, 0, sizeof(sev));
- sev.sigev_notify = SIGEV_THREAD;
- sev.sigev_notify_function = handler;
- sev.sigev_value.sival_ptr = e;
- if (timer_create(CLOCK_REALTIME, &sev, &e->timer_id) == -1)
- {
- audio_log_v(AUDIO_LOG_LEVEL_ERROR, "timer_create error.(%s)", strerror(errno));
- return -1;
- }
- its.it_value.tv_sec = 0;
- its.it_value.tv_nsec = 1000 * 1000 * FRAME_TIME;
- its.it_interval.tv_sec = its.it_value.tv_sec;
- its.it_interval.tv_nsec = its.it_value.tv_nsec;
- if (timer_settime(e->timer_id, 0, &its, NULL) == -1)
- {
- audio_log_v(AUDIO_LOG_LEVEL_ERROR, "timer_settime error.(%s)", strerror(errno));
- return -1;
- }
- #endif
- return e->timer_id ? APR_SUCCESS : apr_get_os_error();
- }
- void audioengine_stop(audioengine_t *e)
- {
- if (e) {
- #ifdef _WIN32
- timeKillEvent(e->timer_id);
- e->timer_id = 0;
- #else
- timer_delete(e->timer_id);
- e->timer_id = 0;
- #endif
- }
- }
- int audioengine_is_started(audioengine_t *e)
- {
- return e->timer_id != 0;
- }
- apr_status_t audioengine_start_context(audioengine_t *e, audiocontext_t *ctx)
- {
- if (!e || !ctx) {
- return APR_BADARG;
- }
- apr_thread_mutex_lock(e->mtx);
- APR_ARRAY_PUSH(e->arr_ctx, audiocontext_t*) = ctx;
- apr_thread_mutex_unlock(e->mtx);
- return APR_SUCCESS;
- }
- void audioengine_stop_context(audioengine_t *e, audiocontext_t *ctx)
- {
- if (e && ctx) {
- int i;
- apr_thread_mutex_lock(e->mtx);
- for (i = 0; i < e->arr_ctx->nelts; ++i) {
- if (ctx == APR_ARRAY_IDX(e->arr_ctx, i, audiocontext_t*)) {
- if (i < e->arr_ctx->nelts-1) {
- audiocontext_t *tmp = APR_ARRAY_IDX(e->arr_ctx, i, audiocontext_t*);
- APR_ARRAY_IDX(e->arr_ctx, i, audiocontext_t*) = APR_ARRAY_IDX(e->arr_ctx, e->arr_ctx->nelts-1, audiocontext_t*);
- APR_ARRAY_IDX(e->arr_ctx, e->arr_ctx->nelts-1, audiocontext_t*) = tmp;
- }
- apr_array_pop(e->arr_ctx);
- break;
- }
- }
- apr_thread_mutex_unlock(e->mtx);
- }
- }
|