Cambiare periferica AUDIO PLAY/REC

di il
31 risposte

Cambiare periferica AUDIO PLAY/REC

Ciao

Sto usando questo breve codice che mi REGISTRA poi SALVA e riproduce un file audio che sono riuscito a far funzionare sul VBnet 2019


Public Class Form1
    Private Declare Function record Lib "winmm.dll" Alias "mciSendStringA" (ByVal lpstrCommand As String, ByVal lpstrReturnString As String, ByVal uReturnLength As Integer, ByVal hwndCallback As Integer) As Integer

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        record("open new Type waveaudio Alias recsound", "", 0, 0)
        record("record recsound", "", 0, 0)
    End Sub

    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
        record("save recsound mic.wav", "", 0, 0)
        record("close recsound", "", 0, 0)
    End Sub

    Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
        My.Computer.Audio.Play("mic.wav")
    End Sub
End Class

Purtroppo però registra SOLO da microfono di default di windows10 e riproduce sugli altoparlanti.

Vorrei poter definire una scheda audio esterna che usa un altro microfono e altri altoparlanti.
Poter scegliere in pratica dalla lista delle periferiche audio su quale scheda audio MIC e ALTOPARLANTI o altro come I/O e magari anche coi rispettivi volumi.

Come potrei fare per poter cambiare la scheda audio e per gestirne i volumi?
Non ne ho proprio idea... sono principiantissimo!

GRAZIE MILLE per qualche possibile aiuto.
Anto

