TransPCM—use Float16/24 to reduce bit-depth, also promotes compression, 2012-05-29: beta v0.1.1 / formerly HalfPrecision / ref.: IEEE 754-2008 |
TransPCM—use Float16/24 to reduce bit-depth, also promotes compression, 2012-05-29: beta v0.1.1 / formerly HalfPrecision / ref.: IEEE 754-2008 |
Sep 12 2011, 22:03
Post
#1
|
|
![]() lossyWAV Developer Group: Developer Posts: 1722 Joined: 11-April 07 From: Wherever here is Member No.: 42400 |
When I first became aware of the Float16 type I found it interesting in terms of maybe having potential as a possible lossy storage type.
Attached is a processed version of the sample in this thread which has been decoded back to PCM. The processing is as follows (at this stage as there is no player that I am aware of): Input file Sample [PCM] > FLOAT16 > [PCM] > Output File. The conversion from integer to Float16 reduces the number of significant bits of the 24-bit sample to (a maximum of) 11. There is therefore an amount of added noise due to truncation. The added noise has been noise shaped using SG's adaptive noise shaping method as used in lossyWAV. Original Sample If the 24-bit coded sample is encoded with FLAC (wFormatTag left as 0x0001 as FLAC does not handle Floating Point samples and wBitsPerSample is left as 24) there is a saving of in excess of 20% in filesize. I don't see any practical advantage using this storage type for native 16-bit PCM. This post has been edited by Nick.C: May 29 2012, 21:36 -------------------- lossyWAV -q X | FLAC -8 ~= 308kbps
SGS III (Rooted) + 64GB |
|
|
|
![]() |
Sep 22 2011, 13:05
Post
#2
|
|
![]() lossyWAV Developer Group: Developer Posts: 1722 Joined: 11-April 07 From: Wherever here is Member No.: 42400 |
Below is Delphi / IA32 & x87 code used to encode Double to Float16 and decode Float16 to Double (actually extended [80-bit] in this case). Hopefully someone will find it useful.
Compatibility at a player level would be a great starting point (i.e. simply playing a RIFF WAVE with wFormatTag=0x0003 and wBitsPerSample=0x0010). CODE //============================================================================== [edit] Code update. [/edit]
// // Float16 encode / decode functions; // // 2011 Nick Currie // //============================================================================== Type Float16 = Word; SingleRec = Packed Record Case Integer of 1:(Single : Single); 2:(Integer : Integer); 3:(Words : Array[0..1] of Word); 4:(BytePx : Byte; WordP1 : Word;); 5:(Bytes : Array[0..3] of Byte); End; DoubleRec = Packed Record Case Integer of 1:(Double : Double); 2:(Int64 : Int64); 3:(Integers : Array[0..1] of Integer); 4:(Words : Array[0..3] of Word); 5:(BytePx : Byte; WordP1,WordP3,WordP5 : Word;); 6:(Bytes : Array[0..7] of Byte); End; ExtendedRec = Packed Record Case Integer of 1:(Extended : Extended); 2:(Int64 : Int64); 3:(Integers : Array[0..1] of Integer); 4:(Words : Array[0..4] of Word); 5:(Bytes : Array[0..9] of Byte); End; Var Powersof = Packed Record two : array[-1024..1023] of Double; End; {$IFNDEF USEASM} //============================================================================ Function F80_to_F16(F80_Value : Extended) : Float16; //============================================================================ Var Exponent : Integer; Sign : Word; Begin //============================================================================ Sign:=ExtendedRec(F80_Value).Words[4] and $8000; If (F80_Value=0) then F80_to_F16:=Sign else Begin Exponent:=(ExtendedRec(F80_Value).Words[4] and $7FFF)-$3FFF; ExtendedRec(F80_Value).Words[4]:=ExtendedRec(F80_Value).Words[4] or $3FFF; if Exponent>15 then F80_to_F16:=Sign or $7C00 else If (Exponent>-15) then F80_to_F16:=(Sign or ((Exponent+15) shl 10) or ((ExtendedRec(F80_Value).Words[3] and $7FFF) shr 5)) else if Exponent>-25 then F80_to_F16:=(Sign or (ExtendedRec(F80_Value).Words[3] shr (-Exponent-9))) else F80_to_F16:=Sign; End; //============================================================================ End; //============================================================================ {$ELSE} //============================================================================ Function F80_to_F16(F80_Value : Extended) : Float16; Assembler; //============================================================================ asm push ecx push edx xor eax,eax xor edx,edx mov cx,word ptr F80_Value+8 mov dh,ch and dh,$80 and cx,$7FFF jz @@EX sub cx,$3FFF cmp cx,-$19 jle @@EX mov ah,$7C cmp cx,$10 jge @@EX @@01: mov ax,word ptr F80_Value+6 cmp cx,-$0F jg @@02 neg cl sub cl,$09 shr eax,cl jmp @@EX @@02: add cl,$0F shr ax,$05 shl cl,$02 and ax,$03FF or ah,cl @@EX: or ax,dx pop edx pop ecx End; //============================================================================ {$ENDIF} {$IFNDEF USEASM} //============================================================================ Function F64_to_F16(F64_Value : Double) : Float16; //============================================================================ Var Exponent : Integer; Sign : Word; Begin //============================================================================ DoubleRec(F64_Value).Double:=F64_Value; Sign:=DoubleRec(F64_Value).Words[3] and $8000; If (F64_Value=0) then F64_to_F16:=Sign else Begin Exponent:=(((DoubleRec(F64_Value).Words[3] and $7FF0) shr 4)-$3FF); DoubleRec(F64_Value).Words[3]:=((DoubleRec(F64_Value).Words[3] and $000F) or $3FF0); if Exponent>15 then F64_to_F16:=Sign or $7C00 else If (Exponent>-15) then F64_to_F16:=(Sign or ((Exponent+15) shl 10) or ((DoubleRec(F64_Value).WordP5 shr 2) and $3FF)) else if Exponent>-25 then F64_to_F16:=(Sign or (((DoubleRec(F64_Value).WordP5 or $1000) and $1FFE) shr (-Exponent-12))) else F64_to_F16:=Sign; End; //============================================================================ End; //============================================================================ {$ELSE} //============================================================================ Function F64_to_F16(F64_Value : Double) : Float16; Assembler; //============================================================================ asm push ecx push edx xor edx,edx xor eax,eax mov cx,word ptr F64_Value+6 mov dh,ch and dh,$80 and cx,$7FF0 jz @@EX shr cx,4 sub cx,$3FF cmp cx,-$19 jle @@EX mov ah,$7C cmp cx,$10 jge @@EX @@01: mov ax,word ptr F64_Value+5 shr ax,2 and ax,$03FF cmp cx,-$0F jg @@02 or ah,$04 neg cl and ax,$07FF sub cl,14 shr eax,cl jmp @@EX @@02: add cl,15 shl cl,2 or ah,cl @@EX: or ax,dx pop edx pop ecx End; //============================================================================ {$ENDIF} {$IFNDEF USEASM} //============================================================================ Function F16_to_F80(F16_Value : Float16) : Extended; //============================================================================ Begin //============================================================================ if F16_Value and $8000<>0 then Begin if ((F16_Value and $7FFF)=0) then F16_to_F80:=-0 else if ((F16_Value and $7C00)=0) then F16_to_F80:=-(F16_Value and $3FF)*powersof.two[-24] else F16_to_F80:=-((F16_Value and $3FF) or $400)*powersof.two[((F16_Value shr 10) and $1F)-25] End else Begin if F16_Value=0 then F16_to_F80:=0 else if ((F16_Value and $7C00)=0) then F16_to_F80:=(F16_Value and $3FF)*powersof.two[-24] else F16_to_F80:=((F16_Value and $3FF) or $400)*powersof.two[((F16_Value shr 10) and $1F)-25] End; //============================================================================ End; //============================================================================ {$ELSE} //============================================================================ Function F16_to_F80(F16_Value : Float16) : Extended; //============================================================================ asm push ecx push edx movzx eax,F16_Value mov dl,ah and ax,$7FFF jnz @@01 fldz jmp @@EX @@01: fld1 test dl,$80 jz @@02 fchs @@02: mov ecx,eax and ax,$3FF shr cx,10 mov edx,1000 push eax and cl,$1F jz @@03 or word ptr [esp],$400 mov dx,999 add dx,cx @@03: fimul dword ptr [esp] fmul qword ptr powersof.two[edx*double_size] @@04: pop eax @@EX: pop edx pop ecx //============================================================================ End; //============================================================================ {$ENDIF} This post has been edited by Nick.C: Oct 27 2011, 07:26 -------------------- lossyWAV -q X | FLAC -8 ~= 308kbps
SGS III (Rooted) + 64GB |
|
|
|
Nick.C TransPCM—use Float16/24 to reduce bit-depth, also promotes compression Sep 12 2011, 22:03
AndyH-ha This differs from simply reducing the bit depth? Sep 12 2011, 22:11
Nick.C Yes - in that values up to c. +/- 2^31 can still b... Sep 12 2011, 22:19
saratoga Isn't this pretty much what ADPCM does? Excep... Sep 12 2011, 22:32
C.R.Helmrich You mean a-Law/µ-Law?
Makes me wonder how many bi... Sep 12 2011, 23:05
bryant QUOTE (Nick.C @ Sep 12 2011, 14:03) Attac... Sep 13 2011, 06:13
Nick.C The plan was to simply set wFormatTag= 0x0003 and ... Sep 15 2011, 21:09
benski QUOTE (Nick.C @ Sep 15 2011, 16:09) The p... Sep 16 2011, 14:03
knutinh float16 could be very efficient on GPU hardware if... Sep 16 2011, 13:49
Nick.C I understand that currently players are rather unl... Sep 16 2011, 19:26
Nick.C HalfPrecision beta 0.0.2cd attached. [bugfix] [sup... Oct 20 2011, 12:53
Gumboot QUOTE (Nick.C @ Oct 20 2011, 11:53) NB: t... Dec 22 2011, 23:19
lvqcl foobar2000 1.1.9 beta1: "Implemented experime... Oct 22 2011, 10:54
Nick.C RE: TransPCM—use Float16/24 to reduce bit-depth, also promotes compression Oct 22 2011, 14:24
Nick.C HalfPrecision beta 0.0.2e attached [superseded]. F... Oct 24 2011, 18:23
pdq I once had an idea for how to encode audio data. T... Oct 24 2011, 19:29
Nick.C That would be one way of doing it. However sample ... Oct 24 2011, 21:02
Nick.C HalfPrecision beta 0.0.2f attached superseded .
... Nov 1 2011, 13:53
Nick.C HalfPrecision beta 0.0.2g attached. Superseded.
... Nov 10 2011, 13:41
Didjeridoo Nick.C Thank you for your innovation.
It remains t... Nov 11 2011, 11:36
Nick.C @Didjeridoo: Thanks - I am also looking forward to... Nov 11 2011, 23:05
Nick.C HalfPrecision beta 0.0.2h attached. Superseded
... Nov 14 2011, 21:22
Didjeridoo Nick.C I watch all the moves and develops
Is not... Nov 15 2011, 10:32
lvqcl QUOTE (Didjeridoo @ Nov 15 2011, 13:32) P... Nov 15 2011, 15:53
Ljubo44 Do you have any sample of command line for foobar. Nov 15 2011, 19:13
Nick.C HalfPrecision beta 0.0.2i attached. Superseded. F... Nov 15 2011, 20:05
Ljubo44 on 16/44,1 size is same after compress halfp.wav 1... Nov 15 2011, 21:24
Nick.C QUOTE (Ljubo44 @ Nov 15 2011, 20:24) ....... Nov 15 2011, 22:05
Ljubo44 You are right, I used foobar 1.1.9 to convert to f... Nov 15 2011, 22:37
Nick.C HalfPrecision beta 0.0.2j attached. Superseded.
... Nov 15 2011, 23:02
Nick.C HalfPrecision beta 0.1.0a attached. Superseded.
... Nov 17 2011, 14:20
Didjeridoo I hope the developers do not ignore innovation Nov 18 2011, 19:44
Nick.C foobar2000 1.1.10 beta 1 adds Float24 support - re... Nov 18 2011, 21:24
pompon QUOTE (Nick.C @ Sep 12 2011, 16:03) When ... Dec 5 2011, 06:37
FreaqyFrequency @pompon:
This is different from those coding sche... Dec 5 2011, 08:44
Nick.C Right then people - HalfPrecision needs a new name... Dec 22 2011, 20:34
Nick.C .... a surprise, yes, however as the standard has ... Dec 23 2011, 08:20
Gumboot Well, by "huge surprise" I mean "de... Dec 23 2011, 08:43
Nick.C It would surprise me if, when using any type of fl... Dec 23 2011, 09:01
Gumboot Well it's not really in its infancy. I includ... Dec 23 2011, 22:02
Nick.C I accept that the Float16 proposal must have been ... Dec 27 2011, 21:34
FreaqyFrequency I fear that I may need a little more clarification... Jan 9 2012, 05:48
Nick.C Hi there,
Using HalfPrecision to convert from 24-... Jan 9 2012, 20:05
FreaqyFrequency Thanks for the reply, Nick.
Looking at the Replay... Jan 10 2012, 03:36
Nick.C TransPCM beta v0.1.1 attached. Superseded
Chang... May 29 2012, 21:51
Nick.C TransPCM beta 0.1.2 attached.
Changelog:Modificat... Jun 2 2012, 13:57
Ljubo44 CODE/d /c C:\bin\TransPCM_beta_0.1.2... Jun 14 2012, 01:29
lvqcl QUOTE (Ljubo44 @ Jun 14 2012, 04:29) What... Jun 14 2012, 15:47
db1989 Why do you have switches before the executable? An... Jun 14 2012, 09:02
Nick.C The use of --stdinname %d is to tell the program w... Jun 14 2012, 17:47
Nick.C Rockbox now has added Float16 compatibility* - tha... Nov 24 2012, 23:15
saratoga No problem. Hope its useful to people. Nov 25 2012, 00:28![]() ![]() |
|
Lo-Fi Version | Time is now: 23rd May 2013 - 17:07 |