Commit e9d42461 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/kraxel/tags/audio-20191018-pull-request' into staging



audio: bugfixes, pa connection and stream naming.
audio: 5.1/7.1 support for alsa, pa and usb-audio.

# gpg: Signature made Fri 18 Oct 2019 08:41:26 BST
# gpg:                using RSA key 4CB6D8EED3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>" [full]
# gpg:                 aka "Gerd Hoffmann <gerd@kraxel.org>" [full]
# gpg:                 aka "Gerd Hoffmann (private) <kraxel@gmail.com>" [full]
# Primary key fingerprint: A032 8CFF B93A 17A7 9901  FE7D 4CB6 D8EE D3E8 7138

* remotes/kraxel/tags/audio-20191018-pull-request:
  paaudio: fix channel order for usb-audio 5.1 and 7.1 streams
  usbaudio: change playback counters to 64 bit
  usb-audio: support more than two channels of audio
  usb-audio: do not count on avail bytes actually available
  audio: basic support for multichannel audio
  audio: replace shift in audio_pcm_info with bytes_per_frame
  audio: support more than two channels in volume setting
  paaudio: get/put_buffer functions
  audio: make mixeng optional
  audio: add mixing-engine option (documentation)
  audio: paaudio: ability to specify stream name
  audio: paaudio: fix connection and stream name
  audio: fix parameter dereference before NULL check

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents ca32646d 0cf13e36
Loading
Loading
Loading
Loading
+6 −12
Original line number Diff line number Diff line
@@ -493,13 +493,6 @@ static int alsa_open(bool in, struct alsa_params_req *req,
        goto err;
    }

    if (nchannels != 1 && nchannels != 2) {
        alsa_logerr2 (err, typ,
                      "Can not handle obtained number of channels %d\n",
                      nchannels);
        goto err;
    }

    if (apdo->buffer_length) {
        int dir = 0;
        unsigned int btime = apdo->buffer_length;
@@ -602,7 +595,7 @@ static size_t alsa_write(HWVoiceOut *hw, void *buf, size_t len)
{
    ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
    size_t pos = 0;
    size_t len_frames = len >> hw->info.shift;
    size_t len_frames = len / hw->info.bytes_per_frame;

    while (len_frames) {
        char *src = advance(buf, pos);
@@ -648,7 +641,7 @@ static size_t alsa_write(HWVoiceOut *hw, void *buf, size_t len)
            }
        }

        pos += written << hw->info.shift;
        pos += written * hw->info.bytes_per_frame;
        if (written < len_frames) {
            break;
        }
@@ -802,7 +795,8 @@ static size_t alsa_read(HWVoiceIn *hw, void *buf, size_t len)
        void *dst = advance(buf, pos);
        snd_pcm_sframes_t nread;

        nread = snd_pcm_readi(alsa->handle, dst, len >> hw->info.shift);
        nread = snd_pcm_readi(
            alsa->handle, dst, len / hw->info.bytes_per_frame);

        if (nread <= 0) {
            switch (nread) {
@@ -828,8 +822,8 @@ static size_t alsa_read(HWVoiceIn *hw, void *buf, size_t len)
            }
        }

        pos += nread << hw->info.shift;
        len -= nread << hw->info.shift;
        pos += nread * hw->info.bytes_per_frame;
        len -= nread * hw->info.bytes_per_frame;
    }

    return pos;
