Adaptive Differential Pulse Code Modulation

Everything else that doesn't fall into one of the other PB categories.
es_91
Enthusiast
Enthusiast
Posts: 242
Joined: Thu Jan 27, 2011 12:00 pm
Location: DE

Adaptive Differential Pulse Code Modulation

Post by es_91 »

Hi.

ADPCM uses 4 Bit to store adapted delta values. This leaves hiss in the audio compressed.

Is there maybe an 8 bit ADPCM codec out there to store the signal in better quality?

Regards,

es_91.
SeregaZ
Enthusiast
Enthusiast
Posts: 619
Joined: Fri Feb 20, 2009 9:24 am
Location: Almaty (Kazakhstan. not Borat, but Triple G)
Contact:

Re: Adaptive Differential Pulse Code Modulation

Post by SeregaZ »

who knows this format and know what do for playng this ADPCM? or like ADPCM?

i have some samples from console's game and probably i have table with values (ValleyBell or maybe it's just 0xF0 bytes and begins at 0x200):

Code: Select all

Offset      0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F

00000200   00 F9 FA FB FC FD FE FF  00 01 02 03 04 05 06 07    щъыьэюя        
00000210   00 F6 F8 FA FB FD FE FF  00 01 02 03 05 06 08 0A    цшъыэюя        
00000220   00 F0 F3 F6 F8 FA FC FE  00 02 04 06 08 0A 0D 10    руцшъью        
00000230   00 E9 ED F1 F5 F8 FB FE  00 02 05 08 0B 0F 13 17    йнсхшыю        
00000240   00 E2 E8 ED F1 F6 F9 FD  00 03 07 0A 0F 13 18 1E    винсцщэ        
00000250   00 DA E1 E8 EE F3 F8 FC  00 04 08 0D 12 18 1F 26    Ъбиоушь       &
00000260   00 D2 DB E3 EA F0 F6 FB  00 05 0A 10 16 1D 25 2E    ТЫгкрцы      %.
00000270   00 CA D4 DD E6 ED F4 FA  00 06 0C 13 1A 23 2C 36    КФЭжнфъ     #,6
00000280   00 C1 CD D8 E1 EA F2 F9  00 07 0E 16 1F 28 33 3F    БНШбктщ     (3?
00000290   00 B7 C5 D1 DD E7 F0 F8  00 07 10 19 23 2E 3A 48    ·ЕСЭзрш    #.:H
000002A0   00 AD BD CB D8 E3 EE F7  00 09 12 1C 28 35 43 52    ­ЅЛШгоч    (5CR
000002B0   00 A3 B5 C4 D3 E0 EC F6  00 0A 14 20 2D 3B 4B 5C    ЈµДУамц    -;K\
000002C0   00 98 AC BD CD DC E9 F5  00 0B 17 24 32 42 54 67    ˜¬ЅНЬйх   $2BTg
000002D0   00 8C A2 B6 C8 D8 E7 F4  00 0C 19 28 38 4A 5D 73    Њў¶ИШзф   (8J]s
000002E0   00 80 98 AE C2 D4 E4 F3  00 0D 1C 2C 3E 51 67 7F    Ђ˜®ВФду   ,>Qg
its look like table for ADPCM?

i am not understand this process... how to make it play? how to make some memory convert to PCM 8bit mono?

archive with samples: https://www.dropbox.com/s/aqqwzp3c91uoj ... e.zip?dl=1
they lay at 038, 039 and etc folders - .snd files. it is nohead data. and theory it is some kind of 4bit ADPCM. and probably 8700kbs.

if samples is 4bit - so data need to be read back to forward:
%0000xxxx - as first value
%xxxx0000 - as second value

so what formula for getting sound is? i am not understand. for DPCM this table have only 16 values, as 4bit - so every 4bit it was array index. but this case table is more bigger than 16 as 4 bit. how to know this formula?
SeregaZ
Enthusiast
Enthusiast
Posts: 619
Joined: Fri Feb 20, 2009 9:24 am
Location: Almaty (Kazakhstan. not Borat, but Triple G)
Contact:

Re: Adaptive Differential Pulse Code Modulation

Post by SeregaZ »

thanks, but too not understandible for me :)

i am solve my problem as last Terminator - by long way :) Comix Zone have same system, that Ooze have. Comix Zone not have test sfx sounds in options, but Ooze have. so idea was: take ADPCM samples, play it in that options of Ooze game and record VGM file from emulator (Fusion). then i am parse this VGM file and get from that normal 8bit sample. by this method i can extract all Ooze samples. then time is come of Comix Zone. idea was: find where lays longest sample of Ooze in a rom file. find him size value in a header. then take Comix Zone samples and copy it over original sample of Ooze and set new size in a header. then start emulator, play sample, record VGM, parse... by this way i am make this "decrypting" and finaly add this two games into my Online GEMS Database :) now this base can use by 2 games - Dune and Zombie Ate My Neighbors. i want to add for this Zero Tolerance too, but this game a little another, becouse it have probably 2 GEMS banks, not 1 as most of GEMS games. and i am cant to find this second.
User avatar
Olliv
Enthusiast
Enthusiast
Posts: 542
Joined: Tue Sep 22, 2009 10:41 pm

