Opóźnienie przy odtwarzaniu dźwięku przez TMediaPlayer

0

Witam

Przepraszam jeśli to jest lamerskie pytanie ale programuje sobie hobbystycznie w delphi xe5 (FireMonkey) i chcę zrobić najprostszą rzecz na świecie i mam problem.

Chcę zwyczajnie odtworzyć krótki dźwięk po kliknięciu na przycisk, problem w tym, że używając poniższego kodu dźwięk pojawia się z lekkim około 1 sekundowym opóźnieniem a ja potrzebuje aby wydobył się z głośników natychmiast po kliknięciu. Pomożecie ?

procedure TForm1.btnDzwiekk(Sender: TObject);
begin
  sciezka:='C:\klik.wav';
  mediaplayer1.FileName:=sciezka;
  mediaplayer1.play;
end;

dodanie znacznika <code class="delphi"> - furious programming

0

Może zrób to: w wątku / z użyciem PlaySound/ posiłkując się bass.dll. Polecam Tobie te ostatnie.

0

Załaduj wcześniej plik do mediaplayera, a w buttonie daj Play. To tak na szybko.

0
misiakufal napisał(a):

Załaduj wcześniej plik do mediaplayera, a w buttonie daj Play. To tak na szybko.

W zdarzeniu Formy OnCreate załadowałem plik do media playera i owszem za pierwszym razem po kliknieciu na button słyszałem szybko dźwięk ale klikając ponownoe już nie było o dźwięku tak jakby mediaplayer zapomniał ścieżki. Ale swoją drogą trzrba to będzie zrobić w wątku tak jak pisał olesio. Pozdro

2

Akurat tutaj ładowanie w wątku nic nie da. Jeśli chcesz, żeby zaraz po naciśnięciu został odtworzony dźwięk, to musi on być wcześniej załadowany do pamięci. Możesz go oczywiscie załadować w wątku, możesz skorzysać z bass, PlaySound.

PS. Działało tylko za pierwszym razem, bo w OnCreate załadowałeś dźwięk, dałeś Play, dźwięk zaczął sie odtwarzać, doszedł do końca i został na końcu. Dając play jeszcze raz cały czas byłeś na końcu dźwięku. Albo wywołaj jawnie Rewind, albo ustaw property AutoRewind na true.

1
olesio napisał(a):

Może zrób to: w wątku / z użyciem PlaySound/ posiłkując się bass.dll. Polecam Tobie te ostatnie.

Ale to armata na muchę i bass.dll nie jest do tego potrzebny...
Unit MMSystem i:

MMSystem.PlaySoundW(PWideChar(SoundPath + ASoundID), 0, SND_ASYNC or SND_FILENAME);

A tym, którzy proponują postawienie TMediaPayer'a do odpalenie krótkiego dźwięku dziękujemy ;-)

0

Dziękuję wszystkim za porady, okazało się, że świetnym rozwiązaniem jest darmowa klasa TGameAudioManager napisana specjalnie pod szybkie odtwarzanie krótkich dźwięków, szczególnie wykorzystywana w grach. Sprawdza się znakomicie.

Jeśli ktoś byłby zainteresowany podaję linka poniżej.

http://www.fmxexpress.com/free-game-audio-manager-wrapper-class-in-delphi-xe6-firemonkey-for-android-ios-windows-and-osx/

Dzięki jeszcze raz, pozdrawiam.

0

Która robi dokładnie to samo (oczywiście dla Windows) co Ci pokazałem ;-)

1

Włochate rozwiązanie to jest to co używałem, z tym że lepiej jest załadować plik do pamięci i:

// Zagranie
    SndPlaySound(GetSoundData,
                 SND_MEMORY or SND_NODEFAULT or SND_ASYNC or SND_NOSTOP);

// Zastopowanie
   SndPlaySound(nil, SND_NODEFAULT or SND_ASYNC);

(SndPlaySound to stary odpowiednik PlaySound)

procedure TKeySoundObject.PrepareExtSound;
var
  FileStream: TStream;
  MemStream: TMemoryStream;
begin
  FileStream := CreateExtSoundStream;

  Assert(FileStream<>nil);

  try
    MemStream := TMemoryStream.Create;
    try
      MemStream.CopyFrom(FileStream, 0);
      FKeySoundStream := MemStream;
    except
      MemStream.Free;
      raise;
    end;
  finally
    FileStream.Free;
  end;
end;

function TKeySoundObject.GetSoundData: pointer;
begin
    Result := Pointer(FKeySoundStream.Memory);
end;

Do tego może być pomocne jeszcze wątkowanie, ale spróbuj najpierw bez.

0

Dlaczego lepiej do pamięci, skoro i tak trzeba załadować go z dysku? Przecież to malutkie pliki są...
Co do wątkowania - flaga SND_ASYNC właśnie to robi... Odtwarza dźwięk w wątku pobocznym, ale go nie ładuje w wątku.

1
wloochacz napisał(a):

Dlaczego lepiej do pamięci, skoro i tak trzeba załadować go z dysku? Przecież to malutkie pliki są...

W idealnym świecie raz załadowany plik siedzi w cache więc może być ładowany wielokrotnie bez opóźnień.
W bardziej rzeczywistym świecie w tle leci kompilacja, konwersja filmu czy backup i opóźnienie na drodze program -> API -> OS -> driver -> cache -> dysk będzie większe od 0.

Nie wiem jak często ma następować ten "klik" - jeśli "jak mi się zachce" to plik jest OK. Jeśli to element jakiejś częstej interakcji to nawet 200 ms jest odczuwalne.

0

OK, to oczywiście zależy co i jak - ale sprawdziłem specjalnie dla małych plików WAV, takich jak w Windows czyli o wielkości od kilkunastu do 70 Kib; czas potrzebny na obsługę z ładowaniem z pliku to od 16 do 30 milisekund, na dość zapracowanym komputerze.
Jak dla mnie to wystarczająco szybko i nie ma sensu pisać obsługi ich keszowania, nawet jeśli jest banalna.
Ale mam swoje 5gr do owej częstej interakcji z dżwiękiem; moim zdaniem, jeśli taka akcja będzie następowała zbyt często, to traci całe swoje walory i tylko irytyuje użytkownika. Podobnie jak brzęczący błotnik w rowerze... słyszę, ale ignoruję ten dźwięk.

0
wloochacz napisał(a):

moim zdaniem, jeśli taka akcja będzie następowała zbyt często, to traci całe swoje walory i tylko irytyuje użytkownika. Podobnie jak brzęczący błotnik w rowerze... słyszę, ale ignoruję ten dźwięk.

Wszystko zależy od zastosowania, ja właśnie hobbystycznie skrobię sobie na androida małą gierkę na czas reakcji. W skrócie trzeba kliknąć 10 razy kulkę która pojawia się w losowych miejscach. Okazuje się że kiedy dodałem krótki dźwięk (6kb mp3) podczas kliknięcia to zacząłem uzyskiwać lepsze czasy, wpada się jakby w rytm kliknięć następujących szybko po sobie. I właśnie wszystko rozchodziło się o błyskawiczne odtworzenie dźwięku bez opóźnień przy kliknięciu na kulkę ;).

0

Pełna zgoda @masohaso, ale raczej o grach nie myślałem pisząc to co piszę - w ogóle nie myślę o grach :P

1 użytkowników online, w tym zalogowanych: 0, gości: 1