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

📄 audio.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 4 页
字号:
        strcat (optname, opt->name);        def = 1;        switch (opt->tag) {        case AUD_OPT_BOOL:        case AUD_OPT_INT:            {                int *intp = opt->valp;                *intp = audio_get_conf_int (optname, *intp, &def);            }            break;        case AUD_OPT_FMT:            {                audfmt_e *fmtp = opt->valp;                *fmtp = audio_get_conf_fmt (optname, *fmtp, &def);            }            break;        case AUD_OPT_STR:            {                const char **strp = opt->valp;                *strp = audio_get_conf_str (optname, *strp, &def);            }            break;        default:            dolog ("Bad value tag for option `%s' - %d\n",                   optname, opt->tag);            break;        }        if (!opt->overriddenp) {            opt->overriddenp = &opt->overridden;        }        *opt->overriddenp = !def;        qemu_free (optname);    }}static void audio_print_settings (audsettings_t *as){    dolog ("frequency=%d nchannels=%d fmt=", as->freq, as->nchannels);    switch (as->fmt) {    case AUD_FMT_S8:        AUD_log (NULL, "S8");        break;    case AUD_FMT_U8:        AUD_log (NULL, "U8");        break;    case AUD_FMT_S16:        AUD_log (NULL, "S16");        break;    case AUD_FMT_U16:        AUD_log (NULL, "U16");        break;    default:        AUD_log (NULL, "invalid(%d)", as->fmt);        break;    }    AUD_log (NULL, " endianness=");    switch (as->endianness) {    case 0:        AUD_log (NULL, "little");        break;    case 1:        AUD_log (NULL, "big");        break;    default:        AUD_log (NULL, "invalid");        break;    }    AUD_log (NULL, "\n");}static int audio_validate_settings (audsettings_t *as){    int invalid;    invalid = as->nchannels != 1 && as->nchannels != 2;    invalid |= as->endianness != 0 && as->endianness != 1;    switch (as->fmt) {    case AUD_FMT_S8:    case AUD_FMT_U8:    case AUD_FMT_S16:    case AUD_FMT_U16:    case AUD_FMT_S32:    case AUD_FMT_U32:        break;    default:        invalid = 1;        break;    }    invalid |= as->freq <= 0;    return invalid ? -1 : 0;}static int audio_pcm_info_eq (struct audio_pcm_info *info, audsettings_t *as){    int bits = 8, sign = 0;    switch (as->fmt) {    case AUD_FMT_S8:        sign = 1;    case AUD_FMT_U8:        break;    case AUD_FMT_S16:        sign = 1;    case AUD_FMT_U16:        bits = 16;        break;    case AUD_FMT_S32:        sign = 1;    case AUD_FMT_U32:        bits = 32;        break;    }    return info->freq == as->freq        && info->nchannels == as->nchannels        && info->sign == sign        && info->bits == bits        && info->swap_endianness == (as->endianness != AUDIO_HOST_ENDIANNESS);}void audio_pcm_init_info (struct audio_pcm_info *info, audsettings_t *as){    int bits = 8, sign = 0, shift = 0;    switch (as->fmt) {    case AUD_FMT_S8:        sign = 1;    case AUD_FMT_U8:        break;    case AUD_FMT_S16:        sign = 1;    case AUD_FMT_U16:        bits = 16;        shift = 1;        break;    case AUD_FMT_S32:        sign = 1;    case AUD_FMT_U32:        bits = 32;        shift = 2;        break;    }    info->freq = as->freq;    info->bits = bits;    info->sign = sign;    info->nchannels = as->nchannels;    info->shift = (as->nchannels == 2) + shift;    info->align = (1 << info->shift) - 1;    info->bytes_per_second = info->freq << info->shift;    info->swap_endianness = (as->endianness != AUDIO_HOST_ENDIANNESS);}void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len){    if (!len) {        return;    }    if (info->sign) {        memset (buf, 0x00, len << info->shift);    }    else {        switch (info->bits) {        case 8:            memset (buf, 0x80, len << info->shift);            break;        case 16:            {                int i;                uint16_t *p = buf;                int shift = info->nchannels - 1;                short s = INT16_MAX;                if (info->swap_endianness) {                    s = bswap16 (s);                }                for (i = 0; i < len << shift; i++) {                    p[i] = s;                }            }            break;        case 32:            {                int i;                uint32_t *p = buf;                int shift = info->nchannels - 1;                int32_t s = INT32_MAX;                if (info->swap_endianness) {                    s = bswap32 (s);                }                for (i = 0; i < len << shift; i++) {                    p[i] = s;                }            }            break;        default:            AUD_log (NULL, "audio_pcm_info_clear_buf: invalid bits %d\n",                     info->bits);            break;        }    }}/* * Capture */static void noop_conv (st_sample_t *dst, const void *src,                       int samples, volume_t *vol){    (void) src;    (void) dst;    (void) samples;    (void) vol;}static CaptureVoiceOut *audio_pcm_capture_find_specific (    AudioState *s,    audsettings_t *as    ){    CaptureVoiceOut *cap;    for (cap = s->cap_head.lh_first; cap; cap = cap->entries.le_next) {        if (audio_pcm_info_eq (&cap->hw.info, as)) {            return cap;        }    }    return NULL;}static void audio_notify_capture (CaptureVoiceOut *cap, audcnotification_e cmd){    struct capture_callback *cb;#ifdef DEBUG_CAPTURE    dolog ("notification %d sent\n", cmd);#endif    for (cb = cap->cb_head.lh_first; cb; cb = cb->entries.le_next) {        cb->ops.notify (cb->opaque, cmd);    }}static void audio_capture_maybe_changed (CaptureVoiceOut *cap, int enabled){    if (cap->hw.enabled != enabled) {        audcnotification_e cmd;        cap->hw.enabled = enabled;        cmd = enabled ? AUD_CNOTIFY_ENABLE : AUD_CNOTIFY_DISABLE;        audio_notify_capture (cap, cmd);    }}static void audio_recalc_and_notify_capture (CaptureVoiceOut *cap){    HWVoiceOut *hw = &cap->hw;    SWVoiceOut *sw;    int enabled = 0;    for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {        if (sw->active) {            enabled = 1;            break;        }    }    audio_capture_maybe_changed (cap, enabled);}static void audio_detach_capture (HWVoiceOut *hw){    SWVoiceCap *sc = hw->cap_head.lh_first;    while (sc) {        SWVoiceCap *sc1 = sc->entries.le_next;        SWVoiceOut *sw = &sc->sw;        CaptureVoiceOut *cap = sc->cap;        int was_active = sw->active;        if (sw->rate) {            st_rate_stop (sw->rate);            sw->rate = NULL;        }        LIST_REMOVE (sw, entries);        LIST_REMOVE (sc, entries);        qemu_free (sc);        if (was_active) {            /* We have removed soft voice from the capture:               this might have changed the overall status of the capture               since this might have been the only active voice */            audio_recalc_and_notify_capture (cap);        }        sc = sc1;    }}static int audio_attach_capture (AudioState *s, HWVoiceOut *hw){    CaptureVoiceOut *cap;    audio_detach_capture (hw);    for (cap = s->cap_head.lh_first; cap; cap = cap->entries.le_next) {        SWVoiceCap *sc;        SWVoiceOut *sw;        HWVoiceOut *hw_cap = &cap->hw;        sc = audio_calloc (AUDIO_FUNC, 1, sizeof (*sc));        if (!sc) {            dolog ("Could not allocate soft capture voice (%zu bytes)\n",                   sizeof (*sc));            return -1;        }        sc->cap = cap;        sw = &sc->sw;        sw->hw = hw_cap;        sw->info = hw->info;        sw->empty = 1;        sw->active = hw->enabled;        sw->conv = noop_conv;        sw->ratio = ((int64_t) hw_cap->info.freq << 32) / sw->info.freq;        sw->rate = st_rate_start (sw->info.freq, hw_cap->info.freq);        if (!sw->rate) {            dolog ("Could not start rate conversion for `%s'\n", SW_NAME (sw));            qemu_free (sw);            return -1;        }        LIST_INSERT_HEAD (&hw_cap->sw_head, sw, entries);        LIST_INSERT_HEAD (&hw->cap_head, sc, entries);#ifdef DEBUG_CAPTURE        asprintf (&sw->name, "for %p %d,%d,%d",                  hw, sw->info.freq, sw->info.bits, sw->info.nchannels);        dolog ("Added %s active = %d\n", sw->name, sw->active);#endif        if (sw->active) {            audio_capture_maybe_changed (cap, 1);        }    }    return 0;}/* * Hard voice (capture) */static int audio_pcm_hw_find_min_in (HWVoiceIn *hw){    SWVoiceIn *sw;    int m = hw->total_samples_captured;    for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {        if (sw->active) {            m = audio_MIN (m, sw->total_hw_samples_acquired);        }    }    return m;}int audio_pcm_hw_get_live_in (HWVoiceIn *hw){    int live = hw->total_samples_captured - audio_pcm_hw_find_min_in (hw);    if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) {        dolog ("live=%d hw->samples=%d\n", live, hw->samples);        return 0;    }    return live;}/* * Soft voice (capture) */static int audio_pcm_sw_get_rpos_in (SWVoiceIn *sw){    HWVoiceIn *hw = sw->hw;    int live = hw->total_samples_captured - sw->total_hw_samples_acquired;    int rpos;    if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) {        dolog ("live=%d hw->samples=%d\n", live, hw->samples);        return 0;    }    rpos = hw->wpos - live;    if (rpos >= 0) {        return rpos;    }    else {        return hw->samples + rpos;    }}int audio_pcm_sw_read (SWVoiceIn *sw, void *buf, int size){    HWVoiceIn *hw = sw->hw;    int samples, live, ret = 0, swlim, isamp, osamp, rpos, total = 0;    st_sample_t *src, *dst = sw->buf;    rpos = audio_pcm_sw_get_rpos_in (sw) % hw->samples;    live = hw->total_samples_captured - sw->total_hw_samples_acquired;    if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) {        dolog ("live_in=%d hw->samples=%d\n", live, hw->samples);        return 0;    }    samples = size >> sw->info.shift;    if (!live) {        return 0;    }    swlim = (live * sw->ratio) >> 32;    swlim = audio_MIN (swlim, samples);    while (swlim) {        src = hw->conv_buf + rpos;        isamp = hw->wpos - rpos;        /* XXX: <= ? */        if (isamp <= 0) {            isamp = hw->samples - rpos;        }        if (!isamp) {            break;        }        osamp = swlim;        if (audio_bug (AUDIO_FUNC, osamp < 0)) {            dolog ("osamp=%d\n", osamp);            return 0;        }        st_rate_flow (sw->rate, src, dst, &isamp, &osamp);        swlim -= osamp;        rpos = (rpos + isamp) % hw->samples;        dst += osamp;        ret += osamp;        total += isamp;    }    sw->clip (buf, sw->buf, ret);    sw->total_hw_samples_acquired += total;    return ret << sw->info.shift;}/* * Hard voice (playback) */static int audio_pcm_hw_find_min_out (HWVoiceOut *hw, int *nb_livep){    SWVoiceOut *sw;    int m = INT_MAX;    int nb_live = 0;    for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {        if (sw->active || !sw->empty) {            m = audio_MIN (m, sw->total_hw_samples_mixed);            nb_live += 1;        }    }    *nb_livep = nb_live;    return m;}int audio_pcm_hw_get_live_out2 (HWVoiceOut *hw, int *nb_live){    int smin;    smin = audio_pcm_hw_find_min_out (hw, nb_live);    if (!*nb_live) {        return 0;    }    else {        int live = smin;        if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) {

⌨️ 快捷键说明

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