0

This is a .NET wrapper for the library Secret Rabbit Code (aka libsamplerate), when calling src_callback_read in CallbackRead : AccessViolationException - Attempted to read or write protected memory.

From C header :

/* Opaque data type SRC_STATE. */
typedef struct SRC_STATE_tag SRC_STATE ;

typedef long (*src_callback_t) (void *cb_data, float **data) ;

SRC_STATE* src_callback_new (src_callback_t func, int converter_type, int channels,                 int *error, void* cb_data) ;

long src_callback_read (SRC_STATE *state, double src_ratio, long frames, float *

I then created the following :

C++/CLI class library that calls the C library :

public delegate long SRCCallback ( void *cb_data, float **data ) ;

static  IntPtr CallbackNew ( SRCCallback ^func, RabbitConverter converter_type, int channels, int *error, void* cb_data )
        {
            src_callback_t* cb = ( src_callback_t* ) &func;
            SRC_STATE* state =  src_callback_new ( *cb, ( int ) converter_type, channels, error, cb_data );
            IntPtr ptr = IntPtr ( state );
            return ptr;
        }

static long CallbackRead ( IntPtr  src_state, double src_ratio, long frames , float * data )
        {
            void* toPointer = src_state.ToPointer();
            SRC_STATE* state = ( SRC_STATE* ) toPointer;
            long l = src_callback_read ( state, src_ratio, frames, data );
            return l;
        }

C# application that uses the C++/CLI library :

private static readonly unsafe SRCCallback _callback = target;

private static unsafe void Callback()
{
    var input = GetSine(1000.0d, 44100, 1);
    fixed (float* f = input)
    {
        RabbitError error = RabbitError.SRC_ERR_NO_ERROR;
        var @void = Rabbit.CallbackNew(_callback, RabbitConverter.SRC_SINC_BEST_QUALITY, 1, (int*) (&error),
                                        (void*) IntPtr.Zero);
        var callbackRead = Rabbit.CallbackRead(@void  , 1d, input.Length/2, f);
        if (callbackRead != input.Length)
        {
            // throw new InvalidOperationException();
        }
    }
}

private static unsafe int target(void* cb_data, float** data)
{
    return 9;
}
aybe
  • 15,516
  • 9
  • 57
  • 105
  • Might this http://stackoverflow.com/questions/1241080/problem-with-c-callback-function-in-c-sharp-how-to-pass-value-to-a-pointer be of some help? –  Apr 15 '12 at 23:14
  • "Arbitrary in this case means that the ratio of input and output sample rates can be an irrational number"... I'd like this sound resampled to 10000 \pi Hz, please! Actually, it would concern me to trust signal reconstruction to someone who clearly doesn't know what a rational number is. – Ben Voigt Apr 15 '12 at 23:18
  • Ascension Systems : I tried to use ref but that didn't do it. – aybe Apr 15 '12 at 23:46
  • Ben Voigt : do you know an alternative then ? :-) – aybe Apr 15 '12 at 23:47

1 Answers1

0

I have fixed it using the following :

[System::Runtime::InteropServices::UnmanagedFunctionPointerAttribute ( CallingConvention::Cdecl )]
public delegate long SRCCallback ( void *cb_data, float **data ) ;

static  IntPtr CallbackNew ( SRCCallback ^ % func, RabbitConverter converter_type, int channels, int *error, void* cb_data ) { ... }

In short : now it uses C calling convention and C# ref keyword.

aybe
  • 15,516
  • 9
  • 57
  • 105