mirror of
https://github.com/crskycode/GARbro.git
synced 2025-01-11 12:39:16 +08:00
(Adp4Audio): implemented ADPS decoder.
This commit is contained in:
parent
3cfdb81ffa
commit
511ba480b0
@ -38,23 +38,33 @@ namespace GameRes.Formats.GameSystem
|
|||||||
public override uint Signature { get { return 0; } }
|
public override uint Signature { get { return 0; } }
|
||||||
public override bool CanWrite { get { return false; } }
|
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)
|
public override SoundInput TryOpen (IBinaryStream file)
|
||||||
{
|
{
|
||||||
bool is_adp4 = file.Name.EndsWith (".adp4", StringComparison.InvariantCultureIgnoreCase);
|
bool is_adp4 = file.Name.EndsWith (".adp4", StringComparison.InvariantCultureIgnoreCase);
|
||||||
if (!is_adp4 || file.Length <= 4)
|
bool is_adps = !is_adp4 && file.Name.EndsWith (".adps", StringComparison.InvariantCultureIgnoreCase);
|
||||||
|
if (!(is_adp4 || is_adps) || file.Length <= 4)
|
||||||
return null;
|
return null;
|
||||||
var decoder = new AdpDecoder (file);
|
var decoder = new AdpDecoder (file);
|
||||||
var pcm = decoder.Decode();
|
var pcm = decoder.Decode (is_adps);
|
||||||
var format = new WaveFormat {
|
var format = new WaveFormat {
|
||||||
FormatTag = 1,
|
FormatTag = 1,
|
||||||
Channels = 2,
|
Channels = 2,
|
||||||
SamplesPerSecond = 44100, // XXX varies
|
SamplesPerSecond = DefaultSampleRate,
|
||||||
BlockAlign = 4,
|
BlockAlign = 4,
|
||||||
BitsPerSample = 16,
|
BitsPerSample = 16,
|
||||||
};
|
};
|
||||||
format.SetBPS();
|
format.SetBPS();
|
||||||
var input = new MemoryStream (pcm);
|
var input = new MemoryStream (pcm);
|
||||||
return new RawPcmInput (input, format);
|
var sound = new RawPcmInput (input, format);
|
||||||
|
file.Dispose();
|
||||||
|
return sound;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,15 +79,58 @@ namespace GameRes.Formats.GameSystem
|
|||||||
|
|
||||||
byte[] m_output;
|
byte[] m_output;
|
||||||
|
|
||||||
public byte[] Decode ()
|
public byte[] Decode (bool is_adps)
|
||||||
{
|
{
|
||||||
m_input.Position = 0;
|
m_input.Position = 0;
|
||||||
int sample_count = m_input.ReadInt32();
|
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];
|
m_output = new byte[sample_count * 8];
|
||||||
DecodeBits (sample_count);
|
if (is_adps)
|
||||||
|
DecodeAdps (sample_count);
|
||||||
|
else
|
||||||
|
DecodeBits (sample_count);
|
||||||
return m_output;
|
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)
|
void DecodeBits (int sample_count)
|
||||||
{
|
{
|
||||||
bool copy_stereo = true;
|
bool copy_stereo = true;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user