Open Specific Sound Device

Hello,

currently I am writing a tool that will utilize three different audio outputs and outputs to them for some events. For this purpose I have installed 3 USB Sound Devices in my computer. I only use Linux and have no intention on porting this to windows, so everything I write will be Linux specific :). The Problem is, that I cannot open a specific sound device, e.g. via ALSA Adress or via USB Path. The documentation here says, that you use the UTF-8 Device string reported by SDL_GetAudioDeviceName. I have written this small tool to enumerate all sound devices:

#include <SDL2/SDL.h>
#include <iostream>

int main()
{
        SDL_Init( SDL_INIT_EVERYTHING );
        std::cout << SDL_GetError() << std::endl;
        atexit( SDL_Quit );
        int count = SDL_GetNumAudioDevices(0);
        for (int i = 0; i < count; ++i)
        {
                std::cout << "Device " << i << ": " << SDL_GetAudioDeviceName(i, 0) << std::endl;
        }
        return 0;
}

(Please note, this is just a quick and dirty program, so no error checking is done, etc).

This gives me this output:

Device 0: Internes Audio Digital Stereo (IEC958)
Device 1: C-Media Electronics, Inc. Audio Adapter
Device 2: C-Media Electronics, Inc. Audio Adapter
Device 3: C-Media Electronics, Inc. Audio Adapter

As you see, the device strings are identical. Is there any way to select the sounddevice either by index or via ALSA Device string (e.g. “hw:0.1”)?

Please note: I will open 3 devies in my program, so setting an envvar wont fix the problem… Or will setenv before the open call work?

Thank you for all answers!

Weird, I thought we handled this already, but I guess not.

I’ll add some code tomorrow to rename the duplicates “C-Media Electronics, Inc. Audio Adapter (2)” and such.

–ryan.

1 Like

Cool, thank you very much! If you post when finished I will be glad to test the code!

If it helps: The driver that is used is the ALSA driver.

Another question is: Do I somehow get informations about the device used? e.g. in alsa, can I get the address (like: “hw:0,3”) or something like that?

any news on this? if you need help or testing, just ping me.

Ive hacked it in for alsa now, if someone else needs it. It will add the device string to the name now so it will enumerate something like:

Device 7: USB PnP Sound Device, USB Audio (hw:CARD=Device,DEV=0)
Device 8: USB PnP Sound Device, USB Audio (hw:CARD=Device_1,DEV=0)
Device 9: USB PnP Sound Device, USB Audio (hw:CARD=Device_2,DEV=0)

Heres the patch:

index 48b9c0cae..e272370ba 100644
--- a/src/audio/alsa/SDL_alsa_audio.c
+++ b/src/audio/alsa/SDL_alsa_audio.c
@@ -719,6 +719,7 @@ add_device(const int iscapture, const char *name, void *hint, ALSA_Device **pSee
     char *desc;
     char *handle = NULL;
     char *ptr;
+    SDL_bool desc_is_name = SDL_FALSE;
 
     if (!dev) {
         return;
@@ -735,6 +736,7 @@ add_device(const int iscapture, const char *name, void *hint, ALSA_Device **pSee
             return;
         }
     } else {
+        desc_is_name = SDL_TRUE;
         desc = (char *) name;
     }
 
@@ -747,6 +749,15 @@ add_device(const int iscapture, const char *name, void *hint, ALSA_Device **pSee
         *ptr = '\0';
     }
 
+	if (desc_is_name == SDL_FALSE)
+	{
+		uint32_t maxlen = SDL_strlen(desc) + SDL_strlen(name) + 4;
+		char *temp = SDL_malloc(sizeof(char) * (maxlen + 1));
+		SDL_snprintf(temp, maxlen, "%s (%s)", desc, name);
+		SDL_free(desc);
+		desc = temp;
+	}
+
     /*printf("ALSA: adding %s device '%s' (%s)\n", iscapture ? "capture" : "output", name, desc);*/
 
     handle = SDL_strdup(name);
1 Like

Finally got around to this: now all devices have unique names. If you have two devices named “SoundBlaster Pro”, the second one will be reported as “SoundBlaster Pro (2)”.