From nobody Wed Nov 12 08:37:45 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1568929670; cv=none; d=zoho.com; s=zohoarc; b=PWYjeLqJcvoZQmUYeDXm6Ss1lrjLM5Cnc+PTK7833zysnsbik/ePRe5OA5FsB6rzXhZRj3wMHSVGStIC3Uyd/LPVLNiP88LkPWbKFBeHX56LNsSEM7AQGu3VEGULAhRlGfzORrZ/I9GEIkkhXeS9RlzXe5hJe/aaNaCIR8mnLEM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1568929670; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=y4hrO1Uu0paB0JQc174Zf7748JlB8HDxf5+LZFaxdz0=; b=fk9QOnT0HAHwimPnLqqIxU3FWMBcYd5M+/ZrXTQrwcZxZ2fdFf3IE2UqKUjvKjcJUoAZC9iQvKiGt+PhcliwDC/vsj4KRcsrwsaceVohotBCMzP8+INoarHjgEWuE0Sq6raiJJyip+4NiCiUWeUIq6/JcdWyZLCNfYBgIiFLOG4= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1568929670705375.39734952770823; Thu, 19 Sep 2019 14:47:50 -0700 (PDT) Received: from localhost ([::1]:48778 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iB4HE-0008VD-JB for importer@patchew.org; Thu, 19 Sep 2019 17:47:48 -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) 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) 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) From: "=?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?=" X-Google-Original-From: =?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?= To: qemu-devel@nongnu.org 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 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::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+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: pass (identity @gmail.com) 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=C5=91v=C3=A1g=C3=B3, Zolt=C3=A1n --- 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 =3D 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 =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + ticks =3D now - rate->start_ticks; + bytes =3D muldiv64(ticks, info->bytes_per_second, NANOSECONDS_PER_SECO= ND); + samples =3D (bytes - rate->bytes_sent) >> info->shift; + if (samples < 0 || samples > 65536) { + AUD_log(NULL, "Resetting rate control (%" PRId64 " samples)\n", sa= mples); + audio_rate_start(rate); + samples =3D 0; + } + + ret =3D MIN(samples << info->shift, bytes_avail); + rate->bytes_sent +=3D 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, s= ize_t size); =20 void audio_run(AudioState *s, const char *msg); =20 +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 @@ =20 typedef struct NoVoiceOut { HWVoiceOut hw; - int64_t old_ticks; + RateCtl rate; } NoVoiceOut; =20 typedef struct NoVoiceIn { HWVoiceIn hw; - int64_t old_ticks; + RateCtl rate; } NoVoiceIn; =20 static size_t no_write(HWVoiceOut *hw, void *buf, size_t len) { NoVoiceOut *no =3D (NoVoiceOut *) hw; - int64_t now; - int64_t ticks; - int64_t bytes; - - now =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - ticks =3D now - no->old_ticks; - bytes =3D muldiv64(ticks, hw->info.bytes_per_second, NANOSECONDS_PER_S= ECOND); - - no->old_ticks =3D now; - return MIN(len, bytes); + return audio_rate_get_bytes(&hw->info, &no->rate, len); } =20 static int no_init_out(HWVoiceOut *hw, struct audsettings *as, void *drv_o= paque) { + NoVoiceOut *no =3D (NoVoiceOut *) hw; + audio_pcm_init_info (&hw->info, as); hw->samples =3D 1024; + audio_rate_start(&no->rate); return 0; } =20 @@ -70,15 +64,21 @@ static void no_fini_out (HWVoiceOut *hw) =20 static int no_ctl_out (HWVoiceOut *hw, int cmd, ...) { - (void) hw; - (void) cmd; + NoVoiceOut *no =3D (NoVoiceOut *) hw; + + if (cmd =3D=3D VOICE_ENABLE) { + audio_rate_start(&no->rate); + } return 0; } =20 static int no_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opa= que) { + NoVoiceIn *no =3D (NoVoiceIn *) hw; + audio_pcm_init_info (&hw->info, as); hw->samples =3D 1024; + audio_rate_start(&no->rate); return 0; } =20 @@ -89,25 +89,20 @@ static void no_fini_in (HWVoiceIn *hw) =20 static size_t no_read(HWVoiceIn *hw, void *buf, size_t size) { - size_t to_clear; NoVoiceIn *no =3D (NoVoiceIn *) hw; + int64_t bytes =3D audio_rate_get_bytes(&hw->info, &no->rate, size); =20 - int64_t now =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - int64_t ticks =3D now - no->old_ticks; - int64_t bytes =3D - muldiv64(ticks, hw->info.bytes_per_second, NANOSECONDS_PER_SECOND); - - no->old_ticks =3D now; - to_clear =3D 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; } =20 static int no_ctl_in (HWVoiceIn *hw, int cmd, ...) { - (void) hw; - (void) cmd; + NoVoiceIn *no =3D (NoVoiceIn *) hw; + + if (cmd =3D=3D VOICE_ENABLE) { + audio_rate_start(&no->rate); + } return 0; } =20 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 =20 -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; =20 @@ -89,32 +84,6 @@ static void spice_audio_fini (void *opaque) /* nothing */ } =20 -static void rate_start (SpiceRateCtl *rate) -{ - memset (rate, 0, sizeof (*rate)); - rate->start_ticks =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); -} - -static int rate_get_samples (struct audio_pcm_info *info, SpiceRateCtl *ra= te) -{ - int64_t now; - int64_t ticks; - int64_t bytes; - int64_t samples; - - now =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - ticks =3D now - rate->start_ticks; - bytes =3D muldiv64(ticks, info->bytes_per_second, NANOSECONDS_PER_SECO= ND); - samples =3D (bytes - rate->bytes_sent) >> info->shift; - if (samples < 0 || samples > 65536) { - error_report("Resetting rate control (%" PRId64 " samples)", sampl= es); - rate_start(rate); - samples =3D 0; - } - rate->bytes_sent +=3D samples << info->shift; - return samples; -} - /* playback */ =20 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 =3D container_of(hw, SpiceVoiceOut, hw); - size_t decr; =20 if (!out->frame) { spice_server_playback_get_buffer(&out->sin, &out->frame, &out->fsi= ze); @@ -162,12 +130,10 @@ static void *line_out_get_buffer(HWVoiceOut *hw, size= _t *size) } =20 if (out->frame) { - decr =3D rate_get_samples(&hw->info, &out->rate); - decr =3D MIN(out->fsize - out->fpos, decr); - - *size =3D decr << hw->info.shift; + *size =3D audio_rate_get_bytes( + &hw->info, &out->rate, (out->fsize - out->fpos) << hw->info.sh= ift); } 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 =3D 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 =3D container_of (hw, SpiceVoiceIn, hw); - uint64_t delta_samp =3D rate_get_samples(&hw->info, &in->rate); - uint64_t to_read =3D MIN(len >> 2, delta_samp); + uint64_t to_read =3D audio_rate_get_bytes(&hw->info, &in->rate, len) >= > 2; size_t ready =3D spice_server_record_get_samples(&in->sin, buf, to_rea= d); =20 /* XXX: do we need this? */ @@ -296,7 +261,7 @@ static int line_in_ctl (HWVoiceIn *hw, int cmd, ...) break; } in->active =3D 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; =20 static size_t wav_write_out(HWVoiceOut *hw, void *buf, size_t len) { WAVVoiceOut *wav =3D (WAVVoiceOut *) hw; - int64_t now =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - int64_t ticks =3D now - wav->old_ticks; - int64_t bytes =3D - muldiv64(ticks, hw->info.bytes_per_second, NANOSECONDS_PER_SECOND); - - bytes =3D MIN(bytes, len); - bytes =3D bytes >> hw->info.shift << hw->info.shift; - wav->old_ticks =3D now; + int64_t bytes =3D audio_rate_get_bytes(&hw->info, &wav->rate, len); + assert(bytes >> hw->info.shift << hw->info.shift =3D=3D bytes); =20 if (bytes && fwrite(buf, bytes, 1, wav->f) !=3D 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 audsetti= ngs *as, strerror(errno)); return -1; } + + audio_rate_start(&wav->rate); return 0; } =20 @@ -179,8 +175,11 @@ static void wav_fini_out (HWVoiceOut *hw) =20 static int wav_ctl_out (HWVoiceOut *hw, int cmd, ...) { - (void) hw; - (void) cmd; + WAVVoiceOut *wav =3D (WAVVoiceOut *) hw; + + if (cmd =3D=3D VOICE_ENABLE) { + audio_rate_start(&wav->rate); + } return 0; } =20 --=20 2.23.0