2009-08-16 6 views
10

Je crée un programme d'échantillonneur où chaque touche de 1 à 9 fera un son différent. Tout fonctionne bien, mais quand j'appuie deux (ou plus) sons en même temps, le second "tue" le premier. Je joue les sons à partir de fichiers .WAV, en utilisant SoundPlayer. Comment puis-je resoudre ceci?Jouer plusieurs sons avec SoundPlayer

Répondre

6

Vous devez utiliser DirectX (DirectSound) ou une API similaire conçue pour permettre la lecture de plusieurs sons en même temps.

1

Je suppose que dans votre événement KeyPress (ou celui que vous utilisez) vous créez une nouvelle instance de SoundPlayer en utilisant le constructeur qui prend un chemin vers le fichier WAV, puis en appelant sa méthode Play. En théorie, cela ne devrait pas causer l'effet "mono" que vous rencontrez, puisque Windows a été capable de lire plusieurs fichiers WAV simultanément depuis Windows 98. Ce que je pense que vous entendez (basé sur ma propre utilisation de cette classe) n'est pas une coupure du premier son quand le second démarre, mais en réalité un problème qui résulte de la lecture générale s'arrêtant lorsque le fichier WAV est chargé à partir du disque. Au lieu de charger une nouvelle instance de SoundPlayer à chaque pression de touche, essayez de créer un tableau d'objets SoundPlayer de classe et de les pré-charger à partir du disque dans l'événement Load de votre formulaire. Ensuite, appelez simplement la méthode Play de chaque SoundPlayer lorsque vous appuyez sur la touche. Cela peut résoudre votre problème, même si je pense que vous aurez toujours des problèmes occasionnels de cette façon.

6

Il existe une manière simple de lire plusieurs sons à la fois en C# ou en VB.Net. Vous devrez appeler la fonction API mciSendString() pour lire chaque fichier .wav. Vous n'aurez même pas besoin de faire du multi-threading, sauf si vous jouez en boucle. Here est un exemple de travail complet d'une classe MusicPlayer créée en utilisant mciSendString().

// Sound api functions 
[DllImport("winmm.dll")] 
static extern Int32 mciSendString(string command, StringBuilder buffer, int bufferSize, IntPtr hwndCallback); 

Dans la fonction ci-dessus, la clé est la première commande de paramètre. Tant que vous appelez deux fonctions avec un nom de commande distinct, elles seront lues séparément/simultanément. C'est ce que j'ai fait dans l'un de mes programmes C#:

private void PlayWorker() 
{ 
    StringBuilder sb = new StringBuilder(); 
    mciSendString("open \"" + FileName + "\" alias " + this.TrackName, sb, 0, IntPtr.Zero); 
    mciSendString("play " + this.TrackName, sb, 0, IntPtr.Zero); 
    IsBeingPlayed = true; 
} 

EDIT: lien ajouté à un exemple de travail.

+0

Cela fonctionne uniquement si vous envoyez un NOUVEAU nom de piste unique à chaque fois, est-ce voulu?Si vous essayez de jouer un autre son sur un nom de piste déjà utilisé (même longtemps après l'arrêt du premier), il est silencieux. – Sire

+0

@Sire Cela ne devrait pas arriver. Êtes-vous sûr d'envoyer la commande "stop" suivie de la commande "close" après la fin de la lecture? Vous pouvez vous référer à l'ensemble de l'implémentation de MusicPlayer [ici] (http://pastebin.com/TtrCdeER). Portez une attention particulière à PlayWorker() qui est appelé à l'intérieur d'un thread pour la lecture d'un fichier audio. –

+0

Merci pour le code complet! J'ajouterais ce lien à la réponse. – Sire

3

Vous pouvez le faire:

SoundPlayer soutient WAV Stream. Vous pouvez

  • échantillons MIX vous jouez « par la main » et,
  • Faux (obtenir l'en-tête WAV de quelque part, ce n'est pas compliqué).

et de fournir un tel flux en tant que paramètre à the SoundPlayer constructor. De cette façon, vous n'aurez pas besoin d'utiliser des bibliothèques DirectSound compliquées, et vous aurez encore du mixage (plusieurs sons à la fois).

1
using System.Windows.Media 

Function void Play(string audioPath) 
{ 
MediaPlayer myPlayer = new MediaPlayer(); 
myPlayer.Open(new System.Uri(audioPath)); 
myPlayer.Play(); 
} 

Play(Application.StartupPath + "\\Track1.wav"); 
Play(Application.StartupPath + "\\Track2.wav"); 

Ce code pourrait jouer deux fichiers audio simultanément, l'appel à la deuxième audio track2.wav ne perturbera pas le jeu de track1.wav.

+0

c'est une bonne solution. 2 questions: 1. apparemment, 'Load' n'existe pas dans' MediaPlayer'. Cela fonctionne quand même sans. 2. Ajouter un autre 'mPlayer.Play()' juste après le premier ne jouera pas le fichier audio deux fois, mais une fois - pourquoi? – HeyJude

+0

La méthode de chargement est présente dans SoundPlayer, elle doit être corrigée. Deuxièmement, il ne va pas jouer le fichier audio deux fois parce que nous passons différents fichiers audio. Track1.wav, Track2.wav. – Vijayaraghavan

+0

@Pransesh, laissez-moi clarifier mon intention: Ce que je voulais dire, c'est que si nous faisons: 'Fonction void Play (chaîne audioPath) {... myPlayer.Play(); myPlayer.Play(); } 'alors Play s'exécutera une fois, au lieu de deux fois. Pourquoi? – HeyJude