9front - general discussion about 9front
 help / color / mirror / Atom feed
* [9front] games/snes audio patches
@ 2021-02-15 10:25 Michael Forney
  2021-02-15 10:55 ` Steve Simon
                   ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: Michael Forney @ 2021-02-15 10:25 UTC (permalink / raw)
  To: 9front

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

I noticed that the audio of games/snes was pretty bad for most games I
tried, so I did some bug hunting and found a few. Patches are attached.

The main issue (patch 1) was incorrect BRR decoding for filter types 2
and 3, which is the sample compression scheme that the SNES audio chip
uses.

I also saw that the noise and echo features of the DSP were
essentially just stubs. Patches 2 and 3 implement noise and echo
respectively.

Finally, I saw that it was using nearest-neighbor upsampling from 32
kHz to 44.1 kHz, which results in noticable aliasing. My first
thought was to pipe the output through audio/pcmconv which has a
high-quality resampler. However, games/snes uses audio write blocking
to control the emulation speed, so using a pipe here was problematic.
It would fill up the pipe buffer, then hang while pcmconv wrote the
upsampled data to /dev/audio, then repeat. Anyone have ideas about a
good way to reuse the pcmconv resampler for this (maybe split off into
a library)? For now, patch 4 changes it to use linear interpolation,
which is a big improvement and may be good enough.

Patch 5 is just a style patch to use the enums already defined instead
of hex constants in a couple places.

Here are some samples demonstrating the specific problems:
- BRR decoding
  https://mforney.org/misc/ct-122a-old.flac
  https://mforney.org/misc/ct-122a-new.flac
- Echo
  https://mforney.org/misc/ct-206-old.flac
  https://mforney.org/misc/ct-206-new.flac
- Noise (supposed to be wave noises)
  https://mforney.org/misc/ct-s02-old.flac
  https://mforney.org/misc/ct-s02-new.flac

[-- Attachment #2: 0001-games-snes-fix-BRR-decoding-with-filters-2-and-3.patch --]
[-- Type: text/plain, Size: 746 bytes --]

 From f3f21968489011d0fee39a054c63c70f1a18bb92
From: Michael Forney <mforney@mforney.org>
Date: Mon, 15 Feb 2021 09:28:12 +0000
Subject: games/snes: fix BRR decoding with filters 2 and 3


s1 and s2 should store the last and next to last output, but were set
in the wrong order, causing them both to be the last output. This
breaks filters 2 and 3, which both utilize s2.

diff a78495b8877d2a9e805d098b7963d3a3cf90c7c3 f3f21968489011d0fee39a054c63c70f1a18bb92
--- a/sys/src/games/snes/dsp.c	Wed Feb 10 01:00:05 2021
+++ b/sys/src/games/snes/dsp.c	Mon Feb 15 01:28:12 2021
@@ -275,8 +275,8 @@
 		d = (s16int)(clamp16(d) << 1);
 		p->buf[p->bp] = d;
 		p->buf[p->bp++ + 12] = d;
-		s1 = d;
 		s2 = s1;
+		s1 = d;
 		brr <<= 4;
 	}
 	if(p->bp == 12)

[-- Attachment #3: 0002-games-snes-implement-DSP-noise.patch --]
[-- Type: text/plain, Size: 933 bytes --]

 From c9d42c085558d9ac0272cd3df4e1868a2c410e46
From: Michael Forney <mforney@mforney.org>
Date: Mon, 15 Feb 2021 09:30:29 +0000
Subject: games/snes: implement DSP noise


I'm not sure if this LFSR is the same one used by the hardware or is
arbitrary, but it matches the noise sequence used by all other snes
emulators I looked at.

diff f3f21968489011d0fee39a054c63c70f1a18bb92 c9d42c085558d9ac0272cd3df4e1868a2c410e46
--- a/sys/src/games/snes/dsp.c	Mon Feb 15 01:28:12 2021
+++ b/sys/src/games/snes/dsp.c	Mon Feb 15 01:30:29 2021
@@ -6,7 +6,7 @@
 #include "fns.h"
 
 u8int dsp[256], dspstate;
-u16int dspcounter, noise;
+u16int dspcounter, noise = 0x8000;
 static s16int samp[2], echoin[2];
 
 enum {
@@ -517,6 +517,8 @@
 		}
 		if(dspcounter-- == 0)
 			dspcounter = 0x77ff;
+		if(envyes(dsp[FLG] & 0x1f))
+			noise = (noise << 13 ^ noise << 14) & 0x8000 | noise >> 1 & ~1;
 		break;
 	case 31: voice(0, 4); voice(2, 1); break;
 	}

[-- Attachment #4: 0003-games-snes-implement-DSP-echo.patch --]
[-- Type: text/plain, Size: 3281 bytes --]

 From b78eaf915465b6d6d13f2dc36964c9aad9a2b76c
From: Michael Forney <mforney@mforney.org>
Date: Mon, 15 Feb 2021 09:38:22 +0000
Subject: games/snes: implement DSP echo

diff c9d42c085558d9ac0272cd3df4e1868a2c410e46 b78eaf915465b6d6d13f2dc36964c9aad9a2b76c
--- a/sys/src/games/snes/dsp.c	Mon Feb 15 01:30:29 2021
+++ b/sys/src/games/snes/dsp.c	Mon Feb 15 01:38:22 2021
@@ -7,7 +7,9 @@
 
 u8int dsp[256], dspstate;
 u16int dspcounter, noise = 0x8000;
-static s16int samp[2], echoin[2];
+static s16int samp[2], echoin[2], echobuf[2*2*8];
+static u16int echoaddr;
+static int echobp, echopos;
 
 enum {
 	VOLL = 0,
@@ -24,15 +26,17 @@
 	EFB = 0x0d,
 	MVOLR = 0x1c,
 	EVOLL = 0x2c,
-	EVOLR = 0x2d,
 	PMON = 0x2d,
+	EVOLR = 0x3c,
 	NON = 0x3d,
 	EON = 0x4d,
 	KON = 0x4c,
 	KOFF = 0x5c,
 	DIR = 0x5d,
 	FLG = 0x6c,
+	ESA = 0x6d,
 	ENDX = 0x7c,
+	EDL = 0x7d,
 	NEWKON = 0x8e,
 	INT = 0x80,
 };
@@ -96,6 +100,13 @@
 	return v;
 }
 
+static void
+spcput16(u16int p, u16int v)
+{
+	spcmem[p++] = v;
+	spcmem[p] = v >> 8;
+}
+
 u8int
 dspread(u8int p)
 {
@@ -412,33 +423,57 @@
 echo(int s)
 {
 	static s16int echoout[2];
-	static u8int fir[8];
+	s16int *x;
+	s8int h;
 	int a, b;
 
+	x = echobuf + echobp;
 	switch(s){
 	case 22:
-		echoout[0] = 0;
-		fir[0] = dsp[0x0f];
+		echoaddr = (dsp[INT|ESA] << 8) + echopos;
+		x[0] = x[16] = spc16(echoaddr);
+		h = dsp[0x0f];
+		echoout[0] = x[2] * h >> 7;
+		echoout[1] = x[3] * h >> 7;
 		break;
 	case 23:
-		fir[1] = dsp[0x1f];
-		fir[2] = dsp[0x2f];
+		h = dsp[0x1f];
+		echoout[0] += x[4] * h >> 7;
+		echoout[1] += x[5] * h >> 7;
+		h = dsp[0x2f];
+		echoout[0] += x[6] * h >> 7;
+		echoout[1] += x[7] * h >> 7;
+		x[1] = x[17] = spc16(echoaddr + 2);
 		break;
 	case 24:
-		fir[3] = dsp[0x3f];
-		fir[4] = dsp[0x4f];
-		fir[5] = dsp[0x5f];
+		h = dsp[0x3f];
+		echoout[0] += x[8] * h >> 7;
+		echoout[1] += x[9] * h >> 7;
+		h = dsp[0x4f];
+		echoout[0] += x[10] * h >> 7;
+		echoout[1] += x[11] * h >> 7;
+		h = dsp[0x5f];
+		echoout[0] += x[12] * h >> 7;
+		echoout[1] += x[13] * h >> 7;
 		break;
 	case 25:
-		fir[6] = dsp[0x6f];
-		fir[7] = dsp[0x7f];
+		h = dsp[0x6f];
+		echoout[0] += x[14] * h >> 7;
+		echoout[1] += x[15] * h >> 7;
+		h = dsp[0x7f];
+		echoout[0] += x[16] * h >> 7;
+		echoout[1] += x[17] * h >> 7;
+		echoout[0] &= ~1;
+		echoout[1] &= ~1;
 		break;
 	case 26:
 		a = (samp[0] * (s8int)dsp[MVOLL]) >> 7;
 		b = (echoout[0] * (s8int)dsp[EVOLL]) >> 7;
 		samp[0] = clamp16(a + b);
-		echoin[0] = (echoin[0] * (s8int)dsp[EFB]) >> 7;
-		echoin[1] = (echoin[1] * (s8int)dsp[EFB]) >> 7;
+		a = echoout[0] * (s8int)dsp[EFB] >> 7;
+		echoin[0] = clamp16(echoin[0] + a) & ~1;
+		a = echoout[1] * (s8int)dsp[EFB] >> 7;
+		echoin[1] = clamp16(echoin[1] + a) & ~1;
 		break;
 	case 27:
 		a = (samp[1] * (s8int)dsp[MVOLR]) >> 7;
@@ -449,9 +484,22 @@
 		dsp[INT|FLG] = dsp[FLG];
 		break;
 	case 29:
+		dsp[INT|ESA] = dsp[ESA];
+		if(echopos == 0)
+			dsp[INT|EDL] = dsp[EDL] & 0xf;
+		echopos += 4;
+		if(echopos >= dsp[INT|EDL] << 11)
+			echopos = 0;
+		if((dsp[INT|FLG] & 0x20) == 0)
+			spcput16(echoaddr, echoin[0]);
+		echoin[0] = 0;
 		dsp[INT|FLG] = dsp[FLG];
 		break;
 	case 30:
+		if((dsp[INT|FLG] & 0x20) == 0)
+			spcput16(echoaddr + 2, echoin[1]);
+		echoin[1] = 0;
+		echobp = echobp + 2 & 15;
 		break;
 	}
 }

[-- Attachment #5: 0004-games-snes-use-linear-interpolation-to-resample.patch --]
[-- Type: text/plain, Size: 821 bytes --]

 From 909e181a497074c52e0be927c007cb6b6d66fc8c
From: Michael Forney <mforney@mforney.org>
Date: Mon, 15 Feb 2021 09:40:11 +0000
Subject: games/snes: use linear interpolation to resample


This is still not ideal, but noticably better than nearest-neighbor.

diff b78eaf915465b6d6d13f2dc36964c9aad9a2b76c 909e181a497074c52e0be927c007cb6b6d66fc8c
--- a/sys/src/games/snes/dsp.c	Mon Feb 15 01:38:22 2021
+++ b/sys/src/games/snes/dsp.c	Mon Feb 15 01:40:11 2021
@@ -64,13 +64,17 @@
 static void
 audiosample(s16int *s)
 {
+	static s16int s1[2];
+
 	stime -= 1<<16;
 	do {
-		sbufp[0] = s[0];
-		sbufp[1] = s[1];
+		sbufp[0] = s[0] + ((s[0] - s1[0]) * stime >> 16);
+		sbufp[1] = s[1] + ((s[1] - s1[1]) * stime >> 16);
 		sbufp += 2;
 		stime += (32000<<16)/Freq;
 	} while(stime < 0);
+	s1[0] = s[0];
+	s1[1] = s[1];
 }
 
 int

[-- Attachment #6: 0005-games-snes-use-enum-constants-KON-and-ENDX-instead-of-their-values.patch --]
[-- Type: text/plain, Size: 571 bytes --]

 From 903b37d82b46bee9050d911e81235c4d4d25e4e2
From: Michael Forney <mforney@mforney.org>
Date: Mon, 15 Feb 2021 09:42:11 +0000
Subject: games/snes: use enum constants KON and ENDX instead of their values

diff 909e181a497074c52e0be927c007cb6b6d66fc8c 903b37d82b46bee9050d911e81235c4d4d25e4e2
--- a/sys/src/games/snes/dsp.c	Mon Feb 15 01:40:11 2021
+++ b/sys/src/games/snes/dsp.c	Mon Feb 15 01:42:11 2021
@@ -124,10 +124,10 @@
 	if(p >= 0x80)
 		return;
 	switch(p){
-	case 0x4c:
+	case KON:
 		dsp[NEWKON] = v;
 		break;
-	case 0x7c:
+	case ENDX:
 		v = 0;
 		break;
 	}

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [9front] games/snes audio patches
  2021-02-15 10:25 [9front] games/snes audio patches Michael Forney
@ 2021-02-15 10:55 ` Steve Simon
  2021-02-17  0:05 ` qwx
  2021-02-21 11:06 ` [9front] " Michael Forney
  2 siblings, 0 replies; 12+ messages in thread
