How to capture audio on c++ UWP app with WASAPI? - c++

I can not seem to find any tutorial on the internet for my question.
All the simple guide is not suitable for UWP.
For Example,
To use WASAPI there are these steps
enumerate devices
capture audio
play (render) audio back
But the enumerating step, The client must call CoCreateInstance. But from my understanding this function is not support in UWP. Also I failed at Line 30 when following this code.
So, I try to understand This, C++ UWP using WASAPI, But I can't find any Enumerate part and this project is very complicate for me.
It include a lot of other files (DeviceState.h, common.h)
And I failed to extract the code to create my own application.
My question is how can I capture audio on c++ UWP app with WASAPI?
If this question is too board, I will change my question to How to enumerate audio device in c++ UWP application?.
And the reason why I use WASAPI is because I want to access the data stored in the Buffer.
Edit:
For enumerating.
https://github.com/Microsoft/Windows-universal-samples/blob/7c7832e1f144e4fc836603fd70e1352024a5fe1a/Samples/WindowsAudioSession/cpp/Scenario1.xaml.cpp#L85

Yes, you can use WASAPI to do audio capturing in UWP and this is what is done in the sample you have referenced (https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/WindowsAudioSession).
For the enumeration, the main function is DeviceInformation::FindAllAsync with this selector MediaDevice::GetAudioCaptureSelector it will allow you to list the capture devices.
For the stream capturing, the main function you need is
ActivateAudioInterfaceAsync, it will allow you to create an IAudioClient from a device id (specific device) or a device class (render or capture) if you just need to use the default device.
Once you have this IAudioClient you can use it to get an IAudioClientCapture, basically the things that you have seen in the sample.

Related

How to check if MMDevice is captured exclusively?

I am able to capture default microphone exclusively using similar code as described here https://learn.microsoft.com/en-us/windows/win32/coreaudio/exclusive-mode-streams
I also need to check if an audio device is already captured exclusively by some app.
As a possible solution I tried to catpure audio device in shared mode and if it is already caputred exclusively I am getting this error: AUDCLNT_E_DEVICE_IN_USE
This seems to work but I am wondering if we can check if device is captured exclusively, without capturing it, maybe by reading some propery of the audio device.
I suggest you could try to use IAudioSessionEvents::OnSessionDisconnected method
DisconnectReasonExclusiveModeOverride:The (shared-mode) audio session was disconnected to make the audio endpoint device available for an exclusive-mode connection.

Grabber for splitting in UWP

