Sinc interpolating

Bare metal programming in PureBasic, for experienced users
User avatar
oryaaaaa
Enthusiast
Enthusiast
Posts: 779
Joined: Mon Jan 12, 2004 11:40 pm
Location: Okazaki, JAPAN

Sinc interpolating

Post by oryaaaaa »

Code: Select all

Procedure SincInterpolation(*buffer_audio_ptr, *sinc_table_ptr, *out_buffer_ptr, *dummy)
  !XOR Ecx, Ecx
  !XOR Edx, Edx
  !MOV Ecx, [p.p_sinc_table_ptr]
  !MOV Edx, [p.p_buffer_audio_ptr]
  !SUB  Edx, 2048
  !PXOR xmm4, xmm4
  !PXOR xmm5, xmm5 
  For i=0 To 256
    !PXOR xmm3, xmm3 ; R
    !PXOR xmm1, xmm1 ; L
    !PXOR xmm0, xmm0 ; sinc
    !MOVSD xmm0, [Ecx] ; sinc 
    !ADD Ecx, 8 ; sinc double table
    !MOVSS xmm1, [Edx] ; L
    !ADD Edx,4
    !MOVSS xmm3, [Edx] ; R
    !ADD Edx,12 ;  
    !CVTSS2SD xmm1, xmm1
    !CVTSS2SD xmm3, xmm3
    !mulpd xmm1, xmm0 ; sinc x L
    !mulpd xmm3, xmm0 ; sinc x R 
    !ADDPD xmm4, xmm1 ; pcmdata2 L ++
    !ADDPD xmm5, xmm3 ; pcmdata2 R ++
  Next i
  !CVTSD2SS xmm4, xmm4
  !CVTSD2SS xmm5, xmm5
  !XOR Edx, Edx
  !MOV Edx, [p.p_out_buffer_ptr]
  !MOVSS [Edx], xmm4
  !MOVSS [Edx+4], xmm5
  !XOR Ecx, Ecx
  !XOR Edx, Edx
EndProcedure
Last edited by oryaaaaa on Tue Aug 21, 2012 3:55 am, edited 2 times in total.
Thorium
Addict
Addict
Posts: 1264
Joined: Sat Aug 15, 2009 6:59 pm

Re: Sinc interpolating (All source code)

Post by Thorium »

You should replace for next with a asm loop. For next is very slow compared to a asm loop.
User avatar
oryaaaaa
Enthusiast
Enthusiast
Posts: 779
Joined: Mon Jan 12, 2004 11:40 pm
Location: Okazaki, JAPAN

Re: Sinc interpolating (All source code)

Post by oryaaaaa »

Because, Asm loop is crushed. then This loop used.
Could you teach me about asm loop?

Thanks
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3715
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Sinc interpolating (All source code)

Post by wilbert »

I don't understand what you mean by 'crushed'.
Your routine currently isn't doing anything with the EAX register so you could use that one as a counter.
Another option is to calculate the end value of ECX or EDX and store that in EAX and compare after each cycle if the end has been reached.

The last two lines of your function
!XOR Ecx, Ecx
!XOR Edx, Edx
aren't required by the way. There's no need to reset these registers to 0.
Thorium
Addict
Addict
Posts: 1264
Joined: Sat Aug 15, 2009 6:59 pm

Re: Sinc interpolating (All source code)

Post by Thorium »

That should do it, but untested.

Code: Select all

Procedure SincInterpolation(*buffer_audio_ptr, *sinc_table_ptr, *out_buffer_ptr, *dummy)
  !XOR Ecx, Ecx
  !XOR Edx, Edx
  !MOV Ecx, [p.p_sinc_table_ptr]
  !MOV Edx, [p.p_buffer_audio_ptr]
  !SUB  Edx, 2048
  !PXOR xmm4, xmm4
  !PXOR xmm5, xmm5
  
  !mov eax, 257
  !align 4
  !SincInterLoop:
  
    !PXOR xmm3, xmm3 ; R
    !PXOR xmm1, xmm1 ; L
    !PXOR xmm0, xmm0 ; sinc
    !MOVSD xmm0, [Ecx] ; sinc
    !ADD Ecx, 8 ; sinc double table
    !MOVSS xmm1, [Edx] ; L
    !ADD Edx,4
    !MOVSS xmm3, [Edx] ; R
    !ADD Edx,12 ; 
    !CVTSS2SD xmm1, xmm1
    !CVTSS2SD xmm3, xmm3
    !mulpd xmm1, xmm0 ; sinc x L
    !mulpd xmm3, xmm0 ; sinc x R
    !ADDPD xmm4, xmm1 ; pcmdata2 L ++
    !ADDPD xmm5, xmm3 ; pcmdata2 R ++
    
  !dec eax
  !jnz SincInterLoop
  
  !CVTSD2SS xmm4, xmm4
  !CVTSD2SS xmm5, xmm5
  !XOR Edx, Edx
  !MOV Edx, [p.p_out_buffer_ptr]
  !MOVSS [Edx], xmm4
  !MOVSS [Edx+4], xmm5
  !XOR Ecx, Ecx
  !XOR Edx, Edx
EndProcedure
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8172
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: Sinc interpolating (All source code)

Post by netmaestro »

I don't understand what you mean by 'crushed'.
He means when he tries it it crashes.
BERESHEIT
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3715
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Sinc interpolating (All source code)

Post by wilbert »

@Netmaestro, now I understand :wink:

@oryaaaaa, just like the code from Thorium it's untested but you should be able to handle the left and right samples at the same time since each SSE register can contain two double precision values.
Something like

Code: Select all

Procedure SincInterpolation(*buffer_audio_ptr, *sinc_table_ptr, *out_buffer_ptr, *dummy)
  !mov ecx, [p.p_sinc_table_ptr]
  !mov edx, [p.p_buffer_audio_ptr]
  !sub edx, 2048
  !pxor xmm2, xmm2
  
  !mov eax, 257
  !align 4
  !SincInterLoop:
  
  !movq xmm0, [ecx] ; sinc
  !movlhps xmm0, xmm0
  !cvtps2pd xmm1, [edx] ; L + R
  !mulpd xmm1, xmm0
  !addpd xmm2, xmm1
  !add ecx, 8
  !add edx, 16
  
  !dec eax
  !jnz SincInterLoop
  
  !cvtpd2ps xmm2, xmm2
  !mov edx, [p.p_out_buffer_ptr]
  !movq [edx], xmm2
EndProcedure
User avatar
oryaaaaa
Enthusiast
Enthusiast
Posts: 779
Joined: Mon Jan 12, 2004 11:40 pm
Location: Okazaki, JAPAN

Re: Sinc interpolating (All source code)

Post by oryaaaaa »

Thank you

I understand use to 2 register SIMD programing.
User avatar
oryaaaaa
Enthusiast
Enthusiast
Posts: 779
Joined: Mon Jan 12, 2004 11:40 pm
Location: Okazaki, JAPAN

Re: Sinc interpolating (All source code)

Post by oryaaaaa »

Is there a method of the suppression of LOAD of CPU and execution?
Post Reply