From: Steve Simon @ 2021-02-15 10:55 UTC (permalink / raw)
  To: 9front

Re: cheap audio upsampling

nearest neighbour is a crude upconverter, linear is much better,
a halfband filter with a few taps (maybe 8) should be good enough IMHO,
though I am not a game player so you may disagree. You can improve the
resolts of a short halfband filter by feeding it your linerly interpolated
stream.

Don't be tempted to filter only the missing samples as you are likely
to have gain or/and phase ripples due to the rounding errors of your
coeficents. itsbetter to filter everything equally well/badly.

-Steve

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [9front] games/snes audio patches
  2021-02-15 10:25 [9front] games/snes audio patches Michael Forney
  2021-02-15 10:55 ` Steve Simon
@ 2021-02-17  0:05 ` qwx
  2021-02-17  5:31   ` Amavect
  2021-02-21 11:06 ` [9front] " Michael Forney
  2 siblings, 1 reply; 12+ messages in thread
From: qwx @ 2021-02-17  0:05 UTC (permalink / raw)
  To: 9front

Hi,

> I noticed that the audio of games/snes was pretty bad for most games I
> tried, so I did some bug hunting and found a few. Patches are attached.

These look good to me, the results are great, good job!  I'm in favor
of pushing patches 1-3 and 5.


