Up Sampling 44.1 to 88.2 and Sinc interpolation 36 point

Share your advanced PureBasic knowledge/code with the community.
User avatar
oryaaaaa
Addict
Addict
Posts: 825
Joined: Mon Jan 12, 2004 11:40 pm
Location: Okazaki, JAPAN

Up Sampling 44.1 to 88.2 and Sinc interpolation 36 point

Post by oryaaaaa »

Hello.

Binaly Download ( Max 20min / MP3 only)
http://purebasic.coolverse.jp/_userdata/MP3_PLAY.zip


Need 96kHz external DAC or 96kHz Line out Sounds card

AND

Very high quality headphone or Very high quality speaker


Example headphone... SENNHEISER HD-650
DAC... 192kHz DAC Headphone Amplifer

hehehe 8-)

1. 44.1kHz Streo Wave to 88.2kHz Streo Wave
Insert Zero
2.Sinc interpolation 36 point
Creating Data

Could you optimize more faster? Thank you

and... I have to create LPF (FIR filter). hehehe

Releation Topic
MP3 Encoder and Decorder
viewtopic.php?f=12&t=16891
DirectSound Stream Playing
viewtopic.php?f=12&t=20841

Code: Select all

Procedure.w SincInterpolation(*BufferAudio, pos.l)
  Protected pcmdata2.d
  *BufferAudio+pos -76 ; -76
  pcmdata2 + PeekW(*BufferAudio)*-0.00440808432177
  *BufferAudio + 4 ; -72
  pcmdata2 + PeekW(*BufferAudio)*0.00556328473613
  *BufferAudio + 4 ; -68
  pcmdata2 + PeekW(*BufferAudio)*-0.0057079186663
  *BufferAudio + 4 ; -64
  pcmdata2 + PeekW(*BufferAudio)*0.00469026016071
  *BufferAudio + 4 ; -60
  pcmdata2 + PeekW(*BufferAudio)*-0.00256317574531
  *BufferAudio + 4 ; -56
  pcmdata2 + PeekW(*BufferAudio)*-0.00040220390656
  *BufferAudio + 4 ; -52
  pcmdata2 + PeekW(*BufferAudio)*0.00373957841657
  *BufferAudio + 4 ; -48
  pcmdata2 + PeekW(*BufferAudio)*-0.00684468308464
  *BufferAudio + 4 ; -44
  pcmdata2 + PeekW(*BufferAudio)*0.0090610217303
  *BufferAudio + 4 ; -40
  pcmdata2 + PeekW(*BufferAudio)*-0.00978076830506
  *BufferAudio + 4 ; -36
  pcmdata2 + PeekW(*BufferAudio)*0.00854528136551
  *BufferAudio + 4 ; -32
  pcmdata2 + PeekW(*BufferAudio)*-0.00512989936396
  *BufferAudio + 4 ; -28
  pcmdata2 + PeekW(*BufferAudio)*-0.00040235937922
  *BufferAudio + 4 ; -24
  pcmdata2 + PeekW(*BufferAudio)*0.00768743222579
  *BufferAudio + 4 ; -20
  pcmdata2 + PeekW(*BufferAudio)*-0.01609098725021
  *BufferAudio + 4 ; -16
  pcmdata2 + PeekW(*BufferAudio)*0.02478164248168
  *BufferAudio + 4 ; -12
  pcmdata2 + PeekW(*BufferAudio)*-0.03283505514264
  *BufferAudio + 4 ; -8
  pcmdata2 + PeekW(*BufferAudio)*0.03935587778687
  *BufferAudio + 4 ; -4
  pcmdata2 + PeekW(*BufferAudio)*-0.04359867796302
  *BufferAudio + 4
  pcmdata2 + PeekW(*BufferAudio)
  *BufferAudio + 4 ; 4
  pcmdata2 + PeekW(*BufferAudio)*-0.04359867796302 
  *BufferAudio + 4 ; 8
  pcmdata2 + PeekW(*BufferAudio)*0.03935587778687
  *BufferAudio + 4 ; 12
  pcmdata2 + PeekW(*BufferAudio)*-0.03283505514264
  *BufferAudio + 4 ; 16
  pcmdata2 + PeekW(*BufferAudio)*0.02478164248168
  *BufferAudio + 4 ; 20
  pcmdata2 + PeekW(*BufferAudio)*-0.01609098725021
  *BufferAudio + 4 ; 24
  pcmdata2 + PeekW(*BufferAudio)*0.00768743222579
  *BufferAudio + 4 ; 28
  pcmdata2 + PeekW(*BufferAudio)*-0.00512989936396
  *BufferAudio + 4 ; 32
  pcmdata2 + PeekW(*BufferAudio)*0.00854528136551
  *BufferAudio + 4 ; 36
  pcmdata2 + PeekW(*BufferAudio)*-0.00978076830506
  *BufferAudio + 4 ; 40
  pcmdata2 + PeekW(*BufferAudio)*0.0090610217303
  *BufferAudio + 4 ; 44
  pcmdata2 + PeekW(*BufferAudio)*-0.00684468308464
  *BufferAudio + 4 ; 48
  pcmdata2 + PeekW(*BufferAudio)*0.00373957841657
  *BufferAudio + 4 ; 52
  pcmdata2 + PeekW(*BufferAudio)*-0.00040220390656
  *BufferAudio + 4 ; 56
  pcmdata2 + PeekW(*BufferAudio)*-0.00256317574531
  *BufferAudio + 4 ; 60
  pcmdata2 + PeekW(*BufferAudio)*0.00469026016071
  *BufferAudio + 4 ; 64
  pcmdata2 + PeekW(*BufferAudio)*-0.0057079186663
  *BufferAudio + 4 ; 68
  pcmdata2 + PeekW(*BufferAudio)*0.00556328473613
  *BufferAudio + 4 ; 72
  pcmdata2 + PeekW(*BufferAudio)*-0.00440808432177
  
  ProcedureReturn Int(pcmdata2)
