#6690(avformat:new): Raw Electronic Arts ADPCM support
#6690: Raw Electronic Arts ADPCM support ----------------------------------+--------------------------------------- Reporter: koops | Type: enhancement Status: new | Priority: normal Component: avformat | Version: unspecified Keywords: | Blocked By: Blocking: | Reproduced by developer: 0 Analyzed by developer: 0 | ----------------------------------+--------------------------------------- Summary of the bug: How to reproduce: {{{ $ ffmpeg -i sound.XA sound.wav sound.XA: Invalid data found when processing input }}} I would like support for headerless Electronic Arts ADPCM files to be added. These files are common in some Electronic Arts games, like Harry Potter and the Chamber of Secrets and Brother Bear. The format is similar to adpcm_ea_r1, but the file is always mono, there is no channels header. ADPCM history is always initialized to [0, 0]. File size is always a multiple of 15, there is no raw sample mode (0xEE). Sample rate is 22050Hz by default. Files can be encoded into this format using sx.exe: {{{
sx -raw -eaxa_blk sample.wav -=sample.XA }}
I attached a test case, a XA file and the corresponding decoded raw file. This is decoder code in C# (I release it under CC0): {{{ using System; using System.IO; using System.Text; namespace KoopsAudioDecoder { class Program { static int coeff1, coeff2, shift, adpcmHistory1 = 0, adpcmHistory2 = 0; static readonly int[] EA_XA_TABLE = new int[] { 0, 0, 240, 0, 460, -208, 392, -220, }; static void DecodeSingleFrame(BinaryReader stream, BinaryWriter outbuf) { int frameInfo = stream.ReadByte(); coeff1 = EA_XA_TABLE[((frameInfo >> 4) & 15) << 1]; coeff2 = EA_XA_TABLE[(((frameInfo >> 4) & 15) << 1) + 1]; shift = (frameInfo & 15) + 8; for (int i = 0; i < 14; i++) { int sample_byte = stream.ReadByte(); int[] nibbles = { sample_byte >> 4, sample_byte & 15 }; foreach (int nibble in nibbles) { int sample = GetSample(nibble); outbuf.Write(Clamp16(sample)); } } } private static int GetSample(int nibble) { int sample = (nibble << 28 >> shift) + (coeff1 * adpcmHistory1) + (coeff2 * adpcmHistory2) >> 8; adpcmHistory2 = adpcmHistory1; adpcmHistory1 = sample; return sample; } static private short Clamp16(int sample) { if (sample > 32767) { return 32767; } else if (sample < -32768) { return -32768; } else { return (short) sample; } } static int Main(string[] args) { if (args.Length != 1) { Console.WriteLine("This program takes only one argument, input file"); return 1; } string inputFileName = args[0], outputFileName = Path.ChangeExtension(inputFileName, "raw"); Stream inputFile = File.OpenRead(inputFileName), outputFile = File.OpenWrite(outputFileName); BinaryReader inputFileReader = new BinaryReader(inputFile); BinaryWriter outputFileWriter = new BinaryWriter(outputFile); while (inputFile.Length - inputFile.Position >= 15) { DecodeSingleFrame(inputFileReader, outputFileWriter); } if (inputFile.Length - inputFile.Position > 0) { Console.WriteLine("File has {0} spare bytes.", inputFile.Length - inputFile.Position); } return 0; } } } }}} -- Ticket URL: <https://trac.ffmpeg.org/ticket/6690> FFmpeg <https://ffmpeg.org> FFmpeg issue tracker
#6690: Raw Electronic Arts ADPCM support -------------------------------------+------------------------------------ Reporter: koops | Owner: Type: enhancement | Status: new Priority: normal | Component: avformat Version: unspecified | Resolution: Keywords: | Blocked By: Blocking: | Reproduced by developer: 0 Analyzed by developer: 0 | -------------------------------------+------------------------------------ Comment (by koops): Test case files are uploaded to https://streams.videolan.org/upload/. -- Ticket URL: <https://trac.ffmpeg.org/ticket/6690#comment:1> FFmpeg <https://ffmpeg.org> FFmpeg issue tracker
#6690: Raw Electronic Arts ADPCM support -------------------------------------+------------------------------------ Reporter: koops | Owner: Type: enhancement | Status: new Priority: normal | Component: avformat Version: unspecified | Resolution: Keywords: | Blocked By: Blocking: | Reproduced by developer: 0 Analyzed by developer: 0 | -------------------------------------+------------------------------------ Comment (by koops): Test case files are uploaded to https://streams.videolan.org/upload/. -- Ticket URL: <https://trac.ffmpeg.org/ticket/6690#comment:2> FFmpeg <https://ffmpeg.org> FFmpeg issue tracker
#6690: Raw Electronic Arts ADPCM support (.XA) -------------------------------------+------------------------------------ Reporter: koops | Owner: Type: enhancement | Status: new Priority: normal | Component: avformat Version: unspecified | Resolution: Keywords: | Blocked By: Blocking: | Reproduced by developer: 0 Analyzed by developer: 0 | -------------------------------------+------------------------------------ -- Ticket URL: <https://trac.ffmpeg.org/ticket/6690#comment:3> FFmpeg <https://ffmpeg.org> FFmpeg issue tracker
#6690: Raw Electronic Arts ADPCM support (.XA) -------------------------------------+------------------------------------- Reporter: koops | Owner: Type: enhancement | Status: open Priority: wish | Component: avformat Version: git-master | Resolution: Keywords: | Blocked By: electronicarts | Reproduced by developer: 0 Blocking: | Analyzed by developer: 0 | -------------------------------------+------------------------------------- Changes (by cehoyos): * keywords: => electronicarts * priority: normal => wish * version: unspecified => git-master * status: new => open Old description:
Summary of the bug: How to reproduce: {{{ $ ffmpeg -i sound.XA sound.wav sound.XA: Invalid data found when processing input }}}
I would like support for headerless Electronic Arts ADPCM files to be added. These files are common in some Electronic Arts games, like Harry Potter and the Chamber of Secrets and Brother Bear.
The format is similar to adpcm_ea_r1, but the file is always mono, there is no channels header. ADPCM history is always initialized to [0, 0]. File size is always a multiple of 15, there is no raw sample mode (0xEE).
Sample rate is 22050Hz by default.
Files can be encoded into this format using sx.exe: {{{
sx -raw -eaxa_blk sample.wav -=sample.XA }}
I attached a test case, a XA file and the corresponding decoded raw file.
This is decoder code in C# (I release it under CC0):
{{{ using System; using System.IO; using System.Text;
namespace KoopsAudioDecoder { class Program { static int coeff1, coeff2, shift, adpcmHistory1 = 0, adpcmHistory2 = 0;
static readonly int[] EA_XA_TABLE = new int[] { 0, 0, 240, 0, 460, -208, 392, -220, };
static void DecodeSingleFrame(BinaryReader stream, BinaryWriter outbuf) { int frameInfo = stream.ReadByte();
coeff1 = EA_XA_TABLE[((frameInfo >> 4) & 15) << 1]; coeff2 = EA_XA_TABLE[(((frameInfo >> 4) & 15) << 1) + 1]; shift = (frameInfo & 15) + 8;
for (int i = 0; i < 14; i++) { int sample_byte = stream.ReadByte();
int[] nibbles = { sample_byte >> 4, sample_byte & 15 };
foreach (int nibble in nibbles) { int sample = GetSample(nibble);
outbuf.Write(Clamp16(sample)); } } }
private static int GetSample(int nibble) { int sample = (nibble << 28 >> shift) + (coeff1 * adpcmHistory1) + (coeff2 * adpcmHistory2) >> 8;
adpcmHistory2 = adpcmHistory1; adpcmHistory1 = sample;
return sample; }
static private short Clamp16(int sample) { if (sample > 32767) { return 32767; } else if (sample < -32768) { return -32768; } else { return (short) sample; } }
static int Main(string[] args) { if (args.Length != 1) { Console.WriteLine("This program takes only one argument, input file"); return 1; }
string inputFileName = args[0], outputFileName = Path.ChangeExtension(inputFileName, "raw"); Stream inputFile = File.OpenRead(inputFileName), outputFile = File.OpenWrite(outputFileName); BinaryReader inputFileReader = new BinaryReader(inputFile); BinaryWriter outputFileWriter = new BinaryWriter(outputFile);
while (inputFile.Length - inputFile.Position >= 15) { DecodeSingleFrame(inputFileReader, outputFileWriter); }
if (inputFile.Length - inputFile.Position > 0) { Console.WriteLine("File has {0} spare bytes.", inputFile.Length - inputFile.Position); }
return 0; } } } }}}
New description: Summary of the bug: How to reproduce: {{{ $ ffmpeg -i sound.XA sound.wav sound.XA: Invalid data found when processing input }}} I would like support for headerless Electronic Arts ADPCM files to be added. These files are common in some Electronic Arts games, like Harry Potter and the Chamber of Secrets and Brother Bear. The format is similar to adpcm_ea_r1, but the file is always mono, there is no channels header. ADPCM history is always initialized to [0, 0]. File size is always a multiple of 15, there is no raw sample mode (0xEE). Sample rate is 22050Hz by default. Files can be encoded into this format using sx.exe: {{{
sx -raw -eaxa_blk sample.wav -=sample.XA }}}
I attached a test case, a XA file and the corresponding decoded raw file. This is decoder code in C# (I release it under CC0): {{{ using System; using System.IO; using System.Text; namespace KoopsAudioDecoder { class Program { static int coeff1, coeff2, shift, adpcmHistory1 = 0, adpcmHistory2 = 0; static readonly int[] EA_XA_TABLE = new int[] { 0, 0, 240, 0, 460, -208, 392, -220, }; static void DecodeSingleFrame(BinaryReader stream, BinaryWriter outbuf) { int frameInfo = stream.ReadByte(); coeff1 = EA_XA_TABLE[((frameInfo >> 4) & 15) << 1]; coeff2 = EA_XA_TABLE[(((frameInfo >> 4) & 15) << 1) + 1]; shift = (frameInfo & 15) + 8; for (int i = 0; i < 14; i++) { int sample_byte = stream.ReadByte(); int[] nibbles = { sample_byte >> 4, sample_byte & 15 }; foreach (int nibble in nibbles) { int sample = GetSample(nibble); outbuf.Write(Clamp16(sample)); } } } private static int GetSample(int nibble) { int sample = (nibble << 28 >> shift) + (coeff1 * adpcmHistory1) + (coeff2 * adpcmHistory2) >> 8; adpcmHistory2 = adpcmHistory1; adpcmHistory1 = sample; return sample; } static private short Clamp16(int sample) { if (sample > 32767) { return 32767; } else if (sample < -32768) { return -32768; } else { return (short) sample; } } static int Main(string[] args) { if (args.Length != 1) { Console.WriteLine("This program takes only one argument, input file"); return 1; } string inputFileName = args[0], outputFileName = Path.ChangeExtension(inputFileName, "raw"); Stream inputFile = File.OpenRead(inputFileName), outputFile = File.OpenWrite(outputFileName); BinaryReader inputFileReader = new BinaryReader(inputFile); BinaryWriter outputFileWriter = new BinaryWriter(outputFile); while (inputFile.Length - inputFile.Position >= 15) { DecodeSingleFrame(inputFileReader, outputFileWriter); } if (inputFile.Length - inputFile.Position > 0) { Console.WriteLine("File has {0} spare bytes.", inputFile.Length - inputFile.Position); } return 0; } } } }}} -- -- Ticket URL: <https://trac.ffmpeg.org/ticket/6690#comment:4> FFmpeg <https://ffmpeg.org> FFmpeg issue tracker
#6690: Raw Electronic Arts ADPCM support (.XA) -------------------------------------+------------------------------------- Reporter: koops | Owner: Type: enhancement | Status: open Priority: wish | Component: avformat Version: git-master | Resolution: Keywords: | Blocked By: electronicarts | Reproduced by developer: 0 Blocking: | Analyzed by developer: 0 | -------------------------------------+------------------------------------- Comment (by koops): @cehoyos There is also a decoded .raw file. -- Ticket URL: <https://trac.ffmpeg.org/ticket/6690#comment:5> FFmpeg <https://ffmpeg.org> FFmpeg issue tracker
#6690: Raw Electronic Arts ADPCM support (.XA) -------------------------------------+------------------------------------- Reporter: koops | Owner: Type: enhancement | Status: open Priority: wish | Component: avformat Version: git-master | Resolution: Keywords: | Blocked By: electronicarts | Reproduced by developer: 0 Blocking: | Analyzed by developer: 0 | -------------------------------------+------------------------------------- Comment (by koops): Edit: the file can actually be stereo. -- Ticket URL: <https://trac.ffmpeg.org/ticket/6690#comment:6> FFmpeg <https://ffmpeg.org> FFmpeg issue tracker
#6690: Raw Electronic Arts ADPCM support (.XA) -------------------------------------+------------------------------------- Reporter: koops | Owner: Type: enhancement | Status: open Priority: wish | Component: avformat Version: git-master | Resolution: Keywords: | Blocked By: electronicarts | Reproduced by developer: 0 Blocking: | Analyzed by developer: 0 | -------------------------------------+------------------------------------- Comment (by cehoyos): Please provide a stereo sample. -- Ticket URL: <https://trac.ffmpeg.org/ticket/6690#comment:7> FFmpeg <https://ffmpeg.org> FFmpeg issue tracker
#6690: Raw Electronic Arts ADPCM support (.XA) -------------------------------------+------------------------------------- Reporter: koops | Owner: Type: enhancement | Status: open Priority: wish | Component: avformat Version: git-master | Resolution: Keywords: | Blocked By: electronicarts | Reproduced by developer: 0 Blocking: | Analyzed by developer: 0 | -------------------------------------+------------------------------------- Comment (by koops): I uploaded it to https://streams.videolan.org/upload/. It's the one without "fixed" in description, I accidentally created a stereo sample, while I wanted mono. -- Ticket URL: <https://trac.ffmpeg.org/ticket/6690#comment:8> FFmpeg <https://ffmpeg.org> FFmpeg issue tracker
#6690: Raw Electronic Arts ADPCM support (.XA) -------------------------------------+------------------------------------- Reporter: koops | Owner: Type: enhancement | Status: open Priority: wish | Component: avformat Version: git-master | Resolution: Keywords: | Blocked By: electronicarts | Reproduced by developer: 0 Blocking: | Analyzed by developer: 0 | -------------------------------------+------------------------------------- Comment (by koops): You can detect this format by file size being a multiple of 15 and 0th, 15th, 30th and so on bytes being less than 0x40. -- Ticket URL: <https://trac.ffmpeg.org/ticket/6690#comment:9> FFmpeg <https://ffmpeg.org> FFmpeg issue tracker
#6690: Raw Electronic Arts ADPCM support (.XA) -------------------------------------+------------------------------------- Reporter: koops | Owner: Type: enhancement | Status: open Priority: wish | Component: avformat Version: git-master | Resolution: Keywords: | Blocked By: electronicarts | Reproduced by developer: 0 Blocking: | Analyzed by developer: 0 | -------------------------------------+------------------------------------- Comment (by koops): https://gist.github.com/koops76/e830ce92e1eb9c13d4cbfa861c0fc109 -- Ticket URL: <https://trac.ffmpeg.org/ticket/6690#comment:10> FFmpeg <https://ffmpeg.org> FFmpeg issue tracker
#6690: Raw Electronic Arts ADPCM support (.XA) -------------------------------------+------------------------------------- Reporter: koops | Owner: Type: enhancement | Status: open Priority: wish | Component: avformat Version: git-master | Resolution: Keywords: | Blocked By: electronicarts | Reproduced by developer: 0 Blocking: | Analyzed by developer: 0 | -------------------------------------+------------------------------------- Comment (by koops): Replace the code in the first comment with this one from the previous comment and delete it please. -- Ticket URL: <https://trac.ffmpeg.org/ticket/6690#comment:11> FFmpeg <https://ffmpeg.org> FFmpeg issue tracker
#6690: Raw Electronic Arts ADPCM support (.XA) -------------------------------------+------------------------------------- Reporter: koops | Owner: Type: enhancement | Status: open Priority: wish | Component: avformat Version: git-master | Resolution: Keywords: | Blocked By: electronicarts | Reproduced by developer: 0 Blocking: | Analyzed by developer: 0 | -------------------------------------+------------------------------------- Old description:
Summary of the bug: How to reproduce: {{{ $ ffmpeg -i sound.XA sound.wav sound.XA: Invalid data found when processing input }}}
I would like support for headerless Electronic Arts ADPCM files to be added. These files are common in some Electronic Arts games, like Harry Potter and the Chamber of Secrets and Brother Bear.
The format is similar to adpcm_ea_r1, but the file is always mono, there is no channels header. ADPCM history is always initialized to [0, 0]. File size is always a multiple of 15, there is no raw sample mode (0xEE).
Sample rate is 22050Hz by default.
Files can be encoded into this format using sx.exe: {{{
sx -raw -eaxa_blk sample.wav -=sample.XA }}}
I attached a test case, a XA file and the corresponding decoded raw file.
This is decoder code in C# (I release it under CC0):
{{{ using System; using System.IO; using System.Text;
namespace KoopsAudioDecoder { class Program { static int coeff1, coeff2, shift, adpcmHistory1 = 0, adpcmHistory2 = 0;
static readonly int[] EA_XA_TABLE = new int[] { 0, 0, 240, 0, 460, -208, 392, -220, };
static void DecodeSingleFrame(BinaryReader stream, BinaryWriter outbuf) { int frameInfo = stream.ReadByte();
coeff1 = EA_XA_TABLE[((frameInfo >> 4) & 15) << 1]; coeff2 = EA_XA_TABLE[(((frameInfo >> 4) & 15) << 1) + 1]; shift = (frameInfo & 15) + 8;
for (int i = 0; i < 14; i++) { int sample_byte = stream.ReadByte();
int[] nibbles = { sample_byte >> 4, sample_byte & 15 };
foreach (int nibble in nibbles) { int sample = GetSample(nibble);
outbuf.Write(Clamp16(sample)); } } }
private static int GetSample(int nibble) { int sample = (nibble << 28 >> shift) + (coeff1 * adpcmHistory1) + (coeff2 * adpcmHistory2) >> 8;
adpcmHistory2 = adpcmHistory1; adpcmHistory1 = sample;
return sample; }
static private short Clamp16(int sample) { if (sample > 32767) { return 32767; } else if (sample < -32768) { return -32768; } else { return (short) sample; } }
static int Main(string[] args) { if (args.Length != 1) { Console.WriteLine("This program takes only one argument, input file"); return 1; }
string inputFileName = args[0], outputFileName = Path.ChangeExtension(inputFileName, "raw"); Stream inputFile = File.OpenRead(inputFileName), outputFile = File.OpenWrite(outputFileName); BinaryReader inputFileReader = new BinaryReader(inputFile); BinaryWriter outputFileWriter = new BinaryWriter(outputFile);
while (inputFile.Length - inputFile.Position >= 15) { DecodeSingleFrame(inputFileReader, outputFileWriter); }
if (inputFile.Length - inputFile.Position > 0) { Console.WriteLine("File has {0} spare bytes.", inputFile.Length - inputFile.Position); }
return 0; } } } }}}
New description: Summary of the bug: How to reproduce: {{{ $ ffmpeg -i sound.XA sound.wav sound.XA: Invalid data found when processing input }}} I would like support for headerless Electronic Arts ADPCM files to be added. These files are common in some Electronic Arts games, like Harry Potter and the Chamber of Secrets and Brother Bear. The format is similar to adpcm_ea_r1, but the file is always mono, there is no channels header. ADPCM history is always initialized to [0, 0]. File size is always a multiple of 15, there is no raw sample mode (0xEE). Sample rate is 22050Hz by default. Files can be encoded into this format using sx.exe: {{{
sx -raw -eaxa_blk sample.wav -=sample.XA }}}
I attached a test case, a XA file and the corresponding decoded raw file. This is decoder code in C# (I release it under CC0): {{{ using System; using System.IO; using System.Text; namespace KoopsAudioDecoder { class Program { static int coeff1, coeff2, shift, adpcmHistory1 = 0, adpcmHistory2 = 0; static readonly int[] EA_XA_TABLE = new int[] { 0, 0, 240, 0, 460, -208, 392, -220, }; static void DecodeSingleFrame(BinaryReader stream, BinaryWriter outbuf) { int frameInfo = stream.ReadByte(); coeff1 = EA_XA_TABLE[((frameInfo >> 4) & 15) * 2]; coeff2 = EA_XA_TABLE[((frameInfo >> 4) & 15) * 2 + 1]; shift = (frameInfo & 15) + 8; for (int i = 0; i < 14; i++) { int sample_byte = stream.ReadByte(); int[] nibbles = { sample_byte >> 4, sample_byte & 15 }; foreach (int nibble in nibbles) { int sample = GetSample(nibble); outbuf.Write(Clamp16(sample)); } } } private static int GetSample(int nibble) { int sample = ((nibble << 28 >> shift) + (coeff1 * adpcmHistory1) + (coeff2 * adpcmHistory2)) >> 8; adpcmHistory2 = adpcmHistory1; adpcmHistory1 = sample; return sample; } static private short Clamp16(int sample) { if (sample > 32767) { return 32767; } if (sample < -32768) { return -32768; } return (short) sample; } static int Main(string[] args) { if (args.Length != 1) { Console.WriteLine("This program takes only one argument, input file"); return 1; } string inputFileName = args[0], outputFileName = Path.ChangeExtension(inputFileName, "raw"); Stream inputFile = File.OpenRead(inputFileName), outputFile = File.OpenWrite(outputFileName); BinaryReader inputFileReader = new BinaryReader(inputFile); BinaryWriter outputFileWriter = new BinaryWriter(outputFile); while (inputFile.Length - inputFile.Position >= 15) { DecodeSingleFrame(inputFileReader, outputFileWriter); } if (inputFile.Length - inputFile.Position > 0) { Console.WriteLine("File has {0} spare bytes.", inputFile.Length - inputFile.Position); } return 0; } } } }}} -- Comment (by cehoyos): The stereo file unfortunately never appeared, please attach it here. -- Ticket URL: <https://trac.ffmpeg.org/ticket/6690#comment:12> FFmpeg <https://ffmpeg.org> FFmpeg issue tracker
#6690: Raw Electronic Arts ADPCM support (.XA) -------------------------------------+------------------------------------- Reporter: koops | Owner: Type: enhancement | Status: open Priority: wish | Component: avformat Version: git-master | Resolution: Keywords: | Blocked By: electronicarts | Reproduced by developer: 0 Blocking: | Analyzed by developer: 0 | -------------------------------------+------------------------------------- Comment (by koops): The stereo file is two mono files going after each other, not an interleaved file. You can only keep mono support if you like. -- Ticket URL: <https://trac.ffmpeg.org/ticket/6690#comment:13> FFmpeg <https://ffmpeg.org> FFmpeg issue tracker
#6690: Raw Electronic Arts ADPCM support (.XA) -------------------------------------+------------------------------------- Reporter: koops | Owner: Type: enhancement | Status: open Priority: wish | Component: avformat Version: git-master | Resolution: Keywords: | Blocked By: electronicarts | Reproduced by developer: 0 Blocking: | Analyzed by developer: 0 | -------------------------------------+------------------------------------- Comment (by koops): Are you going to implement this feature? -- Ticket URL: <https://trac.ffmpeg.org/ticket/6690#comment:14> FFmpeg <https://ffmpeg.org> FFmpeg issue tracker
#6690: Raw Electronic Arts ADPCM support (.XA) -------------------------------------+------------------------------------- Reporter: koops | Owner: Type: enhancement | Status: open Priority: wish | Component: avformat Version: git-master | Resolution: Keywords: | Blocked By: electronicarts | Reproduced by developer: 0 Blocking: | Analyzed by developer: 0 | -------------------------------------+------------------------------------- Comment (by cehoyos): It seems to me you are the right person to do it, given you already implemented a decoder. -- Ticket URL: <https://trac.ffmpeg.org/ticket/6690#comment:15> FFmpeg <https://ffmpeg.org> FFmpeg issue tracker
#6690: Raw Electronic Arts ADPCM support (.XA) -------------------------------------+------------------------------------- Reporter: koops | Owner: (none) Type: enhancement | Status: open Priority: wish | Component: avformat Version: git-master | Resolution: Keywords: | Blocked By: electronicarts | Blocking: | Reproduced by developer: 0 Analyzed by developer: 0 | -------------------------------------+------------------------------------- Comment (by pross): these are just files encoded with 15-byte AV_CODEC_ID_ADPCM_EA_MAXIS_XA packets there is no way to detect this file format -- Ticket URL: <https://trac.ffmpeg.org/ticket/6690#comment:16> FFmpeg <https://ffmpeg.org> FFmpeg issue tracker
participants (1)
-
FFmpeg