From patchwork Thu Sep 19 21:24:09 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?UTF-8?B?Wm9sdMOhbiBLxZF2w6Fnw7M=?= X-Patchwork-Id: 1164881 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="U1NCSDy1"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46Z8zX563qz9sPV for ; Fri, 20 Sep 2019 07:26:16 +1000 (AEST) Received: from localhost ([::1]:48614 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB3wL-0002i2-CC for incoming@patchwork.ozlabs.org; Thu, 19 Sep 2019 17:26:13 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53450) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB3ud-0002ci-CH for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:30 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iB3ua-0000WO-Pd for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:27 -0400 Received: from mail-wr1-x443.google.com ([2a00:1450:4864:20::443]:35764) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iB3ua-0000Vl-HD for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:24 -0400 Received: by mail-wr1-x443.google.com with SMTP id v8so4644266wrt.2 for ; Thu, 19 Sep 2019 14:24:24 -0700 (PDT) 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=gQTXEae4XxyiTnyrCdtpgMdBnrBg+8cJykseiI2XC+k=; b=U1NCSDy1wdrMn8ywfIlscf4ZzBVquqnaRcp+91/2sLnu/YRVUWv5hicxiXO8YoN2K8 83Sw1Kv5RMVay1K7BjsV7pYFQJ6Oi+Ri+gQGdEwvBAdQ3DgRDGeZulQdrKwiCQwwI9j9 q2VQqHbOdUS8mgFbHQERo5s9jaG48KAKHOC1ZN7fFalZ48ppb5TgjIWzlSZ8Cal5hcXX oh6IoZn+NwsrgpbvRqq7dNz8bEd32JH6NUhkbisTZ9/nKPUV+H/MVSaP6SV7/Qq4jQ/m 762zOFi07T/xmzNC5cS1k0uLeNKQMArZ3tnr4oWRCSz9JHazMROk0d+B55i518RzeFwM 71Dg== 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=gQTXEae4XxyiTnyrCdtpgMdBnrBg+8cJykseiI2XC+k=; b=MCwYQJjzOSAIMa1WEj6yFIJ03kDXLyOzOh+DiLFmVtRb/PjWkKuWhwbfahR3mN3ckD Y39kx5qoFfxDNnbefKXm0MnZH+lG/fC8olyPj3uqkqWivDx83Z1Yev+7FqkouiN7v+/Z W0MNGX6W3P8JiKLXz1+9zQK3BALrjDsHvgIHEr6BkcitCJ+P3WoYIkwTj+U7OlW8BlRd rpOFo9U0w3Ttwy80r/UKg2rkFziRPiz9A5b8zPzZu0agjm8glZUkzM983zK1C2PPe+ZF IBtocRK035m3+XY6WsyGyeSGpgGlXgAv6YT0LuZK1/DutN34hU3X3+lGlaj30XFlX7vf nADQ== X-Gm-Message-State: APjAAAXACn4nHlYymGF6Z8wHwlTcwfHj0KndeYskRLh378iwBncPcljz Fj3mFqOmaRMMwnG6M3v7pO77WMYH X-Google-Smtp-Source: APXvYqz/NKhRIXaq0QUgromWGeRIBfCHPvu93fYCx8Bm/DXNkKDEXC6gPtHZPQ1vZmfrTVgw3oHN2g== X-Received: by 2002:a5d:500f:: with SMTP id e15mr8105661wrt.300.1568928263120; Thu, 19 Sep 2019 14:24:23 -0700 (PDT) Received: from nullptr.home.dirty-ice.org (2a01-036c-0113-74ef-0000-0000-0000-0005.pool6.digikabel.hu. [2a01:36c:113:74ef::5]) by smtp.gmail.com with ESMTPSA id w125sm13191292wmg.32.2019.09.19.14.24.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Sep 2019 14:24:22 -0700 (PDT) From: "=?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?=" X-Google-Original-From: =?utf-8?b?S8WRdsOhZ8OzLCBab2x0w6Fu?= To: qemu-devel@nongnu.org Subject: [PATCH v4 01/24] audio: api for mixeng code free backends Date: Thu, 19 Sep 2019 23:24:09 +0200 Message-Id: <15a33c03a62228922d851f7324c52f73cb8d2414.1568927990.git.DirtY.iCE.hu@gmail.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: References: MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::443 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Gerd Hoffmann Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" This will make it possible to skip mixeng with audio playback and recording, allowing us to free ourselves from the limitations of the current mixeng (stereo, int64 samples only). In this case, HW and SW voices will be essentially the same, for every SW voice we will create a HW voice, since we can no longer mix multiple voices together. Some backends expect us to call a function when we have data ready write()/read() style, while others provide a buffer and expects us to directly write/read it, so for optimal performance audio_pcm_ops provide methods for both cases. Previously backends asked mixeng for more data in run_out/run_it, now instead mixeng or the frontends will call the backends, so that's why two sets of functions required. audio.c contains glue code between the two styles, so backends only ever have to implement one style and frontends are free to call whichever is more convenient for them. Signed-off-by: Kővágó, Zoltán --- Notes: Changes from v2: * audio_pcm_hw_run_out: handle NULL result from get_buffer_out audio/audio.c | 216 ++++++++++++++++++++++++++++++++++++++++- audio/audio_int.h | 43 ++++++-- audio/audio_template.h | 1 + 3 files changed, 251 insertions(+), 9 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index e99fcd0694..e29a1e15eb 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -573,6 +573,25 @@ size_t audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, return clipped; } +static void audio_pcm_hw_clip_out2(HWVoiceOut *hw, void *pcm_buf, size_t len) +{ + size_t clipped = 0; + size_t pos = hw->rpos; + + while (len) { + st_sample *src = hw->mix_buf + pos; + uint8_t *dst = advance(pcm_buf, clipped << hw->info.shift); + size_t samples_till_end_of_buf = hw->samples - pos; + size_t samples_to_clip = MIN(len, samples_till_end_of_buf); + + hw->clip(dst, src, samples_to_clip); + + pos = (pos + samples_to_clip) % hw->samples; + len -= samples_to_clip; + clipped += samples_to_clip; + } +} + /* * Soft voice (capture) */ @@ -1050,6 +1069,36 @@ static void audio_capture_mix_and_clear(HWVoiceOut *hw, size_t rpos, mixeng_clear(hw->mix_buf, samples - n); } +static size_t audio_pcm_hw_run_out(HWVoiceOut *hw, size_t live) +{ + size_t clipped = 0; + + while (live) { + size_t size, decr, proc; + void *buf = hw->pcm_ops->get_buffer_out(hw, &size); + if (!buf) { + /* retrying will likely won't help, drop everything. */ + hw->rpos = (hw->rpos + live) % hw->samples; + return clipped + live; + } + + decr = MIN(size >> hw->info.shift, live); + audio_pcm_hw_clip_out2(hw, buf, decr); + proc = hw->pcm_ops->put_buffer_out(hw, buf, decr << hw->info.shift) >> + hw->info.shift; + + live -= proc; + clipped += proc; + hw->rpos = (hw->rpos + proc) % hw->samples; + + if (proc == 0 || proc < decr) { + break; + } + } + + return clipped; +} + static void audio_run_out (AudioState *s) { HWVoiceOut *hw = NULL; @@ -1097,7 +1146,11 @@ static void audio_run_out (AudioState *s) } prev_rpos = hw->rpos; - played = hw->pcm_ops->run_out (hw, live); + if (hw->pcm_ops->run_out) { + played = hw->pcm_ops->run_out(hw, live); + } else { + played = audio_pcm_hw_run_out(hw, live); + } replay_audio_out(&played); if (audio_bug(__func__, hw->rpos >= hw->samples)) { dolog("hw->rpos=%zu hw->samples=%zu played=%zu\n", @@ -1156,6 +1209,35 @@ static void audio_run_out (AudioState *s) } } +static size_t audio_pcm_hw_run_in(HWVoiceIn *hw, size_t samples) +{ + size_t conv = 0; + + while (samples) { + size_t proc; + size_t size = samples << hw->info.shift; + void *buf = hw->pcm_ops->get_buffer_in(hw, &size); + + assert((size & hw->info.align) == 0); + if (size == 0) { + hw->pcm_ops->put_buffer_in(hw, buf, size); + break; + } + + proc = MIN(size >> hw->info.shift, + hw->samples - hw->wpos); + + hw->conv(hw->conv_buf + hw->wpos, buf, proc); + hw->wpos = (hw->wpos + proc) % hw->samples; + + samples -= proc; + conv += proc; + hw->pcm_ops->put_buffer_in(hw, buf, proc << hw->info.shift); + } + + return conv; +} + static void audio_run_in (AudioState *s) { HWVoiceIn *hw = NULL; @@ -1165,7 +1247,12 @@ static void audio_run_in (AudioState *s) size_t captured = 0, min; if (replay_mode != REPLAY_MODE_PLAY) { - captured = hw->pcm_ops->run_in(hw); + if (hw->pcm_ops->run_in) { + captured = hw->pcm_ops->run_in(hw); + } else { + captured = 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); @@ -1259,12 +1346,137 @@ void audio_run(AudioState *s, const char *msg) #endif } +void *audio_generic_get_buffer_in(HWVoiceIn *hw, size_t *size) +{ + ssize_t start; + + if (unlikely(!hw->buf_emul)) { + size_t calc_size = hw->samples << hw->info.shift; + hw->buf_emul = g_malloc(calc_size); + hw->size_emul = calc_size; + hw->pos_emul = hw->pending_emul = 0; + } + + while (hw->pending_emul < hw->size_emul) { + size_t read_len = MIN(hw->size_emul - hw->pos_emul, + hw->size_emul - hw->pending_emul); + size_t read = hw->pcm_ops->read(hw, hw->buf_emul + hw->pos_emul, + read_len); + hw->pending_emul += read; + if (read < read_len) { + break; + } + } + + start = ((ssize_t) hw->pos_emul) - hw->pending_emul; + if (start < 0) { + start += hw->size_emul; + } + assert(start >= 0 && start < hw->size_emul); + + *size = 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 <= hw->pending_emul); + hw->pending_emul -= size; +} + +void *audio_generic_get_buffer_out(HWVoiceOut *hw, size_t *size) +{ + if (unlikely(!hw->buf_emul)) { + size_t calc_size = hw->samples << hw->info.shift; + + hw->buf_emul = g_malloc(calc_size); + hw->size_emul = calc_size; + hw->pos_emul = hw->pending_emul = 0; + } + + *size = 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 == hw->buf_emul + hw->pos_emul && + size + hw->pending_emul <= hw->size_emul); + + hw->pending_emul += size; + hw->pos_emul = (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 = ((ssize_t) hw->pos_emul) - hw->pending_emul; + if (start < 0) { + start += hw->size_emul; + } + assert(start >= 0 && start < hw->size_emul); + + write_len = MIN(hw->pending_emul, hw->size_emul - start); + + written = hw->pcm_ops->write(hw, hw->buf_emul + start, write_len); + hw->pending_emul -= 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 = hw->pcm_ops->get_buffer_out(hw, &dst_size); + copy_size = 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 = hw->pcm_ops->get_buffer_in(hw, &dst_size); + copy_size = 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, bool msg, Audiodev *dev) { s->drv_opaque = drv->init(dev); if (s->drv_opaque) { + if (!drv->pcm_ops->get_buffer_in) { + drv->pcm_ops->get_buffer_in = audio_generic_get_buffer_in; + drv->pcm_ops->put_buffer_in = audio_generic_put_buffer_in; + } + if (!drv->pcm_ops->get_buffer_out) { + drv->pcm_ops->get_buffer_out = audio_generic_get_buffer_out; + drv->pcm_ops->put_buffer_out = audio_generic_put_buffer_out; + } + audio_init_nb_voices_out(s, drv); audio_init_nb_voices_in(s, drv); s->drv = drv; diff --git a/audio/audio_int.h b/audio/audio_int.h index a674c5374a..8fb1ca8a8d 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -65,6 +65,8 @@ typedef struct HWVoiceOut { uint64_t ts_helper; struct st_sample *mix_buf; + void *buf_emul; + size_t pos_emul, pending_emul, size_emul; size_t samples; QLIST_HEAD (sw_out_listhead, SWVoiceOut) sw_head; @@ -87,6 +89,8 @@ typedef struct HWVoiceIn { uint64_t ts_helper; struct st_sample *conv_buf; + void *buf_emul; + size_t pos_emul, pending_emul, size_emul; size_t samples; QLIST_HEAD (sw_in_listhead, SWVoiceIn) sw_head; @@ -147,17 +151,42 @@ struct audio_driver { }; struct audio_pcm_ops { - int (*init_out)(HWVoiceOut *hw, struct audsettings *as, void *drv_opaque); - void (*fini_out)(HWVoiceOut *hw); + int (*init_out)(HWVoiceOut *hw, audsettings *as, void *drv_opaque); + void (*fini_out)(HWVoiceOut *hw); size_t (*run_out)(HWVoiceOut *hw, size_t live); - int (*ctl_out) (HWVoiceOut *hw, int cmd, ...); - - int (*init_in) (HWVoiceIn *hw, struct audsettings *as, void *drv_opaque); - void (*fini_in) (HWVoiceIn *hw); + size_t (*write) (HWVoiceOut *hw, void *buf, size_t size); + /* + * get a buffer that after later can be passed to put_buffer_out; optional + * 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, ...); + + int (*init_in) (HWVoiceIn *hw, audsettings *as, void *drv_opaque); + void (*fini_in) (HWVoiceIn *hw); size_t (*run_in)(HWVoiceIn *hw); - int (*ctl_in) (HWVoiceIn *hw, int cmd, ...); + 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, ...); }; +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 2562bf5f00..ff4a173f18 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, static void glue (audio_pcm_hw_free_resources_, TYPE) (HW *hw) { + g_free(hw->buf_emul); g_free (HWBUF); HWBUF = NULL; } From patchwork Thu Sep 19 21:24:10 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?UTF-8?B?Wm9sdMOhbiBLxZF2w6Fnw7M=?= X-Patchwork-Id: 1164879 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="thvKs0pI"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46Z8zV4yzRz9sPP for ; Fri, 20 Sep 2019 07:26:14 +1000 (AEST) Received: from localhost ([::1]:48612 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB3wK-0002gG-50 for incoming@patchwork.ozlabs.org; Thu, 19 Sep 2019 17:26:12 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53453) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB3ud-0002cv-Hc for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:29 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iB3ub-0000Wq-HC for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:27 -0400 Received: from mail-wr1-x444.google.com ([2a00:1450:4864:20::444]:44246) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iB3ub-0000WK-87 for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:25 -0400 Received: by mail-wr1-x444.google.com with SMTP id i18so4581290wru.11 for ; Thu, 19 Sep 2019 14:24:25 -0700 (PDT) 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=lDG6NNDECQDn4/nyyITVRisGzx5VHFjiAPGOHzavck0=; b=thvKs0pIyIyVv1m8fezY2Nr8CChsknXBFFY70PtiE8MhXDIhBaqMr5LRC4C+NtcWwB fVKtBtyOcr5uAAiBY7UVtiWmDbJftkGjxap8A7YLX4qUORrC8d75dfu43CJn+D/roA4X AoGGZxhar/J4hoDy/PUxaq94WjNKXCKIJ4dOkCs6tleHis27pt8bl6x5EUdJg/4OOdBZ Y5jz9gAfO0GUGU/rAxEyhbXfbiqOGAr4BYmQcGxxyLfukDxMAccWSYlLrY6ltkrRZrJe gDaEuLNZbKQ9Nb/H75siG2lYBd5ol3OcSZroAFqVfnV4m08cF4pgsbqWtAx4QpP6lKIN EFCQ== 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=lDG6NNDECQDn4/nyyITVRisGzx5VHFjiAPGOHzavck0=; b=E1rArIWO6taKv9b/xndKoxvzN4bn3q9X7M741v3rO7j04EoImSxUgm1GIdd6aRXNs8 E+pdAF0XJIdRh5Xry09Ls7ReHPfJjt27h5Q+FTtFgqNCY0OePPvHR+UlvYb75t4Jl+lr 3XqbpksPuvG0cu/vYnl5PfHoWjeXP3cLatin4PVphH0NtKN/lfU/zI7ubkNe9BpL+u3/ XC1nH0AO9HnC7yfRFkvdbDhP9vgykKjZCmdjR3wxyMu3Qr+HYuIh9TJQvLAovo74OV48 GECZFhxNSNwEh94p8NHSL3jEB6sjKrKIpnGpqo87RMrkJb7hy+3i7axG18n8Fko1N2pM VdLQ== X-Gm-Message-State: APjAAAUMT/e2ArXvhM9htdLJdGC608caOanWsMVmHI6RFy4y9E600u4w CthUzvRh9Meq7rb8OB/5XQQVJAy/ X-Google-Smtp-Source: APXvYqzAWOFVKNkSMLP0QvUgLap/aN6esDeycJPFeA7zG6H9TFmLO4wM9yPule/BKR/XwZHnPZaCOA== X-Received: by 2002:adf:fa90:: with SMTP id h16mr1372999wrr.52.1568928263962; Thu, 19 Sep 2019 14:24:23 -0700 (PDT) Received: from nullptr.home.dirty-ice.org (2a01-036c-0113-74ef-0000-0000-0000-0005.pool6.digikabel.hu. [2a01:36c:113:74ef::5]) by smtp.gmail.com with ESMTPSA id w125sm13191292wmg.32.2019.09.19.14.24.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Sep 2019 14:24:23 -0700 (PDT) From: "=?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?=" X-Google-Original-From: =?utf-8?b?S8WRdsOhZ8OzLCBab2x0w6Fu?= To: qemu-devel@nongnu.org Subject: [PATCH v4 02/24] alsaaudio: port to the new audio backend api Date: Thu, 19 Sep 2019 23:24:10 +0200 Message-Id: X-Mailer: git-send-email 2.23.0 In-Reply-To: References: MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::444 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Gerd Hoffmann Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Signed-off-by: Kővágó, Zoltán --- audio/alsaaudio.c | 302 ++++++++++++---------------------------------- 1 file changed, 80 insertions(+), 222 deletions(-) diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index 591344dccd..19124d09d8 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -44,9 +44,6 @@ struct pollhlp { typedef struct ALSAVoiceOut { HWVoiceOut hw; - int wpos; - int pending; - void *pcm_buf; snd_pcm_t *handle; struct pollhlp pollhlp; Audiodev *dev; @@ -55,7 +52,6 @@ typedef struct ALSAVoiceOut { typedef struct ALSAVoiceIn { HWVoiceIn hw; snd_pcm_t *handle; - void *pcm_buf; struct pollhlp pollhlp; Audiodev *dev; } ALSAVoiceIn; @@ -602,102 +598,64 @@ static int alsa_open(bool in, struct alsa_params_req *req, return -1; } -static snd_pcm_sframes_t alsa_get_avail (snd_pcm_t *handle) +static size_t alsa_write(HWVoiceOut *hw, void *buf, size_t len) { - snd_pcm_sframes_t avail; - - avail = snd_pcm_avail_update (handle); - if (avail < 0) { - if (avail == -EPIPE) { - if (!alsa_recover (handle)) { - avail = snd_pcm_avail_update (handle); - } - } - - if (avail < 0) { - alsa_logerr (avail, - "Could not obtain number of available frames\n"); - return -1; - } - } + ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw; + size_t pos = 0; + size_t len_frames = len >> hw->info.shift; + + while (len_frames) { + char *src = advance(buf, pos); + snd_pcm_sframes_t written; + + written = snd_pcm_writei(alsa->handle, src, len_frames); + + if (written <= 0) { + switch (written) { + case 0: + trace_alsa_wrote_zero(len_frames); + return pos; + + case -EPIPE: + if (alsa_recover(alsa->handle)) { + alsa_logerr(written, "Failed to write %zu frames\n", + len_frames); + return pos; + } + trace_alsa_xrun_out(); + continue; + + case -ESTRPIPE: + /* + * stream is suspended and waiting for an application + * recovery + */ + if (alsa_resume(alsa->handle)) { + alsa_logerr(written, "Failed to write %zu frames\n", + len_frames); + return pos; + } + trace_alsa_resume_out(); + continue; - return avail; -} + case -EAGAIN: + return pos; -static void alsa_write_pending (ALSAVoiceOut *alsa) -{ - HWVoiceOut *hw = &alsa->hw; - - while (alsa->pending) { - int left_till_end_samples = hw->samples - alsa->wpos; - int len = MIN (alsa->pending, left_till_end_samples); - char *src = advance (alsa->pcm_buf, alsa->wpos << hw->info.shift); - - while (len) { - snd_pcm_sframes_t written; - - written = snd_pcm_writei (alsa->handle, src, len); - - if (written <= 0) { - switch (written) { - case 0: - trace_alsa_wrote_zero(len); - return; - - case -EPIPE: - if (alsa_recover (alsa->handle)) { - alsa_logerr (written, "Failed to write %d frames\n", - len); - return; - } - trace_alsa_xrun_out(); - continue; - - case -ESTRPIPE: - /* stream is suspended and waiting for an - application recovery */ - if (alsa_resume (alsa->handle)) { - alsa_logerr (written, "Failed to write %d frames\n", - len); - return; - } - trace_alsa_resume_out(); - continue; - - case -EAGAIN: - return; - - default: - alsa_logerr (written, "Failed to write %d frames from %p\n", - len, src); - return; - } + default: + alsa_logerr(written, "Failed to write %zu frames from %p\n", + len, src); + return pos; } - - alsa->wpos = (alsa->wpos + written) % hw->samples; - alsa->pending -= written; - len -= written; } - } -} - -static size_t alsa_run_out(HWVoiceOut *hw, size_t live) -{ - ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw; - size_t decr; - snd_pcm_sframes_t avail; - avail = alsa_get_avail (alsa->handle); - if (avail < 0) { - dolog ("Could not get number of available playback frames\n"); - return 0; + pos += written << hw->info.shift; + if (written < len_frames) { + break; + } + len_frames -= written; } - decr = MIN (live, avail); - decr = audio_pcm_hw_clip_out (hw, alsa->pcm_buf, decr, alsa->pending); - alsa->pending += decr; - alsa_write_pending (alsa); - return decr; + return pos; } static void alsa_fini_out (HWVoiceOut *hw) @@ -706,9 +664,6 @@ static void alsa_fini_out (HWVoiceOut *hw) ldebug ("alsa_fini\n"); alsa_anal_close (&alsa->handle, &alsa->pollhlp); - - g_free(alsa->pcm_buf); - alsa->pcm_buf = NULL; } static int alsa_init_out(HWVoiceOut *hw, struct audsettings *as, @@ -737,14 +692,6 @@ static int alsa_init_out(HWVoiceOut *hw, struct audsettings *as, audio_pcm_init_info (&hw->info, &obt_as); hw->samples = obt.samples; - alsa->pcm_buf = audio_calloc(__func__, obt.samples, 1 << hw->info.shift); - if (!alsa->pcm_buf) { - dolog("Could not allocate DAC buffer (%zu samples, each %d bytes)\n", - hw->samples, 1 << hw->info.shift); - alsa_anal_close1 (&handle); - return -1; - } - alsa->pollhlp.s = hw->s; alsa->handle = handle; alsa->dev = dev; @@ -839,14 +786,6 @@ static int alsa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) audio_pcm_init_info (&hw->info, &obt_as); hw->samples = obt.samples; - alsa->pcm_buf = audio_calloc(__func__, hw->samples, 1 << hw->info.shift); - if (!alsa->pcm_buf) { - dolog("Could not allocate ADC buffer (%zu samples, each %d bytes)\n", - hw->samples, 1 << hw->info.shift); - alsa_anal_close1 (&handle); - return -1; - } - alsa->pollhlp.s = hw->s; alsa->handle = handle; alsa->dev = dev; @@ -858,129 +797,48 @@ static void alsa_fini_in (HWVoiceIn *hw) ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw; alsa_anal_close (&alsa->handle, &alsa->pollhlp); - - g_free(alsa->pcm_buf); - alsa->pcm_buf = NULL; } -static size_t alsa_run_in(HWVoiceIn *hw) +static size_t alsa_read(HWVoiceIn *hw, void *buf, size_t len) { ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw; - int hwshift = hw->info.shift; - int i; - size_t live = audio_pcm_hw_get_live_in (hw); - size_t dead = hw->samples - live; - size_t decr; - struct { - size_t add; - size_t len; - } bufs[2] = { - { .add = hw->wpos, .len = 0 }, - { .add = 0, .len = 0 } - }; - snd_pcm_sframes_t avail; - snd_pcm_uframes_t read_samples = 0; - - if (!dead) { - return 0; - } + size_t pos = 0; - avail = alsa_get_avail (alsa->handle); - if (avail < 0) { - dolog ("Could not get number of captured frames\n"); - return 0; - } - - if (!avail) { - snd_pcm_state_t state; - - state = snd_pcm_state (alsa->handle); - switch (state) { - case SND_PCM_STATE_PREPARED: - avail = hw->samples; - break; - case SND_PCM_STATE_SUSPENDED: - /* stream is suspended and waiting for an application recovery */ - if (alsa_resume (alsa->handle)) { - dolog ("Failed to resume suspended input stream\n"); - return 0; - } - trace_alsa_resume_in(); - break; - default: - trace_alsa_no_frames(state); - return 0; - } - } + while (len) { + void *dst = advance(buf, pos); + snd_pcm_sframes_t nread; - decr = MIN(dead, avail); - if (!decr) { - return 0; - } + nread = snd_pcm_readi(alsa->handle, dst, len >> hw->info.shift); - if (hw->wpos + decr > hw->samples) { - bufs[0].len = (hw->samples - hw->wpos); - bufs[1].len = (decr - (hw->samples - hw->wpos)); - } - else { - bufs[0].len = decr; - } + if (nread <= 0) { + switch (nread) { + case 0: + trace_alsa_read_zero(len); + return pos;; - for (i = 0; i < 2; ++i) { - void *src; - struct st_sample *dst; - snd_pcm_sframes_t nread; - snd_pcm_uframes_t len; - - len = bufs[i].len; - - src = advance (alsa->pcm_buf, bufs[i].add << hwshift); - dst = hw->conv_buf + bufs[i].add; - - while (len) { - nread = snd_pcm_readi (alsa->handle, src, len); - - if (nread <= 0) { - switch (nread) { - case 0: - trace_alsa_read_zero(len); - goto exit; - - case -EPIPE: - if (alsa_recover (alsa->handle)) { - alsa_logerr (nread, "Failed to read %ld frames\n", len); - goto exit; - } - trace_alsa_xrun_in(); - continue; - - case -EAGAIN: - goto exit; - - default: - alsa_logerr ( - nread, - "Failed to read %ld frames from %p\n", - len, - src - ); - goto exit; + case -EPIPE: + if (alsa_recover(alsa->handle)) { + alsa_logerr(nread, "Failed to read %zu frames\n", len); + return pos; } - } + trace_alsa_xrun_in(); + continue; - hw->conv (dst, src, nread); + case -EAGAIN: + return pos; - src = advance (src, nread << hwshift); - dst += nread; - - read_samples += nread; - len -= nread; + default: + alsa_logerr(nread, "Failed to read %zu frames to %p\n", + len, dst); + return pos;; + } } + + pos += nread << hw->info.shift; + len -= nread << hw->info.shift; } - exit: - hw->wpos = (hw->wpos + read_samples) % hw->samples; - return read_samples; + return pos; } static int alsa_ctl_in (HWVoiceIn *hw, int cmd, ...) @@ -1065,12 +923,12 @@ static void alsa_audio_fini (void *opaque) static struct audio_pcm_ops alsa_pcm_ops = { .init_out = alsa_init_out, .fini_out = alsa_fini_out, - .run_out = alsa_run_out, + .write = alsa_write, .ctl_out = alsa_ctl_out, .init_in = alsa_init_in, .fini_in = alsa_fini_in, - .run_in = alsa_run_in, + .read = alsa_read, .ctl_in = alsa_ctl_in, }; From patchwork Thu Sep 19 21:24:11 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?UTF-8?B?Wm9sdMOhbiBLxZF2w6Fnw7M=?= X-Patchwork-Id: 1164885 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="NAL27pcH"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46Z94f1HcJz9sPJ for ; Fri, 20 Sep 2019 07:30:42 +1000 (AEST) Received: from localhost ([::1]:48636 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB40c-00079V-Fa for incoming@patchwork.ozlabs.org; Thu, 19 Sep 2019 17:30:38 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53469) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB3uf-0002en-4N for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:31 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iB3uc-0000XI-Gc for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:28 -0400 Received: from mail-wm1-x342.google.com ([2a00:1450:4864:20::342]:53744) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iB3uc-0000Wu-8t for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:26 -0400 Received: by mail-wm1-x342.google.com with SMTP id i16so6337711wmd.3 for ; Thu, 19 Sep 2019 14:24:26 -0700 (PDT) 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=P1Yx/dZ4rieO/0gJLGQ3xdgMx3pyBcyEnZuiP7yaO78=; b=NAL27pcHuyj1Ca6I8XB9JqJUnaxAX4dcdab+dhyAVw6k6iFERyO3PmrfQNy2YbDO59 Rz6E7nN95hAYKidOm/YPtw78hIFeqollNaSsktCKdacnUW2ise8grUm/M4CFeHoXgHao LO8Wa/xjIx0z++DlB62+91pAF+xJrWQpoPO1Z33lnYk3xFkoe8TzB2BZBn+wSnkkggAR 0X/tVxqNGrQqXSCxWHhVBB2iHr0KeFDknSwegf8fThLqy17LSEOQ2ExgfSp1nU6UzUCw Xx2yj66PcbvHJqpzDDDetMbI7EBvDHqmrAEXYvYg5Vrzj5pHdhXv7sblFga96sMin0v1 V3Og== 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=P1Yx/dZ4rieO/0gJLGQ3xdgMx3pyBcyEnZuiP7yaO78=; b=lkTKQw4WKHSk4EqzUYr05xlYo/Z48Sonyt7x4rW4cZUbUe7Mk6ajygSCkhgbT6wPbF hsh7rLq+nWLwEOngfMNSEsXoaWWzoHLQzCN9K6Lh4dfKTJHL/75f4rzZLm3wc3j6zePE aWH3NZif76gCoSdqteHd5rxkTiIcSsArCgWIesp0aMtfUHmJWSR4+lsZDdtKFEV7/SsL fVljBzFa1VqUxyXyN4ChgR8a9vV8tQapJyKueHZc4NWOpH+Wo08zpi7Z5sB49l5BjbxB 87pUgAD1pbKKb/p1h5+Btbvpj4RkPo5eX30DEUH9MyD1qULjDQeJVwPWY66fquTaS/sf 5bqw== X-Gm-Message-State: APjAAAWKzPFar3SUjI2TABn9Cw/5Waxu85wmrnwffKv5LN4q4n8iQh+k h2C86O93M4Rq1E4+rY56ykVk77ny X-Google-Smtp-Source: APXvYqyMlcASVh2KybuR4v7YwxGBcPb3CSwj1ie6OGEuBPsikmMIRTaKUDPDcaptSiw2hm3hVqdQrQ== X-Received: by 2002:a05:600c:241:: with SMTP id 1mr74170wmj.162.1568928264840; Thu, 19 Sep 2019 14:24:24 -0700 (PDT) Received: from nullptr.home.dirty-ice.org (2a01-036c-0113-74ef-0000-0000-0000-0005.pool6.digikabel.hu. [2a01:36c:113:74ef::5]) by smtp.gmail.com with ESMTPSA id w125sm13191292wmg.32.2019.09.19.14.24.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Sep 2019 14:24:24 -0700 (PDT) From: "=?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?=" X-Google-Original-From: =?utf-8?b?S8WRdsOhZ8OzLCBab2x0w6Fu?= To: qemu-devel@nongnu.org Subject: [PATCH v4 03/24] coreaudio: port to the new audio backend api Date: Thu, 19 Sep 2019 23:24:11 +0200 Message-Id: <586a1e66de5cbc6c5234f9ae556d24befb6afada.1568927990.git.DirtY.iCE.hu@gmail.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: References: MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::342 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Gerd Hoffmann Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Signed-off-by: Kővágó, Zoltán --- audio/coreaudio.c | 130 ++++++++++++++++++++++++---------------------- 1 file changed, 69 insertions(+), 61 deletions(-) diff --git a/audio/coreaudio.c b/audio/coreaudio.c index d1be58b40a..5cde42f982 100644 --- a/audio/coreaudio.c +++ b/audio/coreaudio.c @@ -43,9 +43,6 @@ typedef struct coreaudioVoiceOut { UInt32 audioDevicePropertyBufferFrameSize; AudioStreamBasicDescription outputStreamBasicDescription; AudioDeviceIOProcID ioprocid; - size_t live; - size_t decr; - size_t rpos; } coreaudioVoiceOut; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 @@ -397,31 +394,29 @@ static int coreaudio_unlock (coreaudioVoiceOut *core, const char *fn_name) return 0; } -static size_t coreaudio_run_out(HWVoiceOut *hw, size_t live) -{ - size_t decr; - coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw; - - if (coreaudio_lock (core, "coreaudio_run_out")) { - return 0; +#define COREAUDIO_WRAPPER_FUNC(name, ret_type, args_decl, args) \ + static ret_type glue(coreaudio_, name)args_decl \ + { \ + coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw; \ + ret_type ret; \ + \ + if (coreaudio_lock(core, "coreaudio_" #name)) { \ + return 0; \ + } \ + \ + ret = glue(audio_generic_, name)args; \ + \ + coreaudio_unlock(core, "coreaudio_" #name); \ + return ret; \ } - - if (core->decr > live) { - ldebug ("core->decr %d live %d core->live %d\n", - core->decr, - live, - core->live); - } - - decr = MIN (core->decr, live); - core->decr -= decr; - - core->live = live - decr; - hw->rpos = core->rpos; - - coreaudio_unlock (core, "coreaudio_run_out"); - return decr; -} +COREAUDIO_WRAPPER_FUNC(get_buffer_out, void *, (HWVoiceOut *hw, size_t *size), + (hw, size)) +COREAUDIO_WRAPPER_FUNC(put_buffer_out_nowrite, size_t, + (HWVoiceOut *hw, void *buf, size_t size), + (hw, buf, size)) +COREAUDIO_WRAPPER_FUNC(write, size_t, (HWVoiceOut *hw, void *buf, size_t size), + (hw, buf, size)) +#undef COREAUDIO_WRAPPER_FUNC /* callback to feed audiooutput buffer */ static OSStatus audioDeviceIOProc( @@ -433,19 +428,11 @@ static OSStatus audioDeviceIOProc( const AudioTimeStamp* inOutputTime, void* hwptr) { - UInt32 frame, frameCount; - float *out = outOutputData->mBuffers[0].mData; + UInt32 frameCount, pending_frames; + void *out = outOutputData->mBuffers[0].mData; HWVoiceOut *hw = hwptr; coreaudioVoiceOut *core = (coreaudioVoiceOut *) hwptr; - int rpos, live; - struct st_sample *src; -#ifndef FLOAT_MIXENG -#ifdef RECIPROCAL - const float scale = 1.f / UINT_MAX; -#else - const float scale = UINT_MAX; -#endif -#endif + size_t len; if (coreaudio_lock (core, "audioDeviceIOProc")) { inInputTime = 0; @@ -453,42 +440,51 @@ static OSStatus audioDeviceIOProc( } frameCount = core->audioDevicePropertyBufferFrameSize; - live = core->live; + pending_frames = hw->pending_emul >> hw->info.shift; /* if there are not enough samples, set signal and return */ - if (live < frameCount) { + if (pending_frames < frameCount) { inInputTime = 0; coreaudio_unlock (core, "audioDeviceIOProc(empty)"); return 0; } - rpos = core->rpos; - src = hw->mix_buf + rpos; + len = frameCount << hw->info.shift; + while (len) { + size_t write_len; + ssize_t start = ((ssize_t) hw->pos_emul) - hw->pending_emul; + if (start < 0) { + start += hw->size_emul; + } + assert(start >= 0 && start < hw->size_emul); - /* fill buffer */ - for (frame = 0; frame < frameCount; frame++) { -#ifdef FLOAT_MIXENG - *out++ = src[frame].l; /* left channel */ - *out++ = src[frame].r; /* right channel */ -#else -#ifdef RECIPROCAL - *out++ = src[frame].l * scale; /* left channel */ - *out++ = src[frame].r * scale; /* right channel */ -#else - *out++ = src[frame].l / scale; /* left channel */ - *out++ = src[frame].r / scale; /* right channel */ -#endif -#endif - } + write_len = MIN(MIN(hw->pending_emul, len), + hw->size_emul - start); - rpos = (rpos + frameCount) % hw->samples; - core->decr += frameCount; - core->rpos = rpos; + memcpy(out, hw->buf_emul + start, write_len); + hw->pending_emul -= write_len; + len -= write_len; + out += write_len; + } coreaudio_unlock (core, "audioDeviceIOProc"); return 0; } +static UInt32 coreaudio_get_flags(struct audio_pcm_info *info, + struct audsettings *as) +{ + UInt32 flags = info->sign ? kAudioFormatFlagIsSignedInteger : 0; + if (as->endianness) { /* 0 = little, 1 = big */ + flags |= kAudioFormatFlagIsBigEndian; + } + + if (flags == 0) { /* must not be 0 */ + flags = kAudioFormatFlagsAreAllClear; + } + return flags; +} + static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as, void *drv_opaque) { @@ -576,6 +572,16 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as, /* set Samplerate */ core->outputStreamBasicDescription.mSampleRate = (Float64) as->freq; + core->outputStreamBasicDescription.mFormatID = kAudioFormatLinearPCM; + core->outputStreamBasicDescription.mFormatFlags = + coreaudio_get_flags(&hw->info, as); + core->outputStreamBasicDescription.mBytesPerPacket = + core->outputStreamBasicDescription.mBytesPerFrame = + hw->info.nchannels * hw->info.bits / 8; + core->outputStreamBasicDescription.mFramesPerPacket = 1; + core->outputStreamBasicDescription.mChannelsPerFrame = hw->info.nchannels; + core->outputStreamBasicDescription.mBitsPerChannel = hw->info.bits; + status = coreaudio_set_streamformat(core->outputDeviceID, &core->outputStreamBasicDescription); if (status != kAudioHardwareNoError) { @@ -686,7 +692,9 @@ static void coreaudio_audio_fini (void *opaque) static struct audio_pcm_ops coreaudio_pcm_ops = { .init_out = coreaudio_init_out, .fini_out = coreaudio_fini_out, - .run_out = coreaudio_run_out, + .write = coreaudio_write, + .get_buffer_out = coreaudio_get_buffer_out, + .put_buffer_out = coreaudio_put_buffer_out_nowrite, .ctl_out = coreaudio_ctl_out }; From patchwork Thu Sep 19 21:24:12 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?UTF-8?B?Wm9sdMOhbiBLxZF2w6Fnw7M=?= X-Patchwork-Id: 1164886 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="dWjKuTLQ"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46Z94z5lxnz9sPJ for ; Fri, 20 Sep 2019 07:30:59 +1000 (AEST) Received: from localhost ([::1]:48640 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB40v-0007F4-0h for incoming@patchwork.ozlabs.org; Thu, 19 Sep 2019 17:30:57 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53502) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB3uh-0002gy-1T for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:34 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iB3ud-0000YH-S4 for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:30 -0400 Received: from mail-wr1-x42e.google.com ([2a00:1450:4864:20::42e]:39195) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iB3ud-0000XW-H5 for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:27 -0400 Received: by mail-wr1-x42e.google.com with SMTP id r3so4622391wrj.6 for ; Thu, 19 Sep 2019 14:24:27 -0700 (PDT) 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=/3hgkV2+/v9H8hK3ryAoNU2NcM+2uuhTDg4UcFZG3ac=; b=dWjKuTLQlpB6JcFQA7WYfoyQOfjFqwdtV6CvIEIRVEU6EcCrDCH6sxh8p0o1ReM7aq 1jwOazJHWTPX+nLkp0ajgDPa8ddG+ZZVGpnn2vOrdT3aCtjAWn8BAyUtZtMuwMw6IuYk j0ssYmIL0KbtgRbxvED2tiiVcsjGiF4bzZwCtK9XxKw+tEzDp6B0SvigejWd/noGes9R 5jETtcB2ujrGlef7qz8fmUm9KfNevs5ZpFX8NQj2dywQme9hhagvLdgIWVJKBCHtlCfn R30m4y5Am1ITO8EA0nQ6tauoycfPadPgqqhKI/gArlFv+gRRT87mCPKJG3pbPJuKWh2O JA4g== 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=/3hgkV2+/v9H8hK3ryAoNU2NcM+2uuhTDg4UcFZG3ac=; b=sdsHtlSgjMuIDWosM9N381z94k7tH7eyuhpZpa6DIBVEicccaPKS0lszAjz2vd0dFU 3XbkD2ntmxJXmU6EDyhCaykGh+G/0hPp5qMO+PykJNsL5WrI6k9tF1fFZTFLRDJZCZHr 8T+bKXn9LijMJSxFgzLB6DiT++9FX9Bz+dUCizke/wOhAZ5ydC8BgS4PRVFEEBlJh+Em SRNaNRAN773JdjlaVN6xs5YsftPFdWkvd14R4A+YyAfyQNLcOQ3Rq8OITJGvJ9+pvxId PYE4vm4uzL8AM/0EWnnhfb5NZYBLPL+GfEP/WJaVf8LbW/o1a2VDJLosKszEuZDoIHQp renQ== X-Gm-Message-State: APjAAAVU5h93zW+qdM4nULw4XzBtqClIszZcWFk318ppBFP3IHROm06k 24VV2Pn3Wq6Wuslm9pEIUXLtwr0A X-Google-Smtp-Source: APXvYqy5s56OHSphimwqHW4tdmo/IwqgAdTOGi+L3VGwUxWSXdp0xuVf6frIo6KUVb2aykMzTChNvQ== X-Received: by 2002:adf:bb8e:: with SMTP id q14mr8568988wrg.74.1568928265891; Thu, 19 Sep 2019 14:24:25 -0700 (PDT) Received: from nullptr.home.dirty-ice.org (2a01-036c-0113-74ef-0000-0000-0000-0005.pool6.digikabel.hu. [2a01:36c:113:74ef::5]) by smtp.gmail.com with ESMTPSA id w125sm13191292wmg.32.2019.09.19.14.24.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Sep 2019 14:24:25 -0700 (PDT) From: "=?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?=" X-Google-Original-From: =?utf-8?b?S8WRdsOhZ8OzLCBab2x0w6Fu?= To: qemu-devel@nongnu.org Subject: [PATCH v4 04/24] dsoundaudio: port to the new audio backend api Date: Thu, 19 Sep 2019 23:24:12 +0200 Message-Id: <2ca925ab551ea832c930fc2db213a9e73d8dab7f.1568927990.git.DirtY.iCE.hu@gmail.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: References: MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::42e X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Gerd Hoffmann Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Signed-off-by: Kővágó, Zoltán --- audio/dsound_template.h | 47 ++++--- audio/dsoundaudio.c | 305 +++++++++------------------------------- 2 files changed, 91 insertions(+), 261 deletions(-) diff --git a/audio/dsound_template.h b/audio/dsound_template.h index 8ece870c9e..9f10b688df 100644 --- a/audio/dsound_template.h +++ b/audio/dsound_template.h @@ -29,6 +29,8 @@ #define BUFPTR LPDIRECTSOUNDCAPTUREBUFFER #define FIELD dsound_capture_buffer #define FIELD2 dsound_capture +#define HWVOICE HWVoiceIn +#define DSOUNDVOICE DSoundVoiceIn #else #define NAME "playback buffer" #define NAME2 "DirectSound" @@ -37,6 +39,8 @@ #define BUFPTR LPDIRECTSOUNDBUFFER #define FIELD dsound_buffer #define FIELD2 dsound +#define HWVOICE HWVoiceOut +#define DSOUNDVOICE DSoundVoiceOut #endif static int glue (dsound_unlock_, TYPE) ( @@ -72,8 +76,6 @@ static int glue (dsound_lock_, TYPE) ( ) { HRESULT hr; - LPVOID p1 = NULL, p2 = NULL; - DWORD blen1 = 0, blen2 = 0; DWORD flag; #ifdef DSBTYPE_IN @@ -81,7 +83,7 @@ static int glue (dsound_lock_, TYPE) ( #else flag = entire ? DSBLOCK_ENTIREBUFFER : 0; #endif - hr = glue(IFACE, _Lock)(buf, pos, len, &p1, &blen1, &p2, &blen2, flag); + hr = glue(IFACE, _Lock)(buf, pos, len, p1p, blen1p, p2p, blen2p, flag); if (FAILED (hr)) { #ifndef DSBTYPE_IN @@ -96,34 +98,34 @@ static int glue (dsound_lock_, TYPE) ( goto fail; } - if ((p1 && (blen1 & info->align)) || (p2 && (blen2 & info->align))) { - dolog ("DirectSound returned misaligned buffer %ld %ld\n", - blen1, blen2); - glue (dsound_unlock_, TYPE) (buf, p1, p2, blen1, blen2); + if ((p1p && *p1p && (*blen1p & info->align)) || + (p2p && *p2p && (*blen2p & info->align))) { + dolog("DirectSound returned misaligned buffer %ld %ld\n", + *blen1p, *blen2p); + glue(dsound_unlock_, TYPE)(buf, *p1p, p2p ? *p2p : NULL, *blen1p, + blen2p ? *blen2p : 0); goto fail; } - if (!p1 && blen1) { - dolog ("warning: !p1 && blen1=%ld\n", blen1); - blen1 = 0; + if (p1p && !*p1p && *blen1p) { + dolog("warning: !p1 && blen1=%ld\n", *blen1p); + *blen1p = 0; } - if (!p2 && blen2) { - dolog ("warning: !p2 && blen2=%ld\n", blen2); - blen2 = 0; + if (p2p && !*p2p && *blen2p) { + dolog("warning: !p2 && blen2=%ld\n", *blen2p); + *blen2p = 0; } - *p1p = p1; - *p2p = p2; - *blen1p = blen1; - *blen2p = blen2; return 0; fail: *p1p = NULL - 1; - *p2p = NULL - 1; *blen1p = -1; - *blen2p = -1; + if (p2p) { + *p2p = NULL - 1; + *blen2p = -1; + } return -1; } @@ -242,7 +244,6 @@ static int dsound_init_out(HWVoiceOut *hw, struct audsettings *as, goto fail0; } - ds->first_time = 1; obt_as.endianness = 0; audio_pcm_init_info (&hw->info, &obt_as); @@ -252,15 +253,13 @@ static int dsound_init_out(HWVoiceOut *hw, struct audsettings *as, bc.dwBufferBytes, hw->info.align + 1 ); } + hw->size_emul = bc.dwBufferBytes; hw->samples = bc.dwBufferBytes >> hw->info.shift; ds->s = s; #ifdef DEBUG_DSOUND dolog ("caps %ld, desc %ld\n", bc.dwBufferBytes, bd.dwBufferBytes); - - dolog ("bufsize %d, freq %d, chan %d, fmt %d\n", - hw->bufsize, settings.freq, settings.nchannels, settings.fmt); #endif return 0; @@ -276,3 +275,5 @@ static int dsound_init_out(HWVoiceOut *hw, struct audsettings *as, #undef BUFPTR #undef FIELD #undef FIELD2 +#undef HWVOICE +#undef DSOUNDVOICE diff --git a/audio/dsoundaudio.c b/audio/dsoundaudio.c index 2fc118b795..9960247814 100644 --- a/audio/dsoundaudio.c +++ b/audio/dsoundaudio.c @@ -53,19 +53,11 @@ typedef struct { typedef struct { HWVoiceOut hw; LPDIRECTSOUNDBUFFER dsound_buffer; - DWORD old_pos; - int first_time; dsound *s; -#ifdef DEBUG_DSOUND - DWORD old_ppos; - DWORD played; - DWORD mixed; -#endif } DSoundVoiceOut; typedef struct { HWVoiceIn hw; - int first_time; LPDIRECTSOUNDCAPTUREBUFFER dsound_capture_buffer; dsound *s; } DSoundVoiceIn; @@ -243,11 +235,6 @@ static void GCC_FMT_ATTR (3, 4) dsound_logerr2 ( dsound_log_hresult (hr); } -static uint64_t usecs_to_bytes(struct audio_pcm_info *info, uint32_t usecs) -{ - return muldiv64(usecs, info->bytes_per_second, 1000000); -} - #ifdef DEBUG_DSOUND static void print_wave_format (WAVEFORMATEX *wfx) { @@ -312,33 +299,6 @@ static int dsound_get_status_in (LPDIRECTSOUNDCAPTUREBUFFER dscb, return 0; } -static void dsound_write_sample (HWVoiceOut *hw, uint8_t *dst, int dst_len) -{ - int src_len1 = dst_len; - int src_len2 = 0; - int pos = hw->rpos + dst_len; - struct st_sample *src1 = hw->mix_buf + hw->rpos; - struct st_sample *src2 = NULL; - - if (pos > hw->samples) { - src_len1 = hw->samples - hw->rpos; - src2 = hw->mix_buf; - src_len2 = dst_len - src_len1; - pos = src_len2; - } - - if (src_len1) { - hw->clip (dst, src1, src_len1); - } - - if (src_len2) { - dst = advance (dst, src_len1 << hw->info.shift); - hw->clip (dst, src2, src_len2); - } - - hw->rpos = pos % hw->samples; -} - static void dsound_clear_sample (HWVoiceOut *hw, LPDIRECTSOUNDBUFFER dsb, dsound *s) { @@ -350,7 +310,7 @@ static void dsound_clear_sample (HWVoiceOut *hw, LPDIRECTSOUNDBUFFER dsb, dsb, &hw->info, 0, - hw->samples << hw->info.shift, + hw->size_emul, &p1, &p2, &blen1, &blen2, 1, @@ -454,139 +414,51 @@ static int dsound_ctl_out (HWVoiceOut *hw, int cmd, ...) return 0; } -static size_t dsound_run_out(HWVoiceOut *hw, size_t live) +static void *dsound_get_buffer_out(HWVoiceOut *hw, size_t *size) { - int err; - HRESULT hr; DSoundVoiceOut *ds = (DSoundVoiceOut *) hw; LPDIRECTSOUNDBUFFER dsb = ds->dsound_buffer; - size_t len; - int hwshift; - DWORD blen1, blen2; - DWORD len1, len2; - DWORD decr; - DWORD wpos, ppos, old_pos; - LPVOID p1, p2; - size_t bufsize; - dsound *s = ds->s; - AudiodevDsoundOptions *dso = &s->dev->u.dsound; - - if (!dsb) { - dolog ("Attempt to run empty with playback buffer\n"); - return 0; - } - - hwshift = hw->info.shift; - bufsize = hw->samples << hwshift; - - hr = IDirectSoundBuffer_GetCurrentPosition ( - dsb, - &ppos, - ds->first_time ? &wpos : NULL - ); - if (FAILED (hr)) { - dsound_logerr (hr, "Could not get playback buffer position\n"); - return 0; - } - - len = live << hwshift; - - if (ds->first_time) { - if (dso->latency) { - DWORD cur_blat; + HRESULT hr; + DWORD ppos, act_size; + size_t req_size; + int err; + void *ret; - cur_blat = audio_ring_dist (wpos, ppos, bufsize); - ds->first_time = 0; - old_pos = wpos; - old_pos += - usecs_to_bytes(&hw->info, dso->latency) - cur_blat; - old_pos %= bufsize; - old_pos &= ~hw->info.align; - } - else { - old_pos = wpos; - } -#ifdef DEBUG_DSOUND - ds->played = 0; - ds->mixed = 0; -#endif + hr = IDirectSoundBuffer_GetCurrentPosition(dsb, &ppos, NULL); + if (FAILED(hr)) { + dsound_logerr(hr, "Could not get playback buffer position\n"); + *size = 0; + return NULL; } - else { - if (ds->old_pos == ppos) { -#ifdef DEBUG_DSOUND - dolog ("old_pos == ppos\n"); -#endif - return 0; - } -#ifdef DEBUG_DSOUND - ds->played += audio_ring_dist (ds->old_pos, ppos, hw->bufsize); -#endif - old_pos = ds->old_pos; - } + req_size = audio_ring_dist(ppos, hw->pos_emul, hw->size_emul); + req_size = MIN(req_size, hw->size_emul - hw->pos_emul); - if ((old_pos < ppos) && ((old_pos + len) > ppos)) { - len = ppos - old_pos; - } - else { - if ((old_pos > ppos) && ((old_pos + len) > (ppos + bufsize))) { - len = bufsize - old_pos + ppos; - } + err = dsound_lock_out(dsb, &hw->info, hw->pos_emul, req_size, &ret, NULL, + &act_size, NULL, false, ds->s); + if (err) { + dolog("Failed to lock buffer\n"); + *size = 0; + return NULL; } - if (audio_bug(__func__, len > bufsize)) { - dolog("len=%zu bufsize=%zu old_pos=%ld ppos=%ld\n", - len, bufsize, old_pos, ppos); - return 0; - } + *size = act_size; + return ret; +} - len &= ~hw->info.align; - if (!len) { - return 0; - } +static size_t dsound_put_buffer_out(HWVoiceOut *hw, void *buf, size_t len) +{ + DSoundVoiceOut *ds = (DSoundVoiceOut *) hw; + LPDIRECTSOUNDBUFFER dsb = ds->dsound_buffer; + int err = dsound_unlock_out(dsb, buf, NULL, len, 0); -#ifdef DEBUG_DSOUND - ds->old_ppos = ppos; -#endif - err = dsound_lock_out ( - dsb, - &hw->info, - old_pos, - len, - &p1, &p2, - &blen1, &blen2, - 0, - s - ); if (err) { + dolog("Failed to unlock buffer!!\n"); return 0; } + hw->pos_emul = (hw->pos_emul + len) % hw->size_emul; - len1 = blen1 >> hwshift; - len2 = blen2 >> hwshift; - decr = len1 + len2; - - if (p1 && len1) { - dsound_write_sample (hw, p1, len1); - } - - if (p2 && len2) { - dsound_write_sample (hw, p2, len2); - } - - dsound_unlock_out (dsb, p1, p2, blen1, blen2); - ds->old_pos = (old_pos + (decr << hwshift)) % bufsize; - -#ifdef DEBUG_DSOUND - ds->mixed += decr << hwshift; - - dolog ("played %lu mixed %lu diff %ld sec %f\n", - ds->played, - ds->mixed, - ds->mixed - ds->played, - abs (ds->mixed - ds->played) / (double) hw->info.bytes_per_second); -#endif - return decr; + return len; } static int dsound_ctl_in (HWVoiceIn *hw, int cmd, ...) @@ -641,96 +513,49 @@ static int dsound_ctl_in (HWVoiceIn *hw, int cmd, ...) return 0; } -static size_t dsound_run_in(HWVoiceIn *hw) +static void *dsound_get_buffer_in(HWVoiceIn *hw, size_t *size) { - int err; - HRESULT hr; DSoundVoiceIn *ds = (DSoundVoiceIn *) hw; LPDIRECTSOUNDCAPTUREBUFFER dscb = ds->dsound_capture_buffer; - size_t live, len, dead; - DWORD blen1, blen2; - DWORD len1, len2; - DWORD decr; - DWORD cpos, rpos; - LPVOID p1, p2; - int hwshift; - dsound *s = ds->s; - - if (!dscb) { - dolog ("Attempt to run without capture buffer\n"); - return 0; - } - - hwshift = hw->info.shift; - - live = audio_pcm_hw_get_live_in (hw); - dead = hw->samples - live; - if (!dead) { - return 0; - } - - hr = IDirectSoundCaptureBuffer_GetCurrentPosition ( - dscb, - &cpos, - ds->first_time ? &rpos : NULL - ); - if (FAILED (hr)) { - dsound_logerr (hr, "Could not get capture buffer position\n"); - return 0; - } - - if (ds->first_time) { - ds->first_time = 0; - if (rpos & hw->info.align) { - ldebug ("warning: Misaligned capture read position %ld(%d)\n", - rpos, hw->info.align); - } - hw->wpos = rpos >> hwshift; - } + HRESULT hr; + DWORD cpos, act_size; + size_t req_size; + int err; + void *ret; - if (cpos & hw->info.align) { - ldebug ("warning: Misaligned capture position %ld(%d)\n", - cpos, hw->info.align); + hr = IDirectSoundCaptureBuffer_GetCurrentPosition(dscb, &cpos, NULL); + if (FAILED(hr)) { + dsound_logerr(hr, "Could not get capture buffer position\n"); + *size = 0; + return NULL; } - cpos >>= hwshift; - len = audio_ring_dist (cpos, hw->wpos, hw->samples); - if (!len) { - return 0; - } - len = MIN (len, dead); + req_size = audio_ring_dist(cpos, hw->pos_emul, hw->size_emul); + req_size = MIN(req_size, hw->size_emul - hw->pos_emul); - err = dsound_lock_in ( - dscb, - &hw->info, - hw->wpos << hwshift, - len << hwshift, - &p1, - &p2, - &blen1, - &blen2, - 0, - s - ); + err = dsound_lock_in(dscb, &hw->info, hw->pos_emul, req_size, &ret, NULL, + &act_size, NULL, false, ds->s); if (err) { - return 0; + dolog("Failed to lock buffer\n"); + *size = 0; + return NULL; } - len1 = blen1 >> hwshift; - len2 = blen2 >> hwshift; - decr = len1 + len2; + *size = act_size; + return ret; +} - if (p1 && len1) { - hw->conv (hw->conv_buf + hw->wpos, p1, len1); - } +static void dsound_put_buffer_in(HWVoiceIn *hw, void *buf, size_t len) +{ + DSoundVoiceIn *ds = (DSoundVoiceIn *) hw; + LPDIRECTSOUNDCAPTUREBUFFER dscb = ds->dsound_capture_buffer; + int err = dsound_unlock_in(dscb, buf, NULL, len, 0); - if (p2 && len2) { - hw->conv (hw->conv_buf, p2, len2); + if (err) { + dolog("Failed to unlock buffer!!\n"); + return; } - - dsound_unlock_in (dscb, p1, p2, blen1, blen2); - hw->wpos = (hw->wpos + decr) % hw->samples; - return decr; + hw->pos_emul = (hw->pos_emul + len) % hw->size_emul; } static void dsound_audio_fini (void *opaque) @@ -846,12 +671,16 @@ static void *dsound_audio_init(Audiodev *dev) static struct audio_pcm_ops dsound_pcm_ops = { .init_out = dsound_init_out, .fini_out = dsound_fini_out, - .run_out = dsound_run_out, + .write = audio_generic_write, + .get_buffer_out = dsound_get_buffer_out, + .put_buffer_out = dsound_put_buffer_out, .ctl_out = dsound_ctl_out, .init_in = dsound_init_in, .fini_in = dsound_fini_in, - .run_in = dsound_run_in, + .read = audio_generic_read, + .get_buffer_in = dsound_get_buffer_in, + .put_buffer_in = dsound_put_buffer_in, .ctl_in = dsound_ctl_in }; From patchwork Thu Sep 19 21:24:13 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?UTF-8?B?Wm9sdMOhbiBLxZF2w6Fnw7M=?= X-Patchwork-Id: 1164884 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="kl7AawCn"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46Z94T3RhWz9sNk for ; Fri, 20 Sep 2019 07:30:33 +1000 (AEST) Received: from localhost ([::1]:48634 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB40T-00073G-IQ for incoming@patchwork.ozlabs.org; Thu, 19 Sep 2019 17:30:29 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53498) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB3ug-0002gP-Le for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:31 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iB3ue-0000Yx-TR for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:30 -0400 Received: from mail-wr1-x442.google.com ([2a00:1450:4864:20::442]:36228) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iB3ue-0000YN-Ky for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:28 -0400 Received: by mail-wr1-x442.google.com with SMTP id y19so4640842wrd.3 for ; Thu, 19 Sep 2019 14:24:28 -0700 (PDT) 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=aJOgLJbUU33d0sFNF8d3VZOVm5JVuSp9jkJ/aPDzPik=; b=kl7AawCnYB5geqEpJnk7wWBcA4LtB+XIaptOZDGNPT+NLXmPKa6rmv+WgkxWiOigL8 TgPQiGSSep7Vkb4D8moXtAz9Ze6cpUPKCRUJ4pKv2UmGazAieM7gjq4jAT/8aQR+UZeH 1t2KhAtXklEvSwOpjEo2xqQs+uNF7lrBqzHITSPjdTymT554+gm8RfeWIkSNmSWDv5ws /thkB2R9NQU5xA7x+u1uHuSwGi+10uZEw3lRrb4n1He5sygqLKz3lhr+26DTlHWTDj3d QNozvN6DN2eFTHI/JMK/sDeor41V6rDQOPsjGrrT5Z5LGn/a0S0yay5p5CWS+bflYoSY ajoQ== 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=aJOgLJbUU33d0sFNF8d3VZOVm5JVuSp9jkJ/aPDzPik=; b=KcqYpuKu8Fl8Td7ZiX9Rhnt2AQzLdeHMaeEa4D59xUsN7mtMSfZHiPBMASLE1bjoy8 5uL1fxwDr1kkEMQTH2OtpLJwaE9ndPR1tFVvyj51NmDo14ZsDZKSnLZfp1uqOSAitijG ctoqHZcIiW4b9aL4HqKSUXg+CEdOMaq3SWWemCPUrdlDbSeN8x0zCt8u9E5rg4LdB21K /XXQlWI9y4fCKPVVM+PBurImMcFaKmK3EAB1ACPyUhn6AnFTz9NJrerlEtJPyS6YQKDY xm07zE/F15qnLwUtxi/gjpOicynV4OfBsEjrckhM+c7cFsAyQycT6hajmzOrFgegx78n wJHA== X-Gm-Message-State: APjAAAW3ENxkphfCvmvBW3udEi8vyaDKOo/8VOYhWjKXVs4orkoUNDOx mlniN7PdN6L+jWtILbhz8pAxQL1c X-Google-Smtp-Source: APXvYqxAqP7Tthxp9pGMcTNLy2HT9/Z2CcjlSTrk9dj7gmuZsUXVdJDaUx8FfTxirK9ZZQKz7kP8Ag== X-Received: by 2002:a05:6000:188:: with SMTP id p8mr6279571wrx.220.1568928267271; Thu, 19 Sep 2019 14:24:27 -0700 (PDT) Received: from nullptr.home.dirty-ice.org (2a01-036c-0113-74ef-0000-0000-0000-0005.pool6.digikabel.hu. [2a01:36c:113:74ef::5]) by smtp.gmail.com with ESMTPSA id w125sm13191292wmg.32.2019.09.19.14.24.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Sep 2019 14:24:26 -0700 (PDT) From: "=?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?=" X-Google-Original-From: =?utf-8?b?S8WRdsOhZ8OzLCBab2x0w6Fu?= To: qemu-devel@nongnu.org Subject: [PATCH v4 05/24] noaudio: port to the new audio backend api Date: Thu, 19 Sep 2019 23:24:13 +0200 Message-Id: <10eebdd2e1529c2bd403ef98dd9d346c6d4ca3d1.1568927990.git.DirtY.iCE.hu@gmail.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: References: MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::442 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Gerd Hoffmann Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Signed-off-by: Kővágó, Zoltán --- audio/noaudio.c | 43 +++++++++++++++++-------------------------- 1 file changed, 17 insertions(+), 26 deletions(-) diff --git a/audio/noaudio.c b/audio/noaudio.c index 0fb2629cf2..b054fd225b 100644 --- a/audio/noaudio.c +++ b/audio/noaudio.c @@ -41,10 +41,9 @@ typedef struct NoVoiceIn { int64_t old_ticks; } NoVoiceIn; -static size_t no_run_out(HWVoiceOut *hw, size_t live) +static size_t no_write(HWVoiceOut *hw, void *buf, size_t len) { NoVoiceOut *no = (NoVoiceOut *) hw; - size_t decr, samples; int64_t now; int64_t ticks; int64_t bytes; @@ -52,13 +51,9 @@ static size_t no_run_out(HWVoiceOut *hw, size_t live) now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); ticks = now - no->old_ticks; bytes = muldiv64(ticks, hw->info.bytes_per_second, NANOSECONDS_PER_SECOND); - bytes = MIN(bytes, SIZE_MAX); - samples = bytes >> hw->info.shift; no->old_ticks = now; - decr = MIN (live, samples); - hw->rpos = (hw->rpos + decr) % hw->samples; - return decr; + return MIN(len, bytes); } static int no_init_out(HWVoiceOut *hw, struct audsettings *as, void *drv_opaque) @@ -92,25 +87,21 @@ static void no_fini_in (HWVoiceIn *hw) (void) hw; } -static size_t no_run_in(HWVoiceIn *hw) +static size_t no_read(HWVoiceIn *hw, void *buf, size_t size) { + size_t to_clear; NoVoiceIn *no = (NoVoiceIn *) hw; - size_t live = audio_pcm_hw_get_live_in(hw); - size_t dead = hw->samples - live; - size_t samples = 0; - - if (dead) { - int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - int64_t ticks = now - no->old_ticks; - int64_t bytes = - muldiv64(ticks, hw->info.bytes_per_second, NANOSECONDS_PER_SECOND); - - no->old_ticks = now; - bytes = MIN (bytes, SIZE_MAX); - samples = bytes >> hw->info.shift; - samples = MIN (samples, dead); - } - return samples; + + int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + int64_t ticks = now - no->old_ticks; + int64_t bytes = + muldiv64(ticks, hw->info.bytes_per_second, NANOSECONDS_PER_SECOND); + + no->old_ticks = now; + to_clear = MIN(bytes, size); + + audio_pcm_info_clear_buf(&hw->info, buf, to_clear >> hw->info.shift); + return to_clear; } static int no_ctl_in (HWVoiceIn *hw, int cmd, ...) @@ -133,12 +124,12 @@ static void no_audio_fini (void *opaque) static struct audio_pcm_ops no_pcm_ops = { .init_out = no_init_out, .fini_out = no_fini_out, - .run_out = no_run_out, + .write = no_write, .ctl_out = no_ctl_out, .init_in = no_init_in, .fini_in = no_fini_in, - .run_in = no_run_in, + .read = no_read, .ctl_in = no_ctl_in }; From patchwork Thu Sep 19 21:24:14 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?UTF-8?B?Wm9sdMOhbiBLxZF2w6Fnw7M=?= X-Patchwork-Id: 1164890 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="vQIkB1Ec"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46Z9Cw5XXTz9sNk for ; Fri, 20 Sep 2019 07:37:00 +1000 (AEST) Received: from localhost ([::1]:48674 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB46k-000411-18 for incoming@patchwork.ozlabs.org; Thu, 19 Sep 2019 17:36:58 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53515) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB3ui-0002iY-E8 for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:36 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iB3uf-0000Zr-SO for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:32 -0400 Received: from mail-wr1-x442.google.com ([2a00:1450:4864:20::442]:41618) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iB3uf-0000Z2-Iz for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:29 -0400 Received: by mail-wr1-x442.google.com with SMTP id h7so4600352wrw.8 for ; Thu, 19 Sep 2019 14:24:29 -0700 (PDT) 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=y7iHNMJr/K6vEM5IKPVSAJe6YZjvyzTOTmHMWROPW74=; b=vQIkB1EcBBmxPUHCNIwLJIjXaPAMrautVO8u2twW3Wrl9hU5d+up/TrD6cpZO/v1yf dIUOvaXAzAmn9Gptihk4yq+Uw0lvU3SHLuchnLpZZmi0OBQhB5HJQvOI6m+PgefHgt4w 7BFyQOGdSgmI7LmKqOLrSqGYbeiwTm6+gbt+2a/HRv66K6987XBfZtnmt3owQyE/D4V7 sLcwXe5slTwXDPbfaFL5RdJIaL48SPqCEJQqfDiHtgVNyhyK4P2KDHgWUN7omQMv0/C3 xEbdXQ6Fl0KY/Rt9DyIp+MCYt8lqtQhQz+B6+ueTYtBnv+vOOr/Ct1JSrxCd56OhN1df JXhA== 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=y7iHNMJr/K6vEM5IKPVSAJe6YZjvyzTOTmHMWROPW74=; b=JujgTyX4w/AXB/MZLcLq1Lfs5c/ry9d+p0MdIlh2DZ92Q6mUOTeJNxkZUY8LUlrDXl KYxWe1LG1LATtDnxyek7qFyDsllOXqFtNSUZ1KRvhQFjp8zU675ScNFp/LkVp94EoqGz tWQR0vDfAka2Z1oujyOvj84CLLFxKzetKHhL3QO7uon5tA6+WGgOe/uNju/ASbjaQ7G0 beSEafACnR6fZ4c/InbTy235IZ2kl3gGz5T5DoHK445fiExOpF98tRejSB3sf1+ffwNs CJIa5ENGBC06No4Msj1BdVNklxOHprEUGZSpLHT6BcB/PHS/lTChm2w6CWfy1jIB71k9 TeQw== X-Gm-Message-State: APjAAAVIMB6Gfc8pUCS35D7BQSRM+dOnE0yh6PoLwFpUX2ys0RPOA7YV Ty+N9mNf2HjNJHqKRthL9YFo6P6i X-Google-Smtp-Source: APXvYqweeAR1BP+dIwEmLFfUDRJCS4f1fHwjkvWN1MzqQHBXoC9c4s1riqHkQZVSbzBMpAteWiS3IA== X-Received: by 2002:a5d:660c:: with SMTP id n12mr8973194wru.286.1568928268226; Thu, 19 Sep 2019 14:24:28 -0700 (PDT) Received: from nullptr.home.dirty-ice.org (2a01-036c-0113-74ef-0000-0000-0000-0005.pool6.digikabel.hu. [2a01:36c:113:74ef::5]) by smtp.gmail.com with ESMTPSA id w125sm13191292wmg.32.2019.09.19.14.24.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Sep 2019 14:24:27 -0700 (PDT) From: "=?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?=" X-Google-Original-From: =?utf-8?b?S8WRdsOhZ8OzLCBab2x0w6Fu?= To: qemu-devel@nongnu.org Subject: [PATCH v4 06/24] ossaudio: port to the new audio backend api Date: Thu, 19 Sep 2019 23:24:14 +0200 Message-Id: <22ab335146acd8099779583edcf6ed46de836bd6.1568927990.git.DirtY.iCE.hu@gmail.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: References: MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::442 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Gerd Hoffmann Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Signed-off-by: Kővágó, Zoltán --- audio/ossaudio.c | 272 +++++++++++++++++------------------------------ 1 file changed, 96 insertions(+), 176 deletions(-) diff --git a/audio/ossaudio.c b/audio/ossaudio.c index 1696933688..2782512706 100644 --- a/audio/ossaudio.c +++ b/audio/ossaudio.c @@ -40,19 +40,15 @@ typedef struct OSSVoiceOut { HWVoiceOut hw; - void *pcm_buf; int fd; - int wpos; int nfrags; int fragsize; int mmapped; - int pending; Audiodev *dev; } OSSVoiceOut; typedef struct OSSVoiceIn { HWVoiceIn hw; - void *pcm_buf; int fd; int nfrags; int fragsize; @@ -371,98 +367,87 @@ static int oss_open(int in, struct oss_params *req, audsettings *as, return -1; } -static void oss_write_pending (OSSVoiceOut *oss) +static size_t oss_get_available_bytes(OSSVoiceOut *oss) { - HWVoiceOut *hw = &oss->hw; + int err; + struct count_info cntinfo; + assert(oss->mmapped); - if (oss->mmapped) { - return; + err = ioctl(oss->fd, SNDCTL_DSP_GETOPTR, &cntinfo); + if (err < 0) { + oss_logerr(errno, "SNDCTL_DSP_GETOPTR failed\n"); + return 0; } - while (oss->pending) { - int samples_written; - ssize_t bytes_written; - int samples_till_end = hw->samples - oss->wpos; - int samples_to_write = MIN (oss->pending, samples_till_end); - int bytes_to_write = samples_to_write << hw->info.shift; - void *pcm = advance (oss->pcm_buf, oss->wpos << hw->info.shift); + return audio_ring_dist(cntinfo.ptr, oss->hw.pos_emul, oss->hw.size_emul); +} - bytes_written = write (oss->fd, pcm, bytes_to_write); - if (bytes_written < 0) { - if (errno != EAGAIN) { - oss_logerr (errno, "failed to write %d bytes\n", - bytes_to_write); - } - break; - } +static void *oss_get_buffer_out(HWVoiceOut *hw, size_t *size) +{ + OSSVoiceOut *oss = (OSSVoiceOut *) hw; + if (oss->mmapped) { + *size = MIN(oss_get_available_bytes(oss), hw->size_emul - hw->pos_emul); + return hw->buf_emul + hw->pos_emul; + } else { + return audio_generic_get_buffer_out(hw, size); + } +} - if (bytes_written & hw->info.align) { - dolog ("misaligned write asked for %d, but got %zd\n", - bytes_to_write, bytes_written); - return; - } +static size_t oss_put_buffer_out(HWVoiceOut *hw, void *buf, size_t size) +{ + OSSVoiceOut *oss = (OSSVoiceOut *) hw; + if (oss->mmapped) { + assert(buf == hw->buf_emul + hw->pos_emul && size < hw->size_emul); - samples_written = bytes_written >> hw->info.shift; - oss->pending -= samples_written; - oss->wpos = (oss->wpos + samples_written) % hw->samples; - if (bytes_written - bytes_to_write) { - break; - } + hw->pos_emul = (hw->pos_emul + size) % hw->size_emul; + return size; + } else { + return audio_generic_put_buffer_out(hw, buf, size); } } -static size_t oss_run_out(HWVoiceOut *hw, size_t live) +static size_t oss_write(HWVoiceOut *hw, void *buf, size_t len) { OSSVoiceOut *oss = (OSSVoiceOut *) hw; - int err; - size_t decr; - struct audio_buf_info abinfo; - struct count_info cntinfo; - size_t bufsize; - - bufsize = hw->samples << hw->info.shift; + size_t pos; if (oss->mmapped) { - int bytes, pos; + size_t total_len; + len = MIN(len, oss_get_available_bytes(oss)); - err = ioctl (oss->fd, SNDCTL_DSP_GETOPTR, &cntinfo); - if (err < 0) { - oss_logerr (errno, "SNDCTL_DSP_GETOPTR failed\n"); - return 0; - } + total_len = len; + while (len) { + size_t to_copy = MIN(len, hw->size_emul - hw->pos_emul); + memcpy(hw->buf_emul + hw->pos_emul, buf, to_copy); - pos = hw->rpos << hw->info.shift; - bytes = audio_ring_dist (cntinfo.ptr, pos, bufsize); - decr = MIN (bytes >> hw->info.shift, live); - } - else { - err = ioctl (oss->fd, SNDCTL_DSP_GETOSPACE, &abinfo); - if (err < 0) { - oss_logerr (errno, "SNDCTL_DSP_GETOPTR failed\n"); - return 0; + hw->pos_emul = (hw->pos_emul + to_copy) % hw->pos_emul; + buf += to_copy; + len -= to_copy; } + return total_len; + } - if (abinfo.bytes > bufsize) { - trace_oss_invalid_available_size(abinfo.bytes, bufsize); - abinfo.bytes = bufsize; - } + pos = 0; + while (len) { + ssize_t bytes_written; + void *pcm = advance(buf, pos); - if (abinfo.bytes < 0) { - trace_oss_invalid_available_size(abinfo.bytes, bufsize); - return 0; + bytes_written = write(oss->fd, pcm, len); + if (bytes_written < 0) { + if (errno != EAGAIN) { + oss_logerr(errno, "failed to write %zu bytes\n", + len); + } + return pos; } - decr = MIN (abinfo.bytes >> hw->info.shift, live); - if (!decr) { - return 0; + pos += bytes_written; + if (bytes_written < len) { + break; } + len -= bytes_written; } - - decr = audio_pcm_hw_clip_out (hw, oss->pcm_buf, decr, oss->pending); - oss->pending += decr; - oss_write_pending (oss); - - return decr; + return pos; } static void oss_fini_out (HWVoiceOut *hw) @@ -473,18 +458,13 @@ static void oss_fini_out (HWVoiceOut *hw) ldebug ("oss_fini\n"); oss_anal_close (&oss->fd); - if (oss->pcm_buf) { - if (oss->mmapped) { - err = munmap (oss->pcm_buf, hw->samples << hw->info.shift); - if (err) { - oss_logerr(errno, "Failed to unmap buffer %p, size %zu\n", - oss->pcm_buf, hw->samples << hw->info.shift); - } - } - else { - g_free (oss->pcm_buf); + if (oss->mmapped && hw->buf_emul) { + err = munmap(hw->buf_emul, hw->size_emul); + if (err) { + oss_logerr(errno, "Failed to unmap buffer %p, size %zu\n", + hw->buf_emul, hw->size_emul); } - oss->pcm_buf = NULL; + hw->buf_emul = NULL; } } @@ -535,19 +515,20 @@ static int oss_init_out(HWVoiceOut *hw, struct audsettings *as, oss->mmapped = 0; if (oopts->has_try_mmap && oopts->try_mmap) { - oss->pcm_buf = mmap ( + hw->size_emul = hw->samples << hw->info.shift; + hw->buf_emul = mmap( NULL, - hw->samples << hw->info.shift, + hw->size_emul, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 ); - if (oss->pcm_buf == MAP_FAILED) { + if (hw->buf_emul == MAP_FAILED) { oss_logerr(errno, "Failed to map %zu bytes of DAC\n", - hw->samples << hw->info.shift); - } - else { + hw->size_emul); + hw->buf_emul = NULL; + } else { int err; int trig = 0; if (ioctl (fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) { @@ -567,30 +548,16 @@ static int oss_init_out(HWVoiceOut *hw, struct audsettings *as, } if (!oss->mmapped) { - err = munmap (oss->pcm_buf, hw->samples << hw->info.shift); + err = munmap(hw->buf_emul, hw->size_emul); if (err) { oss_logerr(errno, "Failed to unmap buffer %p size %zu\n", - oss->pcm_buf, hw->samples << hw->info.shift); + hw->buf_emul, hw->size_emul); } + hw->buf_emul = NULL; } } } - if (!oss->mmapped) { - oss->pcm_buf = audio_calloc(__func__, - hw->samples, - 1 << hw->info.shift); - if (!oss->pcm_buf) { - dolog ( - "Could not allocate DAC buffer (%zu samples, each %d bytes)\n", - hw->samples, - 1 << hw->info.shift - ); - oss_anal_close (&fd); - return -1; - } - } - oss->fd = fd; oss->dev = dev; return 0; @@ -618,7 +585,7 @@ static int oss_ctl_out (HWVoiceOut *hw, int cmd, ...) return 0; } - audio_pcm_info_clear_buf (&hw->info, oss->pcm_buf, hw->samples); + audio_pcm_info_clear_buf(&hw->info, hw->buf_emul, hw->samples); trig = PCM_ENABLE_OUTPUT; if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) { oss_logerr ( @@ -692,13 +659,6 @@ static int oss_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) } hw->samples = (obt.nfrags * obt.fragsize) >> hw->info.shift; - oss->pcm_buf = audio_calloc(__func__, hw->samples, 1 << hw->info.shift); - if (!oss->pcm_buf) { - dolog("Could not allocate ADC buffer (%zu samples, each %d bytes)\n", - hw->samples, 1 << hw->info.shift); - oss_anal_close (&fd); - return -1; - } oss->fd = fd; oss->dev = dev; @@ -710,78 +670,36 @@ static void oss_fini_in (HWVoiceIn *hw) OSSVoiceIn *oss = (OSSVoiceIn *) hw; oss_anal_close (&oss->fd); - - g_free(oss->pcm_buf); - oss->pcm_buf = NULL; } -static size_t oss_run_in(HWVoiceIn *hw) +static size_t oss_read(HWVoiceIn *hw, void *buf, size_t len) { OSSVoiceIn *oss = (OSSVoiceIn *) hw; - int hwshift = hw->info.shift; - int i; - size_t live = audio_pcm_hw_get_live_in (hw); - size_t dead = hw->samples - live; - size_t read_samples = 0; - struct { - size_t add; - size_t len; - } bufs[2] = { - { .add = hw->wpos, .len = 0 }, - { .add = 0, .len = 0 } - }; - - if (!dead) { - return 0; - } - - if (hw->wpos + dead > hw->samples) { - bufs[0].len = (hw->samples - hw->wpos) << hwshift; - bufs[1].len = (dead - (hw->samples - hw->wpos)) << hwshift; - } - else { - bufs[0].len = dead << hwshift; - } + size_t pos = 0; - for (i = 0; i < 2; ++i) { + while (len) { ssize_t nread; - if (bufs[i].len) { - void *p = advance (oss->pcm_buf, bufs[i].add << hwshift); - nread = read (oss->fd, p, bufs[i].len); - - if (nread > 0) { - if (nread & hw->info.align) { - dolog("warning: Misaligned read %zd (requested %zu), " - "alignment %d\n", nread, bufs[i].add << hwshift, - hw->info.align + 1); - } - read_samples += nread >> hwshift; - hw->conv (hw->conv_buf + bufs[i].add, p, nread >> hwshift); - } + void *dst = advance(buf, pos); + nread = read(oss->fd, dst, len); - if (bufs[i].len - nread) { - if (nread == -1) { - switch (errno) { - case EINTR: - case EAGAIN: - break; - default: - oss_logerr( - errno, - "Failed to read %zu bytes of audio (to %p)\n", - bufs[i].len, p - ); - break; - } - } + if (nread == -1) { + switch (errno) { + case EINTR: + case EAGAIN: + break; + default: + oss_logerr(errno, "Failed to read %zu bytes of audio (to %p)\n", + len, dst); break; } } + + pos += nread; + len -= nread; } - hw->wpos = (hw->wpos + read_samples) % hw->samples; - return read_samples; + return pos; } static int oss_ctl_in (HWVoiceIn *hw, int cmd, ...) @@ -845,12 +763,14 @@ static void oss_audio_fini (void *opaque) static struct audio_pcm_ops oss_pcm_ops = { .init_out = oss_init_out, .fini_out = oss_fini_out, - .run_out = oss_run_out, + .write = oss_write, + .get_buffer_out = oss_get_buffer_out, + .put_buffer_out = oss_put_buffer_out, .ctl_out = oss_ctl_out, .init_in = oss_init_in, .fini_in = oss_fini_in, - .run_in = oss_run_in, + .read = oss_read, .ctl_in = oss_ctl_in }; From patchwork Thu Sep 19 21:24:15 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?UTF-8?B?Wm9sdMOhbiBLxZF2w6Fnw7M=?= X-Patchwork-Id: 1164882 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="APZcNJbU"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46Z8zg37THz9sNf for ; Fri, 20 Sep 2019 07:26:23 +1000 (AEST) Received: from localhost ([::1]:48616 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB3wS-0002sC-BX for incoming@patchwork.ozlabs.org; Thu, 19 Sep 2019 17:26:20 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53535) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB3um-0002kc-BH for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:40 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iB3uh-0000ay-N7 for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:36 -0400 Received: from mail-wm1-x331.google.com ([2a00:1450:4864:20::331]:53212) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iB3ug-0000a0-QZ for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:31 -0400 Received: by mail-wm1-x331.google.com with SMTP id x2so2180wmj.2 for ; Thu, 19 Sep 2019 14:24:30 -0700 (PDT) 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=AZf6/it/Lyk8fL9jYDjwtnrnumA5OJWUoIFrfXMwHcw=; b=APZcNJbUbaFT6Pv0jic44WVYPA3KDo3r1lrY15YKqKIh7/Iff022vRp/Y8H7L1Zusb ukeRCxVUpSWx5JL8Q+RFqYaAIhk4+u9AiMkbxA36yVYdExzgjt+P2yCTkZUAfGu0k9FT qWpdPQP11QbyPetO7ygd7LkumhjRy38YwmfuFKqv2QH9xL8BbuPZKiFTjDBz20R/HqSg wWkGhlrxR+7gEg89vI1ESQN2Qyi0KCVHSqxsFJofWA3ti40Fro7KvofcMWVkyEZ8r7It sNI5+/Ll3DT85ewIlHbD3lhyJpDoVDTT0LzsbDt54/Opq+6kphMFgVz24hFLckV8sFN7 xBPg== 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=AZf6/it/Lyk8fL9jYDjwtnrnumA5OJWUoIFrfXMwHcw=; b=nfr8q48zBli6egbhPl3NcBbpaVMlQKg1tXm6d8Awre+LeVXTbWqojlUjF/jES1xuhD nPvpQ4ci2wUZemK7hySGQBH26QpYXl05zfvY/VC4yAcSyXxaszDurPM4gtRdULr+eAhR unnTCJVxGTh/jHZ8v+/pizL7ELQBDc4JJMQ6pATQG3MsC9Pd4+zEOmn1CUflfhN10gm5 jSOQ2FP3YIw62oiWy0J4nPnW3cNyDPSxgmrG9aq3vxEv10c/zZawcyqrbm54qQGUxilk LK+t/nDryWsl/pojLO+YLMNZnguhIZ02Zx/fKk4f7khKI9nEtioxT12K7jBYk3mcovOP 1oJA== X-Gm-Message-State: APjAAAUcfzx/S562WoePFy2hU2yBI/7Rr8gIyBS/uRks051/7HsMT6mb hRfXtEmiylePDjMM2S0x93GRZ6Zc X-Google-Smtp-Source: APXvYqybA1V385M0JSzYM4Awri14LNfSVby2tMjGGbCEjhPj4mfL9peiJ9HHIXvfI66FTsbs8vn4vg== X-Received: by 2002:a7b:c5c5:: with SMTP id n5mr63443wmk.69.1568928269152; Thu, 19 Sep 2019 14:24:29 -0700 (PDT) Received: from nullptr.home.dirty-ice.org (2a01-036c-0113-74ef-0000-0000-0000-0005.pool6.digikabel.hu. [2a01:36c:113:74ef::5]) by smtp.gmail.com with ESMTPSA id w125sm13191292wmg.32.2019.09.19.14.24.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Sep 2019 14:24:28 -0700 (PDT) From: "=?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?=" X-Google-Original-From: =?utf-8?b?S8WRdsOhZ8OzLCBab2x0w6Fu?= To: qemu-devel@nongnu.org Subject: [PATCH v4 07/24] paaudio: port to the new audio backend api Date: Thu, 19 Sep 2019 23:24:15 +0200 Message-Id: <21fe8f2cf949039c8c40a0352590c593b104917d.1568927990.git.DirtY.iCE.hu@gmail.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: References: MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::331 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Gerd Hoffmann Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Signed-off-by: Kővágó, Zoltán --- audio/Makefile.objs | 1 - audio/audio_pt_int.c | 173 -------------------- audio/audio_pt_int.h | 22 --- audio/paaudio.c | 372 ++++++------------------------------------- configure | 5 - 5 files changed, 45 insertions(+), 528 deletions(-) delete mode 100644 audio/audio_pt_int.c delete mode 100644 audio/audio_pt_int.h diff --git a/audio/Makefile.objs b/audio/Makefile.objs index dca87f6347..d7490a379f 100644 --- a/audio/Makefile.objs +++ b/audio/Makefile.objs @@ -2,7 +2,6 @@ common-obj-y = audio.o audio_legacy.o noaudio.o wavaudio.o mixeng.o common-obj-$(CONFIG_SPICE) += spiceaudio.o common-obj-$(CONFIG_AUDIO_COREAUDIO) += coreaudio.o common-obj-$(CONFIG_AUDIO_DSOUND) += dsoundaudio.o -common-obj-$(CONFIG_AUDIO_PT_INT) += audio_pt_int.o common-obj-$(CONFIG_AUDIO_WIN_INT) += audio_win_int.o common-obj-y += wavcapture.o diff --git a/audio/audio_pt_int.c b/audio/audio_pt_int.c deleted file mode 100644 index 9f9d44ad4a..0000000000 --- a/audio/audio_pt_int.c +++ /dev/null @@ -1,173 +0,0 @@ -#include "qemu/osdep.h" -#include "audio.h" - -#define AUDIO_CAP "audio-pt" - -#include "audio_int.h" -#include "audio_pt_int.h" - -static void GCC_FMT_ATTR(3, 4) logerr (struct audio_pt *pt, int err, - const char *fmt, ...) -{ - va_list ap; - - va_start (ap, fmt); - AUD_vlog (pt->drv, fmt, ap); - va_end (ap); - - AUD_log (NULL, "\n"); - AUD_log (pt->drv, "Reason: %s\n", strerror (err)); -} - -int audio_pt_init (struct audio_pt *p, void *(*func) (void *), - void *opaque, const char *drv, const char *cap) -{ - int err, err2; - const char *efunc; - sigset_t set, old_set; - - p->drv = drv; - - err = sigfillset (&set); - if (err) { - logerr(p, errno, "%s(%s): sigfillset failed", cap, __func__); - return -1; - } - - err = pthread_mutex_init (&p->mutex, NULL); - if (err) { - efunc = "pthread_mutex_init"; - goto err0; - } - - err = pthread_cond_init (&p->cond, NULL); - if (err) { - efunc = "pthread_cond_init"; - goto err1; - } - - err = pthread_sigmask (SIG_BLOCK, &set, &old_set); - if (err) { - efunc = "pthread_sigmask"; - goto err2; - } - - err = pthread_create (&p->thread, NULL, func, opaque); - - err2 = pthread_sigmask (SIG_SETMASK, &old_set, NULL); - if (err2) { - logerr(p, err2, "%s(%s): pthread_sigmask (restore) failed", - cap, __func__); - /* We have failed to restore original signal mask, all bets are off, - so terminate the process */ - exit (EXIT_FAILURE); - } - - if (err) { - efunc = "pthread_create"; - goto err2; - } - - return 0; - - err2: - err2 = pthread_cond_destroy (&p->cond); - if (err2) { - logerr(p, err2, "%s(%s): pthread_cond_destroy failed", cap, __func__); - } - - err1: - err2 = pthread_mutex_destroy (&p->mutex); - if (err2) { - logerr(p, err2, "%s(%s): pthread_mutex_destroy failed", cap, __func__); - } - - err0: - logerr(p, err, "%s(%s): %s failed", cap, __func__, efunc); - return -1; -} - -int audio_pt_fini (struct audio_pt *p, const char *cap) -{ - int err, ret = 0; - - err = pthread_cond_destroy (&p->cond); - if (err) { - logerr(p, err, "%s(%s): pthread_cond_destroy failed", cap, __func__); - ret = -1; - } - - err = pthread_mutex_destroy (&p->mutex); - if (err) { - logerr(p, err, "%s(%s): pthread_mutex_destroy failed", cap, __func__); - ret = -1; - } - return ret; -} - -int audio_pt_lock (struct audio_pt *p, const char *cap) -{ - int err; - - err = pthread_mutex_lock (&p->mutex); - if (err) { - logerr(p, err, "%s(%s): pthread_mutex_lock failed", cap, __func__); - return -1; - } - return 0; -} - -int audio_pt_unlock (struct audio_pt *p, const char *cap) -{ - int err; - - err = pthread_mutex_unlock (&p->mutex); - if (err) { - logerr(p, err, "%s(%s): pthread_mutex_unlock failed", cap, __func__); - return -1; - } - return 0; -} - -int audio_pt_wait (struct audio_pt *p, const char *cap) -{ - int err; - - err = pthread_cond_wait (&p->cond, &p->mutex); - if (err) { - logerr(p, err, "%s(%s): pthread_cond_wait failed", cap, __func__); - return -1; - } - return 0; -} - -int audio_pt_unlock_and_signal (struct audio_pt *p, const char *cap) -{ - int err; - - err = pthread_mutex_unlock (&p->mutex); - if (err) { - logerr(p, err, "%s(%s): pthread_mutex_unlock failed", cap, __func__); - return -1; - } - err = pthread_cond_signal (&p->cond); - if (err) { - logerr(p, err, "%s(%s): pthread_cond_signal failed", cap, __func__); - return -1; - } - return 0; -} - -int audio_pt_join (struct audio_pt *p, void **arg, const char *cap) -{ - int err; - void *ret; - - err = pthread_join (p->thread, &ret); - if (err) { - logerr(p, err, "%s(%s): pthread_join failed", cap, __func__); - return -1; - } - *arg = ret; - return 0; -} diff --git a/audio/audio_pt_int.h b/audio/audio_pt_int.h deleted file mode 100644 index 4c0c15b9af..0000000000 --- a/audio/audio_pt_int.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef QEMU_AUDIO_PT_INT_H -#define QEMU_AUDIO_PT_INT_H - -#include - -struct audio_pt { - const char *drv; - pthread_t thread; - pthread_cond_t cond; - pthread_mutex_t mutex; -}; - -int audio_pt_init (struct audio_pt *, void *(*) (void *), void *, - const char *, const char *); -int audio_pt_fini (struct audio_pt *, const char *); -int audio_pt_lock (struct audio_pt *, const char *); -int audio_pt_unlock (struct audio_pt *, const char *); -int audio_pt_wait (struct audio_pt *, const char *); -int audio_pt_unlock_and_signal (struct audio_pt *, const char *); -int audio_pt_join (struct audio_pt *, void **, const char *); - -#endif /* QEMU_AUDIO_PT_INT_H */ diff --git a/audio/paaudio.c b/audio/paaudio.c index bfef9acaad..75fce53202 100644 --- a/audio/paaudio.c +++ b/audio/paaudio.c @@ -9,7 +9,6 @@ #define AUDIO_CAP "pulseaudio" #include "audio_int.h" -#include "audio_pt_int.h" typedef struct PAConnection { char *server; @@ -30,28 +29,16 @@ typedef struct { typedef struct { HWVoiceOut hw; - size_t done; - size_t live; - size_t decr; - size_t rpos; pa_stream *stream; - void *pcm_buf; - struct audio_pt pt; paaudio *g; size_t samples; } PAVoiceOut; typedef struct { HWVoiceIn hw; - size_t done; - size_t dead; - size_t incr; - size_t wpos; pa_stream *stream; - void *pcm_buf; - struct audio_pt pt; const void *read_data; - size_t read_index, read_length; + size_t read_length; paaudio *g; size_t samples; } PAVoiceIn; @@ -89,298 +76,96 @@ static inline int PA_STREAM_IS_GOOD(pa_stream_state_t x) } #endif -#define CHECK_SUCCESS_GOTO(c, rerror, expression, label) \ +#define CHECK_SUCCESS_GOTO(c, expression, label, msg) \ do { \ if (!(expression)) { \ - if (rerror) { \ - *(rerror) = pa_context_errno ((c)->context); \ - } \ + qpa_logerr(pa_context_errno((c)->context), msg); \ goto label; \ } \ } while (0) -#define CHECK_DEAD_GOTO(c, stream, rerror, label) \ +#define CHECK_DEAD_GOTO(c, stream, label, msg) \ do { \ if (!(c)->context || !PA_CONTEXT_IS_GOOD (pa_context_get_state((c)->context)) || \ !(stream) || !PA_STREAM_IS_GOOD (pa_stream_get_state ((stream)))) { \ if (((c)->context && pa_context_get_state ((c)->context) == PA_CONTEXT_FAILED) || \ ((stream) && pa_stream_get_state ((stream)) == PA_STREAM_FAILED)) { \ - if (rerror) { \ - *(rerror) = pa_context_errno ((c)->context); \ - } \ + qpa_logerr(pa_context_errno((c)->context), msg); \ } else { \ - if (rerror) { \ - *(rerror) = PA_ERR_BADSTATE; \ - } \ + qpa_logerr(PA_ERR_BADSTATE, msg); \ } \ goto label; \ } \ } while (0) -static int qpa_simple_read (PAVoiceIn *p, void *data, size_t length, int *rerror) +static size_t qpa_read(HWVoiceIn *hw, void *data, size_t length) { + PAVoiceIn *p = (PAVoiceIn *) hw; PAConnection *c = p->g->conn; + size_t l; + int r; pa_threaded_mainloop_lock(c->mainloop); - CHECK_DEAD_GOTO(c, p->stream, rerror, unlock_and_fail); - - while (length > 0) { - size_t l; - - while (!p->read_data) { - int r; - - r = pa_stream_peek (p->stream, &p->read_data, &p->read_length); - CHECK_SUCCESS_GOTO(c, rerror, r == 0, unlock_and_fail); - - if (!p->read_data) { - pa_threaded_mainloop_wait(c->mainloop); - CHECK_DEAD_GOTO(c, p->stream, rerror, unlock_and_fail); - } else { - p->read_index = 0; - } - } - - l = p->read_length < length ? p->read_length : length; - memcpy (data, (const uint8_t *) p->read_data+p->read_index, l); - - data = (uint8_t *) data + l; - length -= l; + CHECK_DEAD_GOTO(c, p->stream, unlock_and_fail, + "pa_threaded_mainloop_lock failed\n"); - p->read_index += l; - p->read_length -= l; + if (!p->read_length) { + r = pa_stream_peek(p->stream, &p->read_data, &p->read_length); + CHECK_SUCCESS_GOTO(c, r == 0, unlock_and_fail, + "pa_stream_peek failed\n"); + } - if (!p->read_length) { - int r; + l = MIN(p->read_length, length); + memcpy(data, p->read_data, l); - r = pa_stream_drop (p->stream); - p->read_data = NULL; - p->read_length = 0; - p->read_index = 0; + p->read_data += l; + p->read_length -= l; - CHECK_SUCCESS_GOTO(c, rerror, r == 0, unlock_and_fail); - } + if (!p->read_length) { + r = pa_stream_drop(p->stream); + CHECK_SUCCESS_GOTO(c, r == 0, unlock_and_fail, + "pa_stream_drop failed\n"); } pa_threaded_mainloop_unlock(c->mainloop); - return 0; + return l; unlock_and_fail: pa_threaded_mainloop_unlock(c->mainloop); - return -1; + return 0; } -static int qpa_simple_write (PAVoiceOut *p, const void *data, size_t length, int *rerror) +static size_t qpa_write(HWVoiceOut *hw, void *data, size_t length) { + PAVoiceOut *p = (PAVoiceOut *) hw; PAConnection *c = p->g->conn; + size_t l; + int r; pa_threaded_mainloop_lock(c->mainloop); - CHECK_DEAD_GOTO(c, p->stream, rerror, unlock_and_fail); + CHECK_DEAD_GOTO(c, p->stream, unlock_and_fail, + "pa_threaded_mainloop_lock failed\n"); - while (length > 0) { - size_t l; - int r; + l = pa_stream_writable_size(p->stream); - while (!(l = pa_stream_writable_size (p->stream))) { - pa_threaded_mainloop_wait(c->mainloop); - CHECK_DEAD_GOTO(c, p->stream, rerror, unlock_and_fail); - } - - CHECK_SUCCESS_GOTO(c, rerror, l != (size_t) -1, unlock_and_fail); - - if (l > length) { - l = length; - } + CHECK_SUCCESS_GOTO(c, l != (size_t) -1, unlock_and_fail, + "pa_stream_writable_size failed\n"); - r = pa_stream_write (p->stream, data, l, NULL, 0LL, PA_SEEK_RELATIVE); - CHECK_SUCCESS_GOTO(c, rerror, r >= 0, unlock_and_fail); - - data = (const uint8_t *) data + l; - length -= l; + if (l > length) { + l = length; } + r = pa_stream_write(p->stream, data, l, NULL, 0LL, PA_SEEK_RELATIVE); + CHECK_SUCCESS_GOTO(c, r >= 0, unlock_and_fail, "pa_stream_write failed\n"); + pa_threaded_mainloop_unlock(c->mainloop); - return 0; + return l; unlock_and_fail: pa_threaded_mainloop_unlock(c->mainloop); - return -1; -} - -static void *qpa_thread_out (void *arg) -{ - PAVoiceOut *pa = arg; - HWVoiceOut *hw = &pa->hw; - - if (audio_pt_lock(&pa->pt, __func__)) { - return NULL; - } - - for (;;) { - size_t decr, to_mix, rpos; - - for (;;) { - if (pa->done) { - goto exit; - } - - if (pa->live > 0) { - break; - } - - if (audio_pt_wait(&pa->pt, __func__)) { - goto exit; - } - } - - decr = to_mix = MIN(pa->live, pa->samples >> 5); - rpos = pa->rpos; - - if (audio_pt_unlock(&pa->pt, __func__)) { - return NULL; - } - - while (to_mix) { - int error; - size_t chunk = MIN (to_mix, hw->samples - rpos); - struct st_sample *src = hw->mix_buf + rpos; - - hw->clip (pa->pcm_buf, src, chunk); - - if (qpa_simple_write (pa, pa->pcm_buf, - chunk << hw->info.shift, &error) < 0) { - qpa_logerr (error, "pa_simple_write failed\n"); - return NULL; - } - - rpos = (rpos + chunk) % hw->samples; - to_mix -= chunk; - } - - if (audio_pt_lock(&pa->pt, __func__)) { - return NULL; - } - - pa->rpos = rpos; - pa->live -= decr; - pa->decr += decr; - } - - exit: - audio_pt_unlock(&pa->pt, __func__); - return NULL; -} - -static size_t qpa_run_out(HWVoiceOut *hw, size_t live) -{ - size_t decr; - PAVoiceOut *pa = (PAVoiceOut *) hw; - - if (audio_pt_lock(&pa->pt, __func__)) { - return 0; - } - - decr = MIN (live, pa->decr); - pa->decr -= decr; - pa->live = live - decr; - hw->rpos = pa->rpos; - if (pa->live > 0) { - audio_pt_unlock_and_signal(&pa->pt, __func__); - } - else { - audio_pt_unlock(&pa->pt, __func__); - } - return decr; -} - -/* capture */ -static void *qpa_thread_in (void *arg) -{ - PAVoiceIn *pa = arg; - HWVoiceIn *hw = &pa->hw; - - if (audio_pt_lock(&pa->pt, __func__)) { - return NULL; - } - - for (;;) { - size_t incr, to_grab, wpos; - - for (;;) { - if (pa->done) { - goto exit; - } - - if (pa->dead > 0) { - break; - } - - if (audio_pt_wait(&pa->pt, __func__)) { - goto exit; - } - } - - incr = to_grab = MIN(pa->dead, pa->samples >> 5); - wpos = pa->wpos; - - if (audio_pt_unlock(&pa->pt, __func__)) { - return NULL; - } - - while (to_grab) { - int error; - size_t chunk = MIN (to_grab, hw->samples - wpos); - void *buf = advance (pa->pcm_buf, wpos); - - if (qpa_simple_read (pa, buf, - chunk << hw->info.shift, &error) < 0) { - qpa_logerr (error, "pa_simple_read failed\n"); - return NULL; - } - - hw->conv (hw->conv_buf + wpos, buf, chunk); - wpos = (wpos + chunk) % hw->samples; - to_grab -= chunk; - } - - if (audio_pt_lock(&pa->pt, __func__)) { - return NULL; - } - - pa->wpos = wpos; - pa->dead -= incr; - pa->incr += incr; - } - - exit: - audio_pt_unlock(&pa->pt, __func__); - return NULL; -} - -static size_t qpa_run_in(HWVoiceIn *hw) -{ - size_t live, incr, dead; - PAVoiceIn *pa = (PAVoiceIn *) hw; - - if (audio_pt_lock(&pa->pt, __func__)) { - return 0; - } - - live = audio_pcm_hw_get_live_in (hw); - dead = hw->samples - live; - incr = MIN (dead, pa->incr); - pa->incr -= incr; - pa->dead = dead - incr; - hw->wpos = pa->wpos; - if (pa->dead > 0) { - audio_pt_unlock_and_signal(&pa->pt, __func__); - } - else { - audio_pt_unlock(&pa->pt, __func__); - } - return incr; + return 0; } static pa_sample_format_t audfmt_to_pa (AudioFormat afmt, int endianness) @@ -468,13 +253,6 @@ static void stream_state_cb (pa_stream *s, void * userdata) } } -static void stream_request_cb (pa_stream *s, size_t length, void *userdata) -{ - PAConnection *c = userdata; - - pa_threaded_mainloop_signal(c->mainloop, 0); -} - static pa_stream *qpa_simple_new ( PAConnection *c, const char *name, @@ -497,8 +275,6 @@ static pa_stream *qpa_simple_new ( } pa_stream_set_state_callback(stream, stream_state_cb, c); - pa_stream_set_read_callback(stream, stream_request_cb, c); - pa_stream_set_write_callback(stream, stream_request_cb, c); flags = PA_STREAM_INTERPOLATE_TIMING @@ -579,28 +355,9 @@ static int qpa_init_out(HWVoiceOut *hw, struct audsettings *as, hw->samples = pa->samples = audio_buffer_samples( qapi_AudiodevPaPerDirectionOptions_base(ppdo), &obt_as, ppdo->buffer_length); - pa->pcm_buf = audio_calloc(__func__, hw->samples, 1 << hw->info.shift); - pa->rpos = hw->rpos; - if (!pa->pcm_buf) { - dolog("Could not allocate buffer (%zu bytes)\n", - hw->samples << hw->info.shift); - goto fail2; - } - - if (audio_pt_init(&pa->pt, qpa_thread_out, hw, AUDIO_CAP, __func__)) { - goto fail3; - } return 0; - fail3: - g_free (pa->pcm_buf); - pa->pcm_buf = NULL; - fail2: - if (pa->stream) { - pa_stream_unref (pa->stream); - pa->stream = NULL; - } fail1: return -1; } @@ -647,28 +404,9 @@ static int qpa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) hw->samples = pa->samples = audio_buffer_samples( qapi_AudiodevPaPerDirectionOptions_base(ppdo), &obt_as, ppdo->buffer_length); - pa->pcm_buf = audio_calloc(__func__, hw->samples, 1 << hw->info.shift); - pa->wpos = hw->wpos; - if (!pa->pcm_buf) { - dolog("Could not allocate buffer (%zu bytes)\n", - hw->samples << hw->info.shift); - goto fail2; - } - - if (audio_pt_init(&pa->pt, qpa_thread_in, hw, AUDIO_CAP, __func__)) { - goto fail3; - } return 0; - fail3: - g_free (pa->pcm_buf); - pa->pcm_buf = NULL; - fail2: - if (pa->stream) { - pa_stream_unref (pa->stream); - pa->stream = NULL; - } fail1: return -1; } @@ -696,42 +434,22 @@ static void qpa_simple_disconnect(PAConnection *c, pa_stream *stream) static void qpa_fini_out (HWVoiceOut *hw) { - void *ret; PAVoiceOut *pa = (PAVoiceOut *) hw; - audio_pt_lock(&pa->pt, __func__); - pa->done = 1; - audio_pt_unlock_and_signal(&pa->pt, __func__); - audio_pt_join(&pa->pt, &ret, __func__); - if (pa->stream) { qpa_simple_disconnect(pa->g->conn, pa->stream); pa->stream = NULL; } - - audio_pt_fini(&pa->pt, __func__); - g_free (pa->pcm_buf); - pa->pcm_buf = NULL; } static void qpa_fini_in (HWVoiceIn *hw) { - void *ret; PAVoiceIn *pa = (PAVoiceIn *) hw; - audio_pt_lock(&pa->pt, __func__); - pa->done = 1; - audio_pt_unlock_and_signal(&pa->pt, __func__); - audio_pt_join(&pa->pt, &ret, __func__); - if (pa->stream) { qpa_simple_disconnect(pa->g->conn, pa->stream); pa->stream = NULL; } - - audio_pt_fini(&pa->pt, __func__); - g_free (pa->pcm_buf); - pa->pcm_buf = NULL; } static int qpa_ctl_out (HWVoiceOut *hw, int cmd, ...) @@ -1005,12 +723,12 @@ static void qpa_audio_fini (void *opaque) static struct audio_pcm_ops qpa_pcm_ops = { .init_out = qpa_init_out, .fini_out = qpa_fini_out, - .run_out = qpa_run_out, + .write = qpa_write, .ctl_out = qpa_ctl_out, .init_in = qpa_init_in, .fini_in = qpa_fini_in, - .run_in = qpa_run_in, + .read = qpa_read, .ctl_in = qpa_ctl_in }; diff --git a/configure b/configure index 30aad233d1..d72ea39bb7 100755 --- a/configure +++ b/configure @@ -297,7 +297,6 @@ host_cc="cc" libs_cpu="" libs_softmmu="" libs_tools="" -audio_pt_int="" audio_win_int="" libs_qga="" debug_info="yes" @@ -3383,7 +3382,6 @@ for drv in $audio_drv_list; do pa | try-pa) if $pkg_config libpulse --exists; then pulse_libs=$($pkg_config libpulse --libs) - audio_pt_int="yes" if test "$drv" = "try-pa"; then audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/try-pa/pa/') fi @@ -6606,9 +6604,6 @@ echo "PULSE_LIBS=$pulse_libs" >> $config_host_mak echo "COREAUDIO_LIBS=$coreaudio_libs" >> $config_host_mak echo "DSOUND_LIBS=$dsound_libs" >> $config_host_mak echo "OSS_LIBS=$oss_libs" >> $config_host_mak -if test "$audio_pt_int" = "yes" ; then - echo "CONFIG_AUDIO_PT_INT=y" >> $config_host_mak -fi if test "$audio_win_int" = "yes" ; then echo "CONFIG_AUDIO_WIN_INT=y" >> $config_host_mak fi From patchwork Thu Sep 19 21:24:16 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?UTF-8?B?Wm9sdMOhbiBLxZF2w6Fnw7M=?= X-Patchwork-Id: 1164895 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="GZoy3rJ+"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46Z9Lb0T0nz9sNf for ; Fri, 20 Sep 2019 07:42:47 +1000 (AEST) Received: from localhost ([::1]:48722 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB4CK-000371-DR for incoming@patchwork.ozlabs.org; Thu, 19 Sep 2019 17:42:44 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53534) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB3um-0002ka-BT for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:38 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iB3ui-0000bA-7a for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:35 -0400 Received: from mail-wr1-x444.google.com ([2a00:1450:4864:20::444]:40382) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iB3uh-0000ab-NU for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:31 -0400 Received: by mail-wr1-x444.google.com with SMTP id l3so4606216wru.7 for ; Thu, 19 Sep 2019 14:24:31 -0700 (PDT) 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=DqChsnZIXAGMvroXVL0MQvbI8g2z6bOPhBgHC6Jjg7E=; b=GZoy3rJ+MBZPHWm8aLBo+DW4vhl+T6zJX5wzbxAkNBxcje9tixaySk378VTxtJBS4R 7QQdVkYZ9ucpmSAOdW3K0QFLZB12zzzhLZszAsjhrPuwZgSb6+NlgzZC3d3FkfG1WZbW PKQVa87wST5WIWuLUMlUVQWPg6h1Yynokgxpjt/O7oW4lCCEcXS3lNnh6qhhTkz/b33c /VXfsrnCUFo9re1me/gfA3oQa+rEivvweqMJZpG5FQgw7tRs7Dy5CWU3f2mC5XVctAyz YYgSbnAYY+R1AQ1n+7HQWq6+8Hl0R7J5AsMj7oQv4GlwhuYtD6r3X94CB4H7NZJOVDWf 2fYw== 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=DqChsnZIXAGMvroXVL0MQvbI8g2z6bOPhBgHC6Jjg7E=; b=VHolHVZCixaU+D1GG6LEFwHZcbX7ZasF0RiTVH9U7HuPFzlbS3av8Us7W0PegAp/9m fYUpImX/XOJSx1rS6TSg6BJHvs3l4mV4fRQvZNi+Depz7bP8aOElt3Irl8IO+58Ilvi+ NCLloBMfAPqPor9KtiL8zCqZnF/OjYdnYLqWQEBtO9pzOiJ8ACOsGEW+PH6a/V4tw08m K0A5mUK5nBuXfj/14YVUvfh1Xx8eJa/mbs1oguYLW7D9+Z/4RAEEAeS7V3wAeMASMSrE EXgh3Y7LIbSEptzXfs7BQYVhETLdjkbue76hNWKYsF8S9MLig36nL9oIoJAmyFJ8errM fOqg== X-Gm-Message-State: APjAAAVpEJtPNSlz+OO//sbCmxCynreVbTRS5WRFQcDcQBcex9ZnsvlL XskcETij/M2S4hKOTTMGUX+V2fK5 X-Google-Smtp-Source: APXvYqyj4jqMyVqM9gCjrgzpFzSPmLnJPDKuuBIqumfRIYx+IKExCAxZFTSZz9ZVkuDoI1l+ILmgyA== X-Received: by 2002:a5d:4582:: with SMTP id p2mr9162217wrq.305.1568928270279; Thu, 19 Sep 2019 14:24:30 -0700 (PDT) Received: from nullptr.home.dirty-ice.org (2a01-036c-0113-74ef-0000-0000-0000-0005.pool6.digikabel.hu. [2a01:36c:113:74ef::5]) by smtp.gmail.com with ESMTPSA id w125sm13191292wmg.32.2019.09.19.14.24.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Sep 2019 14:24:29 -0700 (PDT) From: "=?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?=" X-Google-Original-From: =?utf-8?b?S8WRdsOhZ8OzLCBab2x0w6Fu?= To: qemu-devel@nongnu.org Subject: [PATCH v4 08/24] sdlaudio: port to the new audio backend api Date: Thu, 19 Sep 2019 23:24:16 +0200 Message-Id: X-Mailer: git-send-email 2.23.0 In-Reply-To: References: MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::444 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Gerd Hoffmann Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Signed-off-by: Kővágó, Zoltán --- audio/sdlaudio.c | 87 +++++++++++++++++++++++------------------------- 1 file changed, 42 insertions(+), 45 deletions(-) diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c index 14b11f0335..f7ac8cd101 100644 --- a/audio/sdlaudio.c +++ b/audio/sdlaudio.c @@ -41,8 +41,6 @@ typedef struct SDLVoiceOut { HWVoiceOut hw; - size_t live; - size_t decr; } SDLVoiceOut; static struct SDLAudioState { @@ -184,62 +182,59 @@ static void sdl_callback (void *opaque, Uint8 *buf, int len) SDLVoiceOut *sdl = opaque; SDLAudioState *s = &glob_sdl; HWVoiceOut *hw = &sdl->hw; - size_t samples = len >> hw->info.shift; - size_t to_mix, decr; - if (s->exit || !sdl->live) { + if (s->exit) { return; } /* dolog ("in callback samples=%zu live=%zu\n", samples, sdl->live); */ - to_mix = MIN(samples, sdl->live); - decr = to_mix; - while (to_mix) { - size_t chunk = MIN(to_mix, hw->samples - hw->rpos); - struct st_sample *src = hw->mix_buf + hw->rpos; - - /* dolog ("in callback to_mix %zu, chunk %zu\n", to_mix, chunk); */ - hw->clip(buf, src, chunk); - hw->rpos = (hw->rpos + chunk) % hw->samples; - to_mix -= chunk; - buf += chunk << hw->info.shift; + while (hw->pending_emul && len) { + size_t write_len; + ssize_t start = ((ssize_t) hw->pos_emul) - hw->pending_emul; + if (start < 0) { + start += hw->size_emul; + } + assert(start >= 0 && start < hw->size_emul); + + write_len = MIN(MIN(hw->pending_emul, len), + hw->size_emul - start); + + memcpy(buf, hw->buf_emul + start, write_len); + hw->pending_emul -= write_len; + len -= write_len; + buf += write_len; } - samples -= decr; - sdl->live -= decr; - sdl->decr += decr; - /* dolog ("done len=%zu\n", len); */ - - /* SDL2 does not clear the remaining buffer for us, so do it on our own */ - if (samples) { - memset(buf, 0, samples << hw->info.shift); + /* clear remaining buffer that we couldn't fill with data */ + if (len) { + memset(buf, 0, len); } } -static size_t sdl_run_out(HWVoiceOut *hw, size_t live) -{ - size_t decr; - SDLVoiceOut *sdl = (SDLVoiceOut *) hw; - - SDL_LockAudio(); - - if (sdl->decr > live) { - ldebug ("sdl->decr %d live %d sdl->live %d\n", - sdl->decr, - live, - sdl->live); +#define SDL_WRAPPER_FUNC(name, ret_type, args_decl, args, fail, unlock) \ + static ret_type glue(sdl_, name)args_decl \ + { \ + ret_type ret; \ + \ + SDL_LockAudio(); \ + \ + ret = glue(audio_generic_, name)args; \ + \ + SDL_UnlockAudio(); \ + return ret; \ } - decr = MIN (sdl->decr, live); - sdl->decr -= decr; - - sdl->live = live; +SDL_WRAPPER_FUNC(get_buffer_out, void *, (HWVoiceOut *hw, size_t *size), + (hw, size), *size = 0, sdl_unlock) +SDL_WRAPPER_FUNC(put_buffer_out_nowrite, size_t, + (HWVoiceOut *hw, void *buf, size_t size), (hw, buf, size), + /*nothing*/, sdl_unlock_and_post) +SDL_WRAPPER_FUNC(write, size_t, + (HWVoiceOut *hw, void *buf, size_t size), (hw, buf, size), + /*nothing*/, sdl_unlock_and_post) - SDL_UnlockAudio(); - - return decr; -} +#undef SDL_WRAPPER_FUNC static void sdl_fini_out (HWVoiceOut *hw) { @@ -336,7 +331,9 @@ static void sdl_audio_fini (void *opaque) static struct audio_pcm_ops sdl_pcm_ops = { .init_out = sdl_init_out, .fini_out = sdl_fini_out, - .run_out = sdl_run_out, + .write = sdl_write, + .get_buffer_out = sdl_get_buffer_out, + .put_buffer_out = sdl_put_buffer_out_nowrite, .ctl_out = sdl_ctl_out, }; From patchwork Thu Sep 19 21:24:18 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?UTF-8?B?Wm9sdMOhbiBLxZF2w6Fnw7M=?= X-Patchwork-Id: 1164891 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="SLWRQjRf"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46Z9D54Vj8z9sNf for ; Fri, 20 Sep 2019 07:37:09 +1000 (AEST) Received: from localhost ([::1]:48678 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB46s-0004Jj-Kd for incoming@patchwork.ozlabs.org; Thu, 19 Sep 2019 17:37:06 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53572) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB3uq-0002oz-KN for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:42 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iB3uo-0000ex-9O for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:40 -0400 Received: from mail-wr1-x42f.google.com ([2a00:1450:4864:20::42f]:40962) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iB3um-0000bf-5o for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:37 -0400 Received: by mail-wr1-x42f.google.com with SMTP id h7so4600542wrw.8 for ; Thu, 19 Sep 2019 14:24:33 -0700 (PDT) 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=I1lTNtGdmCXDaEAxgrssEq6HlR95R7rdwP0M4w4IEEo=; b=SLWRQjRfTBl2M1TNSdQ4dKVNKSadRdGd+XpCibc1dpzIi5FfTtJ/ULTJn4fjhsvEs3 uzTKHeQ2fL0RRmoXHYy+HNbFOgNRHhodDXoBJ2Dfok4q9GZsFkC5OlgHhTD9OiDFq+mv C4RcvvJzRSktwEuF8hiQ78zgftN/R7iIPX0HQsy6F76Rf35J96k7rqUyd6+sVySAso0S c+D93kxq06GvJ9V9mbEhIcRZoVKRMgU3WinQhRnlngAUqn1skdNhXBMPZokW/WR7LWck yOfsRx0pqhjmowZimLz94L0O2lUIJj79QppziDTuPPm+BGgxr2k4TglgBLUs8vAAwA8l /0Zg== 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=I1lTNtGdmCXDaEAxgrssEq6HlR95R7rdwP0M4w4IEEo=; b=BY8Ea6ujYBATKGKiCt5kIDz0oLiOffQfPjAKnR7DOKLozGBh8M58QBbj9wIVJFFHsZ KsoqT9Edc0UVOkYax8AjVoloe65SU5bM0a6Dgikg8L/DiL3g1b0JuEcSV/FtN4GA/oLS 3uTFOiWdbbylb9Tk3vR15NuC4LFRrlXZ6dkgisxbhAjg28AXhFWaCvkLrla++0sfYNlc 1IdgYu0hbmL+CXToqaQGAMaugeEMuYV9nuhKXQ2wbwexSwWoZJuLH3+qVYWaaILGC7Fe 3V7dQSJ6rmZ7kaMumdHBZIGKxV7m2TGEr98W2lTTKTfxPiXi5Ha8ZaE+jvZkkFKUo/ny V4fw== X-Gm-Message-State: APjAAAVh+geQuuAiLzkd31HfnhbiofVPAxW/4ZiV7CDsAdikpqzOxiZY x7ktVZMaWq20euv3GonnWBDa81sd X-Google-Smtp-Source: APXvYqx2l8reSeyBKZTu2QZYuXmUiH6QPK6syP7WnrUufcjbh2Jp4OP7CSVONRUGLYxiS4jRjxX0WA== X-Received: by 2002:a5d:620d:: with SMTP id y13mr7861038wru.86.1568928272515; Thu, 19 Sep 2019 14:24:32 -0700 (PDT) Received: from nullptr.home.dirty-ice.org (2a01-036c-0113-74ef-0000-0000-0000-0005.pool6.digikabel.hu. [2a01:36c:113:74ef::5]) by smtp.gmail.com with ESMTPSA id w125sm13191292wmg.32.2019.09.19.14.24.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Sep 2019 14:24:31 -0700 (PDT) From: "=?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?=" X-Google-Original-From: =?utf-8?b?S8WRdsOhZ8OzLCBab2x0w6Fu?= To: qemu-devel@nongnu.org Subject: [PATCH v4 10/24] wavaudio: port to the new audio backend api Date: Thu, 19 Sep 2019 23:24:18 +0200 Message-Id: X-Mailer: git-send-email 2.23.0 In-Reply-To: References: MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::42f X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Gerd Hoffmann Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Signed-off-by: Kővágó, Zoltán --- Notes: Changes from v3: * fix compilation on 32-bit targets audio/wavaudio.c | 54 ++++++++---------------------------------------- 1 file changed, 9 insertions(+), 45 deletions(-) diff --git a/audio/wavaudio.c b/audio/wavaudio.c index b6eeeb4e26..78af2f1338 100644 --- a/audio/wavaudio.c +++ b/audio/wavaudio.c @@ -36,52 +36,28 @@ typedef struct WAVVoiceOut { HWVoiceOut hw; FILE *f; int64_t old_ticks; - void *pcm_buf; int total_samples; } WAVVoiceOut; -static size_t wav_run_out(HWVoiceOut *hw, size_t live) +static size_t wav_write_out(HWVoiceOut *hw, void *buf, size_t len) { WAVVoiceOut *wav = (WAVVoiceOut *) hw; - size_t rpos, decr, samples; - uint8_t *dst; - struct st_sample *src; int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); int64_t ticks = now - wav->old_ticks; int64_t bytes = muldiv64(ticks, hw->info.bytes_per_second, NANOSECONDS_PER_SECOND); - if (bytes > INT_MAX) { - samples = INT_MAX >> hw->info.shift; - } - else { - samples = bytes >> hw->info.shift; - } - + bytes = MIN(bytes, len); + bytes = bytes >> hw->info.shift << hw->info.shift; wav->old_ticks = now; - decr = MIN (live, samples); - samples = decr; - rpos = hw->rpos; - while (samples) { - int left_till_end_samples = hw->samples - rpos; - int convert_samples = MIN (samples, left_till_end_samples); - - src = hw->mix_buf + rpos; - dst = advance (wav->pcm_buf, rpos << hw->info.shift); - - hw->clip (dst, src, convert_samples); - if (fwrite (dst, convert_samples << hw->info.shift, 1, wav->f) != 1) { - dolog ("wav_run_out: fwrite of %d bytes failed\nReaons: %s\n", - convert_samples << hw->info.shift, strerror (errno)); - } - rpos = (rpos + convert_samples) % hw->samples; - samples -= convert_samples; - wav->total_samples += convert_samples; + if (bytes && fwrite(buf, bytes, 1, wav->f) != 1) { + dolog("wav_write_out: fwrite of %" PRId64 " bytes failed\nReason: %s\n", + bytes, strerror(errno)); } - hw->rpos = rpos; - return decr; + wav->total_samples += bytes >> hw->info.shift; + return bytes; } /* VICE code: Store number as little endian. */ @@ -137,13 +113,6 @@ static int wav_init_out(HWVoiceOut *hw, struct audsettings *as, audio_pcm_init_info (&hw->info, &wav_as); hw->samples = 1024; - wav->pcm_buf = audio_calloc(__func__, hw->samples, 1 << hw->info.shift); - if (!wav->pcm_buf) { - dolog("Could not allocate buffer (%zu bytes)\n", - hw->samples << hw->info.shift); - return -1; - } - le_store (hdr + 22, hw->info.nchannels, 2); le_store (hdr + 24, hw->info.freq, 4); le_store (hdr + 28, hw->info.freq << (bits16 + stereo), 4); @@ -153,8 +122,6 @@ static int wav_init_out(HWVoiceOut *hw, struct audsettings *as, if (!wav->f) { dolog ("Failed to open wave file `%s'\nReason: %s\n", wav_path, strerror(errno)); - g_free (wav->pcm_buf); - wav->pcm_buf = NULL; return -1; } @@ -208,9 +175,6 @@ static void wav_fini_out (HWVoiceOut *hw) wav->f, strerror (errno)); } wav->f = NULL; - - g_free (wav->pcm_buf); - wav->pcm_buf = NULL; } static int wav_ctl_out (HWVoiceOut *hw, int cmd, ...) @@ -234,7 +198,7 @@ static void wav_audio_fini (void *opaque) static struct audio_pcm_ops wav_pcm_ops = { .init_out = wav_init_out, .fini_out = wav_fini_out, - .run_out = wav_run_out, + .write = wav_write_out, .ctl_out = wav_ctl_out, }; From patchwork Thu Sep 19 21:24:19 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?UTF-8?B?Wm9sdMOhbiBLxZF2w6Fnw7M=?= X-Patchwork-Id: 1164889 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="bovBLDSJ"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46Z9Cv68GTz9sNf for ; Fri, 20 Sep 2019 07:36:58 +1000 (AEST) Received: from localhost ([::1]:48670 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB46g-0003vK-NK for incoming@patchwork.ozlabs.org; Thu, 19 Sep 2019 17:36:54 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53573) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB3uq-0002p1-KV for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:42 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iB3uo-0000f5-AX for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:40 -0400 Received: from mail-wr1-x444.google.com ([2a00:1450:4864:20::444]:42848) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iB3um-0000c1-6a for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:38 -0400 Received: by mail-wr1-x444.google.com with SMTP id n14so4593161wrw.9 for ; Thu, 19 Sep 2019 14:24:34 -0700 (PDT) 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=9dCYX3ixRkcD+NNYc2l8dezINSISvFmfcL42McUxrm0=; b=bovBLDSJNnZOgdbXvDo8RtHwR+LPe/4E4GAsQD0Cc8m4Pg+bf4IrbLTcxMwUGiQE8e G/xpt23eZubCz0w1hqlvjr30VNKDxxPAqIJ/WHHhknM0wmdZgUx0bA+CN0VMskTwRMD9 A9M+3+CmQrh+acr2x1PA3EgzTbCyt+/BQch4P1aafoqiIUHVdG5qLMnqUpJdlOU3zC02 PMZo7/YBG3RPNb6MId1s8XxaSEhaEMO7QoyWAUVftYVZAt8GB7zdx9vbxV9e52IhBJ+H CgMskfQ+qNW2u1X6kt9prMEpaePHPT0CQ+ZnS2J17ASe5FhisLGoxYdt3jOjLwwz/Jbq MiQA== 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=9dCYX3ixRkcD+NNYc2l8dezINSISvFmfcL42McUxrm0=; b=oh5HizJZRc/jyFr28t0NyIh7SNdL2QJcxyavCZFC5kDuhhj/tYqd9PuA5iQMR9EOHh X93N18SZw0vT9ceAyMVCYf6CUnSKNHSJqqfmUdOD9USaFD+Gs/3y+SKdUjTscGzrP5Hh tLQcqJs38w5sfEtanwxeeuei7KhfoVRmiAZsKkLmDDhjrBj2hfR6tchQ8jJLlbRQ0uXS OcEItBisbow6dFgW4eH8PXVru+IomLM/D5Uvt9wVZqBX6107MY2Rd9tvvhbEo+EmjWPu kax4ySNmSUyhwxIAyx6FFwyPW937W8+U69K6e/FQjlciLtyW2MOV9K9/vkUjgzkPI55G uHkA== X-Gm-Message-State: APjAAAVQGiaF/gRK8pY2EU2HB7pkp8E7ZA1fWJg2sOG9jttod25oKTK6 PeJ0cARYjMm1OFnDt4rIW8dwU3po X-Google-Smtp-Source: APXvYqw1z6OfEI2T3e7BW0Ep3EM8RMtg1BGiHKGmZhLHVxnZuroF691FuFpIRmDMW6cE6s53xoaSdQ== X-Received: by 2002:a5d:628f:: with SMTP id k15mr7984384wru.124.1568928273602; Thu, 19 Sep 2019 14:24:33 -0700 (PDT) Received: from nullptr.home.dirty-ice.org (2a01-036c-0113-74ef-0000-0000-0000-0005.pool6.digikabel.hu. [2a01:36c:113:74ef::5]) by smtp.gmail.com with ESMTPSA id w125sm13191292wmg.32.2019.09.19.14.24.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Sep 2019 14:24:33 -0700 (PDT) From: "=?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?=" X-Google-Original-From: =?utf-8?b?S8WRdsOhZ8OzLCBab2x0w6Fu?= To: qemu-devel@nongnu.org Subject: [PATCH v4 11/24] audio: remove remains of the old backend api Date: Thu, 19 Sep 2019 23:24:19 +0200 Message-Id: <497decab6d0f0fb9529bea63ec7ce0bd7b553038.1568927990.git.DirtY.iCE.hu@gmail.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: References: MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::444 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Gerd Hoffmann Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Signed-off-by: Kővágó, Zoltán --- audio/audio.c | 42 ++++++------------------------------------ audio/audio_int.h | 7 ------- 2 files changed, 6 insertions(+), 43 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index e29a1e15eb..435bcf20c1 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -541,7 +541,7 @@ static size_t audio_pcm_hw_find_min_in (HWVoiceIn *hw) return m; } -size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw) +static size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw) { size_t live = hw->total_samples_captured - audio_pcm_hw_find_min_in (hw); if (audio_bug(__func__, live > hw->samples)) { @@ -551,29 +551,7 @@ size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw) return live; } -size_t audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, - size_t live, size_t pending) -{ - size_t left = hw->samples - pending; - size_t len = MIN (left, live); - size_t clipped = 0; - - while (len) { - struct st_sample *src = hw->mix_buf + hw->rpos; - uint8_t *dst = advance (pcm_buf, hw->rpos << hw->info.shift); - size_t samples_till_end_of_buf = hw->samples - hw->rpos; - size_t samples_to_clip = MIN (len, samples_till_end_of_buf); - - hw->clip (dst, src, samples_to_clip); - - hw->rpos = (hw->rpos + samples_to_clip) % hw->samples; - len -= samples_to_clip; - clipped += samples_to_clip; - } - return clipped; -} - -static void audio_pcm_hw_clip_out2(HWVoiceOut *hw, void *pcm_buf, size_t len) +static void audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, size_t len) { size_t clipped = 0; size_t pos = hw->rpos; @@ -1083,7 +1061,7 @@ static size_t audio_pcm_hw_run_out(HWVoiceOut *hw, size_t live) } decr = MIN(size >> hw->info.shift, live); - audio_pcm_hw_clip_out2(hw, buf, decr); + audio_pcm_hw_clip_out(hw, buf, decr); proc = hw->pcm_ops->put_buffer_out(hw, buf, decr << hw->info.shift) >> hw->info.shift; @@ -1146,11 +1124,7 @@ static void audio_run_out (AudioState *s) } prev_rpos = hw->rpos; - if (hw->pcm_ops->run_out) { - played = hw->pcm_ops->run_out(hw, live); - } else { - played = audio_pcm_hw_run_out(hw, live); - } + played = audio_pcm_hw_run_out(hw, live); replay_audio_out(&played); if (audio_bug(__func__, hw->rpos >= hw->samples)) { dolog("hw->rpos=%zu hw->samples=%zu played=%zu\n", @@ -1247,12 +1221,8 @@ static void audio_run_in (AudioState *s) size_t captured = 0, min; if (replay_mode != REPLAY_MODE_PLAY) { - if (hw->pcm_ops->run_in) { - captured = hw->pcm_ops->run_in(hw); - } else { - captured = audio_pcm_hw_run_in( - hw, hw->samples - audio_pcm_hw_get_live_in(hw)); - } + captured = 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); diff --git a/audio/audio_int.h b/audio/audio_int.h index 8fb1ca8a8d..c76d7c39e8 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -153,7 +153,6 @@ struct audio_driver { struct audio_pcm_ops { int (*init_out)(HWVoiceOut *hw, audsettings *as, void *drv_opaque); void (*fini_out)(HWVoiceOut *hw); - size_t (*run_out)(HWVoiceOut *hw, size_t live); size_t (*write) (HWVoiceOut *hw, void *buf, size_t size); /* * get a buffer that after later can be passed to put_buffer_out; optional @@ -171,7 +170,6 @@ struct audio_pcm_ops { int (*init_in) (HWVoiceIn *hw, audsettings *as, void *drv_opaque); void (*fini_in) (HWVoiceIn *hw); - size_t (*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); @@ -237,11 +235,6 @@ audio_driver *audio_driver_lookup(const char *name); void audio_pcm_init_info (struct audio_pcm_info *info, struct audsettings *as); void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len); -size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw); - -size_t audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, - size_t live, size_t pending); - int audio_bug (const char *funcname, int cond); void *audio_calloc (const char *funcname, int nmemb, size_t size); From patchwork Thu Sep 19 21:24:20 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?UTF-8?B?Wm9sdMOhbiBLxZF2w6Fnw7M=?= X-Patchwork-Id: 1164904 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="BaSOBsSY"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46Z9c95hKQz9sNf for ; Fri, 20 Sep 2019 07:54:33 +1000 (AEST) Received: from localhost ([::1]:48828 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB4Nj-0007GD-9G for incoming@patchwork.ozlabs.org; Thu, 19 Sep 2019 17:54:31 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53603) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB3us-0002q2-NS for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:46 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iB3uo-0000fA-BE for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:42 -0400 Received: from mail-wr1-x443.google.com ([2a00:1450:4864:20::443]:41621) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iB3um-0000cU-9F for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:38 -0400 Received: by mail-wr1-x443.google.com with SMTP id h7so4600673wrw.8 for ; Thu, 19 Sep 2019 14:24:35 -0700 (PDT) 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=Gi7pblj+Bwol9X24xindAAcvDumLdRvVUdNioHniCYg=; b=BaSOBsSYSWbFu+g0HUlWUo0cCTzKDoD2rvpXpZ/cXfOVu7ECOhI1Io41rc2EWPS7T6 WalhlPhj1o2hQJ7FZJIaXbBXAxlAYlghKJWoZXw8ar4bEampx9kB4tPCa11FtJBRxHDY 9BkfbubQx8C+brzKffPoH/JM5CPVMSc5nQ+dG61+HuqQPQqZlgwUilw4a8i+4dVfMDSV ZXNhW74yMJuWpFuz2qhPy5uLcFY6FeqkTkPmGWu5BtnRAxNWK7UATTvh4grmXPALFCtR 37r7qUgDxoTH6woa9pcUwn4RSf8+KDxx+CKTv2erhP3ep9oHGwn/72LsSkWh9y/kgS8b pEWg== 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=Gi7pblj+Bwol9X24xindAAcvDumLdRvVUdNioHniCYg=; b=UzUPqqUn6XFo48LxP9RiG1U47vcESusM9UR0uG1DaVl789zD7d8KiwZSjbUdNpPTkU XCFule9mOq0j/049GLgdIoxrbqb0OoctUjxPJEluHLV9bW7Y3ntNRX2iyQfz6cmepqXf if5SBGZrtVirpvti9Gdo1ckrHY2Jh09CFq449liR2x38ms9abr30ltUaCcDh/iHl6iuL wZnoqUlfy9iwPhxhSE+uWLgpe5H6X2LMEdq2j3QrIUODobWgwI7QQ0j6iGNDKoxvVfSM ivueb6fo5kn2weYBMuJtcEbn/7gjbJd/Ogy0qiBc1G3ohyPnMe0+QsLktu8abr/lIP07 KaUA== X-Gm-Message-State: APjAAAVP5vUK8L6P3S8uam2K1ijhegks9HV8hTcKzzI6fGrHf9+PDMdx wXskMDxymhJPmZm1I/XZxctyMyGM X-Google-Smtp-Source: APXvYqyFi0qHutc6LAvDJGkPS9e6k1PI1Twl+ZqBvxpgjb6zn3d5Q/fT2LFQArYgidDGZniaGJT53w== X-Received: by 2002:a5d:4c45:: with SMTP id n5mr8478642wrt.100.1568928274391; Thu, 19 Sep 2019 14:24:34 -0700 (PDT) Received: from nullptr.home.dirty-ice.org (2a01-036c-0113-74ef-0000-0000-0000-0005.pool6.digikabel.hu. [2a01:36c:113:74ef::5]) by smtp.gmail.com with ESMTPSA id w125sm13191292wmg.32.2019.09.19.14.24.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Sep 2019 14:24:33 -0700 (PDT) From: "=?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?=" X-Google-Original-From: =?utf-8?b?S8WRdsOhZ8OzLCBab2x0w6Fu?= To: qemu-devel@nongnu.org Subject: [PATCH v4 12/24] audio: unify input and output mixeng buffer management Date: Thu, 19 Sep 2019 23:24:20 +0200 Message-Id: X-Mailer: git-send-email 2.23.0 In-Reply-To: References: MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::443 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Gerd Hoffmann Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Usage notes: hw->samples became hw->{mix,conv}_buf->size, except before initialization (audio_pcm_hw_alloc_resources_*), hw->samples gives the initial size of the STSampleBuffer. The next commit tries to fix this inconsistency. Signed-off-by: Kővágó, Zoltán --- audio/audio.c | 122 +++++++++++++++++++++-------------------- audio/audio_int.h | 12 ++-- audio/audio_template.h | 19 +++---- audio/ossaudio.c | 3 +- 4 files changed, 80 insertions(+), 76 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index 435bcf20c1..ba07fb77dd 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -544,8 +544,8 @@ static size_t audio_pcm_hw_find_min_in (HWVoiceIn *hw) static size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw) { size_t live = hw->total_samples_captured - audio_pcm_hw_find_min_in (hw); - if (audio_bug(__func__, live > hw->samples)) { - dolog("live=%zu hw->samples=%zu\n", live, hw->samples); + if (audio_bug(__func__, live > hw->conv_buf->size)) { + dolog("live=%zu hw->conv_buf->size=%zu\n", live, hw->conv_buf->size); return 0; } return live; @@ -554,17 +554,17 @@ static size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw) static void audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, size_t len) { size_t clipped = 0; - size_t pos = hw->rpos; + size_t pos = hw->mix_buf->pos; while (len) { - st_sample *src = hw->mix_buf + pos; + st_sample *src = hw->mix_buf->samples + pos; uint8_t *dst = advance(pcm_buf, clipped << hw->info.shift); - size_t samples_till_end_of_buf = hw->samples - pos; + size_t samples_till_end_of_buf = hw->mix_buf->size - pos; size_t samples_to_clip = MIN(len, samples_till_end_of_buf); hw->clip(dst, src, samples_to_clip); - pos = (pos + samples_to_clip) % hw->samples; + pos = (pos + samples_to_clip) % hw->mix_buf->size; len -= samples_to_clip; clipped += samples_to_clip; } @@ -579,17 +579,17 @@ static size_t audio_pcm_sw_get_rpos_in(SWVoiceIn *sw) ssize_t live = hw->total_samples_captured - sw->total_hw_samples_acquired; ssize_t rpos; - if (audio_bug(__func__, live < 0 || live > hw->samples)) { - dolog("live=%zu hw->samples=%zu\n", live, hw->samples); + if (audio_bug(__func__, live < 0 || live > hw->conv_buf->size)) { + dolog("live=%zu hw->conv_buf->size=%zu\n", live, hw->conv_buf->size); return 0; } - rpos = hw->wpos - live; + rpos = hw->conv_buf->pos - live; if (rpos >= 0) { return rpos; } else { - return hw->samples + rpos; + return hw->conv_buf->size + rpos; } } @@ -599,11 +599,11 @@ static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, size_t size) size_t samples, live, ret = 0, swlim, isamp, osamp, rpos, total = 0; struct st_sample *src, *dst = sw->buf; - rpos = audio_pcm_sw_get_rpos_in (sw) % hw->samples; + rpos = audio_pcm_sw_get_rpos_in(sw) % hw->conv_buf->size; live = hw->total_samples_captured - sw->total_hw_samples_acquired; - if (audio_bug(__func__, live > hw->samples)) { - dolog("live_in=%zu hw->samples=%zu\n", live, hw->samples); + if (audio_bug(__func__, live > hw->conv_buf->size)) { + dolog("live_in=%zu hw->conv_buf->size=%zu\n", live, hw->conv_buf->size); return 0; } @@ -616,11 +616,11 @@ static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, size_t size) swlim = MIN (swlim, samples); while (swlim) { - src = hw->conv_buf + rpos; - if (hw->wpos > rpos) { - isamp = hw->wpos - rpos; + src = hw->conv_buf->samples + rpos; + if (hw->conv_buf->pos > rpos) { + isamp = hw->conv_buf->pos - rpos; } else { - isamp = hw->samples - rpos; + isamp = hw->conv_buf->size - rpos; } if (!isamp) { @@ -630,7 +630,7 @@ static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, size_t size) st_rate_flow (sw->rate, src, dst, &isamp, &osamp); swlim -= osamp; - rpos = (rpos + isamp) % hw->samples; + rpos = (rpos + isamp) % hw->conv_buf->size; dst += osamp; ret += osamp; total += isamp; @@ -678,8 +678,8 @@ static size_t audio_pcm_hw_get_live_out (HWVoiceOut *hw, int *nb_live) if (nb_live1) { size_t live = smin; - if (audio_bug(__func__, live > hw->samples)) { - dolog("live=%zu hw->samples=%zu\n", live, hw->samples); + if (audio_bug(__func__, live > hw->mix_buf->size)) { + dolog("live=%zu hw->mix_buf->size=%zu\n", live, hw->mix_buf->size); return 0; } return live; @@ -699,11 +699,11 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t size) return size; } - hwsamples = sw->hw->samples; + hwsamples = sw->hw->mix_buf->size; live = sw->total_hw_samples_mixed; if (audio_bug(__func__, live > hwsamples)) { - dolog("live=%zu hw->samples=%zu\n", live, hwsamples); + dolog("live=%zu hw->mix_buf->size=%zu\n", live, hwsamples); return 0; } @@ -714,7 +714,7 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t size) return 0; } - wpos = (sw->hw->rpos + live) % hwsamples; + wpos = (sw->hw->mix_buf->pos + live) % hwsamples; samples = size >> sw->info.shift; dead = hwsamples - live; @@ -740,7 +740,7 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t size) st_rate_flow_mix ( sw->rate, sw->buf + pos, - sw->hw->mix_buf + wpos, + sw->hw->mix_buf->samples + wpos, &isamp, &osamp ); @@ -868,7 +868,7 @@ size_t AUD_read(SWVoiceIn *sw, void *buf, size_t size) int AUD_get_buffer_size_out (SWVoiceOut *sw) { - return sw->hw->samples << sw->hw->info.shift; + return sw->hw->mix_buf->size << sw->hw->info.shift; } void AUD_set_active_out (SWVoiceOut *sw, int on) @@ -969,8 +969,9 @@ static size_t audio_get_avail (SWVoiceIn *sw) } live = sw->hw->total_samples_captured - sw->total_hw_samples_acquired; - if (audio_bug(__func__, live > sw->hw->samples)) { - dolog("live=%zu sw->hw->samples=%zu\n", live, sw->hw->samples); + if (audio_bug(__func__, live > sw->hw->conv_buf->size)) { + dolog("live=%zu sw->hw->conv_buf->size=%zu\n", live, + sw->hw->conv_buf->size); return 0; } @@ -993,12 +994,13 @@ static size_t audio_get_free(SWVoiceOut *sw) live = sw->total_hw_samples_mixed; - if (audio_bug(__func__, live > sw->hw->samples)) { - dolog("live=%zu sw->hw->samples=%zu\n", live, sw->hw->samples); + if (audio_bug(__func__, live > sw->hw->mix_buf->size)) { + dolog("live=%zu sw->hw->mix_buf->size=%zu\n", live, + sw->hw->mix_buf->size); return 0; } - dead = sw->hw->samples - live; + dead = sw->hw->mix_buf->size - live; #ifdef DEBUG_OUT dolog ("%s: get_free live %d dead %d ret %" PRId64 "\n", @@ -1023,12 +1025,12 @@ static void audio_capture_mix_and_clear(HWVoiceOut *hw, size_t rpos, n = samples; while (n) { - size_t till_end_of_hw = hw->samples - rpos2; + 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 written; - sw->buf = hw->mix_buf + rpos2; + sw->buf = hw->mix_buf->samples + rpos2; written = audio_pcm_sw_write (sw, NULL, bytes); if (written - bytes) { dolog("Could not mix %zu bytes into a capture " @@ -1037,14 +1039,14 @@ static void audio_capture_mix_and_clear(HWVoiceOut *hw, size_t rpos, break; } n -= to_write; - rpos2 = (rpos2 + to_write) % hw->samples; + rpos2 = (rpos2 + to_write) % hw->mix_buf->size; } } } - n = MIN(samples, hw->samples - rpos); - mixeng_clear(hw->mix_buf + rpos, n); - mixeng_clear(hw->mix_buf, samples - n); + n = MIN(samples, hw->mix_buf->size - rpos); + mixeng_clear(hw->mix_buf->samples + rpos, n); + mixeng_clear(hw->mix_buf->samples, samples - n); } static size_t audio_pcm_hw_run_out(HWVoiceOut *hw, size_t live) @@ -1056,7 +1058,7 @@ static size_t audio_pcm_hw_run_out(HWVoiceOut *hw, size_t live) void *buf = hw->pcm_ops->get_buffer_out(hw, &size); if (!buf) { /* retrying will likely won't help, drop everything. */ - hw->rpos = (hw->rpos + live) % hw->samples; + hw->mix_buf->pos = (hw->mix_buf->pos + live) % hw->mix_buf->size; return clipped + live; } @@ -1067,7 +1069,7 @@ static size_t audio_pcm_hw_run_out(HWVoiceOut *hw, size_t live) live -= proc; clipped += proc; - hw->rpos = (hw->rpos + proc) % hw->samples; + hw->mix_buf->pos = (hw->mix_buf->pos + proc) % hw->mix_buf->size; if (proc == 0 || proc < decr) { break; @@ -1091,8 +1093,8 @@ static void audio_run_out (AudioState *s) live = 0; } - if (audio_bug(__func__, live > hw->samples)) { - dolog ("live=%zu hw->samples=%zu\n", live, hw->samples); + if (audio_bug(__func__, live > hw->mix_buf->size)) { + dolog("live=%zu hw->mix_buf->size=%zu\n", live, hw->mix_buf->size); continue; } @@ -1123,13 +1125,13 @@ static void audio_run_out (AudioState *s) continue; } - prev_rpos = hw->rpos; + prev_rpos = hw->mix_buf->pos; played = audio_pcm_hw_run_out(hw, live); replay_audio_out(&played); - if (audio_bug(__func__, hw->rpos >= hw->samples)) { - dolog("hw->rpos=%zu hw->samples=%zu played=%zu\n", - hw->rpos, hw->samples, played); - hw->rpos = 0; + if (audio_bug(__func__, hw->mix_buf->pos >= hw->mix_buf->size)) { + dolog("hw->mix_buf->pos=%zu hw->mix_buf->size=%zu played=%zu\n", + hw->mix_buf->pos, hw->mix_buf->size, played); + hw->mix_buf->pos = 0; } #ifdef DEBUG_OUT @@ -1186,6 +1188,7 @@ static void audio_run_out (AudioState *s) static size_t audio_pcm_hw_run_in(HWVoiceIn *hw, size_t samples) { size_t conv = 0; + STSampleBuffer *conv_buf = hw->conv_buf; while (samples) { size_t proc; @@ -1199,10 +1202,10 @@ static size_t audio_pcm_hw_run_in(HWVoiceIn *hw, size_t samples) } proc = MIN(size >> hw->info.shift, - hw->samples - hw->wpos); + conv_buf->size - conv_buf->pos); - hw->conv(hw->conv_buf + hw->wpos, buf, proc); - hw->wpos = (hw->wpos + proc) % hw->samples; + hw->conv(conv_buf->samples + conv_buf->pos, buf, proc); + conv_buf->pos = (conv_buf->pos + proc) % conv_buf->size; samples -= proc; conv += proc; @@ -1222,9 +1225,10 @@ static void audio_run_in (AudioState *s) if (replay_mode != REPLAY_MODE_PLAY) { captured = audio_pcm_hw_run_in( - hw, hw->samples - audio_pcm_hw_get_live_in(hw)); + hw, hw->conv_buf->size - audio_pcm_hw_get_live_in(hw)); } - replay_audio_in(&captured, hw->conv_buf, &hw->wpos, hw->samples); + replay_audio_in(&captured, hw->conv_buf->samples, &hw->conv_buf->pos, + hw->conv_buf->size); min = audio_pcm_hw_find_min_in (hw); hw->total_samples_captured += captured - min; @@ -1255,14 +1259,14 @@ static void audio_run_capture (AudioState *s) SWVoiceOut *sw; captured = live = audio_pcm_hw_get_live_out (hw, NULL); - rpos = hw->rpos; + rpos = hw->mix_buf->pos; while (live) { - size_t left = hw->samples - rpos; + size_t left = hw->mix_buf->size - rpos; size_t to_capture = MIN(live, left); struct st_sample *src; struct capture_callback *cb; - src = hw->mix_buf + rpos; + src = hw->mix_buf->samples + rpos; hw->clip (cap->buf, src, to_capture); mixeng_clear (src, to_capture); @@ -1270,10 +1274,10 @@ static void audio_run_capture (AudioState *s) cb->ops.capture (cb->opaque, cap->buf, to_capture << hw->info.shift); } - rpos = (rpos + to_capture) % hw->samples; + rpos = (rpos + to_capture) % hw->mix_buf->size; live -= to_capture; } - hw->rpos = rpos; + hw->mix_buf->pos = rpos; for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) { if (!sw->active && sw->empty) { @@ -1321,7 +1325,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->samples << hw->info.shift; + size_t calc_size = hw->conv_buf->size << hw->info.shift; hw->buf_emul = g_malloc(calc_size); hw->size_emul = calc_size; hw->pos_emul = hw->pending_emul = 0; @@ -1357,7 +1361,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->samples << hw->info.shift; + size_t calc_size = hw->mix_buf->size << hw->info.shift; hw->buf_emul = g_malloc(calc_size); hw->size_emul = calc_size; @@ -1764,11 +1768,11 @@ CaptureVoiceOut *AUD_add_capture( /* XXX find a more elegant way */ hw->samples = 4096 * 4; - hw->mix_buf = g_new0(struct st_sample, hw->samples); + audio_pcm_hw_alloc_resources_out(hw); audio_pcm_init_info (&hw->info, as); - cap->buf = g_malloc0_n(hw->samples, 1 << hw->info.shift); + cap->buf = g_malloc0_n(hw->mix_buf->size, 1 << hw->info.shift); hw->clip = mixeng_clip [hw->info.nchannels == 2] diff --git a/audio/audio_int.h b/audio/audio_int.h index c76d7c39e8..20021df9e8 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -52,6 +52,11 @@ struct audio_pcm_info { typedef struct AudioState AudioState; typedef struct SWVoiceCap SWVoiceCap; +typedef struct STSampleBuffer { + size_t pos, size; + st_sample samples[]; +} STSampleBuffer; + typedef struct HWVoiceOut { AudioState *s; int enabled; @@ -60,11 +65,9 @@ typedef struct HWVoiceOut { struct audio_pcm_info info; f_sample *clip; - - size_t rpos; uint64_t ts_helper; - struct st_sample *mix_buf; + STSampleBuffer *mix_buf; void *buf_emul; size_t pos_emul, pending_emul, size_emul; @@ -84,11 +87,10 @@ typedef struct HWVoiceIn { t_sample *conv; - size_t wpos; size_t total_samples_captured; uint64_t ts_helper; - struct st_sample *conv_buf; + STSampleBuffer *conv_buf; void *buf_emul; size_t pos_emul, pending_emul, size_emul; diff --git a/audio/audio_template.h b/audio/audio_template.h index ff4a173f18..87c6d2d271 100644 --- a/audio/audio_template.h +++ b/audio/audio_template.h @@ -76,16 +76,15 @@ static void glue (audio_pcm_hw_free_resources_, TYPE) (HW *hw) HWBUF = NULL; } -static bool glue(audio_pcm_hw_alloc_resources_, TYPE)(HW *hw) +static void glue(audio_pcm_hw_alloc_resources_, TYPE)(HW *hw) { - HWBUF = audio_calloc(__func__, hw->samples, sizeof(struct st_sample)); - if (!HWBUF) { - dolog("Could not allocate " NAME " buffer (%zu samples)\n", - hw->samples); - return false; + size_t samples = hw->samples; + if (audio_bug(__func__, samples == 0)) { + dolog("Attempted to allocate empty buffer\n"); } - return true; + HWBUF = g_malloc0(sizeof(STSampleBuffer) + sizeof(st_sample) * samples); + HWBUF->size = samples; } static void glue (audio_pcm_sw_free_resources_, TYPE) (SW *sw) @@ -104,7 +103,7 @@ static int glue (audio_pcm_sw_alloc_resources_, TYPE) (SW *sw) { int samples; - samples = ((int64_t) sw->hw->samples << 32) / sw->ratio; + samples = ((int64_t) sw->HWBUF->size << 32) / sw->ratio; sw->buf = audio_calloc(__func__, samples, sizeof(struct st_sample)); if (!sw->buf) { @@ -280,9 +279,7 @@ static HW *glue(audio_pcm_hw_add_new_, TYPE)(AudioState *s, [hw->info.swap_endianness] [audio_bits_to_index (hw->info.bits)]; - if (!glue(audio_pcm_hw_alloc_resources_, TYPE)(hw)) { - goto err1; - } + glue(audio_pcm_hw_alloc_resources_, TYPE)(hw); QLIST_INSERT_HEAD (&s->glue (hw_head_, TYPE), hw, entries); glue (s->nb_hw_voices_, TYPE) -= 1; diff --git a/audio/ossaudio.c b/audio/ossaudio.c index 2782512706..76c082d5e2 100644 --- a/audio/ossaudio.c +++ b/audio/ossaudio.c @@ -585,7 +585,8 @@ static int oss_ctl_out (HWVoiceOut *hw, int cmd, ...) return 0; } - audio_pcm_info_clear_buf(&hw->info, hw->buf_emul, hw->samples); + audio_pcm_info_clear_buf( + &hw->info, hw->buf_emul, hw->mix_buf->size); trig = PCM_ENABLE_OUTPUT; if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) { oss_logerr ( From patchwork Thu Sep 19 21:24:21 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?UTF-8?B?Wm9sdMOhbiBLxZF2w6Fnw7M=?= X-Patchwork-Id: 1164897 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="rsIbEQ06"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46Z9P643rKz9sNf for ; Fri, 20 Sep 2019 07:44:58 +1000 (AEST) Received: from localhost ([::1]:48736 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB4ER-0005nw-HP for incoming@patchwork.ozlabs.org; Thu, 19 Sep 2019 17:44:55 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53601) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB3us-0002q0-Mt for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:45 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iB3uq-0000hd-G2 for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:42 -0400 Received: from mail-wr1-x444.google.com ([2a00:1450:4864:20::444]:33156) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iB3uo-0000ch-6r for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:38 -0400 Received: by mail-wr1-x444.google.com with SMTP id b9so4661328wrs.0 for ; Thu, 19 Sep 2019 14:24:36 -0700 (PDT) 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=y4hrO1Uu0paB0JQc174Zf7748JlB8HDxf5+LZFaxdz0=; b=rsIbEQ06TfwRVZ1wmzumLJutCNaRqM7GZS6WyrD7cDSY9lRviBEhur8G8wOnb0luzv e5MdNpKX5OfiyGafmVB6ji/YY2qq2Thwryim1oBMP449FUXZCcEk/pbozx77LyR3HKIT i5k5mg55HqDh5v5M+kxD9qGXySYkve2MN9FuaAe+luYUIl1oTbYqfjpKKObBhJqLX9yG aXgBMZhRYOtYyKNE4KxqqIL2DCNJiyPWguwGGhdhUx+B+2bGWQDKmavWhpQUKj2IPBMg nP+LL1IgQWwS3N5U3H4EDdK20psDPIKuhDOktwj0MygstxRL5HN3Jlb3F2529/MhYeP6 VuCQ== 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=y4hrO1Uu0paB0JQc174Zf7748JlB8HDxf5+LZFaxdz0=; b=tw+6iNbZlaLrDBfAlBEqKn9ugCdc9XNUhBpc4C0vsQkJ3528oEW2GWqwVlY8/+zD6w rmNN9FEJR7rtgZsYJXOK7sQ9dZupRsx0Km0XBOSduVytOPnU+TTrsvKA0dvtdJ4Lnmgh 60045Q4xpyaqc+l4fGYW84/ckstsuXNC3P7gavNMqJ7Xqtt6pfRcUSmv6/hnFAa9SwEZ 7CBpYgio1oN/sF3NOo1Tl2L0cnlvrcT3fdljiT/SGnLuJbozsDrc/bARo3rcv7bGGLuM cKpdHKTTt4g1SeeIkQX3fPOknnBr83XRvtyYf8VN4V82/G8F+vr44JnDlZF2yU46PyjZ SC/Q== X-Gm-Message-State: APjAAAVmhaynkD2GA9W59iCQoONTwQKbZZsfXaxm9Wogqk5U8b9abMHj nq6uHtZTkC43RdBTX0oC3jSqGbOu X-Google-Smtp-Source: APXvYqw4MUzM4YotE+OPeAo10U1rk2AwxQ23giluPxjEsGevYJQ2SdMeLT179aDGK/ZJk2pM9hnXVA== X-Received: by 2002:a5d:4b4e:: with SMTP id w14mr8483626wrs.191.1568928275328; Thu, 19 Sep 2019 14:24:35 -0700 (PDT) Received: from nullptr.home.dirty-ice.org (2a01-036c-0113-74ef-0000-0000-0000-0005.pool6.digikabel.hu. [2a01:36c:113:74ef::5]) by smtp.gmail.com with ESMTPSA id w125sm13191292wmg.32.2019.09.19.14.24.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Sep 2019 14:24:35 -0700 (PDT) From: "=?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?=" X-Google-Original-From: =?utf-8?b?S8WRdsOhZ8OzLCBab2x0w6Fu?= To: qemu-devel@nongnu.org Subject: [PATCH v4 13/24] audio: common rate control code for timer based outputs Date: Thu, 19 Sep 2019 23:24:21 +0200 Message-Id: X-Mailer: git-send-email 2.23.0 In-Reply-To: References: MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::444 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Gerd Hoffmann Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" This commit removes the ad-hoc rate-limiting code from noaudio and wavaudio, and replaces them with a (slightly modified) code from spiceaudio. This way multiple write calls (for example when the circular buffer wraps around) do not cause problems. Signed-off-by: Kővágó, Zoltán --- audio/audio.c | 30 +++++++++++++++++++++++++++ audio/audio_int.h | 9 ++++++++ audio/noaudio.c | 49 ++++++++++++++++++++------------------------ audio/spiceaudio.c | 51 ++++++++-------------------------------------- audio/wavaudio.c | 21 +++++++++---------- 5 files changed, 79 insertions(+), 81 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index ba07fb77dd..fab1e35718 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -2051,3 +2051,33 @@ const char *audio_get_id(QEMUSoundCard *card) return ""; } } + +void audio_rate_start(RateCtl *rate) +{ + memset(rate, 0, sizeof(RateCtl)); + rate->start_ticks = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); +} + +size_t audio_rate_get_bytes(struct audio_pcm_info *info, RateCtl *rate, + size_t bytes_avail) +{ + int64_t now; + int64_t ticks; + int64_t bytes; + int64_t samples; + size_t ret; + + 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; + 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); + rate->bytes_sent += ret; + return ret; +} diff --git a/audio/audio_int.h b/audio/audio_int.h index 20021df9e8..778615ccaf 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -242,6 +242,15 @@ void *audio_calloc (const char *funcname, int nmemb, size_t size); void audio_run(AudioState *s, const char *msg); +typedef struct RateCtl { + int64_t start_ticks; + int64_t bytes_sent; +} RateCtl; + +void audio_rate_start(RateCtl *rate); +size_t audio_rate_get_bytes(struct audio_pcm_info *info, RateCtl *rate, + size_t bytes_avail); + #define VOICE_ENABLE 1 #define VOICE_DISABLE 2 #define VOICE_VOLUME 3 diff --git a/audio/noaudio.c b/audio/noaudio.c index b054fd225b..9f1cc67df9 100644 --- a/audio/noaudio.c +++ b/audio/noaudio.c @@ -33,33 +33,27 @@ typedef struct NoVoiceOut { HWVoiceOut hw; - int64_t old_ticks; + RateCtl rate; } NoVoiceOut; typedef struct NoVoiceIn { HWVoiceIn hw; - int64_t old_ticks; + RateCtl rate; } NoVoiceIn; static size_t no_write(HWVoiceOut *hw, void *buf, size_t len) { NoVoiceOut *no = (NoVoiceOut *) hw; - int64_t now; - int64_t ticks; - int64_t bytes; - - now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - ticks = now - no->old_ticks; - bytes = muldiv64(ticks, hw->info.bytes_per_second, NANOSECONDS_PER_SECOND); - - no->old_ticks = now; - return MIN(len, bytes); + return audio_rate_get_bytes(&hw->info, &no->rate, len); } static int no_init_out(HWVoiceOut *hw, struct audsettings *as, void *drv_opaque) { + NoVoiceOut *no = (NoVoiceOut *) hw; + audio_pcm_init_info (&hw->info, as); hw->samples = 1024; + audio_rate_start(&no->rate); return 0; } @@ -70,15 +64,21 @@ static void no_fini_out (HWVoiceOut *hw) static int no_ctl_out (HWVoiceOut *hw, int cmd, ...) { - (void) hw; - (void) cmd; + NoVoiceOut *no = (NoVoiceOut *) hw; + + if (cmd == VOICE_ENABLE) { + audio_rate_start(&no->rate); + } return 0; } static int no_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) { + NoVoiceIn *no = (NoVoiceIn *) hw; + audio_pcm_init_info (&hw->info, as); hw->samples = 1024; + audio_rate_start(&no->rate); return 0; } @@ -89,25 +89,20 @@ static void no_fini_in (HWVoiceIn *hw) static size_t no_read(HWVoiceIn *hw, void *buf, size_t size) { - size_t to_clear; NoVoiceIn *no = (NoVoiceIn *) hw; + int64_t bytes = audio_rate_get_bytes(&hw->info, &no->rate, size); - int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - int64_t ticks = now - no->old_ticks; - int64_t bytes = - muldiv64(ticks, hw->info.bytes_per_second, NANOSECONDS_PER_SECOND); - - no->old_ticks = now; - to_clear = MIN(bytes, size); - - audio_pcm_info_clear_buf(&hw->info, buf, to_clear >> hw->info.shift); - return to_clear; + audio_pcm_info_clear_buf(&hw->info, buf, bytes >> hw->info.shift); + return bytes; } static int no_ctl_in (HWVoiceIn *hw, int cmd, ...) { - (void) hw; - (void) cmd; + NoVoiceIn *no = (NoVoiceIn *) hw; + + if (cmd == VOICE_ENABLE) { + audio_rate_start(&no->rate); + } return 0; } diff --git a/audio/spiceaudio.c b/audio/spiceaudio.c index ff4e4dcbb0..4ce4f94c6d 100644 --- a/audio/spiceaudio.c +++ b/audio/spiceaudio.c @@ -40,15 +40,10 @@ #define LINE_IN_SAMPLES (256 * 4) #endif -typedef struct SpiceRateCtl { - int64_t start_ticks; - int64_t bytes_sent; -} SpiceRateCtl; - typedef struct SpiceVoiceOut { HWVoiceOut hw; SpicePlaybackInstance sin; - SpiceRateCtl rate; + RateCtl rate; int active; uint32_t *frame; uint32_t fpos; @@ -58,7 +53,7 @@ typedef struct SpiceVoiceOut { typedef struct SpiceVoiceIn { HWVoiceIn hw; SpiceRecordInstance sin; - SpiceRateCtl rate; + RateCtl rate; int active; } SpiceVoiceIn; @@ -89,32 +84,6 @@ static void spice_audio_fini (void *opaque) /* nothing */ } -static void rate_start (SpiceRateCtl *rate) -{ - memset (rate, 0, sizeof (*rate)); - rate->start_ticks = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); -} - -static int rate_get_samples (struct audio_pcm_info *info, SpiceRateCtl *rate) -{ - int64_t now; - int64_t ticks; - int64_t bytes; - int64_t samples; - - 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; - if (samples < 0 || samples > 65536) { - error_report("Resetting rate control (%" PRId64 " samples)", samples); - rate_start(rate); - samples = 0; - } - rate->bytes_sent += samples << info->shift; - return samples; -} - /* playback */ static int line_out_init(HWVoiceOut *hw, struct audsettings *as, @@ -154,7 +123,6 @@ static void line_out_fini (HWVoiceOut *hw) static void *line_out_get_buffer(HWVoiceOut *hw, size_t *size) { SpiceVoiceOut *out = container_of(hw, SpiceVoiceOut, hw); - size_t decr; if (!out->frame) { spice_server_playback_get_buffer(&out->sin, &out->frame, &out->fsize); @@ -162,12 +130,10 @@ static void *line_out_get_buffer(HWVoiceOut *hw, size_t *size) } if (out->frame) { - decr = rate_get_samples(&hw->info, &out->rate); - decr = MIN(out->fsize - out->fpos, decr); - - *size = decr << hw->info.shift; + *size = audio_rate_get_bytes( + &hw->info, &out->rate, (out->fsize - out->fpos) << hw->info.shift); } else { - rate_start(&out->rate); + audio_rate_start(&out->rate); } return out->frame + out->fpos; } @@ -197,7 +163,7 @@ static int line_out_ctl (HWVoiceOut *hw, int cmd, ...) break; } out->active = 1; - rate_start (&out->rate); + audio_rate_start(&out->rate); spice_server_playback_start (&out->sin); break; case VOICE_DISABLE: @@ -273,8 +239,7 @@ static void line_in_fini (HWVoiceIn *hw) static size_t line_in_read(HWVoiceIn *hw, void *buf, size_t len) { SpiceVoiceIn *in = container_of (hw, SpiceVoiceIn, hw); - uint64_t delta_samp = rate_get_samples(&hw->info, &in->rate); - uint64_t to_read = MIN(len >> 2, delta_samp); + uint64_t to_read = audio_rate_get_bytes(&hw->info, &in->rate, len) >> 2; size_t ready = spice_server_record_get_samples(&in->sin, buf, to_read); /* XXX: do we need this? */ @@ -296,7 +261,7 @@ static int line_in_ctl (HWVoiceIn *hw, int cmd, ...) break; } in->active = 1; - rate_start (&in->rate); + audio_rate_start(&in->rate); spice_server_record_start (&in->sin); break; case VOICE_DISABLE: diff --git a/audio/wavaudio.c b/audio/wavaudio.c index 78af2f1338..85f5ff9c28 100644 --- a/audio/wavaudio.c +++ b/audio/wavaudio.c @@ -35,21 +35,15 @@ typedef struct WAVVoiceOut { HWVoiceOut hw; FILE *f; - int64_t old_ticks; + RateCtl rate; int total_samples; } WAVVoiceOut; static size_t wav_write_out(HWVoiceOut *hw, void *buf, size_t len) { WAVVoiceOut *wav = (WAVVoiceOut *) hw; - int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - int64_t ticks = now - wav->old_ticks; - int64_t bytes = - muldiv64(ticks, hw->info.bytes_per_second, NANOSECONDS_PER_SECOND); - - bytes = MIN(bytes, len); - bytes = bytes >> hw->info.shift << hw->info.shift; - wav->old_ticks = now; + int64_t bytes = audio_rate_get_bytes(&hw->info, &wav->rate, len); + assert(bytes >> hw->info.shift << hw->info.shift == bytes); if (bytes && fwrite(buf, bytes, 1, wav->f) != 1) { dolog("wav_write_out: fwrite of %" PRId64 " bytes failed\nReason: %s\n", @@ -130,6 +124,8 @@ static int wav_init_out(HWVoiceOut *hw, struct audsettings *as, strerror(errno)); return -1; } + + audio_rate_start(&wav->rate); return 0; } @@ -179,8 +175,11 @@ static void wav_fini_out (HWVoiceOut *hw) static int wav_ctl_out (HWVoiceOut *hw, int cmd, ...) { - (void) hw; - (void) cmd; + WAVVoiceOut *wav = (WAVVoiceOut *) hw; + + if (cmd == VOICE_ENABLE) { + audio_rate_start(&wav->rate); + } return 0; } From patchwork Thu Sep 19 21:24:22 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?UTF-8?B?Wm9sdMOhbiBLxZF2w6Fnw7M=?= X-Patchwork-Id: 1164912 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="Vyc4pSuc"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46Z9pL19Xtz9sNf for ; Fri, 20 Sep 2019 08:03:21 +1000 (AEST) Received: from localhost ([::1]:48906 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB4WE-0000Cz-6v for incoming@patchwork.ozlabs.org; Thu, 19 Sep 2019 18:03:18 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53657) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB3uv-0002tG-BR for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:49 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iB3uq-0000hv-JR for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:45 -0400 Received: from mail-wr1-x442.google.com ([2a00:1450:4864:20::442]:36229) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iB3uo-0000dQ-9c for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:40 -0400 Received: by mail-wr1-x442.google.com with SMTP id y19so4641215wrd.3 for ; Thu, 19 Sep 2019 14:24:37 -0700 (PDT) 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=7YNgB397JDwCtK0HvpydcrpyrQODcodQATJlTPkw3dw=; b=Vyc4pSuc0LG3Cw58gO0nqBntRjRQN9qd50yIwRSqA9fFbNUoWHaxdJ6q2hYNYhsxY1 v1dQfvddo6yegEwFY/OVABP4EMyStEsoZHULR6/QogfFGBWaxku0wVrKb5cRz7XnYsbf gOsZbmqHBk637uQviiuJMyDCuAK5D42S6aT8wZOti8Re90ubMNvHyreU5+Qler1zG1X1 GGVApv/GKGiQY4EM9qxjsYvuCjRRIiDFOqgBDHLBJNLckbGVBu0S7xSX0T2Nhfj4JjGo eyeVngvaGTxru6T5v5YqFkj5MYDu57EqiYgkI1mZYqhdxT0LbBHJoDEZdnIcZXuZmN1I gIBg== 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=7YNgB397JDwCtK0HvpydcrpyrQODcodQATJlTPkw3dw=; b=hOrzdKheZqk1w3h4z3BL/NxMIAjhjro8dMyycVJUzBwzyOL3HjeSyanXutwoj/wa1n 8VMhdrrUXEfcqUbnPczbMcsu2fp3yjfFTgjrx4DriJZaZpcn50Vq7QgFAyat3q9D/5uN E4G4OMG89Az9CUOqSQVAATmWqCaTW9ygt8qW2MqLTX58JR0jZajYGFbiGSofNJCq1lJV f8IBrqCvR/xHoF+FJmxhXG6D5aepN84Cg9FMgssxSZKukrFSm5dEk8T4YXf6zL6Bs7fN LA988gwx2Eu7h/l/OItJWlmQdTd2q3c0cLogTZ2ZdUcqMy0kWo66+y4mawt7pZXk9tfn kbvg== X-Gm-Message-State: APjAAAUDeKvS0myCeeMrE1cFjvwe6QkFPXDDb+tml6/QtB96UwWu11c1 IzNlNzH9CWndDf85t2B8Uiqj+mIT X-Google-Smtp-Source: APXvYqzxmIBQ4fFRMak1UD7R1uzja+5nEInbBcw8b+RzpxAb+EAlrjCaNkskK1T/KycsCzImUMZ2MQ== X-Received: by 2002:a5d:500f:: with SMTP id e15mr8106132wrt.300.1568928276197; Thu, 19 Sep 2019 14:24:36 -0700 (PDT) Received: from nullptr.home.dirty-ice.org (2a01-036c-0113-74ef-0000-0000-0000-0005.pool6.digikabel.hu. [2a01:36c:113:74ef::5]) by smtp.gmail.com with ESMTPSA id w125sm13191292wmg.32.2019.09.19.14.24.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Sep 2019 14:24:35 -0700 (PDT) From: "=?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?=" X-Google-Original-From: =?utf-8?b?S8WRdsOhZ8OzLCBab2x0w6Fu?= To: qemu-devel@nongnu.org Subject: [PATCH v4 14/24] audio: split ctl_* functions into enable_* and volume_* Date: Thu, 19 Sep 2019 23:24:22 +0200 Message-Id: <2b08b3773569c5be055d0a0fb2f29ff64e79f0f4.1568927990.git.DirtY.iCE.hu@gmail.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: References: MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::442 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Gerd Hoffmann Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" This way we no longer need vararg functions, improving compile time error detection. Also now it's possible to check actually what commands are supported, without needing to manually update ctl_caps. Signed-off-by: Kővágó, Zoltán --- audio/alsaaudio.c | 62 ++++++++---------- audio/audio.c | 45 ++++++++----- audio/audio_int.h | 15 ++--- audio/audio_template.h | 1 - audio/coreaudio.c | 13 ++-- audio/dsoundaudio.c | 50 ++++++--------- audio/noaudio.c | 14 ++--- audio/ossaudio.c | 79 +++++++++-------------- audio/paaudio.c | 139 +++++++++++++++++------------------------ audio/sdlaudio.c | 17 +---- audio/spiceaudio.c | 102 +++++++++++++----------------- audio/wavaudio.c | 7 +-- 12 files changed, 223 insertions(+), 321 deletions(-) diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index 19124d09d8..cfe42284a6 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -731,34 +731,28 @@ static int alsa_voice_ctl (snd_pcm_t *handle, const char *typ, int ctl) return 0; } -static int alsa_ctl_out (HWVoiceOut *hw, int cmd, ...) +static void alsa_enable_out(HWVoiceOut *hw, bool enable) { ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw; AudiodevAlsaPerDirectionOptions *apdo = alsa->dev->u.alsa.out; - switch (cmd) { - case VOICE_ENABLE: - { - bool poll_mode = apdo->try_poll; + if (enable) { + bool poll_mode = apdo->try_poll; - ldebug ("enabling voice\n"); - if (poll_mode && alsa_poll_out (hw)) { - poll_mode = 0; - } - hw->poll_mode = poll_mode; - return alsa_voice_ctl (alsa->handle, "playback", VOICE_CTL_PREPARE); + ldebug("enabling voice\n"); + if (poll_mode && alsa_poll_out(hw)) { + poll_mode = 0; } - - case VOICE_DISABLE: - ldebug ("disabling voice\n"); + hw->poll_mode = poll_mode; + alsa_voice_ctl(alsa->handle, "playback", VOICE_CTL_PREPARE); + } else { + ldebug("disabling voice\n"); if (hw->poll_mode) { hw->poll_mode = 0; - alsa_fini_poll (&alsa->pollhlp); + alsa_fini_poll(&alsa->pollhlp); } - return alsa_voice_ctl (alsa->handle, "playback", VOICE_CTL_PAUSE); + alsa_voice_ctl(alsa->handle, "playback", VOICE_CTL_PAUSE); } - - return -1; } static int alsa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) @@ -841,35 +835,29 @@ static size_t alsa_read(HWVoiceIn *hw, void *buf, size_t len) return pos; } -static int alsa_ctl_in (HWVoiceIn *hw, int cmd, ...) +static void alsa_enable_in(HWVoiceIn *hw, bool enable) { ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw; AudiodevAlsaPerDirectionOptions *apdo = alsa->dev->u.alsa.in; - switch (cmd) { - case VOICE_ENABLE: - { - bool poll_mode = apdo->try_poll; + if (enable) { + bool poll_mode = apdo->try_poll; - ldebug ("enabling voice\n"); - if (poll_mode && alsa_poll_in (hw)) { - poll_mode = 0; - } - hw->poll_mode = poll_mode; - - return alsa_voice_ctl (alsa->handle, "capture", VOICE_CTL_START); + ldebug("enabling voice\n"); + if (poll_mode && alsa_poll_in(hw)) { + poll_mode = 0; } + hw->poll_mode = poll_mode; - case VOICE_DISABLE: + alsa_voice_ctl(alsa->handle, "capture", VOICE_CTL_START); + } else { ldebug ("disabling voice\n"); if (hw->poll_mode) { hw->poll_mode = 0; - alsa_fini_poll (&alsa->pollhlp); + alsa_fini_poll(&alsa->pollhlp); } - return alsa_voice_ctl (alsa->handle, "capture", VOICE_CTL_PAUSE); + alsa_voice_ctl(alsa->handle, "capture", VOICE_CTL_PAUSE); } - - return -1; } static void alsa_init_per_direction(AudiodevAlsaPerDirectionOptions *apdo) @@ -924,12 +912,12 @@ static struct audio_pcm_ops alsa_pcm_ops = { .init_out = alsa_init_out, .fini_out = alsa_fini_out, .write = alsa_write, - .ctl_out = alsa_ctl_out, + .enable_out = alsa_enable_out, .init_in = alsa_init_in, .fini_in = alsa_fini_in, .read = alsa_read, - .ctl_in = alsa_ctl_in, + .enable_in = alsa_enable_in, }; static struct audio_driver alsa_audio_driver = { diff --git a/audio/audio.c b/audio/audio.c index fab1e35718..7128ee98dc 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -636,7 +636,7 @@ static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, size_t size) total += isamp; } - if (!(hw->ctl_caps & VOICE_VOLUME_CAP)) { + if (!hw->pcm_ops->volume_in) { mixeng_volume (sw->buf, ret, &sw->vol); } @@ -723,7 +723,7 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t size) if (swlim) { sw->conv (sw->buf, buf, swlim); - if (!(sw->hw->ctl_caps & VOICE_VOLUME_CAP)) { + if (!sw->hw->pcm_ops->volume_out) { mixeng_volume (sw->buf, swlim, &sw->vol); } } @@ -890,7 +890,9 @@ void AUD_set_active_out (SWVoiceOut *sw, int on) if (!hw->enabled) { hw->enabled = 1; if (s->vm_running) { - hw->pcm_ops->ctl_out(hw, VOICE_ENABLE); + if (hw->pcm_ops->enable_out) { + hw->pcm_ops->enable_out(hw, true); + } audio_reset_timer (s); } } @@ -935,7 +937,9 @@ void AUD_set_active_in (SWVoiceIn *sw, int on) if (!hw->enabled) { hw->enabled = 1; if (s->vm_running) { - hw->pcm_ops->ctl_in(hw, VOICE_ENABLE); + if (hw->pcm_ops->enable_in) { + hw->pcm_ops->enable_in(hw, true); + } audio_reset_timer (s); } } @@ -952,7 +956,9 @@ void AUD_set_active_in (SWVoiceIn *sw, int on) if (nb_active == 1) { hw->enabled = 0; - hw->pcm_ops->ctl_in (hw, VOICE_DISABLE); + if (hw->pcm_ops->enable_in) { + hw->pcm_ops->enable_in(hw, false); + } } } } @@ -1105,7 +1111,9 @@ static void audio_run_out (AudioState *s) #endif hw->enabled = 0; hw->pending_disable = 0; - hw->pcm_ops->ctl_out (hw, VOICE_DISABLE); + if (hw->pcm_ops->enable_out) { + hw->pcm_ops->enable_out(hw, false); + } for (sc = hw->cap_head.lh_first; sc; sc = sc->entries.le_next) { sc->sw.active = 0; audio_recalc_and_notify_capture (sc->cap); @@ -1470,15 +1478,18 @@ static void audio_vm_change_state_handler (void *opaque, int running, AudioState *s = opaque; HWVoiceOut *hwo = NULL; HWVoiceIn *hwi = NULL; - int op = running ? VOICE_ENABLE : VOICE_DISABLE; s->vm_running = running; while ((hwo = audio_pcm_hw_find_any_enabled_out(s, hwo))) { - hwo->pcm_ops->ctl_out(hwo, op); + if (hwo->pcm_ops->enable_out) { + hwo->pcm_ops->enable_out(hwo, running); + } } while ((hwi = audio_pcm_hw_find_any_enabled_in(s, hwi))) { - hwi->pcm_ops->ctl_in(hwi, op); + if (hwi->pcm_ops->enable_in) { + hwi->pcm_ops->enable_in(hwi, running); + } } audio_reset_timer (s); } @@ -1498,8 +1509,8 @@ static void free_audio_state(AudioState *s) QLIST_FOREACH_SAFE(hwo, &s->hw_head_out, entries, hwon) { SWVoiceCap *sc; - if (hwo->enabled) { - hwo->pcm_ops->ctl_out (hwo, VOICE_DISABLE); + if (hwo->enabled && hwo->pcm_ops->enable_out) { + hwo->pcm_ops->enable_out(hwo, false); } hwo->pcm_ops->fini_out (hwo); @@ -1515,8 +1526,8 @@ static void free_audio_state(AudioState *s) } QLIST_FOREACH_SAFE(hwi, &s->hw_head_in, entries, hwin) { - if (hwi->enabled) { - hwi->pcm_ops->ctl_in (hwi, VOICE_DISABLE); + if (hwi->enabled && hwi->pcm_ops->enable_in) { + hwi->pcm_ops->enable_in(hwi, false); } hwi->pcm_ops->fini_in (hwi); QLIST_REMOVE(hwi, entries); @@ -1838,8 +1849,8 @@ void AUD_set_volume_out (SWVoiceOut *sw, int mute, uint8_t lvol, uint8_t rvol) sw->vol.l = nominal_volume.l * lvol / 255; sw->vol.r = nominal_volume.r * rvol / 255; - if (hw->pcm_ops->ctl_out) { - hw->pcm_ops->ctl_out (hw, VOICE_VOLUME, sw); + if (hw->pcm_ops->volume_out) { + hw->pcm_ops->volume_out(hw, &sw->vol); } } } @@ -1853,8 +1864,8 @@ void AUD_set_volume_in (SWVoiceIn *sw, int mute, uint8_t lvol, uint8_t rvol) sw->vol.l = nominal_volume.l * lvol / 255; sw->vol.r = nominal_volume.r * rvol / 255; - if (hw->pcm_ops->ctl_in) { - hw->pcm_ops->ctl_in (hw, VOICE_VOLUME, sw); + if (hw->pcm_ops->volume_in) { + hw->pcm_ops->volume_in(hw, &sw->vol); } } } diff --git a/audio/audio_int.h b/audio/audio_int.h index 778615ccaf..22a703c13e 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -74,7 +74,6 @@ typedef struct HWVoiceOut { size_t samples; QLIST_HEAD (sw_out_listhead, SWVoiceOut) sw_head; QLIST_HEAD (sw_cap_listhead, SWVoiceCap) cap_head; - int ctl_caps; struct audio_pcm_ops *pcm_ops; QLIST_ENTRY (HWVoiceOut) entries; } HWVoiceOut; @@ -96,7 +95,6 @@ typedef struct HWVoiceIn { size_t samples; QLIST_HEAD (sw_in_listhead, SWVoiceIn) sw_head; - int ctl_caps; struct audio_pcm_ops *pcm_ops; QLIST_ENTRY (HWVoiceIn) entries; } HWVoiceIn; @@ -148,7 +146,6 @@ struct audio_driver { int max_voices_in; int voice_size_out; int voice_size_in; - int ctl_caps; QLIST_ENTRY(audio_driver) next; }; @@ -168,14 +165,16 @@ struct audio_pcm_ops { * size may be smaller */ size_t (*put_buffer_out)(HWVoiceOut *hw, void *buf, size_t size); - int (*ctl_out) (HWVoiceOut *hw, int cmd, ...); + void (*enable_out)(HWVoiceOut *hw, bool enable); + void (*volume_out)(HWVoiceOut *hw, struct mixeng_volume *vol); int (*init_in) (HWVoiceIn *hw, audsettings *as, void *drv_opaque); void (*fini_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, ...); + void (*enable_in)(HWVoiceIn *hw, bool enable); + void (*volume_in)(HWVoiceIn *hw, struct mixeng_volume *vol); }; void *audio_generic_get_buffer_in(HWVoiceIn *hw, size_t *size); @@ -251,12 +250,6 @@ void audio_rate_start(RateCtl *rate); size_t audio_rate_get_bytes(struct audio_pcm_info *info, RateCtl *rate, size_t bytes_avail); -#define VOICE_ENABLE 1 -#define VOICE_DISABLE 2 -#define VOICE_VOLUME 3 - -#define VOICE_VOLUME_CAP (1 << VOICE_VOLUME) - static inline size_t audio_ring_dist(size_t dst, size_t src, size_t len) { return (dst >= src) ? (dst - src) : (len - src + dst); diff --git a/audio/audio_template.h b/audio/audio_template.h index 87c6d2d271..235d1acbbe 100644 --- a/audio/audio_template.h +++ b/audio/audio_template.h @@ -254,7 +254,6 @@ static HW *glue(audio_pcm_hw_add_new_, TYPE)(AudioState *s, hw->s = s; hw->pcm_ops = drv->pcm_ops; - hw->ctl_caps = drv->ctl_caps; QLIST_INIT (&hw->sw_head); #ifdef DAC diff --git a/audio/coreaudio.c b/audio/coreaudio.c index 5cde42f982..1427c9f622 100644 --- a/audio/coreaudio.c +++ b/audio/coreaudio.c @@ -648,13 +648,12 @@ static void coreaudio_fini_out (HWVoiceOut *hw) } } -static int coreaudio_ctl_out (HWVoiceOut *hw, int cmd, ...) +static void coreaudio_enable_out(HWVoiceOut *hw, bool enable) { OSStatus status; coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw; - switch (cmd) { - case VOICE_ENABLE: + if (enable) { /* start playback */ if (!isPlaying(core->outputDeviceID)) { status = AudioDeviceStart(core->outputDeviceID, core->ioprocid); @@ -662,9 +661,7 @@ static int coreaudio_ctl_out (HWVoiceOut *hw, int cmd, ...) coreaudio_logerr (status, "Could not resume playback\n"); } } - break; - - case VOICE_DISABLE: + } else { /* stop playback */ if (!audio_is_cleaning_up()) { if (isPlaying(core->outputDeviceID)) { @@ -675,9 +672,7 @@ static int coreaudio_ctl_out (HWVoiceOut *hw, int cmd, ...) } } } - break; } - return 0; } static void *coreaudio_audio_init(Audiodev *dev) @@ -695,7 +690,7 @@ static struct audio_pcm_ops coreaudio_pcm_ops = { .write = coreaudio_write, .get_buffer_out = coreaudio_get_buffer_out, .put_buffer_out = coreaudio_put_buffer_out_nowrite, - .ctl_out = coreaudio_ctl_out + .enable_out = coreaudio_enable_out }; static struct audio_driver coreaudio_audio_driver = { diff --git a/audio/dsoundaudio.c b/audio/dsoundaudio.c index 9960247814..d4a4757445 100644 --- a/audio/dsoundaudio.c +++ b/audio/dsoundaudio.c @@ -361,7 +361,7 @@ static int dsound_open (dsound *s) return 0; } -static int dsound_ctl_out (HWVoiceOut *hw, int cmd, ...) +static void dsound_enable_out(HWVoiceOut *hw, bool enable) { HRESULT hr; DWORD status; @@ -371,18 +371,17 @@ static int dsound_ctl_out (HWVoiceOut *hw, int cmd, ...) if (!dsb) { dolog ("Attempt to control voice without a buffer\n"); - return 0; + return; } - switch (cmd) { - case VOICE_ENABLE: + if (enable) { if (dsound_get_status_out (dsb, &status, s)) { - return -1; + return; } if (status & DSBSTATUS_PLAYING) { dolog ("warning: Voice is already playing\n"); - return 0; + return; } dsound_clear_sample (hw, dsb, s); @@ -390,28 +389,24 @@ static int dsound_ctl_out (HWVoiceOut *hw, int cmd, ...) hr = IDirectSoundBuffer_Play (dsb, 0, 0, DSBPLAY_LOOPING); if (FAILED (hr)) { dsound_logerr (hr, "Could not start playing buffer\n"); - return -1; + return; } - break; - - case VOICE_DISABLE: + } else { if (dsound_get_status_out (dsb, &status, s)) { - return -1; + return; } if (status & DSBSTATUS_PLAYING) { hr = IDirectSoundBuffer_Stop (dsb); if (FAILED (hr)) { dsound_logerr (hr, "Could not stop playing buffer\n"); - return -1; + return; } } else { dolog ("warning: Voice is not playing\n"); } - break; } - return 0; } static void *dsound_get_buffer_out(HWVoiceOut *hw, size_t *size) @@ -461,7 +456,7 @@ static size_t dsound_put_buffer_out(HWVoiceOut *hw, void *buf, size_t len) return len; } -static int dsound_ctl_in (HWVoiceIn *hw, int cmd, ...) +static void dsound_enable_in(HWVoiceIn *hw, bool enable) { HRESULT hr; DWORD status; @@ -470,18 +465,17 @@ static int dsound_ctl_in (HWVoiceIn *hw, int cmd, ...) if (!dscb) { dolog ("Attempt to control capture voice without a buffer\n"); - return -1; + return; } - switch (cmd) { - case VOICE_ENABLE: + if (enable) { if (dsound_get_status_in (dscb, &status)) { - return -1; + return; } if (status & DSCBSTATUS_CAPTURING) { dolog ("warning: Voice is already capturing\n"); - return 0; + return; } /* clear ?? */ @@ -489,28 +483,24 @@ static int dsound_ctl_in (HWVoiceIn *hw, int cmd, ...) hr = IDirectSoundCaptureBuffer_Start (dscb, DSCBSTART_LOOPING); if (FAILED (hr)) { dsound_logerr (hr, "Could not start capturing\n"); - return -1; + return; } - break; - - case VOICE_DISABLE: + } else { if (dsound_get_status_in (dscb, &status)) { - return -1; + return; } if (status & DSCBSTATUS_CAPTURING) { hr = IDirectSoundCaptureBuffer_Stop (dscb); if (FAILED (hr)) { dsound_logerr (hr, "Could not stop capturing\n"); - return -1; + return; } } else { dolog ("warning: Voice is not capturing\n"); } - break; } - return 0; } static void *dsound_get_buffer_in(HWVoiceIn *hw, size_t *size) @@ -674,14 +664,14 @@ static struct audio_pcm_ops dsound_pcm_ops = { .write = audio_generic_write, .get_buffer_out = dsound_get_buffer_out, .put_buffer_out = dsound_put_buffer_out, - .ctl_out = dsound_ctl_out, + .enable_out = dsound_enable_out, .init_in = dsound_init_in, .fini_in = dsound_fini_in, .read = audio_generic_read, .get_buffer_in = dsound_get_buffer_in, .put_buffer_in = dsound_put_buffer_in, - .ctl_in = dsound_ctl_in + .enable_in = dsound_enable_in, }; static struct audio_driver dsound_audio_driver = { diff --git a/audio/noaudio.c b/audio/noaudio.c index 9f1cc67df9..ec8a287f36 100644 --- a/audio/noaudio.c +++ b/audio/noaudio.c @@ -62,14 +62,13 @@ static void no_fini_out (HWVoiceOut *hw) (void) hw; } -static int no_ctl_out (HWVoiceOut *hw, int cmd, ...) +static void no_enable_out(HWVoiceOut *hw, bool enable) { NoVoiceOut *no = (NoVoiceOut *) hw; - if (cmd == VOICE_ENABLE) { + if (enable) { audio_rate_start(&no->rate); } - return 0; } static int no_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) @@ -96,14 +95,13 @@ static size_t no_read(HWVoiceIn *hw, void *buf, size_t size) return bytes; } -static int no_ctl_in (HWVoiceIn *hw, int cmd, ...) +static void no_enable_in(HWVoiceIn *hw, bool enable) { NoVoiceIn *no = (NoVoiceIn *) hw; - if (cmd == VOICE_ENABLE) { + if (enable) { audio_rate_start(&no->rate); } - return 0; } static void *no_audio_init(Audiodev *dev) @@ -120,12 +118,12 @@ static struct audio_pcm_ops no_pcm_ops = { .init_out = no_init_out, .fini_out = no_fini_out, .write = no_write, - .ctl_out = no_ctl_out, + .enable_out = no_enable_out, .init_in = no_init_in, .fini_in = no_fini_in, .read = no_read, - .ctl_in = no_ctl_in + .enable_in = no_enable_in }; static struct audio_driver no_audio_driver = { diff --git a/audio/ossaudio.c b/audio/ossaudio.c index 76c082d5e2..0c4451e972 100644 --- a/audio/ossaudio.c +++ b/audio/ossaudio.c @@ -563,60 +563,50 @@ static int oss_init_out(HWVoiceOut *hw, struct audsettings *as, return 0; } -static int oss_ctl_out (HWVoiceOut *hw, int cmd, ...) +static void oss_enable_out(HWVoiceOut *hw, bool enable) { int trig; OSSVoiceOut *oss = (OSSVoiceOut *) hw; AudiodevOssPerDirectionOptions *opdo = oss->dev->u.oss.out; - switch (cmd) { - case VOICE_ENABLE: - { - bool poll_mode = opdo->try_poll; + if (enable) { + bool poll_mode = opdo->try_poll; - ldebug ("enabling voice\n"); - if (poll_mode) { - oss_poll_out (hw); - poll_mode = 0; - } - hw->poll_mode = poll_mode; - - if (!oss->mmapped) { - return 0; - } + ldebug("enabling voice\n"); + if (poll_mode) { + oss_poll_out(hw); + poll_mode = 0; + } + hw->poll_mode = poll_mode; - audio_pcm_info_clear_buf( - &hw->info, hw->buf_emul, hw->mix_buf->size); - trig = PCM_ENABLE_OUTPUT; - if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) { - oss_logerr ( - errno, - "SNDCTL_DSP_SETTRIGGER PCM_ENABLE_OUTPUT failed\n" - ); - return -1; - } + if (!oss->mmapped) { + return; } - break; - case VOICE_DISABLE: + audio_pcm_info_clear_buf(&hw->info, hw->buf_emul, hw->mix_buf->size); + trig = PCM_ENABLE_OUTPUT; + if (ioctl(oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) { + oss_logerr(errno, + "SNDCTL_DSP_SETTRIGGER PCM_ENABLE_OUTPUT failed\n"); + return; + } + } else { if (hw->poll_mode) { qemu_set_fd_handler (oss->fd, NULL, NULL, NULL); hw->poll_mode = 0; } if (!oss->mmapped) { - return 0; + return; } ldebug ("disabling voice\n"); trig = 0; if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) { oss_logerr (errno, "SNDCTL_DSP_SETTRIGGER 0 failed\n"); - return -1; + return; } - break; } - return 0; } static int oss_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) @@ -703,32 +693,25 @@ static size_t oss_read(HWVoiceIn *hw, void *buf, size_t len) return pos; } -static int oss_ctl_in (HWVoiceIn *hw, int cmd, ...) +static void oss_enable_in(HWVoiceIn *hw, bool enable) { OSSVoiceIn *oss = (OSSVoiceIn *) hw; AudiodevOssPerDirectionOptions *opdo = oss->dev->u.oss.out; - switch (cmd) { - case VOICE_ENABLE: - { - bool poll_mode = opdo->try_poll; + if (enable) { + bool poll_mode = opdo->try_poll; - if (poll_mode) { - oss_poll_in (hw); - poll_mode = 0; - } - hw->poll_mode = poll_mode; + if (poll_mode) { + oss_poll_in(hw); + poll_mode = 0; } - break; - - case VOICE_DISABLE: + hw->poll_mode = poll_mode; + } else { if (hw->poll_mode) { hw->poll_mode = 0; qemu_set_fd_handler (oss->fd, NULL, NULL, NULL); } - break; } - return 0; } static void oss_init_per_direction(AudiodevOssPerDirectionOptions *opdo) @@ -767,12 +750,12 @@ static struct audio_pcm_ops oss_pcm_ops = { .write = oss_write, .get_buffer_out = oss_get_buffer_out, .put_buffer_out = oss_put_buffer_out, - .ctl_out = oss_ctl_out, + .enable_out = oss_enable_out, .init_in = oss_init_in, .fini_in = oss_fini_in, .read = oss_read, - .ctl_in = oss_ctl_in + .enable_in = oss_enable_in }; static struct audio_driver oss_audio_driver = { diff --git a/audio/paaudio.c b/audio/paaudio.c index 75fce53202..ed31f863f7 100644 --- a/audio/paaudio.c +++ b/audio/paaudio.c @@ -452,7 +452,7 @@ static void qpa_fini_in (HWVoiceIn *hw) } } -static int qpa_ctl_out (HWVoiceOut *hw, int cmd, ...) +static void qpa_volume_out(HWVoiceOut *hw, struct mixeng_volume *vol) { PAVoiceOut *pa = (PAVoiceOut *) hw; pa_operation *op; @@ -463,49 +463,36 @@ static int qpa_ctl_out (HWVoiceOut *hw, int cmd, ...) pa_cvolume_init (&v); /* function is present in 0.9.13+ */ #endif - switch (cmd) { - case VOICE_VOLUME: - { - SWVoiceOut *sw; - va_list ap; - - va_start (ap, cmd); - sw = va_arg (ap, SWVoiceOut *); - va_end (ap); - - v.channels = 2; - v.values[0] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * sw->vol.l) / UINT32_MAX; - v.values[1] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * sw->vol.r) / UINT32_MAX; - - pa_threaded_mainloop_lock(c->mainloop); - - op = pa_context_set_sink_input_volume(c->context, - pa_stream_get_index (pa->stream), - &v, NULL, NULL); - if (!op) { - qpa_logerr(pa_context_errno(c->context), - "set_sink_input_volume() failed\n"); - } else { - pa_operation_unref(op); - } - - op = pa_context_set_sink_input_mute(c->context, - pa_stream_get_index (pa->stream), - sw->vol.mute, NULL, NULL); - if (!op) { - qpa_logerr(pa_context_errno(c->context), - "set_sink_input_mute() failed\n"); - } else { - pa_operation_unref(op); - } - - pa_threaded_mainloop_unlock(c->mainloop); - } + v.channels = 2; + v.values[0] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * vol->l) / UINT32_MAX; + v.values[1] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * vol->r) / UINT32_MAX; + + pa_threaded_mainloop_lock(c->mainloop); + + op = pa_context_set_sink_input_volume(c->context, + pa_stream_get_index(pa->stream), + &v, NULL, NULL); + if (!op) { + qpa_logerr(pa_context_errno(c->context), + "set_sink_input_volume() failed\n"); + } else { + pa_operation_unref(op); } - return 0; + + op = pa_context_set_sink_input_mute(c->context, + pa_stream_get_index(pa->stream), + vol->mute, NULL, NULL); + if (!op) { + qpa_logerr(pa_context_errno(c->context), + "set_sink_input_mute() failed\n"); + } else { + pa_operation_unref(op); + } + + pa_threaded_mainloop_unlock(c->mainloop); } -static int qpa_ctl_in (HWVoiceIn *hw, int cmd, ...) +static void qpa_volume_in(HWVoiceIn *hw, struct mixeng_volume *vol) { PAVoiceIn *pa = (PAVoiceIn *) hw; pa_operation *op; @@ -516,46 +503,33 @@ static int qpa_ctl_in (HWVoiceIn *hw, int cmd, ...) pa_cvolume_init (&v); #endif - switch (cmd) { - case VOICE_VOLUME: - { - SWVoiceIn *sw; - va_list ap; - - va_start (ap, cmd); - sw = va_arg (ap, SWVoiceIn *); - va_end (ap); - - v.channels = 2; - v.values[0] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * sw->vol.l) / UINT32_MAX; - v.values[1] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * sw->vol.r) / UINT32_MAX; - - pa_threaded_mainloop_lock(c->mainloop); - - op = pa_context_set_source_output_volume(c->context, - pa_stream_get_index(pa->stream), - &v, NULL, NULL); - if (!op) { - qpa_logerr(pa_context_errno(c->context), - "set_source_output_volume() failed\n"); - } else { - pa_operation_unref(op); - } - - op = pa_context_set_source_output_mute(c->context, - pa_stream_get_index (pa->stream), - sw->vol.mute, NULL, NULL); - if (!op) { - qpa_logerr(pa_context_errno(c->context), - "set_source_output_mute() failed\n"); - } else { - pa_operation_unref (op); - } - - pa_threaded_mainloop_unlock(c->mainloop); - } + v.channels = 2; + v.values[0] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * vol->l) / UINT32_MAX; + v.values[1] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * vol->r) / UINT32_MAX; + + pa_threaded_mainloop_lock(c->mainloop); + + op = pa_context_set_source_output_volume(c->context, + pa_stream_get_index(pa->stream), + &v, NULL, NULL); + if (!op) { + qpa_logerr(pa_context_errno(c->context), + "set_source_output_volume() failed\n"); + } else { + pa_operation_unref(op); } - return 0; + + op = pa_context_set_source_output_mute(c->context, + pa_stream_get_index(pa->stream), + vol->mute, NULL, NULL); + if (!op) { + qpa_logerr(pa_context_errno(c->context), + "set_source_output_mute() failed\n"); + } else { + pa_operation_unref(op); + } + + pa_threaded_mainloop_unlock(c->mainloop); } static int qpa_validate_per_direction_opts(Audiodev *dev, @@ -724,12 +698,12 @@ static struct audio_pcm_ops qpa_pcm_ops = { .init_out = qpa_init_out, .fini_out = qpa_fini_out, .write = qpa_write, - .ctl_out = qpa_ctl_out, + .volume_out = qpa_volume_out, .init_in = qpa_init_in, .fini_in = qpa_fini_in, .read = qpa_read, - .ctl_in = qpa_ctl_in + .volume_in = qpa_volume_in }; static struct audio_driver pa_audio_driver = { @@ -743,7 +717,6 @@ static struct audio_driver pa_audio_driver = { .max_voices_in = INT_MAX, .voice_size_out = sizeof (PAVoiceOut), .voice_size_in = sizeof (PAVoiceIn), - .ctl_caps = VOICE_VOLUME_CAP }; static void register_audio_pa(void) diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c index f7ac8cd101..5c6bcfcb3e 100644 --- a/audio/sdlaudio.c +++ b/audio/sdlaudio.c @@ -285,20 +285,9 @@ static int sdl_init_out(HWVoiceOut *hw, struct audsettings *as, return 0; } -static int sdl_ctl_out (HWVoiceOut *hw, int cmd, ...) +static void sdl_enable_out(HWVoiceOut *hw, bool enable) { - (void) hw; - - switch (cmd) { - case VOICE_ENABLE: - SDL_PauseAudio (0); - break; - - case VOICE_DISABLE: - SDL_PauseAudio (1); - break; - } - return 0; + SDL_PauseAudio(!enable); } static void *sdl_audio_init(Audiodev *dev) @@ -334,7 +323,7 @@ static struct audio_pcm_ops sdl_pcm_ops = { .write = sdl_write, .get_buffer_out = sdl_get_buffer_out, .put_buffer_out = sdl_put_buffer_out_nowrite, - .ctl_out = sdl_ctl_out, + .enable_out = sdl_enable_out, }; static struct audio_driver sdl_audio_driver = { diff --git a/audio/spiceaudio.c b/audio/spiceaudio.c index 4ce4f94c6d..9860f9c5e1 100644 --- a/audio/spiceaudio.c +++ b/audio/spiceaudio.c @@ -153,22 +153,20 @@ static size_t line_out_put_buffer(HWVoiceOut *hw, void *buf, size_t size) return size; } -static int line_out_ctl (HWVoiceOut *hw, int cmd, ...) +static void line_out_enable(HWVoiceOut *hw, bool enable) { SpiceVoiceOut *out = container_of (hw, SpiceVoiceOut, hw); - switch (cmd) { - case VOICE_ENABLE: + if (enable) { if (out->active) { - break; + return; } out->active = 1; audio_rate_start(&out->rate); spice_server_playback_start (&out->sin); - break; - case VOICE_DISABLE: + } else { if (!out->active) { - break; + return; } out->active = 0; if (out->frame) { @@ -177,29 +175,21 @@ static int line_out_ctl (HWVoiceOut *hw, int cmd, ...) out->frame = NULL; } spice_server_playback_stop (&out->sin); - break; - case VOICE_VOLUME: - { -#if ((SPICE_INTERFACE_PLAYBACK_MAJOR >= 1) && (SPICE_INTERFACE_PLAYBACK_MINOR >= 2)) - SWVoiceOut *sw; - va_list ap; - uint16_t vol[2]; - - va_start (ap, cmd); - sw = va_arg (ap, SWVoiceOut *); - va_end (ap); - - vol[0] = sw->vol.l / ((1ULL << 16) + 1); - vol[1] = sw->vol.r / ((1ULL << 16) + 1); - spice_server_playback_set_volume (&out->sin, 2, vol); - spice_server_playback_set_mute (&out->sin, sw->vol.mute); -#endif - break; - } } +} - return 0; +#if ((SPICE_INTERFACE_PLAYBACK_MAJOR >= 1) && (SPICE_INTERFACE_PLAYBACK_MINOR >= 2)) +static void line_out_volume(HWVoiceOut *hw, struct mixeng_volume *vol) +{ + SpiceVoiceOut *out = container_of(hw, SpiceVoiceOut, hw); + uint16_t svol[2]; + + svol[0] = vol->l / ((1ULL << 16) + 1); + svol[1] = vol->r / ((1ULL << 16) + 1); + spice_server_playback_set_volume(&out->sin, 2, svol); + spice_server_playback_set_mute(&out->sin, vol->mute); } +#endif /* record */ @@ -251,48 +241,38 @@ static size_t line_in_read(HWVoiceIn *hw, void *buf, size_t len) return ready << 2; } -static int line_in_ctl (HWVoiceIn *hw, int cmd, ...) +static void line_in_enable(HWVoiceIn *hw, bool enable) { SpiceVoiceIn *in = container_of (hw, SpiceVoiceIn, hw); - switch (cmd) { - case VOICE_ENABLE: + if (enable) { if (in->active) { - break; + return; } in->active = 1; audio_rate_start(&in->rate); spice_server_record_start (&in->sin); - break; - case VOICE_DISABLE: + } else { if (!in->active) { - break; + return; } in->active = 0; spice_server_record_stop (&in->sin); - break; - case VOICE_VOLUME: - { -#if ((SPICE_INTERFACE_RECORD_MAJOR >= 2) && (SPICE_INTERFACE_RECORD_MINOR >= 2)) - SWVoiceIn *sw; - va_list ap; - uint16_t vol[2]; - - va_start (ap, cmd); - sw = va_arg (ap, SWVoiceIn *); - va_end (ap); - - vol[0] = sw->vol.l / ((1ULL << 16) + 1); - vol[1] = sw->vol.r / ((1ULL << 16) + 1); - spice_server_record_set_volume (&in->sin, 2, vol); - spice_server_record_set_mute (&in->sin, sw->vol.mute); -#endif - break; - } } +} - return 0; +#if ((SPICE_INTERFACE_RECORD_MAJOR >= 2) && (SPICE_INTERFACE_RECORD_MINOR >= 2)) +static void line_in_volume(HWVoiceIn *hw, struct mixeng_volume *vol) +{ + SpiceVoiceIn *in = container_of(hw, SpiceVoiceIn, hw); + uint16_t svol[2]; + + svol[0] = vol->l / ((1ULL << 16) + 1); + svol[1] = vol->r / ((1ULL << 16) + 1); + spice_server_record_set_volume(&in->sin, 2, svol); + spice_server_record_set_mute(&in->sin, vol->mute); } +#endif static struct audio_pcm_ops audio_callbacks = { .init_out = line_out_init, @@ -300,12 +280,19 @@ static struct audio_pcm_ops audio_callbacks = { .write = audio_generic_write, .get_buffer_out = line_out_get_buffer, .put_buffer_out = line_out_put_buffer, - .ctl_out = line_out_ctl, + .enable_out = line_out_enable, +#if (SPICE_INTERFACE_PLAYBACK_MAJOR >= 1) && \ + (SPICE_INTERFACE_PLAYBACK_MINOR >= 2) + .volume_out = line_out_volume, +#endif .init_in = line_in_init, .fini_in = line_in_fini, .read = line_in_read, - .ctl_in = line_in_ctl, + .enable_in = line_in_enable, +#if ((SPICE_INTERFACE_RECORD_MAJOR >= 2) && (SPICE_INTERFACE_RECORD_MINOR >= 2)) + .volume_in = line_in_volume, +#endif }; static struct audio_driver spice_audio_driver = { @@ -318,9 +305,6 @@ static struct audio_driver spice_audio_driver = { .max_voices_in = 1, .voice_size_out = sizeof (SpiceVoiceOut), .voice_size_in = sizeof (SpiceVoiceIn), -#if ((SPICE_INTERFACE_PLAYBACK_MAJOR >= 1) && (SPICE_INTERFACE_PLAYBACK_MINOR >= 2)) - .ctl_caps = VOICE_VOLUME_CAP -#endif }; void qemu_spice_audio_init (void) diff --git a/audio/wavaudio.c b/audio/wavaudio.c index 85f5ff9c28..47efdc1b1e 100644 --- a/audio/wavaudio.c +++ b/audio/wavaudio.c @@ -173,14 +173,13 @@ static void wav_fini_out (HWVoiceOut *hw) wav->f = NULL; } -static int wav_ctl_out (HWVoiceOut *hw, int cmd, ...) +static void wav_enable_out(HWVoiceOut *hw, bool enable) { WAVVoiceOut *wav = (WAVVoiceOut *) hw; - if (cmd == VOICE_ENABLE) { + if (enable) { audio_rate_start(&wav->rate); } - return 0; } static void *wav_audio_init(Audiodev *dev) @@ -198,7 +197,7 @@ static struct audio_pcm_ops wav_pcm_ops = { .init_out = wav_init_out, .fini_out = wav_fini_out, .write = wav_write_out, - .ctl_out = wav_ctl_out, + .enable_out = wav_enable_out, }; static struct audio_driver wav_audio_driver = { From patchwork Thu Sep 19 21:24:23 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?UTF-8?B?Wm9sdMOhbiBLxZF2w6Fnw7M=?= X-Patchwork-Id: 1164893 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="T729J/bi"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46Z9KG3bjfz9sNf for ; Fri, 20 Sep 2019 07:41:38 +1000 (AEST) Received: from localhost ([::1]:48702 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB4BD-0001KO-6L for incoming@patchwork.ozlabs.org; Thu, 19 Sep 2019 17:41:35 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53604) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB3us-0002q5-MD for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:44 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iB3uq-0000hi-Ga for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:42 -0400 Received: from mail-wr1-x434.google.com ([2a00:1450:4864:20::434]:40967) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iB3uo-0000eX-8H for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:38 -0400 Received: by mail-wr1-x434.google.com with SMTP id h7so4600766wrw.8 for ; Thu, 19 Sep 2019 14:24:38 -0700 (PDT) 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=SAJE24jrD+6zgfdi/kjreA5oPQEW/oM4tr6aWGLatS8=; b=T729J/bi5mNiTOXtjBdx/MmujoNm0zzx/BBO1/CPFFXJZcgThXQrbOq8uzpKF5HDOb pw3vud2Ca+C+USedsJrxM+EcuKxB/JgsLJjjbSn4r7x6VO+g1ZSu0RgBiBz4hW3TwYGI qPAuKIjdDuk+aJkdfGhM9friSpf8cXs3C5X4BiwPzz+JR8uGLcGF8ibXDunq0JTcrZqs xSGikditgUy1xH186Is6u4ZPTDt46a8izcEFnwjAnR0MV4W4xI+sr2RyKSBtiY+Ap7QX zRTCkdsaVM9voPf2bjfFslaq7A65Ofe4OPCwOUvr8eMZhnVvwGOjWTv1rxd0VgR/TCpj eXCw== 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=SAJE24jrD+6zgfdi/kjreA5oPQEW/oM4tr6aWGLatS8=; b=FqqJHJWIrifmzo5sw7fsOYieZLyCEXg4TQus4vvHNv7QNmneNkksqtBHfP1CQafLBI DlrrjcVQm1EEXtnBLq/uC1/XigUkmcNDmAv8O/nlwq7hxkya7Z9319X1SGr9RrFv/Lut VLFxJOAiczxA3CYQZEjNbikaC4KT3umNxjMCIJbnunBlO3ZVni6jbuv7MSbo5GnsxBu1 Ny31+6tRv/3o4cVOZyd3sPnGpPpd5UiBrBinrY59gCWFBuT1GFxda4910NLeX+hA9Q9p yCk0HTpU6SGW+cimo89X5XzCweyJwFd1wZJcEeL9+SdLTU6IgwnneWOCnLG5K9hJh/1A QRMg== X-Gm-Message-State: APjAAAVyoPKjIuqJokXehtjvyubIUy1CwYC910TzQiLlASWdGjRTs0bm UY6Q38Y2+0lnJSxijSs1x2aLKDIz X-Google-Smtp-Source: APXvYqylUWYkxcp/rt9vR5158j6CZuG4ZQeJ2Hz0o9VBP16zRV56KaFwHtMVRGksgkQ1y/SQn1zLqA== X-Received: by 2002:a5d:5384:: with SMTP id d4mr8582649wrv.255.1568928276927; Thu, 19 Sep 2019 14:24:36 -0700 (PDT) Received: from nullptr.home.dirty-ice.org (2a01-036c-0113-74ef-0000-0000-0000-0005.pool6.digikabel.hu. [2a01:36c:113:74ef::5]) by smtp.gmail.com with ESMTPSA id w125sm13191292wmg.32.2019.09.19.14.24.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Sep 2019 14:24:36 -0700 (PDT) From: "=?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?=" X-Google-Original-From: =?utf-8?b?S8WRdsOhZ8OzLCBab2x0w6Fu?= To: qemu-devel@nongnu.org Subject: [PATCH v4 15/24] audio: add mixing-engine option (documentation) Date: Thu, 19 Sep 2019 23:24:23 +0200 Message-Id: <68c4b4bd438e9cb5c97aed32ee31e3dabd96cbf6.1568927990.git.DirtY.iCE.hu@gmail.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: References: MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::434 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Gerd Hoffmann , Markus Armbruster Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" This will allow us to disable mixeng when we use a decent backend. Disabling mixeng have a few advantages: * we no longer convert the audio output from one format to another, when the underlying audio system would just convert it to a third format. We no longer convert, only the underlying system, when needed. * the underlying system probably has better resampling and sample format converting methods anyway... * we may support formats that the mixeng currently does not support (S24 or float samples, more than two channels) * when using an audio server (like pulseaudio) different sound card outputs will show up as separate streams, even if we use only one backend Disadvantages: * audio capturing no longer works (wavcapture, and vnc audio extension) * some backends only support a single playback stream or very picky about the audio format. In this case we can't disable mixeng. However mixeng is not removed, only made optional, so this shouldn't be a big concern. Signed-off-by: Kővágó, Zoltán --- Notes: Changes from v1: * renamed mixeng to mixing-engine qapi/audio.json | 5 +++++ qemu-options.hx | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/qapi/audio.json b/qapi/audio.json index 9fefdf5186..0535eff794 100644 --- a/qapi/audio.json +++ b/qapi/audio.json @@ -11,6 +11,10 @@ # General audio backend options that are used for both playback and # recording. # +# @mixing-engine: use QEMU's mixing engine to mix all streams inside QEMU. When +# set to off, fixed-settings must be also off. Not every backend +# compatible with the off setting (default on, since 4.2) +# # @fixed-settings: use fixed settings for host input/output. When off, # frequency, channels and format must not be # specified (default true) @@ -31,6 +35,7 @@ ## { 'struct': 'AudiodevPerDirectionOptions', 'data': { + '*mixing-engine': 'bool', '*fixed-settings': 'bool', '*frequency': 'uint32', '*channels': 'uint32', diff --git a/qemu-options.hx b/qemu-options.hx index bbfd936d29..395427422a 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -433,6 +433,7 @@ DEF("audiodev", HAS_ARG, QEMU_OPTION_audiodev, " specifies the audio backend to use\n" " id= identifier of the backend\n" " timer-period= timer period in microseconds\n" + " in|out.mixing-engine= use mixing engine to mix streams inside QEMU\n" " in|out.fixed-settings= use fixed settings for host audio\n" " in|out.frequency= frequency to use with fixed settings\n" " in|out.channels= number of channels to use with fixed settings\n" @@ -503,6 +504,11 @@ Identifies the audio backend. Sets the timer @var{period} used by the audio subsystem in microseconds. Default is 10000 (10 ms). +@item in|out.mixing-engine=on|off +Use QEMU's mixing engine to mix all streams inside QEMU. When off, +@var{fixed-settings} must be off too. Not every backend is fully +compatible with the off setting. Default is on. + @item in|out.fixed-settings=on|off Use fixed settings for host audio. When off, it will change based on how the guest opens the sound card. In this case you must not specify From patchwork Thu Sep 19 21:24:24 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?UTF-8?B?Wm9sdMOhbiBLxZF2w6Fnw7M=?= X-Patchwork-Id: 1164901 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="RvVizH8m"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46Z9Ww2VjNz9sNf for ; Fri, 20 Sep 2019 07:50:52 +1000 (AEST) Received: from localhost ([::1]:48794 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB4K9-0003Cf-Hk for incoming@patchwork.ozlabs.org; Thu, 19 Sep 2019 17:50:49 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53602) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB3us-0002q1-Ly for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:45 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iB3uq-0000i5-MC for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:42 -0400 Received: from mail-wm1-x343.google.com ([2a00:1450:4864:20::343]:38891) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iB3uq-0000fI-Dh for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:40 -0400 Received: by mail-wm1-x343.google.com with SMTP id 3so5632860wmi.3 for ; Thu, 19 Sep 2019 14:24:38 -0700 (PDT) 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=CkbcNK8c6K6YdTYC4vE0JkUjaFLBw/HOWigtjbt3gZ8=; b=RvVizH8mZTJdV+ThiTVZKQI0S5aRua2Y8XCdXxj4n9lugF5qBGulqDicdWq9nPIVg0 aidXHYpNxqqg6lRvjx2xplmSOtCrgyPmDUIh9qrejIKkvCfoy7be/E5e8l1dFGGcUQTY bK/c71i0AwUo9zadUAsHtqoDQpRAErIBIzzDfRoAW9PytKlOb0yGuyBoQaFS5xIgthAo S7QEL4k2SWnZN2lHy6yOuVV5VHl/nYAdmbbgYhsw/ZKCtCNjTdwj5+7jrI4MoLm3cHgb kI4fSOIJ/KLFFCLCd/7KrvLFG7Xfy+g3e4tB79cUCH6QXLt5rofG2N2bG8+4c+2iODVC 2w8w== 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=CkbcNK8c6K6YdTYC4vE0JkUjaFLBw/HOWigtjbt3gZ8=; b=P+HJMBgYcx7kUoi4+8pf9dwvDsRI8hRH8a+QJc5YU3ScCXQxXtk52PcBX9MxYmgciQ PPoVbNOJMTHb8hPaqM5sgoQcRQ2zU53OiF3+5kATkFOB7Iidzibvdbu52fGodGZFaFGz yLC+gcIxsLYYhxv+DmdBNW54Ff4GtMpdKbbK6CGyKau62UJ9tHQo4hP0UH7JvjRUzqfh v/46XsPr/OmARLpWANwhoL09CJJkFdOlMsqVuRZ9XV7rsDM8pW/nllUcLgblzIlDzUsr n4zlAv7yhDf5O2jzMD8Q0BV+RJQWyW8s2u71hDUOIlRl7yMxgtQfGvSnvLJ9QRoIAl7s aLfA== X-Gm-Message-State: APjAAAVTJwjLZLWBVSHcFxlAwsbQbjy5VU9YHMS21lsf0nqngLYL08j0 MFlUarylebOqD70Ne+DlNzP30GO7 X-Google-Smtp-Source: APXvYqwXqhl7qLA3iKDBWGJmMtl7L8p/42YCKt/Ijt4JEXI4TLZt4JusV0847SErLOKAAUnlXhuavg== X-Received: by 2002:a05:600c:1103:: with SMTP id b3mr75885wma.3.1568928277780; Thu, 19 Sep 2019 14:24:37 -0700 (PDT) Received: from nullptr.home.dirty-ice.org (2a01-036c-0113-74ef-0000-0000-0000-0005.pool6.digikabel.hu. [2a01:36c:113:74ef::5]) by smtp.gmail.com with ESMTPSA id w125sm13191292wmg.32.2019.09.19.14.24.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Sep 2019 14:24:37 -0700 (PDT) From: "=?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?=" X-Google-Original-From: =?utf-8?b?S8WRdsOhZ8OzLCBab2x0w6Fu?= To: qemu-devel@nongnu.org Subject: [PATCH v4 16/24] audio: make mixeng optional Date: Thu, 19 Sep 2019 23:24:24 +0200 Message-Id: X-Mailer: git-send-email 2.23.0 In-Reply-To: References: MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::343 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Gerd Hoffmann Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Implementation of the previously added mixing-engine option. Signed-off-by: Kővágó, Zoltán --- audio/audio.c | 70 ++++++++++++++++++++++++++++++++++++++---- audio/audio_template.h | 20 ++++++++---- 2 files changed, 78 insertions(+), 12 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index 7128ee98dc..d616a4af98 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -838,32 +838,46 @@ 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; } - return audio_pcm_sw_write(sw, buf, size); + 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; } - return audio_pcm_sw_read(sw, buf, size); + 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) @@ -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; @@ -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; @@ -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); @@ -1905,9 +1955,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 +1969,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 +1984,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; diff --git a/audio/audio_template.h b/audio/audio_template.h index 235d1acbbe..b6c5466cff 100644 --- a/audio/audio_template.h +++ b/audio/audio_template.h @@ -78,13 +78,17 @@ static void glue (audio_pcm_hw_free_resources_, TYPE) (HW *hw) static void glue(audio_pcm_hw_alloc_resources_, TYPE)(HW *hw) { - size_t samples = hw->samples; - if (audio_bug(__func__, samples == 0)) { - dolog("Attempted to allocate empty buffer\n"); - } + 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"); + } - HWBUF = g_malloc0(sizeof(STSampleBuffer) + sizeof(st_sample) * samples); - HWBUF->size = samples; + 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)); From patchwork Thu Sep 19 21:24:26 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?UTF-8?B?Wm9sdMOhbiBLxZF2w6Fnw7M=?= X-Patchwork-Id: 1164892 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="qYG/PH9T"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46Z9D63rj8z9sNk for ; Fri, 20 Sep 2019 07:37:10 +1000 (AEST) Received: from localhost ([::1]:48680 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB46t-0004O5-PJ for incoming@patchwork.ozlabs.org; Thu, 19 Sep 2019 17:37:07 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53656) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB3uv-0002tD-91 for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:47 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iB3us-0000jH-Lg for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:44 -0400 Received: from mail-wr1-x442.google.com ([2a00:1450:4864:20::442]:44247) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iB3uq-0000h9-IW for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:42 -0400 Received: by mail-wr1-x442.google.com with SMTP id i18so4581957wru.11 for ; Thu, 19 Sep 2019 14:24:40 -0700 (PDT) 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=hBNbSNYdRxpi4YPwJzeBrQcOF4eLYJl4drOoaIZgmh0=; b=qYG/PH9TAJA2E3I9z14eo1AM0NVKw0EoWcxBq/VOw4CBOyly+wSPNYG6VmNBkavyre +fzp+avRUTYVP2/eDn4+xCF7GpB2XI2bn+f9FYXiNrhLl07/7aPKnTrJjJucyqxLIthZ B5/ymK4ywvnqoQgoeCCMvO2UTbQ/x7lYWaADUeSh05kKfCHWZzLwQgU2tmSpnO+LVx50 uavtMFGpft8W4UKGcB/z1BfcIIth+vmpIsL1vRPR08xoerarXUWvAxae8/Rq1Jxjamx2 MWJ34N0z7hQpY185bgG9wsVozmwxtMJ7bSAUyGgf+oPt8i0UXMgg2f8TInPiG+j2vB1I bFjg== 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=hBNbSNYdRxpi4YPwJzeBrQcOF4eLYJl4drOoaIZgmh0=; b=fs6hQuDZLOfmBmrt1lZv6g9YTmyluBzqUbfMZ7UJPQUrNAXJzurpMZfhmzUcGKPBs/ BA9GCc4NgdAl0zwWT0VgRM3u7skCbj46nHLvJTuA1674JF9OubJkgrIlMprgPUVKQcIX HJaLop0CfH8G2gAXJnPHv5KCFyAXC4vvnON9umi0mI2ZdsPIjbfHP1Pl4wA7m5cpCyep 5WIfPLJKAbzM3E979YsSnOlVPN1euIWvQgP7WI2yLyUDfCogPRQmc/S/5nUcUfErYyEq S9yARN28+cTCXWu27kUwigVfKT9tF4hj+4rggk+EhLWZyDn07GHlARr3GqUM6pFp7z4R eIXA== X-Gm-Message-State: APjAAAXYWKJLipGt0ZsYGe/rct0PaKbJV89tL7/hK8azcZuY9mH8u4JL +nQ9wzbVgxN7HdgHN83T/coHLl5a X-Google-Smtp-Source: APXvYqw5xuUIwvXtnTghIehZQONtnXxXl2zaK3tNNehqdEzVbXDfrCg626EwAhctGH/QPgYGr/ki4w== X-Received: by 2002:a5d:4745:: with SMTP id o5mr8418666wrs.125.1568928279259; Thu, 19 Sep 2019 14:24:39 -0700 (PDT) Received: from nullptr.home.dirty-ice.org (2a01-036c-0113-74ef-0000-0000-0000-0005.pool6.digikabel.hu. [2a01:36c:113:74ef::5]) by smtp.gmail.com with ESMTPSA id w125sm13191292wmg.32.2019.09.19.14.24.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Sep 2019 14:24:38 -0700 (PDT) From: "=?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?=" X-Google-Original-From: =?utf-8?b?S8WRdsOhZ8OzLCBab2x0w6Fu?= To: qemu-devel@nongnu.org Subject: [PATCH v4 18/24] audio: support more than two channels in volume setting Date: Thu, 19 Sep 2019 23:24:26 +0200 Message-Id: <554e7d54424036e01ac0be8d5baccd2ccc8393cc.1568927990.git.DirtY.iCE.hu@gmail.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: References: MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::442 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Gerd Hoffmann Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Signed-off-by: Kővágó, Zoltán --- audio/audio.c | 30 ++++++++++++++++++++++-------- audio/audio.h | 10 ++++++++++ audio/audio_int.h | 4 ++-- audio/paaudio.c | 20 ++++++++++++-------- audio/spiceaudio.c | 14 ++++++++------ 5 files changed, 54 insertions(+), 24 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index d616a4af98..f1c145dfcd 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -1891,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); } } } diff --git a/audio/audio.h b/audio/audio.h index c74abb8c47..0db3c7dd5e 100644 --- a/audio/audio.h +++ b/audio/audio.h @@ -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, diff --git a/audio/audio_int.h b/audio/audio_int.h index 22a703c13e..9176db249b 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -166,7 +166,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 +174,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); diff --git a/audio/paaudio.c b/audio/paaudio.c index 6ccdf31415..d195b1caa8 100644 --- a/audio/paaudio.c +++ b/audio/paaudio.c @@ -531,20 +531,22 @@ static void qpa_fini_in (HWVoiceIn *hw) } } -static void qpa_volume_out(HWVoiceOut *hw, struct mixeng_volume *vol) +static void qpa_volume_out(HWVoiceOut *hw, Volume *vol) { PAVoiceOut *pa = (PAVoiceOut *) hw; pa_operation *op; pa_cvolume v; PAConnection *c = pa->g->conn; + int i; #ifdef PA_CHECK_VERSION /* macro is present in 0.9.16+ */ pa_cvolume_init (&v); /* function is present in 0.9.13+ */ #endif - v.channels = 2; - v.values[0] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * vol->l) / UINT32_MAX; - v.values[1] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * vol->r) / UINT32_MAX; + v.channels = vol->channels; + for (i = 0; i < vol->channels; ++i) { + v.values[i] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * vol->vol[i]) / 255; + } pa_threaded_mainloop_lock(c->mainloop); @@ -571,20 +573,22 @@ static void qpa_volume_out(HWVoiceOut *hw, struct mixeng_volume *vol) pa_threaded_mainloop_unlock(c->mainloop); } -static void qpa_volume_in(HWVoiceIn *hw, struct mixeng_volume *vol) +static void qpa_volume_in(HWVoiceIn *hw, Volume *vol) { PAVoiceIn *pa = (PAVoiceIn *) hw; pa_operation *op; pa_cvolume v; PAConnection *c = pa->g->conn; + int i; #ifdef PA_CHECK_VERSION pa_cvolume_init (&v); #endif - v.channels = 2; - v.values[0] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * vol->l) / UINT32_MAX; - v.values[1] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * vol->r) / UINT32_MAX; + v.channels = vol->channels; + for (i = 0; i < vol->channels; ++i) { + v.values[i] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * vol->vol[i]) / 255; + } pa_threaded_mainloop_lock(c->mainloop); diff --git a/audio/spiceaudio.c b/audio/spiceaudio.c index 9860f9c5e1..6ed7f7a79e 100644 --- a/audio/spiceaudio.c +++ b/audio/spiceaudio.c @@ -179,13 +179,14 @@ static void line_out_enable(HWVoiceOut *hw, bool enable) } #if ((SPICE_INTERFACE_PLAYBACK_MAJOR >= 1) && (SPICE_INTERFACE_PLAYBACK_MINOR >= 2)) -static void line_out_volume(HWVoiceOut *hw, struct mixeng_volume *vol) +static void line_out_volume(HWVoiceOut *hw, Volume *vol) { SpiceVoiceOut *out = container_of(hw, SpiceVoiceOut, hw); uint16_t svol[2]; - svol[0] = vol->l / ((1ULL << 16) + 1); - svol[1] = vol->r / ((1ULL << 16) + 1); + assert(vol->channels == 2); + svol[0] = vol->vol[0] * 257; + svol[1] = vol->vol[1] * 257; spice_server_playback_set_volume(&out->sin, 2, svol); spice_server_playback_set_mute(&out->sin, vol->mute); } @@ -262,13 +263,14 @@ static void line_in_enable(HWVoiceIn *hw, bool enable) } #if ((SPICE_INTERFACE_RECORD_MAJOR >= 2) && (SPICE_INTERFACE_RECORD_MINOR >= 2)) -static void line_in_volume(HWVoiceIn *hw, struct mixeng_volume *vol) +static void line_in_volume(HWVoiceIn *hw, Volume *vol) { SpiceVoiceIn *in = container_of(hw, SpiceVoiceIn, hw); uint16_t svol[2]; - svol[0] = vol->l / ((1ULL << 16) + 1); - svol[1] = vol->r / ((1ULL << 16) + 1); + assert(vol->channels == 2); + svol[0] = vol->vol[0] * 257; + svol[1] = vol->vol[1] * 257; spice_server_record_set_volume(&in->sin, 2, svol); spice_server_record_set_mute(&in->sin, vol->mute); } From patchwork Thu Sep 19 21:24:27 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?UTF-8?B?Wm9sdMOhbiBLxZF2w6Fnw7M=?= X-Patchwork-Id: 1164915 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="PUpOmbvJ"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46Z9tm2Yhcz9sPT for ; Fri, 20 Sep 2019 08:07:12 +1000 (AEST) Received: from localhost ([::1]:48940 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB4Zx-00050O-Nz for incoming@patchwork.ozlabs.org; Thu, 19 Sep 2019 18:07:09 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53694) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB3ux-0002vS-2J for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:49 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iB3ut-0000jb-0O for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:46 -0400 Received: from mail-wr1-x431.google.com ([2a00:1450:4864:20::431]:40028) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iB3us-0000iJ-JI for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:42 -0400 Received: by mail-wr1-x431.google.com with SMTP id l3so4606633wru.7 for ; Thu, 19 Sep 2019 14:24:41 -0700 (PDT) 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=FZBJxE6vgXiUYQRHq25EgBqFYd27odUS2eGRI60cvzc=; b=PUpOmbvJ5Q6hSiIIJUH7zyWeW0pHpJiXrPWTDybP85CBlVMijePeWx15eN4MFie9u6 zq9ecygcB2AoU+oL9W0bpW1E5BJnNMzJW8D8gUnNJWhM+mM4C6KMZgydQqzVRb4kOXPw HIXvL0R4aUYpJQ6ChgtQ6ICMBw5wWXi8x/htuKAX7trnluyltz5+U2P5zqFrvoDieu/c V/d4mUmT8U/AuoGo4dhdcLaZpP/s3gN/Z4q/UMnrbHyzB9QKddxxSo8RfzoRxSpaDO3W hn2IGXrr+Wl/gl4YozCWaKMv2NvvZ8zW2I9dvmbDHIAUrg6vHl16vgyrUGUHI4Wdru0w 319g== 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=FZBJxE6vgXiUYQRHq25EgBqFYd27odUS2eGRI60cvzc=; b=OLbLYuav7UQj9/LLRrj4lRpX5+DyrMnAeEX3Wr59fcB12zoEsyRipoxLR69WqLj00N bn8nTcD3JZDYp8+qhgYWFJUAXKu0ALBMxQgpk1dIMtjJl8m5fN8zcAe27c4TE/2V40Yp He9PBfvKdUG6trc/hwAThRuTyLyh0k+wDOXj5HJcXqkwNFIu1oA8v1lL18McZQ5UcEZs 6cAVWntAr92e5KgPfhQZD1X7ntdWnxcGlT5uLA/eIDuuEtZYhERMYaFUx/BR58krr26b XZaXUEf7LuJ3EObachmcsJ0Wjbp1imS90VAubDGfYpYcNUvuzJbXh3c/xi1HX/PnOmBJ r6+Q== X-Gm-Message-State: APjAAAVp43sUtitDgqc364HxClFa6qdZGSYnff4QYmCZkjEWGAaFJ3VG Gab4GFTuWjFUJxToPtF6iB6VLYZR X-Google-Smtp-Source: APXvYqxkHSacdfPXOgoxnKTRh4DPOOL2Sp95SlZz4o8XVi0NETg97Lo+ozYAffgskDFuR8FF/uCn+g== X-Received: by 2002:a05:6000:188:: with SMTP id p8mr6280066wrx.220.1568928280006; Thu, 19 Sep 2019 14:24:40 -0700 (PDT) Received: from nullptr.home.dirty-ice.org (2a01-036c-0113-74ef-0000-0000-0000-0005.pool6.digikabel.hu. [2a01:36c:113:74ef::5]) by smtp.gmail.com with ESMTPSA id w125sm13191292wmg.32.2019.09.19.14.24.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Sep 2019 14:24:39 -0700 (PDT) From: "=?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?=" X-Google-Original-From: =?utf-8?b?S8WRdsOhZ8OzLCBab2x0w6Fu?= To: qemu-devel@nongnu.org Subject: [PATCH v4 19/24] audio: replace shift in audio_pcm_info with bytes_per_frame Date: Thu, 19 Sep 2019 23:24:27 +0200 Message-Id: <423e5476cce3b8a0a92b08dcf0e0f5bb620adf0e.1568927990.git.DirtY.iCE.hu@gmail.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: References: MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::431 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Gerd Hoffmann Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" The bit shifting trick worked because the number of bytes per frame was always a power-of-two (since QEMU only supports mono, stereo and 8, 16 and 32 bit samples). But if we want to add support for surround sound, this no longer holds true. Signed-off-by: Kővágó, Zoltán --- audio/alsaaudio.c | 11 +++--- audio/audio.c | 74 ++++++++++++++++++++--------------------- audio/audio_int.h | 3 +- audio/coreaudio.c | 4 +-- audio/dsound_template.h | 10 +++--- audio/dsoundaudio.c | 4 +-- audio/noaudio.c | 2 +- audio/ossaudio.c | 14 ++++---- audio/spiceaudio.c | 3 +- audio/wavaudio.c | 6 ++-- 10 files changed, 66 insertions(+), 65 deletions(-) diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index cfe42284a6..eddf013a53 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -602,7 +602,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 +648,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 +802,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 +829,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; diff --git a/audio/audio.c b/audio/audio.c index f1c145dfcd..c00f4deddd 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -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 @@ -882,7 +880,7 @@ size_t AUD_read(SWVoiceIn *sw, void *buf, size_t 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) @@ -998,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) @@ -1025,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, @@ -1047,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; @@ -1082,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; @@ -1234,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); @@ -1251,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; @@ -1325,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; @@ -1378,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; @@ -1414,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; @@ -1833,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] @@ -2153,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; } diff --git a/audio/audio_int.h b/audio/audio_int.h index 9176db249b..5ba2078346 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -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; }; diff --git a/audio/coreaudio.c b/audio/coreaudio.c index 1427c9f622..66f0f459cf 100644 --- a/audio/coreaudio.c +++ b/audio/coreaudio.c @@ -440,7 +440,7 @@ static OSStatus audioDeviceIOProc( } frameCount = core->audioDevicePropertyBufferFrameSize; - pending_frames = hw->pending_emul >> hw->info.shift; + pending_frames = hw->pending_emul / hw->info.bytes_per_frame; /* if there are not enough samples, set signal and return */ if (pending_frames < frameCount) { @@ -449,7 +449,7 @@ static OSStatus audioDeviceIOProc( return 0; } - len = frameCount << hw->info.shift; + len = frameCount * hw->info.bytes_per_frame; while (len) { size_t write_len; ssize_t start = ((ssize_t) hw->pos_emul) - hw->pending_emul; diff --git a/audio/dsound_template.h b/audio/dsound_template.h index 9f10b688df..7a15f91ce5 100644 --- a/audio/dsound_template.h +++ b/audio/dsound_template.h @@ -98,8 +98,8 @@ static int glue (dsound_lock_, TYPE) ( goto fail; } - if ((p1p && *p1p && (*blen1p & info->align)) || - (p2p && *p2p && (*blen2p & info->align))) { + if ((p1p && *p1p && (*blen1p % info->bytes_per_frame)) || + (p2p && *p2p && (*blen2p % info->bytes_per_frame))) { dolog("DirectSound returned misaligned buffer %ld %ld\n", *blen1p, *blen2p); glue(dsound_unlock_, TYPE)(buf, *p1p, p2p ? *p2p : NULL, *blen1p, @@ -247,14 +247,14 @@ static int dsound_init_out(HWVoiceOut *hw, struct audsettings *as, obt_as.endianness = 0; audio_pcm_init_info (&hw->info, &obt_as); - if (bc.dwBufferBytes & hw->info.align) { + if (bc.dwBufferBytes % hw->info.bytes_per_frame) { dolog ( "GetCaps returned misaligned buffer size %ld, alignment %d\n", - bc.dwBufferBytes, hw->info.align + 1 + bc.dwBufferBytes, hw->info.bytes_per_frame ); } hw->size_emul = bc.dwBufferBytes; - hw->samples = bc.dwBufferBytes >> hw->info.shift; + hw->samples = bc.dwBufferBytes / hw->info.bytes_per_frame; ds->s = s; #ifdef DEBUG_DSOUND diff --git a/audio/dsoundaudio.c b/audio/dsoundaudio.c index d4a4757445..c265c0094b 100644 --- a/audio/dsoundaudio.c +++ b/audio/dsoundaudio.c @@ -320,8 +320,8 @@ static void dsound_clear_sample (HWVoiceOut *hw, LPDIRECTSOUNDBUFFER dsb, return; } - len1 = blen1 >> hw->info.shift; - len2 = blen2 >> hw->info.shift; + len1 = blen1 / hw->info.bytes_per_frame; + len2 = blen2 / hw->info.bytes_per_frame; #ifdef DEBUG_DSOUND dolog ("clear %p,%ld,%ld %p,%ld,%ld\n", diff --git a/audio/noaudio.c b/audio/noaudio.c index ec8a287f36..ff99b253ff 100644 --- a/audio/noaudio.c +++ b/audio/noaudio.c @@ -91,7 +91,7 @@ static size_t no_read(HWVoiceIn *hw, void *buf, size_t size) NoVoiceIn *no = (NoVoiceIn *) hw; int64_t bytes = audio_rate_get_bytes(&hw->info, &no->rate, size); - audio_pcm_info_clear_buf(&hw->info, buf, bytes >> hw->info.shift); + audio_pcm_info_clear_buf(&hw->info, buf, bytes / hw->info.bytes_per_frame); return bytes; } diff --git a/audio/ossaudio.c b/audio/ossaudio.c index 0c4451e972..c43faeeea4 100644 --- a/audio/ossaudio.c +++ b/audio/ossaudio.c @@ -506,16 +506,16 @@ static int oss_init_out(HWVoiceOut *hw, struct audsettings *as, oss->nfrags = obt.nfrags; oss->fragsize = obt.fragsize; - if (obt.nfrags * obt.fragsize & hw->info.align) { + if (obt.nfrags * obt.fragsize % hw->info.bytes_per_frame) { dolog ("warning: Misaligned DAC buffer, size %d, alignment %d\n", - obt.nfrags * obt.fragsize, hw->info.align + 1); + obt.nfrags * obt.fragsize, hw->info.bytes_per_frame); } - hw->samples = (obt.nfrags * obt.fragsize) >> hw->info.shift; + hw->samples = (obt.nfrags * obt.fragsize) / hw->info.bytes_per_frame; oss->mmapped = 0; if (oopts->has_try_mmap && oopts->try_mmap) { - hw->size_emul = hw->samples << hw->info.shift; + hw->size_emul = hw->samples * hw->info.bytes_per_frame; hw->buf_emul = mmap( NULL, hw->size_emul, @@ -644,12 +644,12 @@ static int oss_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) oss->nfrags = obt.nfrags; oss->fragsize = obt.fragsize; - if (obt.nfrags * obt.fragsize & hw->info.align) { + if (obt.nfrags * obt.fragsize % hw->info.bytes_per_frame) { dolog ("warning: Misaligned ADC buffer, size %d, alignment %d\n", - obt.nfrags * obt.fragsize, hw->info.align + 1); + obt.nfrags * obt.fragsize, hw->info.bytes_per_frame); } - hw->samples = (obt.nfrags * obt.fragsize) >> hw->info.shift; + hw->samples = (obt.nfrags * obt.fragsize) / hw->info.bytes_per_frame; oss->fd = fd; oss->dev = dev; diff --git a/audio/spiceaudio.c b/audio/spiceaudio.c index 6ed7f7a79e..b6b5da4812 100644 --- a/audio/spiceaudio.c +++ b/audio/spiceaudio.c @@ -131,7 +131,8 @@ static void *line_out_get_buffer(HWVoiceOut *hw, size_t *size) if (out->frame) { *size = audio_rate_get_bytes( - &hw->info, &out->rate, (out->fsize - out->fpos) << hw->info.shift); + &hw->info, &out->rate, + (out->fsize - out->fpos) * hw->info.bytes_per_frame); } else { audio_rate_start(&out->rate); } diff --git a/audio/wavaudio.c b/audio/wavaudio.c index 47efdc1b1e..e46d834bd3 100644 --- a/audio/wavaudio.c +++ b/audio/wavaudio.c @@ -43,14 +43,14 @@ static size_t wav_write_out(HWVoiceOut *hw, void *buf, size_t len) { WAVVoiceOut *wav = (WAVVoiceOut *) hw; int64_t bytes = audio_rate_get_bytes(&hw->info, &wav->rate, len); - assert(bytes >> hw->info.shift << hw->info.shift == bytes); + assert(bytes % hw->info.bytes_per_frame == 0); if (bytes && fwrite(buf, bytes, 1, wav->f) != 1) { dolog("wav_write_out: fwrite of %" PRId64 " bytes failed\nReason: %s\n", bytes, strerror(errno)); } - wav->total_samples += bytes >> hw->info.shift; + wav->total_samples += bytes / hw->info.bytes_per_frame; return bytes; } @@ -134,7 +134,7 @@ static void wav_fini_out (HWVoiceOut *hw) WAVVoiceOut *wav = (WAVVoiceOut *) hw; uint8_t rlen[4]; uint8_t dlen[4]; - uint32_t datalen = wav->total_samples << hw->info.shift; + uint32_t datalen = wav->total_samples * hw->info.bytes_per_frame; uint32_t rifflen = datalen + 36; if (!wav->f) { From patchwork Thu Sep 19 21:24:28 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?UTF-8?B?Wm9sdMOhbiBLxZF2w6Fnw7M=?= X-Patchwork-Id: 1164888 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="AHOSlsIf"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46Z95B2hvLz9sPG for ; Fri, 20 Sep 2019 07:31:08 +1000 (AEST) Received: from localhost ([::1]:48642 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB412-0007QV-P1 for incoming@patchwork.ozlabs.org; Thu, 19 Sep 2019 17:31:04 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53646) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB3uu-0002so-Ul for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:46 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iB3ut-0000jg-0j for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:44 -0400 Received: from mail-wm1-x336.google.com ([2a00:1450:4864:20::336]:36487) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iB3us-0000iS-MI for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:42 -0400 Received: by mail-wm1-x336.google.com with SMTP id m18so7313wmc.1 for ; Thu, 19 Sep 2019 14:24:41 -0700 (PDT) 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=I/J8Dq/+F7R0/J6BZwd7lt84Aly4P3hEz64ceVDIF5c=; b=AHOSlsIfbajntxWCcG9fEUs344E6E1JUHXLXxLaIUc/mBfTNysPLGeivbZYYtDy+bY /L0dKFQRhmFNSQM8b2BdUM/WKBodRpxM9gcpxV846OXsV4gZwtVCqGpdTMu8sJv/7ya1 zaqraQm6GGbJh7hyvdw8lOOjiDoFEVbPw7utdKg7N/Yg09jLktWFzQRV5cIrMU/b6NsS qmS/aDDx+f0tTZPKDa4ss+PI/XUso9zV/KdH1KNDiS6IGgvXLy7x1lqEFpML2XlteOWs wJtBFFux31aOfK45b2BkKxrFPm/Dvnz1jfKCC4R7VFgoGV4UkciWr4sKgHc7ka8bxA07 VOuw== 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=I/J8Dq/+F7R0/J6BZwd7lt84Aly4P3hEz64ceVDIF5c=; b=gun1KyzjuTXFmwNlJ6XcvUPn/W0JTB0ldJIZwup8/yjcs5jn7i1KQ5GVHxMcXw4u22 8briC4b4GBLW/n+dQEp4mywcSZByWKh31xhxeu1uzEOodWzdcnKBiwvm28i4BTa1dgo8 pHA09X9zjzucSdotO1KDpGvtClJ8zjqgyRuMqLT+60uMGaYYcZ0+nWv6wiSxMwDxuH9+ 9mp+H2cRqBd0cOraM36GXQiC0lv4NyUkaPtpmLDR9K7ppaYMLT6iM7rq0OMEboe95BGB SEJ/aPw+915TD+bHfT3o+9tkgkH+xRjdc3TeHpfocSxgPVMvMBD3qdKFxRh4AD6MBSHq r71w== X-Gm-Message-State: APjAAAVz/9HWn28gKzG2wMAGvtMMuRmfV8tFkNXSOT3Q6JJT2B/mMReH ho9tZNAmuZ43SSp/Q36fWJQZxY9j X-Google-Smtp-Source: APXvYqwhbqDcI0Hk9Oiw45ldyKVbrXPxNIeYszs4t2bnBqNA7h3bdZMxUViKkwspl4QYHIdgHcPDvg== X-Received: by 2002:a1c:35c9:: with SMTP id c192mr62686wma.91.1568928280857; Thu, 19 Sep 2019 14:24:40 -0700 (PDT) Received: from nullptr.home.dirty-ice.org (2a01-036c-0113-74ef-0000-0000-0000-0005.pool6.digikabel.hu. [2a01:36c:113:74ef::5]) by smtp.gmail.com with ESMTPSA id w125sm13191292wmg.32.2019.09.19.14.24.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Sep 2019 14:24:40 -0700 (PDT) From: "=?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?=" X-Google-Original-From: =?utf-8?b?S8WRdsOhZ8OzLCBab2x0w6Fu?= To: qemu-devel@nongnu.org Subject: [PATCH v4 20/24] audio: basic support for multichannel audio Date: Thu, 19 Sep 2019 23:24:28 +0200 Message-Id: <6af77a930dc3cce0b807154182ad621a64786307.1568927990.git.DirtY.iCE.hu@gmail.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: References: MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::336 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Gerd Hoffmann Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Which currently only means removing some checks. Old code won't require more than two channels, but new code will need it. Signed-off-by: Kővágó, Zoltán --- audio/alsaaudio.c | 7 ------- audio/audio.c | 2 +- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index eddf013a53..f37ce1ce85 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -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; diff --git a/audio/audio.c b/audio/audio.c index c00f4deddd..7fc3aa9d16 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -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) { From patchwork Thu Sep 19 21:24:29 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?UTF-8?B?Wm9sdMOhbiBLxZF2w6Fnw7M=?= X-Patchwork-Id: 1164908 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="ktJAOxZT"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46Z9hJ436Zz9sCJ for ; Fri, 20 Sep 2019 07:58:06 +1000 (AEST) Received: from localhost ([::1]:48858 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB4R8-0003P3-WE for incoming@patchwork.ozlabs.org; Thu, 19 Sep 2019 17:58:03 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53660) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB3uv-0002tS-EG for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:47 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iB3ut-0000jq-BR for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:45 -0400 Received: from mail-wr1-x444.google.com ([2a00:1450:4864:20::444]:46637) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iB3ut-0000is-2u for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:43 -0400 Received: by mail-wr1-x444.google.com with SMTP id o18so4579870wrv.13 for ; Thu, 19 Sep 2019 14:24:42 -0700 (PDT) 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=yGxCQiMWd3+h7OUolo7+j9DrxcBH9Yz1dYvYs0gOXqo=; b=ktJAOxZT0NTQZfY4adOCjCLRlTRu745Q4ye3K1mJeic1SKuOrcXvZPszIl10UylYeV Wrn4CxbipRsBv55ISjiG2/eUKkAqC+ftZlZ+4GR5RNRCZnnpI+5/vAsttJl2gqzMHxtk Wl7CyVoaqymiIFFaB304cZBaNDXKPEiRRkI4DFrhDLHZsVA886wWSmnYJbDgRI0Ol1eT vJ4GehOVZUCWl1JIU8rtTDCujdTA66FZyuS1zJkiftBQmPErevaQn5MoFcUWdBZj1OaC +zo3Nu3WLpXEh0IkZ+OX50j8+Jj2hd+CEv0Fnmb2Gxt1nRWn8xMWBCx5ExiyjVgr3GfF EQ6g== 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=yGxCQiMWd3+h7OUolo7+j9DrxcBH9Yz1dYvYs0gOXqo=; b=V56OtbV8lpu/0XM1b4z0fcNeYvovKELfnRNvE9YuqxKvyVuPWeCIrwpyuB/rifgESh jZ4s0Sk+icJyrYEsHYjlTHqzGnD0v4NSm9KAiaYIAmtsjh3kVMzDGHqioKKmIjJ85dnn cN2zPjk9jyoE791DK3Zxo9SrwBWW6Et6T9SWY2/L1PMQcTrKIP+giJO5ZClKOLCqTPZb BieTtKDsCxxjYO4HlnZjki1cQgmDr6FgT6wFy6q5X2nAxeYImrBaUv1qbPLkaIHneOyc HhAPFjFvDIJ0NX5YG4EJA4dIFCb9UzKzdXbCu9/iy6guDzSlcroK3RAXtROcI3KjXV3g pqOA== X-Gm-Message-State: APjAAAXz6oKSiBfGs//TXfzVOP+7aDWLG4/JYos2KRh6OZRmJSm/Rah6 9Iwdwvy1PFIjuo7vgtrUCJGyZDsE X-Google-Smtp-Source: APXvYqzT4zBmE9z9FSGlCKtuFMbF6jyyuB6ES6nDmks+9wBgGQ4wbDXhWurNYtT9cM+D02goIPv/sg== X-Received: by 2002:a5d:660c:: with SMTP id n12mr8973719wru.286.1568928281692; Thu, 19 Sep 2019 14:24:41 -0700 (PDT) Received: from nullptr.home.dirty-ice.org (2a01-036c-0113-74ef-0000-0000-0000-0005.pool6.digikabel.hu. [2a01:36c:113:74ef::5]) by smtp.gmail.com with ESMTPSA id w125sm13191292wmg.32.2019.09.19.14.24.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Sep 2019 14:24:41 -0700 (PDT) From: "=?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?=" X-Google-Original-From: =?utf-8?b?S8WRdsOhZ8OzLCBab2x0w6Fu?= To: qemu-devel@nongnu.org Subject: [PATCH v4 21/24] paaudio: channel-map option Date: Thu, 19 Sep 2019 23:24:29 +0200 Message-Id: <8f650662fd6cc50baaede260581aeb560eed44fb.1568927990.git.DirtY.iCE.hu@gmail.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: References: MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::444 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Gerd Hoffmann , Markus Armbruster Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Add an option to change the channel map used by pulseaudio. If not specified, falls back to an OSS compatible channel map. Signed-off-by: Kővágó, Zoltán --- audio/paaudio.c | 18 ++++++++++++++---- qapi/audio.json | 7 +++++-- qemu-options.hx | 9 +++++++++ 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/audio/paaudio.c b/audio/paaudio.c index d195b1caa8..20402b0718 100644 --- a/audio/paaudio.c +++ b/audio/paaudio.c @@ -338,17 +338,27 @@ static pa_stream *qpa_simple_new ( pa_stream_direction_t dir, const char *dev, const pa_sample_spec *ss, - const pa_channel_map *map, + const char *map, const pa_buffer_attr *attr, int *rerror) { int r; pa_stream *stream; pa_stream_flags_t flags; + pa_channel_map pa_map; pa_threaded_mainloop_lock(c->mainloop); - stream = pa_stream_new(c->context, name, ss, map); + if (map && !pa_channel_map_parse(&pa_map, map)) { + dolog("Invalid channel map specified: '%s'\n", map); + map = NULL; + } + if (!map) { + pa_channel_map_init_extend(&pa_map, ss->channels, + PA_CHANNEL_MAP_OSS); + } + + stream = pa_stream_new(c->context, name, ss, &pa_map); if (!stream) { goto fail; } @@ -421,7 +431,7 @@ static int qpa_init_out(HWVoiceOut *hw, struct audsettings *as, PA_STREAM_PLAYBACK, ppdo->has_name ? ppdo->name : NULL, &ss, - NULL, /* channel map */ + ppdo->has_channel_map ? ppdo->channel_map : NULL, &ba, /* buffering attributes */ &error ); @@ -470,7 +480,7 @@ static int qpa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) PA_STREAM_RECORD, ppdo->has_name ? ppdo->name : NULL, &ss, - NULL, /* channel map */ + ppdo->has_channel_map ? ppdo->channel_map : NULL, &ba, /* buffering attributes */ &error ); diff --git a/qapi/audio.json b/qapi/audio.json index 0535eff794..07003808cb 100644 --- a/qapi/audio.json +++ b/qapi/audio.json @@ -214,13 +214,16 @@ # @latency: latency you want PulseAudio to achieve in microseconds # (default 15000) # +# @channel-map: channel map to use (default: OSS compatible map, since: 4.2) +# # Since: 4.0 ## { 'struct': 'AudiodevPaPerDirectionOptions', 'base': 'AudiodevPerDirectionOptions', 'data': { - '*name': 'str', - '*latency': 'uint32' } } + '*name': 'str', + '*latency': 'uint32', + '*channel-map': 'str' } } ## # @AudiodevPaOptions: diff --git a/qemu-options.hx b/qemu-options.hx index 395427422a..f3bc342f98 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -471,6 +471,7 @@ DEF("audiodev", HAS_ARG, QEMU_OPTION_audiodev, "-audiodev pa,id=id[,prop[=value][,...]]\n" " server= PulseAudio server address\n" " in|out.name= source/sink device name\n" + " in|out.channel-map= channel map to use\n" #endif #ifdef CONFIG_AUDIO_SDL "-audiodev sdl,id=id[,prop[=value][,...]]\n" @@ -636,6 +637,14 @@ Sets the PulseAudio @var{server} to connect to. @item in|out.name=@var{sink} Use the specified source/sink for recording/playback. +@item in|out.channel-map=@var{map} +Use the specified channel map. The default is an OSS compatible +channel map. Do not forget to escape commas inside the map: + +@example +-audiodev pa,id=example,sink.channel-map=front-left,,front-right +@end example + @end table @item -audiodev sdl,id=@var{id}[,@var{prop}[=@var{value}][,...]] From patchwork Thu Sep 19 21:24:30 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?UTF-8?B?Wm9sdMOhbiBLxZF2w6Fnw7M=?= X-Patchwork-Id: 1164898 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="sEAIDvr/"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46Z9Rm2k0fz9sNk for ; Fri, 20 Sep 2019 07:47:16 +1000 (AEST) Received: from localhost ([::1]:48760 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB4Gf-0007TW-LB for incoming@patchwork.ozlabs.org; Thu, 19 Sep 2019 17:47:13 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53669) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB3uv-0002uE-Qt for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:47 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iB3uu-0000k9-2G for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:45 -0400 Received: from mail-wr1-x442.google.com ([2a00:1450:4864:20::442]:45124) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iB3ut-0000jk-QL for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:43 -0400 Received: by mail-wr1-x442.google.com with SMTP id r5so4574832wrm.12 for ; Thu, 19 Sep 2019 14:24:43 -0700 (PDT) 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=8TTUthXqXhh1DdLxMpTCEbLpELmMAAhIVdhapb9+b1E=; b=sEAIDvr/w/jncZIJMs54Dwu0Vf6ErZ6zInfGFlcIdGGHx0ARaMrzeZHH04/kn4zsdi 8vpxpliz6Pw7Q8Ye4VbHR6hAoWMqOSpIFifBdvW7Vv7nYBUXqslr9IDH0s/9KLBZ6Fpy o4wG/HMbY9+hhAYkeCrgJolnhIfE8VhYI8PYWd9qB2OZQI8XYKMj6oHRCO4L8YdkRQJq QLUQJRJVE51pOIqBJaSKm699xN64cRUeX4jMQko1cE/lUTUay+xQAb9BcdTJnrrPy7J5 rYAUmihTEd4wntEFDssFXa2A2rk8i7h57r36+a920RqVoSabazwbxi1nXVznh497opci f6fQ== 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=8TTUthXqXhh1DdLxMpTCEbLpELmMAAhIVdhapb9+b1E=; b=C9wpggCKMj099ZEb6qbMQ/6/tNvAZXzjyj7DwQul0/aWnAAmNiSXpOpt6YJobT57EM d2Hu1viiggqmyw3nOhVBI8txWRKrRP4Kip9WnJ4WwWkqlSrRGvX0rUcYbkJHheQRgM74 C2WH/Xguv20jjqvT/6CrGLMjwHpq1zOnO3lzqZjWPIYXChVnmIKskpsJ5GJcl8YV6F1H LQw0AI0bkX0o3JS7x8m1OTLIiJ8hWijRQm/9VERcXQKU/0hq6BAmc56IOLBCvz7Skyyq DGdY3vL3Hxmz3N9ffigKiPUfq3xoxG3qfD7y9Ep7WT0iABBwv89dAjOu9F4Hb8Q0gAc4 VImw== X-Gm-Message-State: APjAAAUNfBemjWTzWam92iwdskF45WPNXxm2BMzUW/gghN95YHxByXE1 MLJfsIOc3DoaO0HyRo66q4JI5q4b X-Google-Smtp-Source: APXvYqy57j1yKJ8ycKOBM8xXk+FK10g9C+YzUBKnW+tpElyuEeURZrmgAKbi6ZdgP7PUbfLMOOF5HA== X-Received: by 2002:a5d:4dcb:: with SMTP id f11mr2834732wru.239.1568928282547; Thu, 19 Sep 2019 14:24:42 -0700 (PDT) Received: from nullptr.home.dirty-ice.org (2a01-036c-0113-74ef-0000-0000-0000-0005.pool6.digikabel.hu. [2a01:36c:113:74ef::5]) by smtp.gmail.com with ESMTPSA id w125sm13191292wmg.32.2019.09.19.14.24.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Sep 2019 14:24:42 -0700 (PDT) From: "=?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?=" X-Google-Original-From: =?utf-8?b?S8WRdsOhZ8OzLCBab2x0w6Fu?= To: qemu-devel@nongnu.org Subject: [PATCH v4 22/24] usb-audio: do not count on avail bytes actually available Date: Thu, 19 Sep 2019 23:24:30 +0200 Message-Id: X-Mailer: git-send-email 2.23.0 In-Reply-To: References: MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::442 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Gerd Hoffmann Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" This assumption is no longer true when mixeng is turned off. Signed-off-by: Kővágó, Zoltán --- hw/usb/dev-audio.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/hw/usb/dev-audio.c b/hw/usb/dev-audio.c index ae42e5a2f1..74c99b1f12 100644 --- a/hw/usb/dev-audio.c +++ b/hw/usb/dev-audio.c @@ -319,30 +319,31 @@ static int streambuf_put(struct streambuf *buf, USBPacket *p) { uint32_t free = buf->size - (buf->prod - buf->cons); - if (!free) { + if (free < USBAUDIO_PACKET_SIZE) { return 0; } if (p->iov.size != USBAUDIO_PACKET_SIZE) { return 0; } - assert(free >= USBAUDIO_PACKET_SIZE); + usb_packet_copy(p, buf->data + (buf->prod % buf->size), USBAUDIO_PACKET_SIZE); buf->prod += USBAUDIO_PACKET_SIZE; return USBAUDIO_PACKET_SIZE; } -static uint8_t *streambuf_get(struct streambuf *buf) +static uint8_t *streambuf_get(struct streambuf *buf, size_t *len) { uint32_t used = buf->prod - buf->cons; uint8_t *data; if (!used) { + *len = 0; return NULL; } - assert(used >= USBAUDIO_PACKET_SIZE); data = buf->data + (buf->cons % buf->size); - buf->cons += USBAUDIO_PACKET_SIZE; + *len = MIN(buf->prod - buf->cons, + buf->size - (buf->cons % buf->size)); return data; } @@ -374,16 +375,21 @@ static void output_callback(void *opaque, int avail) USBAudioState *s = opaque; uint8_t *data; - for (;;) { - if (avail < USBAUDIO_PACKET_SIZE) { + while (avail) { + size_t written, len; + + data = streambuf_get(&s->out.buf, &len); + if (!data) { return; } - data = streambuf_get(&s->out.buf); - if (!data) { + + written = AUD_write(s->out.voice, data, len); + avail -= written; + s->out.buf.cons += written; + + if (written < len) { return; } - AUD_write(s->out.voice, data, USBAUDIO_PACKET_SIZE); - avail -= USBAUDIO_PACKET_SIZE; } } From patchwork Thu Sep 19 21:24:32 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?UTF-8?B?Wm9sdMOhbiBLxZF2w6Fnw7M=?= X-Patchwork-Id: 1164896 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="PCjiQb1U"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46Z9Lm31fbz9sNk for ; Fri, 20 Sep 2019 07:42:56 +1000 (AEST) Received: from localhost ([::1]:48724 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB4CT-0003J7-Sx for incoming@patchwork.ozlabs.org; Thu, 19 Sep 2019 17:42:53 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53700) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB3ux-0002vw-Jg for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:48 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iB3uv-0000lJ-P5 for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:47 -0400 Received: from mail-wm1-x344.google.com ([2a00:1450:4864:20::344]:36217) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iB3uv-0000kh-Du for qemu-devel@nongnu.org; Thu, 19 Sep 2019 17:24:45 -0400 Received: by mail-wm1-x344.google.com with SMTP id m18so7427wmc.1 for ; Thu, 19 Sep 2019 14:24:45 -0700 (PDT) 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=csUz3G+oANfAghQDvskgbpzawb3MHELRqPU8L59Mp1o=; b=PCjiQb1Ukd3EaTlXC0NfwALkyapPUWxqCykoI9T+O+T0MGz22uOm7vpL0ZI1pqqiDH axHC8vYf6uha4MN7o43xD4nFhnPwKgL9WxevSPWoyJ0infS0G9A9xnrVjiP8364qdySQ peO6z5jOtvW6OsPa7cjKsFtbVLuTmUwnQR6+y6GQInLF60ZJuZPk++nfXDbqnK23gXmT oqpPInHOA4x7cGep6v6gkDSDPx7y1nT0iERXM68xcc4guQLyO7FjRi1WonAB0vodmbRg haLj1Q3icGxYPMFzQYaoeGjmayqLHPhR5FawA6nrGxv1dn4uoefMFdI+i2pNheGFDh5P 5kjQ== 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=csUz3G+oANfAghQDvskgbpzawb3MHELRqPU8L59Mp1o=; b=b44cr14yB/vekLtqm38cV//Dd7lDu8ZLbacKxpg/FANJ1yVqG24gWg3FQwbpyUYjGd Cp4XOsWnHM5KVkC5UndeWD7YtB0Gy7W/ubkSaNmoJCHwU99VZUGPCLqaRamvE/OyeZbU K8t56Dfid+h26OtBxGDiHRy5wSJT7uRUkIXGvjJO5hYr/R0goaEtt9mlb22grdC/kh9r H9XVDJV9WUISgxjJR0kq2iVaelDN36sC8g77Lr+4WuJ55O6nN1YIPH3KUkqAVcPCeC3y rsdnO5M0NkREDTffyGQkPnBw59+5wNtmZcYDwTKwOGCdFmAYtI6edA3oiI7qo8uRw6oZ hztA== X-Gm-Message-State: APjAAAWUPtAoHmVGneila+1BY62IiJZLF7fUnhO/GRqqHyTbWJHZrYfk Kt1xpukhNtZrgoDeYAU7IGSvlkVp X-Google-Smtp-Source: APXvYqzJXk8w8sNEDuQEJ41udFDdphxK/RGU/Xg1Q3ficrd2a81f4dJxy+wWiSWyQGtYoHMz4N2jbQ== X-Received: by 2002:a05:600c:241:: with SMTP id 1mr74963wmj.162.1568928284238; Thu, 19 Sep 2019 14:24:44 -0700 (PDT) Received: from nullptr.home.dirty-ice.org (2a01-036c-0113-74ef-0000-0000-0000-0005.pool6.digikabel.hu. [2a01:36c:113:74ef::5]) by smtp.gmail.com with ESMTPSA id w125sm13191292wmg.32.2019.09.19.14.24.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Sep 2019 14:24:43 -0700 (PDT) From: "=?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?=" X-Google-Original-From: =?utf-8?b?S8WRdsOhZ8OzLCBab2x0w6Fu?= To: qemu-devel@nongnu.org Subject: [PATCH v4 24/24] usbaudio: change playback counters to 64 bit Date: Thu, 19 Sep 2019 23:24:32 +0200 Message-Id: <71151db7022c023bdb16b88659cff0a25fa6235e.1568927990.git.DirtY.iCE.hu@gmail.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: References: MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::344 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Gerd Hoffmann Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" With stereo playback, they need about 375 minutes of continuous audio playback to overflow, which is usually not a problem (as stopping and later resuming playback resets the counters). But with 7.1 audio, they only need about 95 minutes to overflow. After the overflow, the buf->prod % USBAUDIO_PACKET_SIZE(channels) assertion no longer holds true, which will result in overflowing the buffer. With 64 bit variables, it would take about 762000 years to overflow. Signed-off-by: Kővágó, Zoltán --- hw/usb/dev-audio.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/hw/usb/dev-audio.c b/hw/usb/dev-audio.c index e42bdfbdc1..ea604bbb8e 100644 --- a/hw/usb/dev-audio.c +++ b/hw/usb/dev-audio.c @@ -578,9 +578,9 @@ static const USBDesc desc_audio_multi = { struct streambuf { uint8_t *data; - uint32_t size; - uint32_t prod; - uint32_t cons; + size_t size; + uint64_t prod; + uint64_t cons; }; static void streambuf_init(struct streambuf *buf, uint32_t size, @@ -601,7 +601,7 @@ static void streambuf_fini(struct streambuf *buf) static int streambuf_put(struct streambuf *buf, USBPacket *p, uint32_t channels) { - uint32_t free = buf->size - (buf->prod - buf->cons); + int64_t free = buf->size - (buf->prod - buf->cons); if (free < USBAUDIO_PACKET_SIZE(channels)) { return 0; @@ -610,6 +610,8 @@ static int streambuf_put(struct streambuf *buf, USBPacket *p, uint32_t channels) return 0; } + /* can happen if prod overflows */ + assert(buf->prod % USBAUDIO_PACKET_SIZE(channels) == 0); usb_packet_copy(p, buf->data + (buf->prod % buf->size), USBAUDIO_PACKET_SIZE(channels)); buf->prod += USBAUDIO_PACKET_SIZE(channels); @@ -618,10 +620,10 @@ static int streambuf_put(struct streambuf *buf, USBPacket *p, uint32_t channels) static uint8_t *streambuf_get(struct streambuf *buf, size_t *len) { - uint32_t used = buf->prod - buf->cons; + int64_t used = buf->prod - buf->cons; uint8_t *data; - if (!used) { + if (used <= 0) { *len = 0; return NULL; }