atrac3: apply the whole mdct window

Only the first and last 128 points of the 512 point window were
applied, and the 256 between were taken to be one. They are not:
the window rises to 1.207 there. Every block was therefore up to
1.6 dB low over half its length, which left the output 0.7 dB low
on average and an error about 23 dB below the signal at all
frequencies.

Add the missing half of the table and apply it.

Checked with perfsim (Sansa e200v1 build) against ffmpeg's decode,
with the two previous fixes applied before and after:

                               level     SNR
  five plain stereo RM files   -0.7 dB   23 dB  ->  0.0 dB   54-57 dB
  joint stereo RM file         -0.7 dB   23 dB  ->  0.0 dB   37-45 dB
  joint stereo OMA file        -0.7 dB   23 dB  ->  0.0 dB   45 dB

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Michael Giacomelli 2026-10-06 01:15:08 -04:00
parent 1bae7e0e0a
commit b7170e03c4
2 changed files with 35 additions and 1 deletions

View file

@ -252,11 +252,16 @@ atrac3_imdct_windowing(int32_t *buffer,
const int32_t *win) const int32_t *win)
{ {
int32_t i; int32_t i;
/* win[0..127] = win[511..384], win[128..383] = 1 */ /* win[0..127] = win[511..384] */
for(i = 0; i<128; i++) { for(i = 0; i<128; i++) {
buffer[ i] = fixmul31(win[i], buffer[ i]); buffer[ i] = fixmul31(win[i], buffer[ i]);
buffer[511-i] = fixmul31(win[i], buffer[511-i]); buffer[511-i] = fixmul31(win[i], buffer[511-i]);
} }
/* win[128..255] = win[383..256] = 1 + window_lookup_mid[] */
for(i = 0; i<128; i++) {
buffer[128+i] += fixmul31(window_lookup_mid[i], buffer[128+i]);
buffer[383-i] += fixmul31(window_lookup_mid[i], buffer[383-i]);
}
} }

View file

@ -76,6 +76,35 @@ static const int32_t window_lookup[128] ICONST_ATTR MEM_ALIGN_ATTR = {
-0x82660c01, -0x80ca4a01, -0x82660c01, -0x80ca4a01,
}; };
/* The window above is the first 128 points of the 512 point mdct window.
* Points 128..255 are these values plus one, scaled by 2^31; they rise to
* 1.207 and fall back to 1. The second half of the window mirrors the
* first. */
static const int32_t window_lookup_mid[128] ICONST_ATTR MEM_ALIGN_ATTR = {
0x00c7d1c8, 0x024fd962, 0x03cd6738, 0x05401bc8, 0x06a79e95, 0x08039e75,
0x0953d1d1, 0x0a97f6df, 0x0bcfd3c6, 0x0cfb36c3, 0x0e19f636, 0x0f2bf0a8,
0x10310cc9, 0x11293955, 0x12146d01, 0x12f2a64e, 0x13c3eb59, 0x148849a0,
0x153fd5c0, 0x15eaab2c, 0x1688ebd9, 0x171abfeb, 0x17a05559, 0x1819df8c,
0x188796ff, 0x18e9b8db, 0x1940868e, 0x198c456d, 0x19cd3e43, 0x1a03bcf6,
0x1a301021, 0x1a5288af, 0x1a6b7984, 0x1a7b371a, 0x1a821730, 0x1a807072,
0x1a769a2c, 0x1a64ebfc, 0x1a4bbd8d, 0x1a2b6653, 0x1a043d52, 0x19d698de,
0x19a2ce6d, 0x19693261, 0x192a17e5, 0x18e5d0be, 0x189cad2d, 0x184efbcf,
0x17fd0985, 0x17a72158, 0x174d8c6b, 0x16f091e8, 0x169076f2, 0x162d7ea1,
0x15c7e9f4, 0x155ff7cf, 0x14f5e4fc, 0x1489ec23, 0x141c45d4, 0x13ad2886,
0x133cc89d, 0x12cb5870, 0x12590851, 0x11e60697, 0x11727fa4, 0x10fe9df7,
0x108a8a2e, 0x10166b1a, 0x0fa265c6, 0x0f2e9d86, 0x0ebb3404, 0x0e48494e,
0x0dd5fbe2, 0x0d6468bc, 0x0cf3ab63, 0x0c83ddf9, 0x0c151945, 0x0ba774c2,
0x0b3b06af, 0x0acfe414, 0x0a6620d7, 0x09fdcfc5, 0x0997029e, 0x0931ca20,
0x08ce3615, 0x086c555d, 0x080c35f8, 0x07ade513, 0x07516f11, 0x06f6df92,
0x069e4182, 0x06479f20, 0x05f30203, 0x05a0732a, 0x054ffafe, 0x0501a15d,
0x04b56d9f, 0x046b66a1, 0x042392c9, 0x03ddf80e, 0x039a9bfc, 0x035983bd,
0x031ab41f, 0x02de3196, 0x02a40042, 0x026c23f9, 0x0236a043, 0x02037867,
0x01d2af6a, 0x01a44813, 0x017844f1, 0x014ea85c, 0x0127747d, 0x0102ab49,
0x00e04e8c, 0x00c05fe5, 0x00a2e0cf, 0x0087d29c, 0x006f367d, 0x00590d81,
0x00455897, 0x00341890, 0x00254e20, 0x0018f9df, 0x000f1c4a, 0x0007b5c4,
0x0002c697, 0x00004ef5,
};
/* Gain tables scaled by 2^16 */ /* Gain tables scaled by 2^16 */
static const int32_t gain_tab2[31] ICONST_ATTR = { static const int32_t gain_tab2[31] ICONST_ATTR = {
0x0003ab03, 0x00035d14, 0x0003159d, 0x0002d414, 0x000297fb, 0x000260e0, 0x0003ab03, 0x00035d14, 0x0003159d, 0x0002d414, 0x000297fb, 0x000260e0,