Re: Adaptive Differential Pulse Code Modulation

Post by Olliv »

This explain how to convert :
ADPCM --> PCM

Although you want to convert :
PCM --> ADPCM

I recommand you to study the 1st flow (from ADPCM to PCM) to get then ability to create the 2nd flow process (from PCM to ADPCM).

I do not know what is your level in PUREBASIC. In example : do you usually use arithmetic optimizing, or not? Et caetera...

I suggest you publish a source code in the 'coding questions' section.

In the 2 ways, such a converting consists in dispatching datas blocks to a large quantity of sub-blocks.

The reason for which I recommand you to study from ADPCM to PCM first is, it is a lightly simpler to extract ADPCM datas and use current sub-block tables to get PCM datas.

In the other way (from PCM to ADPCM) you have to create current sub-block tables. What is a lightly harder work.
ADPCM to PCM process wrote: [4bits data] pointing [16values table] pointing [88values table]
Here "pointing" means :

- calculate (see URL above)
- clamp
- point in the following table identifyed on the process above.
User avatar
Olliv
Enthusiast
Enthusiast
Posts: 542
Joined: Tue Sep 22, 2009 10:41 pm

Re: Adaptive Differential Pulse Code Modulation

Post by Olliv »

This http://www.cs.columbia.edu/~hgs/audio/dvi/ is more understandable ?
SeregaZ
Enthusiast
Enthusiast
Posts: 619
Joined: Fri Feb 20, 2009 9:24 am
Location: Almaty (Kazakhstan. not Borat, but Triple G)
Contact:

Re: Adaptive Differential Pulse Code Modulation

Post by SeregaZ »

this two games have two types of samples - this ADPCM and normal PCM. it sets by some flags for samples in a header. so creators of this games in 90s have a very small place for sound, that is why (i think) some of samples is ADPCM, some is usual PCM. now i have no this limit for size. so i can replace all ADPCM to PCM. emulators can play any size of rom-file. hardware probably will not play... but i have no flash... how it names... cartrige for check it. so i think PCM -> ADPCM not realy need for my case. now even we have no Ooze or Comix Zone builder for making romhacks. so now it have no sound-switching problem yet. maybe somewhen in a future and if size of file rom will be critical - i will start to dig this ADPCM more deeper.

about my level - it is a very low :) i am still not understand many things. and many of my ideas still didnt come true in a ready code :) for my Dune editor i want to map editor part, GEMS-tracker part, grafic editor part (mentats, herbs, units, buildings). now for editing need a lot of manualy work with hex editor, some not very userfriendly YY-Chr programm, some tyle map editors... and etc software. i want to make all in one and very simple. and in a progress of it - i am a little growup :) and i am like it - to know something new.
User avatar
Olliv
Enthusiast
Enthusiast
Posts: 542
Joined: Tue Sep 22, 2009 10:41 pm

Re: Adaptive Differential Pulse Code Modulation

Post by Olliv »