> Finally, I saw that it was using nearest-neighbor upsampling from 32
> kHz to 44.1 kHz, which results in noticable aliasing. My first
> thought was to pipe the output through audio/pcmconv which has a
> high-quality resampler. However, games/snes uses audio write blocking
> to control the emulation speed, so using a pipe here was problematic.
> It would fill up the pipe buffer, then hang while pcmconv wrote the
> upsampled data to /dev/audio, then repeat. Anyone have ideas about a
> good way to reuse the pcmconv resampler for this (maybe split off into
> a library)? For now, patch 4 changes it to use linear interpolation,
> which is a big improvement and may be good enough.

From: "Steve Simon" <steve@quintile.net>
Date: Mon, 15 Feb 2021 10:55:09 +0000
To: 9front@9front.org
Subject: Re: [9front] games/snes audio patches
> nearest neighbour is a crude upconverter, linear is much better,
> a halfband filter with a few taps (maybe 8) should be good enough IMHO,
> though I am not a game player so you may disagree. You can improve the
> resolts of a short halfband filter by feeding it your linerly interpolated
> stream.
> 
> Don't be tempted to filter only the missing samples as you are likely
> to have gain or/and phase ripples due to the rounding errors of your
> coeficents. itsbetter to filter everything equally well/badly.
> 
> -Steve

