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
next prev 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).