PortAudio for PB

Share your advanced PureBasic knowledge/code with the community.
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: PortAudio for PB

Post by wilbert »

SeregaZ wrote:yes. your code sounds better, but anyway have hiss.
For better quality you probably need to upsample to 16 bit / 22050 Hz (or 44100 Hz) and add a low pass filter.
Windows (x64)
Raspberry Pi OS (Arm64)
SeregaZ
Enthusiast
Enthusiast
Posts: 619
Joined: Fri Feb 20, 2009 9:24 am
Location: Almaty (Kazakhstan. not Borat, but Triple G)
Contact:

Re: PortAudio for PB

Post by SeregaZ »

probably false alarm. we start think it is some custom modification of GEMS driver. and probably it is ADPCM, not PCM. or maybe something else. probably i will lay as you procedure do. just for know how it sounds, without record options. cursed MK developers :) make so dificult for me :)
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: PortAudio for PB

Post by wilbert »

SeregaZ wrote:probably false alarm. we start think it is some custom modification of GEMS driver. and probably it is ADPCM, not PCM. or maybe something else. probably i will lay as you procedure do. just for know how it sounds, without record options. cursed MK developers :) make so dificult for me :)
Try this 4 to 16 bit conversion.

Code: Select all

Procedure PCM4to16(*src.Ascii, *dst.Unicode, cnt)
  Protected Dim vt.u(15)
  PokeQ(@vt(00),$0400020001000000)
  PokeQ(@vt(04),$4000200010000800)
  PokeQ(@vt(08),$FC00FE00FF008000)
  PokeQ(@vt(12),$C000E000F000F800)
  While cnt
    *dst\u = vt(*src\a&$f) : *dst+2
    *dst\u = vt(*src\a>>4) : *dst+2
    *src + 1 : cnt - 1
  Wend
EndProcedure

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, $10)
        
 ;data    
 PokeB(*memst+36, $64)
 PokeB(*memst+37, $61)
 PokeB(*memst+38, $74)
 PokeB(*memst+39, $61)
  
EndProcedure

inpval.b

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

If *sndsource
  *snddest = AllocateMemory(length*4+44)
  If *snddest
    WavHeaderCreation(*snddest)
    
    ;size
    PokeL(*snddest +  4, length*4+40)
    PokeL(*snddest + 40, length*4)
    ;kbs
    PokeL(*snddest + 24, 6500)
    PokeL(*snddest + 28, 6500)
    
    PCM4to16(*sndsource, *snddest+44, length)
    
  EndIf
EndIf


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

;Delay(5000)

If CreateFile(0, "D:\demo.wav")
  WriteData(0, *snddest, length*4+44)
  CloseFile(0)
EndIf
Windows (x64)
Raspberry Pi OS (Arm64)
SeregaZ
Enthusiast
Enthusiast
Posts: 619
Joined: Fri Feb 20, 2009 9:24 am
Location: Almaty (Kazakhstan. not Borat, but Triple G)
Contact:

Re: PortAudio for PB

Post by SeregaZ »

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

Re: PortAudio for PB

Post by SeregaZ »

ValleyBell get additional info. i am dont know any difference between PCM and any another PCMs, but maybe you will know what he talking about?
2017-07-02 22:45:20 ValleyBell http://vgmrips.net/misc/MK3_DACME.asm disassembled/commented DAC playback routines for MK3
2017-07-02 22:45:38 ValleyBell It allows for 8-bit LPCM or 4-bit DPCM.
2017-07-02 22:45:53 ValleyBell (DPCM, *not* ADPCM)
SeregaZ
Enthusiast
Enthusiast
Posts: 619
Joined: Fri Feb 20, 2009 9:24 am
Location: Almaty (Kazakhstan. not Borat, but Triple G)
Contact:

Re: PortAudio for PB

Post by SeregaZ »

probably i am start something understand... it have table (array):

Code: Select all

dc.b	 00H, 01H, 03H, 07H, 0DH, 15H, 1FH, 2BH
dc.b	-00H,-01H,-03H,-07H,-0DH,-15H,-1FH,-2BH
and that 4bit values 0 to 16 - it is not values them selves, it just array's index. i start get table values and write to file, but same hiss. and someone says about some delta. what a delta? i need write not table value, but something else? how to know sure this formula?

********
As for how the data is compressed, lemme explain that real quick: First, it is a lossy compression. So if you recompress a PCM sample this way, you will lose precision in data. Anyway, what happens is that each compressed data is seperated into nybbles (1 4-bit section of a byte). This first nybble of data is read, and used as an index to a table containing the following data: 0,1,2,4,8,$10,$20,$40,$80,$FF,$FE,$FC,$F8,$F0,$E0,$C0. So if the nybble were equal to F, it'd extract $C0 from the tale. If it were 8, it would extract $80 from the table. Etc. etc. Anyway, there is also another byte of data that we'll call 'd'. At the start of decompression, d is $80. What happens is that d is then added to the data extracted from the table using the nybble. So if the nybble were 4, the 8 would be extracted from the table, then added to d, which is $80, resulting in $88. This result is then put bank into d, then fed into the YM2612 for processing. Then the next nybble is read, the data is extracted from the table, then is added to d (remember, d is now changed because of the previous operation), then is put bank into d, then is fed into the YM2612. This process is repeated until the number of bytes as defined in the table above are read and decompressed.
not understand what i need do sure, but i start making +- array's values to base value $80

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
;}

