Skip to content

Commit

Permalink
Created the Eurocom IMA Adpcm Encoder
Browse files Browse the repository at this point in the history
  • Loading branch information
jmarti856 committed Dec 26, 2022
1 parent 00a2cd7 commit 50793f4
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 76 deletions.
161 changes: 86 additions & 75 deletions ImaAdpcm-Encoder-Decoder/ImaAdpcm Function/ImaAdpcmEncoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public static byte[] Encode(short[] pcmData)
int outputbuffer; /* place to keep previous 4-bit value */
bool bufferstep; /* toggle between outputbuffer/output */
int numSamples; /* Number of Samples to encode*/
int remainingSamples; /* Countdown remaining samples for the output buffer */
int magicID = 65;

//Initialize variables
ImaAdpcmState state = new ImaAdpcmState();
Expand All @@ -35,90 +35,101 @@ public static byte[] Encode(short[] pcmData)
valpred = state.valprev;
index = state.index;
step = stepsizeTable[index];
remainingSamples = 0;

bufferstep = true;

//Ensure that we have chunks of 56 samples
short[] inputBuffer = new short[pcmData.Length + 100];
Buffer.BlockCopy(pcmData, 0, inputBuffer, 0, numSamples * sizeof(short));

for (; numSamples > 0; numSamples--)
//Start encoding
while (inp < numSamples)
{
if (--remainingSamples <= 0)
//Clamp ID
if (magicID > 90)
{
remainingSamples = 56;
outBuff.WriteByte((byte)(valpred & 0xFF));
outBuff.WriteByte((byte)((valpred >> 8) & 0xFF));
outBuff.WriteByte((byte)index);
outBuff.WriteByte(0);
magicID = 65;
}

val = pcmData[inp++];

/* Step 1 - compute difference with previous value */
diff = val - valpred;
sign = (diff < 0) ? 8 : 0;
if (sign != 0) diff = (-diff);

/* Step 2 - Divide and clamp */
/* Note:
** This code *approximately* computes:
** delta = diff*4/step;
** vpdiff = (delta+0.5)*step/4;
** but in shift step bits are dropped. The net result of this is
** that even if you have fast mul/div hardware you cannot put it to
** good use since the fixup would be too expensive.
*/
delta = 0;
vpdiff = (step >> 3);

if (diff >= step)
{
delta = 4;
diff -= step;
vpdiff += step;
}
step >>= 1;
if (diff >= step)
{
delta |= 2;
diff -= step;
vpdiff += step;
}
step >>= 1;
if (diff >= step)
{
delta |= 1;
vpdiff += step;
}
//Write Header Data
outBuff.WriteByte((byte)(valpred & 0xFF));
outBuff.WriteByte((byte)((valpred >> 8) & 0xFF));
outBuff.WriteByte((byte)index);
outBuff.WriteByte((byte)magicID++);

/* Step 3 - Update previous value */
if (sign != 0)
valpred -= vpdiff;
else
valpred += vpdiff;

/* Step 4 - Clamp previous value to 16 bits */
if (valpred > short.MaxValue)
valpred = short.MaxValue;
else if (valpred < short.MinValue)
valpred = short.MinValue;

/* Step 5 - Assemble value, update index and step values */
delta |= sign;

index += indexTable[delta];
if (index < 0) index = 0;
if (index > 88) index = 88;
step = stepsizeTable[index];

/* Step 6 - Output value */
if (bufferstep)
{
outputbuffer = (delta << 4) & 0xf0;
}
else
//56 samples = 28 pairs of nibbles
for (int j = 0; j < 56; j++)
{
outBuff.WriteByte((byte)((delta & 0x0f) | outputbuffer));
val = inputBuffer[inp++];

/* Step 1 - compute difference with previous value */
diff = val - valpred;
sign = (diff < 0) ? 8 : 0;
if (sign != 0) diff = (-diff);

/* Step 2 - Divide and clamp */
/* Note:
** This code *approximately* computes:
** delta = diff*4/step;
** vpdiff = (delta+0.5)*step/4;
** but in shift step bits are dropped. The net result of this is
** that even if you have fast mul/div hardware you cannot put it to
** good use since the fixup would be too expensive.
*/
delta = 0;
vpdiff = (step >> 3);

if (diff >= step)
{
delta = 4;
diff -= step;
vpdiff += step;
}
step >>= 1;
if (diff >= step)
{
delta |= 2;
diff -= step;
vpdiff += step;
}
step >>= 1;
if (diff >= step)
{
delta |= 1;
vpdiff += step;
}

/* Step 3 - Update previous value */
if (sign != 0)
valpred -= vpdiff;
else
valpred += vpdiff;

/* Step 4 - Clamp previous value to 16 bits */
if (valpred > short.MaxValue)
valpred = short.MaxValue;
else if (valpred < short.MinValue)
valpred = short.MinValue;

/* Step 5 - Assemble value, update index and step values */
delta |= sign;

index += indexTable[delta];
if (index < 0) index = 0;
if (index > 88) index = 88;
step = stepsizeTable[index];

/* Step 6 - Output value */
if (bufferstep)
{
outputbuffer = (delta << 4) & 0xf0;
}
else
{
outBuff.WriteByte((byte)((delta & 0x0f) | outputbuffer));
}
bufferstep = !bufferstep;
}
bufferstep = !bufferstep;
}

/* Output last step, if needed */
Expand Down
2 changes: 1 addition & 1 deletion ImaAdpcm-Encoder-Decoder/ProgramFunctions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ internal static void ExecuteEncoder(string inputFile, string outputFile)
internal static void ExecuteDecoder(string inputFile, string outputFile, int sampleRate)
{
string fileExtension = Path.GetExtension(inputFile);
if (fileExtension.Equals(".wav", StringComparison.OrdinalIgnoreCase) || fileExtension.Equals(".ima", StringComparison.OrdinalIgnoreCase))
if (fileExtension.Equals(".wav", StringComparison.OrdinalIgnoreCase) || fileExtension.Equals(".ima", StringComparison.OrdinalIgnoreCase) || fileExtension.Equals(".raw", StringComparison.OrdinalIgnoreCase))
{
byte[] imaData = File.ReadAllBytes(inputFile);

Expand Down

0 comments on commit 50793f4

Please sign in to comment.