As Steve points out, there may be additional adjustments to improve
upsampling.  I don't know much about dsp, but we could either try some
more stuff, or if you think you're not up to it for now, push your patch
which already improves it, and add more further on.  Steve's suggestions
seems relatively simple to try out.  Using pcmconv is a nice idea, but I
think it's overkill.  Either waiting for pcmconv to write to /dev/audio,
or feeding back its input to games/snes, or completely decoupling audio
from timing seem more complex to do correctly than just try to add some
simple processing.  Perhaps if more improvements will blow up the code
size, your linear interpolation might be just fine.

The other patches should be imported imo.

Thanks for your great work!

qwx

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [9front] games/snes audio patches
  2021-02-17  0:05 ` qwx
@ 2021-02-17  5:31   ` Amavect
  2021-02-17  9:10     ` hiro
  2021-02-17 10:53     ` hiro
  0 siblings, 2 replies; 12+ messages in thread
From: Amavect @ 2021-02-17  5:31 UTC (permalink / raw)
  To: 9front

All,

Here's something I dug up.
http://yehar.com/blog/?p=197
It has sample code for a ton of filters.
A great deal of analysis is on 2^n-oversampled audio, which we aren't doing. There's a specific recommendation for 4-point Hermite interpolation in this case if you want high quality and speed.