+124 −52
Original line number Diff line number Diff line
@@ -242,7 +242,7 @@ static int audio_validate_settings (struct audsettings *as)
{
    int invalid;

    invalid = as->nchannels != 1 && as->nchannels != 2;
    invalid = as->nchannels < 1;
    invalid |= as->endianness != 0 && as->endianness != 1;

    switch (as->fmt) {
@@ -299,12 +299,13 @@ static int audio_pcm_info_eq (struct audio_pcm_info *info, struct audsettings *a

void audio_pcm_init_info (struct audio_pcm_info *info, struct audsettings *as)
{
    int bits = 8, sign = 0, shift = 0;
    int bits = 8, sign = 0, mul;

    switch (as->fmt) {
    case AUDIO_FORMAT_S8:
        sign = 1;
    case AUDIO_FORMAT_U8:
        mul = 1;
        break;

    case AUDIO_FORMAT_S16:
@@ -312,7 +313,7 @@ void audio_pcm_init_info (struct audio_pcm_info *info, struct audsettings *as)
        /* fall through */
    case AUDIO_FORMAT_U16:
        bits = 16;
        shift = 1;
        mul = 2;
        break;

    case AUDIO_FORMAT_S32:
@@ -320,7 +321,7 @@ void audio_pcm_init_info (struct audio_pcm_info *info, struct audsettings *as)
        /* fall through */
    case AUDIO_FORMAT_U32:
        bits = 32;
        shift = 2;
        mul = 4;
        break;

    default:
@@ -331,9 +332,8 @@ void audio_pcm_init_info (struct audio_pcm_info *info, struct audsettings *as)
    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->bytes_per_frame = as->nchannels * mul;
    info->bytes_per_second = info->freq * info->bytes_per_frame;
    info->swap_endianness = (as->endianness != AUDIO_HOST_ENDIANNESS);
}

@@ -344,26 +344,25 @@ void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len)
    }

    if (info->sign) {
        memset (buf, 0x00, len << info->shift);
        memset(buf, 0x00, len * info->bytes_per_frame);
    }
    else {
        switch (info->bits) {
        case 8:
            memset (buf, 0x80, len << info->shift);
            memset(buf, 0x80, len * info->bytes_per_frame);
            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++) {
                for (i = 0; i < len * info->nchannels; i++) {
                    p[i] = s;
                }
            }
@@ -373,14 +372,13 @@ void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len)
            {
                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++) {
                for (i = 0; i < len * info->nchannels; i++) {
                    p[i] = s;
                }
            }
@@ -558,7 +556,7 @@ static void audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, size_t len)

    while (len) {
        st_sample *src = hw->mix_buf->samples + pos;
        uint8_t *dst = advance(pcm_buf, clipped << hw->info.shift);
        uint8_t *dst = advance(pcm_buf, clipped * hw->info.bytes_per_frame);
        size_t samples_till_end_of_buf = hw->mix_buf->size - pos;
        size_t samples_to_clip = MIN(len, samples_till_end_of_buf);

@@ -607,7 +605,7 @@ static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, size_t size)
        return 0;
    }

    samples = size >> sw->info.shift;
    samples = size / sw->info.bytes_per_frame;
    if (!live) {
        return 0;
    }
@@ -642,7 +640,7 @@ static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, size_t size)

    sw->clip (buf, sw->buf, ret);
    sw->total_hw_samples_acquired += total;
    return ret << sw->info.shift;
    return ret * sw->info.bytes_per_frame;
}

/*
@@ -715,7 +713,7 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t size)
    }

    wpos = (sw->hw->mix_buf->pos + live) % hwsamples;
    samples = size >> sw->info.shift;
    samples = size / sw->info.bytes_per_frame;

    dead = hwsamples - live;
    swlim = ((int64_t) dead << 32) / sw->ratio;
@@ -759,13 +757,13 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t size)
    dolog (
        "%s: write size %zu ret %zu total sw %zu\n",
        SW_NAME (sw),
        size >> sw->info.shift,
        size / sw->info.bytes_per_frame,
        ret,
        sw->total_hw_samples_mixed
        );
#endif

    return ret << sw->info.shift;
    return ret * sw->info.bytes_per_frame;
}

#ifdef DEBUG_AUDIO
@@ -838,37 +836,51 @@ static void audio_timer (void *opaque)
 */