31 Risposte

  • Re: Cambiare periferica AUDIO PLAY/REC

    Lo vuoi fare da codice?
    Perché se entri nel mixer di win e cambi la periferica predefinita, non devi cambiare nulla.
  • Re: Cambiare periferica AUDIO PLAY/REC

    >> Lo vuoi fare da codice?

    Grazie Rubik per l'intervento.

    Si confermo il poterlo fare direttamente dalle impostazioni audio, ma vorrei forzare il tutto direttamente da codice nel senso di poter scegliere direttamente all'interno del programma quale delle periferiche usare per I/O.
    Anche perchè uso spesso un'uscita poi l'altra ecc... senza dover cambiare il default o forzare il programma stesso da Win.

    Uso 4 schede audio e un paio di VAC (virtual audio cable) e mi piacerebbe memorizzare la scelta direttamente nel codice la scelta.

    Non ho idea se il codice sopra, sia modificabile facilmente.

    Grazie e saluti.
    Anto
  • Re: Cambiare periferica AUDIO PLAY/REC

    La vedo dura, dovresti enumerare le priferiche, ed indirizzare il flusso audio alla periferica voluta, o leggere dalla scheda voluta.
    Solitamente per il C/C++ si trovano esempi per iniziare, in VB.Net no.
    Potresti anche cambiare la scheda predefinita modificando il registro di sistema, ma anche qui ci vogliono tutte le attenzioni del caso.
    https://www.yocker.com/61793/come-cambiare-la-periferica-di-riproduzione-audio-predefinita-in-modo-programmatico.html
  • Re: Cambiare periferica AUDIO PLAY/REC

    Ciao Rubik
    grazie delle info, peccato non si possa fare qualche cosa di "semplice" coi tre bottoni sopra che sulla periferica di default funziona benissimo... ;-(

    Su VB6 ero riuscito, per una cosa del genere, ad enumerare, la lista delle periferiche audio che mettevo in un menu e le sceglievo per il solo programma in uso che dava la variabile che usavo nell'applicazione con la periferica selezionata.
    Una decina di righe/codice.

    Ora in VBnet già da sempre come principiantissimo faccio ancora più fatica ... peccato.

    C/C++ non inizio nemmeno, purtroppo non saprei da che parte voltarmi, mi fermo già per incapacità al VisualBasic.net

    Pensavo che come nell'esempio, con qualche "accorgimento" si poteva reindirizzare su altra periferica come fa con il default.

    Avevo visto tempo fa un bel un progettino open source in VBnet, di un AUDIO RECORDER/PLAYER che permetteva la scelta delle sorgenti mixer e mi sembra anche delle periferiche audio coi suoi volumi ecc..., ma non ricordo se selezionava anche le periferiche audio e purtroppo non lo trovo più...
    Era anche molto corposo e onestamente a me piuttosto incomprensibile.

    Cambiare al volo la periferica di sistema non è il caso, dovrebbe essere indipendente dal sistema.
    In pratica le stesse tre procedure del codice sopra, "semplicissime" nel senso della lunghezza, ma da un'altra periferica.

    Qualsiasi aiuto o esempio benvenga...

    Grazie comunque. Vediamo se salta fuori qualche cosa, intanto cerco

    Ciao Anto
  • Re: Cambiare periferica AUDIO PLAY/REC

    Ho ancora stra-cercato ancora in rete ma non ho trovato nulla che mi possa "facilmente aiutare"...

    DOMANDA:
    Ma volendo registrare e ascoltare su una periferica diversa dal DEFAULT è proprio così complicato poter trovare e selezionare la scheda audio interessata per l'applicazione attivata?

    Se per utilizzare "il default" sono sufficienti quelle poche linee, penso, ripeto penso, dovrebbe essere anche semplice con altre poche linee di codice usare un'altra periferica audio...

    Ma qui per me è assolutamente difficile già capire le linee sopra utilizzate per il default...

    Ma indicizzando quegli "zeri" con 1 - 2 - 3 ... come faccio con VB6, o sicuramente con altro codice più azzeccato, non sarebbe possibile raggiungere altre periferiche audio?

    Grazie mille
    Anto
  • Re: Cambiare periferica AUDIO PLAY/REC

    Ma tu hai un codice VB6 che assolve alla tua esigenza?
    Se si postalo, non dovrebbe essere difficile convertirlo in VB.Net...
  • Re: Cambiare periferica AUDIO PLAY/REC

    Ma tu hai un codice VB6 che assolve alla tua esigenza?
    Se si postalo, non dovrebbe essere difficile convertirlo in VB.Net...

    Ciao,
    con questa "chiamata" in VB6 seleziono le schede audio
    ' PER SCELTA SOUND BLASTER
    Private Const CALLBACK_WINDOW = &H10000
    Private Const MAXPNAMELEN& = 32
    Private Type MIXERCAPS
         wMid As Integer
         wPid As Integer
         vDriverVersion As Long
         szPname As String * MAXPNAMELEN
         fdwSupport As Long
         cDestinations As Long
    End Type
    
    Private Declare Function mixerGetNumDevs Lib "winmm.dll" () As Long
    Private Declare Function mixerOpen Lib "winmm.dll" (phmx As Long, ByVal uMxId As Long, ByVal dwCallback As Long, ByVal dwInstance As Long, ByVal fdwOpen As Long) As Long
    Private Declare Function mixerGetDevCaps Lib "winmm.dll" Alias "mixerGetDevCapsA" (ByVal uMxId As Long, pmxcaps As MIXERCAPS, ByVal cbmxcaps As Long) As Long
    E quindi creo la lista delle periferiche audio
    
    'SCELTA della SOUND BLASTER AUDIO CARD - VB6
    Sub Main()
    On Error Resume Next
        Dim lMixer As Long
        Dim mc As MIXERCAPS
        lMixerCnt = mixerGetNumDevs
        If lMixerCnt Then
            For lLoop = 0 To lMixerCnt - 1
                lRtn = mixerOpen(lMixer, lLoop, hwnd, 0&, CALLBACK_WINDOW)
                If lRtn = 0 Then
                    lRtn = mixerGetDevCaps(lMixer, mc, Len(mc))
                    If lRtn = MMSYSERR_NOERROR Then
                        With mc
                             m_Destinations = .cDestinations
                             m_DeviceID = lLoop
                             m_DriverVersion = CStr(HiByte(mc.vDriverVersion) & "." & LoByte(mc.vDriverVersion))
                             m_hMixer = lMixer
                             m_ManufacturerID = .wMid
                             m_ProductID = .wPid
                             m_ProductName = TrimNulls(mc.szPname)
                        End With
                        s = s & m_DeviceID & ") - " & m_ProductName & vbCrLf
                        If Val(m_DeviceID) < 7 Then FrmPsk.MnuSblaster.Item(m_DeviceID).Caption = m_DeviceID & " - " & m_ProductName
                    End If
                End If
            Next lLoop
            s = ""
        End If
    End Sub
    
    Mi crea la lista in un MENU a tendina nel form FrmPsk e seleziono la scheda audio che corrisponde poi ad un numero.

    Per questa routine in VB6 uso poi una DLL che mi chiede il NUMERO "s" per selezionare la scheda audio...

    Per lo scopo che uso in VB6 funzionicchia, per quel caso specifico tra I/O ho discrepanze e non sempre corrispondono allo stesso numero le 8 periferiche audio che ho inserito, quindi ho messo un file configurabile per differenziare appunto la necessità di avere due numeri diversi, uno per input "MIC" e l'altro per output "altoparlanti" (I/O)...

    Comunque questo non devo correggerlo, ma è con VBnet che volevo fare altro, non per usare quella DLL.
    Partendo dall'esempio riportato, vorrei appunto poter selezionare la scheda audio per poter fare un REC SAVE PLAY come nel mini e funzionante esempio sopra riportato che va solo sulla scheda di DEFAULT.

    Purtroppo in VBnet non sono i grado di farlo... qualsiasi consiglio benvenga.
    Ciao
    Anto
  • Re: Cambiare periferica AUDIO PLAY/REC

    Il codice che hai postato è facilmente replicabile in VB.Net, con modifiche minime visto che usa winmm.dll.
    Devi mettere un combobox sul form
    
    Public Class Form1
        ' PER SCELTA SOUND BLASTER
        Private Const CALLBACK_WINDOW As Integer = &H10000
        Private Const MAXPNAMELEN As Integer = 32
        Private Structure MIXERCAPS
            Dim wMid As Short
            Dim wPid As Short
            Dim vDriverVersion As Integer
            <VBFixedString(MAXPNAMELEN), Runtime.InteropServices.MarshalAs(Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst:=MAXPNAMELEN)> Public szPname() As Char
            Dim fdwSupport As Integer
            Dim cDestinations As Integer
        End Structure
    
        Private Declare Function mixerGetNumDevs Lib "winmm.dll" () As Integer
        Private Declare Function mixerOpen Lib "winmm.dll" (ByRef phmx As Integer, ByVal uMxId As Integer, ByVal dwCallback As Integer, ByVal dwInstance As Integer, ByVal fdwOpen As Integer) As Integer
        Private Declare Function mixerGetDevCaps Lib "winmm.dll" Alias "mixerGetDevCapsA" (ByVal uMxId As Integer, ByRef pmxcaps As MIXERCAPS, ByVal cbmxcaps As Integer) As Integer
    
        Private Sub Form1_Load(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles MyBase.Load
            _Main()
        End Sub
    
        'SCELTA della SOUND BLASTER AUDIO CARD - DA CODICE VB6
        Sub _Main()
            Dim MMSYSERR_NOERROR, m_DeviceID, m_hMixer, m_Destinations, lRtn, lLoop, lMixerCnt As Integer
            Dim s, m_ProductName, m_DriverVersion As String
            Dim m_ProductID, m_ManufacturerID As Short
            Dim lMixer As Long
            Dim mc As MIXERCAPS = New MIXERCAPS
            On Error Resume Next
            lMixerCnt = mixerGetNumDevs
            If lMixerCnt Then
                s = ""
                For lLoop = 0 To lMixerCnt - 1
                    lRtn = mixerOpen(lMixer, lLoop, Handle.ToInt32, 0, CALLBACK_WINDOW)
                    If lRtn = 0 Then
                        lRtn = mixerGetDevCaps(lMixer, mc, Len(mc))
                        If lRtn = MMSYSERR_NOERROR Then
                            With mc
                                m_Destinations = .cDestinations
                                m_DeviceID = lLoop
                                m_DriverVersion = CStr(mc.vDriverVersion)
                                m_hMixer = lMixer
                                m_ManufacturerID = .wMid
                                m_ProductID = .wPid
                                m_ProductName = mc.szPname
                            End With
                            s = s & m_DeviceID & ") - " & m_ProductName & vbCrLf
                            If Val(m_DeviceID) < 7 Then Combo1.Items.Add(m_DeviceID & " - " & m_ProductName)
                        End If
                    End If
                Next lLoop
            End If
        End Sub
    End Class
    
    Se mi avessi messo anche le sub HiByte(), LoByte() e TrimNulls(), che ho solo immaginato quello che fanno, la risposta del programma VB.Net sarebbe stata più simile a quella del programma VB6 che hai tu.

    Quello che manca è come selezionare una delle periferica mostrate....

    In VB.Net si usa System.Management per enumerare le periferiche audio e non solo, con tutte le loro caratteristiche:
    Apri un progetto VB winform, metti nel form una label un combobox e una listbox
    System.Management se ti ritorna errore è perché non hai aggiunto il relativo Assembly
    
    '***************************************************************
    '    ATTENZIONE System.Management non è incluso di Default
    '    In esplora soluzioni sul nome del progetto: tasto destro
    '    Aggiungi / Riferimento / Assembly / Framework 
    '    cerca e seleziona: System.Management
    '***************************************************************
    
    Public Class Form1
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Searcher("SELECT * FROM Win32_SoundDevice")
            ComboBox1.Text = ComboBox1.Items.Count.ToString() & " Periferiche audio caricate "
        End Sub
    
        Private Sub Searcher(query As String)
            Label1.Text = query
            Dim objSearcher As New System.Management.ManagementObjectSearcher(query)
            Dim objCollection As System.Management.ManagementObjectCollection = objSearcher.Get()
            ListBox1.Items.Clear()
            ComboBox1.Items.Clear()
            For Each obj As System.Management.ManagementObject In objCollection
                ComboBox1.Items.Add(obj.GetPropertyValue("Name").ToString())
                ListBox1.Items.Add("------------------------> Nr: " & ComboBox1.Items.Count.ToString & " <------------------------")
                For Each info As System.Management.PropertyData In obj.Properties
                    ListBox1.Items.Add(info.Name & ": " & info.Value)
                Next
            Next
        End Sub
    
    End Class
    
    
    Controlla se tra le info, ci sono quelle di tuo interesse.
  • Re: Cambiare periferica AUDIO PLAY/REC

    Vero, avevo dimenticato di aggiungere le tre sub,
    Private Function HiByte(ByVal wParam As Integer) As Byte
         HiByte = (wParam And &HFF00&) \ (&H100)
    End Function
    Private Function LoByte(ByVal wParam As Integer) As Byte
         LoByte = wParam And &HFF&
    End Function
    Private Function TrimNulls(sString As String) As String
         TrimNulls = Left(sString, InStr(1, sString, Chr(0)) - 1)
    End Function
    Mi scuso per l'incapaità, ma non ho capito bene come usare i tuoi 2 esempi in vbnet e come/dove inserirli...

    Grazie
  • Re: Cambiare periferica AUDIO PLAY/REC

    AntoAnto ha scritto:


    Vero, avevo dimenticato di aggiungere le tre sub,
    Private Function HiByte(ByVal wParam As Integer) As Byte
         HiByte = (wParam And &HFF00&) \ (&H100)
    End Function
    Private Function LoByte(ByVal wParam As Integer) As Byte
         LoByte = wParam And &HFF&
    End Function
    Private Function TrimNulls(sString As String) As String
         TrimNulls = Left(sString, InStr(1, sString, Chr(0)) - 1)
    End Function
    Ed ecco il codice da VB6 a VB.Net completo delle tre sub, che come avevo supposto, sono inutili nel tuo caso:
    
    Public Class Form1
        ' PER SCELTA SOUND BLASTER
        Private Const CALLBACK_WINDOW As Integer = &H10000
        Private Const MAXPNAMELEN As Integer = 32
        Private Structure MIXERCAPS
            Dim wMid As Short
            Dim wPid As Short
            Dim vDriverVersion As Integer
            <VBFixedString(MAXPNAMELEN), Runtime.InteropServices.MarshalAs(Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst:=MAXPNAMELEN)> Public szPname() As Char
            Dim fdwSupport As Integer
            Dim cDestinations As Integer
        End Structure
    
        Private Declare Function mixerGetNumDevs Lib "winmm.dll" () As Integer
        Private Declare Function mixerOpen Lib "winmm.dll" (ByRef phmx As Integer, ByVal uMxId As Integer, ByVal dwCallback As Integer, ByVal dwInstance As Integer, ByVal fdwOpen As Integer) As Integer
        Private Declare Function mixerGetDevCaps Lib "winmm.dll" Alias "mixerGetDevCapsA" (ByVal uMxId As Integer, ByRef pmxcaps As MIXERCAPS, ByVal cbmxcaps As Integer) As Integer
    
        Private Sub Form1_Load(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles MyBase.Load
            _Main()
        End Sub
    
        'SCELTA della SOUND BLASTER AUDIO CARD - DA CODICE VB6
        Sub _Main()
            Dim MMSYSERR_NOERROR, m_DeviceID, m_hMixer, m_Destinations, lRtn, lLoop, lMixerCnt As Integer
            Dim s, m_ProductName, m_DriverVersion As String
            Dim m_ProductID, m_ManufacturerID As Short
            Dim lMixer As Long
            Dim mc As MIXERCAPS = New MIXERCAPS
            On Error Resume Next
            lMixerCnt = mixerGetNumDevs
            If lMixerCnt Then
                s = ""
                For lLoop = 0 To lMixerCnt - 1
                    lRtn = mixerOpen(lMixer, lLoop, Handle.ToInt32, 0, CALLBACK_WINDOW)
                    If lRtn = 0 Then
                        lRtn = mixerGetDevCaps(lMixer, mc, Len(mc))
                        If lRtn = MMSYSERR_NOERROR Then
                            With mc
                                m_Destinations = .cDestinations
                                m_DeviceID = lLoop
                                m_DriverVersion = Convert.ToString(HiByte(mc.vDriverVersion) & "." & LoByte(mc.vDriverVersion))
                                m_hMixer = lMixer
                                m_ManufacturerID = .wMid
                                m_ProductID = .wPid
                                m_ProductName = TrimNulls(mc.szPname)
                            End With
                            s = s & m_DeviceID & ") - " & m_ProductName & vbCrLf
                            If Val(m_DeviceID) < 7 Then ComboBox1.Items.Add(m_DeviceID & " - " & m_ProductName)
                        End If
                    End If
                Next lLoop
            End If
        End Sub
    
        Private Function HiByte(ByVal wParam As Integer) As Byte
            HiByte = (wParam And &HFF00&) \ (&H100)
        End Function
    
        Private Function LoByte(ByVal wParam As Integer) As Byte
            LoByte = wParam And &HFF&
        End Function
    
        Private Function TrimNulls(sString As String) As String
            TrimNulls = sString.Replace(Chr(0), "")
        End Function
    
    End Class
    

    AntoAnto ha scritto:


    Mi scuso per l'incapaità, ma non ho capito bene come usare i tuoi 2 esempi in vbnet e come/dove inserirli...
    Se non hai capito come usarli, significa che non riuscirai a fare quello che vuoi fare, ma questo non mi impedisce di risponderti.

    1 ) apri VisualStudio
    2 ) scegli: Crea un nuovo progetto... (è in basso, scritto piccolo)
    3 ) nella finestra nuovo progetto scegli: Visual Basic, Windows Desktop, App Windows Form (.Net Framework)
    metti anche il nome, il percorso e il Framework che vuoi usare.


    nuovoprogetto.png
    nuovoprogetto.png


    4 ) clicca Ok... (si aprirà un progetto nuovo che mostra un form vuoto)
    5 ) dalla Casella degli strumenenti (se non la vedi Ctrl+Alt+x) clicca due volte su Combobox e posizionalo e aggiustalo nel Form


    combobox.png
    combobox.png


    6 ) F7 (per passate al codice)
    7 ) Torna al forum e seleziona tutto il codice che ho postato qui sopra con (CODICE: SELEZIONA TUTTO) e copialo (Ctrl+c)
    8 ) Torna a VisualStudio e incolla (Ctrl+v) nella pagina del codice, sovrascrivendo qualsiasi cosa già c'è


    codice.png
    codice.png


    9 ) F5 (il programma parte e se clicchi la freccetta del combobox devi vedere le periferiche audio)

    Per l'altro programma che ti ho postato, rileggi le info sintetiche, che ora ti dovrebbero essere chiare.
  • Re: Cambiare periferica AUDIO PLAY/REC

    Molto gentile Rubik!!!

    Nel week end proverò a vedere cosa salta fuori per l'elenco delle periferiche audio.

    In effetti sono straprincipiante e con tanta voglia di imparare, ma effettivamente quei codici per me sono quasi incomprensibili.
    Anche in VB6 avevo travasato il codice da un'altro esempio ed ero riuscito a far funzionare I/O su schede diverse dato che la DLL mi permetteva di usarle "numerarandole" 1-2-3-4-5... ecc... che riprendevo dalla lista.

    Poi dovrei ancora riuscire ad usare le tre semplici linee sopra con un'altra scheda.

    prima vedo se riesco ad averne la lista...

    Ti ringrazio moltissimo per l'aiuto!!!!!!
    Anto
  • Re: Cambiare periferica AUDIO PLAY/REC

    Dunque... ho provato e tutto si è creato come previsto.

    All'avvio, nessun errore ma nella combobox1 non esce nulla ...
    la combo resta vuota

    Ho cercato dove si perde e vedo che pur trovando un numero di 16 in lMixerCnt , non le lista nella combo, non passa da lì...

    allego il file zip dell'esempio... (vb2019)
  • Re: Cambiare periferica AUDIO PLAY/REC

    Ho visto il tuo progetto, hai usato il Framework 5 e compilato a 64bit, non va bene per un progetto che è partito da VB6.

    Se il Framework di destinazione è 2, 3 o 3.5, puoi compilare sia a 32 che a 64 bit
    Se il Framework di destinazione è 4 o superiore, puoi compilare solo a 32 bit

    per cambiare il Framework di destinazione: Progetto/Proprietà/Applicazione


    framework.png
    framework.png


    Per compilare a 32 bit scegli Any CPU
  • Re: Cambiare periferica AUDIO PLAY/REC

    Grazie dell'info e dell'enorme aiuto!!!

    Ho la lista delle periferiche audio da 0 a 6 uscita.
    Non ho la lista delle periferiche di entrata (line/mic) ma è già qualcosa

    Ho dovuto lasciare il FW5 perché pur avendo provato ad installare il 2 e riavviare per seguire il tuo esempio, non l'ho in lista.


    prova1.jpg
    prova1.jpg


    Se lascio "any cpu" non funziona, anche "preferendo il 32bit" ho forzato x86 e funziona


    prova2.jpg
    prova2.jpg


    Ottengo quindi 7 periferiche:
    le 4 schede audio e i 3 virtual cable

    Ma come usarle nell'esempio del primo post:
    Public Class Form1
        Private Declare Function record Lib "winmm.dll" Alias "mciSendStringA" (ByVal lpstrCommand As String, ByVal lpstrReturnString As String, ByVal uReturnLength As Integer, ByVal hwndCallback As Integer) As Integer
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            record("open new Type waveaudio Alias recsound", "", 0, 0)
    
            record("record recsound", "", 0, 0)
        End Sub
    
        Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
            record("save recsound mic.wav", "", 0, 0)
    
            record("close recsound", "", 0, 0)
        End Sub
    
        Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
            My.Computer.Audio.Play("mic.wav")
        End Sub
    End Class
    Ho provato (avevo anche già), molto ignorantemente a cambiare i vari 0,0 con qualche altro numero
    ma è sempre su MIC e ALTOPARLANTI... potrà esserci una soluzione o impossibile con VBnet?

    Ciao
Devi accedere o registrarti per scrivere nel forum
31 risposte