Solved

# 24 bit signed integer

Posted on 2001-08-18
1,651 Views
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?
0
Question by:HorridMan
[X]
###### Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

• Help others & share knowledge
• Earn cash & points
• 4
• 3
• 3
• +3

LVL 4

Accepted Solution

DMN earned 100 total points
ID: 6399812
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

LVL 9

Expert Comment

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

LVL 2

Assisted Solution

Hagen040798 earned 100 total points
ID: 6400015
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;

begin
Result := 0;
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;

begin
Result := 0;
Result := Int24ToInt32(Result);
// or
Result := 0;
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

LVL 4

Expert Comment

ID: 6402064
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

LVL 2

Expert Comment

ID: 6403387
@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 Comment

ID: 6405053
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

LVL 2

Expert Comment

ID: 6405134
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 Comment

ID: 6412102
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 Comment

ID: 6412108
See comment just posted.
0

LVL 4

Expert Comment

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

LVL 2

Expert Comment

ID: 6414678
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

LVL 2

Expert Comment

ID: 6414909
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

LVL 17

Expert Comment

ID: 9286735
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

Thanks,

geobul
EE Cleanup Volunteer
0

## Featured Post

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi databaseâ€¦
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy reâ€¦
Six Sigma Control Plans
In a recent question (https://www.experts-exchange.com/questions/29004105/Run-AutoHotkey-script-directly-from-Notepad.html) here at Experts Exchange, a member asked how to run an AutoHotkey script (.AHK) directly from Notepad++ (aka NPP). This videoâ€¦
###### Suggested Courses
Course of the Month4 days, 14 hours left to enroll