locked
How to create an IBuffer from scratch

Answers

All replies

  • Can you explain what you are trying to achieve?

    You can implement IBuffer and IBufferByteAccess on your own array of data. Alternatively, you might be better off using an InMemoryRandomAccessStream or similar.

    --Rob

    Saturday, May 5, 2012 2:50 AM
    Owner
  • I'm writing a small WinRT component around WASAPI, to get buffer based audio capturing in C#.

    What I want to do is to pass the current buffer returned by IAudioCaptureClient to a .NET event handler. The safest way is supposed to be IBuffer. In .NET you have the extension methods in WindowsRuntimeBufferExtensions, like .AsBuffer(), where I can do this:

    byte[] buffer = byte[1 << 16];
    IBuffer ibuffer = buffer.AsBuffer();

    Is there something similar for C++/CX?

    That's a pseudo-code version of what I'm trying to do:

    public delegate void BufferRecordedEventHandler(Platform::Object ^sender, Streams::IBuffer ^buffer);
    
    public ref class Recorder sealed
    {
    	public:
    		event BufferRecordedEventHandler ^BufferRecorded;
    
    		void StartRecording();
    }
    
    void Recorder::StartRecording()
    {
    	...
    	
    	while(abort != FALSE)
    	{
    		...
    			hr = audioCaptureClient->GetBuffer(&buffer, &framesAvailable, &flags, NULL, NULL);
    			...
    			// DO MAGIC
    			IBuffer ^ibuffer = DoMagicWithBuffer(buffer);
    
    			BufferRecorded(this, ibuffer);
    		...
    	}
    	...
    }

    That DoMagicWithBuffer part is where I'm clueless. The documentation in its current state doesn't help.

    --edit: Wait, so you're saying that I need to actually implement a class around IBuffer and IBufferByteAccess? I guess I'll try. I was kind of confused by the fact that you can't do that exact thing in .NET. I'm no C++, I'm currently just making do because Media Foundation is weird and kind of overkill.

    Thanks.

    • Edited by Tom Servo Saturday, May 5, 2012 11:07 AM
    Saturday, May 5, 2012 11:03 AM
  • I don't get it. IBuffer is a managed interface, where as IBufferByteAccess is an unmanaged struct. I can't combine the two.

    --edit:

    I now figured out how to use both by creating an unmanaged class, but now it wants me to implement all this COM stuff. Seriously, why isn't there a canned method to wrap an IBuffer around an array?

    • Edited by Tom Servo Sunday, May 6, 2012 12:27 PM
    Sunday, May 6, 2012 11:56 AM
  • Hey Tom,

    You should be able to create an IDataWriter and set the bytes using WriteBytes. You can then get the IBuffer by calling DetachBuffer.

    DataWriter.WriteBytes
    http://msdn.microsoft.com/en-us/library/windows/apps/windows.storage.streams.datawriter.writebytes.aspx

    DataWriter.DetachBuffer
    http://msdn.microsoft.com/en-us/library/windows/apps/windows.storage.streams.datawriter.detachbuffer.aspx

    I hope this helps,

    James


    Windows Media SDK Technologies - Microsoft Developer Services - http://blogs.msdn.com/mediasdkstuff/

    Wednesday, May 9, 2012 12:50 AM
    Moderator
  • Thanks! That'll solve the issue on the interim.

    I'd still rather fancy a lighter weight approach on the long run. Like a skeleton implementation around IBuffer and IBufferByteAccess, that'll take a pointer and capacity via the constructor, and maybe even a deallocator specified via a template parameter, so it can clean up after being dereferenced. Seems a more sensible approach if you're dealing with a lot of IBuffers (custom WinRT stream implementations and passing data between C++ and the other languages/runtimes in a safer way).

    I'd do it myself, but it'll require going the complete COM route. I don't have experience at all with it.

    Wednesday, May 9, 2012 5:46 PM
  • Hey Tom,

    I'm guessing that you are trying to copy large amounts of audio data to your .net application from your C++ component. This is certainly not recommended. Keep in mind that there is a some overhead in the marshaling between your C++ application and WinRT. If you are crossing between C++ and .net (C#) the marshaling overhead is even greater. I honestly don't know if an IBuffer marshals by pinning the pointer or if there is a full copy occurring during the marshal. My guess is that a full copy is occurring and this can be an extremely expensive operation. Again I don't know your full architecture but I want you to be aware of some potential performance issues you might face.

    I hope this helps,

    James


    Windows Media SDK Technologies - Microsoft Developer Services - http://blogs.msdn.com/mediasdkstuff/

    Wednesday, May 9, 2012 11:21 PM
    Moderator
  • I have an example how to make your own IBuffer^ in my project here: http://jeremiahmorrill.wordpress.com/2012/05/11/http-winrt-client-for-c/

    Just check out NativeBuffer.h and the CreateBuffer(...) method in HttpDataResult.cpp

    • Marked as answer by Tom Servo Saturday, May 12, 2012 10:31 PM
    Friday, May 11, 2012 10:17 PM
  • Exactly what I need! Many thanks!
    Saturday, May 12, 2012 2:20 PM