Ok... You give a second life to very old consoles games...

These links I give are my answer for ADPCM. Its coding is simple containing lists of pre-calculated constants.

I find this subject interesting and will request in the 'coding questions'.
User avatar
idle
Always Here
Always Here
Posts: 5096
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Adaptive Differential Pulse Code Modulation

Post by idle »

SeregaZ wrote: if samples is 4bit - so data need to be read back to forward:
%0000xxxx - as first value
%xxxx0000 - as second value

so what formula for getting sound is? i am not understand. for DPCM this table have only 16 values, as 4bit - so every 4bit it was array index. but this case table is more bigger than 16 as 4 bit. how to know this formula?
if you need to reverse bits or swap nibbles on a byte.

Code: Select all

Macro ReverseBitsByte(v) 
v = ((v >> 1) & $55) | ((v & $55) << 1);
v = ((v >> 2) & $33) | ((v & $33) << 2);
v = ((v >> 4) & $0F) | ((v & $0F) << 4);
EndMacro 

Macro SwapNibbles(v) 
 v = ((v >> 4) & $0F) | ((v & $0F) << 4)
EndMacro  

Global a.a = %10110110 

ReverseBitsByte(a)

Debug RSet(Bin(a,#PB_Unicode),8,"0") ; result 01101101

SwapNibbles(a) 

Debug RSet(Bin(a,#PB_Unicode),8,"0") ;result 11010110
Windows 11, Manjaro, Raspberry Pi OS
Image
SeregaZ
Enthusiast
Enthusiast
Posts: 619
Joined: Fri Feb 20, 2009 9:24 am
Location: Almaty (Kazakhstan. not Borat, but Triple G)
Contact:

Re: Adaptive Differential Pulse Code Modulation

Post by SeregaZ »

on our forum for bits operation used this code:

Code: Select all

Macro SetBit(Var, Bit)
  Var | (Bit)
EndMacro 
Macro ClearBit(Var, Bit)
  Var & (~(Bit))
EndMacro 
Macro TestBit(Var, Bit)
  Bool(Var & (Bit))
EndMacro
Macro NumToBit(Num)
  (1<<(Num))
EndMacro
Macro GetBits(Var, StartPos, EndPos)
  ((Var>>(StartPos))&(NumToBit((EndPos)-(StartPos)+1)-1))
EndMacro
about reverse - i dont know :) for DPCM case it was more understandible, then that this ADPCM case. DPCM is used for Mortal Combat 3 game and MK3 Ultimate and Punisher.

Code: Select all

Enumeration
  #SNDCFGFile
  #SNDSFXFile
  #SNDSampleImage
EndEnumeration

;{
Macro SetBit(Var, Bit)
  Var | (Bit)
EndMacro 
Macro ClearBit(Var, Bit)
  Var & (~(Bit))
EndMacro 
Macro TestBit(Var, Bit)
  Bool(Var & (Bit))
EndMacro
Macro NumToBit(Num) 
  (1<<(Num))
EndMacro
Macro GetBits(Var, StartPos, EndPos)
  ((Var>>(StartPos))&(NumToBit((EndPos)-(StartPos)+1)-1))
EndMacro
;}

;dc.b	 00H, 01H, 03H, 07H, 0DH, 15H, 1FH, 2BH
;dc.b	-00H,-01H,-03H,-07H,-0DH,-15H,-1FH,-2BH
Global Dim pikarray.b(15)
pikarray(0)  = 0
pikarray(1)  = 1
pikarray(2)  = 3
pikarray(3)  = 7
pikarray(4)  = $D
pikarray(5)  = $15
pikarray(6)  = $1F
pikarray(7)  = $2B
pikarray(8)  = 0
pikarray(9)  = -1
pikarray(10) = -3
pikarray(11) = -7
pikarray(12) = -$D
pikarray(13) = -$15
pikarray(14) = -$1F
pikarray(15) = -$2B

Procedure WavHeaderCreation(*memst)
  
 ;RIFF
 PokeB(*memst, $52):PokeB(*memst+1, $49):PokeB(*memst+2,$46):PokeB(*memst+3, $46)
    
 ;WAVE
 PokeB(*memst+8, $57):PokeB(*memst+9, $41):PokeB(*memst+10,$56):PokeB(*memst+11, $45)
    
 ;fmt
 PokeB(*memst+12, $66):PokeB(*memst+13, $6d):PokeB(*memst+14,$74):PokeB(*memst+15, $20) 
    
 ;header size
 PokeB(*memst+16, $10)
    
 ;PCM 01
 PokeB(*memst+20, $01)
    
 ;mono stereo
 PokeB(*memst+22, $01)
    
 ;1
 PokeB(*memst+32, $01)
    
 ;bit
 PokeB(*memst+34, $08)
        
 ;data    
 PokeB(*memst+36, $64)
 PokeB(*memst+37, $61)
 PokeB(*memst+38, $74)
 PokeB(*memst+39, $61)
  
EndProcedure

If ReadFile(0, "D:\sample_49.snd") 
  length = Lof(0)
  *sndsource = AllocateMemory(length)
  If *sndsource
    ReadData(0, *sndsource, length)
  EndIf
  CloseFile(0)
EndIf

If *sndsource
  *snddest = AllocateMemory(length*2+44)
  If *snddest
    WavHeaderCreation(*snddest)
    
    ;size
    PokeL(*snddest +  4, length*2+40)
    PokeL(*snddest + 40, length*2)
    ;kbs
    PokeL(*snddest + 24, 6500)
    PokeL(*snddest + 28, 6500)
    
    DPCMforwrite = $80 ; starting value
    
    For i = 0 To length - 1 ; -1 it is end of file? i dont remember
      inpval = PeekA(*sndsource+i)
      
      first  = GetBits(inpval, 0, 3) ; get %0000xxxx
      second = GetBits(inpval, 4, 7) ; get %xxxx0000

      DPCMforwrite + pikarray(first)
      PokeB(*snddest + 44 + (i*2), DPCMforwrite)
      
      DPCMforwrite + pikarray(second)
      PokeB(*snddest + 44 + (i*2) + 1, DPCMforwrite)
      
    Next
    
  EndIf
EndIf


sndPlaySound_(*snddest,#SND_MEMORY | #SND_ASYNC | #SND_NODEFAULT)

Delay(2000)

;If CreateFile(0, "D:\demo.wav")
;  WriteData(0, *snddest, length*2+44)
;  CloseFile(0)
;EndIf
original sample:
https://www.dropbox.com/s/xb5mukysib6wx ... 9.snd?dl=1
User avatar
Olliv
Enthusiast
Enthusiast
Posts: 542
Joined: Tue Sep 22, 2009 10:41 pm

Re: Adaptive Differential Pulse Code Modulation

Post by Olliv »

Good this code.

SND file format is an other format too.

Code: Select all

;PCM 01
PokeB(*memst+20, $01)
What I am sure for ADPCM is replace this above with :

Code: Select all

;ADPCM 17
PokeB(*memst+20, $11)
That is not a big code actually I give... :D
SeregaZ
Enthusiast
Enthusiast
Posts: 619
Joined: Fri Feb 20, 2009 9:24 am
Location: Almaty (Kazakhstan. not Borat, but Triple G)
Contact:

Re: Adaptive Differential Pulse Code Modulation

Post by SeregaZ »

.snd just custom extention for GEMS unpacked files. it have .raw - FM and PSG data for instruments, .sfx - header for sample with size and frequency flag, and etc values. .code - sequences data - notes, loops, pauses, durations.

this .snd can be normal 8bit mono, but same .snd can be this DPCM or ADPCM 4bit. frequency can be max quality as 10.4k.

in this code - DPCM sample converts into normal PCM, that is why PokeB(*memst+20, $01) for playing with winapi. but for my ugly-player i am not make this wav header. i am play it with special dll's procedure (this dll need to be fixed and it is not PB and i dont know where it have one small mistake). but this dll plays only normal PCM. if sample is DPCM or ADPCM - it need to be convert before. with DPCM i have formula, but for ADPCM is not. but, as i am say before - i am convert it by game it self and unpack normal PCM from VGM file. and now i am no need this ADPCM converting yet. but anyway this converting interesting things. i will study it too... someday... probably... maybe... :oops:

and this ADPCM, i think, not same as standart ADPCM. i think this table of values is custom case, not some windows standart, or wich one it is standart ADPCM. i think switching header flag will not help.
User avatar
Olliv
Enthusiast
Enthusiast
Posts: 542
Joined: Tue Sep 22, 2009 10:41 pm

Re: Adaptive Differential Pulse Code Modulation

Post by Olliv »

There is 3 versions of ADPCM

Code: Select all

a byte containing 2 quartets A B

7 6 5 4 3 2 1 0
a a a a b b b b
    A       B
1) reversed : read B before A
2) read A before B
3) read A and point it in a 16 pre-calculated values array, then read B and point it in the same 16 values array (telephony)

I think what, it interest us is the 2nd version. Maybe the 1st, but it is not very different.

http://www.cs.columbia.edu/~hgs/audio/dvi/

There are near 40 pages : could you read them, or not ? The image format can prevent you to have a good translating.

Page 34 gives an algo to convert 4 bits ADPCM to 16 bits PCM.

This can be inserted in your code. Note the 2 arrays to store earlier.
1) 16 values array is 'step index table'
2) 89 values array is 'step size table'

