I have some questions about Directsound and windows mixers.
My goal is to enumerate all microphones and be able to change the input volume of each one.
I think i'm not far from the solution, but I don't find what is wrong in my code.
Here is what I have done:
- I enumerate all input devices and get a GUID for each one
- I use a method found on a topic to get the mixer id corresponding to a directsound guid using this method (but I'm not sure if it works)
- Then I get the id corresponding to the control in the mixer
- Then I can modify the volume
Here is the code: a vs2008 project
To test, I have connected two microphones usb + the line-in microphone, and I visually check what sliders are moving. But unfortunately it's not the good one ...
here is a screenshot (img177.imageshack.us/img177/5189/mixers.jpg) of all my mixers opened in windows xp.
Have you an idea of what I am doing wrong? Is there an easiest solution?
bonus question: do you know if there is a way to know if a microphone is connected or not in Line-in, using Directsound? Because the Line-in is always detected as connected even if no microphone is connected.
check this questions:
How to adjust microphone gain from C# (needs to work on XP & W7)
or
http://social.msdn.microsoft.com/Forums/en/isvvba/thread/05dc2d35-1d45-4837-8e16-562ee919da85
Related
Does anyone know how to programmatically capture the sound that is being played (that is, everything that is coming from the sound card, not the input devices such as a microphone).
Assuming that you are talking about Windows, there are essentially three ways to do this.
The first is to open the audio device's main output as a recording source. This is only possible when the driver supports it, although most do these days. Common names for the virtual device are "What You Hear" or "Wave Out". You will need to use a suitable API (see WaveIn or DirectSound in MSDN) to do the capturing.
The second way is to write a filter driver that can intercept the audio stream before it reaches the physical device. Again, this technique will only work for devices that have a suitable driver topology and it's certainly not for the faint-hearted.
This means that neither of these options will be guaranteed to work on a PC with arbitrary hardware.
The last alternative is to use a virtual audio device, such as Virtual Audio Cable. If this device is set as the defualt playback device in Windows then all well-behaved apps will play through it. You can then record from the same device to capture the summed output. As long as you have control over the device that the application you want to record uses then this option will always work.
All of these techniques have their pros and cons - it's up to you to decide which would be the most suitable for your needs.
You can use the Waveform Audio Interface, there is an MSDN article on how to access it per PInvoke.
In order to capture the sound that is being played, you just need to open the playback device instead of the microphone. Open for input, of course, not for output ;-)
If you were using OSX, Audio Hijack Pro from Rogue Amoeba probably is the easiest way to go.
Anyway, why not just looping your audio back into your line in and recording that? This is a very simple solution. Just plug a cable in your audio output jack and your line in jack and start recordung.
You have to enable device stero mix. if you do this, direct sound find this device.
Under Windows (7,8) I can mute / adjust volume as per application and per output device.
I wonder how I can set / query these values from my C++ Qt application. Basically I need to figure out / accomplish (use cases):
Is the global mute set (per device)? Set global mute from my application.
Is the application's mixer mute set? Set mixer mute.
Set mixer volume, set global volume.
Query mixer volume, set mixer volume?
Wherever possible I am looking for the Qt-ish way to accomplish things, keeping code as platform independent as possible. I can imagine to query the global mute via an OS-independent API, but using a Windows only class for the mixer.
From the C# question Get Master Sound Volume in c# I understand IAudioMeterInformation, IMMDeviceCollection, IMMDevice are the MSDN documentation entry points for Windows specific handling.
How do I tell if the master volume is muted? shows how commands can be send via WM_APPCOMMAND . Again, windows specific, also not allowing to query values but only to set them.
Is there something for Qt encapsulating these things? Is it Phonon I need to use? Checking Phonon briefly I did not see any methods for what I need, but I might have missed it.
How do I most properly use libusb to talk to connected USB devices?
Specifically, how do I transfer data to the USB devices, receive information from the devices, find out the name of the connected device, if they have storage, etc.
More specifically, I will be running this on a Mac OS X machine, so I know I can't just use Windows header files.
If there is a good explanation on libusb and USB devices, that would be helpful too.
Here is a post on a similar question that might be useful to you. I include plenty of links.
But maybe you'd rather see it here. So in that case, here it goes!
Libusb allows you to enumerate devices and select the one you want based on a specific Vendor/Product id (V/P Id). If you don't know this and can't find it online with the product's description then you can easily find it.
If it is not online you will need to use an app similar to lsusb on Linux. (I don't believe it is on Mac.) When you run lsusb it lists connected devices and their V/P Ids. You can easily find your device by unplugging, running lsusb, and plugging the device back in and comparing. It's a piece of cake. Any usb list app on Mac will hopefully display the V/P ID like lsusb does.
Then once you have this V/P ID you will use libusb (if using 0.1) to enumerate all devices and find the device that matches that id. (I support using libusbx which happens to have a single find device function based on V/P id - in fact, libusbx is a whole lot more concise all around.)
After selecting your device you will send a packet using either Feature or Output Reports. This is the most complicated part because the packet you send is dependent on the individual device I believe. It is 8 bytes of data and only one of which is a single character you wish to send to the usb device. (If you wanted to send 8 characters, you would have to loop through an array of chars and send a feature or output report for each character.)
As an example feel free to reference a rather specific terminal example I wrote for controlling two LEDS. If it's helpful, great! It contains a libusbx and libusb-0.1 example.
I hope this helps!
The official site for libusb 1.0 (the newer and recommended version) is https://libusb.info/. The API documentation is at http://api.libusb.info. Click on the Modules section to walk through the different function areas. The source is at https://github.com/libusb/libusb and you can see some working examples at https://github.com/libusb/libusb/tree/master/examples. Hope that helps!
The article from #user2469202 is a good basic intro also.
The process that you can follow is:
Get the VID, PID for the device that you want to communicate using lsusb
Try to open the device and read the device descriptor
If you want name of the device use string descriptor to get that
Check if any kernel driver is attached. If it is, then detach it and do some raw data transfer
After getting the response again re-attach the driver.
I need to split a PCM audio stream with up to 16 channels into several stereo streams.
As I haven't found anything capable of doing that, I'm trying to write my first directshow filter.
Anything capable of splitting the audio would be very welcomed but I'm assuming that I must do it so there's what I've done:
At first, I tried to create a filter based on ITransformFilter. However, it seems that it's made thinking of filters with only one input pin and one output pin. As I need several output pins, I disregarded it, however perhaps it can be adapted more easily than I thought, so any advice is highly appreciated.
Then, I begin basing on IBaseFilter. I managed to do something. I create the necessary output pins when the input pin gets connected, and destroy them when the input gets disconnected. However, when I connect any output pin to an ACM Wrapper (just to test it), the input tries to reconnect, destroying all my output pins.
I tried to just not destroy them, but then I checked the media type of my input pin and it had changed to a stereo stream. I'm not calling QueryAccept from my code.
How could I avoid the reconnection, or what's the right way to do a demuxer filter?
Edit 2010-07-09:
I've come back to ITransformFilter, but I'm creating the necessary pins. However I've encountered the same problem as with IBaseFilter: When I connect my output pin to an ACM Wrapper, the input pins changes its mediatype to 2 channels.
Not sure how to proceed now...
You can take a look at the DMOSample in the Windows Server 2003 R2 Platform SDK. It is also included in older directx sdk's, but not in newer windows sdk's. You can locate it in Samples\Multimedia\DirectShow\DMO\DMOSample. Here is the documentation of this sample.
I have seen someone create a filter based on this which had a stereo input and two mono outputs. Unfortunately I cannot post the sourcecode.
When I run this code:
MIXERLINE MixerLine;
memset( &MixerLine, 0, sizeof(MIXERLINE) );
MixerLine.cbStruct = sizeof(MIXERLINE);
MixerLine.dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT;
mmResult = mixerGetLineInfo( (HMIXEROBJ)m_dwMixerHandle, &MixerLine, MIXER_GETLINEINFOF_COMPONENTTYPE );
Under XP MixerLine.cChannels comes back as the number of channels that the sound card supports. Often 2, these days often many more.
Under Vista MixerLine.cChannels comes back as one.
I have been then getting a MIXERCONTROL_CONTROLTYPE_VOLUME control and setting the volume for each channel that is supported, and setting the volumne control to different levels on different channels so as to pan music back and forth between the speakers (left to right).
Obviously under Vista this approach isn't working since there is only one channel. I can set the volume and it is for both channels at the same time.
I tried to get a MIXERCONTROL_CONTROLTYPE_PAN for this device, but that was not a valid control.
So, the question for all you MMSystem experts is this: what type of control do I need to get to adjust the left/right balance? Alternately, is there a better way? I would like a solution that works with both XP and Vista.
Computer Details: Running Vista Ultimta 32 bit SP1 and all latest patches. Audio is provided by a Creative Audigy 2 ZS card with 4 speakers attached which can all be properly addressed (controlled) through Vista's sound panel. Driver is latest on Creative's site (SBAX_PCDRV_LB_2_18_0001). The Vista sound is not set to mono, and all channels are visable and controlable from the sound panel.
Running the program in "XP Compatibility Mode" does not change the behaviour of this problem.
If you run your application in "XP compatibility" mode, the mixer APIs should work much closer to the way they did in XP.
If you're not running in XP mode, then the mixer APIs reflect the mix format - if your PC's audio solution is configured for mono, then you'll see only one channel, but if you're machine is configured for multichannel output the mixer APIs should reflect that.
You can run the speaker tuning wizard to determine the # of channels configured for your audio solution.
Long time Microsoftie Larry Osterman has a blog where he discusses issues like this because he was on the team that redid all the audio stuff in Vista.
In the comments to this blog post he seems to indicate that application controlled balance is not something they see the need for:
CN, actually we're not aware of ANY situations in which it's appropriate for an application to control its balance. Having said that, we do support individual channel volumes for applications, but it is STRONGLY recommended that apps don't use it.
He also indicates that panning the sound from one side to the other can be done, but it is dependent on whether the hardware supports it:
Joku, we're exposing the volume controls that the audio solution implements. If it can do pan, we do pan (we actually expose separate sliders for the left and right channels).
So that explains why the MIXERCONTROL_CONTROLTYPE_PAN thing failed -- the audio hardware on your system does not support it.