EndProcedure

Procedure upFreqWav(*BufferAudio, buflen.l)
  Protected I.l, *clearmem, *memory_buf
  *memory_buf = *BufferAudio
  buflen = buflen/2
  *clearmem = AllocateMemory(8)
  SetGadgetAttribute(1, #PB_ProgressBar_Minimum, 1)
  SetGadgetAttribute(1, #PB_ProgressBar_Maximum, buflen/1000)
  
  For I =buflen-76 To 77 Step -4
    CopyMemory(*clearmem, *memory_buf+I*2 -4, 8)
    CopyMemory(*BufferAudio+I, *memory_buf+I*2 , 4)
    PokeW(*memory_buf+I*2-4, SincInterpolation(*BufferAudio, I))
    PokeW(*memory_buf+I*2-2, SincInterpolation(*BufferAudio, I+2))
  Next
  FreeMemory(*clearmem)
EndProcedure

  size.l =MemorySize(*AudioBuffer_Raw)*2
  *AudioBuffer_Raw = ReAllocateMemory(*AudioBuffer_Raw, size)
  upFreqWav(*AudioBuffer_Raw, size)
;  DXSound(*AudioBuffer_Raw+size, 2)
KarLKoX
Enthusiast
Enthusiast
Posts: 681
Joined: Mon Oct 06, 2003 7:13 pm
Location: France
Contact:

Re: Up Sampling 44.1 to 88.2 and Sinc interpolation 36 point

Post by KarLKoX »

Nice :!:
You can find my 16 points FIR sinc interpolation with sse2 optimisations on my blog :)
"Qui baise trop bouffe un poil." P. Desproges

http://karlkox.blogspot.com/
User avatar
oryaaaaa
Addict
Addict
Posts: 825
Joined: Mon Jan 12, 2004 11:40 pm
Location: Okazaki, JAPAN

Re: Up Sampling 44.1 to 88.2 and Sinc interpolation 36 point

Post by oryaaaaa »

Thank you very much :D

I design LPF Digital Filter N=1024, HammingWindow, fs=0.49999.
but this lpf data triming to N=64 only, Because Heavy process....

Code: Select all

Procedure FirFilter(buflen.l) ; LP-both, and Global *men is AudioBuffer
  Protected pcmdata2.d, pcmdata3.d, I.l
  Protected *BufferAudio_tmp, *BufferAudio
  *BufferAudio_tmp = *mem
  For I=132 To buflen-8  Step 8
     *BufferAudio = *BufferAudio_tmp+I- 132;1020

    .....

    *BufferAudio + 2 ; -24
    pcmdata3 + PeekW(*BufferAudio)*0.0000157944
    *BufferAudio + 2 ; -24
    pcmdata2 + PeekW(*BufferAudio)*-0.0000157745
    *BufferAudio + 2 ; -20
    pcmdata3 + PeekW(*BufferAudio)*-0.0000157745
    *BufferAudio + 2 ; -20
    pcmdata2 + PeekW(*BufferAudio)*0.0000157581
    *BufferAudio + 2 ; -16
    pcmdata3 + PeekW(*BufferAudio)*0.0000157581
    *BufferAudio + 2 ; -16
    pcmdata2 + PeekW(*BufferAudio)*-0.0000157451
    *BufferAudio + 2 ; -12
    pcmdata3 + PeekW(*BufferAudio)*-0.0000157451
    *BufferAudio + 2 ; -12
    pcmdata2 + PeekW(*BufferAudio)*0.0000157355
    *BufferAudio + 2 ; -8
    pcmdata3 + PeekW(*BufferAudio)*0.0000157355
    *BufferAudio + 2 ; -8
    pcmdata2 + PeekW(*BufferAudio)*-0.0000157293
    *BufferAudio + 2 ; -4
    pcmdata3 + PeekW(*BufferAudio)*-0.0000157293
    *BufferAudio + 2 ; -4
    pcmdata2 + PeekW(*BufferAudio)*0.0000157265
    *BufferAudio + 2 ; 0
    pcmdata3 + PeekW(*BufferAudio)*0.0000157265
    
    PokeW(*BufferAudio_tmp+I, Int(pcmdata2))
    PokeW(*BufferAudio_tmp+I+2, Int(pcmdata3))
  Next
EndProcedure
binaly Max 20min MP3 or WAV (44.1kHz 16bit), out 96kHz
http://purebasic.coolverse.jp/bbs/downl ... e.php?id=9
User avatar
oryaaaaa
Addict
Addict
Posts: 825
Joined: Mon Jan 12, 2004 11:40 pm
Location: Okazaki, JAPAN

Re: Up Sampling 44.1 to 88.2 and Sinc interpolation 36 point

Post by oryaaaaa »

SSE2 Optimized code
*Change Sinc Table 16bit to 32bit
*Change Sampling point 36 to 128

Code: Select all

#SincSample = 64
Global *sinc_table = AllocateMemory(#SincSample*100)
Global *buffer_audio_part = AllocateMemory(#SincSample*48)
Procedure CreateSincTable(sample.l)
  #PI_64 = 3.1415926535897932385
  Protected I.l
  For I=-sample To sample
    If I = 0
      PokeD(*sinc_table+(I+sample)*8, 1.0);0000000000)  
    Else
      PokeD(*sinc_table+(I+sample)*8, Sin(#PI_64*#PI_64*(I))/(#PI_64*#PI_64*(I)));0000000000) 
    EndIf
    Debug PeekD(*sinc_table+(I+sample)*8)
  Next
EndProcedure
CreateSincTable(#SincSample) 
CallDebugger

Procedure SincInterpolation(*BufferAudio.Long, pos.l, *Out_BufferAudio)
  Protected pcmdata2.d, *sinc_table_ptr, pcmdata1.d
  Protected db.d = 1.0
  *BufferAudio+pos  ; -76
  
  pcmdata2 = #Null
  *pcmdata_ptr = @pcmdata2
  *out_buffer_ptr = *Out_BufferAudio
  *buffer_audio_ptr = *buffer_audio_part
  *sinc_table_ptr = *sinc_table
  For I=-#SincSample To #SincSample
    pcmdata1 = PeekW(*BufferAudio+I*4)
    PokeD(*buffer_audio_ptr+I*16, pcmdata1)
    pcmdata1 = PeekW(*BufferAudio+I*4+2)
    PokeD(*buffer_audio_ptr+I*16+8, pcmdata1)
  Next
  
  !MOV Esi, [p.p_sinc_table_ptr]
  !MOV Edi, [p.p_buffer_audio_ptr]
  !MOV Ebx, [p.p_pcmdata_ptr]
  !MOV Edx, [p.p_out_buffer_ptr]
  !PXOR xmm4, xmm4
  !PXOR xmm5, xmm5
  
  For I=0 To #SincSample*2
    !PXOR xmm3, xmm3 ; R
    !PXOR xmm1, xmm1 ; L
    !MOVUPS xmm1, [Edi] ; L 
    !ADD Edi,8
    !MOVUPS xmm3, [Edi] ; R
    
    !PXOR xmm0, xmm0 ; sinc
    !PXOR xmm2, xmm2 ; sinc
    !MOVUPS xmm0, [Esi] ; sinc
    !MOVUPS xmm2, xmm0
    
    !mulpd xmm1, xmm0 ; sinc x L
    !mulpd xmm3, xmm0 ; sinc x R
    
     !ADDPD xmm4, xmm1 ; pcmdata2 L ++
     !ADDPD xmm5, xmm3 ; pcmdata2 R ++   
     
    !ADD Esi, 8 ; sinc double table
    !ADD Edi, 8 ;  
  Next
  !MOVUPS [Ebx], xmm4
  PokeW(*Out_BufferAudio,Int(PeekD(*pcmdata_ptr)))
  !MOVUPS [Ebx], xmm5
  PokeW(*Out_BufferAudio+2, Int(PeekD(*pcmdata_ptr)))
EndProcedure

Procedure upFreqWav(*BufferAudio, buflen.l)
  Protected I.l, *clearmem, *memory_buf 
  *memory_buf = *BufferAudio
  buflen = buflen/2 
  For I =buflen-(#SincSample*15) To (#SincSample*15+1) Step -4
    FillMemory(*memory_buf+I*2 -4, 8, 0)
    CopyMemory(*BufferAudio+I, *memory_buf+I*2 , 4)
    SincInterpolation(*BufferAudio, I, *memory_buf+I*2-4)
  Next
EndProcedure
ADD

Hello, Could you optimize this code by FASM? please.

Code: Select all

Procedure Word2Double2(*in, len, *out)
  Protected Data1.d, pos.l
  For pos=0 To len
    Data1 = PeekW(*in)
    PokeD(*out, Data1)
    *in +2 :  *out +8
    Data1 = PeekW(*in)
    PokeD(*out, Data1)
    *in +6 :  *out +8
  Next
EndProcedure
User avatar
oryaaaaa
Addict
Addict
Posts: 825
Joined: Mon Jan 12, 2004 11:40 pm
Location: Okazaki, JAPAN

MP3 only 96kHz Sinc 128pt Double Process

Post by oryaaaaa »

MP3 44.1kHz Only, Max 20min, SSE2 CPU, 96kHz Output
http://purebasic.coolverse.jp/bbs/downl ... .php?id=13

This spec
MP3 44.1kHz to 88.2kHz Up sampling and Sinc interpolation 128 point (64bit Process & SSE2 FASM)
DirectSound 32bit Float Output

Ofcource, WAV better than MP3.

Benchmark

MP3 7min 16MB (include ACM Decode Process)
CPU::Core 2 Duo 3.0GHz (45n ... iMac 24")

32bit Float Output 25 sec
16bit word Output 165 sec ( ++ 64tap LPF ).... LPF SSE2 programming is very difficult.

Thank you reading.
User avatar
oryaaaaa
Addict
Addict
Posts: 825
Joined: Mon Jan 12, 2004 11:40 pm
Location: Okazaki, JAPAN

Re: Up Sampling 44.1 to 88.2 and Sinc interpolation 36 point

Post by oryaaaaa »

Sinc interpolation 128 point by SSE2

Code: Select all

Procedure SincInterpolation(*buffer_audio_ptr, *sinc_table_ptr, *out_buffer_ptr)
  !PUSH Esi
  !PUSH Edi
  !MOV Esi, [p.p_sinc_table_ptr]
  !MOV Edi, [p.p_buffer_audio_ptr]
  !PXOR xmm4, xmm4
  !PXOR xmm5, xmm5 
  !MOV    Ecx,128
  !MOV    Edx,0
  !_For1:
  !MOV    Eax,Edx
  !CMP    Eax,Ecx
  !JL    _Next1
  !JO    _Next1
  !PXOR xmm3, xmm3 ; R
  !PXOR xmm1, xmm1 ; L
  !PXOR xmm0, xmm0 ; sinc
  !MOVUPS xmm0, [Esi] ; sinc 
  !ADD Esi, 8 ; sinc double table
  !MOVUPS xmm1, [Edi] ; L
  !ADD Edi,4
  !MOVUPS xmm3, [Edi] ; R
  !ADD Edi,4 ;12 ;  
  !CVTPS2PD xmm1, xmm1
  !CVTPS2PD xmm3, xmm3
  !mulpd xmm1, xmm0 ; sinc x L
  !mulpd xmm3, xmm0 ; sinc x R 
  !ADDPD xmm4, xmm1 ; pcmdata2 L ++
  !ADDPD xmm5, xmm3 ; pcmdata2 R ++
  !INC Edx
  !JMP   _For1
  !_Next1:
  !CVTPD2PS xmm4, xmm4
  !CVTPD2PS xmm5, xmm5
  !MOV Esi, $0FFFFFFFF
  !MOV Edi, [p.p_out_buffer_ptr]
  !PXOR xmm2, xmm2
  !MOVD xmm2, Esi
  !PAND xmm4, xmm2
  !PAND xmm5, xmm2
  !MOVUPS [Edi], xmm4
  !MOVUPS [Edi+4], xmm5
  !POP Edi
  !POP Esi
EndProcedure
Post Reply