# 24 bit signed integer

I need to process PCM audio data (such as in .wav files) as 24 bit signed integers. Although longints hold the same range of values, the data would need to be interleaved with zeros every third byte - a computationally costly process. Does anyone have any sort of code or compiled unit out there to implement a 24 bit signed integer type? Can anyone give me pointers on how to do it?
###### Who is Participating?

x

Commented:
May be it's possible to convert 24bit to 32 bit and vise versa by multiply/divide it on 256?

Int32=Int24 shl 8;
Int24=Int32 shr 8;

A think it's quick enough and will give you additional precision in computations.

0

Commented:
DMN, good idea.
seems better way to use "SAL" and "SAR" assembler commands. Otherwise you will loose a sign of operand.
-----
Igor.
0

Commented:
Conversion between Int32 and Int24 is not realy needed. In fact Int24 are in range of Int32. Easily a over/underflow check from Int32 to Int24 should be doing by

const
MinInt32 = \$80000000;
MaxInt32 = \$7FFFFFFF;
MinInt24 = -\$00800000; (= \$00800000 in Int24 Range);
MaxInt24 = +\$007FFFFF; (= \$007FFFFF in Int24 Range);

function Int32ToInt24(Value: Integer): Integer;
begin
if Value > MaxInt24 then raise Overflow else
if Value < MinInt24 then raise Underflow;
Result := Value and \$00FFFFFF;
end;

function Int24ToInt32(Value: Integer): Integer;
begin
if Value and \$00800000 <> 0 then // sign Bit
Result := \$FF000000 or Value
else
Result := Value;
end;

function LoadInt24(Stream: TStream): Integer;
begin
Result := 0;
Stream.Read(Result, 3 * Sizeof(byte));
Result := Int24ToInt32(Result);
end;

procedure SaveInt24(Stream: TStream; Value: Integer);
begin
Value := Int32ToInt24(Value);
Stream.Write(Value, 3 * Sizeof(byte));
end;

Load/Save use Little Endian Byte order, in use of Intel like CPU's or Delphi Conversion.

Now for Big Endian meaning:

type
WordRec = packed record
Lo,Hi: Byte;
end;
Int32Rec = packed record
Lo,Hi: WordRec;
end;

function LoadInt24(Stream: TStream): Integer;
begin
Result := 0;
Result := Int24ToInt32(Result);
// or
Result := 0;
Stream.Read(Result, 3 * SizeOf(Byte));
asm // swap endianess in order to 2^24 Range
MOV   EAX,Result
BSWAP EAX
SAR   EAX,8         // -Values autom. expanded with \$FF
MOV   Result,EAX
end;
end;

function SaveInt24(Stream: TStream; Value: Integer): Integer;
begin
Value := Int32ToInt24(value);
Stream.Write(Int32Rec(Value).Hi.Lo, SizeOf(Byte));
Stream.Write(Int32Rec(Value).Lo.Hi, SizeOf(Byte));
Stream.Write(Int32Rec(Value).Lo.Lo, SizeOf(Byte));
Result := Int24ToInt32(Result);
// or
asm // swap endianess in order to 2^24 Range
MOV   EAX,Value
BSWAP EAX
SHR   EAX,8
MOV   Value,EAX
end;
Stream.Value(Value, 3 * SizeOf(Byte));
end;

All stuff are done as "Two Complemantary" Integer Types.

The suggestion of DNM is weak, because a division or multiplication would be change the real meaning of the Value. A mul/div as example of Int24(2) * Int24(2) = Int24(4) means same changes in ranges of Int32, Byte, Int64 etc.

Hagen
0

Commented:
Hm... So try to use that:

function to32(number:integer):integer; assembler;
asm
mov eax,number
shl eax,8
sar eax,8
end;

Or even you can use shortest version, because EAX already contains 'number' at funcion startup:

function to32(number:integer):integer; assembler;
asm
shl eax,8
sar eax,8
end;

Test it!
to32(\$007F0000)=\$007F0000,
to32(\$00800000)=\$FF800000

...
It's quick enough.
Hope this helps.
0

Commented:
@DNM

Yes, the second one is the probably fastest way. My comment should only deomstrate how to use Int24 with Int32 :)

as addition the Big Endian stuff

procedure RaiseUnderflow;
begin
raise Exception.Create('Int24 underflow');
end;

procedure RaiseOverflow;
begin
raise Exception.Create('Int24 overflow');
end;

procedure Int24Check(Value: Integer);
asm
CMP   EAX,MinInt24
JL    RaiseUnderflow
CMP   EAX,MaxInt24
JG    RaiseOverflow
end;

fucntion To32BigEndian(Value: Integer): Integer;
asm
CALL   Int24Check
BSWAP  EAX
SAR    EAX,8
end;

Hagen
0

Author Commented:
As I said, I'm not going to convert anything to a new format. That's precisely the thing I'm trying to avoid. I'm still eager to hear from anyone who has a serious answer to a SERIOUS PROBLEM.
Perhaps this question is too tough for 50 points, so I'll quadruple the value.... There. Now maybe someone who knows far, far more than me will really put their head to work on it. You want more points? I've got points to burn. Nominate your price and we'll see.
0

Commented:
Hey, HorridMan! It seems you're trying to build your own coputer. Or compiler, at least. The computer architcture is the one to give you NumberTypes. So, in Intel's you have Byte (8 bit) Word (16 bit), DWord (32 bit), QWord (64 bit) for Integers. Floating-point datatypes are up to 80 bit, using the coprocessor's/MMX 10 byte registers. But nothing 24bit. No 24 bit registers, no 24 bit datatype, no 24 bit operands and operators. Any OneAndHalfWord  will be conversion. I think Hagen and DMN gave you pretty SERIOUS ANSWERS.

In fact conversion is in practice even in the processor itself (since x86 came). Just think how you use 1MB (20 bit) memory space with 16 bit address registers in real mode :-)

Rgds,
Frodo
0

Author Commented:
Thank-you to everyone who contributed. Thank-you FrodoBeggins for your explanation. I think I'll have a go at using an array of three Bytes and typed pointers and do some arithmetic.
Seeing as I could not get the solution I wanted, I think it would be unfair on everyone else if I accepted one comment over another as an answer. I suppose its best to just delete the question. And thanks to everyone for assisting.

- Andrew Pingree.
0

Author Commented:
See comment just posted.
0

Commented:
O'kay. Increase the points, describe functions you wanna see and, may be...
0

Commented:
please remeber a 3 bytes memory access would be always slower as convertion to 32 Bit and back, because 32Bit CPUs works best with 32Bit Datas.

hagen
0

Commented:
please remeber a 3 bytes memory access would be always slower as convertion to 32 Bit and back, because 32Bit CPUs works best with 32Bit Datas.

hagen
0

Commented:
No comment has been added lately, so it's time to clean up this TA.
I will leave a recommendation in the Cleanup topic area that this question is:

split points between DMN and Hagen

Please leave any comments here within the next seven days.

PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!

Thanks,

geobul
EE Cleanup Volunteer
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.