I need your advice. I'd like to develop the app for audio/video splitting using Metro interface.
Usually I use DirectShow for it using the follow schema: create a grabber, add it to DS graph, capture by it the audio/video streams and pass them to my AVstream drivers for splitting. But in new program I want to use Media Foundation and insert it into UWP.
How I see my new app. It must have Metro interface for common control: choice of sources, adding parameters, changing modes and etc. I'd like to use MediaCapture class for capture of streams and rendering them too. Here I don't see any problems, MSDN has many samples for it. But I have no ideas how to insert a grabber between source and render.
Which operations a grabber will do:
Receive input stream from MediaCapture.
Stream converting : YUV -> RGB, adding effects and etc.
Send output stream for rendering (MediaCapture) and to my AVstream driver for splitting with any apps (Skype, Adobe Flash Player, Edge, ....).
How to make a grabber. In MSDN I found three ways:
Sample Grabber Sink (https://msdn.microsoft.com/en-us/library/windows/desktop/hh184779(v=vs.85).aspx). No problem to receive/control/send stream in MF dll. But I don't know how to link that dll with MediaCapture?
Source Reader (https://msdn.microsoft.com/en-us/library/windows/desktop/dd940436(v=vs.85).aspx). The same problems, plus the Source Reader doesn't work for playback.
Custom MFT? Any case MediaCapture allows to connect to MFT by AddEffectAsync().
My environment: MS Windows 10, MS Visual Studio Community 2015.
Thank you for any ideas.
This question and UWP are not actual for me at all. I found the following:
"Some apps can work intensively in background, for example it maybe video converting, online financial data processing and more.
Now UWP application will suspended when it go offscreen."
https://wpdev.uservoice.com/forums/110705-universal-windows-platform/suggestions/9950598-exclude-suspending-in-desktop
So if the user minimizes the program window, then the program stops a video stream.

Video capture application won't work with DirectShow-compatible device

I developed a video capture application in C++ with Qt on Windows 7, using the videoInput library (which uses DirectShow). My application works fine with all the devices I previously tried (some inboard capture devices, webcams, a Pinnacle Dazzle DVC 100, a Pinnacle Studio Movie Box, and even a troubled PixelView PlayTV USB Hybrid), but now I bought an AVerMedia DarkCrystal HD Capture Station (in order to support HD capturing) and it simply won't work.
According to the AVerMedia website, it is totally DirectShow-compatible and I don't even need to use its SDK. I followed the manufacturer's installation instructions and I'm able to capture video using its own bundled software (TotalMedia Studio MV), so I suppose it's working properly.
I tried to run my videoInput-based application and also AmCap (DirectShow sample from Microsoft) and both of them behave the same way. They are able to find the device, retrieve its friendly name, but nothing else. AmCap says Error 80004002: Cannot find VCapture:IAMStreamConfig.
I was debugging AmCap and found out the ICaptureGraphBuilder2::FindInterface method always returns E_NOINTERFACE, i.e. no such interface supported, in lines like this:
hr = gcap.pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE,
&MEDIATYPE_Video, gcap.pVCap,
IID_IAMStreamConfig, (void **)&gcap.pVSC);
Here, gcap.pBuilder is a pointer to ICaptureGraphBuilder2, gcap.pVCap is a pointer to IBaseFilter, and gcap.pVSC is a pointer to IAMStreamConfig and should receive the return value.
I suppose there's some workaround that could help me to capture from this device, since I could sucessfully retrieve the device name (using the ICreateDevEnum::CreateClassEnumerator method, based on the CLSID_VideoInputDeviceCategory class identifier).
A video capture device which does not implement IAMStreamConfig is a possible scenario, though it's not something expected. Actually it more looks like a bug on video device or underlying driver, however you might want to update your app to use default media type in case of missing IAMStreamConfig (you can still use GraphEdit to check if the device is operational).

Record directshow audio device to file

I've stumbled through some code to enumerate my microphone devices (with some help), and am able to grab the "friendly name" and "clsid" information from each device.
I've done some tinkering with GraphEd.exe to try and figure out how I can take audio from directshow and write it to a file (I'm not currently concerned about the format, wav should be fine), and can't seem to find the right combination.
One of the articles I've read linked to this Windows SDK sample, but when I examined the code, I ended up getting pretty confused at how to use that code, ie. setting the output file, or specifying which audio capture device to use.
I also came across a codeguru article that has a nicely featured audio recorder, but it does not have an interface for selecting the audio device, and I can't seem to find where it statically picks which recording device to use.
I think I'd be most interested in figuring out how to use the Windows SDK sample, but any explanation on either of the two approaches would be fantastic.
Edit: I should mention my knowledge and ability as a win32 COM programmer is very low on the scale, so if this is easy, just explain it to me like I'm five, please.
Recording audio into file with DirectShow needs you to build the right filter graph, as you should have figured out already. The parts include:
The device itself, which you instantiate via moniker (not CLSID!), it is typically PCM format
Multiplexer component that converts streams into container format
File Writer Filter that takes file-compatible stream and writes into a file
The tricky moment is #2 since there is not standard component available. Windows SDK samples however contains the missing part - WavDest Filter Sample. Building it and making it ready for use, you can build a graph that records from device into .WAV file.
Your graph will look like this, and it's built easily programmatically as well:
I noticed that I have a variation of WavDest installed with Google Earth - for the case you have troubles building it yourself and you will be looking for prebuilt binary.
You can instruct ffmpeg to record from a directshow device, and output to a file.

Capture audio of a single application on Windows 7

Is there a way to capture the audio outputted by only a single application, and not the system as a whole? With WASAPI I can capture the entire system audio, but I wish to only capture the audio from one application (there will be many applications, all playing audio at once.)
Detours is used for hooking. Using the lib to hook IAudioRenderClient interface, including GetBuffer and ReleaseBuffer, and read data from the buffer.
Depending on the APIs used by the application to play the audio, you could write an AppInit DLL that will wrap the built-in waveIn\waveOut functions and would pass along the audio data. I know this works with the waveIn\waveOut functions, but not sure what other audio playback interfaces there are on Windows 7 and whether they are compatible with the AppInit trick.