2009-08-16 27 views
10

Tworzę program samplera, w którym każdy klawisz od 1 do 9 będzie generował inny dźwięk. Wszystko działa dobrze, ale gdy naciskam dwa (lub więcej) dźwięków w tym samym czasie, drugi "zabija" pierwszy.Odtwarzaj wiele dźwięków za pomocą SoundPlayer

Odtwarzam dźwięki z plików .WAV, używając SoundPlayer. Jak mogę to rozwiązać?

Odpowiedz

6

Należy użyć DirectX (DirectSound) lub podobnego interfejsu API, który umożliwia jednoczesne odtwarzanie wielu dźwięków.

1

Zgaduję, że w wydarzeniu KeyPress (lub cokolwiek innego używasz) tworzysz nową instancję SoundPlayera używając konstruktora, który pobiera ścieżkę do pliku WAV, a następnie wywołując jego metodę Play. Teoretycznie nie powinno to powodować efektu "mono", z którym się spotykasz, ponieważ system Windows był w stanie odtwarzać jednocześnie wiele plików WAV od czasu Windows 98. O czym myślę, że słyszysz (w oparciu o moje własne wykorzystanie tej klasy) nie jest odcięciem pierwszego dźwięku po rozpoczęciu drugiego, ale w rzeczywistości jest to błąd, który wynika z całkowitego wstrzymania odtwarzania, gdy plik WAV jest ładowany z dysku.

Zamiast ładować nową instancję SoundPlayer przy każdym naciśnięciu klawisza, spróbuj utworzyć tablicę obiektów SoundPlayer o zasięgu klasy i załadować je wcześniej z dysku w zdarzeniu Wczytaj formularz. Następnie po prostu wywołaj każdą metodę odtwarzania SoundPlayer po naciśnięciu klawisza. To może naprawić twój problem, chociaż wydaje mi się, że w ten sposób nadal będziesz dostrzegał sporadyczne usterki.

6

Istnieje jeden prosty sposób na odtwarzanie wielu dźwięków jednocześnie w C# lub VB.Net. Będziesz musiał zadzwonić do funkcji API mciSendString(), aby odtworzyć każdy plik .wav. Nie musisz nawet wykonywać wielowątkowości, chyba że grasz w pętli. Here to kompletny przykład działania klasy MusicPlayer utworzonej przy użyciu mciSendString().

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

W powyższej funkcji klucz jest pierwszym poleceniem parametru. Dopóki wywołasz dwie funkcje z osobną nazwą polecenia, będą one odtwarzane oddzielnie/jednocześnie. Oto co zrobiłem w jednym z moich programów 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; 
} 

EDYCJA: Dodano link do działającego przykładu.

+0

Działa to tylko wtedy, gdy za każdym razem wysyłasz NOWY, niepowtarzalny tytuł utworu, czy jest to zgodne z projektem?Jeśli spróbujesz odtworzyć inny dźwięk na poprzednio używanej nazwie utworu (nawet długo po zatrzymaniu pierwszego), jest cicho. – Sire

+0

@Sire To nie powinno się zdarzyć. Czy na pewno wysyłasz polecenie "stop", a następnie polecenie "zamknij" po zakończeniu odtwarzania? Możesz odwołać się do mojej całej implementacji MusicPlayer [tutaj] (http://pastebin.com/TtrCdeER). Zwróć szczególną uwagę na PlayWorker(), który jest nazywany wewnątrz wątku do odtwarzania dźwięku. –

+0

Dzięki za kompletny kod! Dodałbym ten link do odpowiedzi. – Sire

3

Można to zrobić:

SoundPlayer obsługuje WAV Stream. Można

  • próbek mieszanek grasz „za rękę”, a
  • Fałszywe (dostać nagłówek WAV skądś, nie jest to skomplikowane).

Podaj taki strumień jako parametr do the SoundPlayer constructor.

W ten sposób nie będziesz musiał używać w jakiś sposób skomplikowanych bibliotek DirectSound i nadal będziesz mieszał (wiele dźwięków jednocześnie).

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"); 

Kod ten może odgrywać dwa plików audio jednocześnie, połączenie w drugim dźwiękiem track2.wav nie będzie przeszkadzać grę track1.wav.

+0

to dobre rozwiązanie. 2 pytania: 1. najwyraźniej, 'Load' nie istnieje w' MediaPlayer'. Nadal jednak działa bez niego. 2. Dodanie kolejnego 'mPlayer.Play()' zaraz po pierwszym nie odtwarza pliku audio dwa razy, ale raz - dlaczego? – HeyJude

+0

Metoda ładowania jest obecna w SoundPlayer, należy ją poprawić. Po drugie, nie będziemy odtwarzać pliku audio dwukrotnie, ponieważ przekazujemy różne pliki audio. Track1.wav, Track2.wav. – Vijayaraghavan

+0

@Pransesh, pozwól mi wyjaśnić moją intencję: Chciałem powiedzieć, że jeśli to zrobimy: 'Funkcja void Play (string audioPath) {... myPlayer.Play(); myPlayer.Play(); } 'następnie Play uruchomi się raz, zamiast dwa razy. Czemu? – HeyJude

Powiązane problemy