size_t AUD_write(SWVoiceOut *sw, void *buf, size_t size)
{
    HWVoiceOut *hw;

    if (!sw) {
        /* XXX: Consider options */
        return size;
    }
    hw = sw->hw;

    if (!sw->hw->enabled) {
    if (!hw->enabled) {
        dolog ("Writing to disabled voice %s\n", SW_NAME (sw));
        return 0;
    }

    if (audio_get_pdo_out(hw->s->dev)->mixing_engine) {
        return audio_pcm_sw_write(sw, buf, size);
    } else {
        return hw->pcm_ops->write(hw, buf, size);
    }
}

size_t AUD_read(SWVoiceIn *sw, void *buf, size_t size)
{
    HWVoiceIn *hw;

    if (!sw) {
        /* XXX: Consider options */
        return size;
    }
    hw = sw->hw;

    if (!sw->hw->enabled) {
    if (!hw->enabled) {
        dolog ("Reading from disabled voice %s\n", SW_NAME (sw));
        return 0;
    }

    if (audio_get_pdo_in(hw->s->dev)->mixing_engine) {
        return audio_pcm_sw_read(sw, buf, size);
    } else {
        return hw->pcm_ops->read(hw, buf, size);
    }
}

int AUD_get_buffer_size_out (SWVoiceOut *sw)
{
    return sw->hw->mix_buf->size << sw->hw->info.shift;
    return sw->hw->mix_buf->size * sw->hw->info.bytes_per_frame;
}

void AUD_set_active_out (SWVoiceOut *sw, int on)
@@ -984,10 +996,10 @@ static size_t audio_get_avail (SWVoiceIn *sw)
    ldebug (
        "%s: get_avail live %d ret %" PRId64 "\n",
        SW_NAME (sw),
        live, (((int64_t) live << 32) / sw->ratio) << sw->info.shift
        live, (((int64_t) live << 32) / sw->ratio) * sw->info.bytes_per_frame
        );

    return (((int64_t) live << 32) / sw->ratio) << sw->info.shift;
    return (((int64_t) live << 32) / sw->ratio) * sw->info.bytes_per_frame;
}

static size_t audio_get_free(SWVoiceOut *sw)
@@ -1011,10 +1023,11 @@ static size_t audio_get_free(SWVoiceOut *sw)
#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);
           live, dead, (((int64_t) dead << 32) / sw->ratio) *
           sw->info.bytes_per_frame);
#endif

    return (((int64_t) dead << 32) / sw->ratio) << sw->info.shift;
    return (((int64_t) dead << 32) / sw->ratio) * sw->info.bytes_per_frame;
}