Note that, for each converting unit, the 16-bits final value is calculated as you writed above :

Code: Select all

final+stepSize
more accurately:

Code: Select all

For each ADPCM 4-bits value...

x = BitOp(x, ADPCM) ; procedure

step+stepIndex(x + ADPCM) ; 16 values array
step = saturate(step, 0, 15) ; procedure

Final+Stepsize(step) ; 89 values array
Final = saturate(Final, -32768, 32767)
PCM = final

next ADPCM value...
Excepted $11 format code instead of $1, the file header does not have more datas whatever we have PCM or ADPCM sound.
SeregaZ
Enthusiast
Enthusiast
Posts: 619
Joined: Fri Feb 20, 2009 9:24 am
Location: Almaty (Kazakhstan. not Borat, but Triple G)
Contact:

Re: Adaptive Differential Pulse Code Modulation

Post by SeregaZ »

i think final result must be 8bit, not 16. about documents - english not very mine language. and even worse - technical info. translate not very help.

original 4 bit data:

Code: Select all

Offset      0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F

00000000   01 9A BB 39 87 69 68 36  A4 88 4A BE EC 5D A7 94
converted 8 bit data

Code: Select all

Offset      0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F

00000000   80 81 83 86 89 83 84 84  83 81 82 80 80 7A 78 7A
00000010   75 75 75 70 72 75 7D 85  8A 87 8D 8F 8E 8F 8A 84
not clear for me, how to use that table with $F0 values from sound driver.
User avatar
Olliv
Enthusiast
Enthusiast
Posts: 542
Joined: Tue Sep 22, 2009 10:41 pm

Re: Adaptive Differential Pulse Code Modulation

Post by Olliv »

i think final result must be 8bit, not 16
We have a similar problem here : our english neighbours drive on the left in the road, as we drive in the right in the road in France...

You have 8 bits PCM certainly due to the age of the standard. That s all. And I forget to tell you this option must be set in the file header too.

But if we want to listen a sound on a recent hardware, we must consider first ADPCM provides 16 bits linear digit, and is provided by 16 bits linear digit.

ADPCM (4 bits) ---> PCM (16 bits)
PCM (16 bits) ---> ADPCM (4 bits)

It is only after these first flow converting you do a second converting level to transform 16 bits PCM to 8 bits PCM.

It is an other process to add.

Synthesis :

4 bits ADPCM <----> 16 bits PCM <----> 8 bits PCM

Algo references :
ADPCM (4 bits) ---> PCM (16 bits)
PCM (16 bits) ---> ADPCM (4 bits) (1/2)
PCM (16 bits) ---> ADPCM (4 bits) (2/2)
PCM (8 bits) ---> PCM (16 bits)
PCM (16 bits) ---> PCM (8 bits)
Post Reply