Inline C Arrays help

Just starting out? Need help? Post your questions and find answers here.
AndyMK
Enthusiast
Enthusiast
Posts: 467
Joined: Wed Jul 12, 2006 4:38 pm
Location: UK

Inline C Arrays help

Post by AndyMK »

Hi all, i have some inline C code and i need to access an array created in C or have the inline C access a PB array.

Code: Select all

!float inleftBuffer[256];
!float inrightBuffer[256];
!void *inbuffers[2];
!inbuffers[0] = inleftBuffer;
inbuffers[1] = inrightBuffer;
	
!float outleftBuffer1[256];
!float outrightBuffer2[256];
!void *outbuffers[4];
!outbuffers[0] = outleftBuffer1;
!outbuffers[1] = outrightBuffer2;
  
Repeat
  !Pa_ReadStream( p_stream2, inbuffers, 256 );
  !RtlCopyMemory(inbuffers, outbuffers, 256*4*2);
  !Pa_WriteStream( p_stream1, outbuffers, 256 );
ForEver
The above works fine but i want to access the buffers in PB for copying purposes
User avatar
mk-soft
Addict
Addict
Posts: 3709
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Inline C Arrays help

Post by mk-soft »

One way:

Code: Select all

Structure ArrayOfFloat
  f.f[0]
EndStructure

Global *Buffer.ArrayOfFloat

!float inleftBuffer[256];
!inleftBuffer[0] = 10.1;
!inleftBuffer[1] = 20.2;

!p_buffer = (void*)inleftBuffer;

Debug *Buffer\f[0]
Debug *Buffer\f[1]
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
AndyMK
Enthusiast
Enthusiast
Posts: 467
Joined: Wed Jul 12, 2006 4:38 pm
Location: UK

Re: Inline C Arrays help

Post by AndyMK »

Thanks mk-soft. I will try it tomorrow.
AndyMK
Enthusiast
Enthusiast
Posts: 467
Joined: Wed Jul 12, 2006 4:38 pm
Location: UK

Re: Inline C Arrays help

Post by AndyMK »

This code takes the left and right input from an audio device and outputs it to channels 5 and 6 of a multi channel audio device. This code is just the main loop. My question is, can i convert more of the C to pb?

Code: Select all

Structure ArrayOfFloat
  f.f[0] 
EndStructure
  
  *stream1 = PeekL(*user)
  *stream2 = PeekL(*user + 4)
      
  *inBuffer1.ArrayOfFloat
  *inBuffer2.ArrayOfFloat
  
  *silent_buffer = AllocateMemory(128*4*2)
  
  *outBuffer1.ArrayOfFloat
  *outBuffer2.ArrayOfFloat
  *outBuffer3.ArrayOfFloat
  *outBuffer4.ArrayOfFloat
  *outBuffer5.ArrayOfFloat
  *outBuffer6.ArrayOfFloat
  *outBuffer7.ArrayOfFloat
  *outBuffer8.ArrayOfFloat
  *outBuffer9.ArrayOfFloat
  *outBuffer10.ArrayOfFloat
    
  !float inleftBuffer[256];
  !float inrightBuffer[256];
  !void *inbuffers[2];
  !inbuffers[0] = inleftBuffer;
  !inbuffers[1] = inrightBuffer;
    
  !float out1[256];
  !float out2[256];
  !float out3[256];
  !float out4[256];
  !float out5[256];
  !float out6[256];
  !float out7[256];
  !float out8[256];
  !float out9[256];
  !float out10[256];
	
  !void *outbuffers[10];
  !outbuffers[0] = out1;
  !outbuffers[1] = out2;
  !outbuffers[2] = out3;
  !outbuffers[3] = out4;
  !outbuffers[4] = out5;
  !outbuffers[5] = out6;
  !outbuffers[6] = out7;
  !outbuffers[7] = out8;
  !outbuffers[8] = out9;
  !outbuffers[9] = out10;
  
  !p_inbuffer1 = (void*)inleftBuffer;
  !p_inbuffer2 = (void*)inrightBuffer;
  
  !p_outbuffer1 = (void*)out1;
  !p_outbuffer2 = (void*)out2;
  !p_outbuffer3 = (void*)out3;
  !p_outbuffer4 = (void*)out4;
  !p_outbuffer5 = (void*)out5;
  !p_outbuffer6 = (void*)out6;
  !p_outbuffer7 = (void*)out7;
  !p_outbuffer8 = (void*)out8;
  !p_outbuffer9 = (void*)out9;
  !p_outbuffer10 = (void*)out10;
  
  Repeat
    !Pa_ReadStream( p_stream2, inbuffers, 256 );
    
    CopyMemory(*silent_buffer, *outBuffer1, 128*4*2)
    CopyMemory(*silent_buffer, *outBuffer2, 128*4*2)
    CopyMemory(*silent_buffer, *outBuffer3, 128*4*2)
    CopyMemory(*silent_buffer, *outBuffer4, 128*4*2)
    CopyMemory(*inBuffer1, *outBuffer5, 128*4*2)
    CopyMemory(*inBuffer2, *outBuffer6, 128*4*2)
    CopyMemory(*silent_buffer, *outBuffer7, 128*4*2)
    CopyMemory(*silent_buffer, *outBuffer8, 128*4*2)
    CopyMemory(*silent_buffer, *outBuffer9, 128*4*2)
    CopyMemory(*silent_buffer, *outBuffer10, 128*4*2)
    
    !Pa_WriteStream( p_stream1, outbuffers, 256 );
  ForEver