static void audio_capture_mix_and_clear(HWVoiceOut *hw, size_t rpos,
@@ -1033,7 +1046,7 @@ static void audio_capture_mix_and_clear(HWVoiceOut *hw, size_t rpos,
            while (n) {
                size_t till_end_of_hw = hw->mix_buf->size - rpos2;
                size_t to_write = MIN(till_end_of_hw, n);
                size_t bytes = to_write << hw->info.shift;
                size_t bytes = to_write * hw->info.bytes_per_frame;
                size_t written;

                sw->buf = hw->mix_buf->samples + rpos2;
@@ -1068,10 +1081,11 @@ static size_t audio_pcm_hw_run_out(HWVoiceOut *hw, size_t live)
            return clipped + live;
        }

        decr = MIN(size >> hw->info.shift, live);
        decr = MIN(size / hw->info.bytes_per_frame, live);
        audio_pcm_hw_clip_out(hw, buf, decr);
        proc = hw->pcm_ops->put_buffer_out(hw, buf, decr << hw->info.shift) >>
            hw->info.shift;
        proc = hw->pcm_ops->put_buffer_out(hw, buf,
                                           decr * hw->info.bytes_per_frame) /
            hw->info.bytes_per_frame;

        live -= proc;
        clipped += proc;
@@ -1090,6 +1104,26 @@ static void audio_run_out (AudioState *s)
    HWVoiceOut *hw = NULL;
    SWVoiceOut *sw;

    if (!audio_get_pdo_out(s->dev)->mixing_engine) {
        while ((hw = audio_pcm_hw_find_any_enabled_out(s, hw))) {
            /* there is exactly 1 sw for each hw with no mixeng */
            sw = hw->sw_head.lh_first;

            if (hw->pending_disable) {
                hw->enabled = 0;
                hw->pending_disable = 0;
                if (hw->pcm_ops->enable_out) {
                    hw->pcm_ops->enable_out(hw, false);
                }
            }

            if (sw->active) {
                sw->callback.fn(sw->callback.opaque, INT_MAX);
            }
        }
        return;
    }

    while ((hw = audio_pcm_hw_find_any_enabled_out(s, hw))) {
        size_t played, live, prev_rpos, free;
        int nb_live, cleanup_required;
@@ -1200,16 +1234,16 @@ static size_t audio_pcm_hw_run_in(HWVoiceIn *hw, size_t samples)

    while (samples) {
        size_t proc;
        size_t size = samples << hw->info.shift;
        size_t size = samples * hw->info.bytes_per_frame;
        void *buf = hw->pcm_ops->get_buffer_in(hw, &size);

        assert((size & hw->info.align) == 0);
        assert(size % hw->info.bytes_per_frame == 0);
        if (size == 0) {
            hw->pcm_ops->put_buffer_in(hw, buf, size);
            break;
        }

        proc = MIN(size >> hw->info.shift,
        proc = MIN(size / hw->info.bytes_per_frame,
                   conv_buf->size - conv_buf->pos);

        hw->conv(conv_buf->samples + conv_buf->pos, buf, proc);
@@ -1217,7 +1251,7 @@ static size_t audio_pcm_hw_run_in(HWVoiceIn *hw, size_t samples)

        samples -= proc;
        conv += proc;
        hw->pcm_ops->put_buffer_in(hw, buf, proc << hw->info.shift);
        hw->pcm_ops->put_buffer_in(hw, buf, proc * hw->info.bytes_per_frame);
    }

    return conv;
@@ -1227,6 +1261,17 @@ static void audio_run_in (AudioState *s)
{
    HWVoiceIn *hw = NULL;

    if (!audio_get_pdo_in(s->dev)->mixing_engine) {
        while ((hw = audio_pcm_hw_find_any_enabled_in(s, hw))) {
            /* there is exactly 1 sw for each hw with no mixeng */
            SWVoiceIn *sw = hw->sw_head.lh_first;
            if (sw->active) {
                sw->callback.fn(sw->callback.opaque, INT_MAX);
            }
        }
        return;
    }

    while ((hw = audio_pcm_hw_find_any_enabled_in(s, hw))) {
        SWVoiceIn *sw;
        size_t captured = 0, min;
@@ -1280,7 +1325,7 @@ static void audio_run_capture (AudioState *s)

            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);
                                 to_capture * hw->info.bytes_per_frame);
            }
            rpos = (rpos + to_capture) % hw->mix_buf->size;
            live -= to_capture;
@@ -1333,7 +1378,7 @@ void *audio_generic_get_buffer_in(HWVoiceIn *hw, size_t *size)
    ssize_t start;

    if (unlikely(!hw->buf_emul)) {
        size_t calc_size = hw->conv_buf->size << hw->info.shift;
        size_t calc_size = hw->conv_buf->size * hw->info.bytes_per_frame;
        hw->buf_emul = g_malloc(calc_size);
        hw->size_emul = calc_size;
        hw->pos_emul = hw->pending_emul = 0;
@@ -1369,7 +1414,7 @@ void audio_generic_put_buffer_in(HWVoiceIn *hw, void *buf, size_t size)
void *audio_generic_get_buffer_out(HWVoiceOut *hw, size_t *size)
{
    if (unlikely(!hw->buf_emul)) {
        size_t calc_size = hw->mix_buf->size << hw->info.shift;
        size_t calc_size = hw->mix_buf->size * hw->info.bytes_per_frame;

        hw->buf_emul = g_malloc(calc_size);
        hw->size_emul = calc_size;
@@ -1751,6 +1796,11 @@ CaptureVoiceOut *AUD_add_capture(
        s = audio_init(NULL, NULL);
    }

    if (!audio_get_pdo_out(s->dev)->mixing_engine) {
        dolog("Can't capture with mixeng disabled\n");
        return NULL;
    }

    if (audio_validate_settings (as)) {
        dolog ("Invalid settings were passed when trying to add capture\n");
        audio_print_settings (as);
@@ -1783,7 +1833,7 @@ CaptureVoiceOut *AUD_add_capture(

        audio_pcm_init_info (&hw->info, as);

        cap->buf = g_malloc0_n(hw->mix_buf->size, 1 << hw->info.shift);
        cap->buf = g_malloc0_n(hw->mix_buf->size, hw->info.bytes_per_frame);

        hw->clip = mixeng_clip
            [hw->info.nchannels == 2]
@@ -1841,31 +1891,45 @@ void AUD_del_capture (CaptureVoiceOut *cap, void *cb_opaque)
}

void AUD_set_volume_out (SWVoiceOut *sw, int mute, uint8_t lvol, uint8_t rvol)
{
    Volume vol = { .mute = mute, .channels = 2, .vol = { lvol, rvol } };
    audio_set_volume_out(sw, &vol);
}

void audio_set_volume_out(SWVoiceOut *sw, Volume *vol)
{
    if (sw) {
        HWVoiceOut *hw = sw->hw;

        sw->vol.mute = mute;
        sw->vol.l = nominal_volume.l * lvol / 255;
        sw->vol.r = nominal_volume.r * rvol / 255;
        sw->vol.mute = vol->mute;
        sw->vol.l = nominal_volume.l * vol->vol[0] / 255;
        sw->vol.r = nominal_volume.l * vol->vol[vol->channels > 1 ? 1 : 0] /
            255;

        if (hw->pcm_ops->volume_out) {
            hw->pcm_ops->volume_out(hw, &sw->vol);
            hw->pcm_ops->volume_out(hw, vol);
        }
    }
}

void AUD_set_volume_in (SWVoiceIn *sw, int mute, uint8_t lvol, uint8_t rvol)
{
    Volume vol = { .mute = mute, .channels = 2, .vol = { lvol, rvol } };
    audio_set_volume_in(sw, &vol);
}

void audio_set_volume_in(SWVoiceIn *sw, Volume *vol)
{
    if (sw) {
        HWVoiceIn *hw = sw->hw;

        sw->vol.mute = mute;
        sw->vol.l = nominal_volume.l * lvol / 255;
        sw->vol.r = nominal_volume.r * rvol / 255;
        sw->vol.mute = vol->mute;
        sw->vol.l = nominal_volume.l * vol->vol[0] / 255;
        sw->vol.r = nominal_volume.r * vol->vol[vol->channels > 1 ? 1 : 0] /
            255;

        if (hw->pcm_ops->volume_in) {
            hw->pcm_ops->volume_in(hw, &sw->vol);
            hw->pcm_ops->volume_in(hw, vol);
        }
    }
}
@@ -1905,9 +1969,13 @@ void audio_create_pdos(Audiodev *dev)
static void audio_validate_per_direction_opts(
    AudiodevPerDirectionOptions *pdo, Error **errp)
{
    if (!pdo->has_mixing_engine) {
        pdo->has_mixing_engine = true;
        pdo->mixing_engine = true;
    }
    if (!pdo->has_fixed_settings) {
        pdo->has_fixed_settings = true;
        pdo->fixed_settings = true;
        pdo->fixed_settings = pdo->mixing_engine;
    }
    if (!pdo->fixed_settings &&
        (pdo->has_frequency || pdo->has_channels || pdo->has_format)) {
@@ -1915,6 +1983,10 @@ static void audio_validate_per_direction_opts(
                   "You can't use frequency, channels or format with fixed-settings=off");
        return;
    }
    if (!pdo->mixing_engine && pdo->fixed_settings) {
        error_setg(errp, "You can't use fixed-settings without mixeng");
        return;
    }

    if (!pdo->has_frequency) {
        pdo->has_frequency = true;
@@ -1926,7 +1998,7 @@ static void audio_validate_per_direction_opts(
    }
    if (!pdo->has_voices) {
        pdo->has_voices = true;
        pdo->voices = 1;
        pdo->voices = pdo->mixing_engine ? 1 : INT_MAX;
    }
    if (!pdo->has_format) {
        pdo->has_format = true;
@@ -2081,14 +2153,14 @@ size_t audio_rate_get_bytes(struct audio_pcm_info *info, RateCtl *rate,
    now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
    ticks = now - rate->start_ticks;
    bytes = muldiv64(ticks, info->bytes_per_second, NANOSECONDS_PER_SECOND);
    samples = (bytes - rate->bytes_sent) >> info->shift;
    samples = (bytes - rate->bytes_sent) / info->bytes_per_frame;
    if (samples < 0 || samples > 65536) {
        AUD_log(NULL, "Resetting rate control (%" PRId64 " samples)\n", samples);
        audio_rate_start(rate);
        samples = 0;
    }

    ret = MIN(samples << info->shift, bytes_avail);
    ret = MIN(samples * info->bytes_per_frame, bytes_avail);
    rate->bytes_sent += ret;
    return ret;
}
+10 −0
Original line number Diff line number Diff line
@@ -124,6 +124,16 @@ uint64_t AUD_get_elapsed_usec_out (SWVoiceOut *sw, QEMUAudioTimeStamp *ts);
void AUD_set_volume_out (SWVoiceOut *sw, int mute, uint8_t lvol, uint8_t rvol);
void AUD_set_volume_in (SWVoiceIn *sw, int mute, uint8_t lvol, uint8_t rvol);

#define AUDIO_MAX_CHANNELS 16
typedef struct Volume {
    bool mute;
    int channels;
    uint8_t vol[AUDIO_MAX_CHANNELS];
} Volume;

void audio_set_volume_out(SWVoiceOut *sw, Volume *vol);
void audio_set_volume_in(SWVoiceIn *sw, Volume *vol);

SWVoiceIn *AUD_open_in (
    QEMUSoundCard *card,
    SWVoiceIn *sw,
+3 −4
Original line number Diff line number Diff line
@@ -43,8 +43,7 @@ struct audio_pcm_info {
    int sign;
    int freq;
    int nchannels;
    int align;
    int shift;
    int bytes_per_frame;
    int bytes_per_second;
    int swap_endianness;
};
@@ -166,7 +165,7 @@ struct audio_pcm_ops {
     */
    size_t (*put_buffer_out)(HWVoiceOut *hw, void *buf, size_t size);
    void   (*enable_out)(HWVoiceOut *hw, bool enable);
    void   (*volume_out)(HWVoiceOut *hw, struct mixeng_volume *vol);
    void   (*volume_out)(HWVoiceOut *hw, Volume *vol);

    int    (*init_in) (HWVoiceIn *hw, audsettings *as, void *drv_opaque);
    void   (*fini_in) (HWVoiceIn *hw);
@@ -174,7 +173,7 @@ struct audio_pcm_ops {
    void  *(*get_buffer_in)(HWVoiceIn *hw, size_t *size);
    void   (*put_buffer_in)(HWVoiceIn *hw, void *buf, size_t size);
    void   (*enable_in)(HWVoiceIn *hw, bool enable);
    void   (*volume_in)(HWVoiceIn *hw, struct mixeng_volume *vol);
    void   (*volume_in)(HWVoiceIn *hw, Volume *vol);
};

void *audio_generic_get_buffer_in(HWVoiceIn *hw, size_t *size);
+21 −10
Original line number Diff line number Diff line
@@ -78,6 +78,7 @@ static void glue (audio_pcm_hw_free_resources_, TYPE) (HW *hw)

static void glue(audio_pcm_hw_alloc_resources_, TYPE)(HW *hw)
{
    if (glue(audio_get_pdo_, TYPE)(hw->s->dev)->mixing_engine) {
        size_t samples = hw->samples;
        if (audio_bug(__func__, samples == 0)) {
            dolog("Attempted to allocate empty buffer\n");
@@ -85,6 +86,9 @@ static void glue(audio_pcm_hw_alloc_resources_, TYPE)(HW *hw)

        HWBUF = g_malloc0(sizeof(STSampleBuffer) + sizeof(st_sample) * samples);
        HWBUF->size = samples;
    } else {
        HWBUF = NULL;
    }
}

static void glue (audio_pcm_sw_free_resources_, TYPE) (SW *sw)
@@ -103,6 +107,10 @@ static int glue (audio_pcm_sw_alloc_resources_, TYPE) (SW *sw)
{
    int samples;

    if (!glue(audio_get_pdo_, TYPE)(sw->s->dev)->mixing_engine) {
        return 0;
    }

    samples = ((int64_t) sw->HWBUF->size << 32) / sw->ratio;

    sw->buf = audio_calloc(__func__, samples, sizeof(struct st_sample));
@@ -328,9 +336,9 @@ static HW *glue(audio_pcm_hw_add_, TYPE)(AudioState *s, struct audsettings *as)
    HW *hw;
    AudiodevPerDirectionOptions *pdo = glue(audio_get_pdo_, TYPE)(s->dev);

    if (pdo->fixed_settings) {
    if (!pdo->mixing_engine || pdo->fixed_settings) {
        hw = glue(audio_pcm_hw_add_new_, TYPE)(s, as);
        if (hw) {
        if (!pdo->mixing_engine || hw) {
            return hw;
        }
    }
@@ -425,8 +433,8 @@ SW *glue (AUD_open_, TYPE) (
    struct audsettings *as
    )
{
    AudioState *s = card->state;
    AudiodevPerDirectionOptions *pdo = glue(audio_get_pdo_, TYPE)(s->dev);
    AudioState *s;
    AudiodevPerDirectionOptions *pdo;

    if (audio_bug(__func__, !card || !name || !callback_fn || !as)) {
        dolog ("card=%p name=%p callback_fn=%p as=%p\n",
@@ -434,6 +442,9 @@ SW *glue (AUD_open_, TYPE) (
        goto fail;
    }

    s = card->state;
    pdo = glue(audio_get_pdo_, TYPE)(s->dev);

    ldebug ("open %s, freq %d, nchannels %d, fmt %d\n",
            name, as->freq, as->nchannels, as->fmt);

Loading