;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

inpval.a
first.b
second.b
forwrite.b = $80

If ReadFile(0, "D:\Samples.bin")
  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)
    
    For i = 0 To length
      inpval = PeekA(*sndsource+i)
      
      first  = GetBits(inpval, 0, 3) ; get %0000xxxx
      second = GetBits(inpval, 4, 7) ; get %xxxx0000
      
      ;first  * 16
      ;second * 16
      ;first  = pikarray(first)
      ;second = pikarray(second)
      
      forwrite = forwrite + pikarray(first)      
      PokeB(*snddest+44+(i*2), forwrite)
      forwrite = forwrite + pikarray(second)
      PokeB(*snddest+45+(i*2), forwrite)
    Next
    
  EndIf
EndIf


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

;Delay(5000)

If CreateFile(0, "D:\demo.wav")
  WriteData(0, *snddest, length*2+44)
  CloseFile(0)
EndIf
but i think it is uncorrect too.

***********

probably problem was in a bank of samples. becouse this file have all samples at one file. it means delta comes from old sample to new one. it was wrong. samples need to play separately. by my opinion this tables can have special delta-reset value. now table have two "0" values - so one of them can be this my delta reset value...
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: PortAudio for PB

Post by wilbert »

It's a bit hard for me to understand what exactly is required.
I think it's something like the code below (based on my own previous code) but it probably still isn't 100% right.
If the link you quoted ( http://vgmrips.net/misc/MK3_DACME.asm ) is really the asm code from the game itself, you could try to port the z80 asm code to x86 asm code (they are a bit similar).

Code: Select all

Procedure.l limit(l.l)
  If l > 127
    ProcedureReturn 127
  ElseIf l < -128
    ProcedureReturn -128
  Else
    ProcedureReturn l
  EndIf
EndProcedure
  
Procedure PCM4to16(*src.Ascii, *dst.Byte, cnt)
  Protected Dim vt.b(15)
  Protected s.l
  PokeQ(@vt(00),$2b1f150d07030100)
  PokeQ(@vt(08),$d5e1ebf3f9fdff00)
  While cnt
    s + vt(*src\a&$f) : *dst\b = $80!limit(s) : *dst+1
    s + vt(*src\a>>4) : *dst\b = $80!limit(s) : *dst+1
    *src + 1 : cnt - 1
  Wend
EndProcedure

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)
    
 ;number of channels
 PokeB(*memst+22, $01)
    
 ;block align
 PokeB(*memst+32, $01)
    
 ;bits per sample
 PokeB(*memst+34, $08)
        
 ;data    
 PokeB(*memst+36, $64)
 PokeB(*memst+37, $61)
 PokeB(*memst+38, $74)
 PokeB(*memst+39, $61)
  
EndProcedure

inpval.b

If ReadFile(0, "D:\Samples.bin")
  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)
    ;sample rate
    PokeL(*snddest + 24, 6500)
    ; byte rate
    PokeL(*snddest + 28, 6500)
    
    PCM4to16(*sndsource, *snddest+44, length)
    
  EndIf
EndIf


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

;Delay(5000)

If CreateFile(0, "D:\demo.wav")
  WriteData(0, *snddest, length*2+44)
  CloseFile(0)
EndIf
Maybe some moderator should split this topic.
The last posts have nothing to do with PulseAudio.
Windows (x64)
Raspberry Pi OS (Arm64)
SeregaZ
Enthusiast
Enthusiast
Posts: 619
Joined: Fri Feb 20, 2009 9:24 am
Location: Almaty (Kazakhstan. not Borat, but Triple G)
Contact:

Re: PortAudio for PB

Post by SeregaZ »

why that? topic is PortAudio and we make this port audio from DPCM to PCM, that can understand PB :) or it was my bad language... port - it means porting?

about your code - when i am not understand code - i just belive :) only by practice i start to understand something. especially i was in shock, when you made PSG core code with ASM. it was dead end for me, but it work :) so i just belive.

about limit() - it is my failt. i use bank of samples at once. it means delta of old sample comes to new one - it can make this overlimits and scratch for sound.
Image
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: PortAudio for PB

Post by wilbert »

SeregaZ wrote:why that? topic is PortAudio and we make this port audio from DPCM to PCM, that can understand PB :) or it was my bad language... port - it means porting?
PortAudio is an open source cross platform library for streaming audio.
http://www.portaudio.com
This thread is about how to use that library. It's not about porting audio related code in general. :wink:
SeregaZ wrote:about limit() - it is my failt. i use bank of samples at once. it means delta of old sample comes to new one - it can make this overlimits and scratch for sound.
Image
If you don't have to worry about limiting values, you can simply start with $80 and add the values you look up.
The $80 is required because 8 bit audio is unsigned (values 0 - 255). For signed audio you would start out with 0.
Windows (x64)
Raspberry Pi OS (Arm64)
Post Reply