Section 7.
"Also, it shall only be commented that using polynomial interpolators with unoversampled input is a choice that can only be made when the quality is not that important but speed is essential, the most useful interpolators in that case being linear and 4-point Hermite, and Watte tri-linear, which is somewhere between those two in both quality and computational complexity."

Thanks,
Amavect

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [9front] games/snes audio patches
  2021-02-17  5:31   ` Amavect
@ 2021-02-17  9:10     ` hiro
  2021-02-17  9:32       ` Steve Simon
  2021-02-17 10:53     ` hiro
  1 sibling, 1 reply; 12+ messages in thread
From: hiro @ 2021-02-17  9:10 UTC (permalink / raw)
  To: 9front

computational complexity doesn't matter any more for something
low-bitrate like audio.

i don't see why the resampler in pcmconv that's already there
shouldn't be reused. it seems you have a good enough excuse to make it
a library

On 2/17/21, Amavect <amavect@gmail.com> wrote:
> All,
>
> Here's something I dug up.
> http://yehar.com/blog/?p=197
> It has sample code for a ton of filters.
> A great deal of analysis is on 2^n-oversampled audio, which we aren't doing.
> There's a specific recommendation for 4-point Hermite interpolation in this
> case if you want high quality and speed.
>
> Section 7.
> "Also, it shall only be commented that using polynomial interpolators with
> unoversampled input is a choice that can only be made when the quality is
> not that important but speed is essential, the most useful interpolators in
> that case being linear and 4-point Hermite, and Watte tri-linear, which is
> somewhere between those two in both quality and computational complexity."
>
> Thanks,
> Amavect
>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [9front] games/snes audio patches
  2021-02-17  9:10     ` hiro
@ 2021-02-17  9:32       ` Steve Simon
  2021-02-17  9:57         ` hiro
  0 siblings, 1 reply; 12+ messages in thread
From: Steve Simon @ 2021-02-17  9:32 UTC (permalink / raw)
  To: 9front


Hi,

interesting paper.

i admit i haven't followed up the reference for pcmconf but the FIR is big enough to make me think it should be avoided if you don’t need it.

honestly, the only way you are going to know if pcmconf is too slow, or if the aliasing artefacts of hermite are unacceptable is to try them. hermite looks very lightweight and a good design, whether is is good enough i cannot tell.

if you experiment make sure you try with headphones - these can make minor artefacts more tiring.

-Steve


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [9front] games/snes audio patches
  2021-02-17  9:32       ` Steve Simon
