GARbro-mirror/ArcFormats/GameSystem/AudioADP4.cs

385 lines
28 KiB
C#

//! \file AudioADP4.cs
//! \date Fri Feb 24 14:14:17 2017
//! \brief 'Game System' compressed audio format.
//
// Copyright (C) 2017 by morkt
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
using System;
using System.ComponentModel.Composition;
using System.IO;
using GameRes.Utility;
namespace GameRes.Formats.GameSystem
{
[Export(typeof(AudioFormat))]
public class Adp4Audio : AudioFormat
{
public override string Tag { get { return "ADP4"; } }
public override string Description { get { return "'GameSystem' compressed audio"; } }
public override uint Signature { get { return 0; } }
public override bool CanWrite { get { return false; } }
public Adp4Audio ()
{
Extensions = new string[] { "adp4", "adps" };
}
const uint DefaultSampleRate = 44100; // XXX varies
public override SoundInput TryOpen (IBinaryStream file)
{
bool is_adp4 = file.Name.HasExtension (".adp4");
bool is_adps = !is_adp4 && file.Name.HasExtension (".adps");
if (!(is_adp4 || is_adps) || file.Length <= 4)
return null;
var decoder = new AdpDecoder (file);
var pcm = decoder.Decode (is_adps);
var format = new WaveFormat {
FormatTag = 1,
Channels = 2,
SamplesPerSecond = DefaultSampleRate,
BlockAlign = 4,
BitsPerSample = 16,
};
format.SetBPS();
var input = new MemoryStream (pcm);
var sound = new RawPcmInput (input, format);
file.Dispose();
return sound;
}
}
internal sealed class AdpDecoder
{
IBinaryStream m_input;
public AdpDecoder (IBinaryStream input)
{
m_input = input;
}
byte[] m_output;
public byte[] Decode (bool is_adps)
{
m_input.Position = 0;
int sample_count = m_input.ReadInt32();
if (is_adps)
{
m_input.Position = sample_count + 8;
sample_count = m_input.ReadInt32();
}
m_output = new byte[sample_count * 8];
if (is_adps)
DecodeAdps (sample_count);
else
DecodeBits (sample_count);
return m_output;
}
void DecodeAdps (int sample_count)
{
uint sample = 0;
uint left_sample = 0;
uint right_sample = 0;
int dst = 0;
while (sample_count > 0)
{
uint bits = m_input.ReadUInt16();
left_sample += bits & 0xF;
int s = AdpSamples[left_sample] + (short)sample;
sample = sample >> 16 | (uint)(Clamp (s) << 16);
left_sample = AdpAdjust[left_sample];
right_sample += (bits >> 8) & 0xF;
s = AdpSamples[right_sample] + (short)sample;
sample = sample >> 16 | (uint)(Clamp (s) << 16);
right_sample = AdpAdjust[right_sample];
LittleEndian.Pack (sample, m_output, dst);
dst += 4;
left_sample += (bits >> 4) & 0xF;
s = AdpSamples[left_sample] + (short)sample;
sample = sample >> 16 | (uint)(Clamp (s) << 16);
left_sample = AdpAdjust[left_sample];
right_sample += bits >> 12;
s = AdpSamples[right_sample] + (short)sample;
sample = sample >> 16 | (uint)(Clamp (s) << 16);
right_sample = AdpAdjust[right_sample];
LittleEndian.Pack (sample, m_output, dst);
dst += 4;
sample_count -= 2;
}
}
void DecodeBits (int sample_count)
{
bool copy_stereo = true;
uint last_sample = 0;
short sample = 0;
uint key = 0;
int dst = 0;
int bits = 0;
while (dst < m_output.Length)
{
if (bits < 0x100)
{
bits = m_input.ReadUInt8() | 0x8000;
}
int count = m_input.ReadUInt8();
if (count < 0x80)
count = m_input.ReadUInt8() | count << 8;
else
count &= 0x7F;
count++;
if (0 == (bits & 1))
{
do
{
if (dst >= m_output.Length)
return;
uint data_bits = m_input.ReadUInt8() ^ key++;
last_sample += data_bits & 0xF;
int s = AdpSamples[last_sample] + sample;
last_sample = AdpAdjust[last_sample];
sample = Clamp (s);
LittleEndian.Pack (sample, m_output, dst);
dst += 2;
if (copy_stereo)
LittleEndian.Pack (sample, m_output, dst);
dst += 2;
last_sample += (data_bits >> 4) & 0xF;
s = AdpSamples[last_sample] + sample;
last_sample = AdpAdjust[last_sample];
sample = Clamp (s);
LittleEndian.Pack (sample, m_output, dst);
dst += 2;
if (copy_stereo)
LittleEndian.Pack (sample, m_output, dst);
dst += 2;
}
while (--count > 0);
}
else
{
last_sample = 0;
sample = 0;
dst += count * 8;
}
bits >>= 1;
}
}
static short Clamp (int sample)
{
if (sample > 0x7FFF)
sample = 0x7FFF;
else if (sample < -32768)
sample = -32768;
return (short)sample;
}
static readonly int[] AdpSamples = {
0, 2, 4, 6, 7, 9, 11, 13, 0, -2, -4, -6, -7, -9, -11, -13,
1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, -11, -13, -15,
1, 3, 5, 7, 10, 12, 14, 16, -1, -3, -5, -7, -10, -12, -14, -16,
1, 3, 6, 8, 11, 13, 16, 18, -1, -3, -6, -8, -11, -13, -16, -18,
1, 4, 6, 9, 12, 15, 17, 20, -1, -4, -6, -9, -12, -15, -17, -20,
1, 4, 7, 10, 13, 16, 19, 22, -1, -4, -7, -10, -13, -16, -19, -22,
1, 4, 8, 11, 14, 17, 21, 24, -1, -4, -8, -11, -14, -17, -21, -24,
1, 5, 8, 12, 15, 19, 22, 26, -1, -5, -8, -12, -15, -19, -22, -26,
2, 6, 10, 14, 18, 22, 26, 30, -2, -6, -10, -14, -18, -22, -26, -30,
2, 6, 10, 14, 19, 23, 27, 31, -2, -6, -10, -14, -19, -23, -27, -31,
2, 7, 11, 16, 21, 26, 30, 35, -2, -7, -11, -16, -21, -26, -30, -35,
2, 7, 13, 18, 23, 28, 34, 39, -2, -7, -13, -18, -23, -28, -34, -39,
2, 8, 14, 20, 25, 31, 37, 43, -2, -8, -14, -20, -25, -31, -37, -43,
3, 9, 15, 21, 28, 34, 40, 46, -3, -9, -15, -21, -28, -34, -40, -46,
3, 10, 17, 24, 31, 38, 45, 52, -3, -10, -17, -24, -31, -38, -45, -52,
3, 11, 19, 27, 34, 42, 50, 58, -3, -11, -19, -27, -34, -42, -50, -58,
4, 12, 21, 29, 38, 46, 55, 63, -4, -12, -21, -29, -38, -46, -55, -63,
4, 13, 23, 32, 41, 50, 60, 69, -4, -13, -23, -32, -41, -50, -60, -69,
5, 15, 25, 35, 46, 56, 66, 76, -5, -15, -25, -35, -46, -56, -66, -76,
5, 16, 28, 39, 50, 61, 73, 84, -5, -16, -28, -39, -50, -61, -73, -84,
6, 18, 31, 43, 56, 68, 81, 93, -6, -18, -31, -43, -56, -68, -81, -93,
6, 20, 34, 48, 61, 75, 89, 103, -6, -20, -34, -48, -61, -75, -89, -103,
7, 22, 37, 52, 67, 82, 97, 112, -7, -22, -37, -52, -67, -82, -97, -112,
8, 24, 41, 57, 74, 90, 107, 123, -8, -24, -41, -57, -74, -90, -107, -123,
9, 27, 45, 63, 82, 100, 118, 136, -9, -27, -45, -63, -82, -100, -118, -136,
10, 30, 50, 70, 90, 110, 130, 150, -10, -30, -50, -70, -90, -110, -130, -150,
11, 33, 55, 77, 99, 121, 143, 165, -11, -33, -55, -77, -99, -121, -143, -165,
12, 36, 60, 84, 109, 133, 157, 181, -12, -36, -60, -84, -109, -133, -157, -181,
13, 40, 66, 93, 120, 147, 173, 200, -13, -40, -66, -93, -120, -147, -173, -200,
14, 44, 73, 103, 132, 162, 191, 221, -14, -44, -73, -103, -132, -162, -191, -221,
16, 48, 81, 113, 146, 178, 211, 243, -16, -48, -81, -113, -146, -178, -211, -243,
17, 53, 89, 125, 160, 196, 232, 268, -17, -53, -89, -125, -160, -196, -232, -268,
19, 58, 98, 137, 176, 215, 255, 294, -19, -58, -98, -137, -176, -215, -255, -294,
21, 64, 108, 151, 194, 237, 281, 324, -21, -64, -108, -151, -194, -237, -281, -324,
23, 71, 118, 166, 213, 261, 308, 356, -23, -71, -118, -166, -213, -261, -308, -356,
26, 78, 130, 182, 235, 287, 339, 391, -26, -78, -130, -182, -235, -287, -339, -391,
28, 86, 143, 201, 258, 316, 373, 431, -28, -86, -143, -201, -258, -316, -373, -431,
31, 94, 158, 221, 284, 347, 411, 474, -31, -94, -158, -221, -284, -347, -411, -474,
34, 104, 174, 244, 313, 383, 453, 523, -34, -104, -174, -244, -313, -383, -453, -523,
38, 115, 191, 268, 345, 422, 498, 575, -38, -115, -191, -268, -345, -422, -498, -575,
42, 126, 210, 294, 379, 463, 547, 631, -42, -126, -210, -294, -379, -463, -547, -631,
46, 139, 231, 324, 417, 510, 602, 695, -46, -139, -231, -324, -417, -510, -602, -695,
51, 153, 255, 357, 459, 561, 663, 765, -51, -153, -255, -357, -459, -561, -663, -765,
56, 168, 280, 392, 505, 617, 729, 841, -56, -168, -280, -392, -505, -617, -729, -841,
61, 185, 308, 432, 555, 679, 802, 926, -61, -185, -308, -432, -555, -679, -802, -926,
68, 204, 340, 476, 612, 748, 884, 1020, -68, -204, -340, -476, -612, -748, -884, -1020,
74, 224, 373, 523, 672, 822, 971, 1121, -74, -224, -373, -523, -672, -822, -971, -1121,
82, 246, 411, 575, 740, 904, 1069, 1233, -82, -246, -411, -575, -740, -904, -1069, -1233,
90, 271, 452, 633, 814, 995, 1176, 1357, -90, -271, -452, -633, -814, -995, -1176, -1357,
99, 298, 497, 696, 895, 1094, 1293, 1492, -99, -298, -497, -696, -895, -1094, -1293, -1492,
109, 328, 547, 766, 985, 1204, 1423, 1642, -109, -328, -547, -766, -985, -1204, -1423, -1642,
120, 361, 601, 842, 1083, 1324, 1564, 1805, -120, -361, -601, -842, -1083, -1324, -1564, -1805,
132, 397, 662, 927, 1192, 1457, 1722, 1987, -132, -397, -662, -927, -1192, -1457, -1722, -1987,
145, 437, 728, 1020, 1311, 1603, 1894, 2186, -145, -437, -728, -1020, -1311, -1603, -1894, -2186,
160, 480, 801, 1121, 1442, 1762, 2083, 2403, -160, -480, -801, -1121, -1442, -1762, -2083, -2403,
176, 529, 881, 1234, 1587, 1940, 2292, 2645, -176, -529, -881, -1234, -1587, -1940, -2292, -2645,
194, 582, 970, 1358, 1746, 2134, 2522, 2910, -194, -582, -970, -1358, -1746, -2134, -2522, -2910,
213, 640, 1066, 1493, 1920, 2347, 2773, 3200, -213, -640, -1066, -1493, -1920, -2347, -2773, -3200,
234, 704, 1173, 1643, 2112, 2582, 3051, 3521, -234, -704, -1173, -1643, -2112, -2582, -3051, -3521,
258, 774, 1291, 1807, 2324, 2840, 3357, 3873, -258, -774, -1291, -1807, -2324, -2840, -3357, -3873,
284, 852, 1420, 1988, 2556, 3124, 3692, 4260, -284, -852, -1420, -1988, -2556, -3124, -3692, -4260,
312, 937, 1561, 2186, 2811, 3436, 4060, 4685, -312, -937, -1561, -2186, -2811, -3436, -4060, -4685,
343, 1030, 1718, 2405, 3092, 3779, 4467, 5154, -343, -1030, -1718, -2405, -3092, -3779, -4467, -5154,
378, 1134, 1890, 2646, 3402, 4158, 4914, 5670, -378, -1134, -1890, -2646, -3402, -4158, -4914, -5670,
415, 1247, 2079, 2911, 3742, 4574, 5406, 6238, -415, -1247, -2079, -2911, -3742, -4574, -5406, -6238,
457, 1372, 2287, 3202, 4117, 5032, 5947, 6862, -457, -1372, -2287, -3202, -4117, -5032, -5947, -6862,
503, 1509, 2516, 3522, 4529, 5535, 6542, 7548, -503, -1509, -2516, -3522, -4529, -5535, -6542, -7548,
553, 1660, 2767, 3874, 4981, 6088, 7195, 8302, -553, -1660, -2767, -3874, -4981, -6088, -7195, -8302,
608, 1826, 3044, 4262, 5479, 6697, 7915, 9133, -608, -1826, -3044, -4262, -5479, -6697, -7915, -9133,
669, 2009, 3348, 4688, 6027, 7367, 8706, 10046, -669, -2009, -3348, -4688, -6027, -7367, -8706, -10046,
736, 2210, 3683, 5157, 6630, 8104, 9577, 11051, -736, -2210, -3683, -5157, -6630, -8104, -9577, -11051,
810, 2431, 4052, 5673, 7294, 8915, 10536, 12157, -810, -2431, -4052, -5673, -7294, -8915, -10536, -12157,
891, 2674, 4457, 6240, 8023, 9806, 11589, 13372, -891, -2674, -4457, -6240, -8023, -9806, -11589, -13372,
980, 2941, 4903, 6864, 8825, 10786, 12748, 14709, -980, -2941, -4903, -6864, -8825, -10786, -12748, -14709,
1078, 3236, 5393, 7551, 9708, 11866, 14023, 16181, -1078, -3236, -5393, -7551, -9708, -11866, -14023, -16181,
1186, 3559, 5933, 8306, 10679, 13052, 15426, 17799, -1186, -3559, -5933, -8306, -10679, -13052, -15426, -17799,
1305, 3915, 6526, 9136, 11747, 14357, 16968, 19578, -1305, -3915, -6526, -9136, -11747, -14357, -16968, -19578,
1435, 4307, 7179, 10051, 12922, 15794, 18666, 21538, -1435, -4307, -7179, -10051, -12922, -15794, -18666, -21538,
1579, 4738, 7896, 11055, 14214, 17373, 20531, 23690, -1579, -4738, -7896, -11055, -14214, -17373, -20531, -23690,
1737, 5212, 8686, 12161, 15636, 19111, 22585, 26060, -1737, -5212, -8686, -12161, -15636, -19111, -22585, -26060,
1911, 5733, 9555, 13377, 17200, 21022, 24844, 28666, -1911, -5733, -9555, -13377, -17200, -21022, -24844, -28666,
2102, 6306, 10511, 14715, 18920, 23124, 27329, 31533, -2102, -6306, -10511, -14715, -18920, -23124, -27329, -31533,
2312, 6937, 11562, 16187, 20812, 25437, 30062, 34687, -2312, -6937, -11562, -16187, -20812, -25437, -30062, -34687,
2543, 7631, 12718, 17806, 22893, 27981, 33068, 38156, -2543, -7631, -12718, -17806, -22893, -27981, -33068, -38156,
2798, 8394, 13990, 19586, 25183, 30779, 36375, 41971, -2798, -8394, -13990, -19586, -25183, -30779, -36375, -41971,
3077, 9233, 15389, 21545, 27700, 33856, 40012, 46168, -3077, -9233, -15389, -21545, -27700, -33856, -40012, -46168,
3385, 10157, 16928, 23700, 30471, 37243, 44014, 50786, -3385, -10157, -16928, -23700, -30471, -37243, -44014, -50786,
3724, 11172, 18621, 26069, 33518, 40966, 48415, 55863, -3724, -11172, -18621, -26069, -33518, -40966, -48415, -55863,
};
static readonly ushort[] AdpAdjust = {
0, 0, 0, 0, 32, 64, 96, 128, 0, 0, 0, 0, 32, 64, 96, 128,
0, 0, 0, 0, 48, 80, 112, 144, 0, 0, 0, 0, 48, 80, 112, 144,
16, 16, 16, 16, 64, 96, 128, 160, 16, 16, 16, 16, 64, 96, 128, 160,
32, 32, 32, 32, 80, 112, 144, 176, 32, 32, 32, 32, 80, 112, 144, 176,
48, 48, 48, 48, 96, 128, 160, 192, 48, 48, 48, 48, 96, 128, 160, 192,
64, 64, 64, 64, 112, 144, 176, 208, 64, 64, 64, 64, 112, 144, 176, 208,
80, 80, 80, 80, 128, 160, 192, 224, 80, 80, 80, 80, 128, 160, 192, 224,
96, 96, 96, 96, 144, 176, 208, 240, 96, 96, 96, 96, 144, 176, 208, 240,
112, 112, 112, 112, 160, 192, 224, 256, 112, 112, 112, 112, 160, 192, 224, 256,
128, 128, 128, 128, 176, 208, 240, 272, 128, 128, 128, 128, 176, 208, 240, 272,
144, 144, 144, 144, 192, 224, 256, 288, 144, 144, 144, 144, 192, 224, 256, 288,
160, 160, 160, 160, 208, 240, 272, 304, 160, 160, 160, 160, 208, 240, 272, 304,
176, 176, 176, 176, 224, 256, 288, 320, 176, 176, 176, 176, 224, 256, 288, 320,
192, 192, 192, 192, 240, 272, 304, 336, 192, 192, 192, 192, 240, 272, 304, 336,
208, 208, 208, 208, 256, 288, 320, 352, 208, 208, 208, 208, 256, 288, 320, 352,
224, 224, 224, 224, 272, 304, 336, 368, 224, 224, 224, 224, 272, 304, 336, 368,
240, 240, 240, 240, 288, 320, 352, 384, 240, 240, 240, 240, 288, 320, 352, 384,
256, 256, 256, 256, 304, 336, 368, 400, 256, 256, 256, 256, 304, 336, 368, 400,
272, 272, 272, 272, 320, 352, 384, 416, 272, 272, 272, 272, 320, 352, 384, 416,
288, 288, 288, 288, 336, 368, 400, 432, 288, 288, 288, 288, 336, 368, 400, 432,
304, 304, 304, 304, 352, 384, 416, 448, 304, 304, 304, 304, 352, 384, 416, 448,
320, 320, 320, 320, 368, 400, 432, 464, 320, 320, 320, 320, 368, 400, 432, 464,
336, 336, 336, 336, 384, 416, 448, 480, 336, 336, 336, 336, 384, 416, 448, 480,
352, 352, 352, 352, 400, 432, 464, 496, 352, 352, 352, 352, 400, 432, 464, 496,
368, 368, 368, 368, 416, 448, 480, 512, 368, 368, 368, 368, 416, 448, 480, 512,
384, 384, 384, 384, 432, 464, 496, 528, 384, 384, 384, 384, 432, 464, 496, 528,
400, 400, 400, 400, 448, 480, 512, 544, 400, 400, 400, 400, 448, 480, 512, 544,
416, 416, 416, 416, 464, 496, 528, 560, 416, 416, 416, 416, 464, 496, 528, 560,
432, 432, 432, 432, 480, 512, 544, 576, 432, 432, 432, 432, 480, 512, 544, 576,
448, 448, 448, 448, 496, 528, 560, 592, 448, 448, 448, 448, 496, 528, 560, 592,
464, 464, 464, 464, 512, 544, 576, 608, 464, 464, 464, 464, 512, 544, 576, 608,
480, 480, 480, 480, 528, 560, 592, 624, 480, 480, 480, 480, 528, 560, 592, 624,
496, 496, 496, 496, 544, 576, 608, 640, 496, 496, 496, 496, 544, 576, 608, 640,
512, 512, 512, 512, 560, 592, 624, 656, 512, 512, 512, 512, 560, 592, 624, 656,
528, 528, 528, 528, 576, 608, 640, 672, 528, 528, 528, 528, 576, 608, 640, 672,
544, 544, 544, 544, 592, 624, 656, 688, 544, 544, 544, 544, 592, 624, 656, 688,
560, 560, 560, 560, 608, 640, 672, 704, 560, 560, 560, 560, 608, 640, 672, 704,
576, 576, 576, 576, 624, 656, 688, 720, 576, 576, 576, 576, 624, 656, 688, 720,
592, 592, 592, 592, 640, 672, 704, 736, 592, 592, 592, 592, 640, 672, 704, 736,
608, 608, 608, 608, 656, 688, 720, 752, 608, 608, 608, 608, 656, 688, 720, 752,
624, 624, 624, 624, 672, 704, 736, 768, 624, 624, 624, 624, 672, 704, 736, 768,
640, 640, 640, 640, 688, 720, 752, 784, 640, 640, 640, 640, 688, 720, 752, 784,
656, 656, 656, 656, 704, 736, 768, 800, 656, 656, 656, 656, 704, 736, 768, 800,
672, 672, 672, 672, 720, 752, 784, 816, 672, 672, 672, 672, 720, 752, 784, 816,
688, 688, 688, 688, 736, 768, 800, 832, 688, 688, 688, 688, 736, 768, 800, 832,
704, 704, 704, 704, 752, 784, 816, 848, 704, 704, 704, 704, 752, 784, 816, 848,
720, 720, 720, 720, 768, 800, 832, 864, 720, 720, 720, 720, 768, 800, 832, 864,
736, 736, 736, 736, 784, 816, 848, 880, 736, 736, 736, 736, 784, 816, 848, 880,
752, 752, 752, 752, 800, 832, 864, 896, 752, 752, 752, 752, 800, 832, 864, 896,
768, 768, 768, 768, 816, 848, 880, 912, 768, 768, 768, 768, 816, 848, 880, 912,
784, 784, 784, 784, 832, 864, 896, 928, 784, 784, 784, 784, 832, 864, 896, 928,
800, 800, 800, 800, 848, 880, 912, 944, 800, 800, 800, 800, 848, 880, 912, 944,
816, 816, 816, 816, 864, 896, 928, 960, 816, 816, 816, 816, 864, 896, 928, 960,
832, 832, 832, 832, 880, 912, 944, 976, 832, 832, 832, 832, 880, 912, 944, 976,
848, 848, 848, 848, 896, 928, 960, 992, 848, 848, 848, 848, 896, 928, 960, 992,
864, 864, 864, 864, 912, 944, 976, 1008, 864, 864, 864, 864, 912, 944, 976, 1008,
880, 880, 880, 880, 928, 960, 992, 1024, 880, 880, 880, 880, 928, 960, 992, 1024,
896, 896, 896, 896, 944, 976, 1008, 1040, 896, 896, 896, 896, 944, 976, 1008, 1040,
912, 912, 912, 912, 960, 992, 1024, 1056, 912, 912, 912, 912, 960, 992, 1024, 1056,
928, 928, 928, 928, 976, 1008, 1040, 1072, 928, 928, 928, 928, 976, 1008, 1040, 1072,
944, 944, 944, 944, 992, 1024, 1056, 1088, 944, 944, 944, 944, 992, 1024, 1056, 1088,
960, 960, 960, 960, 1008, 1040, 1072, 1104, 960, 960, 960, 960, 1008, 1040, 1072, 1104,
976, 976, 976, 976, 1024, 1056, 1088, 1120, 976, 976, 976, 976, 1024, 1056, 1088, 1120,
992, 992, 992, 992, 1040, 1072, 1104, 1136, 992, 992, 992, 992, 1040, 1072, 1104, 1136,
1008, 1008, 1008, 1008, 1056, 1088, 1120, 1152, 1008, 1008, 1008, 1008, 1056, 1088, 1120, 1152,
1024, 1024, 1024, 1024, 1072, 1104, 1136, 1168, 1024, 1024, 1024, 1024, 1072, 1104, 1136, 1168,
1040, 1040, 1040, 1040, 1088, 1120, 1152, 1184, 1040, 1040, 1040, 1040, 1088, 1120, 1152, 1184,
1056, 1056, 1056, 1056, 1104, 1136, 1168, 1200, 1056, 1056, 1056, 1056, 1104, 1136, 1168, 1200,
1072, 1072, 1072, 1072, 1120, 1152, 1184, 1216, 1072, 1072, 1072, 1072, 1120, 1152, 1184, 1216,
1088, 1088, 1088, 1088, 1136, 1168, 1200, 1232, 1088, 1088, 1088, 1088, 1136, 1168, 1200, 1232,
1104, 1104, 1104, 1104, 1152, 1184, 1216, 1248, 1104, 1104, 1104, 1104, 1152, 1184, 1216, 1248,
1120, 1120, 1120, 1120, 1168, 1200, 1232, 1264, 1120, 1120, 1120, 1120, 1168, 1200, 1232, 1264,
1136, 1136, 1136, 1136, 1184, 1216, 1248, 1280, 1136, 1136, 1136, 1136, 1184, 1216, 1248, 1280,
1152, 1152, 1152, 1152, 1200, 1232, 1264, 1296, 1152, 1152, 1152, 1152, 1200, 1232, 1264, 1296,
1168, 1168, 1168, 1168, 1216, 1248, 1280, 1312, 1168, 1168, 1168, 1168, 1216, 1248, 1280, 1312,
1184, 1184, 1184, 1184, 1232, 1264, 1296, 1328, 1184, 1184, 1184, 1184, 1232, 1264, 1296, 1328,
1200, 1200, 1200, 1200, 1248, 1280, 1312, 1344, 1200, 1200, 1200, 1200, 1248, 1280, 1312, 1344,
1216, 1216, 1216, 1216, 1264, 1296, 1328, 1360, 1216, 1216, 1216, 1216, 1264, 1296, 1328, 1360,
1232, 1232, 1232, 1232, 1280, 1312, 1344, 1376, 1232, 1232, 1232, 1232, 1280, 1312, 1344, 1376,
1248, 1248, 1248, 1248, 1296, 1328, 1360, 1392, 1248, 1248, 1248, 1248, 1296, 1328, 1360, 1392,
1264, 1264, 1264, 1264, 1312, 1344, 1376, 1392, 1264, 1264, 1264, 1264, 1312, 1344, 1376, 1392,
1280, 1280, 1280, 1280, 1328, 1360, 1392, 1392, 1280, 1280, 1280, 1280, 1328, 1360, 1392, 1392,
1296, 1296, 1296, 1296, 1344, 1376, 1392, 1392, 1296, 1296, 1296, 1296, 1344, 1376, 1392, 1392,
1312, 1312, 1312, 1312, 1360, 1392, 1392, 1392, 1312, 1312, 1312, 1312, 1360, 1392, 1392, 1392,
1328, 1328, 1328, 1328, 1376, 1392, 1392, 1392, 1328, 1328, 1328, 1328, 1376, 1392, 1392, 1392,
1344, 1344, 1344, 1344, 1392, 1392, 1392, 1392, 1344, 1344, 1344, 1344, 1392, 1392, 1392, 1392,
1360, 1360, 1360, 1360, 1392, 1392, 1392, 1392, 1360, 1360, 1360, 1360, 1392, 1392, 1392, 1392,
1376, 1376, 1376, 1376, 1392, 1392, 1392, 1392, 1376, 1376, 1376, 1376, 1392, 1392, 1392, 1392,
};
}
}