⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 audio.c

📁 xen 3.2.2 源码
💻 C
📖 第 1 页 / 共 4 页
字号:
    live = sw->total_hw_samples_mixed;    if (audio_bug (AUDIO_FUNC, live < 0 || live > hwsamples)){        dolog ("live=%d hw->samples=%d\n", live, hwsamples);        return 0;    }    if (live == hwsamples) {#ifdef DEBUG_OUT        dolog ("%s is full %d\n", sw->name, live);#endif        return 0;    }    wpos = (sw->hw->rpos + live) % hwsamples;    samples = size >> sw->info.shift;    dead = hwsamples - live;    swlim = ((int64_t) dead << 32) / sw->ratio;    swlim = audio_MIN (swlim, samples);    if (swlim) {        sw->conv (sw->buf, buf, swlim, &sw->vol);    }    while (swlim) {        dead = hwsamples - live;        left = hwsamples - wpos;        blck = audio_MIN (dead, left);        if (!blck) {            break;        }        isamp = swlim;        osamp = blck;        st_rate_flow_mix (            sw->rate,            sw->buf + pos,            sw->hw->mix_buf + wpos,            &isamp,            &osamp            );        ret += isamp;        swlim -= isamp;        pos += isamp;        live += osamp;        wpos = (wpos + osamp) % hwsamples;        total += osamp;    }    sw->total_hw_samples_mixed += total;    sw->empty = sw->total_hw_samples_mixed == 0;#ifdef DEBUG_OUT    dolog (        "%s: write size %d ret %d total sw %d\n",        SW_NAME (sw),        size >> sw->info.shift,        ret,        sw->total_hw_samples_mixed        );#endif    return ret << sw->info.shift;}#ifdef DEBUG_AUDIOstatic void audio_pcm_print_info (const char *cap, struct audio_pcm_info *info){    dolog ("%s: bits %d, sign %d, freq %d, nchan %d\n",           cap, info->bits, info->sign, info->freq, info->nchannels);}#endif#define DAC#include "audio_template.h"#undef DAC#include "audio_template.h"int AUD_write (SWVoiceOut *sw, void *buf, int size){    int bytes;    if (!sw) {        /* XXX: Consider options */        return size;    }    if (!sw->hw->enabled) {        dolog ("Writing to disabled voice %s\n", SW_NAME (sw));        return 0;    }    bytes = sw->hw->pcm_ops->write (sw, buf, size);    return bytes;}int AUD_read (SWVoiceIn *sw, void *buf, int size){    int bytes;    if (!sw) {        /* XXX: Consider options */        return size;    }    if (!sw->hw->enabled) {        dolog ("Reading from disabled voice %s\n", SW_NAME (sw));        return 0;    }    bytes = sw->hw->pcm_ops->read (sw, buf, size);    return bytes;}int AUD_get_buffer_size_out (SWVoiceOut *sw){    return sw->hw->samples << sw->hw->info.shift;}void AUD_set_active_out (SWVoiceOut *sw, int on){    HWVoiceOut *hw;    if (!sw) {        return;    }    hw = sw->hw;    if (sw->active != on) {        SWVoiceOut *temp_sw;        SWVoiceCap *sc;        if (on) {            hw->pending_disable = 0;            if (!hw->enabled) {                hw->enabled = 1;                hw->pcm_ops->ctl_out (hw, VOICE_ENABLE);            }        }        else {            if (hw->enabled) {                int nb_active = 0;                for (temp_sw = hw->sw_head.lh_first; temp_sw;                     temp_sw = temp_sw->entries.le_next) {                    nb_active += temp_sw->active != 0;                }                hw->pending_disable = nb_active == 1;            }        }        for (sc = hw->cap_head.lh_first; sc; sc = sc->entries.le_next) {            sc->sw.active = hw->enabled;            if (hw->enabled) {                audio_capture_maybe_changed (sc->cap, 1);            }        }        sw->active = on;    }}void AUD_set_active_in (SWVoiceIn *sw, int on){    HWVoiceIn *hw;    if (!sw) {        return;    }    hw = sw->hw;    if (sw->active != on) {        SWVoiceIn *temp_sw;        if (on) {            if (!hw->enabled) {                hw->enabled = 1;                hw->pcm_ops->ctl_in (hw, VOICE_ENABLE);            }            sw->total_hw_samples_acquired = hw->total_samples_captured;        }        else {            if (hw->enabled) {                int nb_active = 0;                for (temp_sw = hw->sw_head.lh_first; temp_sw;                     temp_sw = temp_sw->entries.le_next) {                    nb_active += temp_sw->active != 0;                }                if (nb_active == 1) {                    hw->enabled = 0;                    hw->pcm_ops->ctl_in (hw, VOICE_DISABLE);                }            }        }        sw->active = on;    }}static int audio_get_avail (SWVoiceIn *sw){    int live;    if (!sw) {        return 0;    }    live = sw->hw->total_samples_captured - sw->total_hw_samples_acquired;    if (audio_bug (AUDIO_FUNC, live < 0 || live > sw->hw->samples)) {        dolog ("live=%d sw->hw->samples=%d\n", live, sw->hw->samples);        return 0;    }    ldebug (        "%s: get_avail live %d ret %" PRId64 "\n",        SW_NAME (sw),        live, (((int64_t) live << 32) / sw->ratio) << sw->info.shift        );    return (((int64_t) live << 32) / sw->ratio) << sw->info.shift;}static int audio_get_free (SWVoiceOut *sw){    int live, dead;    if (!sw) {        return 0;    }    live = sw->total_hw_samples_mixed;    if (audio_bug (AUDIO_FUNC, live < 0 || live > sw->hw->samples)) {        dolog ("live=%d sw->hw->samples=%d\n", live, sw->hw->samples);        return 0;    }    dead = sw->hw->samples - live;#ifdef DEBUG_OUT    dolog ("%s: get_free live %d dead %d ret %" PRId64 "\n",           SW_NAME (sw),           live, dead, (((int64_t) dead << 32) / sw->ratio) << sw->info.shift);#endif    return (((int64_t) dead << 32) / sw->ratio) << sw->info.shift;}static void audio_capture_mix_and_clear (HWVoiceOut *hw, int rpos, int samples){    int n;    if (hw->enabled) {        SWVoiceCap *sc;        for (sc = hw->cap_head.lh_first; sc; sc = sc->entries.le_next) {            SWVoiceOut *sw = &sc->sw;            int rpos2 = rpos;            n = samples;            while (n) {                int till_end_of_hw = hw->samples - rpos2;                int to_write = audio_MIN (till_end_of_hw, n);                int bytes = to_write << hw->info.shift;                int written;                sw->buf = hw->mix_buf + rpos2;                written = audio_pcm_sw_write (sw, NULL, bytes);                if (written - bytes) {                    dolog ("Could not mix %d bytes into a capture "                           "buffer, mixed %d\n",                           bytes, written);                    break;                }                n -= to_write;                rpos2 = (rpos2 + to_write) % hw->samples;            }        }    }    n = audio_MIN (samples, hw->samples - rpos);    mixeng_clear (hw->mix_buf + rpos, n);    mixeng_clear (hw->mix_buf, samples - n);}static void audio_run_out (AudioState *s){    HWVoiceOut *hw = NULL;    SWVoiceOut *sw;    while ((hw = audio_pcm_hw_find_any_enabled_out (s, hw))) {        int played;        int live, free, nb_live, cleanup_required, prev_rpos;        live = audio_pcm_hw_get_live_out2 (hw, &nb_live);        if (!nb_live) {            live = 0;        }        if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) {            dolog ("live=%d hw->samples=%d\n", live, hw->samples);            continue;        }        if (hw->pending_disable && !nb_live) {            SWVoiceCap *sc;#ifdef DEBUG_OUT            dolog ("Disabling voice\n");#endif            hw->enabled = 0;            hw->pending_disable = 0;            hw->pcm_ops->ctl_out (hw, VOICE_DISABLE);            for (sc = hw->cap_head.lh_first; sc; sc = sc->entries.le_next) {                sc->sw.active = 0;                audio_recalc_and_notify_capture (sc->cap);            }            continue;        }        if (!live) {            for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {                if (sw->active) {                    free = audio_get_free (sw);                    if (free > 0) {                        sw->callback.fn (sw->callback.opaque, free);                    }                }            }            continue;        }        prev_rpos = hw->rpos;        played = hw->pcm_ops->run_out (hw);        if (audio_bug (AUDIO_FUNC, hw->rpos >= hw->samples)) {            dolog ("hw->rpos=%d hw->samples=%d played=%d\n",                   hw->rpos, hw->samples, played);            hw->rpos = 0;        }#ifdef DEBUG_OUT        dolog ("played=%d\n", played);#endif        if (played) {            hw->ts_helper += played;            audio_capture_mix_and_clear (hw, prev_rpos, played);        }        cleanup_required = 0;        for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {            if (!sw->active && sw->empty) {                continue;            }            if (audio_bug (AUDIO_FUNC, played > sw->total_hw_samples_mixed)) {                dolog ("played=%d sw->total_hw_samples_mixed=%d\n",                       played, sw->total_hw_samples_mixed);                played = sw->total_hw_samples_mixed;            }            sw->total_hw_samples_mixed -= played;            if (!sw->total_hw_samples_mixed) {                sw->empty = 1;                cleanup_required |= !sw->active && !sw->callback.fn;            }            if (sw->active) {                free = audio_get_free (sw);                if (free > 0) {                    sw->callback.fn (sw->callback.opaque, free);                }            }        }        if (cleanup_required) {            SWVoiceOut *sw1;            sw = hw->sw_head.lh_first;            while (sw) {                sw1 = sw->entries.le_next;                if (!sw->active && !sw->callback.fn) {#ifdef DEBUG_PLIVE                    dolog ("Finishing with old voice\n");#endif                    audio_close_out (s, sw);                }                sw = sw1;            }        }    }}static void audio_run_in (AudioState *s){    HWVoiceIn *hw = NULL;    while ((hw = audio_pcm_hw_find_any_enabled_in (s, hw))) {        SWVoiceIn *sw;        int captured, min;        captured = hw->pcm_ops->run_in (hw);        min = audio_pcm_hw_find_min_in (hw);        hw->total_samples_captured += captured - min;        hw->ts_helper += captured;        for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {            sw->total_hw_samples_acquired -= min;            if (sw->active) {                int avail;                avail = audio_get_avail (sw);                if (avail > 0) {                    sw->callback.fn (sw->callback.opaque, avail);                }            }        }    }}static void audio_run_capture (AudioState *s){    CaptureVoiceOut *cap;    for (cap = s->cap_head.lh_first; cap; cap = cap->entries.le_next) {        int live, rpos, captured;        HWVoiceOut *hw = &cap->hw;        SWVoiceOut *sw;        captured = live = audio_pcm_hw_get_live_out (hw);        rpos = hw->rpos;        while (live) {            int left = hw->samples - rpos;            int to_capture = audio_MIN (live, left);            st_sample_t *src;            struct capture_callback *cb;            src = hw->mix_buf + rpos;            hw->clip (cap->buf, src, to_capture);            mixeng_clear (src, to_capture);            for (cb = cap->cb_head.lh_first; cb; cb = cb->entries.le_next) {                cb->ops.capture (cb->opaque, cap->buf,                                 to_capture << hw->info.shift);            }            rpos = (rpos + to_capture) % hw->samples;            live -= to_capture;        }        hw->rpos = rpos;        for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {            if (!sw->active && sw->empty) {                continue;            }            if (audio_bug (AUDIO_FUNC, captured > sw->total_hw_samples_mixed)) {                dolog ("captured=%d sw->total_hw_samples_mixed=%d\n",                       captured, sw->total_hw_samples_mixed);                captured = sw->total_hw_samples_mixed;            }            sw->total_hw_samples_mixed -= captured;            sw->empty = sw->total_hw_samples_mixed == 0;        }    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -