2017-08-07 2 views
1

J'ai travaillé sur un projet C# avec NAudio où j'ai besoin d'envoyer des signaux audio spécifiques à des haut-parleurs spécifiques sur un système à 4 canaux. Fondamentalement, j'ai besoin d'envoyer des «sons environnementaux» à l'enceinte arrière gauche, des «sons d'affichage du panneau avant» à l'enceinte avant droite et des «instructions préenregistrées» à l'enceinte avant gauche. Ma conception actuelle fonctionne avec la configuration à 2 canaux prise en charge par mon ordinateur de bureau, mais lorsque j'essaie de l'étendre à 4 canaux sur mon matériel de test, l'erreur suivante persiste: «La valeur ne correspond pas à la plage attendue. quand j'appelle WasapiOut.init(). Je pense que le problème est causé d'une manière ou d'une autre par le MultiplexingSampleProvider, mais je ne suis pas capable de comprendre pourquoi/comment résoudre le problème. Je vérifie que l'AudioDevice que j'utilise supporte suffisamment de canaux avant que j'essaie de le charger, donc ce n'est pas un manque de canaux qui cause le problème.NAudio avec MultiplexingSampleProvider et WasapiOut

Voici le code qui provoque le problème:

// Create mixer provider for each channel. 
for(int Count = 0; Count < Channels; Count++) 
{ 
    _Mixers.Add(new MixingSampleProvider(_Format.AsStandardWaveFormat())); 
    _Mixers[Count].MixerInputEnded += SoundEndedEvent; 
} 

// Create and configure multiplexer provider. 
_Multi = new MultiplexingSampleProvider(_Mixers, Channels); 
for(int count = 0; count < Channels; count++) 
{ 
    _Multi.ConnectInputToOutput(count, 0); 
} 

// Add master volume control provider. 
_Volume = new VolumeSampleProvider(_Multi); 
_Volume.Volume = 1.0f; 

// Initialize output device. 
_OutputDev.Init(p_Volume); 

_format est une classe WAVEFORMATEXTENSIBLE avec les paramètres 44.1kHz, 32 bits, 1 canal. Tout fonctionne jusqu'à ce que j'appelle _OutputDev.Init (p_Volume), qui est l'endroit où je reçois la «valeur ne tombe pas dans la fourchette attendue». Tout fonctionne jusqu'à ce que j'appelle _OutputDev.Init (p_Volume). exception.

Des idées pour lesquelles je reçois cette exception et comment puis-je résoudre le problème?

Merci.

Modifier

C'est la trace de la pile que je reçois.

System.ArgumentException: Value does not fall within the expected range. at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo) at NAudio.Wave.WasapiOut.Init(IWaveProvider waveProvider) at NAudio.Wave.WaveExtensionMethods.Init(IWavePlayer wavePlayer, ISampleProvider sampleProvider, Boolean convertTo16Bit) at GSound.Audio.Player..ctor(Int32 Channels, Int32 Device) in E:\Dev\GSound_Wasapi\Projects\GSound\Audio\Player.cs:line 220 at GSound.Audio.Handler..ctor(Config TheConfig) in E:\Dev\GSound_Wasapi\Projects\GSound\Audio\Handler.cs:line 78 at GSound.UIData..ctor() in E:\Dev\GSound_Wasapi\Projects\GSound\UIData.cs:line 63

Je pense que le problème se produit à l'appel AudioClient.Initialize, qui génère une erreur E_INVALIDARG. Ce qui indique soit un problème avec la valeur de format générée par WasapiOut, soit un problème avec les propriétés du client. Je vais examiner les deux problèmes, mais tout pointeur serait utile.

Merci encore.

+0

Les périphériques WASAPI ne permettent pas nécessairement d'ouvrir avec un son multicanal (c'est-à-dire> 2 canaux). Je n'ai certainement pas réussi à le faire moi-même. Vous aurez probablement plus de succès avec ASIO –

+0

Intéressant, même si le périphérique sélectionné indique par le biais de MMDevice.Properties que PKEY_AudioEndPoint_PhysicalSpeakers masque qu'il dispose de 4 haut-parleurs, leur accès n'est pas réellement garanti.J'ai à voir si je peux obtenir des pilotes ASIO pour la carte son que nous utilisons. Ainsi que d'essayer de comprendre plus en ce qui concerne Wasapi, parce que cela semble juste étrange. – JonDemers

Répondre

0

J'ai obtenu 4 canaux audio pour travailler sur un système (Encore faut-il tester sur un autre système, mais ne vois pas pourquoi il ne sera pas.)

Les ajustements suivants ont été faits:

J'ai supprimé le MultiplexingSampleProvider et modifié mon SampleProvider personnalisé pour gérer la sortie de plusieurs canaux en copiant uniquement les données de signal sur le canal souhaité, et 0 sur les autres. Un des problèmes est que le MultiplexingSampleProvider utilise le format d'onde des fournisseurs d'échantillons d'entrée pour sa sortie, y compris le nombre de canaux des fournisseurs d'échantillons d'entrée. Étant donné que le fournisseur d'échantillons personnalisés d'origine était mono-canal, le multiplexeur pouvait afficher une erreur lorsque j'essayais de l'utiliser avec 4 canaux. Je me demande comment il serait difficile de réécrire le multiplexeur pour utiliser son propre waveformat, qui serait le même que le format d'entrée, mais avec le numéro de canal défini via le constructeur.

Un autre problème avec la MultiplexingSampleProvider ainsi que la classe WasapiOut, est qu'ils ne gèrent pas la classe WAVEFORMATEXTENSIBLE, je fini par modifier les classes MixingSampleProvider et SampleToWaveProvider pour permettre WaveFormat.Encoding être de type extensible (MEDIASUBTYPE_IEEE_FLOAT sous-format) ainsi que IeeeFloat.

/// <summary> 
/// Creates a new MixingSampleProvider, with no inputs, but a specified WaveFormat 
/// </summary> 
/// <param name="waveFormat">The WaveFormat of this mixer. All inputs must be in this format</param> 
public MixingSampleProvider(WaveFormat waveFormat) 
{ 
    if(waveFormat.Encoding == WaveFormatEncoding.Extensible) 
    { 
     if(((WaveFormatExtensible)waveFormat).SubFormat != NAudio.Dmo.AudioMediaSubtypes.MEDIASUBTYPE_IEEE_FLOAT) 
     { 
      throw new ArgumentException("Must be already floating point"); 
     } 
    } 
    else if(waveFormat.Encoding != WaveFormatEncoding.IeeeFloat) 
    { 
     throw new ArgumentException("Mixer wave format must be IEEE float"); 
    } 
    sources = new List<ISampleProvider>(); 
    WaveFormat = waveFormat; 
} 

La dernière chose que je ne faisais ajouter une propriété à WAVEFORMATEXTENSIBLE pour me permettre de régler le paramètre dwChannelMask. Ce réglage indique au système quels haut-parleurs utiliser pour la sortie, ce qui est dans mon cas 0x33 (haut-parleurs FL, FR, RL, RR). Le constructeur WaveFormatExtensible normal suppose que dwChannelMask serait défini sur 0x7, (haut-parleurs FL, FR, FC, LowFreq) puisque ce sont les 4 premières valeurs de haut-parleur. En réglant dwChannelMask je peux indiquer les haut-parleurs à utiliser. Je dirai que cela a été une leçon très intéressante dans le traitement des codecs audio et audio.

Espérons que cela aide les autres.

Encore merci.