AndyMK
Enthusiast
Enthusiast
Posts: 467
Joined: Wed Jul 12, 2006 4:38 pm
Location: UK

Re: Inline C Arrays help

Post by AndyMK »

Is it possible to create an array in PB and access it with inline C?
AndyMK
Enthusiast
Enthusiast
Posts: 467
Joined: Wed Jul 12, 2006 4:38 pm
Location: UK

Re: Inline C Arrays help

Post by AndyMK »

Lets say i have

Code: Select all

Dim buffers(2)
I need to access this in C. I tried

Code: Select all

!a_buffers[0] = 1;
I get an error saying a_buffers is not an array.
User avatar
mk-soft
Addict
Addict
Posts: 3709
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Inline C Arrays help

Post by mk-soft »

It works, but it's best to have the c-code pb output how it works. (--commented)

For easy output see:

IDE Tool DisplayCcode
and for ASM DisplayASMcode
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
idle
Addict
Addict
Posts: 3880
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Inline C Arrays help

Post by idle »

Code: Select all

Dim buffers.i(2) 

buffers(0) = 123;
!((integer*)a_buffers.a)[1]=234;

Debug buffers(0) 
Debug buffers(1)

I'm not sure why your using the blocking I/O methods, using a callback would simplify the problem
as it passes you the pointers for the input and output buffers.

here's an example it will open a the default recording device and the call back copies it to the default output

Code: Select all

!//#include D:\pb\portaudio\portaudio.h;  path to portaudio.h 

ProcedureC IOCallback(*in.float,*out.float,framesPerBuffer,*timeInfo,statusFlags,*userData)
  
  CopyMemory(*in,*out,framesPerBuffer*SizeOf(float)*2) ;copy in to out number of samples * size of float * 2 channels 
    
EndProcedure 

OpenConsole() 

!#define SAMPLE_RATE         (44100)
!#define PA_SAMPLE_TYPE      paFloat32
!PaStreamParameters inputParameters;
!PaStreamParameters outputParameters;
!PaStream *stream;

Global err,pcb,samplesize ;

samplesize = 1024      
pcb= @IOCallback()  

!v_err = Pa_Initialize();
If err <> 0 
  Goto error;
EndIf  

!inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */

!if (inputParameters.device == paNoDevice) {
Debug "Error: No default input device."
Goto error;
!}

!inputParameters.channelCount = 2;       /* stereo input */
!inputParameters.sampleFormat = PA_SAMPLE_TYPE;
!inputParameters.suggestedLatency = Pa_GetDeviceInfo(inputParameters.device )->defaultLowInputLatency;
!inputParameters.hostApiSpecificStreamInfo = 0;

!outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */

!if (outputParameters.device == paNoDevice) {
Debug "Error: No Default output device."
Goto error;
!}

!outputParameters.channelCount = 2;       /* stereo output */
!outputParameters.sampleFormat = PA_SAMPLE_TYPE;
!outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
!outputParameters.hostApiSpecificStreamInfo = 0;

!v_err = Pa_OpenStream(&stream,&inputParameters,&outputParameters,SAMPLE_RATE,v_samplesize,0,v_pcb,0);
If err <> 0 
  Goto error;
EndIf 

!v_err = Pa_StartStream( stream );
If err <> 0 
  Goto error;
EndIf 

PrintN("Hit ENTER to stop program.");
Input()

!v_err = Pa_CloseStream( stream );
If err <> 0 
  Goto error;
EndIf 

!Pa_Terminate();
End 

error:
!Pa_Terminate();

AndyMK
Enthusiast
Enthusiast
Posts: 467
Joined: Wed Jul 12, 2006 4:38 pm
Location: UK

Re: Inline C Arrays help

Post by AndyMK »

Hi idle, thanks for the example. The reason i am using blocking i/o is because the input source is on a different soundcard to the output. The buffer sizes are also different so i used blocking i/o to avoid having to make a buffering system as it manages that for you. Also, different soundcards have different amount of inputs/outputs so i wanted a way to initialize the right amount of buffers automatically. I am also using paNonInterleaved on the sample format so that i can copy any input buffer to any output buffer fast without looping through a buffer.
AndyMK
Enthusiast
Enthusiast
Posts: 467
Joined: Wed Jul 12, 2006 4:38 pm
Location: UK

Re: Inline C Arrays help

Post by AndyMK »

Ist there a way for 2 threads to access a buffer without using locks?
User avatar
idle
Addict
Addict
Posts: 3880
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Inline C Arrays help

Post by idle »

I don't know about using port audio across different sound cards. But If you do it with callbacks you can shunt a block of samples into a ring buffer which you can read and write lock free. you can use the pa_ringbuffer.h in the src for portaudio, it's also easy enough to implement one in PB and use atomic inc or dec on buffer read and write pointers.
AndyMK
Enthusiast
Enthusiast
Posts: 467
Joined: Wed Jul 12, 2006 4:38 pm
Location: UK

Re: Inline C Arrays help

Post by AndyMK »

it's also easy enough to implement one in PB and use atomic inc or dec on buffer read and write pointers.
Do you have a basic example?
AndyMK
Enthusiast
Enthusiast
Posts: 467
Joined: Wed Jul 12, 2006 4:38 pm
Location: UK

Re: Inline C Arrays help

Post by AndyMK »

is this what i should be looking at?

https://docs.microsoft.com/en-us/window ... ble-access
User avatar
idle
Addict
Addict
Posts: 3880
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Inline C Arrays help

Post by idle »

yes, I tried to port the portaudio ring buffer but I haven't got it working yet and haven't had the time to look at it further.

This might be ok for use as a lock

Code: Select all

CompilerIf #PB_Compiler_Backend = #PB_Backend_Asm 
    
  Macro AtomicADD(var,vadd)
    EnableASM
    CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
      mov eax, vadd
      lock add dword [v_#var],eax
    CompilerElse
      mov rax , vadd
      lock add qword [v_#var],rax
    CompilerEndIf   
    DisableASM   
  EndMacro
    
CompilerElse 
  
  Macro AtomicAdd(var,val)
    ! __atomic_add_fetch((int *)&v_#var, v_#val , __ATOMIC_RELAXED);
  EndMacro 
  
CompilerEndIf 


Global a,b,c 
b = 1
c = -1 

AtomicAdd(a,b)

Debug a 

AtomicAdd(a,c)

Debug a 

AndyMK
Enthusiast
Enthusiast
Posts: 467
Joined: Wed Jul 12, 2006 4:38 pm
Location: UK

Re: Inline C Arrays help

Post by AndyMK »

Hi idle. Thanks for the example. I am still not sure what i should be doing with this. Can you explain what this is actually doing so i can implement it?
Post Reply