Solved

24 bit signed integer

Posted on 2001-08-18
13
1,538 Views
Last Modified: 2010-04-06
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
Comment
Question by:HorridMan
  • 4
  • 3
  • 3
  • +3
13 Comments
 
LVL 4

Accepted Solution

by:
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

by:ITugay
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

by:Hagen040798
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;

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;
  Stream.Read(Int32Rec(Result).Hi.Lo, SizeOf(Byte));
  Stream.Read(Int32Rec(Result).Lo.Hi, SizeOf(Byte));
  Stream.Read(Int32Rec(Result).Lo.Lo, SizeOf(Byte));
  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
 
LVL 4

Expert Comment

by:DMN
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

by:Hagen040798
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

by:HorridMan
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
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 2

Expert Comment

by:FrodoBeggins
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

by:HorridMan
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

by:HorridMan
ID: 6412108
See comment just posted.
0
 
LVL 4

Expert Comment

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

Expert Comment

by:Hagen040798
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

by:Hagen040798
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

by:geobul
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

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

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
This video discusses moving either the default database or any database to a new volume.
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

747 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now