XA Format Specs
XA Format Specs
I am looking for technical docs on the XA Container File?
-
Administrator Verified
- Admin / PSXDEV
- Posts: 2691
- Joined: Dec 31, 2012
- I am a: Shadow
- PlayStation Model: H2000/5502
Enjoy!
You do not have the required permissions to view the files attached to this post.
Development Console: SCPH-5502 with 8MB RAM, MM3 Modchip, PAL 60 Colour Modification (for NTSC), PSIO Switch Board, DB-9 breakout headers for both RGB and Serial output and an Xplorer with CAETLA 0.34.
PlayStation Development PC: Windows 98 SE, Pentium 3 at 400MHz, 128MB SDRAM, DTL-H2000, DTL-H2010, DTL-H201A, DTL-S2020 (with 4GB SCSI-2 HDD), 21" Sony G420, CD-R burner, 3.25" and 5.25" Floppy Diskette Drives, ZIP 100 Diskette Drive and an IBM Model M keyboard.
PlayStation Development PC: Windows 98 SE, Pentium 3 at 400MHz, 128MB SDRAM, DTL-H2000, DTL-H2010, DTL-H201A, DTL-S2020 (with 4GB SCSI-2 HDD), 21" Sony G420, CD-R burner, 3.25" and 5.25" Floppy Diskette Drives, ZIP 100 Diskette Drive and an IBM Model M keyboard.
- meth962
- Interested PSXDEV User
- Posts: 8
- Joined: Sep 11, 2014
- I am a: Bucket List Enthusiast
- Motto: Masakatsu agatsu
- Location: USA
Has anyone had success using this documentation? I'm writing an app to convert XA files just for kicks (I know there are some out there but they don't work on win7) and everything seems to be legit until it comes to converting ADPCM to PCM. It looks like the documentation is wrong, since the pseudocode has some errors in it. Basically I tried using the method ADPCMtoPCM provided and it turned all of my soundData to zeroes.
So in attempt to making my own, I was confused on the instructions. I think it has some things backwards or unexplained. This line is confusing to me:
"Shifting is done to the right, so a nibble of 0xF is first extended to a
word: 0xF00, then (arithmetically) shifted to the right, e.g. if range=11, the
result would be 0xFFEE."
So first it's shifted left 8 bits to turn it into a word and then it states to shift to the right. From their example, I cannot find any way that 0xF00 turns into 0xFFEE. In fact, that would be shifting left instead of right since the number increased...right? Am I losing my mind or missing something obvious?
Thanks so much for any help in advance. I'm having fun debugging playstation logic/files/games/etc
Please help me continue the journey!
*Edit: fixed grammar and typos
So in attempt to making my own, I was confused on the instructions. I think it has some things backwards or unexplained. This line is confusing to me:
"Shifting is done to the right, so a nibble of 0xF is first extended to a
word: 0xF00, then (arithmetically) shifted to the right, e.g. if range=11, the
result would be 0xFFEE."
So first it's shifted left 8 bits to turn it into a word and then it states to shift to the right. From their example, I cannot find any way that 0xF00 turns into 0xFFEE. In fact, that would be shifting left instead of right since the number increased...right? Am I losing my mind or missing something obvious?
Thanks so much for any help in advance. I'm having fun debugging playstation logic/files/games/etc

*Edit: fixed grammar and typos
Mind that the nibbles are signed, ie. "F" means "-1".
The 4bit nibbles are left-shifted by 12, to expand them to 16bits (this should give F000, not F00).
And then right shifted (arithmetically = with the sign bit shifted into the upper bits) (with shift amount 11, that would give FFFE, not FFEE).
Here's my own doc on CD-XA, http://problemkaputt.de/psx-spx.htm#cdr ... ompression don't know if it's of any use, but (I hope) it can't be worse than the description that you are currently using).
The 4bit nibbles are left-shifted by 12, to expand them to 16bits (this should give F000, not F00).
And then right shifted (arithmetically = with the sign bit shifted into the upper bits) (with shift amount 11, that would give FFFE, not FFEE).
Here's my own doc on CD-XA, http://problemkaputt.de/psx-spx.htm#cdr ... ompression don't know if it's of any use, but (I hope) it can't be worse than the description that you are currently using).
- meth962
- Interested PSXDEV User
- Posts: 8
- Joined: Sep 11, 2014
- I am a: Bucket List Enthusiast
- Motto: Masakatsu agatsu
- Location: USA
Hi. Guess I celebrated too early on the XA audio. Are you willing to double check my work? I understand if you're too busy or do not want to so don't hesitate to say no.
I know I'm close. I hear a voice but it's mixed with some static. I can tell the wav has some +32.768 or - 32,768 areas that shouldn't be there if I compare what the wav sound looks like compared to the right one in Audacity.
I changed my code to act like yours so it might be easy for you to spot what I did wrong
it is in C# if you can understand it.
I know I'm close. I hear a voice but it's mixed with some static. I can tell the wav has some +32.768 or - 32,768 areas that shouldn't be there if I compare what the wav sound looks like compared to the right one in Audacity.
I changed my code to act like yours so it might be easy for you to spot what I did wrong

