Record an audio stream in C # from the CIO ASIO library

I need to find a better way to record an audio stream. I already created low-level C ++ code and paired it with C #.

So, I have a C ++ callback that gives me an array of float arrays - an audio signal. At the moment, my C ++ lib writes data directly to a wav file, and it just notifies my C # application when it finishes writing.

But I would like to have more interactivity on the user interface side, for example, an โ€œendlessโ€ progress bar, the amount of recorded data, the cancel button, etc., and since in the worst case it will be a minute, it might be better to store it in memory. I know very little about memory management in .NET and C #, so I donโ€™t know how to do this efficiently.

Is there any quick resizable container in C # where I could just put the data inside and later get it as an array?

I would also like to create a waveform image. I already did this in C ++, but somehow I donโ€™t like the idea of โ€‹โ€‹writing too many messages, passing objects, etc.

So, to put things together:

  • I have an unmanaged C ++ callback that does some things, and from the inside I would like to call the C # method, as soon as it processes the data, the C prototype would be:

    void process (float ** signal, int n); (usually [2] [n] - for stereo)

    What is the C # equivalent and how can I call it from this C ++ callback?

  • (, mem.put(float [] [] data, int size)), (, wav )

  • , #? ( ++-, # .. , , DSP), ?:)

,

pablox

, :

++ :

public ref struct CVAudio {
   public:
    float *left;
    float *right;
    int length;
   };

++ :

delegate void       GetAudioData([In, Out] CVAudio^ audio);

, :

void                initializeSoundSystem(void *HWnd, GetAudioData ^audio);

C

typedef void (CALLBACK *GETAUDIODATA)(CVAudio ^a);

++ :

void                initializeSoundSystem(HWND HWnd, GETAUDIODATA audio);

:

void VDAudio::initializeSoundSystem(void *HWnd, GetAudioData ^audio) 
{
    HWND h = (HWND) HWnd;

    acb = audio;
    pin_ptr<GetAudioData ^> tmp = &audio;

    IntPtr ip = Marshal::GetFunctionPointerForDelegate(audio);
    GETAUDIODATA cb = static_cast<GETAUDIODATA>(ip.ToPointer());

    audioObserver->initializeSoundSystem(h, cb);
}

.

:

            VDAudio^ a = gcnew VDAudio();
            a->left = VHOST->Master->getSample()[0]; //returns left channel float*
            a->right = VHOST->Master->getSample()[1];
            a->length = length;
            (*callback)(a);

#:

public void GetSamples(CVAudio audio)
{
    unsafe
    {

        float* l = (float*)audio.left;
        float* r = (float*)audio.right;

        if (l != null)
        {

            SamplePack sample = new SamplePack();

            sample.left = new float[audio.length];
            sample.right = new float[audio.length];

            IntPtr lptr = new IntPtr((void*)l);
            IntPtr rptr = new IntPtr((void*)r);

            Marshal.Copy(lptr, sample.left, 0, audio.length);
            Marshal.Copy(rptr, sample.right, 0, audio.length);

            this.Dispatcher.Invoke(new Action(delegate()
            {
                GetSamples(sample);
            }));
        }
    }
}

, , - . , , , ..:)

+5
1

1: #, C-, ++. , C. ,

delegate void ASIOCallback(IntPtr signal, int n);

, . . 2.

2: , , . . , ( , , MemoryStream ..) .

3: , , - . , # , C/++. . , , . - , , , . , , , , # / ++.

+2

All Articles