From nobody Fri Nov 7 04:14:04 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=gmail.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1545600026019631.1094336678028; Sun, 23 Dec 2018 13:20:26 -0800 (PST) Received: from localhost ([127.0.0.1]:59891 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gbBAc-00005I-I3 for importer@patchew.org; Sun, 23 Dec 2018 16:20:22 -0500 Received: from eggs.gnu.org ([208.118.235.92]:52423) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gbAk4-00083O-Oo for qemu-devel@nongnu.org; Sun, 23 Dec 2018 15:53:01 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gbAk2-0002p4-UB for qemu-devel@nongnu.org; Sun, 23 Dec 2018 15:52:56 -0500 Received: from mail-wm1-x342.google.com ([2a00:1450:4864:20::342]:36147) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1gbAk2-0002l4-Kp for qemu-devel@nongnu.org; Sun, 23 Dec 2018 15:52:54 -0500 Received: by mail-wm1-x342.google.com with SMTP id p6so10418101wmc.1 for ; Sun, 23 Dec 2018 12:52:54 -0800 (PST) Received: from nullptr.home.dirty-ice.org (2a01-036c-0113-24a3-0000-0000-0000-0005.pool6.digikabel.hu. [2a01:36c:113:24a3::5]) by smtp.gmail.com with ESMTPSA id g198sm25456920wmd.23.2018.12.23.12.52.52 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 23 Dec 2018 12:52:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Xx8jsSimDtCrlyE22EoFoyLHbKim9wAP8S82IzGMhm0=; b=GxpxeYAqRjukJkin9yYx6jB/cLQHSbGspFKgHVTLVu3IzJhZ8M4S9GLNtPlAWMIezP 8UKApOfEjNfSM7kQxtqgP2MwZHhMLeer4qzeVZa76jbclQtc2wM1xllmrzvYcYjz7GxK X/B34Td4sc0f20cgWtXY8MlMBP1ziioO+iE4y1S9Osz63whm7PnQu6tsGSw4zGvv1awF W4yKYpxH2TscY6EEUh6qvAOiwT8WBhei1aT8NiJ0urG+4hPqmMaGPLgj+YPPY97LMStE cCPXqimFUhZd9YgDGzj8OXhgABIBG9xZihV6lyHxsdYHDdy4qRHgwK9yaBSmqtD4sAhl bkKw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Xx8jsSimDtCrlyE22EoFoyLHbKim9wAP8S82IzGMhm0=; b=VWF9CKEnzT2fe0CFRSykwS83UEWJCWxDzIzkGxzw+qyC1ERMnJi0nD7eMiPAGl+NCh 93S0iM+7IOrXdZcgEtXvfTu1YS5X1ss6BG9Y3XYs0Bk9HC18jE+7TLEy/KLJcHj/RMtT d7BnTSpRJfRWn23VoJtIQbQH8EfpVg9uDM/7oSznVQ7cNXCoQESPzx1hRIeGvKmNmA4Q fx+Kx3BxdFqw+fvvtuRxQJSKVlX8U8qX63lXrvvbvSRvcptdiXX+JzFC7q3DYJjA44Fu Mo/z73DRZI4RmqXVVctwAw9ifv35afltzgxZejcwZ3JCNfveaT5GmwT2fTj5riih9qKv NYWw== X-Gm-Message-State: AJcUukf4vIL91zHQbzEhbp/KPMbFt/DKAFpHgXl/yEcmHTfR1k1I9SFA l3/D1h8eMGDxVItvqKcx6GQEbCdLn2M= X-Google-Smtp-Source: ALg8bN6KO4bvW23iPcW3LYKle/rebSFK7I6dmoeg2MyYdQOuRXK+2PePadkCxnZZgs6yhha3Mp8Avg== X-Received: by 2002:a1c:8d49:: with SMTP id p70mr10749336wmd.68.1545598373273; Sun, 23 Dec 2018 12:52:53 -0800 (PST) From: "=?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?=" X-Google-Original-From: =?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?= To: qemu-devel@nongnu.org Date: Sun, 23 Dec 2018 21:52:04 +0100 Message-Id: <59bee9fad02c04c6600eba20dafb0c4cd1b31007.1545598229.git.DirtY.iCE.hu@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::342 Subject: [Qemu-devel] [PATCH v2 28/52] audio: api for mixeng code free backends X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Gerd Hoffmann Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Signed-off-by: K=C5=91v=C3=A1g=C3=B3, Zolt=C3=A1n --- audio/audio.c | 211 ++++++++++++++++++++++++++++++++++++++++- audio/audio_int.h | 45 +++++++-- audio/audio_template.h | 1 + 3 files changed, 247 insertions(+), 10 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index 27a8a31a64..1897e22444 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -575,6 +575,25 @@ size_t audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm= _buf, return clipped; } =20 +static void audio_pcm_hw_clip_out2(HWVoiceOut *hw, void *pcm_buf, size_t l= en) +{ + size_t clipped =3D 0; + size_t pos =3D hw->rpos; + + while (len) { + st_sample *src =3D hw->mix_buf + pos; + uint8_t *dst =3D advance (pcm_buf, clipped << hw->info.shift); + size_t samples_till_end_of_buf =3D hw->samples - pos; + size_t samples_to_clip =3D MIN(len, samples_till_end_of_buf); + + hw->clip (dst, src, samples_to_clip); + + pos =3D (pos + samples_to_clip) % hw->samples; + len -=3D samples_to_clip; + clipped +=3D samples_to_clip; + } +} + /* * Soft voice (capture) */ @@ -1052,6 +1071,31 @@ static void audio_capture_mix_and_clear(HWVoiceOut *= hw, size_t rpos, mixeng_clear(hw->mix_buf, samples - n); } =20 +static size_t audio_pcm_hw_run_out(HWVoiceOut *hw, size_t live) +{ + size_t clipped =3D 0; + + while (live) { + size_t size, decr, proc; + void *buf =3D hw->pcm_ops->get_buffer_out(hw, &size); + + decr =3D MIN(size >> hw->info.shift, live); + audio_pcm_hw_clip_out2(hw, buf, decr); + proc =3D hw->pcm_ops->put_buffer_out(hw, buf, decr << hw->info.shi= ft) >> + hw->info.shift; + + live -=3D proc; + clipped +=3D proc; + hw->rpos =3D (hw->rpos + proc) % hw->samples; + + if (proc =3D=3D 0 || proc < decr) { + break; + } + } + + return clipped; +} + static void audio_run_out (AudioState *s) { HWVoiceOut *hw =3D NULL; @@ -1099,7 +1143,11 @@ static void audio_run_out (AudioState *s) } =20 prev_rpos =3D hw->rpos; - played =3D hw->pcm_ops->run_out (hw, live); + if (hw->pcm_ops->run_out) { + played =3D hw->pcm_ops->run_out(hw, live); + } else { + played =3D audio_pcm_hw_run_out(hw, live); + } replay_audio_out(&played); if (audio_bug(__func__, hw->rpos >=3D hw->samples)) { dolog("hw->rpos=3D%zu hw->samples=3D%zu played=3D%zu\n", @@ -1158,6 +1206,35 @@ static void audio_run_out (AudioState *s) } } =20 +static size_t audio_pcm_hw_run_in(HWVoiceIn *hw, size_t samples) +{ + size_t conv =3D 0; + + while (samples) { + size_t proc; + size_t size =3D samples << hw->info.shift; + void *buf =3D hw->pcm_ops->get_buffer_in(hw, &size); + + assert((size & hw->info.align) =3D=3D 0); + if (size =3D=3D 0) { + hw->pcm_ops->put_buffer_in(hw, buf, size); + break; + } + + proc =3D MIN(size >> hw->info.shift, + hw->samples - hw->wpos); + + hw->conv(hw->conv_buf + hw->wpos, buf, proc); + hw->wpos =3D (hw->wpos + proc) % hw->samples; + + samples -=3D proc; + conv +=3D proc; + hw->pcm_ops->put_buffer_in(hw, buf, proc << hw->info.shift); + } + + return conv; +} + static void audio_run_in (AudioState *s) { HWVoiceIn *hw =3D NULL; @@ -1167,7 +1244,12 @@ static void audio_run_in (AudioState *s) size_t captured =3D 0, min; =20 if (replay_mode !=3D REPLAY_MODE_PLAY) { - captured =3D hw->pcm_ops->run_in(hw); + if (hw->pcm_ops->run_in) { + captured =3D hw->pcm_ops->run_in(hw); + } else { + captured =3D audio_pcm_hw_run_in( + hw, hw->samples - audio_pcm_hw_get_live_in(hw)); + } } replay_audio_in(&captured, hw->conv_buf, &hw->wpos, hw->samples); =20 @@ -1261,12 +1343,137 @@ void audio_run(AudioState *s, const char *msg) #endif } =20 +void *audio_generic_get_buffer_in(HWVoiceIn *hw, size_t *size) +{ + ssize_t start; + + if (unlikely(!hw->buf_emul)) { + size_t calc_size =3D hw->samples << hw->info.shift; + hw->buf_emul =3D g_malloc(calc_size); + hw->size_emul =3D calc_size; + hw->pos_emul =3D hw->pending_emul =3D 0; + } + + while (hw->pending_emul < hw->size_emul) { + size_t read_len =3D MIN(hw->size_emul - hw->pos_emul, + hw->size_emul - hw->pending_emul); + size_t read =3D hw->pcm_ops->read(hw, hw->buf_emul + hw->pos_emul, + read_len); + hw->pending_emul +=3D read; + if (read < read_len) { + break; + } + } + + start =3D ((ssize_t) hw->pos_emul) - hw->pending_emul; + if (start < 0) { + start +=3D hw->size_emul; + } + assert(start >=3D 0 && start < hw->size_emul); + + *size =3D MIN(hw->pending_emul, hw->size_emul - start); + return hw->buf_emul + start; +} + +void audio_generic_put_buffer_in(HWVoiceIn *hw, void *buf, size_t size) +{ + assert(size <=3D hw->pending_emul); + hw->pending_emul -=3D size; +} + +void *audio_generic_get_buffer_out(HWVoiceOut *hw, size_t *size) +{ + if (unlikely(!hw->buf_emul)) { + size_t calc_size =3D hw->samples << hw->info.shift; + + hw->buf_emul =3D g_malloc(calc_size); + hw->size_emul =3D calc_size; + hw->pos_emul =3D hw->pending_emul =3D 0; + } + + *size =3D MIN(hw->size_emul - hw->pending_emul, + hw->size_emul - hw->pos_emul); + return hw->buf_emul + hw->pos_emul; +} + +size_t audio_generic_put_buffer_out_nowrite(HWVoiceOut *hw, void *buf, + size_t size) +{ + assert(buf =3D=3D hw->buf_emul + hw->pos_emul && + size + hw->pending_emul <=3D hw->size_emul); + + hw->pending_emul +=3D size; + hw->pos_emul =3D (hw->pos_emul + size) % hw->size_emul; + + return size; +} + +size_t audio_generic_put_buffer_out(HWVoiceOut *hw, void *buf, size_t size) +{ + audio_generic_put_buffer_out_nowrite(hw, buf, size); + + while (hw->pending_emul) { + size_t write_len, written; + ssize_t start =3D ((ssize_t) hw->pos_emul) - hw->pending_emul; + if (start < 0) { + start +=3D hw->size_emul; + } + assert(start >=3D 0 && start < hw->size_emul); + + write_len =3D MIN(hw->pending_emul, hw->size_emul - start); + + written =3D hw->pcm_ops->write(hw, hw->buf_emul + start, write_len= ); + hw->pending_emul -=3D written; + + if (written < write_len) { + break; + } + } + + /* + * fake we have written everything. non-written data remain in pending= _emul, + * so we do not have to clip them multiple times + */ + return size; +} + +size_t audio_generic_write(HWVoiceOut *hw, void *buf, size_t size) +{ + size_t dst_size, copy_size; + void *dst =3D hw->pcm_ops->get_buffer_out(hw, &dst_size); + copy_size =3D MIN(size, dst_size); + + memcpy(dst, buf, copy_size); + return hw->pcm_ops->put_buffer_out(hw, buf, copy_size); +} + +size_t audio_generic_read(HWVoiceIn *hw, void *buf, size_t size) +{ + size_t dst_size, copy_size; + void *dst =3D hw->pcm_ops->get_buffer_in(hw, &dst_size); + copy_size =3D MIN(size, dst_size); + + memcpy(dst, buf, copy_size); + hw->pcm_ops->put_buffer_in(hw, buf, copy_size); + return copy_size; +} + + static int audio_driver_init(AudioState *s, struct audio_driver *drv, Audiodev *dev) { s->drv_opaque =3D drv->init(dev); =20 if (s->drv_opaque) { + if (!drv->pcm_ops->get_buffer_in) { + drv->pcm_ops->get_buffer_in =3D audio_generic_get_buffer_in; + drv->pcm_ops->put_buffer_in =3D audio_generic_put_buffer_in; + } + if (!drv->pcm_ops->get_buffer_out) { + drv->pcm_ops->get_buffer_out =3D audio_generic_get_buffer_out; + drv->pcm_ops->put_buffer_out =3D audio_generic_put_buffer_out; + } + audio_init_nb_voices_out(s, drv); audio_init_nb_voices_in(s, drv); s->drv =3D drv; diff --git a/audio/audio_int.h b/audio/audio_int.h index 330c465d0b..5c361d9451 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -64,6 +64,8 @@ typedef struct HWVoiceOut { uint64_t ts_helper; =20 struct st_sample *mix_buf; + void *buf_emul; + size_t pos_emul, pending_emul, size_emul; =20 size_t samples; QLIST_HEAD (sw_out_listhead, SWVoiceOut) sw_head; @@ -86,6 +88,8 @@ typedef struct HWVoiceIn { uint64_t ts_helper; =20 struct st_sample *conv_buf; + void *buf_emul; + size_t pos_emul, pending_emul, size_emul; =20 size_t samples; QLIST_HEAD (sw_in_listhead, SWVoiceIn) sw_head; @@ -146,17 +150,42 @@ struct audio_driver { }; =20 struct audio_pcm_ops { - int (*init_out)(HWVoiceOut *hw, struct audsettings *as, void *drv_opa= que); - void (*fini_out)(HWVoiceOut *hw); - int (*run_out) (HWVoiceOut *hw, int live); - int (*ctl_out) (HWVoiceOut *hw, int cmd, ...); + int (*init_out)(HWVoiceOut *hw, audsettings *as, void *drv_opaque); + void (*fini_out)(HWVoiceOut *hw); + int (*run_out) (HWVoiceOut *hw, int live); + size_t (*write) (HWVoiceOut *hw, void *buf, size_t size); + /* + * get a buffer that after later can be passed to put_buffer_out; opti= onal + * returns the buffer, and writes it's size to size (in bytes) + * this is unrelated to the above buffer_size_out function + */ + void *(*get_buffer_out)(HWVoiceOut *hw, size_t *size); + /* + * put back the buffer returned by get_buffer_out; optional + * buf must be equal the pointer returned by get_buffer_out, + * size may be smaller + */ + size_t (*put_buffer_out)(HWVoiceOut *hw, void *buf, size_t size); + int (*ctl_out) (HWVoiceOut *hw, int cmd, ...); =20 - int (*init_in) (HWVoiceIn *hw, struct audsettings *as, void *drv_opaq= ue); - void (*fini_in) (HWVoiceIn *hw); - int (*run_in) (HWVoiceIn *hw); - int (*ctl_in) (HWVoiceIn *hw, int cmd, ...); + int (*init_in) (HWVoiceIn *hw, audsettings *as, void *drv_opaque); + void (*fini_in) (HWVoiceIn *hw); + int (*run_in) (HWVoiceIn *hw); + size_t (*read) (HWVoiceIn *hw, void *buf, size_t size); + void *(*get_buffer_in)(HWVoiceIn *hw, size_t *size); + void (*put_buffer_in)(HWVoiceIn *hw, void *buf, size_t size); + int (*ctl_in) (HWVoiceIn *hw, int cmd, ...); }; =20 +void *audio_generic_get_buffer_in(HWVoiceIn *hw, size_t *size); +void audio_generic_put_buffer_in(HWVoiceIn *hw, void *buf, size_t size); +void *audio_generic_get_buffer_out(HWVoiceOut *hw, size_t *size); +size_t audio_generic_put_buffer_out(HWVoiceOut *hw, void *buf, size_t size= ); +size_t audio_generic_put_buffer_out_nowrite(HWVoiceOut *hw, void *buf, + size_t size); +size_t audio_generic_write(HWVoiceOut *hw, void *buf, size_t size); +size_t audio_generic_read(HWVoiceIn *hw, void *buf, size_t size); + struct capture_callback { struct audio_capture_ops ops; void *opaque; diff --git a/audio/audio_template.h b/audio/audio_template.h index fecbf1a046..33cdb66d7f 100644 --- a/audio/audio_template.h +++ b/audio/audio_template.h @@ -71,6 +71,7 @@ static void glue(audio_init_nb_voices_, TYPE)(AudioState = *s, =20 static void glue (audio_pcm_hw_free_resources_, TYPE) (HW *hw) { + g_free(hw->buf_emul); g_free (HWBUF); HWBUF =3D NULL; } --=20 2.20.1