Code: Select all
bw.Write(Encoding.Default.GetBytes("data"));
bw.Write(size);
short dstLeft = 0, oldLeft = 0, olderLeft = 0, dstRight = 1, oldRight = 0, olderRight = 0;
foreach (var sg in c.SoundGroups)
{
for (byte b = 0; b < 4; b++)
{
DecodeBlock(sg.AudioBytes, sg.SoundParameters, b, 1, dstLeft, ref oldLeft, ref olderLeft);
DecodeBlock(sg.AudioBytes, sg.SoundParameters, b, 0, dstRight, ref oldRight, ref olderRight);
for (byte d = 0; d < decoded.Length; d++)
bw.Write(decoded[d]);
}
}
Code: Select all
private void DecodeBlock(byte[] samples, byte[] parameters, byte block, byte nibble, short dst, ref short old, ref short older)
{
byte shift = (byte)(12 - (parameters[4+block*2+nibble] & 0xF));
byte filter = (byte)(parameters[4+block*2+nibble] & 0x30 >> 4);
short f0 = pos_adpcm_table[filter];
short f1 = neg_adpcm_table[filter];
for(int d = 0; d < 28; d++)
{
sbyte t = Signed4bit((byte)((samples[block + d * 4] >> (nibble * 4)) & 0xF));
short s = (short)((t << shift) + ((old * f0 + older * f1 + 32) / 64));
s = MinMax(s, -0x8000, 0x7fff);
decoded[dst] = s;
dst += 2;
older = old;
old = s;
}
}
I am more familar with asm. What means "short"? Is that a signed/unsigned variable? And how many bits is it?
If it's only 16bits, then the MinMax function obviously can't adjust values that are exceeding the 16bit range : - )
If it's only 16bits, then the MinMax function obviously can't adjust values that are exceeding the 16bit range : - )
- meth962
- Interested PSXDEV User
- Posts: 8
- Joined: Sep 11, 2014
- I am a: Bucket List Enthusiast
- Motto: Masakatsu agatsu
- Location: USA
Yeah, I wish I could just breakpoint PSX and follow the assembly to figure it out 
Short is a signed 16 bit, so yeah it already has the min/max, whoops! To test it, I even break pointed the return min or max lines and they are never hit (even after changing the type to be shifted to int32).
Ah yeah, here are the couple other methods in there for reference:

Short is a signed 16 bit, so yeah it already has the min/max, whoops! To test it, I even break pointed the return min or max lines and they are never hit (even after changing the type to be shifted to int32).
Ah yeah, here are the couple other methods in there for reference:
Code: Select all
private int MinMax(int number, int min, int max)
{
if (number < min)
return min;
if (number > max)
return max;
return number;
}
Code: Select all
private sbyte Signed4bit(sbyte number)
{
if ((number & 0x8) == 0x8)
return (sbyte)((number & 0x7)-8);
else
return (sbyte)number;
}
- meth962
- Interested PSXDEV User
- Posts: 8
- Joined: Sep 11, 2014
- I am a: Bucket List Enthusiast
- Motto: Masakatsu agatsu
- Location: USA
So I can see the pattern is there, at least I have the blocks/samples in the right order for both channel. Just doing some shifting or something wrong as it seems I'm getting much higher (or lower) values than I'm suppose to which make the wave forms look very large. Here is a comparison to the same sound I am trying to decode.
Top one is the way it should look, and the bottom one is what I am outputting.

Top one is the way it should look, and the bottom one is what I am outputting.

- meth962
- Interested PSXDEV User
- Posts: 8
- Joined: Sep 11, 2014
- I am a: Bucket List Enthusiast
- Motto: Masakatsu agatsu
- Location: USA
Got it folks! It was the Filter.........bad parenthesis!
Error:
sbyte filter = (sbyte)(parameters[4+block*2+nibble] & 0x30 >> 4);
Correction:
sbyte filter = (sbyte)((parameters[4+block*2+nibble] & 0x30) >> 4);
Simple order of operations whoops! Thank you for your support, Shadow and NoCash!
Error:
sbyte filter = (sbyte)(parameters[4+block*2+nibble] & 0x30 >> 4);
Correction:
sbyte filter = (sbyte)((parameters[4+block*2+nibble] & 0x30) >> 4);
Simple order of operations whoops! Thank you for your support, Shadow and NoCash!
Who is online
Users browsing this forum: No registered users and 2 guests