9front - general discussion about 9front
 help / color / mirror / Atom feed
From: Michael Forney <mforney@mforney.org>
To: 9front@9front.org
Subject: [9front] Re: games/snes audio patches
Date: Sun, 21 Feb 2021 03:06:32 -0800	[thread overview]
Message-ID: <3TYJK0YCE3OF6.2G7TZ7NP81HEX@mforney.org> (raw)
In-Reply-To: <71E80890743ACBD0D641DECE5D327028@arrow.hsd1.ca.comcast.net>

[-- Attachment #1: Type: text/plain, Size: 1748 bytes --]

Thanks everyone for the suggestions about resample techniques (and
qwx for applying the other patches).

I'm quite familiar with the jos resample algorithm used by pcmconv,
I implemented it just a couple months ago for another project[0].
While the filter in pcmconv has a lot of coefficients, this is
because it is a polyphase filter with 256 phases. Only 12 taps are
used for each output sample, so it performs quite well. For anyone
interested in the topic, I highly recommend reading through that
document[1].

To compare the different approaches for resampling, I made a test
file sweeping from 1 to 16 kHz with sox (similar to [2]):
sox -n -t raw -e signed -b 16 -r 32000 sweep.pcm synth -n 5 sine 1+16000 gain -6

Here are the results: https://mforney.org/misc/snes-resample/

As is suggested by the spectrograms, aliasing is still audible in
the higher frequencies in linear and hermite, but it is worse in
linear. Nearest-neighbor is *really* bad (in fact, it's not even
nearest neighbor, but next neighbor), so anything else is a huge
improvement.

I do think we should try to reuse the pcmconv code since it's already
there and works well, but this is not something I plan on working
on in the near future. For now, I think we should just change it
to hermite or linear, since they can be implemented in just a few
lines of code, and I'm not sure I could tell the difference between
them and pcmconv for actual game audio.

I attached a patch for hermite interpolation if that is preferred
over linear. I'd be happy with either of them for now.

[0] https://git.sr.ht/~mcf/resample/tree/master/item/resample.c
[1] https://ccrma.stanford.edu/~jos/resample/resample.pdf
[2] https://src.infinitewave.ca/

[-- Attachment #2.1: Type: text/plain, Size: 418 bytes --]

from postmaster@1ess:
The following attachment had content that we can't
prove to be harmless.  To avoid possible automatic
execution, we changed the content headers.
The original header was:

	Content-Disposition: attachment;
 filename*0*=UTF-8''0001-games-snes-use-4-point-hermite-interpolation-to-;
 filename*1*=resample.patch
	Content-Type: text/x-diff;charset=us-ascii
	Content-Transfer-Encoding: quoted-printable

[-- Attachment #2.2: file.suspect --]
[-- Type: application/octet-stream, Size: 1346 bytes --]

From dd8e5ff3ae64aa752f21b3fd1309c19bb753cd5b
From: Michael Forney <mforney@mforney.org>
Date: Sun, 21 Feb 2021 10:44:34 +0000
Subject: games/snes: use 4-point hermite interpolation to resample


This is noticeably better than nearest-neighbor.

diff 3937a76b73e983907018cce7e9de9439f3287d21 dd8e5ff3ae64aa752f21b3fd1309c19bb753cd5b
--- a/sys/src/games/snes/dsp.c	Sun Feb 21 01:44:39 2021
+++ b/sys/src/games/snes/dsp.c	Sun Feb 21 02:44:34 2021
@@ -49,7 +49,6 @@
 
 enum { Freq = 44100 };
 static s16int sbuf[2*2000], *sbufp;
-static int stime;
 static int fd;
 
 void
@@ -61,16 +60,36 @@
 	sbufp = sbuf;
 }
 
+static int
+hermite(int *x, int t)
+{
+	int y;
+
+	y = (x[0] - x[6]) / 2 + (x[4] - x[2]) * 3 / 2;
+	y = y * t >> 15;
+	y += x[6] - x[4] * 5 / 2 + x[2] * 2 - x[0] / 2;
+	y = y * t >> 15;
+	y += (x[2] - x[6]) / 2;
+	y = y * t >> 15;
+	y += x[4];
+	return y;
+}
+
 static void
 audiosample(s16int *s)
 {
-	stime -= 1<<16;
+	static int x[8], t;
+
+	x[0] = s[0];
+	x[1] = s[1];
 	do {
-		sbufp[0] = s[0];
-		sbufp[1] = s[1];
+		sbufp[0] = hermite(x, t);
+		sbufp[1] = hermite(x + 1, t);
 		sbufp += 2;
-		stime += (32000<<16)/Freq;
-	} while(stime < 0);
+		t += (32000<<15)/Freq;
+	} while(t < 1<<15);
+	t -= 1<<15;
+	memmove(x + 2, x, sizeof(x) - 2 * sizeof(x[0]));
 }
 
 int


  parent reply	other threads:[~2021-02-21 12:19 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-02-15 10:25 [9front] " Michael Forney
2021-02-15 10:55 ` Steve Simon
2021-02-17  0:05 ` qwx
2021-02-17  5:31   ` Amavect
2021-02-17  9:10     ` hiro
2021-02-17  9:32       ` Steve Simon
2021-02-17  9:57         ` hiro
2021-02-17 10:24           ` qwx
2021-02-17 10:53     ` hiro
2021-02-21 11:06 ` Michael Forney [this message]
2021-02-22  0:32   ` [9front] " qwx
2021-02-22 15:15   ` qwx

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3TYJK0YCE3OF6.2G7TZ7NP81HEX@mforney.org \
    --to=mforney@mforney.org \
    --cc=9front@9front.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).