@ 2021-02-17  9:57         ` hiro
  2021-02-17 10:24           ` qwx
  0 siblings, 1 reply; 12+ messages in thread
From: hiro @ 2021-02-17  9:57 UTC (permalink / raw)
  To: 9front

@steve i recommend you read this
https://ccrma.stanford.edu/~jos/resample/resample.pdf

On 2/17/21, Steve Simon <steve@quintile.net> wrote:
>
> Hi,
>
> interesting paper.
>
> i admit i haven't followed up the reference for pcmconf but the FIR is big
> enough to make me think it should be avoided if you don’t need it.
>
> honestly, the only way you are going to know if pcmconf is too slow, or if
> the aliasing artefacts of hermite are unacceptable is to try them. hermite
> looks very lightweight and a good design, whether is is good enough i cannot
> tell.
>
> if you experiment make sure you try with headphones - these can make minor
> artefacts more tiring.
>
> -Steve
>
>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [9front] games/snes audio patches
  2021-02-17  9:57         ` hiro
@ 2021-02-17 10:24           ` qwx
  0 siblings, 0 replies; 12+ messages in thread
From: qwx @ 2021-02-17 10:24 UTC (permalink / raw)
  To: 9front

Hello,

I pushed the other patches.  Interesting discussion on dsp, I'm learning
a lot :)

Thanks again Michael, great work!

qwx

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [9front] games/snes audio patches
  2021-02-17  5:31   ` Amavect
  2021-02-17  9:10     ` hiro
@ 2021-02-17 10:53     ` hiro
  1 sibling, 0 replies; 12+ messages in thread
From: hiro @ 2021-02-17 10:53 UTC (permalink / raw)
  To: 9front

> A great deal of analysis is on 2^n-oversampled audio, which we aren't doing.

pcmconv is also oversampling

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [9front] Re: games/snes audio patches
  2021-02-15 10:25 [9front] games/snes audio patches Michael Forney
  2021-02-15 10:55 ` Steve Simon
  2021-02-17  0:05 ` qwx
@ 2021-02-21 11:06 ` Michael Forney
  2021-02-22  0:32   ` qwx
  2021-02-22 15:15   ` qwx
  2 siblings, 2 replies; 12+ messages in thread
From: Michael Forney @ 2021-02-21 11:06 UTC (permalink / raw)
  To: 9front

[-- 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


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [9front] Re: games/snes audio patches
  2021-02-21 11:06 ` [9front] " Michael Forney
@ 2021-02-22  0:32   ` qwx
  2021-02-22 15:15   ` qwx
  1 sibling, 0 replies; 12+ messages in thread
From: qwx @ 2021-02-22  0:32 UTC (permalink / raw)
  To: 9front

Hi,

[...]
> 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.

Great work!  Looks good to me.

pcmconv might be best, but I agree it's fine to use a simpler fix for
now.  Since you already provide a patch for hermite, and it looks like
it yields good results, I'd merge that.

If there are no objections, I'll push that patch.

Thanks again!

qwx

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [9front] Re: games/snes audio patches
  2021-02-21 11:06 ` [9front] " Michael Forney
  2021-02-22  0:32   ` qwx
@ 2021-02-22 15:15   ` qwx
  1 sibling, 0 replies; 12+ messages in thread
From: qwx @ 2021-02-22 15:15 UTC (permalink / raw)
  To: 9front

Hermite interpolation patch applied.

Thanks again!!

qwx

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2021-02-22 19:46 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-02-15 10:25 [9front] games/snes audio patches 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 ` [9front] " Michael Forney
2021-02-22  0:32   ` qwx
2021-02-22 15:15   ` qwx

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